summaryrefslogtreecommitdiff
path: root/odb/mysql/schema.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'odb/mysql/schema.hxx')
-rw-r--r--odb/mysql/schema.hxx314
1 files changed, 311 insertions, 3 deletions
diff --git a/odb/mysql/schema.hxx b/odb/mysql/schema.hxx
index e221c92..1defad7 100644
--- a/odb/mysql/schema.hxx
+++ b/odb/mysql/schema.hxx
@@ -6,12 +6,320 @@
#ifndef ODB_MYSQL_SCHEMA_HXX
#define ODB_MYSQL_SCHEMA_HXX
-#include <odb/mysql/context.hxx>
+#include <set>
+
+#include <odb/emitter.hxx>
+#include <odb/mysql/common.hxx>
namespace mysql
{
- void
- generate_schema (context&);
+ struct schema_context: context
+ {
+ typedef std::set<string> tables;
+
+ schema_context (context& c, std::ostream& os, emitter& e)
+ : context (c, os), e_ (e)
+ {
+ }
+
+ schema_context (schema_context& c) : context (c), e_ (c.e_) {}
+
+ emitter& e_;
+ };
+
+ //
+ // Drop.
+ //
+
+ struct member_drop: object_members_base, schema_context
+ {
+ member_drop (schema_context& c, tables& t)
+ : object_members_base (c, false, true),
+ schema_context (c),
+ tables_ (t)
+ {
+ }
+
+ virtual void
+ container (semantics::data_member& m)
+ {
+ // Ignore inverse containers of object pointers.
+ //
+ if (inverse (m, "value"))
+ return;
+
+ string const& name (table_name (m, table_prefix_));
+
+ if (tables_.count (name))
+ return;
+
+ e_.pre ();
+ os << "DROP TABLE IF EXISTS `" << name << "`" << endl;
+ e_.post ();
+
+ tables_.insert (name);
+ }
+
+ private:
+ tables& tables_;
+ };
+
+ struct class_drop: traversal::class_, schema_context
+ {
+ class_drop (context& c, emitter& e)
+ : schema_context (c, os, e), os (e),
+ member_drop_ (*this, tables_)
+ {
+ }
+
+ 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;
+
+ e_.pre ();
+ os << "DROP TABLE IF EXISTS `" << name << "`" << endl;
+ e_.post ();
+
+ tables_.insert (name);
+
+ // Drop tables for members.
+ //
+ member_drop_.traverse (c);
+ }
+
+ private:
+ tables tables_;
+ emitter_ostream os;
+ member_drop member_drop_;
+ };
+
+ //
+ // Create.
+ //
+
+ struct object_columns: object_columns_base, schema_context
+ {
+ object_columns (schema_context& c, string const& prefix = string ())
+ : object_columns_base (c), schema_context (c), prefix_ (prefix)
+ {
+ }
+
+ virtual bool
+ column (semantics::data_member& m, string const& name, bool first)
+ {
+ // Ignore inverse object pointers.
+ //
+ if (inverse (m))
+ return false;
+
+ if (!first)
+ os << "," << endl;
+
+ os << " `" << name << "` " << column_type (m, prefix_);
+
+ if (m.count ("id"))
+ os << " PRIMARY KEY";
+
+ using semantics::class_;
+ if (class_* c = object_pointer (member_type (m, prefix_)))
+ {
+ os << " REFERENCES `" << table_name (*c) << "` (`" <<
+ column_name (id_member (*c)) << "`)";
+ }
+
+ return true;
+ }
+
+ private:
+ string prefix_;
+ };
+
+ struct member_create: object_members_base, schema_context
+ {
+ member_create (schema_context& c, semantics::class_& object, tables& t)
+ : object_members_base (c, false, true),
+ schema_context (c),
+ id_member_ (id_member (object)),
+ tables_ (t)
+ {
+ }
+
+ virtual void
+ container (semantics::data_member& m)
+ {
+ using semantics::type;
+ using semantics::data_member;
+
+ // Ignore inverse containers of object pointers.
+ //
+ if (inverse (m, "value"))
+ return;
+
+ type& t (m.type ());
+ container_kind_type ck (container_kind (t));
+ type& vt (container_vt (t));
+
+ string const& name (table_name (m, table_prefix_));
+
+ if (tables_.count (name))
+ return;
+
+ e_.pre ();
+ os << "CREATE TABLE `" << name << "` (" << endl;
+
+ // object_id (simple value)
+ //
+ string id_name (column_name (m, "id", "object_id"));
+ os << " `" << id_name << "` " << column_type (id_member_, "ref");
+
+ // index (simple value)
+ //
+ string index_name;
+ bool ordered (ck == ck_ordered && !unordered (m));
+ if (ordered)
+ {
+ index_name = column_name (m, "index", "index");
+
+ os << "," << endl
+ << " `" << index_name << "` " << column_type (m, "index");
+ }
+
+ // key (simple or composite value)
+ //
+ if (ck == ck_map || ck == ck_multimap)
+ {
+ type& kt (container_kt (t));
+
+ os << "," << endl;
+
+ if (semantics::class_* ckt = comp_value (kt))
+ {
+ object_columns oc (*this);
+ oc.traverse_composite (m, *ckt, "key", "key");
+ }
+ else
+ {
+ object_columns oc (*this, "key");
+ string const& name (column_name (m, "key", "key"));
+ oc.column (m, name, true);
+ }
+ }
+
+ // value (simple or composite value)
+ //
+ {
+ os << "," << endl;
+
+ if (semantics::class_* cvt = comp_value (vt))
+ {
+ object_columns oc (*this);
+ oc.traverse_composite (m, *cvt, "value", "value");
+ }
+ else
+ {
+ object_columns oc (*this, "value");
+ string const& name (column_name (m, "value", "value"));
+ oc.column (m, name, true);
+ }
+ }
+
+ // object_id index
+ //
+ os << "," << endl
+ << " INDEX (`" << id_name << "`)";
+
+ // index index
+ //
+ if (ordered)
+ os << "," << endl
+ << " INDEX (`" << index_name << "`)";
+
+ os << ")";
+
+ string const& engine (options.mysql_engine ());
+
+ if (engine != "default")
+ os << endl
+ << " ENGINE=" << engine;
+
+ os << endl;
+ e_.post ();
+
+ tables_.insert (name);
+ }
+
+ private:
+ semantics::data_member& id_member_;
+ tables& tables_;
+ };
+
+ struct class_create: traversal::class_, schema_context
+ {
+ class_create (context& c, emitter& e)
+ : schema_context (c, os, e), os (e)
+ {
+ }
+
+ 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;
+
+ e_.pre ();
+ os << "CREATE TABLE `" << name << "` (" << endl;
+
+ {
+ object_columns oc (*this);
+ oc.traverse (c);
+ }
+
+ os << ")";
+
+ string const& engine (options.mysql_engine ());
+
+ if (engine != "default")
+ os << endl
+ << " ENGINE=" << engine;
+
+ os << endl;
+ e_.post ();
+
+ tables_.insert (name);
+
+ // Create tables for members.
+ //
+ {
+ member_create mc (*this, c, tables_);
+ mc.traverse (c);
+ }
+ }
+
+ private:
+ tables tables_;
+ emitter_ostream os;
+ };
}
#endif // ODB_MYSQL_SCHEMA_HXX