aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2013-04-26 17:18:12 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2013-04-26 17:18:12 +0200
commit6692558ba588c76f5e61eb7ed9a1040d36cb9ed7 (patch)
tree6f7a29e911713829583bc573e938591383f8486c
parent84cb9f184bc24ef7151ab9931b46311b03219b14 (diff)
Add support for extra database info in primary key
Use that to handle Oracle sequence name and SQLite lax auto ids.
-rw-r--r--odb/relational/changelog.cxx18
-rw-r--r--odb/relational/model.hxx6
-rw-r--r--odb/relational/mssql/schema.cxx2
-rw-r--r--odb/relational/mysql/schema.cxx2
-rw-r--r--odb/relational/oracle/model.cxx7
-rw-r--r--odb/relational/oracle/schema.cxx14
-rw-r--r--odb/relational/schema.hxx4
-rw-r--r--odb/relational/sqlite/model.cxx7
-rw-r--r--odb/relational/sqlite/schema.cxx4
-rw-r--r--odb/semantics/relational/elements.hxx29
-rw-r--r--odb/semantics/relational/name.cxx70
-rw-r--r--odb/semantics/relational/name.hxx3
-rw-r--r--odb/semantics/relational/primary-key.cxx18
-rw-r--r--odb/semantics/relational/primary-key.hxx14
14 files changed, 132 insertions, 66 deletions
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<sema_rel::unames> (table_, *pkey_, "");
+ primary_key (*pkey_);
}
model_.new_edge<sema_rel::contains> (*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> 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<primary_key&> (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> 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> 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 <typename X>
bool
is_a () const
{
return dynamic_cast<X const*> (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 <typename X>
bool
@@ -88,10 +79,18 @@ namespace semantics
return dynamic_cast<X const*> (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 <map>
+
#include <odb/semantics/relational/elements.hxx>
#include <odb/semantics/relational/key.hxx>
@@ -18,6 +20,17 @@ namespace semantics
bool
auto_ () const {return auto__;}
+ // Extra database information.
+ //
+ public:
+ typedef std::map<string, string> 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_;
};
}
}