summaryrefslogtreecommitdiff
path: root/odb/odb/relational/header.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'odb/odb/relational/header.cxx')
-rw-r--r--odb/odb/relational/header.cxx1146
1 files changed, 1146 insertions, 0 deletions
diff --git a/odb/odb/relational/header.cxx b/odb/odb/relational/header.cxx
new file mode 100644
index 0000000..364d48e
--- /dev/null
+++ b/odb/odb/relational/header.cxx
@@ -0,0 +1,1146 @@
+// file : odb/relational/header.cxx
+// license : GNU GPL v3; see accompanying LICENSE file
+
+#include <odb/relational/header.hxx>
+#include <odb/relational/generate.hxx>
+
+using namespace std;
+
+void relational::header::class1::
+traverse_object (type& c)
+{
+ using semantics::data_member;
+
+ data_member_path* id (id_member (c));
+ data_member* idf (id ? id->front () : 0);
+ data_member* idb (id ? id->back () : 0);
+ bool auto_id (id && auto_ (*id));
+ bool base_id (id && &idf->scope () != &c); // Comes from base.
+
+ data_member* opt (context::optimistic (c));
+
+ type* poly_root (polymorphic (c));
+ bool poly (poly_root != 0);
+ bool poly_derived (poly && poly_root != &c);
+ data_member* discriminator (poly ? context::discriminator (*poly_root) : 0);
+
+ bool abst (abstract (c));
+ bool reuse_abst (abst && !poly);
+
+ bool versioned (context::versioned (c));
+
+ string const& type (class_fq_name (c));
+
+ // Sections.
+ //
+ user_sections& uss (c.get<user_sections> ("user-sections"));
+
+ os << "// " << class_name (c) << endl
+ << "//" << endl;
+
+ // pointer_query_columns & query_columns
+ //
+ if (options.generate_query ())
+ {
+ // If we don't have object pointers, then also generate
+ // query_columns (in this case pointer_query_columns and
+ // query_columns are the same and the former inherits from
+ // the latter). Otherwise we have to postpone query_columns
+ // generation until the second pass to deal with forward-
+ // declared objects.
+ //
+ if (!has_a (c, test_pointer | include_base))
+ query_columns_type_->traverse (c);
+
+ pointer_query_columns_type_->traverse (c);
+ }
+
+ // object_traits_impl
+ //
+ os << "template <>" << endl
+ << "class " << exp << "access::object_traits_impl< " << type << ", " <<
+ "id_" << db << " >:" << endl
+ << " public access::object_traits< " << type << " >"
+ << "{"
+ << "public:" << endl;
+
+ object_public_extra_pre (c);
+
+ // For dynamic multi-database support also generate common traits
+ // alias (used in query aliasing).
+ //
+ if (options.generate_query () && multi_dynamic)
+ {
+ os << "typedef access::object_traits_impl< " << type << ", " <<
+ "id_common > common_traits;"
+ << endl;
+ }
+
+ // Polymorphic root_traits, base_traits, and discriminator_image_type.
+ //
+ if (poly)
+ {
+ 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 object_traits_impl<base_type, id_" << db << "> " <<
+ "base_traits;"
+ << endl;
+ }
+ else
+ {
+ os << endl
+ << "struct discriminator_image_type"
+ << "{";
+
+ discriminator_image_member_->traverse (*discriminator);
+
+ if (opt != 0)
+ version_image_member_->traverse (*opt);
+
+ os << "std::size_t version;"
+ << "};";
+ }
+ }
+
+ // id_image_type
+ //
+ if (id != 0)
+ {
+ if (base_id)
+ {
+ if (poly_derived)
+ os << "typedef root_traits::id_image_type id_image_type;"
+ << endl;
+ else
+ {
+ semantics::class_& b (
+ dynamic_cast<semantics::class_&> (idf->scope ()));
+
+ os << "typedef object_traits_impl< " << class_fq_name (b) << ", " <<
+ "id_" << db << " >::id_image_type id_image_type;"
+ << endl;
+ }
+ }
+ else
+ {
+ os << "struct id_image_type"
+ << "{";
+
+ id_image_member_->traverse (*idb);
+
+ if (opt != 0)
+ version_image_member_->traverse (*opt);
+
+ os << "std::size_t version;"
+ << "};";
+ }
+ }
+
+ // Polymorphic map.
+ //
+ if (poly)
+ {
+ if (!poly_derived)
+ os << "static map_type* map;";
+
+ os << "static const " << (abst ? "abstract_" : "") << "info_type info;"
+ << endl;
+ }
+
+ // image_type
+ //
+ image_type_->traverse (c);
+
+ // Extra (container, section) statement cache (forward declaration).
+ //
+ if (!reuse_abst && id != 0)
+ os << "struct extra_statement_cache_type;"
+ << endl;
+
+ //
+ // Containers (abstract and concrete).
+ //
+
+ {
+ instance<container_traits> t (c);
+ t->traverse (c);
+ }
+
+ //
+ // Sections (abstract and concrete).
+ //
+
+ for (user_sections::iterator i (uss.begin ()); i != uss.end (); ++i)
+ {
+ instance<section_traits> t (c);
+ t->traverse (*i);
+ }
+
+ //
+ // Query (abstract and concrete).
+ //
+
+ if (options.generate_query ())
+ {
+ // Generate object pointer tags here unless we are generating dynamic
+ // multi-database support, in which case they generated in object_traits.
+ //
+ if (!multi_dynamic && has_a (c, test_pointer | exclude_base))
+ {
+ query_tags t; // Not customizable.
+ t.traverse (c);
+ }
+ }
+
+ //
+ // Functions (abstract and concrete).
+ //
+
+ if (id != 0 || !reuse_abst)
+ os << "using object_traits<object_type>::id;"
+ << endl;
+
+ if (opt != 0)
+ os << "using object_traits<object_type>::version;"
+ << endl;
+
+ if (!poly_derived && id != 0)
+ {
+ if (auto_id)
+ os << "static id_type" << endl
+ << "id (const id_image_type&);"
+ << endl;
+
+ if (options.generate_query ())
+ os << "static id_type" << endl
+ << "id (const image_type&);"
+ << endl;
+
+ if (opt != 0)
+ os << "static version_type" << endl
+ << "version (const image_type&);"
+ << endl;
+ }
+
+ // discriminator()
+ //
+ if (poly && !poly_derived)
+ os << "static discriminator_type" << endl
+ << "discriminator (const image_type&);"
+ << endl;
+
+ // grow ()
+ //
+ if (generate_grow)
+ {
+ // For derived classes in a polymorphic hierarchy, grow() will
+ // check bases up to the specified depth. If one of the base
+ // images has grown, then it will increment its version. But
+ // the return value only indicates the state of this image,
+ // excluding polymorphic bases (in other words, it is possible
+ // that one of the bases has grown but this function returns
+ // false).
+ //
+ os << "static bool" << endl
+ << "grow (image_type&," << endl
+ << truncated_vector;
+
+ if (versioned)
+ os << "," << endl
+ << "const schema_version_migration&";
+
+ if (poly_derived)
+ os << "," << endl
+ << "std::size_t = depth";
+
+ os << ");"
+ << endl;
+ }
+
+ // bind (image_type)
+ //
+ os << "static void" << endl
+ << "bind (" << bind_vector << "," << endl;
+
+ // If we are a derived type in a polymorphic hierarchy, then
+ // we get the the external id binding.
+ //
+ if (poly_derived)
+ os << "const " << bind_vector << " id," << endl
+ << "std::size_t id_size," << endl;
+
+ os << "image_type&," << endl
+ << db << "::statement_kind";
+
+ if (versioned)
+ os << "," << endl
+ << "const schema_version_migration&";
+
+ os << ");"
+ << endl;
+
+ // bind (id_image_type)
+ //
+ if (id != 0)
+ {
+ os << "static void" << endl
+ << "bind (" << bind_vector << ", id_image_type&" <<
+ (opt != 0 ? ", bool bind_version = true" : "") << ");"
+ << endl;
+ }
+
+ // init (image, object)
+ //
+ os << "static " << (generate_grow ? "bool" : "void") << endl
+ << "init (image_type&," << endl
+ << "const object_type&," << endl
+ << db << "::statement_kind";
+
+ if (versioned)
+ os << "," << endl
+ << "const schema_version_migration&";
+
+ os << ");"
+ << endl;
+
+ // init (object, image)
+ //
+ os << "static void" << endl
+ << "init (object_type&," << endl
+ << "const image_type&," << endl
+ << "database*";
+
+ if (versioned)
+ os << "," << endl
+ << "const schema_version_migration&";
+
+ if (poly_derived)
+ os << "," << endl
+ << "std::size_t = depth";
+
+ os << ");"
+ << endl;
+
+ // init (id_image, id)
+ //
+ if (id != 0)
+ {
+ os << "static void" << endl
+ << "init (id_image_type&, const id_type&" <<
+ (opt != 0 ? ", const version_type* = 0" : "") << ");"
+ << endl;
+ }
+
+ if (poly_derived)
+ {
+ // check_version
+ //
+ os << "static bool" << endl
+ << "check_version (const std::size_t*, const image_type&);"
+ << endl;
+
+ // update_version
+ //
+ os << "static void" << endl
+ << "update_version (std::size_t*, const image_type&, " <<
+ db << "::binding*);"
+ << endl;
+ }
+
+ // The rest does not apply to reuse-abstract objects.
+ //
+ if (reuse_abst)
+ {
+ object_public_extra_post (c);
+ os << "};";
+ return;
+ }
+
+ column_count_type const& cc (column_count (c));
+
+ // Statements typedefs.
+ //
+ if (poly)
+ {
+ if (poly_derived)
+ os << "typedef" << endl
+ << db << "::polymorphic_derived_object_statements" <<
+ "<object_type>" << endl
+ << "statements_type;"
+ << endl
+ << "typedef" << endl
+ << db << "::polymorphic_root_object_statements<root_type>" << endl
+ << "root_statements_type;"
+ << endl;
+ else
+ os << "typedef" << endl
+ << db << "::polymorphic_root_object_statements<object_type>" << endl
+ << "statements_type;"
+ << endl
+ << "typedef statements_type root_statements_type;"
+ << endl;
+ }
+ else
+ {
+ if (id != 0)
+ os << "typedef " << db << "::object_statements<object_type> " <<
+ "statements_type;"
+ << endl;
+ else
+ os << "typedef " << db << "::no_id_object_statements<object_type> " <<
+ "statements_type;"
+ << endl;
+ }
+
+ //
+ // Query (concrete).
+ //
+
+ if (options.generate_query ())
+ {
+ // query_base_type
+ //
+ os << "typedef " << db << "::query_base query_base_type;"
+ << endl;
+ }
+
+ //
+ // Containers (concrete).
+ //
+
+ //
+ // Sections (concrete).
+ //
+
+ // column_count
+ //
+ os << "static const std::size_t column_count = " << cc.total << "UL;"
+ << "static const std::size_t id_column_count = " << cc.id << "UL;"
+ << "static const std::size_t inverse_column_count = " <<
+ cc.inverse << "UL;"
+ << "static const std::size_t readonly_column_count = " <<
+ cc.readonly << "UL;"
+ << "static const std::size_t managed_optimistic_column_count = " <<
+ cc.optimistic_managed << "UL;";
+
+ if (poly && !poly_derived)
+ os << "static const std::size_t discriminator_column_count = " <<
+ cc.discriminator << "UL;";
+
+ os << endl
+ << "static const std::size_t separate_load_column_count = " <<
+ cc.separate_load << "UL;"
+ << "static const std::size_t separate_update_column_count = " <<
+ cc.separate_update << "UL;"
+ << endl;
+
+ os << "static const bool versioned = " << versioned << ";"
+ << endl;
+
+ // Statements.
+ //
+ os << "static const char persist_statement[];";
+
+ if (id != 0)
+ {
+ if (poly_derived)
+ {
+ char const* n (abst ? "1" : "depth");
+
+ os << "static const char* const find_statements[" << n << "];"
+ << "static const std::size_t find_column_counts[" << n << "];";
+ }
+ else
+ {
+ os << "static const char find_statement[];";
+
+ if (poly)
+ os << "static const char find_discriminator_statement[];";
+ }
+
+ if (cc.total != cc.id + cc.inverse + cc.readonly + cc.separate_update)
+ os << "static const char update_statement[];";
+
+ os << "static const char erase_statement[];";
+
+ if (opt != 0 && !poly_derived)
+ os << "static const char optimistic_erase_statement[];";
+ }
+
+ if (options.generate_query ())
+ {
+ os << "static const char query_statement[];"
+ << "static const char erase_query_statement[];"
+ << endl
+ << "static const char table_name[];";
+ }
+
+ os << endl;
+
+ //
+ // Functions (concrete).
+ //
+
+ // persist ()
+ //
+ os << "static void" << endl
+ << "persist (database&, " << (auto_id ? "" : "const ") << "object_type&";
+
+ if (poly)
+ os << ", bool top = true, bool dyn = true";
+
+ os << ");"
+ << endl;
+
+ if (c.count ("bulk-persist"))
+ os << "static void" << endl
+ << "persist (database&, " << (auto_id ? "" : "const ") <<
+ "object_type**, std::size_t, multiple_exceptions&);"
+ << endl;
+
+ if (id != 0)
+ {
+ // find (id)
+ //
+ if (c.default_ctor ())
+ os << "static pointer_type" << endl
+ << "find (database&, const id_type&);"
+ << endl;
+
+ // find (id, obj)
+ //
+ os << "static bool" << endl
+ << "find (database&, const id_type&, object_type&";
+
+ if (poly)
+ os << ", bool dyn = true";
+
+ os << ");"
+ << endl;
+
+ // reload ()
+ //
+ os << "static bool" << endl
+ << "reload (database&, object_type&";
+
+ if (poly)
+ os << ", bool dyn = true";
+
+ os << ");"
+ << endl;
+
+ // update ()
+ //
+ // In case of a polymorphic object, we generate update() even if it is
+ // readonly since the potentially-readwrite base will rely on it to
+ // initialize the id image.
+ //
+ //
+ if (!readonly (c) || poly)
+ {
+ os << "static void" << endl
+ << "update (database&, const object_type&";
+
+ if (poly)
+ os << ", bool top = true, bool dyn = true";
+
+ os << ");"
+ << endl;
+
+ if (c.count ("bulk-update"))
+ os << "static void" << endl
+ << "update (database&, const object_type**, std::size_t, " <<
+ "multiple_exceptions&);"
+ << endl;
+ }
+
+ // erase ()
+ //
+ os << "static void" << endl
+ << "erase (database&, const id_type&";
+
+ if (poly)
+ os << ", bool top = true, bool dyn = true";
+
+ os << ");"
+ << endl;
+
+ os << "static void" << endl
+ << "erase (database&, const object_type&";
+
+ if (poly)
+ os << ", bool top = true, bool dyn = true";
+
+ os << ");"
+ << endl;
+
+ if (c.count ("bulk-erase"))
+ {
+ os << "static std::size_t" << endl
+ << "erase (database&, const id_type**, std::size_t, " <<
+ "multiple_exceptions&);"
+ << endl;
+
+ os << "static void" << endl
+ << "erase (database&, const object_type**, std::size_t, " <<
+ "multiple_exceptions&);"
+ << endl;
+ }
+
+ // Sections.
+ //
+ // We treat all polymorphic sections as (potentially) having something
+ // to load or to update since we cannot predict what will be added to
+ // them in overrides.
+ //
+ if (uss.count (user_sections::count_total |
+ user_sections::count_load |
+ (poly ? user_sections::count_load_empty : 0)) != 0)
+ os << "static bool" << endl
+ << "load (connection&, object_type&, section&" <<
+ (poly ? ", const info_type* = 0" : "") << ");"
+ << endl;
+
+ if (uss.count (user_sections::count_total |
+ user_sections::count_update |
+ (poly ? user_sections::count_update_empty : 0)) != 0)
+ os << "static bool" << endl
+ << "update (connection&, const object_type&, const section&" <<
+ (poly ? ", const info_type* = 0" : "") << ");"
+ << endl;
+ }
+
+ // query ()
+ //
+ if (options.generate_query ())
+ {
+ if (!options.omit_unprepared ())
+ {
+ os << "static result<object_type>" << endl
+ << "query (database&, const query_base_type&);"
+ << endl;
+
+ if (multi_dynamic)
+ os << "static result<object_type>" << endl
+ << "query (database&, const odb::query_base&);"
+ << endl;
+ }
+
+ os << "static unsigned long long" << endl
+ << "erase_query (database&, const query_base_type&);"
+ << endl;
+
+ if (multi_dynamic)
+ os << "static unsigned long long" << endl
+ << "erase_query (database&, const odb::query_base&);"
+ << 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;
+
+ if (multi_dynamic)
+ os << "static odb::details::shared_ptr<prepared_query_impl>" << endl
+ << "prepare_query (connection&, const char*, " <<
+ "const odb::query_base&);"
+ << endl;
+
+ os << "static odb::details::shared_ptr<result_impl>" << endl
+ << "execute_query (prepared_query_impl&);"
+ << endl;
+ }
+ }
+
+ object_public_extra_post (c);
+
+ // Implementation details.
+ //
+ os << "public:" << endl;
+
+ if (id != 0)
+ {
+ // Load the object image.
+ //
+ os << "static bool" << endl
+ << "find_ (statements_type&," << endl
+ << "const id_type*";
+
+ if (versioned)
+ os << "," << endl
+ << "const schema_version_migration&";
+
+ if (poly_derived && !abst)
+ os << "," << endl
+ << "std::size_t = depth";
+
+ os << ");"
+ << endl;
+
+ // Load the rest of the object (containers, etc). Expects the id
+ // image in the object statements to be initialized to the object
+ // id.
+ //
+ os << "static void" << endl
+ << "load_ (statements_type&," << endl
+ << "object_type&," << endl
+ << "bool reload";
+
+ if (versioned)
+ os << "," << endl
+ << "const schema_version_migration&";
+
+ if (poly_derived)
+ os << "," << endl
+ << "std::size_t = depth";
+
+ os << ");"
+ << endl;
+ }
+
+ // discriminator_ ()
+ //
+ if (poly && !poly_derived)
+ {
+ os << "static void" << endl
+ << "discriminator_ (statements_type&," << endl
+ << "const id_type&," << endl
+ << "discriminator_type*";
+
+ if (opt != 0)
+ os << "," << endl
+ << "version_type* = 0";
+
+ os << ");"
+ << endl;
+ }
+
+ // Load the dynamic part of the object. Depth inidicates where
+ // the dynamic part starts. Expects the id image in the object
+ // statements to be initialized to the object id. We don't need
+ // it if we are poly-abstract.
+ //
+ if (poly_derived && !abst)
+ os << "static void" << endl
+ << "load_ (database&, root_type&, std::size_t);"
+ << endl;
+
+ // Image chain manipulation.
+ //
+ if (poly && need_image_clone && options.generate_query ())
+ {
+ os << "static root_traits::image_type&" << endl
+ << "root_image (image_type&);"
+ << endl;
+
+ // Note that the original image is non-const since for some databases
+ // the copy "steals" stuff from the original (e.g., LOB descriptors in
+ // Oracle).
+ //
+ os << "static image_type*" << endl
+ << "clone_image (image_type&);"
+ << endl;
+
+ os << "static void" << endl
+ << "copy_image (image_type&, image_type&);"
+ << endl;
+
+ os << "static void" << endl
+ << "free_image (image_type*);"
+ << endl;
+ }
+
+ os << "};";
+
+
+ // object_traits_impl< , id_common>
+ //
+ // 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_common >:" << endl
+ << " public access::object_traits_impl< " << type << ", " <<
+ "id_" << db << " >"
+ << "{"
+ << "};";
+ }
+}
+
+void relational::header::class1::
+traverse_view (type& c)
+{
+ bool versioned (context::versioned (c));
+
+ string const& type (class_fq_name (c));
+ size_t columns (column_count (c).total);
+ size_t obj_count (c.get<size_t> ("object-count"));
+
+ os << "// " << class_name (c) << endl
+ << "//" << endl;
+
+ // view_traits_impl
+ //
+ os << "template <>" << endl
+ << "class " << exp << "access::view_traits_impl< " << type << ", " <<
+ "id_" << db << " >:" << endl
+ << " public access::view_traits< " << type << " >"
+ << "{"
+ << "public:" << endl;
+
+ view_public_extra_pre (c);
+
+ // For dynamic multi-database support also generate common traits
+ // alias (used in query aliasing).
+ //
+ if (multi_dynamic)
+ {
+ os << "typedef access::view_traits_impl< " << type << ", " <<
+ "id_common > common_traits;"
+ << endl;
+ }
+
+ // image_type
+ //
+ image_type_->traverse (c);
+
+ os << "typedef " << db << "::view_statements<view_type> statements_type;"
+ << endl;
+
+ //
+ // Query.
+ //
+
+ // Generate associated object tags here unless we are generating dynamic
+ // multi-database support, in which case they generated in object_traits.
+ //
+ if (!multi_dynamic)
+ {
+ query_tags t; // Not customizable.
+ t.traverse (c);
+ }
+
+ // query_base_type and query_columns (definition generated by class2).
+ //
+ os << "typedef " << db << "::query_base query_base_type;"
+ << "struct query_columns";
+
+ if (obj_count == 0)
+ os << "{"
+ << "};";
+ else
+ os << ";"
+ << endl;
+
+ os << "static const bool versioned = " << versioned << ";"
+ << endl;
+
+ //
+ // Functions.
+ //
+
+ // grow ()
+ //
+ if (generate_grow)
+ {
+ os << "static bool" << endl
+ << "grow (image_type&," << endl
+ << truncated_vector;
+
+ if (versioned)
+ os << "," << endl
+ << "const schema_version_migration&";
+
+ os << ")" << (columns != 0 ? ";\n" : "{}");
+ }
+
+ // bind (image_type)
+ //
+ os << "static void" << endl
+ << "bind (" << bind_vector << "," << endl
+ << "image_type&";
+
+ if (versioned)
+ os << "," << endl
+ << "const schema_version_migration&";
+
+ os << ")" << (columns != 0 ? ";\n" : "{}");
+
+ // init (view, image)
+ //
+ os << "static void" << endl
+ << "init (view_type&," << endl
+ << "const image_type&," << endl
+ << "database*";
+
+ if (versioned)
+ os << "," << endl
+ << "const schema_version_migration&";
+
+ os << ")" << (columns != 0 ? ";\n" : "{}");
+
+ // column_count
+ //
+ os << "static const std::size_t column_count = " << columns << "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 (multi_dynamic)
+ os << "static result<view_type>" << endl
+ << "query (database&, const odb::query_base&);"
+ << 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;
+
+ if (multi_dynamic)
+ os << "static odb::details::shared_ptr<prepared_query_impl>" << endl
+ << "prepare_query (connection&, const char*, " <<
+ "const odb::query_base&);"
+ << 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_common>
+ //
+ if (options.default_database_specified () &&
+ options.default_database () == db)
+ {
+ os << "template <>" << endl
+ << "class access::view_traits_impl< " << type << ", " <<
+ "id_common >:" << endl
+ << " public access::view_traits_impl< " << type << ", " <<
+ "id_" << db << " >"
+ << "{"
+ << "};";
+ }
+}
+
+void relational::header::class1::
+traverse_composite (type& c)
+{
+ bool versioned (context::versioned (c));
+
+ string const& type (class_fq_name (c));
+
+ os << "// " << class_name (c) << endl
+ << "//" << endl;
+
+ // While composite_value_traits is not used directly by user code, we
+ // still need to export it if the generated code for the same database
+ // is split into several DLLs.
+ //
+ os << "template <>" << endl
+ << "class " << exp << "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&," << endl
+ << truncated_vector;
+
+ if (versioned)
+ os << "," << endl
+ << "const schema_version_migration&";
+
+ os << ");"
+ << endl;
+ }
+
+ // bind (image_type)
+ //
+ os << "static void" << endl
+ << "bind (" << bind_vector << "," << endl
+ << "image_type&," << endl
+ << db << "::statement_kind";
+
+ if (versioned)
+ os << "," << endl
+ << "const schema_version_migration&";
+
+ os << ");"
+ << endl;
+
+ // init (image, value)
+ //
+ os << "static " << (generate_grow ? "bool" : "void") << endl
+ << "init (image_type&," << endl
+ << "const value_type&," << endl
+ << db << "::statement_kind";
+
+ if (versioned)
+ os << "," << endl
+ << "const schema_version_migration&";
+
+ os << ");"
+ << endl;
+
+ // init (value, image)
+ //
+ os << "static void" << endl
+ << "init (value_type&," << endl
+ << "const image_type&," << endl
+ << "database*";
+
+ if (versioned)
+ os << "," << endl
+ << "const schema_version_migration&";
+
+ os << ");"
+ << endl;
+
+ if (!has_a (c, test_container))
+ {
+ // get_null (image)
+ //
+ os << "static bool" << endl
+ << "get_null (const image_type&";
+
+ if (versioned)
+ os << "," << endl
+ << "const schema_version_migration&";
+
+ os << ");"
+ << endl;
+
+ // set_null (image)
+ //
+ os << "static void" << endl
+ << "set_null (image_type&," << endl
+ << db << "::statement_kind";
+
+ if (versioned)
+ os << "," << endl
+ << "const schema_version_migration&";
+
+ os << ");"
+ << endl;
+ }
+
+ column_count_type const& cc (column_count (c));
+ os << "static const std::size_t column_count = " << cc.total << "UL;";
+
+ os << "};";
+}
+
+void relational::header::
+generate ()
+{
+ context ctx;
+ ostream& os (ctx.os);
+
+ instance<include> i;
+ i->generate ();
+
+ os << "namespace odb"
+ << "{";
+
+ {
+ traversal::unit unit;
+ traversal::defines unit_defines;
+ typedefs unit_typedefs (false);
+ traversal::namespace_ ns;
+ instance<class1> c;
+
+ unit >> unit_defines >> ns;
+ unit_defines >> c;
+ unit >> unit_typedefs >> c;
+
+ traversal::defines ns_defines;
+ typedefs ns_typedefs (false);
+
+ ns >> ns_defines >> ns;
+ ns_defines >> c;
+ ns >> ns_typedefs >> c;
+
+ unit.dispatch (ctx.unit);
+ }
+
+ {
+ traversal::unit unit;
+ traversal::defines unit_defines;
+ typedefs unit_typedefs (false);
+ traversal::namespace_ ns;
+ instance<class2> c;
+
+ unit >> unit_defines >> ns;
+ unit_defines >> c;
+ unit >> unit_typedefs >> c;
+
+ traversal::defines ns_defines;
+ typedefs ns_typedefs (false);
+
+ ns >> ns_defines >> ns;
+ ns_defines >> c;
+ ns >> ns_typedefs >> c;
+
+ unit.dispatch (ctx.unit);
+ }
+
+ os << "}";
+}