From 823026b58211a4166de06ac243d978dcb9930271 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Mon, 22 Jan 2024 15:58:08 +0300 Subject: Turn odb repository into muti-package repository Also remove the autoconf/make-based build system. --- odb/context.hxx | 1941 ------------------------------------------------------- 1 file changed, 1941 deletions(-) delete mode 100644 odb/context.hxx (limited to 'odb/context.hxx') diff --git a/odb/context.hxx b/odb/context.hxx deleted file mode 100644 index ec4505b..0000000 --- a/odb/context.hxx +++ /dev/null @@ -1,1941 +0,0 @@ -// file : odb/context.hxx -// license : GNU GPL v3; see accompanying LICENSE file - -#ifndef ODB_CONTEXT_HXX -#define ODB_CONTEXT_HXX - -#include - -#include -#include -#include -#include -#include -#include -#include // std::unique_ptr -#include -#include // std::size_t -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -using std::endl; -using std::cerr; - -// Regex. -// -using cutl::re::regex; -using cutl::re::regexsub; -typedef cutl::re::format regex_format; - -typedef std::vector regex_mapping; - -// Forward-declarations. -// -class cxx_string_lexer; - -// Generic exception thrown to indicate a failure when diagnostics -// has already been issued (to stderr). -// -class operation_failed {}; - -// Keep this enum synchronized with the one in libodb/odb/pointer-traits.hxx. -// -enum pointer_kind -{ - pk_raw, - pk_unique, - pk_shared, - pk_weak -}; - -// Keep this enum synchronized with the one in libodb/odb/container-traits.hxx. -// -enum container_kind -{ - ck_ordered, - ck_set, - ck_multiset, - ck_map, - ck_multimap -}; - -// The same as class_kind in libodb/odb/traits.hxx. -// -enum class_kind -{ - class_object, - class_view, - class_composite, - class_other -}; - -// Data member path. -// -// If it is a direct member of an object, then we will have just -// one member. However, if this is a member inside a composite -// value, then we will have a "path" constructed out of members -// that lead all the way from the object member to the innermost -// composite value member. -// -struct data_member_path: std::vector -{ - data_member_path () {} - - explicit - data_member_path (semantics::data_member& m) {push_back (&m);} - - // Return true if this is a sub-path of (or equal to) the - // specified path. - // - bool - sub (const data_member_path& p) const - { - size_t n (p.size ()); - - if (n > size ()) - return false; - - for (size_t i (0); i != n; ++i) - if ((*this)[i] != p[i]) - return false; - - return true; - } -}; - -// Class inheritance chain, from the most derived to base. -// -typedef std::vector class_inheritance_chain; - -// A list of inheritance chains for a data member in an object. -// The first entry in this list would correspond to the object. -// All subsequent entries, if any, correspond to composite -// values. -// -typedef std::vector data_member_scope; - -// -// Semantic graph context types. -// - -// Custom C++ type mapping. -// -struct custom_cxx_type -{ - custom_cxx_type (): type_node (0), as_node (0) {} - - std::string - translate_to (std::string const& v) const {return translate (v, to);} - - std::string - translate_from (std::string const& v) const {return translate (v, from);} - - tree type_node; - std::string type_name; - semantics::type* type; - semantics::names* type_hint; - - tree as_node; - std::string as_name; - semantics::type* as; - semantics::names* as_hint; - - cxx_tokens to; - bool to_move; // Single (?), so can move. - - cxx_tokens from; - bool from_move; // Single (?), so can move. - - location_t loc; - tree scope; // Scope for which this mapping is defined. - -private: - static std::string - translate (std::string const&, const cxx_tokens&); -}; - -typedef std::vector custom_cxx_types; -typedef std::map custom_cxx_type_map; - - -// Object or view pointer. -// -struct class_pointer -{ - std::string name; - tree scope; - location_t loc; -}; - -// -// -struct default_value -{ - enum kind_type - { - reset, // Default value reset. - null, - boolean, // Literal contains value (true or false). - integer, // Integer number. Literal contains sign. - floating, // Floating-point number. - string, // Literal contains value. - enumerator // Literal is the name, enum_value is the tree node. - }; - - kind_type kind; - std::string literal; - - union - { - tree enum_value; - unsigned long long int_value; - double float_value; - }; -}; - -// Database potentially-qualified and unqualifed names. -// -using semantics::relational::qname; -using semantics::relational::uname; - -// Object or table associated with the view. -// -struct view_object -{ - // Return a diagnostic name for this association. It is either the - // alias, unqualified object name, or string representation of the - // table name. - // - std::string - name () const; - - enum kind_type { object, table }; - enum join_type { left, right, full, inner, cross }; - - kind_type kind; - join_type join; - tree obj_node; // Tree node if kind is object. - std::string obj_name; // Name as specified in the pragma if kind is object. - qname tbl_name; // Table name if kind is table. - std::string alias; - tree scope; - location_t loc; - semantics::class_* obj; - semantics::data_member* ptr; // Corresponding object pointer, if any. - - cxx_tokens cond; // Join condition tokens. -}; - -typedef std::vector view_objects; - -// The view_alias_map does not contain entries for tables. -// -typedef std::map view_alias_map; -typedef std::map view_object_map; - -// Collection of relationships via which the objects are joined. -// We need this information to figure out which alias/table -// names to use for columns corresponding to inverse object -// pointers inside objects that this view may be loading. -// -// The first object is the pointer (i.e., the one containing -// this data member) while the other is the pointee. In other -// words, first -> second. We always store the direct (i.e., -// non-inverse) side of the relationship. Note also that there -// could be multiple objects joined using the same relationship. -// -typedef -std::multimap > -view_relationship_map; - -// -// -struct view_query -{ - view_query (): distinct (false), for_update (false) {} - - enum kind_type - { - runtime, - complete_select, // SELECT query. - complete_execute, // Stored procedure call. - condition - }; - - kind_type kind; - std::string literal; - cxx_tokens expr; - tree scope; - location_t loc; - - // Result modifiers (only for condition). - // - bool distinct; // SELECT DISTINCT - bool for_update; // SELECT FOR UPDATE -}; - -// -// -struct table_column -{ - qname table; - std::string column; - bool expr; // True if column is an expression, and therefore should not - // be quoted. - - table_column () {} - - explicit - table_column (const std::string& c): column (c), expr (false) {} -}; - -// -// -struct column_expr_part -{ - enum kind_type - { - literal, - reference - }; - - kind_type kind; - std::string value; - qname table; // Table name/alias for references. - data_member_path member_path; // Path to member for references. - - // Scope and location of this pragma. Used to resolve the member name. - // - tree scope; - location_t loc; -}; - -struct column_expr: std::vector -{ - location_t loc; -}; - -// -// -struct member_access -{ - member_access (const location& l, const char* k, bool s) - : loc (l), kind (k), synthesized (s), by_value (false) {} - - // Return true of we have the (?) placeholder. - // - bool - placeholder () const; - - // Return true if this is a synthesized expression that goes - // directly for the member. - // - bool - direct () const - { - return synthesized && expr.size () == 3; // this.member - } - - bool - empty () const - { - return expr.empty (); - } - - // Issues diagnostics and throws operation_failed if expression is - // empty. - // - std::string - translate (std::string const& obj, - std::string const& val = std::string (), - std::string const& db = std::string ()) const; - - location loc; - const char* kind; // accessor/modifier; used for diagnostics. - bool synthesized; // If true, then this is a synthesized expression. - cxx_tokens expr; - bool by_value; // True if accessor returns by value. False doesn't - // necessarily mean that it is by reference. -}; - -// -// -struct model_version -{ - unsigned long long base; - unsigned long long current; - bool open; -}; - -// Sections. -// -struct object_section -{ - virtual bool - compare (object_section const&) const = 0; - - virtual bool - separate_load () const = 0; - - virtual bool - separate_update () const = 0; -}; - -inline bool -operator== (object_section const& x, object_section const& y) -{ - return x.compare (y); -} - -inline bool -operator!= (object_section const& x, object_section const& y) -{ - return !x.compare (y); -} - -// Main section. -// -struct main_section_type: object_section -{ - virtual bool - compare (object_section const& s) const; - - virtual bool - separate_load () const {return false;} - - virtual bool - separate_update () const {return false;} -}; - -inline bool -operator== (main_section_type const&, main_section_type const&) -{ - return true; // There is only one main section. -} - -extern main_section_type main_section; - -// User-defined section. -// -struct user_section: object_section -{ - enum load_type - { - load_eager, - load_lazy - }; - - enum update_type - { - update_always, - update_change, - update_manual - }; - - enum special_type - { - special_ordinary, - special_version // Fake section for optimistic version update. - }; - - user_section (semantics::data_member& m, - semantics::class_& o, - std::size_t i, - load_type l, - update_type u, - special_type s = special_ordinary) - : member (&m), object (&o), base (0), index (i), - load (l), update (u), special (s), - total (0), inverse (0), readonly (0), versioned (false), - containers (false), readwrite_containers (false), - versioned_containers (false), readwrite_versioned_containers (false) {} - - virtual bool - compare (object_section const& s) const; - - virtual bool - separate_load () const {return load != load_eager;} - - virtual bool - separate_update () const - { - // A separately-loaded section is always separately-updated since - // it might not be loaded when update is requested. - // - return separate_load () || update != update_always; - } - - bool - load_empty () const; - - bool - update_empty () const; - - bool - empty () const - { - return load_empty () && update_empty (); - } - - // A section is optimistic if the object that contains it is optimistic. - // For polymorphic hierarchies, only sections contained in the root are - // considered optimistic. - // - bool - optimistic () const; - - semantics::data_member* member; // Data member of this section. - semantics::class_* object; // Object containing this section. - user_section* base; // Base of this section. - std::size_t index; // Index of this sections. - - load_type load; - update_type update; - special_type special; - - // Column counts. - // - std::size_t total; - std::size_t inverse; - std::size_t readonly; - - bool versioned; - - bool containers; - bool readwrite_containers; - - bool versioned_containers; - bool readwrite_versioned_containers; - - // Total counts across overrides. - // - std::size_t - total_total () const - { - user_section* b (total_base ()); - return total + (b == 0 ? 0 : b->total_total ()); - } - - std::size_t - total_inverse () const - { - user_section* b (total_base ()); - return inverse + (b == 0 ? 0 : b->total_inverse ()); - } - - std::size_t - total_readonly () const - { - user_section* b (total_base ()); - return readonly + (b == 0 ? 0 : b->total_readonly ()); - } - - bool - total_containers () - { - user_section* b (total_base ()); - return containers || (b != 0 && b->total_containers ()); - } - - bool - total_readwrite_containers () - { - user_section* b (total_base ()); - return readwrite_containers || - (b != 0 && b->total_readwrite_containers ()); - } - -private: - user_section* - total_base () const; -}; - -inline bool -operator== (user_section const& x, user_section const& y) -{ - return x.member == y.member; -} - -// Using list for pointer for element stability (see user_section::base). -// -struct user_sections: std::list -{ - // Count sections that have something to load. - // - static unsigned short const count_load = 0x01; - - // Count sections that are non-eager but have nothing to load. - // - static unsigned short const count_load_empty = 0x02; - - // Count sections that have something to update. - // - static unsigned short const count_update = 0x04; - - // Count sections that have nothing to update. - // - static unsigned short const count_update_empty = 0x08; - - // Count sections that are optimistic. - // - static unsigned short const count_optimistic = 0x10; - - // Modifiers: - // - - // Don't exclude fake optimistic version update section from the count. - // - static unsigned short const count_special_version = 0x20; - - // Only count versioned sections. - // - static unsigned short const count_versioned_only = 0x40; - - - // Count all sections, but excluding special. - // - static unsigned short const count_all = count_update | - count_update_empty; - - static unsigned short const count_new = 0x1000; - static unsigned short const count_override = 0x2000; - static unsigned short const count_total = 0x4000; - - std::size_t - count (unsigned short flags) const; - - user_sections (semantics::class_& o): object (&o) {}; - semantics::class_* object; -}; - -// Context. -// -class context -{ -public: - typedef std::size_t size_t; - typedef std::string string; - typedef std::vector strings; - typedef std::ostream ostream; - - typedef ::options options_type; - - static string - upcase (string const&); - -public: - // Return cvr-unqualified base of the type, or type itself, if it is - // not qualified. - // - static semantics::type& - utype (semantics::type&); - - // The same as above, but also returns the name hint for the unqualified - // type. If the original type is already unqualified, then the hint - // argument is not modified. - // - static semantics::type& - utype (semantics::type&, semantics::names*& hint); - - // The same for a member's type but also do custom C++ type translation. - // - static semantics::type& - utype (semantics::data_member& m, const custom_cxx_type** translation = 0) - { - semantics::names* hint (0); - return utype (m, hint, string (), translation); - } - - static semantics::type& - utype (semantics::data_member& m, - string const& key_prefix, - const custom_cxx_type** translation = 0) - { - semantics::names* hint (0); - return utype (m, hint, key_prefix, translation); - } - - // In addition to the unqualified type, this version also returns the - // name hint for this type. If the member type is already unqualified, - // then the hint is from the belongs edge. Otherwise, it is from the - // qualifies edge. - // - static semantics::type& - utype (semantics::data_member&, - semantics::names*& hint, - string const& key_prefix = string (), - const custom_cxx_type** translation = 0); - - static semantics::type& - utype (const data_member_path& mp, const custom_cxx_type** translation = 0) - { - return utype (*mp.back (), translation); - } - - static semantics::type& - utype (const data_member_path& mp, - string const& key_prefix, - const custom_cxx_type** translation = 0) - { - return utype (*mp.back (), key_prefix, translation); - } - - static semantics::type& - utype (const data_member_path& mp, - semantics::names*& hint, - string const& key_prefix = string (), - const custom_cxx_type** translation = 0) - { - return utype (*mp.back (), hint, key_prefix, translation); - } - - // For arrays this function returns true if the (innermost) element - // type is const. - // - static bool - const_type (semantics::type&); - - static bool - const_member (semantics::data_member& m) {return const_type (m.type ());} - - // Form a reference type for a not mapped, actual member type. If - // make_const is true, then add top-level const qualifier, unless - // it is already there. If it is false, then strip it if it is - // already there. If var is not empty, then embed the variable - // name into the type (e.g., char (*v)[3]). If decay_array is - // false then don't decay the (top-level) array to a pointer. - // - static string - member_ref_type (semantics::data_member& m, - bool make_const, - string const& var = "", - bool decay_array = true) - { - return type_ref_type ( - m.type (), m.belongs ().hint (), make_const, var, decay_array); - } - - static string - type_ref_type (semantics::type&, - semantics::names* hint, - bool make_const, - string const& var = "", - bool decay_array = true); - - // Form a value type for a not mapped, actual member type. If make_const - // is true, then add top-level const qualifier, unless it is already - // there. If it is false, then strip it if it is already there. If var is - // not empty, then embed the variable name into the type (e.g., char v[3]). - // - static string - member_val_type (semantics::data_member& m, - bool make_const, - string const& var = "") - { - return type_val_type (m.type (), m.belongs ().hint (), make_const, var); - } - - static string - type_val_type (semantics::type&, - semantics::names* hint, - bool make_const, - string const& var = ""); - - // Member access helpers. Database can be empty. If type is not empty, - // then it should be the non-cvr type of the member (e.g., id_type). - // - void - set_member (semantics::data_member& m, - const std::string& obj, - const std::string& val, - const std::string& db, - const std::string& type = ""); - - void - inc_member (semantics::data_member& m, - const std::string& sobj, // Set expression object. - const std::string& gobj, // Get expression object. - const std::string& type = ""); - -public: - // Resolve data member name in the form "a.b.c" to the data member path, - // issuing diagnostics and throwing operation_filed in case of an error. - // This function stops if it encounters a container leaving lex usable - // to continue parsing. - // - void - resolve_data_members (data_member_path& append, - semantics::class_& scope, - const std::string& name, - const location&, - cxx_string_lexer&); - - data_member_path - resolve_data_members (semantics::class_& scope, - const std::string& name, - const location& l, - cxx_string_lexer& lex) - { - data_member_path r; - resolve_data_members (r, scope, name, l, lex); - return r; - } - - // Predicates. - // -public: - static bool - object (semantics::type& t) - { - return t.count ("object"); - } - - static bool - view (semantics::type& t) - { - return t.count ("view"); - } - - // Direct member of a view. - // - static bool - view_member (semantics::data_member& m) - { - return view (dynamic_cast (m.scope ())); - } - - // Check whether the type is a wrapper. Return the wrapped type if - // it is a wrapper and NULL otherwise. Note that the returned type - // may be cvr-qualified. - // - static semantics::type* - wrapper (semantics::type& t) - { - return t.count ("wrapper") && t.get ("wrapper") - ? t.get ("wrapper-type") - : 0; - } - - static semantics::type* - wrapper (semantics::type& t, semantics::names*& hint) - { - if (t.count ("wrapper") && t.get ("wrapper")) - { - hint = t.get ("wrapper-hint"); - return t.get ("wrapper-type"); - } - else - return 0; - } - - // Composite value type is a class type that was explicitly marked - // as value type and there was no database type mapping provided for - // it by the user (specifying the database type makes the value type - // simple). - // - static bool - composite (semantics::class_& c) - { - if (c.count ("composite-value")) - return c.get ("composite-value"); - else - return composite_ (c); - } - - // Return the class object if this type is a composite value type - // and NULL otherwise. - // - static semantics::class_* - composite (semantics::type& t) - { - semantics::class_* c (dynamic_cast (&t)); - return c != 0 && composite (*c) ? c : 0; - } - - // As above but also "sees through" wrappers. - // - static semantics::class_* - composite_wrapper (semantics::type& t) - { - if (semantics::class_* c = composite (t)) - return c; - else if (semantics::type* wt = wrapper (t)) - return composite (utype (*wt)); - else - return 0; - } - - // Check if a data member is a container. "Sees through" wrappers and - // returns the actual container type or NULL if not a container. - // - // We require data member as input instead of the type because the - // same type (e.g., vector) can be used for both container - // and simple value members. - // - static semantics::type* - container (semantics::data_member& m) - { - // The same type can be used as both a container and a simple value. - // - if (m.count ("simple")) - return 0; - - semantics::type* t (&utype (m)); - - if (semantics::type* wt = wrapper (*t)) - t = &utype (*wt); - - return t->count ("container-kind") ? t : 0; - } - - static semantics::class_* - object_pointer (semantics::type& t) - { - return t.get ("element-type", 0); - } - - // If this data member is or is part of an object pointer, then - // return the member that is the pointer. Otherwise, return 0. - // - static semantics::data_member* - object_pointer (data_member_path const&); - - static semantics::class_* - points_to (semantics::data_member& m) - { - return m.get ("points-to", 0); - } - - static bool - abstract (semantics::class_& c) - { - // If a class is abstract in the C++ sense then it is also abstract in - // the database sense. - // - return c.abstract () || c.count ("abstract"); - } - - static bool - session (semantics::class_& c) - { - return c.get ("session"); - } - - static bool - transient (semantics::data_member& m) - { - return m.count ("transient"); - } - - // Return the deletion version or 0 if not soft-deleted. - // - static unsigned long long - deleted (semantics::class_& c, location_t* l = 0) - { - unsigned long long v (c.get ("deleted", 0)); - - if (v != 0 && l != 0) - *l = c.get ("deleted-location"); - - return v; - } - - static unsigned long long - deleted (semantics::data_member& m, location_t* l = 0) - { - unsigned long long v (m.get ("deleted", 0)); - - if (v != 0 && l != 0) - *l = m.get ("deleted-location"); - - return v; - } - - static unsigned long long - deleted (data_member_path const& mp, location_t* l = 0) - { - unsigned long long r (0); - - // Find the earliest version since this member was deleted. - // - for (data_member_path::const_reverse_iterator i (mp.rbegin ()); - i != mp.rend (); ++i) - { - unsigned long long v ((*i)->get ("deleted", 0)); - if (v != 0 && (r == 0 || v < r)) - { - r = v; - - if (l != 0) - *l = (*i)->get ("deleted-location"); - } - } - - return r; - } - - static semantics::data_member* - deleted_member (data_member_path const& mp) - { - semantics::data_member* m (0); - - // Find the earliest version since this member was deleted. - // - unsigned long long r (0); - for (data_member_path::const_reverse_iterator i (mp.rbegin ()); - i != mp.rend (); ++i) - { - unsigned long long v ((*i)->get ("deleted", 0)); - if (v != 0 && (r == 0 || v < r)) - { - r = v; - m = *i; - } - } - - return m; - } - - // Return the addition version or 0 if not soft-added. - // - static unsigned long long - added (semantics::class_& c) // Used for composite only. - { - return c.get ("added", 0); - } - - static unsigned long long - added (semantics::data_member& m) - { - return m.get ("added", 0); - } - - static unsigned long long - added (data_member_path const& mp) - { - unsigned long long r (0); - - // Find the latest version since this member was added. - // - for (data_member_path::const_reverse_iterator i (mp.rbegin ()); - i != mp.rend (); ++i) - { - unsigned long long v ((*i)->get ("added", 0)); - if (v != 0 && v > r) - r = v; - } - - return r; - } - - static semantics::data_member* - added_member (data_member_path const& mp) - { - semantics::data_member* m (0); - - // Find the latest version since this member was added. - // - unsigned long long r (0); - for (data_member_path::const_reverse_iterator i (mp.rbegin ()); - i != mp.rend (); ++i) - { - unsigned long long v ((*i)->get ("added", 0)); - if (v != 0 && v > r) - { - r = v; - m = *i; - } - } - - return m; - } - - static bool - id (semantics::data_member& m) - { - return m.count ("id"); - } - - // If this data member is or is part of an id member, then return - // the member that is marked as the id. Otherwise, return 0. - // - static semantics::data_member* - id (data_member_path const&); - - static bool - auto_ (semantics::data_member& m) - { - return id (m) && m.count ("auto"); - } - - // Must be a path returned by id(). In other words, it assumes - // the path is to the id member. - // - static bool - auto_ (data_member_path& mp) - { - return mp.front ()->count ("auto"); - } - - // The member scope is used to override readonly status when a readonly - // class (object or composite value) inherits from a readwrite base. - // - static bool - readonly (data_member_path const&, data_member_scope const&); - - static bool - readonly (semantics::data_member&); - - static bool - readonly (semantics::class_& c) - { - return c.count ("readonly"); - } - - // Null-able. - // - bool - null (data_member_path const&) const; - - bool - null (semantics::data_member&) const; - - bool - null (semantics::data_member&, string const& key_prefix) const; - - // Optimistic concurrency. - // - static semantics::data_member* - optimistic (semantics::class_& c) - { - // Set by the validator. - // - return c.get ("optimistic-member", 0); - } - - static bool - version (semantics::data_member& m) - { - return m.count ("version"); - } - - static bool - version (const data_member_path& mp) - { - return mp.size () == 1 && mp.back ()->count ("version"); - } - - // Polymorphic inheritance. Return root of the hierarchy or NULL if - // not polymorphic. - // - static semantics::class_* - polymorphic (semantics::class_& c) - { - // Set by the validator. - // - return c.get ("polymorphic-root", 0); - } - - static semantics::class_& - polymorphic_base (semantics::class_& c) - { - // Set by the validator. - // - return *c.get ("polymorphic-base"); - } - - static size_t - polymorphic_depth (semantics::class_&); - - static bool - discriminator (semantics::data_member& m) - { - return m.count ("discriminator"); - } - - static semantics::data_member* - discriminator (semantics::class_& c) - { - // Set by type processor. - // - return c.get ("discriminator", 0); - } - - // Model version. - // - bool - versioned () const - { - return unit.count ("model-version") != 0; - } - - model_version const& - version () const - { - return unit.get ("model-version"); - } - - // Versioned object, view, or composite. - // - static bool - versioned (semantics::class_& c) - { - // Set by processor. - // - return c.count ("versioned") != 0; - } - - // Versioned container. - // - static bool - versioned (semantics::data_member& m) - { - // Set by processor. - // - return container (m)->count ("versioned"); - } - - // Object sections. - // - static object_section& - section (semantics::data_member& m) - { - object_section* s (m.get ("section", 0)); - return s == 0 ? main_section : *s; - } - - static object_section& - section (data_member_path const& mp) - { - // The direct member of the object specifies the section. If the - // path is empty (which can happen, for example, for a container - // element), assume it is the main section. - // - // - return mp.empty () ? main_section : section (*mp.front ()); - } - - // Member belongs to a section that is loaded separately. - // - static bool - separate_load (semantics::data_member& m) - { - return section (m).separate_load (); - } - - static bool - separate_load (data_member_path const& mp) - { - return section (mp).separate_load (); - } - - // Member belongs to a section that is updated separately. - // - static bool - separate_update (semantics::data_member& m) - { - return section (m).separate_update (); - } - - static bool - separate_update (data_member_path const& mp) - { - return section (mp).separate_update (); - } - - // - // - typedef ::class_kind class_kind_type; - - static class_kind_type - class_kind (semantics::class_&); - - // Return class names. For ordinary classes, this will be the class - // name itself. For class template instantiations this will be the - // typedef name used in the pragma. - // - static string - class_name (semantics::class_&); - - static string - class_fq_name (semantics::class_&); - - // Return class scope. For ordinary classes, this will be the scope - // where the class is defined. For class template instantiations this - // will be the scope of the typedef name used in the pragma. - // - static semantics::scope& - class_scope (semantics::class_&); - - // Return the class file. For ordinary classes, this will be the file - // where the class is defined. For class template instantiations this - // will be the file containing the pragma. - // - static semantics::path - class_file (semantics::class_&); - - // Return the location (as location_t; useful for comparison) of - // an "ODB class" (i.e., an object, view, or composite value), - // taking into account things like definition point overrides, - // etc. - // - location_t - class_location (semantics::class_&); - - // Same as above, but returns "real" location, that is, ignoring - // the definition point overrides. - // - location_t - class_real_location (semantics::class_&); - - // Database names and types. - // -public: - // Schema name for a namespace. - // - qname - schema (semantics::scope&) const; - - // Table name prefix for a namespace. - // - string - table_name_prefix (semantics::scope&) const; - - // - // - struct table_prefix - { - table_prefix (): level (0), derived (false) {} - table_prefix (semantics::class_&); - - void - append (semantics::data_member&); - - qname ns_schema; // Object's namespace schema. - string ns_prefix; // Object's namespace table prefix. - qname prefix; - size_t level; - bool derived; // One of the components in the prefix was derived. - }; - - qname - table_name (semantics::class_&, bool* derived = 0) const; - - qname - table_name (semantics::class_&, data_member_path const&) const; - - // Table name for the container member. The table prefix passed as the - // second argument must include the table prefix specified with the - // --table-prefix option. - // - qname - table_name (semantics::data_member&, table_prefix const&) const; - - string - table_options (semantics::class_&); - - // Table options for the container member. - // - string - table_options (semantics::data_member&, semantics::type& ct); - - // - // - struct column_prefix - { - column_prefix (): derived (false), underscore (false) {} - - column_prefix (semantics::data_member& m, - string const& key_prefix = string (), - string const& default_name = string ()) - : derived (false), underscore (false) - { - append (m, key_prefix, default_name); - } - - // If the last argument is true, the prefix will include the last member - // in the path. - // - column_prefix (data_member_path const&, bool last = false); - - bool - empty () const {return prefix.empty ();} - - void - append (semantics::data_member&, - string const& key_prefix = string (), - string const& default_name = string ()); - - string prefix; - bool derived; // One of the components in the prefix was derived. - bool underscore; // Trailing underscore was automatically added. - }; - - string - column_name (semantics::data_member&, bool& derived) const; - - string - column_name (semantics::data_member&, column_prefix const&) const; - - string - column_name (semantics::data_member&, - string const& key_prefix, - string const& default_name, - bool& derived) const; - - string - column_name (semantics::data_member&, - string const& key_prefix, - string const& default_name, - column_prefix const&) const; - - string - column_name (data_member_path const&) const; - - // - // - string - column_type (const data_member_path&, - string const& key_prefix = string (), - bool id = false); // Pass true if this type is object id other - // than because of the members in the path. - string - column_type (semantics::data_member&, string const& key_prefix = string ()); - - string - column_options (semantics::data_member&); - - string - column_options (semantics::data_member&, string const& key_prefix); - - // Cleaned-up member name that can be used for database names. - // - string - public_name_db (semantics::data_member&) const; - - // Compose the name by inserting/removing an underscore, as necessary. - // - static string - compose_name (string const& prefix, string const& name); - - // SQL name transformations. - // - enum sql_name_type - { - sql_name_all, - sql_name_table, - sql_name_column, - sql_name_index, - sql_name_fkey, - sql_name_sequence, - sql_name_statement, - sql_name_count - }; - - string - transform_name (string const& name, sql_name_type) const; - - // C++ names. - // -public: - // Cleaned-up and potentially escaped member name that can be used - // in public C++ interfaces. - // - string - public_name (semantics::data_member&, bool escape = true) const; - - // "Flatten" fully-qualified C++ name by replacing '::' with '_' - // and removing leading '::', if any. - // - static string - flat_name (string const& fqname); - - // Escape C++ keywords, reserved names, and illegal characters. - // - string - escape (string const&) const; - - // Make C++ include guard name by split words, e.g., "FooBar" to - // "Foo_Bar" and converting everything to upper case. - // - string - make_guard (string const&) const; - - // Return a string literal that can be used in C++ source code. It - // includes "". - // - static string - strlit (string const&); - -public: - // Generate explicit instantiation headers with all the necessary - // extern and export symbols. - // - void - inst_header (bool decl, bool omit_exp = false); - - // Counts and other information. - // -public: - struct column_count_type - { - column_count_type () - : total (0), - id (0), - inverse (0), - readonly (0), - optimistic_managed (0), - discriminator (0), - added (0), - deleted (0), - soft (0), - separate_load (0), - separate_update (0) - { - } - - size_t total; - size_t id; - size_t inverse; - size_t readonly; - size_t optimistic_managed; - size_t discriminator; - - size_t added; // Soft-added. - size_t deleted; // Soft-deleted. - size_t soft; // Soft-added/deleted (a column can be both). - - size_t separate_load; - size_t separate_update; // Only readwrite. - }; - - static column_count_type - column_count (semantics::class_&, object_section* = 0); - - static data_member_path* - id_member (semantics::class_& c) - { - // Set by the processor. May not be there for reuse-abstract - // classes or classes without object id. - // - return c.count ("id-member") ? &c.get ("id-member") : 0; - } - - // Object pointer information. - // -public: - typedef ::pointer_kind pointer_kind_type; - - pointer_kind_type - pointer_kind (semantics::type& p) - { - return p.get ("pointer-kind"); - } - - bool - lazy_pointer (semantics::type& p) - { - return p.get ("pointer-lazy"); - } - - bool - weak_pointer (semantics::type& p) - { - return pointer_kind (p) == pk_weak; - } - - static data_member_path* - inverse (semantics::data_member& m) - { - return object_pointer (utype (m)) && m.count ("inverse") - ? &m.get ("inverse") - : 0; - } - - data_member_path* - inverse (semantics::data_member& m, string const& key_prefix) - { - if (key_prefix.empty ()) - return inverse (m); - - if (!object_pointer (utype (m, key_prefix))) - return 0; - - string k (key_prefix + "-inverse"); - return m.count (k) ? &m.get (k) : 0; - } - - // Container information. - // -public: - typedef ::container_kind container_kind_type; - - static container_kind_type - container_kind (semantics::type& c) - { - return c.get ("container-kind"); - } - - static bool - container_smart (semantics::type& c) - { - return c.get ("container-smart"); - } - - static semantics::type& - container_idt (semantics::data_member& m, const custom_cxx_type** trans = 0) - { - return utype (m, "id", trans); - } - - static semantics::type& - container_vt (semantics::data_member& m, const custom_cxx_type** trans = 0) - { - return utype (m, "value", trans); - } - - static semantics::type& - container_it (semantics::data_member& m, const custom_cxx_type** trans = 0) - { - return utype (m, "index", trans); - } - - static semantics::type& - container_kt (semantics::data_member& m, const custom_cxx_type** trans = 0) - { - return utype (m, "key", trans); - } - - static bool - unordered (semantics::data_member& m) - { - if (m.count ("unordered")) - return true; - - if (semantics::type* c = container (m)) - return c->count ("unordered"); - - return false; - } - - // The 'is a' and 'has a' tests. The has_a() test currently does not - // cross the container boundaries. - // -public: - static unsigned short const test_pointer = 0x01; - static unsigned short const test_eager_pointer = 0x02; - static unsigned short const test_lazy_pointer = 0x04; - static unsigned short const test_container = 0x08; - static unsigned short const test_straight_container = 0x10; - static unsigned short const test_inverse_container = 0x20; - static unsigned short const test_readonly_container = 0x40; - static unsigned short const test_readwrite_container = 0x80; - static unsigned short const test_smart_container = 0x100; - - // Exclude versioned containers. - // - static unsigned short const exclude_versioned = 0x200; - - // Treat eager loaded members as belonging to the main section. - // If this flag is specified, then section must be main_section. - // - static unsigned short const include_eager_load = 0x800; - - // Exclude added/deleted members. - // - static unsigned short const exclude_added = 0x1000; - static unsigned short const exclude_deleted = 0x2000; - - // By default the test goes into bases for non-polymorphic - // hierarchies and doesn't go for polymorphic. The following - // flags can be used to alter this behavior. - // - static unsigned short const exclude_base = 0x4000; - static unsigned short const include_base = 0x8000; - - bool - is_a (data_member_path const& mp, - data_member_scope const& ms, - unsigned short flags) - { - return is_a (mp, ms, flags, utype (*mp.back ()), ""); - } - - bool - is_a (data_member_path const&, - data_member_scope const&, - unsigned short flags, - semantics::type&, - string const& key_prefix); - - // Return the number of matching entities. Can be used as a just - // a bool value (0 means no match). - // - size_t - has_a (semantics::class_&, unsigned short flags, object_section* = 0); - -public: - // Process include path by adding the prefix, putting it through - // the include regex list, and adding opening and closing include - // characters ("" or <>) if necessary. The prefix argument indicates - // whether the include prefix specified with the --include-prefix - // option should be added. The open argument can be used to specify - // the opening character. It can have three values: ", <, or \0. In - // case of \0, the character is determined based on the value of the - // --include-with-bracket option. - // - string - process_include_path (string const&, bool prefix = true, char open = '\0'); - - // Diverge output. - // -public: - void - diverge (std::ostream& os) - { - diverge (os.rdbuf ()); - } - - void - diverge (std::streambuf* sb); - - void - restore (); - - // Implementation details. - // -private: - static bool - composite_ (semantics::class_&); - - template - static X - indirect_value (semantics::context const& c, string const& key) - { - typedef X (*func) (); - std::type_info const& ti (c.type_info (key)); - - if (ti == typeid (func)) - return c.get (key) (); - else - return c.get (key); - } - - static semantics::type* - indirect_type (semantics::context const& c, - string const& kp, - semantics::names*& hint) - { - typedef semantics::type* (*func) (semantics::names*&); - - string const tk (kp + "-tree-type"); - std::type_info const& ti (c.type_info (tk)); - - if (ti == typeid (func)) - return c.get (tk) (hint); - else - { - hint = c.get (kp + "-tree-hint"); - return c.get (tk); - } - } - -public: - typedef std::set keyword_set_type; - - struct db_type_type - { - db_type_type () {} - db_type_type (string const& t, string const& it, bool n) - : type (t), id_type (it), null (n) - { - } - - string type; - string id_type; - bool null; - }; - - struct type_map_type: std::map - { - typedef std::map base; - - const_iterator - find (semantics::type&, semantics::names* hint); - }; - -protected: - struct data - { - virtual - ~data () {} - - data (std::ostream& os) - : extra_ (0), - os_ (os.rdbuf ()), - in_comment_ (false), - top_object_ (0), - cur_object_ (0), - sql_name_upper_ ("(.+)", "\\U$1"), - sql_name_lower_ ("(.+)", "\\L$1") - { - } - - public: - void* extra_; - - std::ostream os_; - std::stack os_stack_; - - bool in_comment_; - - semantics::class_* top_object_; - semantics::class_* cur_object_; - - string exp_; - string ext_; - - keyword_set_type keyword_set_; - type_map_type type_map_; - - regex_mapping sql_name_regex_[sql_name_count]; - regexsub sql_name_upper_; - regexsub sql_name_lower_; - - regex_mapping include_regex_; - regex_mapping accessor_regex_; - regex_mapping modifier_regex_; - }; - - typedef cutl::shared_ptr data_ptr; - data_ptr data_; - -public: - typedef ::features features_type; - - void*& extra; // Extra data that may need to be shared by a sub-system. - - std::ostream& os; - semantics::unit& unit; - options_type const& options; - features_type& features; - database const db; - - bool& in_comment; - - string& exp; // Export symbol (with trailing space if specified). - string& ext; // Extern symbol. - - keyword_set_type const& keyword_set; - - regex_mapping const& include_regex; - regex_mapping const& accessor_regex; - regex_mapping const& modifier_regex; - - bool embedded_schema; - bool separate_schema; - - bool multi_static; - bool multi_dynamic; - - bool force_versioned; // Force statement processing for debugging. - - // Outermost object or view currently being traversed. - // - semantics::class_*& top_object; - - // Object or view currently being traversed. It can be the same as - // top_object or it can a base of top_object. - // - semantics::class_*& cur_object; - - // Per-database customizable functionality. - // -protected: - // Return empty string if there is no mapping. The type passed is - // already cvr-unqualified. The null out argument indicates whether - // the column should allow NULL values by default. - // - string - database_type (semantics::type& t, - semantics::names* hint, - bool id, - bool* null = 0) - { - return current ().database_type_impl (t, hint, id, null); - } - - // The default implementation uses the type map (populated by the database- - // specific context implementation) to come up with a mapping. - // - virtual string - database_type_impl (semantics::type&, semantics::names*, bool, bool*); - -public: - typedef context root_context; - - virtual - ~context (); - context (); - context (std::ostream&, - semantics::unit&, - options_type const&, - features_type&, - data_ptr = data_ptr ()); - - static context& - current () - { - return *current_; - } - -private: - static context* current_; - -#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) - context& - operator= (context const&) = delete; -#else -private: - context& - operator= (context const&); -#endif -}; - -// Create concrete database context. -// -std::unique_ptr -create_context (std::ostream&, - semantics::unit&, - options const&, - features&, - semantics::relational::model*); - -// Checks if scope Y names any of X. -// -template -bool -has (Y& y) -{ - for (semantics::scope::names_iterator i (y.names_begin ()), - e (y.names_end ()); i != e; ++i) - if (i->named (). template is_a ()) - return true; - - return false; -} - -#include - -#endif // ODB_CONTEXT_HXX -- cgit v1.1