aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS6
-rw-r--r--doc/odb-epilogue.13
-rw-r--r--doc/odb-epilogue.xhtml7
-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
9 files changed, 142 insertions, 22 deletions
diff --git a/NEWS b/NEWS
index 5ff9359..49e4aa4 100644
--- a/NEWS
+++ b/NEWS
@@ -36,6 +36,12 @@ Version 2.4.0
* Support for calling MySQL stored procedures. For details and limitations
refer to Section 17.7, "MySQL Stored Procedures" in the ODB manual.
+ * New option, --statement-regex, can be used to process prepared statement
+ names that are used by PostgreSQL. This can be useful, for example, to
+ shorten names that exceed the PostgreSQL name limit. To this effect, ODB
+ now also warns when an SQL name exceeds the default PostgreSQL limit of
+ 63 characters.
+
* New option, --oracle-warn-truncation, makes ODB warn about SQL names
that are longer than 30 characters and are therefore truncated. ODB
now also detects when such truncations lead to name conflicts and
diff --git a/doc/odb-epilogue.1 b/doc/odb-epilogue.1
index 6968767..0818bf8 100644
--- a/doc/odb-epilogue.1
+++ b/doc/odb-epilogue.1
@@ -41,8 +41,9 @@ can be
.BR column ,
.BR index ,
.BR fkey ,
+.BR sequence ,
or
-.BR sequence .
+.BR statement .
On the other hand, if we want our regular expressions to apply to all SQL
names, then we use the
.B --sql-name-regex
diff --git a/doc/odb-epilogue.xhtml b/doc/odb-epilogue.xhtml
index da3fdef..c108df8 100644
--- a/doc/odb-epilogue.xhtml
+++ b/doc/odb-epilogue.xhtml
@@ -21,9 +21,10 @@
<code><b>--</b><i>kind</i><b>-regex</b></code> options, where
<code><i>kind</i></code> can be <code><b>table</b></code>,
<code><b>column</b></code>, <code><b>index</b></code>,
- <code><b>fkey</b></code>, or <code><b>sequence</b></code>. On the
- other hand, if we want our regular expressions to apply to all SQL
- names, then we use the <code><b>--sql-name-regex</b></code> option.</p>
+ <code><b>fkey</b></code>, <code><b>sequence</b></code>, or
+ <code><b>statement</b></code>. On the other hand, if we want our
+ regular expressions to apply to all SQL names, then we use the
+ <code><b>--sql-name-regex</b></code> option.</p>
<p>The interaction between the higher and lower level transformations
is as follows. Prefixes and suffixes are added first. Then the
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.