aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorConstantin Michael <constantin@codesynthesis.com>2011-07-08 13:53:58 +0200
committerConstantin Michael <constantin@codesynthesis.com>2011-07-08 14:33:02 +0200
commita141e3ca1ec78989de58e4498aaaca0da966bd03 (patch)
treeb52687d458b645dc6983fded41a41d1d216d2840
parent6d7ac4aa978914e8e9e274f813f3aa4a9396a2fa (diff)
Add foreign keys to PostgreSQL schema generation
-rw-r--r--odb/relational/pgsql/schema.cxx129
1 files changed, 129 insertions, 0 deletions
diff --git a/odb/relational/pgsql/schema.cxx b/odb/relational/pgsql/schema.cxx
index de4d507..68c0e4c 100644
--- a/odb/relational/pgsql/schema.cxx
+++ b/odb/relational/pgsql/schema.cxx
@@ -75,8 +75,137 @@ namespace relational
base::type (m);
}
}
+
+ virtual void
+ reference (semantics::data_member&)
+ {
+ }
};
entry<object_columns> object_columns_;
+
+ struct object_columns_references:
+ object_columns_base, relational::common, context
+ {
+ object_columns_references (emitter& e,
+ ostream& os,
+ string const& table,
+ string const& prefix = string ())
+ : relational::common (e, os),
+ table_ (table),
+ prefix_ (prefix)
+ {
+ }
+
+ virtual bool
+ column (semantics::data_member& m, string const& name, bool)
+ {
+ semantics::class_* c (object_pointer (member_type (m, prefix_)));
+
+ if (c != 0 && !inverse (m))
+ {
+ pre_statement ();
+
+ os << "ALTER TABLE " << quote_id (table_) << endl
+ << " ADD FOREIGN KEY (" << quote_id (name) << ")" <<
+ endl
+ << " REFERENCES " << quote_id (table_name (*c)) << endl
+ << " INITIALLY DEFERRED" << endl;
+
+ post_statement ();
+ }
+
+ return true;
+ }
+
+ private:
+ string table_;
+ string prefix_;
+ };
+
+ struct member_create: object_members_base, context
+ {
+ member_create (emitter& e, ostream& os, relational::tables& tables)
+ : object_members_base (false, true),
+ e_ (e),
+ os_ (os),
+ tables_ (tables)
+ {
+ }
+
+ 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;
+
+ string const& name (table_name (m, table_prefix_));
+
+ if (tables_.count (name))
+ return;
+
+ type& t (m.type ());
+ type& vt (container_vt (t));
+
+ if (semantics::class_* cvt = comp_value (vt))
+ {
+ object_columns_references ocr (e_, os_, name);
+ ocr.traverse_composite (m, *cvt, "value", "value");
+ }
+ else
+ {
+ object_columns_references ocr (e_, os_, name, "value");
+ string const& name (column_name (m, "value", "value"));
+ ocr.column (m, name, true);
+ }
+
+ tables_.insert (name);
+ }
+
+ private:
+ emitter& e_;
+ ostream& os_;
+ relational::tables& tables_;
+ };
+
+ struct class_create: relational::class_create
+ {
+ class_create (base const& x): base (x) {}
+
+ virtual void
+ traverse (type& c)
+ {
+ if (pass_ != 2)
+ {
+ base::traverse (c);
+ return;
+ }
+
+ if (c.file () != unit.file ())
+ return;
+
+ if (!c.count ("object") || abstract (c))
+ return;
+
+ string const& name (table_name (c));
+
+ if (tables_[pass_].count (name))
+ return;
+
+ object_columns_references ocr (e_, os_, name);
+ ocr.traverse (c);
+
+ tables_[pass_].insert (name);
+
+ member_create mc (e_, os_, tables_[pass_]);
+ mc.traverse (c);
+ }
+ };
+ entry<class_create> class_create_;
}
}
}