From 84d9c3f57c35cf9e99e89eeeb6cc4f1c52c3f5a2 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 25 Apr 2011 18:32:22 +0200 Subject: Add support for mapping to database types based on type aliases This allows us to, for example, always map size_t to 64-bit type. The current implementation does not work for containers. It is not clear whether it will be possible to make it work using the GCC AST. --- odb/context.cxx | 24 +++++++---- odb/context.hxx | 9 ++-- odb/relational/mysql/context.cxx | 9 ++-- odb/relational/mysql/context.hxx | 2 +- odb/relational/sqlite/context.cxx | 4 +- odb/relational/sqlite/context.hxx | 2 +- odb/relational/type-processor.cxx | 89 +++++++++++++++++++++++++++++++-------- 7 files changed, 101 insertions(+), 38 deletions(-) diff --git a/odb/context.cxx b/odb/context.cxx index d281090..00edd8d 100644 --- a/odb/context.cxx +++ b/odb/context.cxx @@ -264,23 +264,29 @@ column_type (semantics::data_member& m, string const& kp) string context:: database_type_impl (semantics::type& t, - string const& type, + semantics::names* hint, semantics::context& ctx, column_type_flags f) { - // @@ If I handle additional qualifiers (e.g., NOT NULL, AUTO_INCREMENT) - // separately, then I won't need to pass custom type anymore. + type_map_type::const_iterator end (data_->type_map_.end ()), i (end); + + // First check the hinted name. This allows us to handle things like + // size_t which is nice to map to the same type irrespective of the + // actual type. Since this type can be an alias for the one we are + // interested in, go into nested hints. // - if (!type.empty ()) - return type; + for (; hint != 0 && i == end; hint = hint->hint ()) + { + i = data_->type_map_.find (t.fq_name (hint)); + } - // Don't use the name hint here so that we get the primary name (e.g., + // If the hinted name didn't work, try the primary name (e.g., // ::std::string) instead of a user typedef (e.g., my_string). // - string const& name (t.fq_name ()); - type_map_type::const_iterator i (data_->type_map_.find (name)); + if (i == end) + i = data_->type_map_.find (t.fq_name ()); - if (i != data_->type_map_.end ()) + if (i != end) { string r (ctx.count ("id") ? i->second.id_type : i->second.type); diff --git a/odb/context.hxx b/odb/context.hxx index 9878bcb..84e9f70 100644 --- a/odb/context.hxx +++ b/odb/context.hxx @@ -400,16 +400,15 @@ protected: // static column_type_flags const ctf_default_null = 0x01; - // Return empty string if there is no mapping. The second argument - // is the custom type or empty string if it is not specified. + // Return empty string if there is no mapping. // string database_type (semantics::type& t, - string const& type, + semantics::names* hint, semantics::context& c, column_type_flags f) { - return current ().database_type_impl (t, type, c, f); + return current ().database_type_impl (t, hint, c, f); } // The default implementation uses the type map (populated by the database- @@ -417,7 +416,7 @@ protected: // virtual string database_type_impl (semantics::type&, - string const& type, + semantics::names*, semantics::context&, column_type_flags); diff --git a/odb/relational/mysql/context.cxx b/odb/relational/mysql/context.cxx index 4e31361..aa47b78 100644 --- a/odb/relational/mysql/context.cxx +++ b/odb/relational/mysql/context.cxx @@ -50,7 +50,10 @@ namespace relational {"float", "FLOAT", 0}, {"double", "DOUBLE", 0}, - {"::std::string", "TEXT", "VARCHAR (255)"} + {"::std::string", "TEXT", "VARCHAR (255)"}, + + {"::size_t", "BIGINT UNSIGNED", 0}, + {"::std::size_t", "BIGINT UNSIGNED", 0} }; } @@ -232,11 +235,11 @@ namespace relational string context:: database_type_impl (semantics::type& t, - string const& type, + semantics::names* hint, semantics::context& ctx, column_type_flags f) { - string r (base_context::database_type_impl (t, type, ctx, f)); + string r (base_context::database_type_impl (t, hint, ctx, f)); if (!r.empty ()) return r; diff --git a/odb/relational/mysql/context.hxx b/odb/relational/mysql/context.hxx index cada5d9..019b878 100644 --- a/odb/relational/mysql/context.hxx +++ b/odb/relational/mysql/context.hxx @@ -98,7 +98,7 @@ namespace relational protected: virtual string database_type_impl (semantics::type&, - string const& type, + semantics::names*, semantics::context&, column_type_flags); diff --git a/odb/relational/sqlite/context.cxx b/odb/relational/sqlite/context.cxx index b2b3033..b026822 100644 --- a/odb/relational/sqlite/context.cxx +++ b/odb/relational/sqlite/context.cxx @@ -198,11 +198,11 @@ namespace relational string context:: database_type_impl (semantics::type& t, - string const& type, + semantics::names* hint, semantics::context& ctx, column_type_flags f) { - string r (base_context::database_type_impl (t, type, ctx, f)); + string r (base_context::database_type_impl (t, hint, ctx, f)); if (!r.empty ()) return r; diff --git a/odb/relational/sqlite/context.hxx b/odb/relational/sqlite/context.hxx index 621c549..c625069 100644 --- a/odb/relational/sqlite/context.hxx +++ b/odb/relational/sqlite/context.hxx @@ -50,7 +50,7 @@ namespace relational protected: virtual string database_type_impl (semantics::type&, - string const& type, + semantics::names*, semantics::context&, column_type_flags); public: diff --git a/odb/relational/type-processor.cxx b/odb/relational/type-processor.cxx index 5c86b10..f7b0b2a 100644 --- a/odb/relational/type-processor.cxx +++ b/odb/relational/type-processor.cxx @@ -130,12 +130,15 @@ namespace relational if (type.empty () && idt.count ("type")) type = idt.get ("type"); - column_type_flags f (ctf_none); + if (type.empty ()) + { + column_type_flags f (ctf_none); - if (null_pointer (m)) - f |= ctf_default_null; + if (null_pointer (m)) + f |= ctf_default_null; - type = database_type (idt, type, id, f); + type = database_type (idt, id.belongs ().hint (), id, f); + } } else { @@ -145,7 +148,8 @@ namespace relational if (type.empty () && t.count ("type")) type = t.get ("type"); - type = database_type (t, type, m, ctf_none); + if (type.empty ()) + type = database_type (t, m.belongs ().hint (), m, ctf_none); } if (!type.empty ()) @@ -176,6 +180,7 @@ namespace relational void process_container_value (semantics::type& t, + semantics::names* hint, semantics::data_member& m, string const& prefix, bool obj_ptr) @@ -215,19 +220,23 @@ namespace relational if (type.empty () && idt.count ("type")) type = idt.get ("type"); - column_type_flags f (ctf_none); + if (type.empty ()) + { + column_type_flags f (ctf_none); - if (null_pointer (m, prefix)) - f |= ctf_default_null; + if (null_pointer (m, prefix)) + f |= ctf_default_null; - type = database_type (idt, type, id, f); + type = database_type (idt, id.belongs ().hint (), id, f); + } } else { if (type.empty () && t.count ("type")) type = t.get ("type"); - type = database_type (t, type, m, ctf_none); + if (type.empty ()) + type = database_type (t, hint, m, ctf_none); } if (!type.empty ()) @@ -270,16 +279,27 @@ namespace relational semantics::type* it (0); semantics::type* kt (0); + semantics::names* vh (0); + semantics::names* ih (0); + semantics::names* kh (0); + if (t.count ("container")) { ck = t.get ("container-kind"); vt = t.get ("value-tree-type"); + vh = t.get ("value-tree-hint"); if (ck == ck_ordered) + { it = t.get ("index-tree-type"); + ih = t.get ("index-tree-hint"); + } if (ck == ck_map || ck == ck_multimap) + { kt = t.get ("key-tree-type"); + kh = t.get ("key-tree-hint"); + } } else { @@ -358,8 +378,19 @@ namespace relational throw generation_failed (); tree type (TYPE_MAIN_VARIANT (TREE_TYPE (decl))); - vt = &dynamic_cast (*unit.find (type)); + + // Find the hint. + // + for (tree ot (DECL_ORIGINAL_TYPE (decl)); + ot != 0; + ot = decl ? DECL_ORIGINAL_TYPE (decl) : 0) + { + if ((vh = unit.find_hint (ot))) + break; + + decl = TYPE_NAME (ot); + } } catch (generation_failed const&) { @@ -371,7 +402,7 @@ namespace relational } t.set ("value-tree-type", vt); - + t.set ("value-tree-hint", vh); // Get the index type for ordered containers. // @@ -387,8 +418,19 @@ namespace relational throw generation_failed (); tree type (TYPE_MAIN_VARIANT (TREE_TYPE (decl))); - it = &dynamic_cast (*unit.find (type)); + + // Find the hint. + // + for (tree ot (DECL_ORIGINAL_TYPE (decl)); + ot != 0; + ot = decl ? DECL_ORIGINAL_TYPE (decl) : 0) + { + if ((ih = unit.find_hint (ot))) + break; + + decl = TYPE_NAME (ot); + } } catch (generation_failed const&) { @@ -400,6 +442,7 @@ namespace relational } t.set ("index-tree-type", it); + t.set ("index-tree-hint", ih); } // Get the key type for maps. @@ -416,8 +459,19 @@ namespace relational throw generation_failed (); tree type (TYPE_MAIN_VARIANT (TREE_TYPE (decl))); - kt = &dynamic_cast (*unit.find (type)); + + // Find the hint. + // + for (tree ot (DECL_ORIGINAL_TYPE (decl)); + ot != 0; + ot = decl ? DECL_ORIGINAL_TYPE (decl) : 0) + { + if ((kh = unit.find_hint (ot))) + break; + + decl = TYPE_NAME (ot); + } } catch (generation_failed const&) { @@ -429,6 +483,7 @@ namespace relational } t.set ("key-tree-type", kt); + t.set ("key-tree-hint", kh); } } @@ -437,13 +492,13 @@ namespace relational m.set ("id-tree-type", &id_tree_type); m.set ("id-column-type", &id_column_type); - process_container_value (*vt, m, "value", true); + process_container_value (*vt, vh, m, "value", true); if (it != 0) - process_container_value (*it, m, "index", false); + process_container_value (*it, ih, m, "index", false); if (kt != 0) - process_container_value (*kt, m, "key", false); + process_container_value (*kt, kh, m, "key", false); // If this is an inverse side of a bidirectional object relationship // and it is an ordered container, mark it as unordred since there is -- cgit v1.1