From 4701df22146e4e4fc0c7fe58903fbd0482defcb5 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 23 Jan 2015 10:53:46 +0200 Subject: Handle name truncation in PostgreSQL --- odb/relational/pgsql/context.cxx | 75 ++++++++++++++++++++++++++++++++++++++++ odb/relational/pgsql/context.hxx | 11 ++++++ odb/relational/pgsql/source.cxx | 47 +++++++++++++++---------- 3 files changed, 115 insertions(+), 18 deletions(-) (limited to 'odb/relational') diff --git a/odb/relational/pgsql/context.cxx b/odb/relational/pgsql/context.cxx index 9e91e31..f68ff06 100644 --- a/odb/relational/pgsql/context.cxx +++ b/odb/relational/pgsql/context.cxx @@ -5,6 +5,8 @@ #include #include +#include + #include #include @@ -243,6 +245,79 @@ namespace relational } string context:: + quote_id_impl (qname const& id) const + { + string r; + + bool f (true); + for (qname::iterator i (id.begin ()); i < id.end (); ++i) + { + if (i->empty ()) + continue; + + // Warn if the name is greater than the (NAMEDATALEN - 1) limit, + // which is 63 in the default PG build. + // + if (i->size () > 63) + { + cerr << "warning: SQL name '" << *i << "' is longer than " + << "the default PostgreSQL name limit of 63 characters " + << "and may be truncated" << endl; + + cerr << "info: consider shortening it using #pragma db " + << "table/column/index or --*-regex options" << endl; + } + + if (f) + f = false; + else + r += '.'; + + r += '"'; + r += *i; + r += '"'; + } + + return r; + } + + string context:: + statement_name (string const& type, string const& name, semantics::node& n) + { + // Put the type first so that in the case of truncation it + // remains thus lowering the chance of a clash. + // + string r (type); + r += '_'; + r += name; + + r = transform_name (r, sql_name_statement); + + // Warn if the name is greater than the (NAMEDATALEN - 1) limit, + // which is 63 in the default PG build. + // + // Note that we have to do it in addition to the above since this + // name doesn't go through quote_id(). + // + if (r.size () > 63) + { + location const& l (n.location ()); + + warn (l) << "prepared statement name '" << r << "' is longer than " + << "the default PostgreSQL name limit of 63 characters " + << "and may be truncated" << endl; + + info (l) << "consider shortening the corresponding namespace " + << "name, class name, or data member name" << endl; + + info (l) << "or shortening the statement name itself using the " + << "--statement-regex option" << endl; + } + + return r; + } + + string context:: database_type_impl (semantics::type& t, semantics::names* hint, bool id, diff --git a/odb/relational/pgsql/context.hxx b/odb/relational/pgsql/context.hxx index b7ec873..f3e195c 100644 --- a/odb/relational/pgsql/context.hxx +++ b/odb/relational/pgsql/context.hxx @@ -98,10 +98,21 @@ namespace relational static sql_type parse_sql_type (string, custom_db_types const* = 0); + public: + // Construct statement name from a given type and name. + // + string + statement_name (string const& type, + string const& name, + semantics::node&); + protected: virtual string const& convert_expr (string const&, semantics::data_member&, bool); + virtual string + quote_id_impl (qname const&) const; + virtual bool grow_impl (semantics::class_&, user_section*); diff --git a/odb/relational/pgsql/source.cxx b/odb/relational/pgsql/source.cxx index b625524..b3d934d 100644 --- a/odb/relational/pgsql/source.cxx +++ b/odb/relational/pgsql/source.cxx @@ -765,7 +765,8 @@ namespace relational string traits ("access::object_traits_impl< " + n + ", id_pgsql >"); os << "const char " << traits << "::" << endl - << "persist_statement_name[] = " << strlit (fn + "_persist") << ";" + << "persist_statement_name[] = " << + strlit (statement_name ("persist", fn, c)) << ";" << endl; if (id != 0) @@ -784,37 +785,39 @@ namespace relational os << "," << endl; ostringstream ostr; - ostr << fn << "_find_" << i; - os << strlit (ostr.str ()); + ostr << "find_" << i; + os << strlit (statement_name (ostr.str (), fn, c)); } os << "};"; } else os << "const char " << traits << "::" << endl - << "find_statement_name[] = " << strlit (fn + "_find") << ";" + << "find_statement_name[] = " << + strlit (statement_name ("find", fn, c)) << ";" << endl; if (poly && !poly_derived) os << "const char " << traits << "::" << endl << "find_discriminator_statement_name[] = " << - strlit (fn + "_find_discriminator") << ";" + strlit (statement_name ("find_discriminator", fn, c)) << ";" << endl; if (update_columns != 0) os << "const char " << traits << "::" << endl - << "update_statement_name[] = " << strlit (fn + "_update") << - ";" + << "update_statement_name[] = " << + strlit (statement_name ("update", fn, c)) << ";" << endl; os << "const char " << traits << "::" << endl - << "erase_statement_name[] = " << strlit (fn + "_erase") << ";" + << "erase_statement_name[] = " << + strlit (statement_name ("erase", fn, c)) << ";" << endl; if (optimistic != 0) os << "const char " << traits << "::" << endl << "optimistic_erase_statement_name[] = " << - strlit (fn + "_optimistic_erase") << ";" + strlit (statement_name ("erase_optimistic", fn, c)) << ";" << endl; } @@ -823,11 +826,12 @@ namespace relational if (options.generate_query ()) { os << "const char " << traits << "::" << endl - << "query_statement_name[] = " << strlit (fn + "_query") << ";" + << "query_statement_name[] = " << + strlit (statement_name ("query", fn, c)) << ";" << endl << "const char " << traits << "::" << endl << "erase_query_statement_name[] = " << - strlit (fn + "_erase_query") << ";" + strlit (statement_name ("erase_query", fn, c)) << ";" << endl; } @@ -927,7 +931,8 @@ namespace relational string traits ("access::view_traits_impl< " + n + ", id_pgsql >"); os << "const char " << traits << "::" << endl - << "query_statement_name[] = " << strlit (fn + "_query") << ";" + << "query_statement_name[] = " << + strlit (statement_name ("query", fn, c)) << ";" << endl; } @@ -1026,19 +1031,23 @@ namespace relational class_fq_name (*top_object) + "_" + flat_prefix_ + pn)); os << "const char " << scope << "::" << endl - << "select_name[] = " << strlit (fn + "_select") << ";" + << "select_name[] = " << + strlit (statement_name ("select", fn, m)) << ";" << endl << "const char " << scope << "::" << endl - << "insert_name[] = " << strlit (fn + "_insert") << ";" + << "insert_name[] = " << + strlit (statement_name ("insert", fn, m)) << ";" << endl; if (smart) os << "const char " << scope << "::" << endl - << "update_name[] = " << strlit (fn + "_update") << ";" + << "update_name[] = " << + strlit (statement_name ("update", fn, m)) << ";" << endl; os << "const char " << scope << "::" << endl - << "delete_name[] = " << strlit (fn + "_delete") << ";" + << "delete_name[] = " << + strlit (statement_name ("delete", fn, m)) << ";" << endl; // Statement types. @@ -1209,12 +1218,14 @@ namespace relational if (load || load_opt) os << "const char " << scope << "::" << endl - << "select_name[] = " << strlit (fn + "_select") << ";" + << "select_name[] = " << + strlit (statement_name ("select", fn, *s.member)) << ";" << endl; if (update || update_opt) os << "const char " << scope << "::" << endl - << "update_name[] = " << strlit (fn + "_update") << ";" + << "update_name[] = " << + strlit (statement_name ("update", fn, *s.member)) << ";" << endl; // Statement types. -- cgit v1.1