aboutsummaryrefslogtreecommitdiff
path: root/odb
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-01-23 10:53:46 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-01-23 10:53:46 +0200
commit4701df22146e4e4fc0c7fe58903fbd0482defcb5 (patch)
tree502bff26d72ddf0f70513079f33ba9c29c10a28e /odb
parent36863f5f31c202e45c8a406a321deb8d237cbc14 (diff)
Handle name truncation in PostgreSQL
Diffstat (limited to 'odb')
-rw-r--r--odb/context.cxx6
-rw-r--r--odb/context.hxx1
-rw-r--r--odb/options.cli8
-rw-r--r--odb/relational/pgsql/context.cxx75
-rw-r--r--odb/relational/pgsql/context.hxx11
-rw-r--r--odb/relational/pgsql/source.cxx47
6 files changed, 130 insertions, 18 deletions
diff --git a/odb/context.cxx b/odb/context.cxx
index 4af13b7..e56b412 100644
--- a/odb/context.cxx
+++ b/odb/context.cxx
@@ -691,6 +691,12 @@ context (ostream& os_,
data_->sql_name_regex_[sql_name_sequence].assign (s.begin (), s.end ());
}
+ if (ops.statement_regex ().count (db) != 0)
+ {
+ strings const& s (ops.statement_regex ()[db]);
+ data_->sql_name_regex_[sql_name_statement].assign (s.begin (), s.end ());
+ }
+
if (ops.sql_name_regex ().count (db) != 0)
{
strings const& s (ops.sql_name_regex ()[db]);
diff --git a/odb/context.hxx b/odb/context.hxx
index 805691f..9538389 100644
--- a/odb/context.hxx
+++ b/odb/context.hxx
@@ -1191,6 +1191,7 @@ public:
sql_name_index,
sql_name_fkey,
sql_name_sequence,
+ sql_name_statement,
sql_name_count
};
diff --git a/odb/options.cli b/odb/options.cli
index 350bbfc..3e3d070 100644
--- a/odb/options.cli
+++ b/odb/options.cli
@@ -770,6 +770,14 @@ class options
TRANSFORMATIONS section below for details."
};
+ database_map<std::vector<std::string> > --statement-regex
+ {
+ "<regex>",
+ "Add <regex> to the list of regular expressions that is used to
+ transform automatically-derived prepared statement names. See
+ the SQL NAME TRANSFORMATIONS section below for details."
+ };
+
database_map<std::vector<std::string> > --sql-name-regex
{
"<regex>",
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 <cassert>
#include <sstream>
+#include <odb/diagnostics.hxx>
+
#include <odb/sql-token.hxx>
#include <odb/sql-lexer.hxx>
@@ -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.