summaryrefslogtreecommitdiff
path: root/odb/semantics
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2011-10-24 16:32:51 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2011-10-24 16:32:51 +0200
commit08a47c70ad517b80b72914d47d547463f576bcd3 (patch)
tree8a6ab07cf05e8668ea3c91735dfe97e2a98f3f05 /odb/semantics
parenta976183dc95a8b7a9bd7a308c3ea94f08982c426 (diff)
Generate database schema from database model instead of C++ model
We now first create the so-called database model from C++ model and then use that to generate the database schema. The new approach also adds more general support for primary/foreign keys, including multi- column keys. Finally, for MySQL we now generate out-of-line foreign key definitions. Because MySQL does not support deferred constraints checking, deferred foreign keys are written commented out, for documentation.
Diffstat (limited to 'odb/semantics')
-rw-r--r--odb/semantics/relational.hxx18
-rw-r--r--odb/semantics/relational/column.cxx35
-rw-r--r--odb/semantics/relational/column.hxx118
-rw-r--r--odb/semantics/relational/elements.cxx137
-rw-r--r--odb/semantics/relational/elements.hxx277
-rw-r--r--odb/semantics/relational/foreign-key.cxx35
-rw-r--r--odb/semantics/relational/foreign-key.hxx87
-rw-r--r--odb/semantics/relational/index.cxx35
-rw-r--r--odb/semantics/relational/index.hxx44
-rw-r--r--odb/semantics/relational/key.cxx43
-rw-r--r--odb/semantics/relational/key.hxx100
-rw-r--r--odb/semantics/relational/model.cxx35
-rw-r--r--odb/semantics/relational/model.hxx39
-rw-r--r--odb/semantics/relational/primary-key.cxx35
-rw-r--r--odb/semantics/relational/primary-key.hxx45
-rw-r--r--odb/semantics/relational/table.cxx52
-rw-r--r--odb/semantics/relational/table.hxx56
17 files changed, 1191 insertions, 0 deletions
diff --git a/odb/semantics/relational.hxx b/odb/semantics/relational.hxx
new file mode 100644
index 0000000..0d3d06c
--- /dev/null
+++ b/odb/semantics/relational.hxx
@@ -0,0 +1,18 @@
+// file : odb/semantics/relational.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC
+// license : GNU GPL v3; see accompanying LICENSE file
+
+#ifndef ODB_SEMANTICS_RELATIONAL_HXX
+#define ODB_SEMANTICS_RELATIONAL_HXX
+
+#include <odb/semantics/relational/column.hxx>
+#include <odb/semantics/relational/elements.hxx>
+#include <odb/semantics/relational/foreign-key.hxx>
+#include <odb/semantics/relational/index.hxx>
+#include <odb/semantics/relational/key.hxx>
+#include <odb/semantics/relational/model.hxx>
+#include <odb/semantics/relational/primary-key.hxx>
+#include <odb/semantics/relational/table.hxx>
+
+#endif // ODB_SEMANTICS_RELATIONAL_HXX
diff --git a/odb/semantics/relational/column.cxx b/odb/semantics/relational/column.cxx
new file mode 100644
index 0000000..99df5d9
--- /dev/null
+++ b/odb/semantics/relational/column.cxx
@@ -0,0 +1,35 @@
+// file : odb/semantics/relational/column.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC
+// license : GNU GPL v3; see accompanying LICENSE file
+
+#include <cutl/compiler/type-info.hxx>
+
+#include <odb/semantics/relational/column.hxx>
+
+namespace semantics
+{
+ namespace relational
+ {
+ // type info
+ //
+ namespace
+ {
+ struct init
+ {
+ init ()
+ {
+ using compiler::type_info;
+
+ // column
+ //
+ {
+ type_info ti (typeid (column));
+ ti.add_base (typeid (nameable));
+ insert (ti);
+ }
+ }
+ } init_;
+ }
+ }
+}
diff --git a/odb/semantics/relational/column.hxx b/odb/semantics/relational/column.hxx
new file mode 100644
index 0000000..a1024cf
--- /dev/null
+++ b/odb/semantics/relational/column.hxx
@@ -0,0 +1,118 @@
+// file : odb/semantics/relational/column.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC
+// license : GNU GPL v3; see accompanying LICENSE file
+
+#ifndef ODB_SEMANTICS_RELATIONAL_COLUMN_HXX
+#define ODB_SEMANTICS_RELATIONAL_COLUMN_HXX
+
+#include <odb/semantics/relational/elements.hxx>
+#include <odb/semantics/relational/table.hxx>
+
+namespace semantics
+{
+ namespace relational
+ {
+ class contains;
+
+ class column: public nameable
+ {
+ typedef std::vector<contains*> contained_list;
+
+ public:
+ column (string const& id, string const& type, bool null)
+ : nameable (id), type_ (type), null_ (null)
+ {
+ }
+
+ string const&
+ type () const
+ {
+ return type_;
+ }
+
+ bool
+ null () const
+ {
+ return null_;
+ }
+
+ string const&
+ default_ () const
+ {
+ return default__;
+ }
+
+ void
+ default_ (string const& d)
+ {
+ default__ = d;
+ }
+
+ string const&
+ options () const
+ {
+ return options_;
+ }
+
+ void
+ options (string const& o)
+ {
+ options_ = o;
+ }
+
+ public:
+ typedef relational::table table_type;
+
+ table_type&
+ table () const
+ {
+ return dynamic_cast<table_type&> (scope ());
+ }
+
+ // Key containment.
+ //
+ public:
+ typedef
+ pointer_iterator<contained_list::const_iterator>
+ contained_iterator;
+
+ contained_iterator
+ contained_begin () const
+ {
+ return contained_.begin ();
+ }
+
+ contained_iterator
+ contained_end () const
+ {
+ return contained_.end ();
+ }
+
+ public:
+ void
+ add_edge_right (contains& e)
+ {
+ contained_.push_back (&e);
+ }
+
+ using nameable::add_edge_right;
+
+ virtual string
+ kind () const
+ {
+ return "column";
+ }
+
+ private:
+ string type_;
+ bool null_;
+ string default__;
+ string options_;
+
+ contained_list contained_;
+ };
+ }
+}
+
+#endif // ODB_SEMANTICS_RELATIONAL_COLUMN_HXX
diff --git a/odb/semantics/relational/elements.cxx b/odb/semantics/relational/elements.cxx
new file mode 100644
index 0000000..6ab977a
--- /dev/null
+++ b/odb/semantics/relational/elements.cxx
@@ -0,0 +1,137 @@
+// file : odb/semantics/relational/elements.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC
+// license : GNU GPL v3; see accompanying LICENSE file
+
+#include <cutl/compiler/type-info.hxx>
+
+#include <odb/semantics/relational/elements.hxx>
+#include <odb/semantics/relational/column.hxx>
+#include <odb/semantics/relational/primary-key.hxx>
+
+namespace semantics
+{
+ namespace relational
+ {
+ // scope
+ //
+
+ scope::names_iterator scope::
+ find (string const& name)
+ {
+ names_map::iterator i (names_map_.find (name));
+
+ if (i == names_map_.end ())
+ return names_.end ();
+ else
+ return i->second;
+ }
+
+ scope::names_const_iterator scope::
+ find (string const& name) const
+ {
+ names_map::const_iterator i (names_map_.find (name));
+
+ if (i == names_map_.end ())
+ return names_.end ();
+ else
+ return names_const_iterator (i->second);
+ }
+
+ scope::names_iterator scope::
+ find (names const& e)
+ {
+ names_iterator_map::iterator i (iterator_map_.find (&e));
+ return i != iterator_map_.end () ? i->second : names_.end ();
+ }
+
+ scope::names_const_iterator scope::
+ find (names const& e) const
+ {
+ names_iterator_map::const_iterator i (iterator_map_.find (&e));
+ return i != iterator_map_.end () ? i->second : names_.end ();
+ }
+
+ void scope::
+ add_edge_left (names& e)
+ {
+ nameable& n (e.nameable ());
+ string const& name (e.name ());
+
+ names_map::iterator i (names_map_.find (name));
+
+ if (i == names_map_.end ())
+ {
+ names_list::iterator i;
+
+ // We want the order to be columns first, then the primary key,
+ // and then the foreign keys.
+ //
+ if (n.is_a<column> ())
+ i = names_.insert (first_key_, &e);
+ else
+ {
+ if (n.is_a<primary_key> ())
+ first_key_ = i = names_.insert (first_key_, &e);
+ else
+ {
+ i = names_.insert (names_.end (), &e);
+
+ if (first_key_ == names_.end ())
+ first_key_ = i;
+ }
+ }
+
+ names_map_[name] = i;
+ iterator_map_[&e] = i;
+ }
+ else
+ throw duplicate_name (*this, (*i->second)->nameable (), n);
+ }
+
+ // type info
+ //
+ namespace
+ {
+ struct init
+ {
+ init ()
+ {
+ using compiler::type_info;
+
+ // node
+ //
+ insert (type_info (typeid (node)));
+
+ // edge
+ //
+ insert (type_info (typeid (edge)));
+
+ // names
+ //
+ {
+ type_info ti (typeid (names));
+ ti.add_base (typeid (edge));
+ insert (ti);
+ }
+
+ // nameable
+ //
+ {
+ type_info ti (typeid (nameable));
+ ti.add_base (typeid (node));
+ insert (ti);
+ }
+
+ // scope
+ //
+ {
+ type_info ti (typeid (scope));
+ ti.add_base (typeid (node));
+ insert (ti);
+ }
+ }
+ } init_;
+ }
+ }
+}
diff --git a/odb/semantics/relational/elements.hxx b/odb/semantics/relational/elements.hxx
new file mode 100644
index 0000000..d07902d
--- /dev/null
+++ b/odb/semantics/relational/elements.hxx
@@ -0,0 +1,277 @@
+// file : odb/semantics/relational/elements.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC
+// license : GNU GPL v3; see accompanying LICENSE file
+
+#ifndef ODB_SEMANTICS_RELATIONAL_ELEMENTS_HXX
+#define ODB_SEMANTICS_RELATIONAL_ELEMENTS_HXX
+
+#include <map>
+#include <list>
+#include <vector>
+#include <string>
+#include <cassert>
+
+#include <cutl/container/graph.hxx>
+#include <cutl/container/pointer-iterator.hxx>
+#include <cutl/compiler/context.hxx>
+
+namespace semantics
+{
+ namespace relational
+ {
+ using namespace cutl;
+
+ using std::string;
+
+ using container::graph;
+ using container::pointer_iterator;
+
+ using compiler::context;
+
+ //
+ //
+ class node;
+ class edge;
+
+ //
+ //
+ class edge: public context
+ {
+ public:
+ virtual
+ ~edge () {}
+
+ public:
+ template <typename X>
+ bool
+ is_a () const
+ {
+ return dynamic_cast<X const*> (this) != 0;
+ }
+ };
+
+ //
+ //
+ class node: public context
+ {
+ public:
+ virtual
+ ~node () {}
+
+ // Return name of the node.
+ //
+ virtual string
+ kind () const = 0;
+
+ public:
+ template <typename X>
+ bool
+ is_a () const
+ {
+ return dynamic_cast<X const*> (this) != 0;
+ }
+
+ // Sink functions that allow extensions in the form of one-way
+ // edges.
+ //
+ public:
+ void
+ add_edge_right (edge&)
+ {
+ }
+ };
+
+ //
+ //
+ class scope;
+ class nameable;
+
+ //
+ //
+ class names: public edge
+ {
+ public:
+ typedef relational::scope scope_type;
+ typedef relational::nameable nameable_type;
+
+ string const&
+ name () const
+ {
+ return name_;
+ }
+
+ scope_type&
+ scope () const
+ {
+ return *scope_;
+ }
+
+ nameable_type&
+ nameable () const
+ {
+ return *nameable_;
+ }
+
+ public:
+ names (string const& name): name_ (name) {}
+
+ void
+ set_left_node (scope_type& n)
+ {
+ scope_ = &n;
+ }
+
+ void
+ set_right_node (nameable_type& n)
+ {
+ nameable_ = &n;
+ }
+
+ protected:
+ string name_;
+ scope_type* scope_;
+ nameable_type* nameable_;
+ };
+
+ //
+ //
+ class nameable: public virtual node
+ {
+ public:
+ typedef relational::scope scope_type;
+
+ string const&
+ name () const
+ {
+ return named_->name ();
+ }
+
+ scope_type&
+ scope () const
+ {
+ return named ().scope ();
+ }
+
+ names&
+ named () const
+ {
+ return *named_;
+ }
+
+ public:
+ // Id identifies the C++ node (e.g., a class or a data member) that
+ // this model node corresponds to. The ids are not necessarily unique
+ // (e.g., there can be a table and an index with the same id that
+ // correspond to a container member). However, in any given scope,
+ // the {id,typeid} must be unique. This becomes important when we
+ // try to find correspondance between nodes during model diff'ing.
+ //
+ nameable (string const& id): id_ (id), named_ (0) {}
+
+ void
+ add_edge_right (names& e)
+ {
+ assert (named_ == 0);
+ named_ = &e;
+ }
+
+ using node::add_edge_right;
+
+ private:
+ string id_;
+ names* named_;
+ };
+
+
+ //
+ //
+ struct duplicate_name
+ {
+ typedef relational::scope scope_type;
+ typedef relational::nameable nameable_type;
+
+ duplicate_name (scope_type& s, nameable_type& n, nameable_type& d)
+ : scope (s), nameable (n), duplicate (d)
+ {
+ }
+
+ scope_type& scope;
+ nameable_type& nameable;
+ nameable_type& duplicate;
+ };
+
+ class scope: public virtual node
+ {
+ protected:
+ typedef std::list<names*> names_list;
+ typedef std::map<string, names_list::iterator> names_map;
+ typedef std::map<names const*, names_list::iterator> names_iterator_map;
+
+ public:
+ typedef pointer_iterator<names_list::iterator> names_iterator;
+ typedef
+ pointer_iterator<names_list::const_iterator>
+ names_const_iterator;
+
+ public:
+ // Iteration.
+ //
+ names_iterator
+ names_begin ()
+ {
+ return names_.begin ();
+ }
+
+ names_iterator
+ names_end ()
+ {
+ return names_.end ();
+ }
+
+ names_const_iterator
+ names_begin () const
+ {
+ return names_.begin ();
+ }
+
+ names_const_iterator
+ names_end () const
+ {
+ return names_.end ();
+ }
+
+ // Find.
+ //
+ names_iterator
+ find (string const& name);
+
+ names_const_iterator
+ find (string const& name) const;
+
+ names_iterator
+ find (names const&);
+
+ names_const_iterator
+ find (names const&) const;
+
+ public:
+ scope ()
+ : first_key_ (names_.end ())
+ {
+ }
+
+ void
+ add_edge_left (names&);
+
+ private:
+ names_list names_;
+ names_map names_map_;
+ names_iterator_map iterator_map_;
+
+ names_list::iterator first_key_;
+ };
+ }
+}
+
+#endif // ODB_SEMANTICS_RELATIONAL_ELEMENTS_HXX
diff --git a/odb/semantics/relational/foreign-key.cxx b/odb/semantics/relational/foreign-key.cxx
new file mode 100644
index 0000000..eae9c5f
--- /dev/null
+++ b/odb/semantics/relational/foreign-key.cxx
@@ -0,0 +1,35 @@
+// file : odb/semantics/relational/foreign-key.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC
+// license : GNU GPL v3; see accompanying LICENSE file
+
+#include <cutl/compiler/type-info.hxx>
+
+#include <odb/semantics/relational/foreign-key.hxx>
+
+namespace semantics
+{
+ namespace relational
+ {
+ // type info
+ //
+ namespace
+ {
+ struct init
+ {
+ init ()
+ {
+ using compiler::type_info;
+
+ // foreign_key
+ //
+ {
+ type_info ti (typeid (foreign_key));
+ ti.add_base (typeid (key));
+ insert (ti);
+ }
+ }
+ } init_;
+ }
+ }
+}
diff --git a/odb/semantics/relational/foreign-key.hxx b/odb/semantics/relational/foreign-key.hxx
new file mode 100644
index 0000000..4a0b543
--- /dev/null
+++ b/odb/semantics/relational/foreign-key.hxx
@@ -0,0 +1,87 @@
+// file : odb/semantics/relational/foreign-key.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC
+// license : GNU GPL v3; see accompanying LICENSE file
+
+#ifndef ODB_SEMANTICS_RELATIONAL_FOREIGN_KEY_HXX
+#define ODB_SEMANTICS_RELATIONAL_FOREIGN_KEY_HXX
+
+#include <odb/semantics/relational/elements.hxx>
+#include <odb/semantics/relational/key.hxx>
+
+namespace semantics
+{
+ namespace relational
+ {
+ class foreign_key: public key
+ {
+ public:
+ enum action
+ {
+ no_action,
+ cascade
+ };
+
+ foreign_key (string const& id,
+ string const& referenced_table,
+ bool deferred,
+ action on_delete = no_action)
+ : key (id),
+ referenced_table_ (referenced_table),
+ deferred_ (deferred),
+ on_delete_ (on_delete)
+ {
+ }
+
+ public:
+ string
+ referenced_table () const
+ {
+ return referenced_table_;
+ }
+
+ typedef std::vector<string> columns;
+
+ columns const&
+ referenced_columns () const
+ {
+ return referenced_columns_;
+ }
+
+ columns&
+ referenced_columns ()
+ {
+ return referenced_columns_;
+ }
+
+ public:
+ bool
+ deferred () const
+ {
+ return deferred_;
+ }
+
+ public:
+ action
+ on_delete () const
+ {
+ return on_delete_;
+ }
+
+ public:
+ virtual string
+ kind () const
+ {
+ return "foreign key";
+ }
+
+ private:
+ string referenced_table_;
+ columns referenced_columns_;
+ bool deferred_;
+ action on_delete_;
+ };
+ }
+}
+
+#endif // ODB_SEMANTICS_RELATIONAL_FOREIGN_KEY_HXX
diff --git a/odb/semantics/relational/index.cxx b/odb/semantics/relational/index.cxx
new file mode 100644
index 0000000..376a312
--- /dev/null
+++ b/odb/semantics/relational/index.cxx
@@ -0,0 +1,35 @@
+// file : odb/semantics/relational/index.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC
+// license : GNU GPL v3; see accompanying LICENSE file
+
+#include <cutl/compiler/type-info.hxx>
+
+#include <odb/semantics/relational/index.hxx>
+
+namespace semantics
+{
+ namespace relational
+ {
+ // type info
+ //
+ namespace
+ {
+ struct init
+ {
+ init ()
+ {
+ using compiler::type_info;
+
+ // index
+ //
+ {
+ type_info ti (typeid (index));
+ ti.add_base (typeid (key));
+ insert (ti);
+ }
+ }
+ } init_;
+ }
+ }
+}
diff --git a/odb/semantics/relational/index.hxx b/odb/semantics/relational/index.hxx
new file mode 100644
index 0000000..ee6b202
--- /dev/null
+++ b/odb/semantics/relational/index.hxx
@@ -0,0 +1,44 @@
+// file : odb/semantics/relational/index.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC
+// license : GNU GPL v3; see accompanying LICENSE file
+
+#ifndef ODB_SEMANTICS_RELATIONAL_INDEX_HXX
+#define ODB_SEMANTICS_RELATIONAL_INDEX_HXX
+
+#include <odb/semantics/relational/elements.hxx>
+#include <odb/semantics/relational/key.hxx>
+#include <odb/semantics/relational/table.hxx>
+
+namespace semantics
+{
+ namespace relational
+ {
+ // Note that unlike other keys, indexes are defined in the model
+ // scope, not table scope.
+ //
+ class index: public key
+ {
+ public:
+ relational::table&
+ table () const
+ {
+ return contains_begin ()->column ().table ();
+ }
+
+ public:
+ index (string const& id)
+ : key (id)
+ {
+ }
+
+ virtual string
+ kind () const
+ {
+ return "index";
+ }
+ };
+ }
+}
+
+#endif // ODB_SEMANTICS_RELATIONAL_INDEX_HXX
diff --git a/odb/semantics/relational/key.cxx b/odb/semantics/relational/key.cxx
new file mode 100644
index 0000000..648fb26
--- /dev/null
+++ b/odb/semantics/relational/key.cxx
@@ -0,0 +1,43 @@
+// file : odb/semantics/relational/key.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC
+// license : GNU GPL v3; see accompanying LICENSE file
+
+#include <cutl/compiler/type-info.hxx>
+
+#include <odb/semantics/relational/key.hxx>
+
+namespace semantics
+{
+ namespace relational
+ {
+ // type info
+ //
+ namespace
+ {
+ struct init
+ {
+ init ()
+ {
+ using compiler::type_info;
+
+ // contains
+ //
+ {
+ type_info ti (typeid (contains));
+ ti.add_base (typeid (edge));
+ insert (ti);
+ }
+
+ // key
+ //
+ {
+ type_info ti (typeid (key));
+ ti.add_base (typeid (nameable));
+ insert (ti);
+ }
+ }
+ } init_;
+ }
+ }
+}
diff --git a/odb/semantics/relational/key.hxx b/odb/semantics/relational/key.hxx
new file mode 100644
index 0000000..7e7a847
--- /dev/null
+++ b/odb/semantics/relational/key.hxx
@@ -0,0 +1,100 @@
+// file : odb/semantics/relational/key.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC
+// license : GNU GPL v3; see accompanying LICENSE file
+
+#ifndef ODB_SEMANTICS_RELATIONAL_KEY_HXX
+#define ODB_SEMANTICS_RELATIONAL_KEY_HXX
+
+#include <odb/semantics/relational/elements.hxx>
+#include <odb/semantics/relational/column.hxx>
+
+namespace semantics
+{
+ namespace relational
+ {
+ class key;
+
+ class contains: public edge
+ {
+ public:
+ typedef relational::key key_type;
+ typedef relational::column column_type;
+
+ key_type&
+ key () const
+ {
+ return *key_;
+ }
+
+ column_type&
+ column () const
+ {
+ return *column_;
+ }
+
+ public:
+ void
+ set_left_node (key_type& n)
+ {
+ key_ = &n;
+ }
+
+ void
+ set_right_node (column_type& n)
+ {
+ column_ = &n;
+ }
+
+ protected:
+ key_type* key_;
+ column_type* column_;
+ };
+
+ class key: public nameable
+ {
+ typedef std::vector<contains*> contains_list;
+
+ public:
+ typedef
+ pointer_iterator<contains_list::const_iterator>
+ contains_iterator;
+
+ contains_iterator
+ contains_begin () const
+ {
+ return contains_.begin ();
+ }
+
+ contains_iterator
+ contains_end () const
+ {
+ return contains_.end ();
+ }
+
+ contains_list::size_type
+ contains_size () const
+ {
+ return contains_.size ();
+ }
+
+ public:
+ void
+ add_edge_left (contains& e)
+ {
+ contains_.push_back (&e);
+ }
+
+ protected:
+ key (string const& id)
+ : nameable (id)
+ {
+ }
+
+ private:
+ contains_list contains_;
+ };
+ }
+}
+
+#endif // ODB_SEMANTICS_RELATIONAL_KEY_HXX
diff --git a/odb/semantics/relational/model.cxx b/odb/semantics/relational/model.cxx
new file mode 100644
index 0000000..a0ac23f
--- /dev/null
+++ b/odb/semantics/relational/model.cxx
@@ -0,0 +1,35 @@
+// file : odb/semantics/relational/model.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC
+// license : GNU GPL v3; see accompanying LICENSE file
+
+#include <cutl/compiler/type-info.hxx>
+
+#include <odb/semantics/relational/model.hxx>
+
+namespace semantics
+{
+ namespace relational
+ {
+ // type info
+ //
+ namespace
+ {
+ struct init
+ {
+ init ()
+ {
+ using compiler::type_info;
+
+ // model
+ //
+ {
+ type_info ti (typeid (model));
+ ti.add_base (typeid (scope));
+ insert (ti);
+ }
+ }
+ } init_;
+ }
+ }
+}
diff --git a/odb/semantics/relational/model.hxx b/odb/semantics/relational/model.hxx
new file mode 100644
index 0000000..7d2f944
--- /dev/null
+++ b/odb/semantics/relational/model.hxx
@@ -0,0 +1,39 @@
+// file : odb/semantics/relational/model.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC
+// license : GNU GPL v3; see accompanying LICENSE file
+
+#ifndef ODB_SEMANTICS_RELATIONAL_MODEL_HXX
+#define ODB_SEMANTICS_RELATIONAL_MODEL_HXX
+
+#include <odb/semantics/relational/elements.hxx>
+
+namespace semantics
+{
+ namespace relational
+ {
+ class model: public graph<node, edge>, public scope
+ {
+ public:
+ model ()
+ {
+ }
+
+ virtual string
+ kind () const
+ {
+ return "model";
+ }
+
+ public:
+ using scope::add_edge_left;
+ using scope::add_edge_right;
+
+ private:
+ model (model const&);
+ model& operator= (model const&);
+ };
+ }
+}
+
+#endif // ODB_SEMANTICS_RELATIONAL_MODEL_HXX
diff --git a/odb/semantics/relational/primary-key.cxx b/odb/semantics/relational/primary-key.cxx
new file mode 100644
index 0000000..367013e
--- /dev/null
+++ b/odb/semantics/relational/primary-key.cxx
@@ -0,0 +1,35 @@
+// file : odb/semantics/relational/primary-key.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC
+// license : GNU GPL v3; see accompanying LICENSE file
+
+#include <cutl/compiler/type-info.hxx>
+
+#include <odb/semantics/relational/primary-key.hxx>
+
+namespace semantics
+{
+ namespace relational
+ {
+ // type info
+ //
+ namespace
+ {
+ struct init
+ {
+ init ()
+ {
+ using compiler::type_info;
+
+ // primary_key
+ //
+ {
+ type_info ti (typeid (primary_key));
+ ti.add_base (typeid (key));
+ insert (ti);
+ }
+ }
+ } init_;
+ }
+ }
+}
diff --git a/odb/semantics/relational/primary-key.hxx b/odb/semantics/relational/primary-key.hxx
new file mode 100644
index 0000000..a35e8f5
--- /dev/null
+++ b/odb/semantics/relational/primary-key.hxx
@@ -0,0 +1,45 @@
+// file : odb/semantics/relational/primary-key.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC
+// license : GNU GPL v3; see accompanying LICENSE file
+
+#ifndef ODB_SEMANTICS_RELATIONAL_PRIMARY_KEY_HXX
+#define ODB_SEMANTICS_RELATIONAL_PRIMARY_KEY_HXX
+
+#include <odb/semantics/relational/elements.hxx>
+#include <odb/semantics/relational/key.hxx>
+
+namespace semantics
+{
+ namespace relational
+ {
+ class primary_key: public key
+ {
+ public:
+ bool
+ auto_ () const
+ {
+ return auto__;
+ }
+
+ public:
+ // Primary key has the implicit empty id.
+ //
+ primary_key (bool auto_)
+ : key (""), auto__ (auto_)
+ {
+ }
+
+ virtual string
+ kind () const
+ {
+ return "primary key";
+ }
+
+ private:
+ bool auto__;
+ };
+ }
+}
+
+#endif // ODB_SEMANTICS_RELATIONAL_PRIMARY_KEY_HXX
diff --git a/odb/semantics/relational/table.cxx b/odb/semantics/relational/table.cxx
new file mode 100644
index 0000000..a9290c6
--- /dev/null
+++ b/odb/semantics/relational/table.cxx
@@ -0,0 +1,52 @@
+// file : odb/semantics/relational/table.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC
+// license : GNU GPL v3; see accompanying LICENSE file
+
+#include <cutl/compiler/type-info.hxx>
+
+#include <odb/semantics/relational/table.hxx>
+
+namespace semantics
+{
+ namespace relational
+ {
+ // type info
+ //
+ namespace
+ {
+ struct init
+ {
+ init ()
+ {
+ using compiler::type_info;
+
+ // table
+ //
+ {
+ type_info ti (typeid (table));
+ ti.add_base (typeid (nameable));
+ ti.add_base (typeid (scope));
+ insert (ti);
+ }
+
+ // object_table
+ //
+ {
+ type_info ti (typeid (object_table));
+ ti.add_base (typeid (table));
+ insert (ti);
+ }
+
+ // container_table
+ //
+ {
+ type_info ti (typeid (container_table));
+ ti.add_base (typeid (table));
+ insert (ti);
+ }
+ }
+ } init_;
+ }
+ }
+}
diff --git a/odb/semantics/relational/table.hxx b/odb/semantics/relational/table.hxx
new file mode 100644
index 0000000..d2f8649
--- /dev/null
+++ b/odb/semantics/relational/table.hxx
@@ -0,0 +1,56 @@
+// file : odb/semantics/relational/table.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC
+// license : GNU GPL v3; see accompanying LICENSE file
+
+#ifndef ODB_SEMANTICS_RELATIONAL_TABLE_HXX
+#define ODB_SEMANTICS_RELATIONAL_TABLE_HXX
+
+#include <odb/semantics/relational/elements.hxx>
+
+namespace semantics
+{
+ namespace relational
+ {
+ class table: public nameable, public scope
+ {
+ protected:
+ table (string const& id)
+ : nameable (id)
+ {
+ }
+ };
+
+ class object_table: public table
+ {
+ public:
+ object_table (string const& id)
+ : table (id)
+ {
+ }
+
+ virtual string
+ kind () const
+ {
+ return "object table";
+ }
+ };
+
+ class container_table: public table
+ {
+ public:
+ container_table (string const& id)
+ : table (id)
+ {
+ }
+
+ virtual string
+ kind () const
+ {
+ return "container table";
+ }
+ };
+ }
+}
+
+#endif // ODB_SEMANTICS_RELATIONAL_TABLE_HXX