4
\$\begingroup\$

I wrote a wrapper around boost-mpl and transformed it to an sql engine. It is a compile time sql thing, not related to normal databases. I have not finished it completely. I have some problem with the interface.

A template meta program run in compile time. So input data always present in compile time that is why I organized the inputs to tables.

Tables are simple:

#define DEF_COLUMN(name) struct Col##name {}; \
                         template<typename T> struct name \
                         { typedef typename mpl::pair<Col##name, T> type; };
struct TestTable1
{
    DEF_COLUMN(PrimaryKey)
    DEF_COLUMN(Storage)
    DEF_COLUMN(BaseType)
    typedef mpl::vector<ColPrimaryKey, ColStorage, ColBaseType> header;

    // sample table
    // PrimaryKey | Storage |  BaseType
    // -----------+---------+-----------
    // CTypeA1    | int     | CTypeABase
    // CTypeA2    | string  | CTypeABase
    typedef mpl::vector<
        mpl::map3<PrimaryKey<CTypeA1>::type, Storage<int>::type,         BaseType<CTypeABase>::type>,
        mpl::map3<PrimaryKey<CTypeA2>::type, Storage<std::string>::type, BaseType<CTypeABase>::type>
    > type;
};


struct TestTable2
{
    DEF_COLUMN(Tag)
    DEF_COLUMN(Attribute)

    typedef mpl::vector<
        mpl::map2<Tag<CTypeA1>::type, Attribute<CTypeB1>::type>,
        mpl::map2<Tag<CTypeA2>::type, Attribute<CTypeB1>::type>,
        mpl::map2<Tag<CTypeA2>::type, Attribute<CTypeB2>::type>
    > type;
};

And you can make queries on it:

void TestQuery1()
{
    typedef Select<
            Columns<MplFunction<Column<TestTable1::ColStorage>, mpl::sizeof_> >,
            From<TestTable1,
               Join<TestTable2, Equal<TestTable1::ColPrimaryKey, TestTable2::ColTag> >
            >
    > TResultSet;
    DEBUG_TYPE((TResultSet));
    print_table<TResultSet::type>();
}

I have type debug macro and table print template helper.

So the above prints:

TResultSet => Select<Columns<MplFunction<Column<TestTable1::ColStorage>, boost::mpl::sizeof_>, mpl_::na>, From<TestTable1, Join<TestTable2, Equal<TestTable1::ColPrimaryKey, TestTable2::ColTag> > >, Where<True> >
+------------------------+
| TestTable1::ColStorage |
+------------------------+
| mpl_::size_t<8ul>      |
| mpl_::size_t<8ul>      |
| mpl_::size_t<4ul>      |
+------------------------+
3 rows in set

I have problem with the syntax, how can I improve this, to achive an easy to use meta query thing? I think I have to eliminate the Columns, Column thing from the

Select<Columns<MplFunction<Column< ... 

expression. And I need good Row fetch things and others. Any idea? And where can I upload the source?

So this gives back compile time types, not runtime values.

void TestQuery3()
{
    typedef Select<
            Columns<Column<TestTable1::ColStorage> >,
            From<TestTable1>,
            Where<
                Equal<TestTable1::ColPrimaryKey, CTypeA1>
           >
    > TResultSet;
    DEBUG_TYPE((TResultSet));
    print_table<TResultSet::type>();

    // fetch one row
    typedef mpl::back<TResultSet::type>::type TResultRow;

    // get column ColStorage which is an int, TRes will be an int
    typedef mpl::at<TResultRow, TestTable1::ColStorage>::type TRes;

    // use the "int" type
    TRes testInteger = 9;

    // prints test value
    std::cout << "testInteger:" << testInteger << std::endl;
}

this prints:

TResultSet => Select<Columns<Column<TestTable1::ColStorage>, mpl_::na>, From<TestTable1, mpl_::na>, Where<Equal<TestTable1::ColPrimaryKey, CTypeA1> > >
+------------------------+
| TestTable1::ColStorage |
+------------------------+
| int                    |
+------------------------+
1 row in set

testInteger:9
\$\endgroup\$
2
\$\begingroup\$

You my also want to have a look at how the Poco library achieves a similar thing using a Tuple class. From the docs:

typedef Poco::Tuple<std::string, std::string, int> Person;
typedef std::vector<Person> People;

People people;
people.push_back(Person("Bart Simpson", "Springfield", 12));
people.push_back(Person("Lisa Simpson", "Springfield", 10));

Statement insert(session);
insert << "INSERT INTO Person VALUES(:name, :address, :age)",
    use(people), now;

Statement select(session);
select << "SELECT Name, Address, Age FROM Person",
    into(people), now;

for (People::const_iterator it = people.begin(); it != people.end(); ++it)
{
    std::cout << "Name: " << it->get<0>() << 
        ", Address: " << it->get<1>() << 
        ", Age: " << it->get<2>() <<std::endl;
}
\$\endgroup\$
  • \$\begingroup\$ Thanks, but this is run time. My meta sql gives back types, not runtime values. \$\endgroup\$ – Industrial-antidepressant May 4 '11 at 19:52
  • \$\begingroup\$ But I give you +1 because I did not know that library:) \$\endgroup\$ – Industrial-antidepressant May 4 '11 at 19:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.