From 6692558ba588c76f5e61eb7ed9a1040d36cb9ed7 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 26 Apr 2013 17:18:12 +0200 Subject: Add support for extra database info in primary key Use that to handle Oracle sequence name and SQLite lax auto ids. --- odb/relational/changelog.cxx | 18 ++++++++ odb/relational/model.hxx | 6 +++ odb/relational/mssql/schema.cxx | 2 +- odb/relational/mysql/schema.cxx | 2 +- odb/relational/oracle/model.cxx | 7 ++++ odb/relational/oracle/schema.cxx | 14 +++---- odb/relational/schema.hxx | 4 +- odb/relational/sqlite/model.cxx | 7 ++++ odb/relational/sqlite/schema.cxx | 4 +- odb/semantics/relational/elements.hxx | 29 +++++++------ odb/semantics/relational/name.cxx | 70 +++++++++++++++----------------- odb/semantics/relational/name.hxx | 3 ++ odb/semantics/relational/primary-key.cxx | 18 +++++++- odb/semantics/relational/primary-key.hxx | 14 +++++++ 14 files changed, 132 insertions(+), 66 deletions(-) (limited to 'odb') diff --git a/odb/relational/changelog.cxx b/odb/relational/changelog.cxx index 6fc85b7..63ea44f 100644 --- a/odb/relational/changelog.cxx +++ b/odb/relational/changelog.cxx @@ -97,6 +97,24 @@ namespace relational if (pk.auto_ () != opk->auto_ ()) diagnose_primary_key (pk, "auto kind"); + // Database-specific information. + // + for (primary_key::extra_map::const_iterator i ( + pk.extra ().begin ()); i != pk.extra ().end (); ++i) + { + if (opk->extra ().count (i->first) == 0 || + opk->extra ()[i->first] != i->second) + diagnose_primary_key (pk, i->first.c_str ()); + } + + for (primary_key::extra_map::const_iterator i ( + opk->extra ().begin ()); i != opk->extra ().end (); ++i) + { + if (pk.extra ().count (i->first) == 0 || + pk.extra ()[i->first] != i->second) + diagnose_primary_key (pk, i->first.c_str ()); + } + if (pk.contains_size () != opk->contains_size ()) diagnose_primary_key (pk, "member set"); diff --git a/odb/relational/model.hxx b/odb/relational/model.hxx index 6552048..af88eb5 100644 --- a/odb/relational/model.hxx +++ b/odb/relational/model.hxx @@ -187,6 +187,11 @@ namespace relational } virtual void + primary_key (sema_rel::primary_key&) + { + } + + virtual void constraints (semantics::data_member& m, string const& /* name */, string const& /* id */, @@ -211,6 +216,7 @@ namespace relational // name. // model_.new_edge (table_, *pkey_, ""); + primary_key (*pkey_); } model_.new_edge (*pkey_, c); diff --git a/odb/relational/mssql/schema.cxx b/odb/relational/mssql/schema.cxx index c61bbc2..18c1f87 100644 --- a/odb/relational/mssql/schema.cxx +++ b/odb/relational/mssql/schema.cxx @@ -224,7 +224,7 @@ namespace relational } virtual void - auto_ (sema_rel::column&) + auto_ (sema_rel::primary_key&) { os << " IDENTITY"; } diff --git a/odb/relational/mysql/schema.cxx b/odb/relational/mysql/schema.cxx index f89bb61..f06914a 100644 --- a/odb/relational/mysql/schema.cxx +++ b/odb/relational/mysql/schema.cxx @@ -134,7 +134,7 @@ namespace relational create_column (base const& x): base (x) {} virtual void - auto_ (sema_rel::column&) + auto_ (sema_rel::primary_key&) { os << " AUTO_INCREMENT"; } diff --git a/odb/relational/oracle/model.cxx b/odb/relational/oracle/model.cxx index 8032b3b..91f1285 100644 --- a/odb/relational/oracle/model.cxx +++ b/odb/relational/oracle/model.cxx @@ -51,6 +51,13 @@ namespace relational return ostr.str (); } + + virtual void + primary_key (sema_rel::primary_key& pk) + { + if (pk.auto_ ()) + pk.extra ()["sequence"] = sequence_name (table_.name ()).string (); + } }; entry object_columns_; } diff --git a/odb/relational/oracle/schema.cxx b/odb/relational/oracle/schema.cxx index 03da322..5856dd2 100644 --- a/odb/relational/oracle/schema.cxx +++ b/odb/relational/oracle/schema.cxx @@ -149,16 +149,14 @@ namespace relational using sema_rel::primary_key; - qname const& table (t.name ()); - sema_rel::table::names_iterator i (t.find ("")); // Special name. primary_key* pk (i != t.names_end () ? &dynamic_cast (i->nameable ()) : 0); - string qt (quote_id (table)); + string qt (quote_id (t.name ())); string qs (pk != 0 && pk->auto_ () - ? quote_id (sequence_name (table)) + ? quote_id (qname::from_string (pk->extra ()["sequence"])) : ""); if (migration) @@ -249,7 +247,7 @@ namespace relational primary_key (); if (pk != 0 && pk->auto_ ()) - auto_ (c); + auto_ (*pk); } }; entry create_column_; @@ -307,9 +305,11 @@ namespace relational if (pk != 0 && pk->auto_ ()) { + string qs ( + quote_id (qname::from_string (pk->extra ()["sequence"]))); + pre_statement (); - os_ << "CREATE SEQUENCE " << - quote_id (sequence_name (t.name ())) << endl + os_ << "CREATE SEQUENCE " << qs << endl << " START WITH 1 INCREMENT BY 1" << endl; post_statement (); } diff --git a/odb/relational/schema.hxx b/odb/relational/schema.hxx index 95dd68c..85dca09 100644 --- a/odb/relational/schema.hxx +++ b/odb/relational/schema.hxx @@ -535,7 +535,7 @@ namespace relational primary_key (); if (pk != 0 && pk->auto_ ()) - auto_ (c); + auto_ (*pk); } virtual void @@ -570,7 +570,7 @@ namespace relational } virtual void - auto_ (sema_rel::column&) + auto_ (sema_rel::primary_key&) { } diff --git a/odb/relational/sqlite/model.cxx b/odb/relational/sqlite/model.cxx index 63a5302..8f7e341 100644 --- a/odb/relational/sqlite/model.cxx +++ b/odb/relational/sqlite/model.cxx @@ -57,6 +57,13 @@ namespace relational return ostr.str (); } + + virtual void + primary_key (sema_rel::primary_key& pk) + { + if (pk.auto_ () && options.sqlite_lax_auto_id ()) + pk.extra ()["lax"] = "true"; + } }; entry object_columns_; } diff --git a/odb/relational/sqlite/schema.cxx b/odb/relational/sqlite/schema.cxx index 4a2eef2..46ce762 100644 --- a/odb/relational/sqlite/schema.cxx +++ b/odb/relational/sqlite/schema.cxx @@ -117,9 +117,9 @@ namespace relational } virtual void - auto_ (sema_rel::column&) + auto_ (sema_rel::primary_key& pk) { - if (options.sqlite_lax_auto_id ()) + if (pk.extra ().count ("lax")) os << " /*AUTOINCREMENT*/"; else os << " AUTOINCREMENT"; diff --git a/odb/semantics/relational/elements.hxx b/odb/semantics/relational/elements.hxx index 11e7ea8..a0f02a4 100644 --- a/odb/semantics/relational/elements.hxx +++ b/odb/semantics/relational/elements.hxx @@ -49,37 +49,28 @@ namespace semantics class edge: public context { public: - virtual - ~edge () {} - - public: template bool is_a () const { return dynamic_cast (this) != 0; } + + public: + virtual + ~edge () {} }; // // class node: public context { - public: - virtual - ~node () {} - // Return name of the node. // + public: virtual string kind () const = 0; - // XML serialization. - // - public: - virtual void - serialize (xml::serializer&) const = 0; - public: template bool @@ -88,10 +79,18 @@ namespace semantics return dynamic_cast (this) != 0; } + public: + virtual + ~node () {} + + // XML serialization. + // + virtual void + serialize (xml::serializer&) const = 0; + // Sink functions that allow extensions in the form of one-way // edges. // - public: void add_edge_right (edge&) {} diff --git a/odb/semantics/relational/name.cxx b/odb/semantics/relational/name.cxx index 861bac2..8c1af33 100644 --- a/odb/semantics/relational/name.cxx +++ b/odb/semantics/relational/name.cxx @@ -35,58 +35,54 @@ namespace semantics return r; } - ostream& - operator<< (ostream& os, qname const& n) + qname qname:: + from_string (std::string const& s) { - bool f (true); - for (qname::iterator i (n.begin ()); i < n.end (); ++i) + using std::string; + + qname n; + + string::size_type p (string::npos); + + for (size_t i (0); i < s.size (); ++i) { - if (i->empty ()) - continue; + char c (s[i]); - if (f) - f = false; - else - os << '.'; + if (c == '.') + { + if (p == string::npos) + n.append (string (s, 0, i)); + else + n.append (string (s, p + 1, i - p - 1)); - os << *i; + p = i; + } } - return os; + if (p == string::npos) + n.append (s); + else + n.append (string (s, p + 1, string::npos)); + + return n; + } + + ostream& + operator<< (ostream& os, qname const& n) + { + return os << n.string (); } istream& operator>> (istream& is, qname& n) { - n.clear (); - string s; is >> s; if (!is.fail ()) - { - string::size_type p (string::npos); - - for (size_t i (0); i < s.size (); ++i) - { - char c (s[i]); - - if (c == '.') - { - if (p == string::npos) - n.append (string (s, 0, i)); - else - n.append (string (s, p + 1, i - p - 1)); - - p = i; - } - } - - if (p == string::npos) - n.append (s); - else - n.append (string (s, p + 1, string::npos)); - } + n = qname::from_string (s); + else + n.clear (); return is; } diff --git a/odb/semantics/relational/name.hxx b/odb/semantics/relational/name.hxx index 06794be..4ea4487 100644 --- a/odb/semantics/relational/name.hxx +++ b/odb/semantics/relational/name.hxx @@ -123,6 +123,9 @@ namespace semantics std::string string () const; + static qname + from_string (std::string const&); + public: friend bool operator== (qname const& x, qname const& y) diff --git a/odb/semantics/relational/primary-key.cxx b/odb/semantics/relational/primary-key.cxx index fdfed0e..a05887f 100644 --- a/odb/semantics/relational/primary-key.cxx +++ b/odb/semantics/relational/primary-key.cxx @@ -12,7 +12,7 @@ namespace semantics { primary_key:: primary_key (primary_key const& k, uscope& s, graph& g) - : key (k, s, g), auto__ (k.auto__) + : key (k, s, g), auto__ (k.auto__), extra_map_ (k.extra_map_) { } @@ -21,6 +21,16 @@ namespace semantics : key (p, s, g), auto__ (p.attribute ("auto", false)) { + // All unhandled attributes go into the extra map. + // + typedef xml::parser::attribute_map_type attr_map; + attr_map const& am (p.attribute_map ()); + + for (attr_map::const_iterator i (am.begin ()); i != am.end (); ++i) + { + if (!i->second.handled) + extra_map_[i->first.name ()] = i->second.value; + } } primary_key& primary_key:: @@ -34,8 +44,14 @@ namespace semantics { s.start_element (xmlns, "primary-key"); key::serialize_attributes (s); + if (auto_ ()) s.attribute ("auto", true); + + for (extra_map::const_iterator i (extra_map_.begin ()); + i != extra_map_.end (); ++i) + s.attribute (i->first, i->second); + key::serialize_content (s); s.end_element (); } diff --git a/odb/semantics/relational/primary-key.hxx b/odb/semantics/relational/primary-key.hxx index 073245b..0f28966 100644 --- a/odb/semantics/relational/primary-key.hxx +++ b/odb/semantics/relational/primary-key.hxx @@ -5,6 +5,8 @@ #ifndef ODB_SEMANTICS_RELATIONAL_PRIMARY_KEY_HXX #define ODB_SEMANTICS_RELATIONAL_PRIMARY_KEY_HXX +#include + #include #include @@ -18,6 +20,17 @@ namespace semantics bool auto_ () const {return auto__;} + // Extra database information. + // + public: + typedef std::map extra_map; + + extra_map& + extra () {return extra_map_;} + + extra_map const& + extra () const {return extra_map_;} + public: primary_key (bool auto_) : key (""), // Primary key has the implicit empty id. @@ -42,6 +55,7 @@ namespace semantics private: bool auto__; + extra_map extra_map_; }; } } -- cgit v1.1