Monday, October 1, 2012

c++11 tuples and schema generation

Thanks to the new c++11 its finally possible create a system which can take in generic data structures and convert them automatically into the SQL schema and commands.

To do this you simply have to use the tuple as the class container(which you can typedef however its pleases you) and create the Database Adapter with a few of variadic templates that auto generate the SQL commands for data handling. Here is an example of generating the CREATE TABLE command for an sql-lite database adapter.

#include <iostream>
#include <string>
#include <sstream>

template <typename T>
std::string to_string(T t)
{
  //hmm this is missing!
  std::stringstream ss;
  ss << t;
  return ss.str();
}

template <typename I>
struct SchemaType
{
};

template <>
struct SchemaType<int>
{
  static constexpr const char* type = "INTEGER";
};

template <>
struct SchemaType<float>
{
  static constexpr const char* type = "REAL";
};

template <>
struct SchemaType<char*>
{
  static constexpr const char* type = "TEXT";
};

//CREATE TABLE t(x INTEGER, y, z, PRIMARY KEY(x DESC));
template <typename... II>
struct AutoSchemaCore;

template <typename I, typename... II>
struct AutoSchemaCore<I, II...>
{
  static std::string create_params()
  {
    std::string ret = "a"
      + to_string(sizeof...(II))
      + " "
      + SchemaType<I>::type;
    if (sizeof...(II) > 0)
      {
     ret += ","
   + AutoSchemaCore<II...>::create_params();
      }
    return ret;
  }
};

template <>
struct AutoSchemaCore<>
{
  static std::string create_params()
  { return ""; }
};

template <typename I, typename... II>
struct AutoSchema
{
  static std::string create_table(const char* tablename)
  {
    // CREATE TABLE t(x INTEGER, y, z, PRIMARY KEY(x DESC));
    return std::string("CREATE TABLE ") 
      + tablename
      + "("
      + AutoSchemaCore<I,II...>::create_params()
      + ");";
  }
};

int main()
{
  //generate the CREATE TABLE t(...) SQL command 
  std::cout << AutoSchema<float>::create_table("tableA") << "\n";
  std::cout << AutoSchema<int,char*,float>::create_table("tableB") << "\n";
}

Result
CREATE TABLE tableA(a0 REAL);
CREATE TABLE tableB(a2 INTEGER,a1 TEXT,a0 REAL);

No comments:

Post a Comment