Wednesday, December 17, 2014

Type Providers in C++

I recently learned about Type Providers in F# which (among other things) allow you to import the result schema of database queries into your source code. Basically, the compiler can check at compile time if your query is correct and can offer you the result columns directly in you program. Which is neat, because it makes database accesses much nicer and more concise.

After reading that, I wonder, can we do that in C++? And of course we can, at least with a compiler plugin or a small pre-processor. I hacked some quick prototype that scans C++ for embedded SQL snippets like this

for (auto t:SQL select a,5*x as b from r,s where r.x=s.y)
   cout << t.a() << " " << t.b() << endl;

extracts the SQL statements, asks the database about the result schema of that query, and replaces the SQL with an C++ object that offers just the same interface as the query result. You can take a look at an example program and the translated result.

The current extractor is a bit hack-ish, but I think the concept is very nice, you get very natural access to query results. Both the extractor and the generated code use libpqxx for database access, so in principle it should work for PostgreSQL and HyPer. Unfortunately I could not figure out how to get the result schema of a query without actually executing it in libpqxx when using PostgreSQL as backend. So the while generated code supports both databases, the extractor is HyPer only. In recent HyPer releases you can use explain schema to get the result schema of a query, which is not supported by PostgreSQL. But porting that part to PostgreSQL should be simple, patches are welcome.


  1. > The VARCHAR comparisons use the literal values, and thus compare as not equal.

    As far as I understand it, this is wrong. The ANSI standard is that trailing spaces are *not* significant in comparison of VARCHAR values.

    I have always assumed that this is why Oracle VARCHAR2 is not called VARCHAR - because it fails to meet the standard :)

    1. You accidentally posted that to a different blog post, I will answer you in the original one.