summaryrefslogtreecommitdiff
path: root/odb/relational/model.cxx
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/relational/model.cxx
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/relational/model.cxx')
-rw-r--r--odb/relational/model.cxx168
1 files changed, 168 insertions, 0 deletions
diff --git a/odb/relational/model.cxx b/odb/relational/model.cxx
new file mode 100644
index 0000000..e44ffec
--- /dev/null
+++ b/odb/relational/model.cxx
@@ -0,0 +1,168 @@
+// file : odb/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 <odb/gcc.hxx>
+
+#include <cassert>
+#include <limits>
+#include <sstream>
+
+#include <odb/relational/model.hxx>
+#include <odb/relational/generate.hxx>
+
+using namespace std;
+
+namespace relational
+{
+ namespace model
+ {
+ // object_columns
+ //
+ string object_columns::
+ default_ (semantics::data_member& m)
+ {
+ default_value* dv (0);
+
+ semantics::type& t (utype (m));
+
+ if (m.count ("default"))
+ dv = &m.get<default_value> ("default");
+ else if (t.count ("default"))
+ dv = &t.get<default_value> ("default");
+ else
+ return ""; // No default value for this column.
+
+ switch (dv->kind)
+ {
+ case default_value::reset:
+ {
+ // No default value.
+ return "";
+ }
+ case default_value::null:
+ {
+ return default_null (m);
+ break;
+ }
+ case default_value::boolean:
+ {
+ return default_bool (m, dv->value == "true");
+ break;
+ }
+ case default_value::number:
+ {
+ tree n (dv->node);
+
+ switch (TREE_CODE (n))
+ {
+ case INTEGER_CST:
+ {
+ HOST_WIDE_INT hwl (TREE_INT_CST_LOW (n));
+ HOST_WIDE_INT hwh (TREE_INT_CST_HIGH (n));
+
+ unsigned long long l (hwl);
+ unsigned long long h (hwh);
+ unsigned short width (HOST_BITS_PER_WIDE_INT);
+
+ unsigned long long v ((h << width) + l);
+
+ return default_integer (m, v, dv->value == "-");
+ break;
+ }
+ case REAL_CST:
+ {
+ double v;
+
+ REAL_VALUE_TYPE d (TREE_REAL_CST (n));
+
+ if (REAL_VALUE_ISINF (d))
+ v = numeric_limits<double>::infinity ();
+ else if (REAL_VALUE_ISNAN (d))
+ v = numeric_limits<double>::quiet_NaN ();
+ else
+ {
+ char tmp[256];
+ real_to_decimal (tmp, &d, sizeof (tmp), 0, true);
+ istringstream is (tmp);
+ is >> v;
+ }
+
+ if (dv->value == "-")
+ v = -v;
+
+ return default_float (m, v);
+ break;
+ }
+ default:
+ assert (false);
+ }
+ break;
+ }
+ case default_value::string:
+ {
+ return default_string (m, dv->value);
+ break;
+ }
+ case default_value::enumerator:
+ {
+ return default_enum (m, dv->node, dv->value);
+ break;
+ }
+ }
+
+ return "";
+ }
+
+ cutl::shared_ptr<sema_rel::model>
+ generate ()
+ {
+ context ctx;
+ cutl::shared_ptr<sema_rel::model> m (new (shared) sema_rel::model);
+
+ traversal::unit unit;
+ traversal::defines unit_defines;
+ traversal::namespace_ ns;
+ instance<class_> c (*m);
+
+ unit >> unit_defines >> ns;
+ unit_defines >> c;
+
+ traversal::defines ns_defines;
+
+ ns >> ns_defines >> ns;
+ ns_defines >> c;
+
+ try
+ {
+ unit.dispatch (ctx.unit);
+ }
+ catch (sema_rel::duplicate_name const& e)
+ {
+ semantics::node& n (*e.nameable.get<semantics::node*> ("cxx-node"));
+ semantics::node& d (*e.duplicate.get<semantics::node*> ("cxx-node"));
+
+ cerr << d.file () << ":" << d.line () << ":" << d.column ()
+ << ": error: " << e.duplicate.kind () << " name '"
+ << e.nameable.name () << "' conflicts with an already defined "
+ << e.nameable.kind () << " name"
+ << endl;
+
+ cerr << n.file () << ":" << n.line () << ":" << n.column ()
+ << ": info: conflicting " << e.nameable.kind () << " is "
+ << "defined here"
+ << endl;
+
+ cerr << d.file () << ":" << d.line () << ":" << d.column ()
+ << ": error: use '#pragma db column' or '#pragma db table' "
+ << "to change one of the names"
+ << endl;
+
+ throw operation_failed ();
+ }
+
+ return m;
+ }
+ }
+}