// file : odb/mysql/schema.cxx // author : Boris Kolpackov // copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC // license : GNU GPL v3; see accompanying LICENSE file #include #include namespace mysql { namespace { struct data_member: traversal::data_member, context { data_member (context& c) : context (c), first_ (true) { } virtual void traverse (type& m) { if (m.count ("transient")) return; if (first_) first_ = false; else os << "," << endl; os << " `" << column_name (m) << "` " << column_type (m); 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; string const& name (table_name (c)); // If the table with this name was already created, assume the // user knows what they are doing and skip it. // if (tables_.count (name)) return; os << "CREATE TABLE `" << name << "` (" << 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; tables_.insert (name); } private: std::set tables_; }; 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; string const& name (table_name (c)); if (tables_.count (name)) return; os << "DROP TABLE IF EXISTS `" << name << "`;" << endl; tables_.insert (name); } private: std::set tables_; }; static char const file_header[] = "/* This file was generated by ODB, object-relational mapping (ORM)\n" " * compiler for C++.\n" " */\n\n"; } 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); } } }