summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2023-01-11 14:40:02 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2023-01-11 14:40:02 +0200
commit5652354aa256426c5ab32c4a1c5687e5509af868 (patch)
treeac59964abb8696c12ec4ea71c56e9219dd4245e6
parent2a7a60a29cc72f07263ec7534732141f8869b5ed (diff)
Add support for custom table definition options
-rw-r--r--NEWS4
-rw-r--r--doc/manual.xhtml45
-rw-r--r--odb/context.cxx84
-rw-r--r--odb/context.hxx8
-rw-r--r--odb/relational/model.hxx8
-rw-r--r--odb/relational/mysql/model.cxx34
6 files changed, 175 insertions, 8 deletions
diff --git a/NEWS b/NEWS
index d6b2844..1bd577e 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,10 @@ Version 2.5.0
@@ Ref to the manual.
+ * Support for custom table definition options in addition to column
+ definition options. For details, refer to Section 14.1.16, "options" in
+ the ODB manual.
+
* Support for nested object ids. Now the 'id' pragma specifier can optionally
include the data member path to the id inside a composite value. For
example:
diff --git a/doc/manual.xhtml b/doc/manual.xhtml
index 0b6dc08..fde0a54 100644
--- a/doc/manual.xhtml
+++ b/doc/manual.xhtml
@@ -538,6 +538,7 @@ for consistency.
<tr><th>14.1.13</th><td><a href="#14.1.13"><code>sectionable</code></a></td></tr>
<tr><th>14.1.14</th><td><a href="#14.1.14"><code>deleted</code></a></td></tr>
<tr><th>14.1.15</th><td><a href="#14.1.15"><code>bulk</code></a></td></tr>
+ <tr><th>14.1.16</th><td><a href="#14.1.16"><code>options</code></a></td></tr>
</table>
</td>
</tr>
@@ -14360,6 +14361,12 @@ class person
<td><a href="#14.1.15">14.1.15</a></td>
</tr>
+ <tr>
+ <td><code>options</code></td>
+ <td>database options for a persistent class</td>
+ <td><a href="#14.1.16">14.1.16</a></td>
+ </tr>
+
</table>
<h3><a name="14.1.1">14.1.1 <code>table</code></a></h3>
@@ -15002,6 +15009,39 @@ class employer
is the batch size. For more information on this functionality, refer
to <a href="#15.3">Section 15.3, "Bulk Database Operations"</a>.</p>
+ <h3><a name="14.1.16">14.1.16 <code>options</code></a></h3>
+
+ <p>The <code>options</code> specifier specifies additional table
+ definition options that should be used for the persistent class. For
+ example:</p>
+
+ <pre class="cxx">
+#pragma db object options("PARTITION BY RANGE (age)")
+class person
+{
+ ...
+
+ unsigned short age_;
+};
+ </pre>
+
+ <p>Table definition options for a container table can be specified with
+ the <code>options</code> data member specifier
+ (<a href="#14.4.8">Section 14.4.8, "<code>options</code>"</a>). For
+ example:</p>
+
+ <pre class="cxx">
+#pragma db object
+class person
+{
+ ...
+
+ #pragma db options("PARTITION BY RANGE (index)")
+ std::vector&lt;std::string> aliases_;
+};
+ </pre>
+
+
<h2><a name="14.2">14.2 View Type Pragmas</a></h2>
<p>A pragma with the <code>view</code> qualifier declares a C++ class
@@ -16578,6 +16618,11 @@ class person
};
</pre>
+ <p>Note that if specified for the container member, then instead of the
+ column definition options it specifies the table definition options for
+ the container table (<a href="#14.1.16">Section 14.1.16,
+ "<code>options</code>"</a>).</p>
+
<p>Options can also be specified on the per-type basis
(<a href="#14.3.5">Section 14.3.5, "<code>options</code>"</a>).
By default, options are accumulating. That is, the ODB compiler
diff --git a/odb/context.cxx b/odb/context.cxx
index e220d0e..dd4019a 100644
--- a/odb/context.cxx
+++ b/odb/context.cxx
@@ -2130,6 +2130,90 @@ table_name (semantics::data_member& m, table_prefix const& p) const
return r;
}
+string context::
+table_options (semantics::class_& c)
+{
+ string r;
+
+ // Accumulate options from class.
+ //
+ // @@ Should we also get them from bases?
+ //
+ // @@ Note for some databases (like SQLite), options are seperated with
+ // comma, not space. Likely the same issue in the column_options().
+ //
+ if (c.count ("options"))
+ {
+ strings const& o (c.get<strings> ("options"));
+
+ for (strings::const_iterator i (o.begin ()); i != o.end (); ++i)
+ {
+ if (i->empty ())
+ r.clear ();
+ else
+ {
+ if (!r.empty ())
+ r += ' ';
+
+ r += *i;
+ }
+ }
+ }
+
+ return r;
+}
+
+string context::
+table_options (semantics::data_member& m, semantics::type& c)
+{
+ string r;
+
+ // Accumulate options from container and member.
+ //
+ // @@ Currently there is no way to assign options to the container type. If
+ // we use the value specifier, then it ends up being treated as a value
+ // type. To support this we will probably need to invent the container
+ // specifier.
+ //
+ if (c.count ("options"))
+ {
+ strings const& o (c.get<strings> ("options"));
+
+ for (strings::const_iterator i (o.begin ()); i != o.end (); ++i)
+ {
+ if (i->empty ())
+ r.clear ();
+ else
+ {
+ if (!r.empty ())
+ r += ' ';
+
+ r += *i;
+ }
+ }
+ }
+
+ if (m.count ("options"))
+ {
+ strings const& o (m.get<strings> ("options"));
+
+ for (strings::const_iterator i (o.begin ()); i != o.end (); ++i)
+ {
+ if (i->empty ())
+ r.clear ();
+ else
+ {
+ if (!r.empty ())
+ r += ' ';
+
+ r += *i;
+ }
+ }
+ }
+
+ return r;
+}
+
// context::column_prefix
//
context::column_prefix::
diff --git a/odb/context.hxx b/odb/context.hxx
index d10d555..ec4505b 100644
--- a/odb/context.hxx
+++ b/odb/context.hxx
@@ -1342,6 +1342,14 @@ public:
qname
table_name (semantics::data_member&, table_prefix const&) const;
+ string
+ table_options (semantics::class_&);
+
+ // Table options for the container member.
+ //
+ string
+ table_options (semantics::data_member&, semantics::type& ct);
+
//
//
struct column_prefix
diff --git a/odb/relational/model.hxx b/odb/relational/model.hxx
index b7a07ea..fdfa8fd 100644
--- a/odb/relational/model.hxx
+++ b/odb/relational/model.hxx
@@ -555,9 +555,9 @@ namespace relational
}
virtual string
- table_options (semantics::data_member&, semantics::type&)
+ table_options (semantics::data_member& m, semantics::type& ct)
{
- return "";
+ return context::table_options (m, ct);
}
virtual void
@@ -784,9 +784,9 @@ namespace relational
class_ (sema_rel::model& model): model_ (model) {}
virtual string
- table_options (type&)
+ table_options (type& c)
{
- return "";
+ return context::table_options (c);
}
virtual void
diff --git a/odb/relational/mysql/model.cxx b/odb/relational/mysql/model.cxx
index 2ec9d8b..17ed4c0 100644
--- a/odb/relational/mysql/model.cxx
+++ b/odb/relational/mysql/model.cxx
@@ -110,10 +110,23 @@ namespace relational
member_create (base const& x): base (x) {}
virtual string
- table_options (semantics::data_member&, semantics::type&)
+ table_options (semantics::data_member& m, semantics::type& c)
{
+ string r (relational::member_create::table_options (m, c));
+
string const& engine (options.mysql_engine ());
- return engine != "default" ? "ENGINE=" + engine : "";
+ if (engine != "default")
+ {
+ // Note: MySQL table options can be separated with spaces.
+ //
+ if (!r.empty ())
+ r += ' ';
+
+ r += "ENGINE=";
+ r += engine;
+ }
+
+ return r;
}
};
entry<member_create> member_create_;
@@ -123,10 +136,23 @@ namespace relational
class_ (base const& x): base (x) {}
virtual string
- table_options (type&)
+ table_options (type& c)
{
+ string r (relational::class_::table_options (c));
+
string const& engine (options.mysql_engine ());
- return engine != "default" ? "ENGINE=" + engine : "";
+ if (engine != "default")
+ {
+ // Note: MySQL table options can be separated with spaces.
+ //
+ if (!r.empty ())
+ r += ' ';
+
+ r += "ENGINE=";
+ r += engine;
+ }
+
+ return r;
}
};
entry<class_> class__;