summaryrefslogtreecommitdiff
path: root/odb/mysql
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2010-07-22 14:33:21 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2010-07-22 14:33:21 +0200
commitcea6fb57ac8c9a893c0f404fef6c1469f0b6222b (patch)
treefed8b6ffa8ea2cb6347ece69c0cb81003d0ccbf6 /odb/mysql
parent5f71c55a1c24c23af1eeb0d664922497a0e5c071 (diff)
Next chunk of functionality
Add SQL language lexer. Implement MySQL type declaration parser. Create sub-directories for databases, currently mysql and tracer. Create MySQL-specific context.
Diffstat (limited to 'odb/mysql')
-rw-r--r--odb/mysql/common.cxx12
-rw-r--r--odb/mysql/common.hxx16
-rw-r--r--odb/mysql/context.cxx429
-rw-r--r--odb/mysql/context.hxx47
-rw-r--r--odb/mysql/header.cxx155
-rw-r--r--odb/mysql/header.hxx17
-rw-r--r--odb/mysql/inline.cxx76
-rw-r--r--odb/mysql/inline.hxx17
-rw-r--r--odb/mysql/schema.cxx144
-rw-r--r--odb/mysql/schema.hxx17
-rw-r--r--odb/mysql/source.cxx106
-rw-r--r--odb/mysql/source.hxx17
12 files changed, 1053 insertions, 0 deletions
diff --git a/odb/mysql/common.cxx b/odb/mysql/common.cxx
new file mode 100644
index 0000000..cd572d6
--- /dev/null
+++ b/odb/mysql/common.cxx
@@ -0,0 +1,12 @@
+// file : odb/mysql/common.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#include <odb/mysql/common.hxx>
+
+using namespace std;
+
+namespace mysql
+{
+}
diff --git a/odb/mysql/common.hxx b/odb/mysql/common.hxx
new file mode 100644
index 0000000..cd4d27f
--- /dev/null
+++ b/odb/mysql/common.hxx
@@ -0,0 +1,16 @@
+// file : odb/mysql/common.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef ODB_MYSQL_COMMON_HXX
+#define ODB_MYSQL_COMMON_HXX
+
+#include <odb/common.hxx>
+#include <odb/mysql/context.hxx>
+
+namespace mysql
+{
+}
+
+#endif // ODB_MYSQL_COMMON_HXX
diff --git a/odb/mysql/context.cxx b/odb/mysql/context.cxx
new file mode 100644
index 0000000..668ecf4
--- /dev/null
+++ b/odb/mysql/context.cxx
@@ -0,0 +1,429 @@
+// file : odb/mysql/context.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#include <sstream>
+
+#include <odb/sql-token.hxx>
+#include <odb/sql-lexer.hxx>
+
+#include <odb/mysql/context.hxx>
+
+using namespace std;
+
+namespace mysql
+{
+ namespace
+ {
+ struct type_map_entry
+ {
+ const char* const cxx_type;
+ const char* const db_type;
+ const char* const db_id_type;
+ };
+
+ type_map_entry type_map[] =
+ {
+ {"bool", "TINYINT(1)", 0},
+
+ {"char", "TINYINT", 0},
+ {"signed char", "TINYINT", 0},
+ {"unsigned char", "TINYINT UNSIGNED", 0},
+
+ {"short int", "SMALLINT", 0},
+ {"short unsigned int", "SMALLINT UNSIGNED", 0},
+
+ {"int", "INT", 0},
+ {"unsigned int", "INT UNSIGNED", 0},
+
+ {"long int", "BIGINT", 0},
+ {"long unsigned int", "BIGINT UNSIGNED", 0},
+
+ {"long long int", "BIGINT", 0},
+ {"long long unsigned int", "BIGINT UNSIGNED", 0},
+
+ {"float", "FLOAT", 0},
+ {"double", "DOUBLE", 0},
+
+ {"::std::string", "TEXT", "VARCHAR(255)"}
+ };
+ }
+
+ context::
+ context (ostream& os, semantics::unit& u, options_type const& ops)
+ : base_context (os, u, ops, data_ptr (new (shared) data)),
+ data_ (static_cast<data*> (base_context::data_.get ()))
+ {
+ // Populate the C++ type to DB type map.
+ //
+ for (size_t i (0); i < sizeof (type_map) / sizeof (type_map_entry); ++i)
+ {
+ type_map_entry const& e (type_map[i]);
+
+ type_map_type::value_type v (
+ e.cxx_type,
+ db_type_type (e.db_type, e.db_id_type ? e.db_id_type : e.db_type));
+
+ data_->type_map_.insert (v);
+ }
+ }
+
+ context::
+ context (context& c)
+ : base_context (c),
+ data_ (c.data_)
+ {
+ }
+
+ static sql_type
+ parse_sql_type (semantics::data_member& m, std::string const& sql);
+
+ sql_type const& context::
+ db_type (semantics::data_member& m)
+ {
+ if (!m.count ("db-type"))
+ m.set ("db-type", parse_sql_type (m, column_type (m)));
+
+ return m.get<sql_type> ("db-type");
+ }
+
+ static sql_type
+ parse_sql_type (semantics::data_member& m, string const& sql)
+ {
+ try
+ {
+ sql_type r;
+ sql_lexer l (sql);
+
+ // While most type names use single identifier, there are
+ // a couple of exceptions to this rule:
+ //
+ // NATIONAL CHAR|VARCHAR
+ // CHAR BYTE (BINARY)
+ // CHARACTER VARYING (VARCHAR)
+ // LONG VARBINARY (MEDIUMBLOB)
+ // LONG VARCHAR (MEDIUMTEXT)
+ //
+ //
+ enum state
+ {
+ parse_prefix,
+ parse_name,
+ parse_bounds,
+ parse_sign
+ };
+
+ state s (parse_prefix);
+
+ for (sql_token t (l.next ());
+ t.type () != sql_token::t_eos; t = l.next ())
+ {
+ sql_token::token_type tt (t.type ());
+
+ switch (s)
+ {
+ case parse_prefix:
+ {
+ if (tt == sql_token::t_identifier)
+ {
+ string const& id (t.identifier ());
+
+ if (id == "NATIONAL" ||
+ id == "CHAR" ||
+ id == "CHARACTER" ||
+ id == "LONG")
+ {
+ r.type = id;
+ continue;
+ }
+ }
+
+ // Fall through.
+ //
+ s = parse_prefix;
+ }
+ case parse_name:
+ {
+ if (tt == sql_token::t_identifier)
+ {
+ bool match (true);
+ string const& id (t.identifier ());
+
+ // Numeric types.
+ //
+ if (id == "BIT")
+ {
+ r.type = "BIT";
+ }
+ else if (id == "TINYINT" || id == "INT1")
+ {
+ r.type = "TINYINT";
+ }
+ else if (id == "BOOL" || id == "BOOLEAN")
+ {
+ r.type = "TINYINT";
+ r.bounds = true;
+ r.bounds_value = 1;
+ }
+ else if (id == "SMALLINT" || id == "INT2")
+ {
+ r.type = "SMALLINT";
+ }
+ else if (id == "MEDIUMINT" || id == "INT3" || id == "MIDDLEINT")
+ {
+ r.type = "MEDIUMINT";
+ }
+ else if (id == "INT" || id == "INTEGER" || id == "INT4")
+ {
+ r.type = "INT";
+ }
+ else if (id == "BIGINT" || id == "INT8")
+ {
+ r.type = "BIGINT";
+ }
+ else if (id == "SERIAL")
+ {
+ r.type = "BIGINT";
+ r.unsign = true;
+ }
+ else if (id == "FLOAT" || id == "FLOAT4")
+ {
+ r.type = "FLOAT";
+ }
+ else if (id == "DOUBLE" || id == "FLOAT8")
+ {
+ r.type = "DOUBLE";
+ }
+ else if (id == "DECIMAL" ||
+ id == "DEC" ||
+ id == "NUMERIC" ||
+ id == "FIXED")
+ {
+ r.type = "DECIMAL";
+ }
+ //
+ // Date-time types.
+ //
+ else if (id == "DATE")
+ {
+ r.type = "DATE";
+ }
+ else if (id == "TIME")
+ {
+ r.type = "TIME";
+ }
+ else if (id == "DATETIME")
+ {
+ r.type = "DATETIME";
+ }
+ else if (id == "TIMESTAMP")
+ {
+ r.type = "TIMESTAMP";
+ }
+ else if (id == "YEAR")
+ {
+ r.type = "YEAR";
+ }
+ //
+ // String and binary types.
+ //
+ else if (id == "NCHAR")
+ {
+ r.type = "CHAR";
+ }
+ else if (id == "VARCHAR")
+ {
+ r.type = r.type == "LONG" ? "MEDIUMTEXT" : "VARCHAR";
+ }
+ else if (id == "NVARCHAR")
+ {
+ r.type = "VARCHAR";
+ }
+ else if (id == "VARYING" && r.type == "CHARACTER")
+ {
+ r.type = "VARCHAR";
+ }
+ else if (id == "BINARY")
+ {
+ r.type = "BINARY";
+ }
+ else if (id == "BYTE" && r.type == "CHAR")
+ {
+ r.type = "BINARY";
+ }
+ else if (id == "VARBINARY")
+ {
+ r.type = r.type == "LONG" ? "MEDIUMBLOB" : "VARBINARY";
+ }
+ else if (id == "TINYBLOB")
+ {
+ r.type = "TINYBLOB";
+ }
+ else if (id == "TINYTEXT")
+ {
+ r.type = "TINYTEXT";
+ }
+ else if (id == "BLOB")
+ {
+ r.type = "BLOB";
+ }
+ else if (id == "TEXT")
+ {
+ r.type = "TEXT";
+ }
+ else if (id == "MEDIUMBLOB")
+ {
+ r.type = "MEDIUMBLOB";
+ }
+ else if (id == "MEDIUMTEXT")
+ {
+ r.type = "MEDIUMTEXT";
+ }
+ else if (id == "LONGBLOB")
+ {
+ r.type = "LONGBLOB";
+ }
+ else if (id == "LONGTEXT")
+ {
+ r.type = "LONGTEXT";
+ }
+ else if (id == "ENUM")
+ {
+ r.type = "ENUM";
+ }
+ else if (id == "SET")
+ {
+ r.type = "SET";
+ }
+ else
+ match = false;
+
+ if (match)
+ {
+ s = parse_bounds;
+ continue;
+ }
+ }
+
+ bool match (false);
+
+ // Some prefixes can also be type names if not followed
+ // by the actual type name.
+ //
+ if (!r.type.empty ())
+ {
+ if (r.type == "CHAR")
+ match = true;
+ else if (r.type == "CHARACTER")
+ {
+ r.type = "CHAR";
+ match = true;
+ }
+ else if (r.type == "LONG")
+ {
+ r.type = "MEDIUMTEXT";
+ match = true;
+ }
+ }
+
+ if (!match)
+ {
+ cerr << m.file () << ":" << m.line () << ":" << m.column ();
+
+ if (tt == sql_token::t_identifier)
+ cerr << " error: unknown MySQL type '" <<
+ t.identifier () << "'" << endl;
+ else
+ cerr << " error: expected MySQL type name" << endl;
+
+ throw generation_failed ();
+ }
+
+ // Fall through.
+ //
+ s = parse_bounds;
+ }
+ case parse_bounds:
+ {
+ if (t.punctuation () == sql_token::p_lparen)
+ {
+ t = l.next ();
+
+ if (t.type () != sql_token::t_int_lit)
+ {
+ cerr << m.file () << ":" << m.line () << ":" << m.column ()
+ << " error: integer bounds expected in MySQL type "
+ << "declaration" << endl;
+
+ throw generation_failed ();
+ }
+
+ unsigned int v;
+ istringstream is (t.literal ());
+
+ if (!(is >> v && is.eof ()))
+ {
+ cerr << m.file () << ":" << m.line () << ":" << m.column ()
+ << " error: invalid bounds value '" << t.literal ()
+ << "'in MySQL type declaration" << endl;
+
+ throw generation_failed ();
+ }
+
+ r.bounds = true;
+ r.bounds_value = v;
+
+ t = l.next ();
+
+ if (t.punctuation () == sql_token::p_comma)
+ {
+ // We have the second bounds value. Skip it.
+ //
+ l.next ();
+ t = l.next ();
+ }
+
+ if (t.punctuation () != sql_token::p_rparen)
+ {
+ cerr << m.file () << ":" << m.line () << ":" << m.column ()
+ << " error: expected ')' in MySQL type declaration"
+ << endl;
+
+ throw generation_failed ();
+ }
+
+ s = parse_sign;
+ continue;
+ }
+
+ // Fall through.
+ //
+ s = parse_sign;
+ }
+ case parse_sign:
+ {
+ if (tt == sql_token::t_identifier && t.identifier () == "UNSIGNED")
+ {
+ r.unsign = true;
+ }
+
+ return r;
+ }
+ }
+ }
+
+ cerr << m.file () << ":" << m.line () << ":" << m.column ()
+ << " error: empty MySQL type declaration" << endl;
+
+ throw generation_failed ();
+ }
+ catch (sql_lexer::invalid_input const& e)
+ {
+ cerr << m.file () << ":" << m.line () << ":" << m.column ()
+ << " error: invalid MySQL type declaration: " << e.message << endl;
+
+ throw generation_failed ();
+ }
+ }
+}
diff --git a/odb/mysql/context.hxx b/odb/mysql/context.hxx
new file mode 100644
index 0000000..7c075b2
--- /dev/null
+++ b/odb/mysql/context.hxx
@@ -0,0 +1,47 @@
+// file : odb/mysql/context.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef ODB_MYSQL_CONTEXT_HXX
+#define ODB_MYSQL_CONTEXT_HXX
+
+#include <string>
+
+#include <odb/context.hxx>
+
+namespace mysql
+{
+ struct sql_type
+ {
+ sql_type () : unsign (false), bounds (false) {}
+
+ std::string type;
+ bool unsign;
+ bool bounds;
+ unsigned int bounds_value; // MySQL max value is 2^32 - 1 (LONGBLOG/TEXT).
+ };
+
+ class context: public ::context
+ {
+ private:
+ typedef ::context base_context;
+
+ struct data: base_context::data
+ {
+ };
+
+ private:
+ data* data_;
+
+ public:
+ sql_type const&
+ db_type (semantics::data_member&);
+
+ public:
+ context (std::ostream&, semantics::unit&, options_type const&);
+ context (context&);
+ };
+}
+
+#endif // ODB_MYSQL_CONTEXT_HXX
diff --git a/odb/mysql/header.cxx b/odb/mysql/header.cxx
new file mode 100644
index 0000000..a4111ec
--- /dev/null
+++ b/odb/mysql/header.cxx
@@ -0,0 +1,155 @@
+// file : odb/mysql/header.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#include <odb/mysql/common.hxx>
+#include <odb/mysql/header.hxx>
+
+namespace
+{
+ struct class_: traversal::class_, context
+ {
+ class_ (context& c)
+ : context (c)
+ {
+ }
+
+ virtual void
+ traverse (type& c)
+ {
+ if (c.file () != unit.file ())
+ return;
+
+ if (!c.count ("object"))
+ return;
+
+ string const& type (c.fq_name ());
+
+ // Find the id member and type.
+ //
+ id_member t (*this);
+ t.traverse (c);
+
+ if (t.member () == 0)
+ {
+ cerr << c.file () << ":" << c.line () << ":" << c.column ()
+ << " error: no data member designated as object id" << endl;
+
+ cerr << c.file () << ":" << c.line () << ":" << c.column ()
+ << " info: use '#pragma odb id' to specify object id member"
+ << endl;
+
+ throw generation_failed ();
+ }
+
+ semantics::data_member& id (*t.member ());
+ semantics::type& id_type (id.type ());
+
+ if (id_type.anonymous ())
+ {
+ // Can be a template-id (which we should handle eventually) or an
+ // anonymous type in member declaration (e.g., struct {...} m_;).
+ //
+ cerr << id.file () << ":" << id.line () << ":" << id.column ()
+ << " error: unnamed type in data member declaration" << endl;
+
+ cerr << id.file () << ":" << id.line () << ":" << id.column ()
+ << " info: use 'typedef' to name this type"
+ << endl;
+
+ throw generation_failed ();
+ }
+
+ os << "// " << c.name () << endl
+ << "//" << endl;
+
+ os << "template <>" << endl
+ << "class access::object_traits< " << type << " >: " << endl
+ << " public access::object_memory< " << type << " >," << endl
+ << " public access::object_factory< " << type << " >"
+ << "{"
+ << "public:" << endl;
+
+ // object_type & shared_ptr
+ //
+ os << "typedef " << type << " object_type;";
+
+ // id_type
+ //
+ os << "typedef " << id_type.fq_name () << " id_type;"
+ << endl;
+
+ // id_source
+ //
+ os << "static const odb::id_source id_source = odb::ids_assigned;"
+ << endl;
+
+ // id ()
+ //
+ os << "static id_type" << endl
+ << "id (const object_type&);"
+ << endl;
+
+ // persist ()
+ //
+ os << "static void" << endl
+ << "persist (database&, object_type&);"
+ << endl;
+
+ // store ()
+ //
+ os << "static void" << endl
+ << "store (database&, object_type&);"
+ << endl;
+
+ // erase ()
+ //
+ os << "static void" << endl
+ << "erase (database&, const id_type&);"
+ << endl;
+
+ // find ()
+ //
+ os << "static pointer_type" << endl
+ << "find (database&, const id_type&);"
+ << endl;
+
+ os << "static bool" << endl
+ << "find (database&, const id_type&, object_type&);";
+
+ os << "};";
+ }
+ };
+}
+
+namespace mysql
+{
+ void
+ generate_header (context& ctx)
+ {
+ traversal::unit unit;
+ traversal::defines unit_defines;
+ traversal::namespace_ ns;
+ class_ c (ctx);
+
+ unit >> unit_defines >> ns;
+ unit_defines >> c;
+
+ traversal::defines ns_defines;
+
+ ns >> ns_defines >> ns;
+ ns_defines >> c;
+
+ ctx.os << "#include <odb/core.hxx>" << endl
+ << "#include <odb/traits.hxx>" << endl
+ << endl;
+
+ ctx.os << "namespace odb"
+ << "{";
+
+ unit.dispatch (ctx.unit);
+
+ ctx.os << "}";
+ }
+}
diff --git a/odb/mysql/header.hxx b/odb/mysql/header.hxx
new file mode 100644
index 0000000..a31281e
--- /dev/null
+++ b/odb/mysql/header.hxx
@@ -0,0 +1,17 @@
+// file : odb/mysql/header.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef ODB_MYSQL_HEADER_HXX
+#define ODB_MYSQL_HEADER_HXX
+
+#include <odb/mysql/context.hxx>
+
+namespace mysql
+{
+ void
+ generate_header (context&);
+}
+
+#endif // ODB_MYSQL_HEADER_HXX
diff --git a/odb/mysql/inline.cxx b/odb/mysql/inline.cxx
new file mode 100644
index 0000000..44cf9d0
--- /dev/null
+++ b/odb/mysql/inline.cxx
@@ -0,0 +1,76 @@
+// file : odb/mysql/inline.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#include <odb/mysql/common.hxx>
+#include <odb/mysql/inline.hxx>
+
+namespace
+{
+ struct class_: traversal::class_, context
+ {
+ class_ (context& c)
+ : context (c)
+ {
+ }
+
+ virtual void
+ traverse (type& c)
+ {
+ if (c.file () != unit.file ())
+ return;
+
+ if (!c.count ("object"))
+ return;
+
+ string const& type (c.fq_name ());
+ string traits ("access::object_traits< " + type + " >");
+
+ id_member t (*this);
+ t.traverse (c);
+ semantics::data_member& id (*t.member ());
+
+ os << "// " << c.name () << endl
+ << "//" << endl
+ << endl;
+
+ // id ()
+ //
+ os << "inline" << endl
+ << traits << "::id_type" << endl
+ << traits << "::" << endl
+ << "id (const object_type& obj)"
+ << "{"
+ << "return obj." << id.name () << ";" << endl
+ << "}";
+ }
+ };
+}
+
+namespace mysql
+{
+ void
+ generate_inline (context& ctx)
+ {
+ traversal::unit unit;
+ traversal::defines unit_defines;
+ traversal::namespace_ ns;
+ class_ c (ctx);
+
+ unit >> unit_defines >> ns;
+ unit_defines >> c;
+
+ traversal::defines ns_defines;
+
+ ns >> ns_defines >> ns;
+ ns_defines >> c;
+
+ ctx.os << "namespace odb"
+ << "{";
+
+ unit.dispatch (ctx.unit);
+
+ ctx.os << "}";
+ }
+}
diff --git a/odb/mysql/inline.hxx b/odb/mysql/inline.hxx
new file mode 100644
index 0000000..2d76274
--- /dev/null
+++ b/odb/mysql/inline.hxx
@@ -0,0 +1,17 @@
+// file : odb/mysql/inline.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef ODB_MYSQL_INLINE_HXX
+#define ODB_MYSQL_INLINE_HXX
+
+#include <odb/mysql/context.hxx>
+
+namespace mysql
+{
+ void
+ generate_inline (context&);
+}
+
+#endif // ODB_MYSQL_INLINE_HXX
diff --git a/odb/mysql/schema.cxx b/odb/mysql/schema.cxx
new file mode 100644
index 0000000..a38729e
--- /dev/null
+++ b/odb/mysql/schema.cxx
@@ -0,0 +1,144 @@
+// file : odb/mysql/schema.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#include <odb/mysql/schema.hxx>
+
+namespace
+{
+ struct data_member: traversal::data_member, context
+ {
+ data_member (context& c)
+ : context (c), first_ (true)
+ {
+ }
+
+ virtual void
+ traverse (type& m)
+ {
+ if (first_)
+ first_ = false;
+ else
+ os << "," << endl;
+
+ os << " `" << column_name (m) << "` " << column_type (m) <<
+ " NOT NULL";
+
+ if (m.count ("id"))
+ os << " PRIMARY KEY";
+ }
+
+ private:
+ bool first_;
+ };
+
+ struct class_create: traversal::class_, context
+ {
+ class_create (context& c)
+ : context (c)
+ {
+ }
+
+ virtual void
+ traverse (type& c)
+ {
+ if (c.file () != unit.file ())
+ return;
+
+ if (!c.count ("object"))
+ return;
+
+ os << "CREATE TABLE `" << table_name (c) << "` (" << endl;
+
+ {
+ data_member m (*this);
+ traversal::names n (m);
+ names (c, n);
+ }
+
+ os << ")";
+
+ string const& engine (options.mysql_engine ());
+
+ if (engine != "default")
+ os << endl
+ << " ENGINE=" << engine;
+
+ os << ";" << endl
+ << endl;
+ }
+ };
+
+ struct class_drop: traversal::class_, context
+ {
+ class_drop (context& c)
+ : context (c)
+ {
+ }
+
+ virtual void
+ traverse (type& c)
+ {
+ if (c.file () != unit.file ())
+ return;
+
+ if (!c.count ("object"))
+ return;
+
+ os << "DROP TABLE IF EXISTS `" << table_name (c) << "`;" << endl;
+ }
+ };
+}
+
+static char const file_header[] =
+ "/* This file was generated by CodeSynthesis ODB object persistence\n"
+ " * compiler for C++.\n"
+ " */\n\n";
+
+namespace mysql
+{
+ void
+ generate_schema (context& ctx)
+ {
+ ctx.os << file_header;
+
+ // Drop.
+ //
+ {
+ traversal::unit unit;
+ traversal::defines unit_defines;
+ traversal::namespace_ ns;
+ class_drop c (ctx);
+
+ unit >> unit_defines >> ns;
+ unit_defines >> c;
+
+ traversal::defines ns_defines;
+
+ ns >> ns_defines >> ns;
+ ns_defines >> c;
+ unit.dispatch (ctx.unit);
+ }
+
+ ctx.os << endl;
+
+ // Create.
+ //
+ {
+ traversal::unit unit;
+ traversal::defines unit_defines;
+ traversal::namespace_ ns;
+ class_create c (ctx);
+
+ unit >> unit_defines >> ns;
+ unit_defines >> c;
+
+ traversal::defines ns_defines;
+
+ ns >> ns_defines >> ns;
+ ns_defines >> c;
+ unit.dispatch (ctx.unit);
+ }
+ }
+}
diff --git a/odb/mysql/schema.hxx b/odb/mysql/schema.hxx
new file mode 100644
index 0000000..99699d3
--- /dev/null
+++ b/odb/mysql/schema.hxx
@@ -0,0 +1,17 @@
+// file : odb/mysql/schema.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef ODB_MYSQL_SCHEMA_HXX
+#define ODB_MYSQL_SCHEMA_HXX
+
+#include <odb/mysql/context.hxx>
+
+namespace mysql
+{
+ void
+ generate_schema (context&);
+}
+
+#endif // ODB_MYSQL_SCHEMA_HXX
diff --git a/odb/mysql/source.cxx b/odb/mysql/source.cxx
new file mode 100644
index 0000000..0f117ec
--- /dev/null
+++ b/odb/mysql/source.cxx
@@ -0,0 +1,106 @@
+// file : odb/mysql/source.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#include <odb/mysql/common.hxx>
+#include <odb/mysql/source.hxx>
+
+namespace
+{
+ struct class_: traversal::class_, context
+ {
+ class_ (context& c)
+ : context (c)
+ {
+ }
+
+ virtual void
+ traverse (type& c)
+ {
+ if (c.file () != unit.file ())
+ return;
+
+ if (!c.count ("object"))
+ return;
+
+ string const& type (c.fq_name ());
+ string traits ("access::object_traits< " + type + " >");
+
+ id_member t (*this);
+ t.traverse (c);
+ semantics::data_member& id (*t.member ());
+
+ os << "// " << c.name () << endl
+ << "//" << endl
+ << endl;
+
+ // persist ()
+ //
+ os << "void " << traits << "::" << endl
+ << "persist (database&, object_type& obj)"
+ << "{"
+ << "}";
+
+ // store ()
+ //
+ os << "void " << traits << "::" << endl
+ << "store (database&, object_type& obj)"
+ << "{"
+ << "}";
+
+ // erase ()
+ //
+ os << "void " << traits << "::" << endl
+ << "erase (database&, const id_type& id)"
+ << "{"
+ << "}";
+
+ // find ()
+ //
+ os << traits << "::pointer_type" << endl
+ << traits << "::" << endl
+ << "find (database&, const id_type& id)"
+ << "{"
+ << "return 0;"
+ << "}";
+
+ os << "bool " << traits << "::" << endl
+ << "find (database&, const id_type& id, object_type& obj)"
+ << "{"
+ << "return false;"
+ << "}";
+ }
+ };
+}
+
+namespace mysql
+{
+ void
+ generate_source (context& ctx)
+ {
+ traversal::unit unit;
+ traversal::defines unit_defines;
+ traversal::namespace_ ns;
+ class_ c (ctx);
+
+ unit >> unit_defines >> ns;
+ unit_defines >> c;
+
+ traversal::defines ns_defines;
+
+ ns >> ns_defines >> ns;
+ ns_defines >> c;
+
+ ctx.os << "#include <odb/mysql/database.hxx>" << endl
+ << "#include <odb/mysql/exceptions.hxx>" << endl
+ << endl;
+
+ ctx.os << "namespace odb"
+ << "{";
+
+ unit.dispatch (ctx.unit);
+
+ ctx.os << "}";
+ }
+}
diff --git a/odb/mysql/source.hxx b/odb/mysql/source.hxx
new file mode 100644
index 0000000..6a79479
--- /dev/null
+++ b/odb/mysql/source.hxx
@@ -0,0 +1,17 @@
+// file : odb/mysql/source.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef ODB_MYSQL_SOURCE_HXX
+#define ODB_MYSQL_SOURCE_HXX
+
+#include <odb/mysql/context.hxx>
+
+namespace mysql
+{
+ void
+ generate_source (context&);
+}
+
+#endif // ODB_MYSQL_SOURCE_HXX