aboutsummaryrefslogtreecommitdiff
path: root/odb/relational/oracle
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2012-02-17 10:08:18 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2012-02-22 12:29:43 +0200
commit3a1eed21d4d5d0e7f6a9f400420fdc28d7be9b61 (patch)
tree97ba7338fb804c264c9eaaaa41085b08f6483c68 /odb/relational/oracle
parent3f73cc933b64d7d9a88325d33a3c33a0e28720c6 (diff)
Add support for composite object ids
New pragma id_type (member). New test: common/composite-id. The composite example has also been updated.
Diffstat (limited to 'odb/relational/oracle')
-rw-r--r--odb/relational/oracle/common.cxx101
-rw-r--r--odb/relational/oracle/common.hxx118
-rw-r--r--odb/relational/oracle/context.cxx17
-rw-r--r--odb/relational/oracle/context.hxx8
-rw-r--r--odb/relational/oracle/model.cxx4
-rw-r--r--odb/relational/oracle/source.cxx356
6 files changed, 79 insertions, 525 deletions
diff --git a/odb/relational/oracle/common.cxx b/odb/relational/oracle/common.cxx
index 88183cf..661bb4e 100644
--- a/odb/relational/oracle/common.cxx
+++ b/odb/relational/oracle/common.cxx
@@ -16,91 +16,10 @@ namespace relational
// member_base
//
- void member_base::
- traverse (semantics::data_member& m)
+ sql_type const& member_base::
+ member_sql_type (semantics::data_member& m)
{
- if (transient (m))
- return;
-
- string var;
-
- if (!var_override_.empty ())
- var = var_override_;
- else
- {
- string const& name (m.name ());
- var = name + (name[name.size () - 1] == '_' ? "" : "_");
- }
-
- bool cq (type_override_ != 0 ? false : const_type (m.type ()));
- semantics::type& t (type_override_ != 0 ? *type_override_ : utype (m));
-
- semantics::type* cont;
- if (semantics::class_* c = composite_wrapper (t))
- {
- // If t is a wrapper, pass the wrapped type. Also pass the
- // original, wrapper type.
- //
- member_info mi (m,
- *c,
- (wrapper (t) ? &t : 0),
- cq,
- var,
- fq_type_override_);
- if (pre (mi))
- {
- traverse_composite (mi);
- post (mi);
- }
- }
- // This cannot be a container if we have a type override.
- //
- else if (type_override_ == 0 && (cont = context::container (m)))
- {
- // The same unwrapping logic as for composite values.
- //
- member_info mi (m,
- *cont,
- (wrapper (t) ? &t : 0),
- cq,
- var,
- fq_type_override_);
- if (pre (mi))
- {
- traverse_container (mi);
- post (mi);
- }
- }
- else
- {
- sql_type const& st (column_sql_type (m, key_prefix_));
-
- if (semantics::class_* c = object_pointer (t))
- {
- member_info mi (m,
- utype (*id_member (*c)),
- 0,
- cq,
- var,
- fq_type_override_);
- mi.st = &st;
- if (pre (mi))
- {
- traverse_object_pointer (mi);
- post (mi);
- }
- }
- else
- {
- member_info mi (m, t, 0, cq, var, fq_type_override_);
- mi.st = &st;
- if (pre (mi))
- {
- traverse_simple (mi);
- post (mi);
- }
- }
- }
+ return parse_sql_type (column_type (m, key_prefix_), m);
}
void member_base::
@@ -374,10 +293,18 @@ namespace relational
}
member_database_type_id::
+ member_database_type_id (base const& x)
+ : member_base::base (x), // virtual base
+ base (x)
+ {
+ }
+
+ member_database_type_id::
member_database_type_id (semantics::type* type,
string const& fq_type,
string const& key_prefix)
- : relational::member_base (type, fq_type, key_prefix)
+ : member_base::base (type, fq_type, key_prefix), // virtual base
+ base (type, fq_type, key_prefix)
{
}
@@ -469,6 +396,8 @@ namespace relational
lob_database_id[mi.st->type - sql_type::BLOB];
}
+ entry<member_database_type_id> member_database_type_id_;
+
//
// query_columns
//
@@ -494,7 +423,7 @@ namespace relational
{
// For some types we need to pass precision and scale.
//
- sql_type const& st (column_sql_type (m));
+ sql_type const& st (parse_sql_type (column_type (), m));
switch (st.type)
{
diff --git a/odb/relational/oracle/common.hxx b/odb/relational/oracle/common.hxx
index 0f4517d..15120fd 100644
--- a/odb/relational/oracle/common.hxx
+++ b/odb/relational/oracle/common.hxx
@@ -12,118 +12,18 @@ namespace relational
{
namespace oracle
{
- struct member_base: virtual relational::member_base, context
+ struct member_base: virtual relational::member_base_impl<sql_type>, context
{
- member_base (base const& x): base (x) {}
+ member_base (base const& x): base (x), base_impl (x) {}
// This c-tor is for the direct use inside the oracle namespace.
// If you do use this c-tor, you should also explicitly call
- // relational::member_base.
+ // relational::member_base (aka base).
//
member_base () {}
- virtual void
- traverse (semantics::data_member& m);
-
- struct member_info
- {
- semantics::data_member& m; // Member.
- semantics::type& t; // Cvr-unqualified member C++ type, note
- // that m.type () may not be the same as t.
- semantics::type* wrapper; // Wrapper type if member is a composite or
- // container wrapper, also cvr-unqualified.
- // In this case t is the wrapped type.
- bool cq; // True if the original (wrapper) type
- // is const-qualified.
- sql_type const* st; // Member SQL type (only simple values).
- string& var; // Member variable name with trailing '_'.
-
- // C++ type fq-name.
- //
- string
- fq_type (bool unwrap = true) const
- {
- semantics::names* hint;
-
- if (wrapper != 0 && unwrap)
- {
- // Use the hint from the wrapper unless the wrapped type
- // is qualified.
- //
- hint = wrapper->get<semantics::names*> ("wrapper-hint");
- utype (*context::wrapper (*wrapper), hint);
- return t.fq_name (hint);
- }
-
- // Use the original type from 'm' instead of 't' since the hint
- // may be invalid for a different type. Plus, if a type is
- // overriden, then the fq_type must be as well.
- //
- if (fq_type_.empty ())
- {
- semantics::type& t (utype (m, hint));
- return t.fq_name (hint);
- }
- else
- return fq_type_;
- }
-
- string const& fq_type_;
-
- member_info (semantics::data_member& m_,
- semantics::type& t_,
- semantics::type* wrapper_,
- bool cq_,
- string& var_,
- string const& fq_type)
- : m (m_),
- t (t_),
- wrapper (wrapper_),
- cq (cq_),
- st (0),
- var (var_),
- fq_type_ (fq_type)
- {
- }
- };
-
- bool
- container (member_info& mi)
- {
- // This cannot be a container if we have a type override.
- //
- return type_override_ == 0 && context::container (mi.m);
- }
-
- // The false return value indicates that no further callbacks
- // should be called for this member.
- //
- virtual bool
- pre (member_info&)
- {
- return true;
- }
-
- virtual void
- post (member_info&)
- {
- }
-
- virtual void
- traverse_composite (member_info&)
- {
- }
-
- virtual void
- traverse_container (member_info&)
- {
- }
-
- virtual void
- traverse_object_pointer (member_info& mi)
- {
- traverse_simple (mi);
- }
+ virtual sql_type const&
+ member_sql_type (semantics::data_member&);
virtual void
traverse_simple (member_info&);
@@ -240,12 +140,16 @@ namespace relational
string type_;
};
- struct member_database_type_id: member_base
+ struct member_database_type_id: relational::member_database_type_id,
+ member_base
{
+ member_database_type_id (base const&);
+
member_database_type_id (semantics::type* type = 0,
string const& fq_type = string (),
string const& key_prefix = string ());
- string
+
+ virtual string
database_type_id (type&);
virtual void
diff --git a/odb/relational/oracle/context.cxx b/odb/relational/oracle/context.cxx
index 3d87729..dbe61af 100644
--- a/odb/relational/oracle/context.cxx
+++ b/odb/relational/oracle/context.cxx
@@ -159,17 +159,20 @@ namespace relational
//
sql_type const& context::
- column_sql_type (semantics::data_member& m, string const& kp)
+ parse_sql_type (string const& t, semantics::data_member& m)
{
- string key (kp.empty ()
- ? string ("oracle-column-sql-type")
- : "oracle-" + kp + "-column-sql-type");
+ // If this proves to be too expensive, we can maintain a
+ // cache of parsed types.
+ //
+ data::sql_type_cache::iterator i (data_->sql_type_cache_.find (t));
- if (!m.count (key))
+ if (i != data_->sql_type_cache_.end ())
+ return i->second;
+ else
{
try
{
- m.set (key, parse_sql_type (column_type (m, kp)));
+ return (data_->sql_type_cache_[t] = parse_sql_type (t));
}
catch (invalid_sql_type const& e)
{
@@ -179,8 +182,6 @@ namespace relational
throw operation_failed ();
}
}
-
- return m.get<sql_type> (key);
}
sql_type context::
diff --git a/odb/relational/oracle/context.hxx b/odb/relational/oracle/context.hxx
index 273f0e5..37716f0 100644
--- a/odb/relational/oracle/context.hxx
+++ b/odb/relational/oracle/context.hxx
@@ -5,6 +5,8 @@
#ifndef ODB_RELATIONAL_ORACLE_CONTEXT_HXX
#define ODB_RELATIONAL_ORACLE_CONTEXT_HXX
+#include <map>
+
#include <odb/relational/context.hxx>
namespace relational
@@ -73,8 +75,7 @@ namespace relational
{
public:
sql_type const&
- column_sql_type (semantics::data_member&,
- string const& key_prefix = string ());
+ parse_sql_type (string const&, semantics::data_member&);
public:
struct invalid_sql_type
@@ -126,6 +127,9 @@ namespace relational
struct data: base_context::data
{
data (std::ostream& os): base_context::data (os) {}
+
+ typedef std::map<string, sql_type> sql_type_cache;
+ sql_type_cache sql_type_cache_;
};
data* data_;
};
diff --git a/odb/relational/oracle/model.cxx b/odb/relational/oracle/model.cxx
index 347ea37..4b874c8 100644
--- a/odb/relational/oracle/model.cxx
+++ b/odb/relational/oracle/model.cxx
@@ -28,9 +28,7 @@ namespace relational
{
// Make sure the column is mapped to Oracle NUMBER.
//
- sql_type t (column_sql_type (m));
-
- if (t.type != sql_type::NUMBER)
+ if (parse_sql_type (column_type (), m).type != sql_type::NUMBER)
{
cerr << m.file () << ":" << m.line () << ":" << m.column ()
<< ": error: column with default value specified as C++ "
diff --git a/odb/relational/oracle/source.cxx b/odb/relational/oracle/source.cxx
index fb0984a..1d7d81f 100644
--- a/odb/relational/oracle/source.cxx
+++ b/odb/relational/oracle/source.cxx
@@ -316,187 +316,37 @@ namespace relational
// init image
//
- struct init_image_member: relational::init_image_member, member_base
+ struct init_image_member: relational::init_image_member_impl<sql_type>,
+ member_base
{
init_image_member (base const& x)
- : member_base::base (x), // virtual base
- base (x),
- member_base (x),
- member_database_type_id_ (base::type_override_,
- base::fq_type_override_,
- base::key_prefix_)
- {
- }
-
- virtual bool
- pre (member_info& mi)
- {
- // Ignore containers (they get their own table) and inverse
- // object pointers (they are not present in this binding).
- //
- if (container (mi) || inverse (mi.m, key_prefix_))
- return false;
-
- if (!member_override_.empty ())
- member = member_override_;
- else
- {
- // If we are generating standard init() and this member
- // contains version, ignore it.
- //
- if (version (mi.m))
- return false;
-
- string const& name (mi.m.name ());
- member = "o." + name;
-
- os << "// " << name << endl
- << "//" << endl;
-
- // If the whole class is readonly, then we will never be
- // called with sk == statement_update.
- //
- if (!readonly (*context::top_object))
- {
- semantics::class_* c;
-
- if (id (mi.m) ||
- readonly (mi.m) ||
- ((c = composite (mi.t)) && readonly (*c)))
- os << "if (sk == statement_insert)";
- }
- }
-
- // If this is a wrapped composite value, then we need to
- // "unwrap" it. For simple values this is taken care of
- // by the value_traits specializations.
- //
- if (mi.wrapper != 0 && composite (mi.t))
- {
- // Here we need the wrapper type, not the wrapped type.
- //
- member = "wrapper_traits< " + mi.fq_type (false) + " >::" +
- "get_ref (" + member + ")";
- }
-
- if (composite (mi.t))
- {
- os << "{";
- traits = "composite_value_traits< " + mi.fq_type () + " >";
- }
- else
- {
- // When handling a pointer, mi.t is the id type of the referenced
- // object.
- //
- semantics::type& mt (member_utype (mi.m, key_prefix_));
-
- if (semantics::class_* c = object_pointer (mt))
- {
- type = "obj_traits::id_type";
- db_type_id = member_database_type_id_.database_type_id (mi.m);
-
- // Handle NULL pointers and extract the id.
- //
- os << "{"
- << "typedef object_traits< " << class_fq_name (*c) <<
- " > obj_traits;";
-
- if (weak_pointer (mt))
- {
- os << "typedef pointer_traits< " << mi.fq_type () <<
- " > wptr_traits;"
- << "typedef pointer_traits< wptr_traits::" <<
- "strong_pointer_type > ptr_traits;"
- << endl
- << "wptr_traits::strong_pointer_type sp (" <<
- "wptr_traits::lock (" << member << "));";
-
- member = "sp";
- }
- else
- os << "typedef pointer_traits< " << mi.fq_type () <<
- " > ptr_traits;"
- << endl;
-
- os << "bool is_null (ptr_traits::null_ptr (" << member << "));"
- << "if (!is_null)"
- << "{"
- << "const " << type << "& id (" << endl;
-
- if (lazy_pointer (mt))
- os << "ptr_traits::object_id< ptr_traits::element_type > (" <<
- member << ")";
- else
- os << "obj_traits::id (ptr_traits::get_ref (" << member << "))";
-
- os << ");"
- << endl;
-
- member = "id";
- }
- else
- {
- type = mi.fq_type ();
- db_type_id = member_database_type_id_.database_type_id (mi.m);
-
- os << "{"
- << "bool is_null;";
- }
-
- traits = "oracle::value_traits<\n "
- + type + ",\n "
- + db_type_id + " >";
- }
-
- return true;
- }
-
- virtual void
- post (member_info& mi)
+ : member_base::base (x), // virtual base
+ member_base::base_impl (x), // virtual base
+ base_impl (x),
+ member_base (x)
{
- if (composite (mi.t))
- os << "}";
- else
- {
- // When handling a pointer, mi.t is the id type of the referenced
- // object.
- //
- if (object_pointer (member_utype (mi.m, key_prefix_)))
- {
- os << "}";
-
- if (!null (mi.m, key_prefix_))
- os << "else" << endl
- << "throw null_pointer ();";
- }
-
- os << "i." << mi.var << "indicator = is_null ? -1 : 0;"
- << "}";
- }
}
virtual void
- traverse_composite (member_info& mi)
+ set_null (member_info& mi)
{
- os << traits << "::init (" << endl
- << "i." << mi.var << "value," << endl
- << member << "," << endl
- << "sk);";
+ os << "i." << mi.var << "indicator = -1;";
}
virtual void
traverse_int32 (member_info& mi)
{
os << traits << "::set_image (" << endl
- << "i." << mi.var << "value, is_null, " << member << ");";
+ << "i." << mi.var << "value, is_null, " << member << ");"
+ << "i." << mi.var << "indicator = is_null ? -1 : 0;";
}
virtual void
traverse_int64 (member_info& mi)
{
os << traits << "::set_image (" << endl
- << "i." << mi.var << "value, is_null, " << member << ");";
+ << "i." << mi.var << "value, is_null, " << member << ");"
+ << "i." << mi.var << "indicator = is_null ? -1 : 0;";
}
virtual void
@@ -508,6 +358,7 @@ namespace relational
<< "size," << endl
<< "is_null," << endl
<< member << ");"
+ << "i." << mi.var << "indicator = is_null ? -1 : 0;"
<< "i." << mi.var << "size = static_cast<ub2> (size);";
}
@@ -515,14 +366,16 @@ namespace relational
traverse_float (member_info& mi)
{
os << traits << "::set_image (" << endl
- << "i." << mi.var << "value, is_null, " << member << ");";
+ << "i." << mi.var << "value, is_null, " << member << ");"
+ << "i." << mi.var << "indicator = is_null ? -1 : 0;";
}
virtual void
traverse_double (member_info& mi)
{
os << traits << "::set_image (" << endl
- << "i." << mi.var << "value, is_null, " << member << ");";
+ << "i." << mi.var << "value, is_null, " << member << ");"
+ << "i." << mi.var << "indicator = is_null ? -1 : 0;";
}
virtual void
@@ -535,6 +388,7 @@ namespace relational
<< "size," << endl
<< "is_null," << endl
<< member << ");"
+ << "i." << mi.var << "indicator = is_null ? -1 : 0;"
<< "i." << mi.var << "size = static_cast<ub2> (size);";
}
@@ -542,28 +396,32 @@ namespace relational
traverse_date (member_info& mi)
{
os << traits << "::set_image (" << endl
- << "i." << mi.var << "value, is_null, " << member << ");";
+ << "i." << mi.var << "value, is_null, " << member << ");"
+ << "i." << mi.var << "indicator = is_null ? -1 : 0;";
}
virtual void
traverse_timestamp (member_info& mi)
{
os << traits << "::set_image (" << endl
- << "i." << mi.var << "value, is_null, " << member << ");";
+ << "i." << mi.var << "value, is_null, " << member << ");"
+ << "i." << mi.var << "indicator = is_null ? -1 : 0;";
}
virtual void
traverse_interval_ym (member_info& mi)
{
os << traits << "::set_image (" << endl
- << "i." << mi.var << "value, is_null, " << member << ");";
+ << "i." << mi.var << "value, is_null, " << member << ");"
+ << "i." << mi.var << "indicator = is_null ? -1 : 0;";
}
virtual void
traverse_interval_ds (member_info& mi)
{
os << traits << "::set_image (" << endl
- << "i." << mi.var << "value, is_null, " << member << ");";
+ << "i." << mi.var << "value, is_null, " << member << ");"
+ << "i." << mi.var << "indicator = is_null ? -1 : 0;";
}
virtual void
@@ -576,6 +434,7 @@ namespace relational
<< "size," << endl
<< "is_null," << endl
<< member << ");"
+ << "i." << mi.var << "indicator = is_null ? -1 : 0;"
<< "i." << mi.var << "size = static_cast<ub2> (size);";
}
@@ -587,16 +446,9 @@ namespace relational
<< "i." << mi.var << "callback.callback.param," << endl
<< "i." << mi.var << "callback.context.param," << endl
<< "is_null," << endl
- << member << ");";
+ << member << ");"
+ << "i." << mi.var << "indicator = is_null ? -1 : 0;";
}
-
- private:
- string type;
- string db_type_id;
- string member;
- string traits;
-
- member_database_type_id member_database_type_id_;
};
entry<init_image_member> init_image_member_;
@@ -604,147 +456,21 @@ namespace relational
// init value
//
- struct init_value_member: relational::init_value_member, member_base
+ struct init_value_member: relational::init_value_member_impl<sql_type>,
+ member_base
{
init_value_member (base const& x)
- : member_base::base (x), // virtual base
- base (x),
- member_base (x),
- member_database_type_id_ (base::type_override_,
- base::fq_type_override_,
- base::key_prefix_)
- {
- }
-
- virtual bool
- pre (member_info& mi)
- {
- if (container (mi))
- return false;
-
- if (!member_override_.empty ())
- member = member_override_;
- else
- {
- string const& name (mi.m.name ());
- member = "o." + name;
-
- if (mi.cq)
- member = "const_cast< " + mi.fq_type (false) + "& > (" +
- member + ")";
-
- os << "// " << name << endl
- << "//" << endl;
- }
-
- // If this is a wrapped composite value, then we need to
- // "unwrap" it. For simple values this is taken care of
- // by the value_traits specializations.
- //
- if (mi.wrapper != 0 && composite (mi.t))
- {
- // Here we need the wrapper type, not the wrapped type.
- //
- member = "wrapper_traits< " + mi.fq_type (false) + " >::" +
- "set_ref (\n" + member + ")";
- }
-
- if (composite (mi.t))
- traits = "composite_value_traits< " + mi.fq_type () + " >";
- else
- {
- // When handling a pointer, mi.t is the id type of the referenced
- // object.
- //
- semantics::type& mt (member_utype (mi.m, key_prefix_));
-
- if (semantics::class_* c = object_pointer (mt))
- {
- type = "obj_traits::id_type";
- db_type_id = member_database_type_id_.database_type_id (mi.m);
-
- // Handle NULL pointers and extract the id.
- //
- os << "{"
- << "typedef object_traits< " << class_fq_name (*c) <<
- " > obj_traits;"
- << "typedef pointer_traits< " << mi.fq_type () <<
- " > ptr_traits;"
- << endl
- << "if (i." << mi.var << "indicator == -1)" << endl;
-
- if (null (mi.m, key_prefix_))
- os << member << " = ptr_traits::pointer_type ();";
- else
- os << "throw null_pointer ();";
-
- os << "else"
- << "{"
- << type << " id;";
-
- member = "id";
- }
- else
- {
- type = mi.fq_type ();
- db_type_id = member_database_type_id_.database_type_id (mi.m);
- }
-
- traits = "oracle::value_traits<\n "
- + type + ",\n "
- + db_type_id + " >";
- }
-
- return true;
- }
-
- virtual void
- post (member_info& mi)
+ : member_base::base (x), // virtual base
+ member_base::base_impl (x), // virtual base
+ base_impl (x),
+ member_base (x)
{
- if (composite (mi.t))
- return;
-
- // When handling a pointer, mi.t is the id type of the referenced
- // object.
- //
- semantics::type& mt (member_utype (mi.m, key_prefix_));
-
- if (object_pointer (mt))
- {
- if (!member_override_.empty ())
- member = member_override_;
- else
- {
- member = "o." + mi.m.name ();
-
- if (mi.cq)
- member = "const_cast< " + mi.fq_type (false) + "& > (" +
- member + ")";
- }
-
- if (lazy_pointer (mt))
- os << member << " = ptr_traits::pointer_type (db, id);";
- else
- os << "// If a compiler error points to the line below, then" << endl
- << "// it most likely means that a pointer used in a member" << endl
- << "// cannot be initialized from an object pointer." << endl
- << "//" << endl
- << member << " = ptr_traits::pointer_type (" << endl
- << "db.load< obj_traits::object_type > (id));";
-
- os << "}"
- << "}";
- }
}
virtual void
- traverse_composite (member_info& mi)
+ get_null (member_info& mi)
{
- os << traits << "::init (" << endl
- << member << "," << endl
- << "i." << mi.var << "value," << endl
- << "db);"
- << endl;
+ os << "i." << mi.var << "indicator == -1";
}
virtual void
@@ -870,14 +596,6 @@ namespace relational
<< "i." << mi.var << "indicator == -1);"
<< endl;
}
-
- private:
- string type;
- string db_type_id;
- string traits;
- string member;
-
- member_database_type_id member_database_type_id_;
};
entry<init_value_member> init_value_member_;