5
\$\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
asked May 4, 2011 at 19:27
\$\endgroup\$

1 Answer 1

3
\$\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;
}
answered May 4, 2011 at 19:50
\$\endgroup\$
2
  • \$\begingroup\$ Thanks, but this is run time. My meta sql gives back types, not runtime values. \$\endgroup\$ Commented May 4, 2011 at 19:52
  • \$\begingroup\$ But I give you +1 because I did not know that library:) \$\endgroup\$ Commented May 4, 2011 at 19:58

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.