summaryrefslogtreecommitdiff
path: root/odb/odb/relational/header.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'odb/odb/relational/header.hxx')
-rw-r--r--odb/odb/relational/header.hxx1466
1 files changed, 1466 insertions, 0 deletions
diff --git a/odb/odb/relational/header.hxx b/odb/odb/relational/header.hxx
new file mode 100644
index 0000000..964aff2
--- /dev/null
+++ b/odb/odb/relational/header.hxx
@@ -0,0 +1,1466 @@
+// file : odb/relational/header.hxx
+// license : GNU GPL v3; see accompanying LICENSE file
+
+#ifndef ODB_RELATIONAL_HEADER_HXX
+#define ODB_RELATIONAL_HEADER_HXX
+
+#include <odb/relational/context.hxx>
+#include <odb/relational/common.hxx>
+
+namespace relational
+{
+ namespace header
+ {
+ //
+ // image_type
+ //
+
+ struct image_member: virtual member_base
+ {
+ typedef image_member base;
+
+ image_member (string const& var = string ())
+ : member_base (var, 0, 0, string (), string ()) {}
+
+ image_member (string const& var,
+ semantics::type& t,
+ const custom_cxx_type* ct,
+ string const& fq_type,
+ string const& key_prefix)
+ : member_base (var, &t, ct, fq_type, key_prefix) {}
+ };
+
+ template <typename T>
+ struct image_member_impl: image_member, virtual member_base_impl<T>
+ {
+ typedef image_member_impl base_impl;
+
+ image_member_impl (base const& x)
+ : member_base::base (x), // virtual base
+ base (x),
+ member_image_type_ (base::type_override_,
+ base::custom_override_,
+ base::fq_type_override_,
+ base::key_prefix_)
+ {
+ }
+
+ typedef typename member_base_impl<T>::member_info member_info;
+
+ using member_base_impl<T>::container;
+
+ virtual bool
+ pre (member_info& mi)
+ {
+ if (container (mi))
+ return false;
+
+ image_type = member_image_type_->image_type (mi.m);
+
+ if (var_override_.empty ())
+ os << "// " << mi.m.name () << endl
+ << "//" << endl;
+
+ return true;
+ }
+
+ virtual void
+ traverse_pointer (member_info& mi)
+ {
+ // Object pointers in views require special treatment.
+ //
+ if (view_member (mi.m))
+ {
+ using semantics::class_;
+
+ class_& c (*mi.ptr);
+ class_* poly_root (polymorphic (c));
+ bool poly_derived (poly_root != 0 && poly_root != &c);
+
+ if (poly_derived)
+ // Use a helper to create a complete chain of images all
+ // the way to the root (see libodb/odb/view-image.hxx).
+ //
+ os << "view_object_image<" << endl
+ << " " << class_fq_name (c) << "," << endl
+ << " " << class_fq_name (*poly_root) << "," << endl
+ << " id_" << db << " >";
+ else
+ os << "object_traits_impl< " << class_fq_name (c) << ", " <<
+ "id_" << db << " >::image_type";
+
+ os << " " << mi.var << "value;"
+ << endl;
+ }
+ else
+ member_base_impl<T>::traverse_pointer (mi);
+ }
+
+ virtual void
+ traverse_composite (member_info& mi)
+ {
+ os << image_type << " " << mi.var << "value;"
+ << endl;
+ }
+
+ protected:
+ string image_type;
+ instance<member_image_type> member_image_type_;
+ };
+
+ struct image_base: traversal::class_, virtual context
+ {
+ typedef image_base base;
+
+ image_base (): first_ (true) {}
+
+ virtual void
+ traverse (type& c)
+ {
+ bool obj (object (c));
+
+ // Ignore transient bases. Not used for views.
+ //
+ if (!(obj || composite (c)))
+ return;
+
+ if (first_)
+ {
+ os << ": ";
+ first_ = false;
+ }
+ else
+ {
+ os << "," << endl
+ << " ";
+ }
+
+ string const& type (class_fq_name (c));
+
+ if (obj)
+ os << "object_traits_impl< " << type << ", id_" << db <<
+ " >::image_type";
+ else
+ os << "composite_value_traits< " << type << ", id_" << db <<
+ " >::image_type";
+ }
+
+ private:
+ bool first_;
+ };
+
+ struct image_type: traversal::class_, virtual context
+ {
+ typedef image_type base;
+
+ image_type ()
+ {
+ *this >> names_member_ >> member_;
+ }
+
+ image_type (image_type const&)
+ : root_context (), context () //@@ -Wextra
+ {
+ *this >> names_member_ >> member_;
+ }
+
+ virtual void
+ image_extra (type&)
+ {
+ }
+
+ virtual void
+ traverse (type& c)
+ {
+ type* poly_root (polymorphic (c));
+ bool poly_derived (poly_root != 0 && poly_root != &c);
+
+ os << "struct image_type";
+
+ if (!view (c))
+ {
+ // Don't go into the base if we are a derived type in a
+ // polymorphic hierarchy.
+ //
+ if (!poly_derived)
+ {
+ instance<image_base> b;
+ traversal::inherits i (*b);
+ inherits (c, i);
+ }
+ }
+
+ os << "{";
+
+ if (poly_derived)
+ os << "base_traits::image_type* base;"
+ << endl;
+
+ names (c);
+
+ // We don't need a version if this is a composite value type
+ // or reuse-abstract object.
+ //
+ if (!(composite (c) || (abstract (c) && !polymorphic (c))))
+ os << "std::size_t version;"
+ << endl;
+
+ image_extra (c);
+
+ os << "};";
+ }
+
+ private:
+ instance<image_member> member_;
+ traversal::names names_member_;
+ };
+
+ // Member-specific traits types for container members.
+ //
+ struct container_traits: object_members_base, virtual context
+ {
+ typedef container_traits base;
+
+ container_traits (semantics::class_& c)
+ : object_members_base (true, false, false), c_ (c)
+ {
+ }
+
+ virtual void
+ traverse_pointer (semantics::data_member&, semantics::class_&)
+ {
+ // We don't want to traverse composite id.
+ }
+
+ virtual void
+ traverse_composite (semantics::data_member* m, semantics::class_& c)
+ {
+ if (object (c_))
+ object_members_base::traverse_composite (m, c);
+ else
+ {
+ // If we are generating traits for a composite value type, then
+ // we don't want to go into its bases or it composite members.
+ //
+ if (m == 0 && &c == &c_)
+ names (c);
+ }
+ }
+
+ virtual void
+ container_public_extra_pre (semantics::data_member&, semantics::type&)
+ {
+ }
+
+ virtual void
+ container_public_extra_post (semantics::data_member&, semantics::type&)
+ {
+ }
+
+ virtual void
+ traverse_container (semantics::data_member& m, semantics::type& c)
+ {
+ using semantics::type;
+ using semantics::class_;
+
+ // Figure out if this member is from a base object or composite
+ // value and if it's from an object, whether it is reuse-abstract.
+ //
+ bool base, reuse_abst;
+
+ if (object (c_))
+ {
+ base = cur_object != &c_ ||
+ !object (dynamic_cast<type&> (m.scope ()));
+ reuse_abst = abstract (c_) && !polymorphic (c_);
+ }
+ else
+ {
+ base = false; // We don't go into bases.
+ reuse_abst = true; // Always abstract.
+ }
+
+ container_kind_type ck (container_kind (c));
+
+ const custom_cxx_type* vct (0);
+ const custom_cxx_type* ict (0);
+ const custom_cxx_type* kct (0);
+
+ type& vt (container_vt (m, &vct));
+ type* it (0);
+ type* kt (0);
+
+ bool ordered (false);
+ bool inverse (context::inverse (m, "value"));
+
+ switch (ck)
+ {
+ case ck_ordered:
+ {
+ if (!unordered (m))
+ {
+ it = &container_it (m, &ict);
+ ordered = true;
+ }
+ break;
+ }
+ case ck_map:
+ case ck_multimap:
+ {
+ kt = &container_kt (m, &kct);
+ break;
+ }
+ case ck_set:
+ case ck_multiset:
+ {
+ break;
+ }
+ }
+
+ bool smart (!inverse &&
+ (ck != ck_ordered || ordered) &&
+ container_smart (c));
+
+ string name (flat_prefix_ + public_name (m) + "_traits");
+
+ // Figure out column counts.
+ //
+ size_t id_columns, value_columns, data_columns, cond_columns;
+ bool versioned (context::versioned (m));
+
+ if (!reuse_abst)
+ {
+ type& idt (container_idt (m));
+
+ if (class_* idc = composite_wrapper (idt))
+ id_columns = column_count (*idc).total;
+ else
+ id_columns = 1;
+
+ data_columns = cond_columns = id_columns;
+
+ switch (ck)
+ {
+ case ck_ordered:
+ {
+ // Add one for the index.
+ //
+ if (ordered)
+ {
+ data_columns++;
+
+ if (smart)
+ cond_columns++;
+ }
+ break;
+ }
+ case ck_map:
+ case ck_multimap:
+ {
+ // Add some for the key.
+ //
+ size_t n;
+
+ class_* ptr (object_pointer (*kt));
+ semantics::type& t (ptr == 0 ? *kt : utype (*id_member (*ptr)));
+
+ if (class_* comp = composite_wrapper (t))
+ n = column_count (*comp).total;
+ else
+ n = 1;
+
+ data_columns += n;
+
+ // Key is not currently used (see also bind()).
+ //
+ // cond_columns += n;
+
+ break;
+ }
+ case ck_set:
+ case ck_multiset:
+ {
+ // Not currently used (see also bind())
+ //
+ // Value is also a key.
+ //
+ // class_* ptr (object_pointer (vt));
+ // semantics::type& t (ptr == 0 ? vt : utype (*id_member (*ptr)));
+ //
+ // if (class_* comp = composite_wrapper (t))
+ // cond_columns += column_count (*comp).total;
+ // else
+ // cond_columns++;
+ //
+ break;
+ }
+ }
+
+ {
+ class_* ptr (object_pointer (vt));
+ semantics::type& t (ptr == 0 ? vt : utype (*id_member (*ptr)));
+
+ if (class_* comp = composite_wrapper (t))
+ value_columns = column_count (*comp).total;
+ else
+ value_columns = 1;
+
+ data_columns += value_columns;
+ }
+
+ // Store column counts for the source generator.
+ //
+ m.set ("id-column-count", id_columns);
+ m.set ("value-column-count", value_columns);
+ m.set ("cond-column-count", cond_columns);
+ m.set ("data-column-count", data_columns);
+ }
+
+ os << "// " << m.name () << endl
+ << "//" << endl
+ << "struct " << exp << name;
+
+ if (base)
+ {
+ semantics::class_& b (dynamic_cast<semantics::class_&> (m.scope ()));
+ string const& type (class_fq_name (b));
+
+ if (object (b))
+ os << ": access::object_traits_impl< " << type << ", id_" <<
+ db << " >::" << name;
+ else
+ os << ": access::composite_value_traits< " << type << ", id_" <<
+ db << " >::" << public_name (m) << "_traits"; // No prefix_.
+ }
+
+ os << "{";
+
+ container_public_extra_pre (m, c);
+
+ if (!reuse_abst)
+ {
+ // column_count
+ //
+ os << "static const std::size_t id_column_count = " <<
+ id_columns << "UL;";
+
+ if (smart)
+ os << "static const std::size_t value_column_count = " <<
+ value_columns << "UL;"
+ << "static const std::size_t cond_column_count = " <<
+ cond_columns << "UL;";
+
+ os << "static const std::size_t data_column_count = " <<
+ data_columns << "UL;"
+ << endl;
+
+ os << "static const bool versioned = " << versioned << ";"
+ << endl;
+
+ // Statements.
+ //
+ os << "static const char insert_statement[];"
+ << "static const char select_statement[];";
+
+ if (smart)
+ os << "static const char update_statement[];";
+
+ os << "static const char delete_statement[];"
+ << endl;
+ }
+
+ if (base)
+ {
+ container_public_extra_post (m, c);
+ os << "};";
+
+ return;
+ }
+
+ // container_type
+ // container_traits
+ // index_type
+ // key_type
+ // value_type
+ //
+ os << "typedef ";
+
+ {
+ semantics::names* hint;
+ semantics::type& t (utype (m, hint));
+
+ if (semantics::type* wt = wrapper (t))
+ {
+ // Use the hint from the wrapper unless the wrapped type is
+ // qualified. In this case use the hint for the unqualified
+ // type.
+ //
+ hint = t.get<semantics::names*> ("wrapper-hint");
+ utype (*wt, hint);
+
+ os << c.fq_name (hint);
+ }
+ else
+ // t and c are the same.
+ //
+ os << t.fq_name (hint);
+ }
+
+ os << " container_type;";
+
+ os << "typedef" << endl
+ << "odb::access::container_traits<container_type>" << endl
+ << "container_traits_type;";
+
+ switch (ck)
+ {
+ case ck_ordered:
+ {
+ os << "typedef container_traits_type::index_type index_type;";
+ break;
+ }
+ case ck_map:
+ case ck_multimap:
+ {
+ os << "typedef container_traits_type::key_type key_type;";
+ }
+ case ck_set:
+ case ck_multiset:
+ {
+ break;
+ }
+ }
+
+ os << "typedef container_traits_type::value_type value_type;"
+ << endl;
+
+ // functions_type
+ //
+ switch (ck)
+ {
+ case ck_ordered:
+ {
+ os << "typedef " << (smart ? "smart_" : "") <<
+ "ordered_functions<index_type, value_type> functions_type;";
+ break;
+ }
+ case ck_map:
+ case ck_multimap:
+ {
+ os << "typedef map_functions<key_type, value_type> " <<
+ "functions_type;";
+ break;
+ }
+ case ck_set:
+ case ck_multiset:
+ {
+ os << "typedef set_functions<value_type> functions_type;";
+ break;
+ }
+ }
+
+ os << "typedef " << db << "::" << (smart ? "smart_" : "")
+ << "container_statements< " << name << " > statements_type;"
+ << endl;
+
+ // cond_image_type (object id is taken from the object image).
+ //
+ // For dumb containers we use the id binding directly.
+ //
+ if (smart)
+ {
+ os << "struct cond_image_type"
+ << "{";
+
+ switch (ck)
+ {
+ case ck_ordered:
+ {
+ if (ordered)
+ {
+ os << "// index" << endl
+ << "//" << endl;
+ instance<image_member> im (
+ "index_", *it, ict, "index_type", "index");
+ im->traverse (m);
+ }
+ break;
+ }
+ case ck_map:
+ case ck_multimap:
+ {
+ os << "// key" << endl
+ << "//" << endl;
+ instance<image_member> im ("key_", *kt, kct, "key_type", "key");
+ im->traverse (m);
+ break;
+ }
+ case ck_set:
+ case ck_multiset:
+ {
+ os << "// value" << endl
+ << "//" << endl;
+ instance<image_member> im (
+ "value_", vt, vct, "value_type", "value");
+ im->traverse (m);
+ break;
+ }
+ }
+
+ os << "std::size_t version;"
+ << "};";
+ }
+
+ // data_image_type (object id is taken from the object image)
+ //
+ os << "struct data_image_type"
+ << "{";
+
+ switch (ck)
+ {
+ case ck_ordered:
+ {
+ if (ordered)
+ {
+ os << "// index" << endl
+ << "//" << endl;
+ instance<image_member> im (
+ "index_", *it, ict, "index_type", "index");
+ im->traverse (m);
+ }
+ break;
+ }
+ case ck_map:
+ case ck_multimap:
+ {
+ os << "// key" << endl
+ << "//" << endl;
+ instance<image_member> im ("key_", *kt, kct, "key_type", "key");
+ im->traverse (m);
+ break;
+ }
+ case ck_set:
+ case ck_multiset:
+ {
+ break;
+ }
+ }
+
+ os << "// value" << endl
+ << "//" << endl;
+ instance<image_member> im ("value_", vt, vct, "value_type", "value");
+ im->traverse (m);
+
+ os << "std::size_t version;"
+ << "};";
+
+ // bind (cond_image)
+ //
+ if (smart)
+ os << "static void" << endl
+ << "bind (" << bind_vector << "," << endl
+ << "const " << bind_vector << " id," << endl
+ << "std::size_t id_size," << endl
+ << "cond_image_type&);"
+ << endl;
+
+ // bind (data_image)
+ //
+ os << "static void" << endl
+ << "bind (" << bind_vector << "," << endl
+ << "const " << bind_vector << " id," << endl
+ << "std::size_t id_size," << endl
+ << "data_image_type&";
+
+ if (versioned)
+ os << "," << endl
+ << "const schema_version_migration&";
+
+ os << ");"
+ << endl;
+
+ // bind (cond_image, data_image) (update)
+ //
+ if (smart)
+ {
+ os << "static void" << endl
+ << "bind (" << bind_vector << "," << endl
+ << "const " << bind_vector << " id," << endl
+ << "std::size_t id_size," << endl
+ << "cond_image_type&," << endl
+ << "data_image_type&";
+
+ if (versioned)
+ os << "," << endl
+ << "const schema_version_migration&";
+
+ os << ");"
+ << endl;
+ }
+
+ // grow ()
+ //
+ if (generate_grow)
+ {
+ os << "static void" << endl
+ << "grow (data_image_type&," << endl
+ << truncated_vector;
+
+ if (versioned)
+ os << "," << endl
+ << "const schema_version_migration&";
+
+ os << ");"
+ << endl;
+ }
+
+ // init (data_image)
+ //
+ if (!inverse)
+ {
+ os << "static void" << endl
+ << "init (data_image_type&," << endl;
+
+ switch (ck)
+ {
+ case ck_ordered:
+ {
+ if (ordered)
+ os << "index_type*," << endl;
+ break;
+ }
+ case ck_map:
+ case ck_multimap:
+ {
+ os << "const key_type*," << endl;
+ break;
+ }
+ case ck_set:
+ case ck_multiset:
+ break;
+ }
+
+ os << "const value_type&";
+
+ if (versioned)
+ os << "," << endl
+ << "const schema_version_migration&";
+
+ os << ");"
+ << endl;
+ }
+
+ // init (cond_image)
+ //
+ if (smart)
+ {
+ os << "static void" << endl;
+
+ switch (ck)
+ {
+ case ck_ordered:
+ {
+ os << "init (cond_image_type&, index_type);";
+ break;
+ }
+ case ck_map:
+ case ck_multimap:
+ {
+ // os << "init (data_image_type&, const key_type&);";
+ break;
+ }
+ case ck_set:
+ case ck_multiset:
+ {
+ // os << "init (data_image_type&, const value_type&);";
+ break;
+ }
+ }
+
+ os << endl;
+ }
+
+ // init (data)
+ //
+ os << "static void" << endl
+ << "init (";
+
+ switch (ck)
+ {
+ case ck_ordered:
+ {
+ if (ordered)
+ os << "index_type&," << endl;
+ break;
+ }
+ case ck_map:
+ case ck_multimap:
+ {
+ os << "key_type&," << endl;
+ break;
+ }
+ case ck_set:
+ case ck_multiset:
+ break;
+ }
+
+ os << "value_type&," << endl;
+ os << "const data_image_type&," << endl
+ << "database*";
+
+ if (versioned)
+ os << "," << endl
+ << "const schema_version_migration&";
+
+ os << ");"
+ << endl;
+
+ // insert
+ //
+ os << "static void" << endl;
+
+ switch (ck)
+ {
+ case ck_ordered:
+ {
+ os << "insert (index_type, const value_type&, void*);";
+ break;
+ }
+ case ck_map:
+ case ck_multimap:
+ {
+ os << "insert (const key_type&, const value_type&, void*);";
+ break;
+ }
+ case ck_set:
+ case ck_multiset:
+ {
+ os << "insert (const value_type&, void*);";
+ break;
+ }
+ }
+
+ os << endl;
+
+ // select
+ //
+ os << "static bool" << endl;
+
+ switch (ck)
+ {
+ case ck_ordered:
+ {
+ os << "select (index_type&, value_type&, void*);";
+ break;
+ }
+ case ck_map:
+ case ck_multimap:
+ {
+ os << "select (key_type&, value_type&, void*);";
+ break;
+ }
+ case ck_set:
+ case ck_multiset:
+ {
+ os << "select (value_type&, void*);";
+ break;
+ }
+ }
+
+ os << endl;
+
+ // update
+ //
+ if (smart)
+ {
+ os << "static void" << endl;
+
+ switch (ck)
+ {
+ case ck_ordered:
+ {
+ os << "update (index_type, const value_type&, void*);";
+ break;
+ }
+ case ck_map:
+ case ck_multimap:
+ {
+ //os << "update (const key_type&, const value_type&, void*);";
+ break;
+ }
+ case ck_set:
+ case ck_multiset:
+ {
+ //os << "update (const value_type&, const value_type&, void*);";
+ break;
+ }
+ }
+
+ os << endl;
+ }
+
+ // delete_
+ //
+ os << "static void" << endl
+ << "delete_ (";
+
+ if (smart)
+ {
+ switch (ck)
+ {
+ case ck_ordered:
+ {
+ os << "index_type, ";
+ break;
+ }
+ case ck_map:
+ case ck_multimap:
+ {
+ break;
+ }
+ case ck_set:
+ case ck_multiset:
+ {
+ break;
+ }
+ }
+ }
+
+ os << "void*);"
+ << endl;
+
+ // persist
+ //
+ if (!inverse)
+ {
+ os << "static void" << endl
+ << "persist (const container_type&," << endl
+ << "statements_type&";
+
+ if (versioned)
+ os << "," << endl
+ << "const schema_version_migration&";
+
+ os << ");"
+ << endl;
+ }
+
+ // load
+ //
+ os << "static void" << endl
+ << "load (container_type&," << endl
+ << "statements_type&";
+
+ if (versioned)
+ os << "," << endl
+ << "const schema_version_migration&";
+
+ os << ");"
+ << endl;
+
+ // update
+ //
+ if (!(inverse || readonly (member_path_, member_scope_)))
+ {
+ os << "static void" << endl
+ << "update (const container_type&," << endl
+ << "statements_type&";
+
+ if (versioned)
+ os << "," << endl
+ << "const schema_version_migration&";
+
+ os << ");"
+ << endl;
+ }
+
+ // erase
+ //
+ if (!inverse)
+ {
+ os << "static void" << endl
+ << "erase (";
+
+ if (smart)
+ os << "const container_type*, ";
+
+ os << "statements_type&);"
+ << endl;
+ }
+
+ container_public_extra_post (m, c);
+
+ os << "};";
+ }
+
+ protected:
+ semantics::class_& c_;
+ };
+
+ //
+ //
+ struct section_traits: virtual context
+ {
+ typedef section_traits base;
+
+ section_traits (semantics::class_& c): c_ (c) {}
+
+ virtual void
+ section_public_extra_pre (user_section&)
+ {
+ }
+
+ virtual void
+ section_public_extra_post (user_section&)
+ {
+ }
+
+ virtual void
+ traverse (user_section& s)
+ {
+ semantics::class_* poly_root (polymorphic (c_));
+ bool poly (poly_root != 0);
+ bool poly_derived (poly && poly_root != &c_);
+
+ semantics::data_member* opt (optimistic (c_));
+
+ // Treat the special version update sections as abstract in reuse
+ // inheritance.
+ //
+ bool reuse_abst (!poly &&
+ (abstract (c_) ||
+ s.special == user_section::special_version));
+
+ bool load (s.total != 0 && s.separate_load ());
+ bool load_con (s.containers && s.separate_load ());
+ bool load_opt (s.optimistic () && s.separate_load ());
+
+ bool update (s.total != s.inverse + s.readonly); // Always separate.
+ bool update_con (s.readwrite_containers);
+ bool update_opt (s.optimistic () && (s.readwrite_containers || poly));
+
+ // Don't generate anything for empty sections.
+ //
+ if (!(load || load_con || load_opt ||
+ update || update_con || update_opt))
+ return;
+
+ // If we are adding a new section to a derived class in an optimistic
+ // hierarchy, then pretend it inherits from the special version update
+ // section.
+ //
+ user_section* rs (0);
+ if (opt != 0)
+ {
+ // Skip overrides and get to the new section if polymorphic.
+ //
+ for (rs = &s; poly && rs->base != 0; rs = rs->base) ;
+
+ if (rs != 0)
+ {
+ if (rs->object != &opt->scope ())
+ rs->base = &(poly ? poly_root : &opt->scope ())->
+ get<user_sections> ("user-sections").back ();
+ else
+ rs = 0;
+ }
+ }
+
+ string name (public_name (*s.member) + "_traits");
+
+ os << "// " << s.member->name () << endl
+ << "//" << endl
+ << "struct " << exp << name
+ << "{";
+
+ os << "typedef object_traits_impl<object_type, id_" << db <<
+ ">::image_type image_type;"
+ << "typedef object_traits_impl<object_type, id_" << db <<
+ ">::id_image_type id_image_type;"
+ << endl;
+
+ section_public_extra_pre (s);
+
+ // bind (id, image_type)
+ //
+ // If id is NULL, then id is ignored (select). Otherwise, it is
+ // copied at the end (update).
+ //
+ if (load || load_opt || update || update_opt)
+ {
+ os << "static std::size_t" << endl
+ << "bind (" << bind_vector << "," << endl
+ << "const " << bind_vector << " id," << endl
+ << "std::size_t id_size," << endl
+ << "image_type&," << endl
+ << db << "::statement_kind";
+
+ if (s.versioned)
+ os << "," << endl
+ << "const schema_version_migration&";
+
+ os << ");"
+ << endl;
+ }
+
+ // grow ()
+ //
+ // We have to have out own version because the truncated vector
+ // will have different number of elements.
+ //
+ if (generate_grow && (load || load_opt))
+ {
+ os << "static bool" << endl
+ << "grow (image_type&," << endl
+ << truncated_vector;
+
+ if (s.versioned)
+ os << "," << endl
+ << "const schema_version_migration&";
+
+ os << ");"
+ << endl;
+ }
+
+ // init (object, image)
+ //
+ if (load)
+ {
+ os << "static void" << endl
+ << "init (object_type&," << endl
+ << "const image_type&," << endl
+ << "database*";
+
+ if (s.versioned)
+ os << "," << endl
+ << "const schema_version_migration&";
+
+ os << ");"
+ << endl;
+ }
+
+ // init (image, object)
+ //
+ if (update)
+ {
+ os << "static " << (generate_grow ? "bool" : "void") << endl
+ << "init (image_type&," << endl
+ << "const object_type&";
+
+ if (s.versioned)
+ os << "," << endl
+ << "const schema_version_migration&";
+
+ os << ");"
+ << endl;
+ }
+
+ // The rest does not apply to reuse-abstract sections.
+ //
+ if (reuse_abst)
+ {
+ section_public_extra_post (s);
+ os << "};";
+ return;
+ }
+
+ // column_count
+ //
+ column_count_type const& cc (column_count (poly ? *poly_root : c_));
+
+ // Generate load and update column counts even when they are zero so
+ // that we can instantiate section_statements.
+ //
+ os << "static const std::size_t id_column_count = " << cc.id << "UL;";
+
+ os << "static const std::size_t managed_optimistic_load_column_count" <<
+ " = " << cc.optimistic_managed << "UL;"
+ << "static const std::size_t load_column_count = " <<
+ (load ? s.total_total () : 0) << "UL;";
+
+ os << "static const std::size_t managed_optimistic_update_column_count" <<
+ " = " << (poly_derived ? 0 : cc.optimistic_managed) << "UL;"
+ << "static const std::size_t update_column_count = " <<
+ (update ? s.total - s.inverse - s.readonly : 0) << "UL;"
+ << endl;
+
+ os << "static const bool versioned = " << s.versioned << ";"
+ << endl;
+
+ // Statements.
+ //
+ if (load || load_opt)
+ os << "static const char select_statement[];"
+ << endl;
+
+ if (update || update_opt)
+ os << "static const char update_statement[];"
+ << endl;
+
+ // Section statements.
+ //
+ if (load || load_opt || update || update_opt)
+ os << "typedef " << db << "::section_statements< object_type, " <<
+ name << " > statements_type;"
+ << endl;
+
+ // We pass statement cache instead of just statements because
+ // we may also need statements for containers.
+ //
+
+ // load ()
+ //
+ if (load || load_opt || load_con)
+ os << "static void" << endl
+ << "load (extra_statement_cache_type&, object_type&" <<
+ (poly ? ", bool top = true" : "") << ");"
+ << endl;
+
+ // update ()
+ //
+ if (update || update_opt || update_con)
+ os << "static void" << endl
+ << "update (extra_statement_cache_type&, const object_type&" <<
+ (poly_derived && s.base != 0 ? ", bool base = true" : "") << ");"
+ << endl;
+
+ section_public_extra_post (s);
+
+ os << "};";
+
+ if (rs != 0)
+ rs->base = 0;
+ }
+
+ protected:
+ semantics::class_& c_;
+ };
+
+ // First pass over objects, views, and composites. Some code must be
+ // split into two parts to deal with yet undefined types.
+ //
+ struct class1: traversal::class_, virtual context
+ {
+ typedef class1 base;
+
+ class1 ()
+ : typedefs_ (false),
+ id_image_member_ ("id_"),
+ version_image_member_ ("version_"),
+ discriminator_image_member_ ("discriminator_"),
+ query_columns_type_ (false, true, false),
+ pointer_query_columns_type_ (true, true, false)
+ {
+ *this >> defines_ >> *this;
+ *this >> typedefs_ >> *this;
+ }
+
+ class1 (class1 const&)
+ : root_context (), //@@ -Wextra
+ context (),
+ typedefs_ (false),
+ id_image_member_ ("id_"),
+ version_image_member_ ("version_"),
+ discriminator_image_member_ ("discriminator_"),
+ query_columns_type_ (false, true, false),
+ pointer_query_columns_type_ (true, true, false)
+ {
+ *this >> defines_ >> *this;
+ *this >> typedefs_ >> *this;
+ }
+
+ virtual void
+ traverse (type& c)
+ {
+ class_kind_type ck (class_kind (c));
+
+ if (ck == class_other ||
+ (!options.at_once () && class_file (c) != unit.file ()))
+ return;
+
+ names (c);
+
+ switch (ck)
+ {
+ case class_object: traverse_object (c); break;
+ case class_view: traverse_view (c); break;
+ case class_composite: traverse_composite (c); break;
+ default: break;
+ }
+ }
+
+ virtual void
+ object_public_extra_pre (type&)
+ {
+ }
+
+ virtual void
+ object_public_extra_post (type&)
+ {
+ }
+
+ virtual void
+ traverse_object (type&);
+
+ virtual void
+ view_public_extra_pre (type&)
+ {
+ }
+
+ virtual void
+ view_public_extra_post (type&)
+ {
+ }
+
+ virtual void
+ traverse_view (type&);
+
+ virtual void
+ traverse_composite (type&);
+
+ private:
+ traversal::defines defines_;
+ typedefs typedefs_;
+
+ instance<image_type> image_type_;
+ instance<image_member> id_image_member_;
+ instance<image_member> version_image_member_;
+ instance<image_member> discriminator_image_member_;
+
+ instance<query_columns_type> query_columns_type_;
+ instance<query_columns_type> pointer_query_columns_type_;
+ };
+
+ // Second pass over objects, views, and composites.
+ //
+ struct class2: traversal::class_, virtual context
+ {
+ typedef class2 base;
+
+ class2 ()
+ : typedefs_ (false),
+ query_columns_type_ (false, true, false),
+ query_columns_type_inst_ (false, false, true),
+ view_query_columns_type_ (true)
+ {
+ *this >> defines_ >> *this;
+ *this >> typedefs_ >> *this;
+ }
+
+ class2 (class2 const&)
+ : root_context (), //@@ -Wextra
+ context (),
+ typedefs_ (false),
+ query_columns_type_ (false, true, false),
+ query_columns_type_inst_ (false, false, true),
+ view_query_columns_type_ (true)
+ {
+ *this >> defines_ >> *this;
+ *this >> typedefs_ >> *this;
+ }
+
+ virtual void
+ traverse (type& c)
+ {
+ class_kind_type ck (class_kind (c));
+
+ if (ck == class_other ||
+ (!options.at_once () && class_file (c) != unit.file ()))
+ return;
+
+ names (c);
+
+ switch (ck)
+ {
+ case class_object: traverse_object (c); break;
+ case class_view: traverse_view (c); break;
+ case class_composite: traverse_composite (c); break;
+ default: break;
+ }
+ }
+
+ virtual void
+ traverse_object (type& c)
+ {
+ if (options.generate_query ())
+ {
+ os << "// " << class_name (c) << endl
+ << "//" << endl;
+
+ // query_columns
+ //
+ // If we don't have any pointers, then query_columns is generated
+ // in pass 1 (see the comment in class1 for details).
+ //
+ if (has_a (c, test_pointer | include_base))
+ query_columns_type_->traverse (c);
+
+ // Generate extern template declarations.
+ //
+ if (multi_dynamic)
+ query_columns_type_inst_->traverse (c);
+ }
+
+ // Move header comment out of if-block if adding any code here.
+ }
+
+ virtual void
+ traverse_view (type& c)
+ {
+ // query_columns
+ //
+ if (c.get<size_t> ("object-count") != 0)
+ {
+ os << "// " << class_name (c) << endl
+ << "//" << endl;
+
+ view_query_columns_type_->traverse (c);
+ }
+
+ // Move header comment out of if-block if adding any code here.
+ }
+
+ virtual void
+ traverse_composite (type&)
+ {
+ }
+
+ private:
+ traversal::defines defines_;
+ typedefs typedefs_;
+
+ instance<query_columns_type> query_columns_type_;
+ instance<query_columns_type> query_columns_type_inst_;
+ instance<view_query_columns_type> view_query_columns_type_;
+ };
+
+ struct include: virtual context
+ {
+ typedef include base;
+
+ virtual void
+ generate ()
+ {
+ os << "#include <odb/details/buffer.hxx>" << endl
+ << endl;
+
+ os << "#include <odb/" << db << "/version.hxx>" << endl
+ << "#include <odb/" << db << "/forward.hxx>" << endl
+ << "#include <odb/" << db << "/binding.hxx>" << endl
+ << "#include <odb/" << db << "/" << db << "-types.hxx>" << endl;
+
+ if (options.generate_query ())
+ {
+ os << "#include <odb/" << db << "/query.hxx>" << endl;
+
+ if (multi_dynamic)
+ os << "#include <odb/" << db << "/query-dynamic.hxx>" << endl;
+ }
+
+ os << endl;
+ }
+ };
+ }
+}
+
+#endif // ODB_RELATIONAL_HEADER_HXX