summaryrefslogtreecommitdiff
path: root/odb/relational
diff options
context:
space:
mode:
Diffstat (limited to 'odb/relational')
-rw-r--r--odb/relational/common.cxx24
-rw-r--r--odb/relational/common.hxx2
-rw-r--r--odb/relational/header.cxx435
-rw-r--r--odb/relational/header.hxx256
-rw-r--r--odb/relational/inline.hxx186
-rw-r--r--odb/relational/mssql/common.cxx3
-rw-r--r--odb/relational/mysql/common.cxx3
-rw-r--r--odb/relational/mysql/source.cxx2
-rw-r--r--odb/relational/oracle/common.cxx3
-rw-r--r--odb/relational/pgsql/common.cxx3
-rw-r--r--odb/relational/pgsql/source.cxx49
-rw-r--r--odb/relational/processor.cxx1102
-rw-r--r--odb/relational/schema.hxx6
-rw-r--r--odb/relational/source.cxx474
-rw-r--r--odb/relational/source.hxx114
-rw-r--r--odb/relational/sqlite/common.cxx3
-rw-r--r--odb/relational/sqlite/source.cxx2
-rw-r--r--odb/relational/validator.cxx296
18 files changed, 1123 insertions, 1840 deletions
diff --git a/odb/relational/common.cxx b/odb/relational/common.cxx
index 3916184..e9b3485 100644
--- a/odb/relational/common.cxx
+++ b/odb/relational/common.cxx
@@ -88,8 +88,8 @@ namespace relational
{
string const& fq_name (class_fq_name (c));
string guard (
- make_guard (
- "ODB_ALIAS_TRAITS_" + alias + "_FOR_" + flat_name (fq_name)));
+ make_guard ("ODB_" + string (db.string ()) + "_ALIAS_TRAITS_" +
+ alias + "_FOR_" + flat_name (fq_name)));
if (specs_.find (guard) != specs_.end ())
return;
@@ -107,19 +107,20 @@ namespace relational
<< "#define " << guard << endl;
os << "template <bool d>" << endl
- << "struct alias_traits< " << fq_name << ", " << tag << ", d >"
+ << "struct alias_traits< " << fq_name << ", id_" << db << ", " <<
+ tag << ", d >"
<< "{"
<< "static const char table_name[];";
if (poly_derived)
os << "typedef alias_traits< " << class_fq_name (*poly_base) << ", " <<
- tag << " > base_traits;";
+ "id_" << db << ", " << tag << " > base_traits;";
os << "};";
os << "template <bool d>" << endl
- << "const char alias_traits< " << fq_name << ", " << tag <<
- ", d >::" << endl
+ << "const char alias_traits< " << fq_name << ", id_" << db << ", " <<
+ tag << ", d >::" << endl
<< "table_name[] = ";
if (poly_root != 0)
@@ -146,7 +147,8 @@ namespace relational
query_columns_base (semantics::class_& c) //@@ context::{cur,top}_object
: decl_ (false)
{
- scope_ = "query_columns_base< " + class_fq_name (c) + " >";
+ scope_ = "query_columns_base< " + class_fq_name (c) + ", id_" +
+ db.string () + " >";
}
void query_columns_base::
@@ -244,7 +246,8 @@ namespace relational
string const& fq_name (class_fq_name (c));
os << "typedef" << endl
- << "odb::alias_traits< " << fq_name << ", " << tag << " >" << endl
+ << "odb::alias_traits< " << fq_name << ", id_" << db << ", " <<
+ tag << " >" << endl
<< name << "_alias_;"
<< endl;
@@ -254,6 +257,7 @@ namespace relational
<< "odb::query_pointer<" << endl
<< " odb::pointer_query_columns<" << endl
<< " " << fq_name << "," << endl
+ << " id_" << db << "," << endl
<< " " << name << "_alias_ > >" << endl
<< name << "_type_ ;"
<< endl
@@ -284,7 +288,7 @@ namespace relational
: ptr_ (ptr), decl_ (false), in_ptr_ (false)
{
scope_ = ptr ? "pointer_query_columns" : "query_columns";
- scope_ += "< " + class_fq_name (c) + ", A >";
+ scope_ += "< " + class_fq_name (c) + ", id_" + db.string () + ", A >";
}
void query_columns::
@@ -474,6 +478,7 @@ namespace relational
<< "odb::query_pointer<" << endl
<< " odb::pointer_query_columns<" << endl
<< " " << class_fq_name (c) << "," << endl
+ << " id_" << db << "," << endl
<< " " << name << "_alias_ > >" << endl
<< name << "_pointer_type_;"
<< endl;
@@ -519,6 +524,7 @@ namespace relational
<< "odb::query_pointer<" << endl
<< " odb::pointer_query_columns<" << endl
<< " " << class_fq_name (c) << "," << endl
+ << " id_" << db << "," << endl
<< " " << name << "_alias_ > >" << endl
<< name << "_pointer_type_;"
<< endl;
diff --git a/odb/relational/common.hxx b/odb/relational/common.hxx
index 26e8197..b951d15 100644
--- a/odb/relational/common.hxx
+++ b/odb/relational/common.hxx
@@ -336,7 +336,7 @@ namespace relational
static B*
create (B const& prototype)
{
- database db (context::current ().options.database ());
+ database db (context::current ().options.database ()[0]);
if (map_ != 0)
{
diff --git a/odb/relational/header.cxx b/odb/relational/header.cxx
index 538962b..1295106 100644
--- a/odb/relational/header.cxx
+++ b/odb/relational/header.cxx
@@ -13,15 +13,14 @@ traverse_object (type& c)
using semantics::data_member;
data_member* id (id_member (c));
- bool auto_id (id ? id->count ("auto") : false);
- bool base_id (id ? &id->scope () != &c : false); // Comes from base.
+ bool auto_id (id && auto_ (*id));
+ bool base_id (id && &id->scope () != &c); // Comes from base.
data_member* optimistic (context::optimistic (c));
type* poly_root (polymorphic (c));
bool poly (poly_root != 0);
bool poly_derived (poly && poly_root != &c);
- type* poly_base (poly_derived ? &polymorphic_base (c) : 0);
data_member* discriminator (poly ? context::discriminator (*poly_root) : 0);
bool abst (abstract (c));
@@ -33,14 +32,6 @@ traverse_object (type& c)
os << "// " << class_name (c) << endl
<< "//" << endl;
- // class_traits
- //
- os << "template <>" << endl
- << "struct class_traits< " << type << " >"
- << "{"
- << "static const class_kind kind = class_object;"
- << "};";
-
// pointer_query_columns & query_columns
//
if (options.generate_query ())
@@ -58,59 +49,38 @@ traverse_object (type& c)
pointer_query_columns_type_->traverse (c);
}
- // object_traits
+ // object_traits_impl
//
os << "template <>" << endl
- << "class access::object_traits< " << type << " >"
+ << "class access::object_traits_impl< " << type << ", id_" << db <<
+ " >:" << endl
+ << " public access::object_traits< " << type << " >"
<< "{"
<< "public:" << endl;
object_public_extra_pre (c);
- // object_type & pointer_type
- //
- os << "typedef " << type << " object_type;"
- << "typedef " << c.get<string> ("object-pointer") << " pointer_type;"
- << "typedef odb::pointer_traits<pointer_type> pointer_traits;"
- << endl;
-
- // polymorphic, root_type, base_type, etc.
+ // Polymorphic root_traits, base_traits, and discriminator_image_type.
//
- os << "static const bool polymorphic = " << (poly ? "true" : "false") << ";";
-
if (poly)
{
- os << "typedef " << class_fq_name (*poly_root) << " root_type;"
- << "typedef object_traits<root_type> root_traits;";
+ if (!abst)
+ os << "typedef polymorphic_entry<object_type, id_" << db <<
+ "> entry_type;";
+
+ os << "typedef object_traits_impl<root_type, id_" << db << "> " <<
+ "root_traits;";
if (poly_derived)
{
- os << "typedef " << class_fq_name (*poly_base) << " base_type;"
- << "typedef object_traits<base_type> base_traits;"
- << "typedef root_traits::discriminator_type discriminator_type;"
- << "typedef odb::polymorphic_concrete_info<root_type> info_type;";
-
- if (abst)
- os << "typedef odb::polymorphic_abstract_info<root_type> " <<
- "abstract_info_type;";
- else
- os << "typedef odb::polymorphic_entry<object_type> entry_type;";
-
- // Calculate our hierarchy depth (number of classes).
- //
- size_t depth (polymorphic_depth (c));
-
- os << "static const std::size_t depth = " << depth << "UL;";
+ os << "typedef object_traits_impl<base_type, id_" << db << "> " <<
+ "base_traits;"
+ << endl;
}
else
{
- semantics::names* hint;
- semantics::type& t (utype (*discriminator, hint));
-
- os << "typedef " << t.fq_name (hint) << " discriminator_type;"
- << endl;
-
- os << "struct discriminator_image_type"
+ os << endl
+ << "struct discriminator_image_type"
<< "{";
discriminator_image_member_->traverse (*discriminator);
@@ -120,23 +90,10 @@ traverse_object (type& c)
os << "std::size_t version;"
<< "};";
-
- os << "typedef odb::polymorphic_map<object_type> map_type;"
- << "typedef odb::polymorphic_concrete_info<object_type> info_type;";
-
- if (abst)
- os << "typedef odb::polymorphic_abstract_info<object_type> " <<
- "abstract_info_type;";
- else
- os << "typedef odb::polymorphic_entry<object_type> entry_type;";
-
- os << "static const std::size_t depth = 1UL;";
}
}
- os << endl;
-
- // id_type & id_image_type
+ // id_image_type
//
if (id != 0)
{
@@ -144,44 +101,14 @@ traverse_object (type& c)
{
semantics::class_& b (
dynamic_cast<semantics::class_&> (id->scope ()));
- string const& type (class_fq_name (b));
+ string const& type ();
- os << "typedef object_traits< " << type << " >::id_type id_type;";
-
- if (optimistic != 0)
- os << "typedef object_traits< " << type << " >::version_type " <<
- "version_type;";
-
- if (poly_derived)
- os << "typedef object_traits< " << type << " >:: id_image_type " <<
- "id_image_type;"
- << "static const bool auto_id = false;"
- << endl;
- else
- os << "typedef object_traits< " << type << " >::id_image_type " <<
- "id_image_type;"
- << "static const bool auto_id = object_traits< " << type <<
- " >::auto_id;"
- << endl;
+ os << "typedef object_traits_impl< " << class_fq_name (b) << ", " <<
+ "id_" << db << " >::id_image_type id_image_type;"
+ << endl;
}
else
{
- {
- semantics::names* hint;
- semantics::type& t (utype (*id, hint));
- os << "typedef " << t.fq_name (hint) << " id_type;";
- }
-
- if (optimistic != 0)
- {
- semantics::names* hint;
- semantics::type& t (utype (*optimistic, hint));
- os << "typedef " << t.fq_name (hint) << " version_type;";
- }
-
- os << "static const bool auto_id = " << (auto_id ? "true;" : "false;")
- << endl;
-
os << "struct id_image_type"
<< "{";
@@ -194,19 +121,6 @@ traverse_object (type& c)
<< "};";
}
}
- else if (!reuse_abst)
- {
- // Object without id.
- //
- os << "typedef void id_type;"
- << "static const bool auto_id = false;"
- << endl;
- }
-
- // abstract
- //
- os << "static const bool abstract = " << (abst ? "true" : "false") << ";"
- << endl;
// Polymorphic map.
//
@@ -236,19 +150,9 @@ traverse_object (type& c)
// Functions (abstract and concrete).
//
- // id ()
- //
if (id != 0 || !reuse_abst)
- {
- // We want to generate a dummy void id() accessor even if this
- // object has no id to help us in the runtime. This way we can
- // write generic code that will work for both void and non-void
- // ids.
- //
- os << "static id_type" << endl
- << "id (const object_type&);"
+ os << "using object_traits<object_type>::id;"
<< endl;
- }
if (!poly_derived && id != 0)
{
@@ -370,45 +274,6 @@ traverse_object (type& c)
return;
}
- // Cache traits typedefs.
- //
- if (id == 0)
- {
- os << "typedef" << endl
- << "odb::no_id_pointer_cache_traits<pointer_type>" << endl
- << "pointer_cache_traits;"
- << "typedef" << endl
- << "odb::no_id_reference_cache_traits<object_type>" << endl
- << "reference_cache_traits;"
- << endl;
- }
- else
- {
- char const* p (session (c) ? "" : "no_op_");
-
- if (poly_derived)
- {
- os << "typedef" << endl
- << "odb::" << p << "pointer_cache_traits<" <<
- "root_traits::pointer_type>" << endl
- << "pointer_cache_traits;"
- << "typedef" << endl
- << "odb::" << p << "reference_cache_traits<root_type>" << endl
- << "reference_cache_traits;"
- << endl;
- }
- else
- {
- os << "typedef" << endl
- << "odb::" << p << "pointer_cache_traits<pointer_type>" << endl
- << "pointer_cache_traits;"
- << "typedef" << endl
- << "odb::" << p << "reference_cache_traits<object_type>" << endl
- << "reference_cache_traits;"
- << endl;
- }
- }
-
// Statements typedefs.
//
if (poly)
@@ -418,6 +283,7 @@ traverse_object (type& c)
<< db << "::polymorphic_derived_object_statements" <<
"<object_type>" << endl
<< "statements_type;"
+ << endl
<< "typedef" << endl
<< db << "::polymorphic_root_object_statements<root_type>" << endl
<< "root_statements_type;"
@@ -426,6 +292,7 @@ traverse_object (type& c)
os << "typedef" << endl
<< db << "::polymorphic_root_object_statements<object_type>" << endl
<< "statements_type;"
+ << endl
<< "typedef statements_type root_statements_type;"
<< "typedef " << db << "::object_statements<object_type> " <<
"base_statements_type;"
@@ -451,7 +318,7 @@ traverse_object (type& c)
{
// query_base_type
//
- os << "typedef " << db << "::query query_base_type;"
+ os << "typedef " << db << "::query_base query_base_type;"
<< endl;
}
@@ -526,16 +393,6 @@ traverse_object (type& c)
// Functions (concrete).
//
- // callback ()
- //
- os << "static void" << endl
- << "callback (database&, object_type&, callback_event);"
- << endl;
-
- os << "static void" << endl
- << "callback (database&, const object_type&, callback_event);"
- << endl;
-
// persist ()
//
os << "static void" << endl
@@ -622,13 +479,27 @@ traverse_object (type& c)
//
if (options.generate_query ())
{
- os << "static result<object_type>" << endl
- << "query (database&, const query_base_type&);"
- << endl;
+ if (!options.omit_unprepared ())
+ {
+ os << "static result<object_type>" << endl
+ << "query (database&, const query_base_type&);"
+ << endl;
+ }
os << "static unsigned long long" << endl
<< "erase_query (database&, const query_base_type&);"
<< endl;
+
+ if (options.generate_prepared ())
+ {
+ os << "static odb::details::shared_ptr<prepared_query_impl>" << endl
+ << "prepare_query (connection&, const char*, const query_base_type&);"
+ << endl;
+
+ os << "static odb::details::shared_ptr<result_impl>" << endl
+ << "execute_query (prepared_query_impl&);"
+ << endl;
+ }
}
// create_schema ()
@@ -736,6 +607,224 @@ traverse_object (type& c)
}
os << "};";
+
+
+ // object_traits_impl< , id_default>
+ //
+ // Note that it is not generated for reuse-abstract classes.
+ //
+ if (options.default_database_specified () &&
+ options.default_database () == db)
+ {
+ os << "template <>" << endl
+ << "class access::object_traits_impl< " << type << ", " <<
+ "id_default >:" << endl
+ << " public access::object_traits_impl< " << type << ", " <<
+ "id_" << db << " >"
+ << "{"
+ << "};";
+ }
+}
+
+void relational::header::class1::
+traverse_view (type& c)
+{
+ string const& type (class_fq_name (c));
+
+ os << "// " << class_name (c) << endl
+ << "//" << endl;
+
+ // view_traits_impl
+ //
+ os << "template <>" << endl
+ << "class access::view_traits_impl< " << type << ", id_" <<
+ db << " >:" << endl
+ << " public access::view_traits< " << type << " >"
+ << "{"
+ << "public:" << endl;
+
+ view_public_extra_pre (c);
+
+ // image_type
+ //
+ image_type_->traverse (c);
+
+ os << "typedef " << db << "::view_statements<view_type> statements_type;"
+ << endl;
+
+ //
+ // Query.
+ //
+
+ // query_base_type and query_columns (definition generated by class2).
+ //
+ os << "typedef " << db << "::query_base query_base_type;"
+ << "struct query_columns";
+
+ if (c.get<size_t> ("object-count") == 0)
+ os << "{"
+ << "};";
+ else
+ os << ";"
+ << endl;
+
+ //
+ // Functions.
+ //
+
+ // grow ()
+ //
+ if (generate_grow)
+ {
+ os << "static bool" << endl
+ << "grow (image_type&, " << truncated_vector << ");"
+ << endl;
+ }
+
+ // bind (image_type)
+ //
+ os << "static void" << endl
+ << "bind (" << bind_vector << ", image_type&);"
+ << endl;
+
+ // init (view, image)
+ //
+ os << "static void" << endl
+ << "init (view_type&, const image_type&, database*);"
+ << endl;
+
+ // column_count
+ //
+ os << "static const std::size_t column_count = " <<
+ column_count (c).total << "UL;"
+ << endl;
+
+ // Statements.
+ //
+ view_query& vq (c.get<view_query> ("query"));
+
+ if (vq.kind != view_query::runtime)
+ {
+ os << "static query_base_type" << endl
+ << "query_statement (const query_base_type&);"
+ << endl;
+ }
+
+ //
+ // Functions.
+ //
+
+ // query ()
+ //
+ if (!options.omit_unprepared ())
+ os << "static result<view_type>" << endl
+ << "query (database&, const query_base_type&);"
+ << endl;
+
+ if (options.generate_prepared ())
+ {
+ os << "static odb::details::shared_ptr<prepared_query_impl>" << endl
+ << "prepare_query (connection&, const char*, const query_base_type&);"
+ << endl;
+
+ os << "static odb::details::shared_ptr<result_impl>" << endl
+ << "execute_query (prepared_query_impl&);"
+ << endl;
+ }
+
+ view_public_extra_post (c);
+
+ os << "};";
+
+ // view_traits_impl< , id_default>
+ //
+ if (options.default_database_specified () &&
+ options.default_database () == db)
+ {
+ os << "template <>" << endl
+ << "class access::view_traits_impl< " << type << ", " <<
+ "id_default >:" << endl
+ << " public access::view_traits_impl< " << type << ", " <<
+ "id_" << db << " >"
+ << "{"
+ << "};";
+ }
+}
+
+void relational::header::class1::
+traverse_composite (type& c)
+{
+ string const& type (class_fq_name (c));
+
+ os << "// " << class_name (c) << endl
+ << "//" << endl;
+
+ os << "template <>" << endl
+ << "class access::composite_value_traits< " << type << ", " <<
+ "id_" << db << " >"
+ << "{"
+ << "public:" << endl;
+
+ // value_type
+ //
+ os << "typedef " << type << " value_type;"
+ << endl;
+
+ // image_type
+ //
+ image_type_->traverse (c);
+
+ // Containers.
+ //
+ {
+ instance<container_traits> t (c);
+ t->traverse (c);
+ }
+
+ // grow ()
+ //
+ if (generate_grow)
+ {
+ os << "static bool" << endl
+ << "grow (image_type&, " << truncated_vector << ");"
+ << endl;
+ }
+
+ // bind (image_type)
+ //
+ os << "static void" << endl
+ << "bind (" << bind_vector << ", image_type&, " <<
+ db << "::statement_kind);"
+ << endl;
+
+ // init (image, value)
+ //
+ os << "static " << (generate_grow ? "bool" : "void") << endl
+ << "init (image_type&, const value_type&, " << db << "::statement_kind);"
+ << endl;
+
+ // init (value, image)
+ //
+ os << "static void" << endl
+ << "init (value_type&, const image_type&, database*);"
+ << endl;
+
+ if (!has_a (c, test_container))
+ {
+ // get_null (image)
+ //
+ os << "static bool" << endl
+ << "get_null (const image_type&);"
+ << endl;
+
+ // set_null (image)
+ //
+ os << "static void" << endl
+ << "set_null (image_type&, " << db << "::statement_kind);"
+ << endl;
+ }
+
+ os << "};";
}
void relational::header::
diff --git a/odb/relational/header.hxx b/odb/relational/header.hxx
index 25f9480..c0e1e89 100644
--- a/odb/relational/header.hxx
+++ b/odb/relational/header.hxx
@@ -64,9 +64,11 @@ namespace relational
string const& type (class_fq_name (c));
if (obj)
- os << "object_traits< " << type << " >::image_type";
+ os << "object_traits_impl< " << type << ", id_" << db <<
+ " >::image_type";
else
- os << "composite_value_traits< " << type << " >::image_type";
+ os << "composite_value_traits< " << type << ", id_" << db <<
+ " >::image_type";
}
private:
@@ -117,7 +119,7 @@ namespace relational
os << "{";
if (poly_derived)
- os << "object_traits<base_type>::image_type* base;"
+ os << "base_traits::image_type* base;"
<< endl;
names (c);
@@ -173,7 +175,7 @@ namespace relational
}
os << (ptr_ ? "pointer_query_columns" : "query_columns") << "< " <<
- class_fq_name (c) << ", ";
+ class_fq_name (c) << ", id_" << db << ", ";
// If our base is polymorphic, then it has its own table/alias.
//
@@ -213,7 +215,7 @@ namespace relational
<< "//" << endl
<< "typedef " <<
(ptr_ ? "pointer_query_columns" : "query_columns") << "< " <<
- class_fq_name (c) << ", ";
+ class_fq_name (c) << ", id_" << db << ", ";
if (polymorphic (c))
os << "typename A::base_traits";
@@ -246,7 +248,8 @@ namespace relational
if (ptr_)
{
os << "template <typename A>" << endl
- << "struct pointer_query_columns< " << type << ", A >";
+ << "struct pointer_query_columns< " << type << ", id_" << db <<
+ ", A >";
// If we don't have pointers (in the whole hierarchy), then
// pointer_query_columns and query_columns are the same.
@@ -254,7 +257,7 @@ namespace relational
if (!has_a (c, test_pointer | include_base))
{
os << ":" << endl
- << " query_columns< " << type << ", A >"
+ << " query_columns< " << type << ", id_" << db << ", A >"
<< "{"
<< "};";
}
@@ -298,7 +301,8 @@ namespace relational
// table alias (A) template argument.
//
os << "template <>" << endl
- << "struct query_columns_base< " << type << " >"
+ << "struct query_columns_base< " << type << ", id_" <<
+ db << " >"
<< "{";
instance<query_columns_base> t;
@@ -308,11 +312,11 @@ namespace relational
}
os << "template <typename A>" << endl
- << "struct query_columns< " << type << ", A >";
+ << "struct query_columns< " << type << ", id_" << db << ", A >";
if (has_ptr)
os << ":" << endl
- << " query_columns_base< " << type << " >";
+ << " query_columns_base< " << type << ", id_" << db << " >";
{
instance<query_columns_bases> b (ptr_, !has_ptr);
@@ -540,10 +544,11 @@ namespace relational
string const& type (class_fq_name (b));
if (object (b))
- os << ": access::object_traits< " << type << " >::" << name;
+ os << ": access::object_traits_impl< " << type << ", id_" <<
+ db << " >::" << name;
else
- os << ": access::composite_value_traits< " << type << " >::" <<
- public_name (m) << "_traits"; // No prefix_.
+ os << ": access::composite_value_traits< " << type << ", id_" <<
+ db << " >::" << public_name (m) << "_traits"; // No prefix_.
}
os << "{";
@@ -992,7 +997,7 @@ namespace relational
}
virtual void
- traverse_object (type& c);
+ traverse_object (type&);
virtual void
view_public_extra_pre (type&)
@@ -1005,196 +1010,10 @@ namespace relational
}
virtual void
- traverse_view (type& c)
- {
- string const& type (class_fq_name (c));
-
- os << "// " << class_name (c) << endl
- << "//" << endl;
-
- os << "template <>" << endl
- << "struct class_traits< " << type << " >"
- << "{"
- << "static const class_kind kind = class_view;"
- << "};";
-
- os << "template <>" << endl
- << "class access::view_traits< " << type << " >"
- << "{"
- << "public:" << endl;
-
- view_public_extra_pre (c);
-
- // view_type & pointer_type
- //
- os << "typedef " << type << " view_type;"
- << "typedef " << c.get<string> ("object-pointer") << " pointer_type;"
- << endl;
-
- // image_type
- //
- image_type_->traverse (c);
-
- //
- // Query.
- //
-
- // query_base_type and query_columns (definition generated by class2).
- //
- os << "typedef " << db << "::query query_base_type;"
- << "struct query_columns";
-
- if (c.get<size_t> ("object-count") == 0)
- os << "{"
- << "};";
- else
- os << ";"
- << endl;
-
- //
- // Functions.
- //
-
- // grow ()
- //
- if (generate_grow)
- {
- os << "static bool" << endl
- << "grow (image_type&, " << truncated_vector << ");"
- << endl;
- }
-
- // bind (image_type)
- //
- os << "static void" << endl
- << "bind (" << bind_vector << ", image_type&);"
- << endl;
-
- // init (view, image)
- //
- os << "static void" << endl
- << "init (view_type&, const image_type&, database*);"
- << endl;
-
- // column_count
- //
- os << "static const std::size_t column_count = " <<
- column_count (c).total << "UL;"
- << endl;
-
- // Statements.
- //
- view_query& vq (c.get<view_query> ("query"));
-
- if (vq.kind != view_query::runtime)
- {
- os << "static query_base_type" << endl
- << "query_statement (const query_base_type&);"
- << endl;
- }
-
- //
- // Functions.
- //
-
- // callback ()
- //
- os << "static void" << endl
- << "callback (database&, view_type&, callback_event);"
- << endl;
-
- // query ()
- //
- os << "static result<view_type>" << endl
- << "query (database&, const query_base_type&);"
- << endl;
-
- view_public_extra_post (c);
-
- os << "};";
- }
+ traverse_view (type&);
virtual void
- traverse_composite (type& c)
- {
- string const& type (class_fq_name (c));
-
- os << "// " << class_name (c) << endl
- << "//" << endl;
-
- os << "template <>" << endl
- << "struct class_traits< " << type << " >"
- << "{"
- << "static const class_kind kind = class_composite;"
- << "};";
-
- os << "template <>" << endl
- << "class access::composite_value_traits< " << type << " >"
- << "{"
- << "public:" << endl;
-
- // value_type
- //
- os << "typedef " << type << " value_type;"
- << endl;
-
- // image_type
- //
- image_type_->traverse (c);
-
- // Containers.
- //
- {
- instance<container_traits> t (c);
- t->traverse (c);
- }
-
- // grow ()
- //
- if (generate_grow)
- {
- os << "static bool" << endl
- << "grow (image_type&, " << truncated_vector << ");"
- << endl;
- }
-
- // bind (image_type)
- //
- os << "static void" << endl
- << "bind (" << bind_vector << ", image_type&, " <<
- db << "::statement_kind);"
- << endl;
-
- // init (image, value)
- //
- os << "static " << (generate_grow ? "bool" : "void") << endl
- << "init (image_type&, const value_type&, " <<
- db << "::statement_kind);"
- << endl;
-
- // init (value, image)
- //
- os << "static void" << endl
- << "init (value_type&, const image_type&, database*);"
- << endl;
-
- if (!has_a (c, test_container))
- {
- // get_null (image)
- //
- os << "static bool" << endl
- << "get_null (const image_type&);"
- << endl;
-
- // set_null (image)
- //
- os << "static void" << endl
- << "set_null (image_type&, " << db << "::statement_kind);"
- << endl;
- }
-
- os << "};";
- }
+ traverse_composite (type&);
private:
instance<image_type> image_type_;
@@ -1306,7 +1125,8 @@ namespace relational
}
}
- os << "struct access::view_traits< " << type << " >::query_columns";
+ os << "struct access::view_traits_impl< " << type << ", id_" <<
+ db << " >::query_columns";
if (obj_count > 1)
{
@@ -1329,19 +1149,20 @@ namespace relational
<< "//" << endl
<< "typedef" << endl
<< "odb::pointer_query_columns<" << endl
- << " " << otype << "," << endl;
+ << " " << otype << "," << endl
+ << " id_" << db << "," << endl;
if (alias && (polymorphic (o) ||
table.qualified () ||
i->alias != table.uname ()))
{
string tag (escape (i->alias + "_alias_tag"));
- os << " odb::alias_traits< " << otype << ", " <<
- tag << " > >" << endl;
+ os << " odb::alias_traits< " << otype << ", id_" << db <<
+ ", " << tag << " > >" << endl;
}
else
- os << " odb::access::object_traits< " << otype <<
- " > >" << endl;
+ os << " odb::access::object_traits_impl< " << otype <<
+ ", id_" << db << " > >" << endl;
os << oname << ";"
<< endl;
@@ -1370,18 +1191,20 @@ namespace relational
os << ":" << endl
<< " odb::pointer_query_columns<" << endl
- << " " << otype << "," << endl;
+ << " " << otype << "," << endl
+ << " id_" << db << "," << endl;
if (alias && (polymorphic (o) ||
table.qualified () ||
vo->alias != table.uname ()))
{
string tag (escape (vo->alias + "_alias_tag"));
- os << " odb::alias_traits< " << otype << ", " <<
- tag << " > >";
+ os << " odb::alias_traits< " << otype << ", id_" <<
+ db << ", " << tag << " > >";
}
else
- os << " odb::access::object_traits< " << otype << " > >";
+ os << " odb::access::object_traits_impl< " << otype <<
+ ", id_" << db << " > >";
os << "{"
<< "};";
@@ -1410,9 +1233,12 @@ namespace relational
virtual void
generate ()
{
- os << "#include <odb/details/buffer.hxx>" << endl
- << "#include <odb/details/unused.hxx>" << endl
- << endl;
+ os << "#include <odb/details/buffer.hxx>" << endl;
+
+ if (options.generate_query ())
+ os << "#include <odb/details/shared-ptr.hxx>" << endl;
+
+ os << endl;
os << "#include <odb/" << db << "/version.hxx>" << endl
<< "#include <odb/" << db << "/forward.hxx>" << endl
diff --git a/odb/relational/inline.hxx b/odb/relational/inline.hxx
index 76c29f1..466e348 100644
--- a/odb/relational/inline.hxx
+++ b/odb/relational/inline.hxx
@@ -14,68 +14,6 @@ namespace relational
namespace inline_
{
//
- //
- struct callback_calls: traversal::class_, virtual context
- {
- typedef callback_calls base;
-
- callback_calls ()
- {
- *this >> inherits_ >> *this;
- }
-
- callback_calls (callback_calls const&)
- : root_context (), //@@ -Wextra
- context ()
- {
- *this >> inherits_ >> *this;
- }
-
- virtual void
- traverse (type& c, bool constant)
- {
- const_ = constant;
- traverse (c);
- }
-
- virtual void
- traverse (type& c)
- {
- bool obj (object (c));
-
- // Ignore transient bases.
- //
- if (!(obj || view (c)))
- return;
-
- if (c.count ("callback"))
- {
- string name (c.get<string> ("callback"));
-
- // In case of the const instance, we only generate the call if
- // there is a const callback.
- //
- string const& type (class_fq_name (c));
-
- if (const_)
- {
- if (c.count ("callback-const"))
- os << "static_cast< const " << type << "& > (x)." <<
- name << " (e, db);";
- }
- else
- os << "static_cast< " << type << "& > (x)." << name << " (e, db);";
- }
- else if (obj)
- inherits (c);
- }
-
- protected:
- bool const_;
- traversal::inherits inherits_;
- };
-
- //
// get/set null (composite value only)
//
@@ -121,7 +59,8 @@ namespace relational
virtual void
traverse_composite (member_info& mi)
{
- string traits ("composite_value_traits< " + mi.fq_type () + " >");
+ string traits ("composite_value_traits< " + mi.fq_type () + ", id_" +
+ db.string () + " >");
if (get_)
os << "r = r && " << traits << "::get_null (" <<
@@ -145,7 +84,8 @@ namespace relational
if (!composite (c))
return;
- string traits ("composite_value_traits< " + class_fq_name (c) + " >");
+ string traits ("composite_value_traits< " + class_fq_name (c) +
+ ", id_" + db.string () + " >");
// If the derived value type is readonly, then set will never be
// called with sk == statement_update.
@@ -209,7 +149,7 @@ namespace relational
if (object (c))
traverse_object (c);
- if (view (c))
+ else if (view (c))
traverse_view (c);
else if (composite (c))
traverse_composite (c);
@@ -226,11 +166,11 @@ namespace relational
traverse_object (type& c)
{
semantics::data_member* id (id_member (c));
- bool base_id (id ? &id->scope () != &c : false); // Comes from base.
+ bool base_id (id && &id->scope () != &c); // Comes from base.
semantics::data_member* optimistic (context::optimistic (c));
- // Base class the contains the object id and version for optimistic
+ // Base class that contains the object id and version for optimistic
// concurrency.
//
type* base (
@@ -244,7 +184,8 @@ namespace relational
bool reuse_abst (abst && !poly);
string const& type (class_fq_name (c));
- string traits ("access::object_traits< " + type + " >");
+ string traits ("access::object_traits_impl< " + type + ", id_" +
+ db.string () + " >");
os << "// " << class_name (c) << endl
<< "//" << endl
@@ -252,39 +193,6 @@ namespace relational
object_extra (c);
- // id (object_type)
- //
- if (id != 0 || !reuse_abst)
- {
- os << "inline" << endl
- << traits << "::id_type" << endl
- << traits << "::" << endl
- << "id (const object_type&" << (id != 0 ? " o" : "") << ")"
- << "{";
-
- if (id != 0)
- {
- if (base_id)
- os << "return object_traits< " << class_fq_name (*base) <<
- " >::id (o);";
- else
- {
- // Get the id using the accessor expression. If this is not
- // a synthesized expression, then output its location for
- // easier error tracking.
- //
- member_access& ma (id->get<member_access> ("get"));
-
- if (!ma.synthesized)
- os << "// From " << location_string (ma.loc, true) << endl;
-
- os << "return " << ma.translate ("o") << ";";
- }
- }
-
- os << "}";
- }
-
if (id != 0 && base_id)
{
if (!poly_derived)
@@ -298,8 +206,8 @@ namespace relational
<< traits << "::" << endl
<< "id (const image_type& i)"
<< "{"
- << "return object_traits< " << class_fq_name (*base) <<
- " >::id (i);"
+ << "return object_traits_impl< " << class_fq_name (*base) <<
+ ", id_" << db << " >::id (i);"
<< "}";
}
@@ -312,8 +220,8 @@ namespace relational
<< traits << "::" << endl
<< "version (const image_type& i)"
<< "{"
- << "return object_traits< " << class_fq_name (*base) <<
- " >::version (i);"
+ << "return object_traits_impl< " << class_fq_name (*base) <<
+ ", id_" << db << " >::version (i);"
<< "}";
}
}
@@ -325,8 +233,8 @@ namespace relational
<< "bind (" << bind_vector << " b, id_image_type& i" <<
(optimistic != 0 ? ", bool bv" : "") << ")"
<< "{"
- << "object_traits< " << class_fq_name (*base) <<
- " >::bind (b, i" << (optimistic != 0 ? ", bv" : "") << ");"
+ << "object_traits_impl< " << class_fq_name (*base) << ", id_" <<
+ db << " >::bind (b, i" << (optimistic != 0 ? ", bv" : "") << ");"
<< "}";
os << "inline" << endl
@@ -334,8 +242,8 @@ namespace relational
<< "init (id_image_type& i, const id_type& id" <<
(optimistic != 0 ? ", const version_type* v" : "") << ")"
<< "{"
- << "object_traits< " << class_fq_name (*base) <<
- " >::init (i, id" << (optimistic != 0 ? ", v" : "") << ");"
+ << "object_traits_impl< " << class_fq_name (*base) << ", id_" <<
+ db << " >::init (i, id" << (optimistic != 0 ? ", v" : "") << ");"
<< "}";
}
@@ -390,7 +298,6 @@ namespace relational
os << "}";
}
- //
// The rest does not apply to reuse-abstract objects.
//
if (reuse_abst)
@@ -410,31 +317,6 @@ namespace relational
<< "}";
}
- // callback ()
- //
- os << "inline" << endl
- << "void " << traits << "::" << endl
- << "callback (database& db, object_type& x, callback_event e)"
- << endl
- << "{"
- << "ODB_POTENTIALLY_UNUSED (db);"
- << "ODB_POTENTIALLY_UNUSED (x);"
- << "ODB_POTENTIALLY_UNUSED (e);"
- << endl;
- callback_calls_->traverse (c, false);
- os << "}";
-
- os << "inline" << endl
- << "void " << traits << "::" << endl
- << "callback (database& db, const object_type& x, callback_event e)"
- << "{"
- << "ODB_POTENTIALLY_UNUSED (db);"
- << "ODB_POTENTIALLY_UNUSED (x);"
- << "ODB_POTENTIALLY_UNUSED (e);"
- << endl;
- callback_calls_->traverse (c, true);
- os << "}";
-
// load_()
//
if (id != 0 && !(poly_derived || has_a (c, test_container)))
@@ -464,7 +346,7 @@ namespace relational
<< "{";
if (poly_derived)
- os << "return object_traits<base_type>::root_image (*i.base);";
+ os << "return base_traits::root_image (*i.base);";
else
os << "return i;";
@@ -479,9 +361,7 @@ namespace relational
<< "{";
if (poly_derived)
- os << "typedef object_traits<base_type> base_traits;"
- << endl
- << "details::unique_ptr<base_traits::image_type> p (" << endl
+ os << "details::unique_ptr<base_traits::image_type> p (" << endl
<< "base_traits::clone_image (*i.base));"
<< "image_type* c (new image_type (i));"
<< "c->base = p.release ();"
@@ -499,9 +379,7 @@ namespace relational
<< "{";
if (poly_derived)
- os << "typedef object_traits<base_type> base_traits;"
- << endl
- << "base_traits::image_type* b (d.base);"
+ os << "base_traits::image_type* b (d.base);"
<< "base_traits::copy_image (*b, *s.base);"
<< "d = s;" // Overwrites the base pointer.
<< "d.base = b;";
@@ -518,7 +396,7 @@ namespace relational
<< "{";
if (poly_derived)
- os << "object_traits<base_type>::free_image (i->base);";
+ os << "base_traits::free_image (i->base);";
os << "delete i;"
<< "}";
@@ -534,34 +412,22 @@ namespace relational
traverse_view (type& c)
{
string const& type (class_fq_name (c));
- string traits ("access::view_traits< " + type + " >");
+ string traits ("access::view_traits_impl< " + type + ", id_" +
+ db.string () + " >");
os << "// " << class_name (c) << endl
<< "//" << endl
<< endl;
view_extra (c);
-
- // callback ()
- //
- os << "inline" << endl
- << "void " << traits << "::" << endl
- << "callback (database& db, view_type& x, callback_event e)"
- << endl
- << "{"
- << "ODB_POTENTIALLY_UNUSED (db);"
- << "ODB_POTENTIALLY_UNUSED (x);"
- << "ODB_POTENTIALLY_UNUSED (e);"
- << endl;
- callback_calls_->traverse (c, false);
- os << "}";
}
virtual void
traverse_composite (type& c)
{
string const& type (class_fq_name (c));
- string traits ("access::composite_value_traits< " + type + " >");
+ string traits ("access::composite_value_traits< " + type + ", id_" +
+ db.string () + " >");
os << "// " << class_name (c) << endl
<< "//" << endl
@@ -602,8 +468,6 @@ namespace relational
}
private:
- instance<callback_calls> callback_calls_;
-
instance<null_base> get_null_base_;
traversal::inherits get_null_base_inherits_;
instance<null_member> get_null_member_;
diff --git a/odb/relational/mssql/common.cxx b/odb/relational/mssql/common.cxx
index b2f982a..d802e54 100644
--- a/odb/relational/mssql/common.cxx
+++ b/odb/relational/mssql/common.cxx
@@ -202,7 +202,8 @@ namespace relational
void member_image_type::
traverse_composite (member_info& mi)
{
- type_ = "composite_value_traits< " + mi.fq_type () + " >::image_type";
+ type_ = "composite_value_traits< " + mi.fq_type () +
+ ", id_mssql >::image_type";
}
void member_image_type::
diff --git a/odb/relational/mysql/common.cxx b/odb/relational/mysql/common.cxx
index b8fa4c3..9d62b6b 100644
--- a/odb/relational/mysql/common.cxx
+++ b/odb/relational/mysql/common.cxx
@@ -168,7 +168,8 @@ namespace relational
void member_image_type::
traverse_composite (member_info& mi)
{
- type_ = "composite_value_traits< " + mi.fq_type () + " >::image_type";
+ type_ = "composite_value_traits< " + mi.fq_type () +
+ ", id_mysql >::image_type";
}
void member_image_type::
diff --git a/odb/relational/mysql/source.cxx b/odb/relational/mysql/source.cxx
index 494abf5..48ae1f2 100644
--- a/odb/relational/mysql/source.cxx
+++ b/odb/relational/mysql/source.cxx
@@ -346,7 +346,7 @@ namespace relational
traverse_composite (member_info& mi)
{
os << "if (composite_value_traits< " << mi.fq_type () <<
- " >::grow (" << endl
+ ", id_mysql >::grow (" << endl
<< "i." << mi.var << "value, t + " << index_ << "UL))"
<< "{"
<< "grew = true;"
diff --git a/odb/relational/oracle/common.cxx b/odb/relational/oracle/common.cxx
index e9d8390..04bb0f8 100644
--- a/odb/relational/oracle/common.cxx
+++ b/odb/relational/oracle/common.cxx
@@ -188,7 +188,8 @@ namespace relational
void member_image_type::
traverse_composite (member_info& mi)
{
- type_ = "composite_value_traits< " + mi.fq_type () + " >::image_type";
+ type_ = "composite_value_traits< " + mi.fq_type () +
+ ", id_oracle >::image_type";
}
void member_image_type::
diff --git a/odb/relational/pgsql/common.cxx b/odb/relational/pgsql/common.cxx
index 3d7e01e..811269e 100644
--- a/odb/relational/pgsql/common.cxx
+++ b/odb/relational/pgsql/common.cxx
@@ -144,7 +144,8 @@ namespace relational
void member_image_type::
traverse_composite (member_info& mi)
{
- type_ = "composite_value_traits< " + mi.fq_type () + " >::image_type";
+ type_ = "composite_value_traits< " + mi.fq_type () +
+ ", id_pgsql >::image_type";
}
void member_image_type::
diff --git a/odb/relational/pgsql/source.cxx b/odb/relational/pgsql/source.cxx
index 23600d0..332e25b 100644
--- a/odb/relational/pgsql/source.cxx
+++ b/odb/relational/pgsql/source.cxx
@@ -295,7 +295,7 @@ namespace relational
traverse_composite (member_info& mi)
{
os << "if (composite_value_traits< " << mi.fq_type () <<
- " >::grow (" << endl
+ ", id_pgsql >::grow (" << endl
<< "i." << mi.var << "value, t + " << index_ << "UL))"
<< "{"
<< "grew = true;"
@@ -642,7 +642,7 @@ namespace relational
string const& n (class_fq_name (c));
string const& fn (flat_name (n));
- string traits ("access::object_traits< " + n + " >");
+ string traits ("access::object_traits_impl< " + n + ", id_pgsql >");
os << "const char " << traits << "::" << endl
<< "persist_statement_name[] = " << strlit (fn + "_persist") << ";"
@@ -792,7 +792,7 @@ namespace relational
{
string const& n (class_fq_name (c));
string const& fn (flat_name (n));
- string traits ("access::view_traits< " + n + " >");
+ string traits ("access::view_traits_impl< " + n + ", id_pgsql >");
os << "const char " << traits << "::" << endl
<< "query_statement_name[] = " << strlit (fn + "_query") << ";"
@@ -800,14 +800,19 @@ namespace relational
}
virtual void
- object_query_statement_ctor_args (type&)
+ object_query_statement_ctor_args (type&, string const& q, bool prep)
{
- os << "sts.connection ()," << endl
- << "query_statement_name," << endl
- << "query_statement + q.clause ()," << endl
- << "q.parameter_types ()," << endl
- << "q.parameter_count ()," << endl
- << "q.parameters_binding ()," << endl
+ os << "sts.connection ()," << endl;
+
+ if (prep)
+ os << "n," << endl;
+ else
+ os << "query_statement_name," << endl;
+
+ os << "query_statement + " << q << ".clause ()," << endl
+ << q << ".parameter_types ()," << endl
+ << q << ".parameter_count ()," << endl
+ << q << ".parameters_binding ()," << endl
<< "imb";
}
@@ -823,21 +828,27 @@ namespace relational
}
virtual void
- view_query_statement_ctor_args (type&)
+ view_query_statement_ctor_args (type&, string const& q, bool prep)
{
- os << "sts.connection ()," << endl
- << "query_statement_name," << endl
- << "qs.clause ()," << endl
- << "qs.parameter_types ()," << endl
- << "qs.parameter_count ()," << endl
- << "qs.parameters_binding ()," << endl
+ os << "sts.connection ()," << endl;
+
+ if (prep)
+ os << "n," << endl;
+ else
+ os << "query_statement_name," << endl;
+
+ os << q << ".clause ()," << endl
+ << q << ".parameter_types ()," << endl
+ << q << ".parameter_count ()," << endl
+ << q << ".parameters_binding ()," << endl
<< "imb";
}
virtual void
- post_query_ (type&)
+ post_query_ (type&, bool once_off)
{
- os << "st->deallocate ();";
+ if (once_off)
+ os << "st->deallocate ();";
}
};
entry<class_> class_entry_;
diff --git a/odb/relational/processor.cxx b/odb/relational/processor.cxx
index f000858..5100739 100644
--- a/odb/relational/processor.cxx
+++ b/odb/relational/processor.cxx
@@ -305,497 +305,14 @@ namespace relational
throw operation_failed ();
}
- process_access (m, "get");
- process_access (m, "set");
- process_index (m);
- }
-
- //
- // Process member access expressions.
- //
-
- enum found_type
- {
- found_none,
- found_some, // Found something but keep looking for a better one.
- found_best
- };
-
- // Check if a function is a suitable accessor for this member.
- //
- found_type
- check_accessor (semantics::data_member& m,
- tree f,
- string const& n,
- member_access& ma,
- bool strict)
- {
- // Must be const.
- //
- if (!DECL_CONST_MEMFUNC_P (f))
- return found_none;
-
- // Accessor is a function with no arguments (other than 'this').
- //
- if (DECL_CHAIN (DECL_ARGUMENTS (f)) != NULL_TREE)
- return found_none;
-
- // Note that to get the return type we have to use
- // TREE_TYPE(TREE_TYPE()) and not DECL_RESULT, as
- // suggested in the documentation.
- //
- tree r (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (f))));
- int tc (TREE_CODE (r));
-
- // In the strict mode make sure the function returns for non-array
- // types a value or a (const) reference to the member type and for
- // array types a (const) pointer to element type. In the lax mode
- // we just check that the return value is not void.
- //
- if (strict)
- {
- semantics::type& t (utype (m));
- semantics::array* ar (dynamic_cast<semantics::array*> (&t));
-
- if (ar != 0 && tc != POINTER_TYPE)
- return found_none;
-
- tree bt (ar != 0 || tc == REFERENCE_TYPE ? TREE_TYPE (r) : r);
- tree bt_mv (TYPE_MAIN_VARIANT (bt));
-
- if ((ar != 0 ? ar->base_type () : t).tree_node () != bt_mv)
- return found_none;
- }
- else if (r == void_type_node)
- return found_none;
-
- cxx_tokens& e (ma.expr);
- e.push_back (cxx_token (0, CPP_KEYWORD, "this"));
- e.push_back (cxx_token (0, CPP_DOT));
- e.push_back (cxx_token (0, CPP_NAME, n));
- e.push_back (cxx_token (0, CPP_OPEN_PAREN, n));
- e.push_back (cxx_token (0, CPP_CLOSE_PAREN, n));
-
- // See if it returns by value.
- //
- ma.by_value = (tc != REFERENCE_TYPE && tc != POINTER_TYPE);
-
- return found_best;
- }
-
- // Check if a function is a suitable modifier for this member.
- //
- found_type
- check_modifier (semantics::data_member& m,
- tree f,
- string const& n,
- member_access& ma,
- bool strict)
- {
- tree a (DECL_ARGUMENTS (f));
- a = DECL_CHAIN (a); // Skip this.
-
- // For a modifier, it can either be a function that returns a non-
- // const reference (or non-const pointer, in case the member is an
- // array) or a by-value modifier that sets a new value. If both are
- // available, we prefer the former for efficiency.
- //
- cxx_tokens& e (ma.expr);
- semantics::type& t (utype (m));
- semantics::array* ar (dynamic_cast<semantics::array*> (&t));
-
- if (a == NULL_TREE)
+ if (m.count ("polymorphic-ref"))
{
- // Note that to get the return type we have to use
- // TREE_TYPE(TREE_TYPE()) and not DECL_RESULT, as
- // suggested in the documentation.
- //
- tree r (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (f))));
- int tc (TREE_CODE (r));
-
- // By-reference modifier. Should return a reference or a pointer.
- //
- if (tc != (ar != 0 ? POINTER_TYPE : REFERENCE_TYPE))
- return found_none;
-
- // The base type should not be const and, in strict mode, should
- // match the member type.
- //
- tree bt (TREE_TYPE (r));
-
- if (CP_TYPE_CONST_P (bt))
- return found_none;
-
- tree bt_mv (TYPE_MAIN_VARIANT (bt));
-
- if (strict && (ar != 0 ? ar->base_type () : t).tree_node () != bt_mv)
- return found_none;
-
- e.clear (); // Could contain by value modifier.
- e.push_back (cxx_token (0, CPP_KEYWORD, "this"));
- e.push_back (cxx_token (0, CPP_DOT));
- e.push_back (cxx_token (0, CPP_NAME, n));
- e.push_back (cxx_token (0, CPP_OPEN_PAREN, n));
- e.push_back (cxx_token (0, CPP_CLOSE_PAREN, n));
-
- return found_best;
+ m.set ("not-null", true);
+ m.set ("deferred", false);
+ m.set ("on-delete", sema_rel::foreign_key::cascade);
}
- // Otherwise look for a by value modifier, which is a function
- // with a single argument.
- //
- else if (DECL_CHAIN (a) == NULL_TREE)
- {
- // In the lax mode any function with a single argument works
- // for us. And we don't care what it returns.
- //
- if (strict)
- {
- // In the strict mode make sure the argument matches the
- // member. This is exactly the same logic as in accessor
- // with regards to arrays, references, etc.
- //
- tree at (TREE_TYPE (a));
- int tc (TREE_CODE (at));
-
- if (ar != 0 && tc != POINTER_TYPE)
- return found_none;
-
- tree bt (ar != 0 || tc == REFERENCE_TYPE ? TREE_TYPE (at) : at);
- tree bt_mv (TYPE_MAIN_VARIANT (bt));
-
- if ((ar != 0 ? ar->base_type () : t).tree_node () != bt_mv)
- return found_none;
- }
-
- if (e.empty ())
- {
- e.push_back (cxx_token (0, CPP_KEYWORD, "this"));
- e.push_back (cxx_token (0, CPP_DOT));
- e.push_back (cxx_token (0, CPP_NAME, n));
- e.push_back (cxx_token (0, CPP_OPEN_PAREN, n));
- e.push_back (cxx_token (0, CPP_QUERY));
- e.push_back (cxx_token (0, CPP_CLOSE_PAREN, n));
-
- // Continue searching in case there is version that returns a
- // non-const reference which we prefer for efficiency.
- //
- return found_some;
- }
- else
- return found_none; // We didn't find anything better.
- }
-
- return found_none;
- }
-
- void
- process_access (semantics::data_member& m, std::string const& k)
- {
- bool virt (m.count ("virtual"));
-
- // Ignore certain special virtual members.
- //
- if (virt && (m.count ("polymorphic-ref") || m.count ("discriminator")))
- return;
-
- char const* kind (k == "get" ? "accessor" : "modifier");
- semantics::class_& c (dynamic_cast<semantics::class_&> (m.scope ()));
-
- // If we don't have an access expression, try to come up with
- // one.
- //
- if (!m.count (k))
- {
- found_type found (found_none);
- semantics::access const& a (m.named ().access ());
- member_access& ma (m.set (k, member_access (m.location (), true)));
-
- // If this member is not virtual and is either public or if we
- // are a friend of this class, then go for the member directly.
- //
- if (!virt && (a == semantics::access::public_ ||
- c.get<bool> ("friend")))
- {
- ma.expr.push_back (cxx_token (0, CPP_KEYWORD, "this"));
- ma.expr.push_back (cxx_token (0, CPP_DOT));
- ma.expr.push_back (cxx_token (0, CPP_NAME, m.name ()));
- found = found_best;
- }
-
- // Otherwise, try to find a suitable accessor/modifier.
- //
-
- // First try the original name. If that doesn't produce anything,
- // then try the public name.
- //
- bool t (k == "get"
- ? options.accessor_regex_trace ()
- : options.modifier_regex_trace ());
- regex_mapping const& re (
- k == "get" ? accessor_regex : modifier_regex);
-
- for (unsigned short j (0); found != found_best && j != 2; ++j)
- {
- string b (j == 0 ? m.name () : public_name (m, false));
-
- // Skip the second pass if original and public names are the same.
- //
- if (j == 1 && b == m.name ())
- continue;
-
- if (t)
- cerr << kind << (j == 0 ? " original" : " public")
- << " name '" << b << "'" << endl;
-
- for (regex_mapping::const_iterator i (re.begin ());
- found != found_best && i != re.end ();
- ++i)
- {
- if (t)
- cerr << "try: '" << i->regex () << "' : ";
-
- if (!i->match (b))
- {
- if (t)
- cerr << '-' << endl;
- continue;
- }
-
- string n (i->replace (b));
-
- if (t)
- cerr << "'" << n << "' : ";
-
- tree decl (
- lookup_qualified_name (
- c.tree_node (), get_identifier (n.c_str ()), false, false));
-
- if (decl == error_mark_node || TREE_CODE (decl) != BASELINK)
- {
- if (t)
- cerr << '-' << endl;
- continue;
- }
-
- // OVL_* macros work for both FUNCTION_DECL and OVERLOAD.
- //
- for (tree o (BASELINK_FUNCTIONS (decl));
- o != 0;
- o = OVL_NEXT (o))
- {
- tree f (OVL_CURRENT (o));
-
- // We are only interested in public non-static member
- // functions. Note that TREE_PUBLIC() returns something
- // other than what we need.
- //
- if (!DECL_NONSTATIC_MEMBER_FUNCTION_P (f) ||
- TREE_PRIVATE (f) || TREE_PROTECTED (f))
- continue;
-
- found_type r (k == "get"
- ? check_accessor (m, f, n, ma, true)
- : check_modifier (m, f, n, ma, true));
-
- if (r != found_none)
- {
- // Update the location of the access expression to point
- // to this function.
- //
- ma.loc = location (DECL_SOURCE_LOCATION (f));
- found = r;
- }
- }
-
- if (t)
- cerr << (found != found_none ? '+' : '-') << endl;
- }
- }
-
- // If that didn't work then the generated code won't be able
- // to access this member.
- //
- if (found == found_none)
- {
- location const& l (m.location ());
-
- if (virt)
- {
- error (l) << "no suitable " << kind << " function could be "
- << "automatically found for virtual data member '"
- << m.name () << "'" << endl;
-
- info (l) << "use '#pragma db " << k << "' to explicitly "
- << "specify the " << kind << " function or "
- << "expression" << endl;
- }
- else
- {
- error (l) << "data member '" << m.name () << "' is "
- << a.string () << " and no suitable " << kind
- << " function could be automatically found" << endl;
- info (l) << "consider making class 'odb::access' a friend of "
- << "class '" << class_name (c) << "'" << endl;
-
- info (l) << "or use '#pragma db " << k << "' to explicitly "
- << "specify the " << kind << " function or "
- << "expression" << endl;
- }
-
- throw operation_failed ();
- }
- }
-
- member_access& ma (m.get<member_access> (k));
- cxx_tokens& e (ma.expr);
-
- // If it is just a name, resolve it and convert to an appropriate
- // expression.
- //
- if (e.size () == 1 && e.back ().type == CPP_NAME)
- {
- string n (e.back ().literal);
- e.clear ();
-
- tree decl (
- lookup_qualified_name (
- c.tree_node (), get_identifier (n.c_str ()), false, false));
-
- if (decl == error_mark_node)
- {
- error (ma.loc) << "unable to resolve data member or function "
- << "name '" << n << "'" << endl;
- throw operation_failed ();
- }
-
- switch (TREE_CODE (decl))
- {
- case FIELD_DECL:
- {
- e.push_back (cxx_token (0, CPP_KEYWORD, "this"));
- e.push_back (cxx_token (0, CPP_DOT));
- e.push_back (cxx_token (0, CPP_NAME, n));
- break;
- }
- case BASELINK:
- {
- // OVL_* macros work for both FUNCTION_DECL and OVERLOAD.
- //
- for (tree o (BASELINK_FUNCTIONS (decl));
- o != 0;
- o = OVL_NEXT (o))
- {
- tree f (OVL_CURRENT (o));
-
- // We are only interested in non-static member functions.
- //
- if (!DECL_NONSTATIC_MEMBER_FUNCTION_P (f))
- continue;
-
- if ((k == "get"
- ? check_accessor (m, f, n, ma, false)
- : check_modifier (m, f, n, ma, false)) == found_best)
- break;
- }
-
- if (e.empty ())
- {
- error (ma.loc) << "unable to find suitable " << kind
- << " function '" << n << "'" << endl;
- throw operation_failed ();
- }
- break;
- }
- default:
- {
- error (ma.loc) << "name '" << n << "' does not refer to a data "
- << "member or function" << endl;
- throw operation_failed ();
- }
- }
- }
-
- // If there is no 'this' keyword, then add it as a prefix.
- //
- {
- bool t (false);
- for (cxx_tokens::iterator i (e.begin ()); i != e.end (); ++i)
- {
- if (i->type == CPP_KEYWORD && i->literal == "this")
- {
- t = true;
- break;
- }
- }
-
- if (!t)
- {
- e.insert (e.begin (), cxx_token (0, CPP_DOT));
- e.insert (e.begin (), cxx_token (0, CPP_KEYWORD, "this"));
- }
- }
-
- // Check that there is no placeholder in the accessor expression.
- //
- if (k == "get" && ma.placeholder ())
- {
- error (ma.loc) << "(?) placeholder in the accessor expression"
- << endl;
- throw operation_failed ();
- }
-
- // Check that the member type is default-constructible if we
- // have a by value modifier.
- //
- if (k == "set" && ma.placeholder ())
- {
- semantics::class_* c (dynamic_cast<semantics::class_*> (&utype (m)));
-
- // Assume all other types are default-constructible.
- //
- if (c != 0)
- {
- // If this type is a class template instantiation, then make
- // sure it is instantiated. While types used in real members
- // will be instantiated, this is not necessarily the case for
- // virtual members. Without the instantiation we won't be able
- // to detect whether the type has the default ctor.
- //
- // It would have been cleaner to do it in post_process_pragmas()
- // but there we don't yet know whether we need the default ctor.
- // And it is a good idea not to require instantiability unless
- // we really need it.
- //
- tree type (c->tree_node ());
-
- if (!COMPLETE_TYPE_P (type) &&
- CLASSTYPE_TEMPLATE_INSTANTIATION (type))
- {
- // Reset input location so that we get nice diagnostics in
- // case of an error. Use the location of the virtual pragma.
- //
- location_t loc (m.get<location_t> ("virtual-location"));
- input_location = loc;
-
- if (instantiate_class_template (type) == error_mark_node ||
- errorcount != 0 ||
- !COMPLETE_TYPE_P (type))
- {
- error (loc) << "unable to instantiate virtual data member " <<
- "type" << endl;
- throw operation_failed ();
- }
- }
-
- if (!c->default_ctor ())
- {
- error (ma.loc) << "modifier expression requires member type " <<
- "to be default-constructible" << endl;
- throw operation_failed ();
- }
- }
- }
+ process_index (m);
}
// Convert index/unique specifiers to the index entry in the object.
@@ -2351,44 +1868,7 @@ namespace relational
struct class_: traversal::class_, context
{
class_ ()
- : std_string_ (0), std_string_hint_ (0), access_ (0)
{
- // Resolve the std::string type node.
- //
- using semantics::scope;
-
- for (scope::names_iterator_pair ip (unit.find ("std"));
- ip.first != ip.second; ++ip.first)
- {
- if (scope* ns = dynamic_cast<scope*> (&ip.first->named ()))
- {
- scope::names_iterator_pair jp (ns->find ("string"));
-
- if (jp.first != jp.second)
- {
- std_string_ = dynamic_cast<semantics::type*> (
- &jp.first->named ());
- std_string_hint_ = &*jp.first;
- break;
- }
- }
- }
-
- assert (std_string_ != 0); // No std::string?
-
- // Resolve odb::access, if any.
- //
- tree odb = lookup_qualified_name (
- global_namespace, get_identifier ("odb"), false, false);
-
- if (odb != error_mark_node)
- {
- access_ = lookup_qualified_name (
- odb, get_identifier ("access"), true, false);
-
- access_ = (access_ != error_mark_node ? TREE_TYPE (access_) : 0);
- }
-
*this >> member_names_ >> member_;
}
@@ -2400,28 +1880,12 @@ namespace relational
if (k == class_other)
return;
- // Check if odb::access is a friend of this class.
- //
- c.set ("friend", access_ != 0 && is_friend (c.tree_node (), access_));
-
- // Assign pointer.
- //
- if (k == class_object || k == class_view)
- assign_pointer (c);
-
- // Do some additional pre-processing.
- //
- if (k == class_object)
- traverse_object_pre (c);
-
names (c);
- // Do some additional post-processing.
- //
if (k == class_object)
- traverse_object_post (c);
+ traverse_object (c);
else if (k == class_view)
- traverse_view_post (c);
+ traverse_view (c);
}
//
@@ -2429,149 +1893,7 @@ namespace relational
//
virtual void
- traverse_object_pre (type& c)
- {
- semantics::class_* poly_root (polymorphic (c));
-
- // Determine whether it is a session object.
- //
- if (!c.count ("session"))
- {
- // If this is a derived class in a polymorphic hierarchy,
- // then it should have the same session value as the root.
- //
- if (poly_root != 0 && poly_root != &c)
- c.set ("session", session (*poly_root));
- else
- {
- // See if any of the namespaces containing this class specify
- // the session value.
- //
- bool found (false);
- for (semantics::scope* s (&c.scope ());; s = &s->scope_ ())
- {
- using semantics::namespace_;
-
- namespace_* ns (dynamic_cast<namespace_*> (s));
-
- if (ns == 0)
- continue; // Some other scope.
-
- if (ns->extension ())
- ns = &ns->original ();
-
- if (ns->count ("session"))
- {
- c.set ("session", ns->get<bool> ("session"));
- found = true;
- break;
- }
-
- if (ns->global_scope ())
- break;
- }
-
- // If still not found, then use the default value.
- //
- if (!found)
- c.set ("session", options.generate_session ());
- }
- }
-
- if (session (c))
- features.session_object = true;
-
- if (poly_root != 0)
- {
- using namespace semantics;
-
- semantics::data_member& idm (*id_member (*poly_root));
-
- if (poly_root != &c)
- {
- // If we are a derived class in the polymorphic persistent
- // class hierarchy, then add a synthesized virtual pointer
- // member that points back to the root.
- //
- path const& f (idm.file ());
- size_t l (idm.line ()), col (idm.column ());
-
- semantics::data_member& m (
- unit.new_node<semantics::data_member> (f, l, col, tree (0)));
- m.set ("virtual", true);
-
- // Make it the first member in the class.
- //
- node_position<type, scope::names_iterator> np (c, c.names_end ());
- unit.new_edge<semantics::names> (
- np, m, idm.name (), access::public_);
-
- // Use the raw pointer as this member's type.
- //
- if (!poly_root->pointed_p ())
- {
- // Create the pointer type in the graph. The pointer node
- // in GCC seems to always be present, even if not explicitly
- // used in the translation unit.
- //
- tree t (poly_root->tree_node ());
- tree ptr (TYPE_POINTER_TO (t));
- assert (ptr != 0);
- ptr = TYPE_MAIN_VARIANT (ptr);
- pointer& p (unit.new_node<pointer> (f, l, col, ptr));
- unit.insert (ptr, p);
- unit.new_edge<points> (p, *poly_root);
- assert (poly_root->pointed_p ());
- }
-
- unit.new_edge<belongs> (m, poly_root->pointed ().pointer ());
-
- m.set ("not-null", true);
- m.set ("deferred", false);
- m.set ("on-delete", sema_rel::foreign_key::cascade);
-
- // Mark it as a special kind of id.
- //
- m.set ("id", true);
- m.set ("polymorphic-ref", true);
- }
- else
- {
- // If we are a root of the polymorphic persistent class hierarchy,
- // then add a synthesized virtual member for the discriminator.
- // Use the location of the polymorphic pragma as the location of
- // this member.
- //
- location_t loc (c.get<location_t> ("polymorphic-location"));
- semantics::data_member& m (
- unit.new_node<semantics::data_member> (
- path (LOCATION_FILE (loc)),
- LOCATION_LINE (loc),
- LOCATION_COLUMN (loc),
- tree (0)));
- m.set ("virtual", true);
-
- // Insert it after the id member (or first if this id comes
- // from reuse-base).
- //
- node_position<type, scope::names_iterator> np (
- c, c.find (idm.named ()));
- unit.new_edge<semantics::names> (
- np, m, "typeid_", access::public_);
-
- belongs& edge (unit.new_edge<belongs> (m, *std_string_));
- edge.hint (*std_string_hint_);
-
- m.set ("readonly", true);
- m.set ("discriminator", true);
-
- c.set ("discriminator", &m);
- }
- }
- }
-
- virtual void
- traverse_object_post (type& c)
+ traverse_object (type& c)
{
// Process indexes. Here we need to do two things: resolve member
// names to member paths and assign names to unnamed indexes. We
@@ -2767,7 +2089,7 @@ namespace relational
typedef vector<relationship> relationships;
virtual void
- traverse_view_post (type& c)
+ traverse_view (type& c)
{
bool has_q (c.count ("query"));
bool has_o (c.count ("objects"));
@@ -3154,417 +2476,11 @@ namespace relational
view_object& pointee_;
};
- void
- assign_pointer (type& c)
- {
- location_t loc (0); // Pragma location, or 0 if not used.
-
- try
- {
- string ptr;
- string const& type (class_fq_name (c));
-
- tree decl (0); // Resolved template node.
- string decl_name; // User-provided template name.
- tree resolve_scope (0); // Scope in which we resolve names.
-
- class_pointer const* cp (0);
- bool cp_template (false);
-
- if (c.count ("pointer"))
- {
- cp = &c.get<class_pointer> ("pointer");
- }
- // If we are a derived type in polymorphic hierarchy, then use
- // our root's pointer type by default.
- //
- else if (semantics::class_* r = polymorphic (c))
- {
- if (&c != r && r->count ("pointer-template"))
- cp = r->get<class_pointer const*> ("pointer-template");
- }
-
- if (cp != 0)
- {
- string const& p (cp->name);
-
- if (p == "*")
- {
- ptr = type + "*";
- cp_template = true;
- }
- else if (p[p.size () - 1] == '*')
- ptr = p;
- else if (p.find ('<') != string::npos)
- {
- // Template-id.
- //
- ptr = p;
- decl_name.assign (p, 0, p.find ('<'));
- }
- else
- {
- // This is not a template-id. Resolve it and see if it is a
- // template or a type.
- //
- decl = resolve_name (p, cp->scope, true);
- int tc (TREE_CODE (decl));
-
- if (tc == TYPE_DECL)
- {
- ptr = p;
-
- // This can be a typedef'ed alias for a TR1 template-id.
- //
- if (tree ti = TYPE_TEMPLATE_INFO (TREE_TYPE (decl)))
- {
- decl = TI_TEMPLATE (ti); // DECL_TEMPLATE
-
- // Get to the most general template declaration.
- //
- while (DECL_TEMPLATE_INFO (decl))
- decl = DECL_TI_TEMPLATE (decl);
- }
- else
- decl = 0; // Not a template.
- }
- else if (tc == TEMPLATE_DECL && DECL_CLASS_TEMPLATE_P (decl))
- {
- ptr = p + "< " + type + " >";
- decl_name = p;
- cp_template = true;
- }
- else
- {
- error (cp->loc)
- << "name '" << p << "' specified with db pragma pointer "
- << "does not name a type or a template" << endl;
-
- throw operation_failed ();
- }
- }
-
- // Resolve scope is the scope of the pragma.
- //
- resolve_scope = cp->scope;
- loc = cp->loc;
- }
- else
- {
- // See if any of the namespaces containing this class specify
- // a pointer.
- //
- for (semantics::scope* s (&c.scope ());; s = &s->scope_ ())
- {
- using semantics::namespace_;
-
- namespace_* ns (dynamic_cast<namespace_*> (s));
-
- if (ns == 0)
- continue; // Some other scope.
-
- if (ns->extension ())
- ns = &ns->original ();
-
- if (!ns->count ("pointer"))
- {
- if (ns->global_scope ())
- break;
- else
- continue;
- }
-
- cp = &ns->get<class_pointer> ("pointer");
- string const& p (cp->name);
-
- // Namespace-specified pointer can only be '*' or are template.
- //
- if (p == "*")
- ptr = type + "*";
- else if (p[p.size () - 1] == '*')
- {
- error (cp->loc)
- << "name '" << p << "' specified with db pragma pointer "
- << "at namespace level cannot be a raw pointer" << endl;
- }
- else if (p.find ('<') != string::npos)
- {
- error (cp->loc)
- << "name '" << p << "' specified with db pragma pointer "
- << "at namespace level cannot be a template-id" << endl;
- }
- else
- {
- // Resolve this name and make sure it is a template.
- //
- decl = resolve_name (p, cp->scope, true);
- int tc (TREE_CODE (decl));
-
- if (tc == TEMPLATE_DECL && DECL_CLASS_TEMPLATE_P (decl))
- {
- ptr = p + "< " + type + " >";
- decl_name = p;
- }
- else
- {
- error (cp->loc)
- << "name '" << p << "' specified with db pragma pointer "
- << "does not name a template" << endl;
- }
- }
-
- if (ptr.empty ())
- throw operation_failed ();
-
- cp_template = true;
-
- // Resolve scope is the scope of the pragma.
- //
- resolve_scope = cp->scope;
- loc = cp->loc;
- break;
- }
-
- // Use the default pointer.
- //
- if (ptr.empty ())
- {
- string const& p (options.default_pointer ());
-
- if (p == "*")
- ptr = type + "*";
- else
- {
- ptr = p + "< " + type + " >";
- decl_name = p;
- }
-
- // Resolve scope is the scope of the class.
- //
- resolve_scope = c.scope ().tree_node ();
- }
- }
-
- // If this class is a root of a polymorphic hierarchy, then cache
- // the pointer template so that we can use it for derived classes.
- //
- if (cp != 0 && cp_template && polymorphic (c) == &c)
- c.set ("pointer-template", cp);
-
- // Check if we are using TR1.
- //
- if (decl != 0 || !decl_name.empty ())
- {
- bool& tr1 (features.tr1_pointer);
- bool& boost (features.boost_pointer);
-
- // First check the user-supplied name.
- //
- tr1 = tr1
- || decl_name.compare (0, 8, "std::tr1") == 0
- || decl_name.compare (0, 10, "::std::tr1") == 0;
-
- // If there was no match, also resolve the name since it can be
- // a using-declaration for a TR1 template.
- //
- if (!tr1)
- {
- if (decl == 0)
- decl = resolve_name (decl_name, resolve_scope, false);
-
- if (TREE_CODE (decl) != TEMPLATE_DECL || !
- DECL_CLASS_TEMPLATE_P (decl))
- {
- // This is only checked for the --default-pointer option.
- //
- error (c.file (), c.line (), c.column ())
- << "name '" << decl_name << "' specified with the "
- << "--default-pointer option does not name a class "
- << "template" << endl;
-
- throw operation_failed ();
- }
-
- string n (decl_as_string (decl, TFF_PLAIN_IDENTIFIER));
-
- // In case of a boost TR1 implementation, we cannot distinguish
- // between the boost:: and std::tr1:: usage since the latter is
- // just a using-declaration for the former.
- //
- tr1 = tr1
- || n.compare (0, 8, "std::tr1") == 0
- || n.compare (0, 10, "::std::tr1") == 0;
-
- boost = boost
- || n.compare (0, 17, "boost::shared_ptr") == 0
- || n.compare (0, 19, "::boost::shared_ptr") == 0;
- }
- }
-
- // Fully-qualify all the unqualified components of the name.
- //
- try
- {
- lex_.start (ptr);
- ptr.clear ();
-
- string t;
- bool punc (false);
- bool scoped (false);
-
- for (cpp_ttype tt (lex_.next (t));
- tt != CPP_EOF;
- tt = lex_.next (t))
- {
- if (punc && tt > CPP_LAST_PUNCTUATOR)
- ptr += ' ';
-
- punc = false;
-
- switch (static_cast<unsigned> (tt))
- {
- case CPP_LESS:
- {
- ptr += "< ";
- break;
- }
- case CPP_GREATER:
- {
- ptr += " >";
- break;
- }
- case CPP_COMMA:
- {
- ptr += ", ";
- break;
- }
- case CPP_NAME:
- {
- // If the name was not preceeded with '::', look it
- // up in the pragmas's scope and add the qualifer.
- //
- if (!scoped)
- {
- tree decl (resolve_name (t, resolve_scope, false));
- tree scope (CP_DECL_CONTEXT (decl));
-
- if (scope != global_namespace)
- {
- ptr += "::";
- ptr += decl_as_string (scope, TFF_PLAIN_IDENTIFIER);
- }
-
- ptr += "::";
- }
-
- ptr += t;
- punc = true;
- break;
- }
- case CPP_KEYWORD:
- case CPP_NUMBER:
- {
- ptr += t;
- punc = true;
- break;
- }
- default:
- {
- ptr += t;
- break;
- }
- }
-
- scoped = (tt == CPP_SCOPE);
- }
- }
- catch (cxx_lexer::invalid_input const&)
- {
- throw operation_failed ();
- }
-
- c.set ("object-pointer", ptr);
- }
- catch (invalid_name const& ex)
- {
- if (loc != 0)
- error (loc)
- << "name '" << ex.name () << "' specified with db pragma "
- << "pointer is invalid" << endl;
- else
- error (c.file (), c.line (), c.column ())
- << "name '" << ex.name () << "' specified with the "
- << "--default-pointer option is invalid" << endl;
-
-
- throw operation_failed ();
- }
- catch (unable_to_resolve const& ex)
- {
- if (loc != 0)
- error (loc)
- << "unable to resolve name '" << ex.name () << "' specified "
- << "with db pragma pointer" << endl;
- else
- error (c.file (), c.line (), c.column ())
- << "unable to resolve name '" << ex.name () << "' specified "
- << "with the --default-pointer option" << endl;
-
- throw operation_failed ();
- }
- }
-
- private:
- struct invalid_name
- {
- invalid_name (string const& n): name_ (n) {}
-
- string const&
- name () const {return name_;}
-
- private:
- string name_;
- };
-
- typedef lookup::unable_to_resolve unable_to_resolve;
-
- tree
- resolve_name (string const& qn, tree scope, bool is_type)
- {
- try
- {
- string tl;
- tree tn;
- cpp_ttype tt, ptt;
-
- nlex_.start (qn);
- tt = nlex_.next (tl, &tn);
-
- string name;
- return lookup::resolve_scoped_name (
- nlex_, tt, tl, tn, ptt, scope, name, is_type);
- }
- catch (cxx_lexer::invalid_input const&)
- {
- throw invalid_name (qn);
- }
- catch (lookup::invalid_name const&)
- {
- throw invalid_name (qn);
- }
- }
-
private:
cxx_string_lexer lex_;
- cxx_string_lexer nlex_; // Nested lexer.
data_member member_;
traversal::names member_names_;
-
- semantics::type* std_string_;
- semantics::names* std_string_hint_;
-
- tree access_; // odb::access node.
};
}
diff --git a/odb/relational/schema.hxx b/odb/relational/schema.hxx
index 56857f3..63ab860 100644
--- a/odb/relational/schema.hxx
+++ b/odb/relational/schema.hxx
@@ -864,7 +864,8 @@ namespace relational
++end; // Transform the range from [begin, end] to [begin, end).
string const& type (class_fq_name (c));
- string traits ("access::object_traits< " + type + " >");
+ string traits ("access::object_traits_impl< " + type + ", id_" +
+ db.string () + " >");
// create_schema ()
//
@@ -941,7 +942,8 @@ namespace relational
os << "static const schema_catalog_entry" << endl
<< "schema_catalog_entry_" << flat_name (type) << "_ (" << endl
- << strlit (options.schema_name ()) << "," << endl
+ << "id_" << db << "," << endl
+ << strlit (options.schema_name ()[db]) << "," << endl
<< "&" << traits << "::create_schema);"
<< endl;
}
diff --git a/odb/relational/source.cxx b/odb/relational/source.cxx
index 5a02703..7516801 100644
--- a/odb/relational/source.cxx
+++ b/odb/relational/source.cxx
@@ -18,8 +18,8 @@ traverse_object (type& c)
using semantics::data_member;
data_member* id (id_member (c));
- bool auto_id (id ? id->count ("auto") : false);
- bool base_id (id ? &id->scope () != &c : false); // Comes from base.
+ bool auto_id (id && auto_ (*id));
+ bool base_id (id && &id->scope () != &c); // Comes from base.
member_access* id_ma (id ? &id->get<member_access> ("get") : 0);
bool has_ptr (has_a (c, test_pointer));
@@ -49,7 +49,8 @@ traverse_object (type& c)
}
string const& type (class_fq_name (c));
- string traits ("access::object_traits< " + type + " >");
+ string traits ("access::object_traits_impl< " + type + ", id_" +
+ db.string () + " >");
column_count_type const& cc (column_count (c));
os << "// " << class_name (c) << endl
@@ -187,7 +188,7 @@ traverse_object (type& c)
<< "//" << endl
<< "if (--d != 0)"
<< "{"
- << "if (object_traits<base_type>::grow (*i.base, " <<
+ << "if (base_traits::grow (*i.base, " <<
"t + " << cols << "UL" <<
(poly_base != poly_root ? ", d" : "") << "))" << endl
<< "i.base->version++;"
@@ -268,7 +269,7 @@ traverse_object (type& c)
os << "// " << class_name (*poly_base) << " base" << endl
<< "//" << endl
<< "if (sk == statement_select)" << endl
- << "object_traits<base_type>::";
+ << "base_traits::";
if (poly_base == poly_root)
os << "bind (b + n, *i.base, sk);";
@@ -360,7 +361,7 @@ traverse_object (type& c)
os << "// " << class_name (*poly_base) << " base" << endl
<< "//" << endl
<< "if (--d != 0)" << endl
- << "object_traits<base_type>::init (o, *i.base, db" <<
+ << "base_traits::init (o, *i.base, db" <<
(poly_base != poly_root ? ", d" : "") << ");"
<< endl;
}
@@ -450,7 +451,8 @@ traverse_object (type& c)
<< "typeid (" << type << ")," << endl;
if (poly_derived)
- os << "&object_traits< " << class_fq_name (*poly_base) << " >::info";
+ os << "&object_traits_impl< " << class_fq_name (*poly_base) <<
+ ", id_" << db << " >::info";
else
os << "0";
@@ -463,7 +465,7 @@ traverse_object (type& c)
os << "," << endl
<< strlit (string (n, 2, string::npos)) << "," << endl
<< "&odb::create_impl< " << type << " >," << endl
- << "&odb::dispatch_impl< " << type << " >," << endl;
+ << "&odb::dispatch_impl< " << type << ", id_" << db << " >," << endl;
if (poly_derived)
os << "&statements_type::delayed_loader";
@@ -883,7 +885,7 @@ traverse_object (type& c)
// hierarchy.
//
if (poly_derived)
- os << "object_traits<base_type>::persist (db, obj, false, false);"
+ os << "base_traits::persist (db, obj, false, false);"
<< endl;
os << "image_type& im (sts.image ());"
@@ -1135,7 +1137,7 @@ traverse_object (type& c)
//
if (!readonly_base)
{
- os << "object_traits<base_type>::update (db, obj, false, false);"
+ os << "base_traits::update (db, obj, false, false);"
<< endl;
}
else
@@ -1550,7 +1552,7 @@ traverse_object (type& c)
// Call our base last (we erase polymorphic objects from base
// to derived in order not to trigger cascading deletes).
//
- os << "object_traits<base_type>::erase (db, id, false, false);"
+ os << "base_traits::erase (db, id, false, false);"
<< endl;
}
@@ -1787,7 +1789,7 @@ traverse_object (type& c)
// Call our base last (we erase polymorphic objects from base
// to derived in order not to trigger cascading deletes).
//
- os << "object_traits<base_type>::erase (db, obj, false, false);"
+ os << "base_traits::erase (db, obj, false, false);"
<< endl;
}
@@ -2349,7 +2351,7 @@ traverse_object (type& c)
if (poly_derived)
os << "if (--d != 0)" << endl
- << "object_traits<base_type>::load_ (sts.base_statements (), obj" <<
+ << "base_traits::load_ (sts.base_statements (), obj" <<
(poly_base != poly_root ? ", d" : "") << ");"
<< endl;
@@ -2562,60 +2564,6 @@ traverse_object (type& c)
if (options.generate_query ())
{
- // query ()
- //
- os << "result< " << traits << "::object_type >" << endl
- << traits << "::" << endl
- << "query (database&, const query_base_type& q)"
- << "{"
- << "using namespace " << db << ";"
- << "using odb::details::shared;"
- << "using odb::details::shared_ptr;"
- << endl
- << db << "::connection& conn (" << endl
- << db << "::transaction::current ().connection ());"
- << endl
- << "statements_type& sts (" << endl
- << "conn.statement_cache ().find_object<object_type> ());"
- << endl;
-
- // Rebind the image if necessary.
- //
- os << "image_type& im (sts.image ());"
- << "binding& imb (sts.select_image_binding (" <<
- (poly_derived ? "depth" : "") << "));"
- << endl;
-
- if (poly_derived)
- {
- os << "if (imb.version == 0 ||" << endl
- << "check_version (sts.select_image_versions (), im))"
- << "{"
- << "bind (imb.bind, 0, 0, im, statement_select);"
- << "update_version (sts.select_image_versions ()," << endl
- << "im," << endl
- << "sts.select_image_bindings ());"
- << "}";
- }
- else
- {
- os << "if (im.version != sts.select_image_version () ||" << endl
- << "imb.version == 0)"
- << "{"
- << "bind (imb.bind, im, statement_select);"
- << "sts.select_image_version (im.version);"
- << "imb.version++;"
- << "}";
- }
-
- os << "shared_ptr<select_statement> st (" << endl
- << "new (shared) select_statement (" << endl;
- object_query_statement_ctor_args (c);
- os << "));" << endl
- << "st->execute ();";
-
- post_query_ (c);
-
char const* result_type;
if (poly)
result_type = "polymorphic_object_result_impl<object_type>";
@@ -2624,13 +2572,73 @@ traverse_object (type& c)
else
result_type = "no_id_object_result_impl<object_type>";
- os << endl
- << "shared_ptr< odb::" << result_type << " > r (" << endl
- << "new (shared) " << db << "::" << result_type << " (" << endl
- << "q, st, sts));"
- << endl
- << "return result<object_type> (r);"
- << "}";
+ // Unprepared.
+ //
+ if (!options.omit_unprepared ())
+ {
+ // query ()
+ //
+ os << "result< " << traits << "::object_type >" << endl
+ << traits << "::" << endl
+ << "query (database&, const query_base_type& q)"
+ << "{"
+ << "using namespace " << db << ";"
+ << "using odb::details::shared;"
+ << "using odb::details::shared_ptr;"
+ << endl
+ << db << "::connection& conn (" << endl
+ << db << "::transaction::current ().connection ());"
+ << endl
+ << "statements_type& sts (" << endl
+ << "conn.statement_cache ().find_object<object_type> ());"
+ << endl;
+
+ // Rebind the image if necessary.
+ //
+ os << "image_type& im (sts.image ());"
+ << "binding& imb (sts.select_image_binding (" <<
+ (poly_derived ? "depth" : "") << "));"
+ << endl;
+
+ if (poly_derived)
+ {
+ os << "if (imb.version == 0 ||" << endl
+ << "check_version (sts.select_image_versions (), im))"
+ << "{"
+ << "bind (imb.bind, 0, 0, im, statement_select);"
+ << "update_version (sts.select_image_versions ()," << endl
+ << "im," << endl
+ << "sts.select_image_bindings ());"
+ << "}";
+ }
+ else
+ {
+ os << "if (im.version != sts.select_image_version () ||" << endl
+ << "imb.version == 0)"
+ << "{"
+ << "bind (imb.bind, im, statement_select);"
+ << "sts.select_image_version (im.version);"
+ << "imb.version++;"
+ << "}";
+ }
+
+ os << "q.init_parameters ();"
+ << "shared_ptr<select_statement> st (" << endl
+ << "new (shared) select_statement (" << endl;
+ object_query_statement_ctor_args (c, "q", false);
+ os << "));" << endl
+ << "st->execute ();";
+
+ post_query_ (c, true);
+
+ os << endl
+ << "shared_ptr< odb::" << result_type << " > r (" << endl
+ << "new (shared) " << db << "::" << result_type << " (" << endl
+ << "q, st, sts));"
+ << endl
+ << "return result<object_type> (r);"
+ << "}";
+ }
// erase_query
//
@@ -2642,12 +2650,142 @@ traverse_object (type& c)
<< db << "::connection& conn (" << endl
<< db << "::transaction::current ().connection ());"
<< endl
+ << "q.init_parameters ();"
<< "delete_statement st (" << endl;
object_erase_query_statement_ctor_args (c);
os << ");"
<< endl
<< "return st.execute ();"
<< "}";
+
+ // Prepared. Very similar to unprepared but has some annoying variations
+ // that make it difficult to factor out something common.
+ //
+ if (options.generate_prepared ())
+ {
+ os << "odb::details::shared_ptr<prepared_query_impl>" << endl
+ << traits << "::" << endl
+ << "prepare_query (connection& c, const char* n, " <<
+ "const query_base_type& q)"
+ << "{"
+ << "using namespace " << db << ";"
+ << "using odb::details::shared;"
+ << "using odb::details::shared_ptr;"
+ << endl
+ << db << "::connection& conn (" << endl
+ << "static_cast<" << db << "::connection&> (c));"
+ << endl
+ << "statements_type& sts (" << endl
+ << "conn.statement_cache ().find_object<object_type> ());"
+ << endl;
+
+ // Rebind the image if necessary.
+ //
+ os << "image_type& im (sts.image ());"
+ << "binding& imb (sts.select_image_binding (" <<
+ (poly_derived ? "depth" : "") << "));"
+ << endl;
+
+ if (poly_derived)
+ {
+ os << "if (imb.version == 0 ||" << endl
+ << "check_version (sts.select_image_versions (), im))"
+ << "{"
+ << "bind (imb.bind, 0, 0, im, statement_select);"
+ << "update_version (sts.select_image_versions ()," << endl
+ << "im," << endl
+ << "sts.select_image_bindings ());"
+ << "}";
+ }
+ else
+ {
+ os << "if (im.version != sts.select_image_version () ||" << endl
+ << "imb.version == 0)"
+ << "{"
+ << "bind (imb.bind, im, statement_select);"
+ << "sts.select_image_version (im.version);"
+ << "imb.version++;"
+ << "}";
+ }
+
+ os << "shared_ptr<" << db << "::prepared_query_impl> r (" << endl
+ << "new (shared) " << db << "::prepared_query_impl (conn));"
+ << "r->name = n;"
+ << "r->execute = &execute_query;"
+ << "r->query = q;"
+ << "r->stmt.reset (" << endl
+ << "new (shared) select_statement (" << endl;
+ object_query_statement_ctor_args (c, "r->query", true);
+ os << "));"
+ << endl
+ << "return r;"
+ << "}";
+
+ os << "odb::details::shared_ptr<result_impl>" << endl
+ << traits << "::" << endl
+ << "execute_query (prepared_query_impl& q)"
+ << "{"
+ << "using namespace " << db << ";"
+ << "using odb::details::shared;"
+ << "using odb::details::shared_ptr;"
+ << endl
+ << db << "::prepared_query_impl& pq (" << endl
+ << "static_cast<" << db << "::prepared_query_impl&> (q));"
+ << "shared_ptr<select_statement> st (" << endl
+ << "odb::details::inc_ref (" << endl
+ << "static_cast<select_statement*> (pq.stmt.get ())));"
+ << endl
+ << db << "::connection& conn (" << endl
+ << db << "::transaction::current ().connection ());"
+ << endl
+ << "// The connection used by the current transaction and the" << endl
+ << "// one used to prepare this statement must be the same." << endl
+ << "//" << endl
+ << "assert (&conn == &st->connection ());"
+ << endl
+ << "statements_type& sts (" << endl
+ << "conn.statement_cache ().find_object<object_type> ());"
+ << endl;
+
+ // Rebind the image if necessary.
+ //
+ os << "image_type& im (sts.image ());"
+ << "binding& imb (sts.select_image_binding (" <<
+ (poly_derived ? "depth" : "") << "));"
+ << endl;
+
+ if (poly_derived)
+ {
+ os << "if (imb.version == 0 ||" << endl
+ << "check_version (sts.select_image_versions (), im))"
+ << "{"
+ << "bind (imb.bind, 0, 0, im, statement_select);"
+ << "update_version (sts.select_image_versions ()," << endl
+ << "im," << endl
+ << "sts.select_image_bindings ());"
+ << "}";
+ }
+ else
+ {
+ os << "if (im.version != sts.select_image_version () ||" << endl
+ << "imb.version == 0)"
+ << "{"
+ << "bind (imb.bind, im, statement_select);"
+ << "sts.select_image_version (im.version);"
+ << "imb.version++;"
+ << "}";
+ }
+
+ os << "pq.query.init_parameters ();"
+ << "st->execute ();";
+ post_query_ (c, false);
+
+ os << endl
+ << "return shared_ptr<result_impl> (" << endl
+ << "new (shared) " << db << "::" << result_type << " (" << endl
+ << "pq.query, st, sts));"
+ << "}";
+ }
}
if (embedded_schema)
@@ -2658,7 +2796,8 @@ void relational::source::class_::
traverse_view (type& c)
{
string const& type (class_fq_name (c));
- string traits ("access::view_traits< " + type + " >");
+ string traits ("access::view_traits_impl< " + type + ", id_" +
+ db.string () + " >");
os << "// " << class_name (c) << endl
<< "//" << endl
@@ -3391,54 +3530,157 @@ traverse_view (type& c)
<< "}";
}
- // query ()
+ // Unprepared.
//
- os << "result< " << traits << "::view_type >" << endl
- << traits << "::" << endl
- << "query (database&, const query_base_type& q)"
- << "{"
- << "using namespace " << db << ";"
- << "using odb::details::shared;"
- << "using odb::details::shared_ptr;"
- << endl
- << db << "::connection& conn (" << endl
- << db << "::transaction::current ().connection ());"
- << endl
- << "view_statements< view_type >& sts (" << endl
- << "conn.statement_cache ().find_view<view_type> ());"
- << endl
- << "image_type& im (sts.image ());"
- << "binding& imb (sts.image_binding ());"
- << endl
- << "if (im.version != sts.image_version () || imb.version == 0)"
- << "{"
- << "bind (imb.bind, im);"
- << "sts.image_version (im.version);"
- << "imb.version++;"
- << "}";
+ if (!options.omit_unprepared ())
+ {
+ os << "result< " << traits << "::view_type >" << endl
+ << traits << "::" << endl
+ << "query (database&, const query_base_type& q)"
+ << "{"
+ << "using namespace " << db << ";"
+ << "using odb::details::shared;"
+ << "using odb::details::shared_ptr;"
+ << endl
+ << db << "::connection& conn (" << endl
+ << db << "::transaction::current ().connection ());"
+ << endl
+ << "statements_type& sts (" << endl
+ << "conn.statement_cache ().find_view<view_type> ());"
+ << endl
+ << "image_type& im (sts.image ());"
+ << "binding& imb (sts.image_binding ());"
+ << endl
+ << "if (im.version != sts.image_version () || imb.version == 0)"
+ << "{"
+ << "bind (imb.bind, im);"
+ << "sts.image_version (im.version);"
+ << "imb.version++;"
+ << "}";
- if (vq.kind == view_query::runtime)
- os << "const query_base_type& qs (q);";
- else
- os << "const query_base_type& qs (query_statement (q));";
+ if (vq.kind == view_query::runtime)
+ os << "const query_base_type& qs (q);";
+ else
+ os << "const query_base_type& qs (query_statement (q));";
- os << "shared_ptr<select_statement> st (" << endl
- << "new (shared) select_statement (" << endl;
+ os << "qs.init_parameters ();"
+ << "shared_ptr<select_statement> st (" << endl
+ << "new (shared) select_statement (" << endl;
+ view_query_statement_ctor_args (c, "qs", false);
+ os << "));" << endl
+ << "st->execute ();";
- view_query_statement_ctor_args (c);
+ post_query_ (c, true);
- os << "));" << endl
- << "st->execute ();";
+ os << endl
+ << "shared_ptr< odb::view_result_impl<view_type> > r (" << endl
+ << "new (shared) " << db << "::view_result_impl<view_type> (" << endl
+ << "qs, st, sts));"
+ << endl
+ << "return result<view_type> (r);"
+ << "}";
+ }
- post_query_ (c);
+ // Prepared. Very similar to unprepared but has some annoying variations
+ // that make it difficult to factor out something common.
+ //
+ if (options.generate_prepared ())
+ {
+ os << "odb::details::shared_ptr<prepared_query_impl>" << endl
+ << traits << "::" << endl
+ << "prepare_query (connection& c, const char* n, " <<
+ "const query_base_type& q)"
+ << "{"
+ << "using namespace " << db << ";"
+ << "using odb::details::shared;"
+ << "using odb::details::shared_ptr;"
+ << endl
+ << db << "::connection& conn (" << endl
+ << "static_cast<" << db << "::connection&> (c));"
+ << endl
+ << "statements_type& sts (" << endl
+ << "conn.statement_cache ().find_view<view_type> ());"
+ << endl;
- os << endl
- << "shared_ptr< odb::view_result_impl<view_type> > r (" << endl
- << "new (shared) " << db << "::view_result_impl<view_type> (" << endl
- << "qs, st, sts));"
- << endl
- << "return result<view_type> (r);"
- << "}";
+ // Rebind the image if necessary.
+ //
+ os << "image_type& im (sts.image ());"
+ << "binding& imb (sts.image_binding ());"
+ << endl
+ << "if (im.version != sts.image_version () || imb.version == 0)"
+ << "{"
+ << "bind (imb.bind, im);"
+ << "sts.image_version (im.version);"
+ << "imb.version++;"
+ << "}";
+
+ os << "shared_ptr<" << db << "::prepared_query_impl> r (" << endl
+ << "new (shared) " << db << "::prepared_query_impl (conn));"
+ << "r->name = n;"
+ << "r->execute = &execute_query;";
+
+ if (vq.kind == view_query::runtime)
+ os << "r->query = q;";
+ else
+ os << "r->query = query_statement (q);";
+
+ os << "r->stmt.reset (" << endl
+ << "new (shared) select_statement (" << endl;
+ view_query_statement_ctor_args (c, "r->query", true);
+ os << "));"
+ << endl
+ << "return r;"
+ << "}";
+
+ os << "odb::details::shared_ptr<result_impl>" << endl
+ << traits << "::" << endl
+ << "execute_query (prepared_query_impl& q)"
+ << "{"
+ << "using namespace " << db << ";"
+ << "using odb::details::shared;"
+ << "using odb::details::shared_ptr;"
+ << endl
+ << db << "::prepared_query_impl& pq (" << endl
+ << "static_cast<" << db << "::prepared_query_impl&> (q));"
+ << "shared_ptr<select_statement> st (" << endl
+ << "odb::details::inc_ref (" << endl
+ << "static_cast<select_statement*> (pq.stmt.get ())));"
+ << endl
+ << db << "::connection& conn (" << endl
+ << db << "::transaction::current ().connection ());"
+ << endl
+ << "// The connection used by the current transaction and the" << endl
+ << "// one used to prepare this statement must be the same." << endl
+ << "//" << endl
+ << "assert (&conn == &st->connection ());"
+ << endl
+ << "statements_type& sts (" << endl
+ << "conn.statement_cache ().find_view<view_type> ());"
+ << endl;
+
+ // Rebind the image if necessary.
+ //
+ os << "image_type& im (sts.image ());"
+ << "binding& imb (sts.image_binding ());"
+ << endl
+ << "if (im.version != sts.image_version () || imb.version == 0)"
+ << "{"
+ << "bind (imb.bind, im);"
+ << "sts.image_version (im.version);"
+ << "imb.version++;"
+ << "}";
+
+ os << "pq.query.init_parameters ();"
+ << "st->execute ();";
+
+ post_query_ (c, false);
+
+ os << endl
+ << "return shared_ptr<result_impl> (" << endl
+ << "new (shared) " << db << "::view_result_impl<view_type> (" << endl
+ << "pq.query, st, sts));"
+ << "}";
+ }
}
namespace relational
diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx
index b73cd01..8d57b1b 100644
--- a/odb/relational/source.hxx
+++ b/odb/relational/source.hxx
@@ -937,8 +937,9 @@ namespace relational
virtual void
traverse_composite (member_info& mi)
{
- os << "composite_value_traits< " << mi.fq_type () <<
- " >::bind (b + n, " << arg << "." << mi.var << "value, sk);";
+ os << "composite_value_traits< " << mi.fq_type () << ", id_" <<
+ db << " >::bind (" << endl
+ << "b + n, " << arg << "." << mi.var << "value, sk);";
}
protected:
@@ -973,8 +974,12 @@ namespace relational
os << "if (sk != statement_update)"
<< "{";
- os << (obj ? "object" : "composite_value") << "_traits< " <<
- class_fq_name (c) << " >::bind (b + n, i, sk);";
+ if (obj)
+ os << "object_traits_impl< ";
+ else
+ os << "composite_value_traits< ";
+
+ os << class_fq_name (c) << ", id_" << db << " >::bind (b + n, i, sk);";
column_count_type const& cc (column_count (c));
@@ -1067,8 +1072,15 @@ namespace relational
os << "// " << class_name (c) << " base" << endl
<< "//" << endl;
- os << "if (" << (obj ? "object" : "composite_value") << "_traits< " <<
- class_fq_name (c) << " >::grow (i, t + " << index_ << "UL))" << endl
+ os << "if (";
+
+ if (obj)
+ os << "object_traits_impl< ";
+ else
+ os << "composite_value_traits< ";
+
+ os << class_fq_name (c) << ", id_" << db << " >::grow (" << endl
+ << "i, t + " << index_ << "UL))" << endl
<< "grew = true;"
<< endl;
@@ -1232,10 +1244,11 @@ namespace relational
if (null (mi.m, key_prefix_) &&
mi.wrapper->template get<bool> ("wrapper-null-handler"))
{
- os << "if (wrapper_traits< " + wt + " >::get_null (" <<
+ os << "if (wrapper_traits< " << wt << " >::get_null (" <<
member << "))" << endl
- << "composite_value_traits< " + mi.fq_type () + " >::" <<
- "set_null (i." << mi.var << "value, sk);"
+ << "composite_value_traits< " << mi.fq_type () << ", id_" <<
+ db << " >::set_null (" << endl
+ << "i." << mi.var << "value, sk);"
<< "else"
<< "{";
}
@@ -1307,7 +1320,8 @@ namespace relational
}
if (comp)
- traits = "composite_value_traits< " + type + " >";
+ traits = "composite_value_traits< " + type + ", id_" +
+ db.string () + " >";
else
{
db_type_id = member_database_type_id_->database_type_id (mi.m);
@@ -1403,8 +1417,12 @@ namespace relational
if (generate_grow)
os << "if (";
- os << (obj ? "object" : "composite_value") << "_traits< " <<
- class_fq_name (c) << " >::init (i, o, sk)";
+ if (obj)
+ os << "object_traits_impl< ";
+ else
+ os << "composite_value_traits< ";
+
+ os << class_fq_name (c) << ", id_" << db << " >::init (i, o, sk)";
if (generate_grow)
os << ")" << endl
@@ -1571,9 +1589,10 @@ namespace relational
if (null (mi.m, key_prefix_) &&
mi.wrapper->template get<bool> ("wrapper-null-handler"))
{
- os << "if (composite_value_traits< " + mi.fq_type () + " >::" <<
- "get_null (i." << mi.var << "value))" << endl
- << "wrapper_traits< " + wt + " >::set_null (" << member + ");"
+ os << "if (composite_value_traits< " << mi.fq_type () <<
+ ", id_" << db << " >::get_null (" << endl
+ << "i." << mi.var << "value))" << endl
+ << "wrapper_traits< " << wt << " >::set_null (" << member + ");"
<< "else" << endl;
}
@@ -1595,8 +1614,9 @@ namespace relational
os << "if (";
if (comp)
- os << "composite_value_traits< " + type + " >::get_null (i." <<
- mi.var << "value)";
+ os << "composite_value_traits< " << type << ", id_" << db <<
+ " >::get_null (" << endl
+ << "i." << mi.var << "value)";
else
get_null (mi);
@@ -1618,7 +1638,8 @@ namespace relational
type = mi.fq_type ();
if (comp)
- traits = "composite_value_traits< " + type + " >";
+ traits = "composite_value_traits< " + type + ", id_" +
+ db.string () + " >";
else
{
db_type_id = member_database_type_id_->database_type_id (mi.m);
@@ -1645,7 +1666,8 @@ namespace relational
semantics::type& pt (member_utype (mi.m, key_prefix_));
if (lazy_pointer (pt))
- os << member << " = ptr_traits::pointer_type (*db, id);";
+ os << member << " = ptr_traits::pointer_type (" << endl
+ << "*static_cast<" << db << "::database*> (db), id);";
else
{
os << "// If a compiler error points to the line below, then" << endl
@@ -1653,7 +1675,8 @@ namespace relational
<< "// cannot be initialized from an object pointer." << endl
<< "//" << endl
<< member << " = ptr_traits::pointer_type (" << endl
- << "db->load< obj_traits::object_type > (id));";
+ << "static_cast<" << db << "::database*> (db)->load<" << endl
+ << " obj_traits::object_type > (id));";
// If we are loading into an eager weak pointer, make sure there
// is someone else holding a strong pointer to it (normally a
@@ -1730,9 +1753,14 @@ namespace relational
return;
os << "// " << class_name (c) << " base" << endl
- << "//" << endl
- << (obj ? "object" : "composite_value") << "_traits< " <<
- class_fq_name (c) << " >::init (o, i, db);"
+ << "//" << endl;
+
+ if (obj)
+ os << "object_traits_impl< ";
+ else
+ os << "composite_value_traits< ";
+
+ os << class_fq_name (c) << ", id_" << db << " >::init (o, i, db);"
<< endl;
}
};
@@ -1750,12 +1778,11 @@ namespace relational
false),
c_ (c)
{
- string const& type (class_fq_name (c));
+ scope_ = object (c)
+ ? "access::object_traits_impl< "
+ : "access::composite_value_traits< ";
- if (object (c))
- scope_ = "access::object_traits< " + type + " >";
- else
- scope_ = "access::composite_value_traits< " + type + " >";
+ scope_ += class_fq_name (c) + ", id_" + db.string () + " >";
}
// Unless the database system can execute several interleaving
@@ -3381,7 +3408,7 @@ namespace relational
//
virtual void
- post_query_ (type&)
+ post_query_ (type&, bool /*once_off*/)
{
}
@@ -3400,11 +3427,13 @@ namespace relational
}
virtual void
- object_query_statement_ctor_args (type&)
+ object_query_statement_ctor_args (type&,
+ std::string const& q,
+ bool /*prepared*/)
{
- os << "sts.connection ()," << endl
- << "query_statement + q.clause ()," << endl
- << "q.parameters_binding ()," << endl
+ os << "conn," << endl
+ << "query_statement + " << q << ".clause ()," << endl
+ << q << ".parameters_binding ()," << endl
<< "imb";
}
@@ -3429,11 +3458,13 @@ namespace relational
}
virtual void
- view_query_statement_ctor_args (type&)
+ view_query_statement_ctor_args (type&,
+ string const& q,
+ bool /*prepared*/)
{
- os << "sts.connection ()," << endl
- << "qs.clause ()," << endl
- << "qs.parameters_binding ()," << endl
+ os << "conn," << endl
+ << q << ".clause ()," << endl
+ << q << ".parameters_binding ()," << endl
<< "imb";
}
@@ -3469,7 +3500,8 @@ namespace relational
traverse_composite (type& c)
{
string const& type (class_fq_name (c));
- string traits ("access::composite_value_traits< " + type + " >");
+ string traits ("access::composite_value_traits< " + type + ", id_" +
+ db.string () + " >");
os << "// " << class_name (c) << endl
<< "//" << endl
@@ -3637,9 +3669,6 @@ namespace relational
if (embedded_schema)
os << "#include <odb/schema-catalog-impl.hxx>" << endl;
- if (options.generate_query ())
- os << "#include <odb/details/shared-ptr.hxx>" << endl;
-
os << endl;
os << "#include <odb/" << db << "/traits.hxx>" << endl
@@ -3666,6 +3695,9 @@ namespace relational
if (options.generate_query ())
{
+ if (options.generate_prepared ())
+ os << "#include <odb/" << db << "/prepared-query.hxx>" << endl;
+
if (features.simple_object)
os << "#include <odb/" << db << "/simple-object-result.hxx>" << endl;
diff --git a/odb/relational/sqlite/common.cxx b/odb/relational/sqlite/common.cxx
index 7164ef3..601b01d 100644
--- a/odb/relational/sqlite/common.cxx
+++ b/odb/relational/sqlite/common.cxx
@@ -78,7 +78,8 @@ namespace relational
void member_image_type::
traverse_composite (member_info& mi)
{
- type_ = "composite_value_traits< " + mi.fq_type () + " >::image_type";
+ type_ = "composite_value_traits< " + mi.fq_type () +
+ ", id_sqlite >::image_type";
}
void member_image_type::
diff --git a/odb/relational/sqlite/source.cxx b/odb/relational/sqlite/source.cxx
index 03467cc..731afba 100644
--- a/odb/relational/sqlite/source.cxx
+++ b/odb/relational/sqlite/source.cxx
@@ -123,7 +123,7 @@ namespace relational
traverse_composite (member_info& mi)
{
os << "if (composite_value_traits< " << mi.fq_type () <<
- " >::grow (" << endl
+ ", id_sqlite >::grow (" << endl
<< "i." << mi.var << "value, t + " << index_ << "UL))"
<< "{"
<< "grew = true;"
diff --git a/odb/relational/validator.cxx b/odb/relational/validator.cxx
index 1269406..9d14571 100644
--- a/odb/relational/validator.cxx
+++ b/odb/relational/validator.cxx
@@ -21,11 +21,228 @@ namespace relational
// Pass 2.
//
+ struct data_member2: traversal::data_member, context
+ {
+ data_member2 (bool& valid)
+ : valid_ (valid)
+ {
+ }
+
+ virtual void
+ traverse (type& m)
+ {
+ if (transient (m))
+ return;
+
+ if (null (m))
+ {
+ if (semantics::class_* c = composite_wrapper (utype (m)))
+ {
+ if (has_a (*c, test_container))
+ {
+ os << m.file () << ":" << m.line () << ":" << m.column () << ":"
+ << " error: composite member containing containers cannot "
+ << "be null" << endl;
+
+ os << c->file () << ":" << c->line () << ":" << c->column ()
+ << ": info: composite value type is defined here" << endl;
+
+ valid_ = false;
+ }
+ }
+ }
+ }
+
+ bool& valid_;
+ };
+
+ struct object_no_id_members: object_members_base
+ {
+ object_no_id_members (bool& valid)
+ : object_members_base (false, false, true), valid_ (valid), dm_ (0)
+ {
+ }
+
+ virtual void
+ traverse_pointer (semantics::data_member& m, semantics::class_&)
+ {
+ if (inverse (m))
+ {
+ semantics::data_member& dm (dm_ != 0 ? *dm_ : m);
+
+ os << dm.file () << ":" << dm.line () << ":" << dm.column () << ":"
+ << " error: inverse object pointer member '" << member_prefix_
+ << m.name () << "' in an object without an object id" << endl;
+
+ valid_ = false;
+ }
+ }
+
+ virtual void
+ traverse_container (semantics::data_member& m, semantics::type&)
+ {
+ semantics::data_member& dm (dm_ != 0 ? *dm_ : m);
+
+ os << dm.file () << ":" << dm.line () << ":" << dm.column () << ":"
+ << " error: container member '" << member_prefix_ << m.name ()
+ << "' in an object without an object id" << endl;
+
+ valid_ = false;
+ }
+
+ virtual void
+ traverse_composite (semantics::data_member* m, semantics::class_& c)
+ {
+ semantics::data_member* old_dm (dm_);
+
+ if (dm_ == 0)
+ dm_ = m;
+
+ object_members_base::traverse_composite (m, c);
+
+ dm_ = old_dm;
+ }
+
+ private:
+ bool& valid_;
+ semantics::data_member* dm_; // Direct object data member.
+ };
+
+ struct composite_id_members: object_members_base
+ {
+ composite_id_members (bool& valid)
+ : object_members_base (false, false, true), valid_ (valid), dm_ (0)
+ {
+ }
+
+ virtual void
+ traverse_pointer (semantics::data_member& m, semantics::class_&)
+ {
+ semantics::data_member& dm (dm_ != 0 ? *dm_ : m);
+
+ os << dm.file () << ":" << dm.line () << ":" << dm.column () << ":"
+ << " error: object pointer member '" << member_prefix_ << m.name ()
+ << "' in a composite value type that is used as an object id"
+ << endl;
+
+ valid_ = false;
+ }
+
+ virtual void
+ traverse_simple (semantics::data_member& m)
+ {
+ if (readonly (member_path_, member_scope_))
+ {
+ semantics::data_member& dm (dm_ != 0 ? *dm_ : m);
+
+ os << dm.file () << ":" << dm.line () << ":" << dm.column () << ":"
+ << " error: readonly member '" << member_prefix_ << m.name ()
+ << "' in a composite value type that is used as an object id"
+ << endl;
+
+ valid_ = false;
+ }
+ }
+
+ virtual void
+ traverse_container (semantics::data_member& m, semantics::type&)
+ {
+ semantics::data_member& dm (dm_ != 0 ? *dm_ : m);
+
+ os << dm.file () << ":" << dm.line () << ":" << dm.column () << ":"
+ << " error: container member '" << member_prefix_ << m.name ()
+ << "' in a composite value type that is used as an object id"
+ << endl;
+
+ valid_ = false;
+ }
+
+ virtual void
+ traverse_composite (semantics::data_member* m, semantics::class_& c)
+ {
+ semantics::data_member* old_dm (dm_);
+
+ if (dm_ == 0)
+ dm_ = m;
+
+ object_members_base::traverse_composite (m, c);
+
+ dm_ = old_dm;
+ }
+
+ private:
+ bool& valid_;
+ semantics::data_member* dm_; // Direct composite member.
+ };
+
+ struct view_members: object_members_base
+ {
+ view_members (bool& valid)
+ : object_members_base (false, false, true), valid_ (valid), dm_ (0)
+ {
+ }
+
+ virtual void
+ traverse_simple (semantics::data_member& m)
+ {
+ if (object_pointer (utype (m)))
+ {
+ semantics::data_member& dm (dm_ != 0 ? *dm_ : m);
+
+ os << dm.file () << ":" << dm.line () << ":" << dm.column () << ":"
+ << " error: view data member '" << member_prefix_ << m.name ()
+ << "' is an object pointer" << endl;
+
+ os << dm.file () << ":" << dm.line () << ":" << dm.column () << ":"
+ << ": info: views cannot contain object pointers" << endl;
+
+ valid_ = false;
+ }
+ }
+
+ virtual void
+ traverse_container (semantics::data_member& m, semantics::type&)
+ {
+ semantics::data_member& dm (dm_ != 0 ? *dm_ : m);
+
+ os << dm.file () << ":" << dm.line () << ":" << dm.column () << ":"
+ << " error: view data member '" << member_prefix_ << m.name ()
+ << "' is a container" << endl;
+
+ os << dm.file () << ":" << dm.line () << ":" << dm.column () << ":"
+ << ": info: views cannot contain containers" << endl;
+
+ valid_ = false;
+ }
+
+ virtual void
+ traverse_composite (semantics::data_member* m, semantics::class_& c)
+ {
+ semantics::data_member* old_dm (dm_);
+
+ if (dm_ == 0)
+ dm_ = m;
+
+ object_members_base::traverse_composite (m, c);
+
+ dm_ = old_dm;
+ }
+
+ private:
+ bool& valid_;
+ semantics::data_member* dm_; // Direct view data member.
+ };
+
struct class2: traversal::class_, context
{
class2 (bool& valid)
- : valid_ (valid)
+ : valid_ (valid),
+ data_member_ (valid),
+ object_no_id_members_ (valid),
+ composite_id_members_ (valid),
+ view_members_ (valid)
{
+ *this >> data_member_names_ >> data_member_;
}
virtual void
@@ -56,6 +273,66 @@ namespace relational
virtual void
traverse_object (type& c)
{
+ semantics::data_member* id (id_member (c));
+
+ if (id != 0)
+ {
+ if (semantics::class_* cm = composite_wrapper (utype (*id)))
+ {
+ // Composite id cannot be auto.
+ //
+ if (auto_ (*id))
+ {
+ os << id->file () << ":" << id->line () << ":" << id->column ()
+ << ": error: composite id cannot be automatically assigned"
+ << endl;
+
+ valid_ = false;
+ }
+
+ // Make sure we don't have any containers or pointers in this
+ // composite value type.
+ //
+ if (valid_)
+ {
+ composite_id_members_.traverse (*cm);
+
+ if (!valid_)
+ os << id->file () << ":" << id->line () << ":" << id->column ()
+ << ": info: composite id is defined here" << endl;
+ }
+
+ // Check that the composite value type is default-constructible.
+ //
+ if (!cm->default_ctor ())
+ {
+ os << cm->file () << ":" << cm->line () << ":" << cm->column ()
+ << ": error: composite value type that is used as object id "
+ << "is not default-constructible" << endl;
+
+ os << cm->file () << ":" << cm->line () << ":" << cm->column ()
+ << ": info: provide default constructor for this value type"
+ << endl;
+
+ os << id->file () << ":" << id->line () << ":" << id->column ()
+ << ": info: composite id is defined here" << endl;
+
+ valid_ = false;
+ }
+ }
+ }
+ else
+ {
+ if (!abstract (c))
+ {
+ // Make sure we don't have any containers or inverse pointers.
+ //
+ object_no_id_members_.traverse (c);
+ }
+ }
+
+ names (c);
+
// Validate indexes.
//
{
@@ -90,17 +367,30 @@ namespace relational
}
virtual void
- traverse_view (type&)
+ traverse_view (type& c)
{
+ // Make sure we don't have any containers or object pointers.
+ //
+ view_members_.traverse (c);
+
+ names (c);
}
virtual void
- traverse_composite (type&)
+ traverse_composite (type& c)
{
+ names (c);
}
public:
bool& valid_;
+
+ data_member2 data_member_;
+ traversal::names data_member_names_;
+
+ object_no_id_members object_no_id_members_;
+ composite_id_members composite_id_members_;
+ view_members view_members_;
};
}