From e286f8e078a29dec70e4c515d6afa5b000638980 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 27 Feb 2012 12:34:08 +0200 Subject: Add support for specifying table prefix on namespace --- odb/common.cxx | 15 ++++---- odb/context.cxx | 96 ++++++++++++++++++++++++++++++++++++++--------- odb/context.hxx | 12 ++++-- odb/pragma.cxx | 10 ++--- odb/relational/source.hxx | 25 ++++++++---- 5 files changed, 118 insertions(+), 40 deletions(-) diff --git a/odb/common.cxx b/odb/common.cxx index 6261b85..e1aa2d0 100644 --- a/odb/common.cxx +++ b/odb/common.cxx @@ -104,7 +104,8 @@ traverse (semantics::class_& c) if (table_prefix_.level == 0) { - table_prefix_.schema = schema (c.scope ()); + table_prefix_.ns_schema = schema (c.scope ()); + table_prefix_.ns_prefix = table_name_prefix (c.scope ()); table_prefix_.prefix = table_name (c); table_prefix_.prefix += "_"; table_prefix_.level = 1; @@ -120,7 +121,8 @@ traverse (semantics::class_& c) { table_prefix_.level = 0; table_prefix_.prefix.clear (); - table_prefix_.schema.clear (); + table_prefix_.ns_prefix.clear (); + table_prefix_.ns_schema.clear (); } } else @@ -218,6 +220,8 @@ append (semantics::data_member& m, table_prefix& tp) { context& ctx (context::current ()); + assert (tp.level > 0); + // If a custom table prefix was specified, then ignore the top-level // table prefix (this corresponds to a container directly inside an // object) but keep the schema unless the alternative schema is fully @@ -233,14 +237,14 @@ append (semantics::data_member& m, table_prefix& tp) { if (n.qualified ()) { - p = tp.schema; + p = tp.ns_schema; p.append (n.qualifier ()); } else p = tp.prefix.qualifier (); } - p.append (tp.level <= 1 ? ctx.options.table_prefix () : tp.prefix.uname ()); + p.append (tp.level == 1 ? tp.ns_prefix : tp.prefix.uname ()); p += n.uname (); tp.prefix.swap (p); @@ -253,9 +257,6 @@ append (semantics::data_member& m, table_prefix& tp) string name (ctx.public_name_db (m)); size_t n (name.size ()); - if (tp.prefix.empty ()) - tp.prefix.append (ctx.options.table_prefix ()); - tp.prefix += name; if (n != 0 && name[n - 1] != '_') diff --git a/odb/context.cxx b/odb/context.cxx index 15579f3..86cca9d 100644 --- a/odb/context.cxx +++ b/odb/context.cxx @@ -605,17 +605,39 @@ schema (semantics::scope& s) const if (ns->extension ()) ns = &ns->original (); - if (ns->count ("schema")) + bool sf (ns->count ("schema")); + bool tf (ns->count ("table")); + + if (tf) + { + qname n (ns->get ("table")); + tf = n.qualified (); + + // If we have both schema and qualified table prefix, see which + // takes precedence based on order. + // + + if (tf && sf) + { + if (ns->get ("table-location") > + ns->get ("schema-location")) + sf = false; + else + tf = false; + } + } + + if (sf || tf) { - qname n (ns->get ("schema")); + qname n ( + sf + ? ns->get ("schema") + : ns->get ("table").qualifier ()); n.append (r); n.swap (r); - - if (r.fully_qualified ()) - break; } - if (ns->global_scope ()) + if (r.fully_qualified () || ns->global_scope ()) break; } @@ -633,6 +655,45 @@ schema (semantics::scope& s) const return r; } +string context:: +table_name_prefix (semantics::scope& s) const +{ + if (s.count ("table-prefix")) + return s.get ("table-prefix"); + + string r; + + for (semantics::scope* ps (&s);; ps = &ps->scope_ ()) + { + using semantics::namespace_; + + namespace_* ns (dynamic_cast (ps)); + + if (ns == 0) + continue; // Some other scope. + + if (ns->extension ()) + ns = &ns->original (); + + if (ns->count ("table")) + { + qname n (ns->get ("table")); + r = n.uname () + r; + } + + if (ns->global_scope ()) + break; + } + + // Add the prefix that was specified on the command line. + // + if (options.table_prefix_specified ()) + r = options.table_prefix () + r; + + s.set ("table-prefix", r); + return r; +} + qname context:: table_name (semantics::class_& c) const { @@ -679,10 +740,9 @@ table_name (semantics::class_& c) const n.swap (r); } - // Add the table prefix if specified. + // Add the table prefix if any. // - if (options.table_prefix_specified ()) - r.uname () = options.table_prefix () + r.uname (); + r.uname () = table_name_prefix (c.scope ()) + r.uname (); c.set ("qualified-table", r); return r; @@ -691,7 +751,9 @@ table_name (semantics::class_& c) const qname context:: table_name (semantics::class_& obj, data_member_path const& mp) const { - table_prefix tp (schema (obj.scope ()), table_name (obj) + "_", 1); + table_prefix tp (schema (obj.scope ()), + table_name_prefix (obj.scope ()), + table_name (obj) + "_"); if (mp.size () == 1) { @@ -712,15 +774,13 @@ table_name (semantics::class_& obj, data_member_path const& mp) const } } +// The table prefix passed as the second argument must include the table +// prefix specified on namespaces and with the --table-prefix option. +// qname context:: table_name (semantics::data_member& m, table_prefix const& p) const { - // The table prefix passed as the second argument must include - // the table prefix specified with the --table-prefix option. - // - string const& gp (options.table_prefix ()); - assert (p.prefix.uname ().compare (0, gp.size (), gp) == 0); - + assert (p.level > 0); qname r; // If a custom table name was specified, then ignore the top-level @@ -740,14 +800,14 @@ table_name (semantics::data_member& m, table_prefix const& p) const { if (n.qualified ()) { - r = p.schema; + r = p.ns_schema; r.append (n.qualifier ()); } else r = p.prefix.qualifier (); } - r.append (p.level == 1 ? gp : p.prefix.uname ()); + r.append (p.level == 1 ? p.ns_prefix : p.prefix.uname ()); r += n.uname (); } else diff --git a/odb/context.hxx b/odb/context.hxx index 7e62161..3865e88 100644 --- a/odb/context.hxx +++ b/odb/context.hxx @@ -474,6 +474,11 @@ public: qname schema (semantics::scope&) const; + // Table name prefix for a namespace. + // + string + table_name_prefix (semantics::scope&) const; + // // qname @@ -485,10 +490,11 @@ public: struct table_prefix { table_prefix (): level (0) {} - table_prefix (qname const& s, qname const& p, size_t l) - : schema (s), prefix (p), level (l) {} + table_prefix (qname const& ns_s, string const& ns_p, qname const& p) + : ns_schema (ns_s), ns_prefix (ns_p), prefix (p), level (1) {} - qname schema; // Object's namespace schema. + qname ns_schema; // Object's namespace schema. + string ns_prefix; // Object's namespace table prefix. qname prefix; size_t level; }; diff --git a/odb/pragma.cxx b/odb/pragma.cxx index 6c92f0f..010706e 100644 --- a/odb/pragma.cxx +++ b/odb/pragma.cxx @@ -472,13 +472,13 @@ check_spec_decl_type (tree d, } else if (p == "table") { - // Table can be used for both members (container) and types (container, - // object, or view). + // Table can be used for namespaces, members (container), and types + // (container, object, or view). // - if (tc != FIELD_DECL && !TYPE_P (d)) + if (tc != NAMESPACE_DECL && tc != FIELD_DECL && !TYPE_P (d)) { error (l) << "name '" << name << "' in db pragma " << p << " does " - << "not refer to a type or data member" << endl; + << "not refer to a namespace, type, or data member" << endl; return false; } } @@ -612,7 +612,7 @@ handle_pragma (cpp_reader* reader, string const& qualifier, tree decl, string const& decl_name, - bool ns) // True is this is a position namespace pragma. + bool ns) // True if this is a position namespace pragma. { tree t; cpp_ttype tt; diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx index 7f94410..ab5220a 100644 --- a/odb/relational/source.hxx +++ b/odb/relational/source.hxx @@ -118,7 +118,9 @@ namespace relational if (!table_name_.empty ()) { - table_prefix tp (schema (c.scope ()), table_name (c) + "_", 1); + table_prefix tp (schema (c.scope ()), + table_name_prefix (c.scope ()), + table_name (c) + "_"); table = table_qname (*im, tp); } @@ -476,7 +478,9 @@ namespace relational // prefix is just the class table name. // qname const& ct (table_name (c)); - table_prefix tp (schema (c.scope ()), ct + "_", 1); + table_prefix tp (schema (c.scope ()), + table_name_prefix (c.scope ()), + ct + "_"); t = table_qname (*im, tp); // Container's value is our id. @@ -1256,7 +1260,11 @@ namespace relational typedef container_traits base; container_traits (semantics::class_& c) - : object_members_base (true, true, false), c_ (c) + : object_members_base ( + true, + object (c), // Only build table prefix for objects. + false), + c_ (c) { string const& type (class_fq_name (c)); @@ -1431,7 +1439,9 @@ namespace relational // This other container is a direct member of the class so the // table prefix is just the class table name. // - table_prefix tp (schema (c->scope ()), table_name (*c) + "_", 1); + table_prefix tp (schema (c->scope ()), + table_name_prefix (c->scope ()), + table_name (*c) + "_"); inv_table = table_qname (*im, tp); inv_id_cols->traverse (*im, utype (inv_id), "id", "object_id", c); @@ -4629,9 +4639,10 @@ namespace relational // function would have to return a member path instead // of just a single member. // - table_prefix tp (context::schema (vo->obj->scope ()), - table_name (*vo->obj) + "_", - 1); + table_prefix tp ( + context::schema (vo->obj->scope ()), + context::table_name_prefix (vo->obj->scope ()), + table_name (*vo->obj) + "_"); ct = table_qname (*im, tp); } else -- cgit v1.1