aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2012-04-26 11:29:05 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2012-04-26 11:29:05 +0200
commit8e046e3ea7e88f872205c2b65cb7f9b86aaabd93 (patch)
treeaba1ae331454eb1e0cf9525faf8a084d3652bda0
parent6c88333c2e0232aed9e0b3c9077306f09e36c65c (diff)
Make session optional
-rw-r--r--NEWS8
-rw-r--r--doc/manual.xhtml136
-rw-r--r--odb/context.hxx6
-rw-r--r--odb/features.hxx1
-rw-r--r--odb/header.cxx5
-rw-r--r--odb/options.cli11
-rw-r--r--odb/pragma.cxx47
-rw-r--r--odb/relational/header.cxx40
-rw-r--r--odb/relational/processor.cxx66
-rw-r--r--odb/relational/source.hxx2
-rw-r--r--odb/validator.cxx37
11 files changed, 310 insertions, 49 deletions
diff --git a/NEWS b/NEWS
index 44f4ffa..61dd006 100644
--- a/NEWS
+++ b/NEWS
@@ -50,6 +50,14 @@ Version 1.9.0
but one is not used. For more information, refer to Section 6.2,
"Bidirectional Relationships" in the ODB manual.
+ * Session support is now optional and is disabled by default. This is a
+ backwards-incompatible change. Session support can be enabled on the
+ per object basis or at the namespace level using the new session pragma.
+ It can also be enabled by default for all the objects using the
+ --generate-session ODB compiler option. Thus to get the old behavior
+ where all the objects were session-enabled, simply add --generate-session
+ to your ODB compiler command line.
+
Version 1.8.0
* Support for the Microsoft SQL Server database. The provided connection
diff --git a/doc/manual.xhtml b/doc/manual.xhtml
index cad568c..766844f 100644
--- a/doc/manual.xhtml
+++ b/doc/manual.xhtml
@@ -457,6 +457,7 @@ for consistency.
<tr><th>12.1.7</th><td><a href="#12.1.7"><code>callback</code></a></td></tr>
<tr><th>12.1.8</th><td><a href="#12.1.8"><code>schema</code></a></td></tr>
<tr><th>12.1.9</th><td><a href="#12.1.9"><code>polymorphic</code></a></td></tr>
+ <tr><th>12.1.10</th><td><a href="#12.1.10"><code>session</code></a></td></tr>
</table>
</td>
</tr>
@@ -535,6 +536,7 @@ for consistency.
<tr><th>12.5.1</th><td><a href="#12.5.1"><code>pointer</code></a></td></tr>
<tr><th>12.5.2</th><td><a href="#12.5.2"><code>table</code></a></td></tr>
<tr><th>12.5.3</th><td><a href="#12.5.3"><code>schema</code></a></td></tr>
+ <tr><th>12.5.4</th><td><a href="#12.5.4"><code>session</code></a></td></tr>
</table>
</td>
</tr>
@@ -6090,8 +6092,10 @@ class person
<p>However, a value type that can be used as an object id has a number
of restrictions. Such a value type cannot have container, object
pointer, or read-only data members. It also must be
- default-constructible and implement the less-than comparison operator
- (<code>operator&lt;</code>).</p>
+ default-constructible. Furthermore, if the persistent class in which
+ this composite value type is used as object id has session support
+ enabled (<a href="#10">Chapter 10, "Session"</a>), then it must also
+ implement the less-than comparison operator (<code>operator&lt;</code>).</p>
<h3><a name="7.2.2">7.2.2 Composite Value Column and Table Names</a></h3>
@@ -6848,6 +6852,11 @@ class contractor: public person
};
</pre>
+ <p>Similarly, if we enable or disable session support
+ (<a href="#10">Chapter 10, "Session"</a>) for the root class, then
+ the ODB compiler will automatically enable or disable it for all
+ the derived classes.</p>
+
<p>For polymorphic persistent classes, all the database operations can
be performed on objects with different static and dynamic types.
Similarly, operations that load persistent objects from the
@@ -8258,6 +8267,50 @@ struct employee_name
object cache. In future versions it will provide additional
functionality, such as automatic object state change tracking.</p>
+ <p>Session support is optional and can be enabled or disabled on the
+ per object basis using the <code>db&nbsp;session</code> pragma, for
+ example:</p>
+
+ <pre class="c++">
+#pragma db object session
+class person
+{
+ ...
+};
+ </pre>
+
+ <p>We can also enable or disable session support for a group of
+ objects at the namespace level:</p>
+
+ <pre class="c++">
+#pragma db namespace session
+namespace accounting
+{
+ #pragma db object // Session support is enabled.
+ class employee
+ {
+ ...
+ };
+
+ #pragma db object session(false) // Session support is disabled.
+ class employer
+ {
+ ...
+ };
+}
+ </pre>
+
+ <p>Finally, we can pass the <code>--generate-session</code> ODB compiler
+ option to enable session support by default. With this option session
+ support will be enabled for all the persistent classes except those
+ for which it was explicitly disabled using the
+ <code>db&nbsp;session</code>. An alternative to this method with the
+ same effect is to enable session support for the global namespace:</p>
+
+ <pre class="c++">
+#pragma db namespace() session
+ </pre>
+
<p>Each thread of execution in an application can have only one active
session at a time. A session is started by creating an instance of
the <code>odb::session</code> class and is automatically terminated
@@ -8374,8 +8427,8 @@ namespace odb
<h2><a name="10.1">10.1 Object Cache</a></h2>
- <p>A session is an object cache. Every time an object is made persistent
- by calling the <code>database::persist()</code> function
+ <p>A session is an object cache. Every time a session-enabled object is
+ made persistent by calling the <code>database::persist()</code> function
(<a href="#3.7">Section 3.7, "Making Objects Persistent"</a>), loaded
by calling the <code>database::load()</code> or <code>database::find()</code>
function (<a href="#3.8">Section 3.8, "Loading Persistent Objects"</a>),
@@ -8991,6 +9044,12 @@ class person
<td><a href="#12.1.9">12.1.9</a></td>
</tr>
+ <tr>
+ <td><code>session</code></td>
+ <td>enable/disable session support for a persistent class</td>
+ <td><a href="#12.1.10">12.1.10</a></td>
+ </tr>
+
</table>
<h3><a name="12.1.1">12.1.1 <code>table</code></a></h3>
@@ -9549,6 +9608,38 @@ class employee
class is polymorphic. For more information on polymorphism support,
refer to <a href="#8">Chapter 8, "Inheritance"</a>.</p>
+ <h3><a name="12.1.10">12.1.10 <code>session</code></a></h3>
+
+ <p>The <code>session</code> specifier specifies whether to enable
+ session support for a persistent class. For example:</p>
+
+ <pre class="c++">
+#pragma db object session // Enable.
+class person
+{
+ ...
+};
+
+#pragma db object session(true) // Enable.
+class employee
+{
+ ...
+};
+
+#pragma db object session(false) // Disable.
+class employer
+{
+ ...
+};
+ </pre>
+
+ <p>Session support is disabled by default unless the
+ <code>--generate-session</code> ODB compiler option is specified
+ or session support is enabled at the namespace level
+ (<a href="#12.5.4">Section 12.5.4, "<code>session</code>"</a>).
+ For more information on sessions, refer to <a href="#10">Chapter
+ 10, "Session"</a>.</p>
+
<h2><a name="12.2">12.2 View Type Pragmas</a></h2>
<p>A pragma with the <code>view</code> qualifier declares a C++ class
@@ -11380,6 +11471,12 @@ namespace test
<td><a href="#12.5.3">12.5.3</a></td>
</tr>
+ <tr>
+ <td><code>session</code></td>
+ <td>enable/disable session support for persistent classes inside a namespace</td>
+ <td><a href="#12.5.4">12.5.4</a></td>
+ </tr>
+
</table>
<h3><a name="12.5.1">12.5.1 <code>pointer</code></a></h3>
@@ -11507,6 +11604,37 @@ class employer
For more information on specifying a database schema refer to
<a href="#12.1.8">Section 12.1.8, "<code>schema</code>"</a>.</p>
+ <h3><a name="12.5.4">12.5.4 <code>session</code></a></h3>
+
+ <p>The <code>session</code> specifier specifies whether to enable
+ session support for persistent classes inside a namespace. For
+ example:</p>
+
+ <pre class="c++">
+#pragma db namespace session
+namespace hr
+{
+ #pragma db object // Enabled.
+ class employee
+ {
+ ...
+ };
+
+ #pragma db object session(false) // Disabled.
+ class employer
+ {
+ ...
+ };
+}
+ </pre>
+
+ <p>Session support is disabled by default unless the
+ <code>--generate-session</code> ODB compiler option is specified.
+ Session support specified at the namespace level can be overridden
+ on the per object basis (<a href="#12.1.10">Section 12.1.10,
+ "<code>session</code>"</a>). For more information on sessions,
+ refer to <a href="#10">Chapter 10, "Session"</a>.</p>
+
<h2><a name="12.6">12.6 C++ Compiler Warnings</a></h2>
<p>When a C++ header file defining persistent classes and containing
diff --git a/odb/context.hxx b/odb/context.hxx
index cdb49ac..2bb91cb 100644
--- a/odb/context.hxx
+++ b/odb/context.hxx
@@ -381,6 +381,12 @@ public:
}
static bool
+ session (semantics::class_& c)
+ {
+ return c.get<bool> ("session");
+ }
+
+ static bool
transient (semantics::data_member& m)
{
return m.count ("transient");
diff --git a/odb/features.hxx b/odb/features.hxx
index 0468acb..359d99e 100644
--- a/odb/features.hxx
+++ b/odb/features.hxx
@@ -18,6 +18,7 @@ struct features
bool simple_object;
bool polymorphic_object;
bool no_id_object;
+ bool session_object;
bool view;
};
diff --git a/odb/header.cxx b/odb/header.cxx
index a2b3b96..8e6718d 100644
--- a/odb/header.cxx
+++ b/odb/header.cxx
@@ -46,6 +46,11 @@ namespace header
os << "#include <odb/container-traits.hxx>" << endl;
+ if (ctx.features.session_object)
+ os << "#include <odb/cache-traits.hxx>" << endl;
+ else
+ os << "#include <odb/no-op-cache-traits.hxx>" << endl;
+
if (ctx.features.polymorphic_object)
os << "#include <odb/polymorphic-info.hxx>" << endl;
diff --git a/odb/options.cli b/odb/options.cli
index 95a5d4c..d205039 100644
--- a/odb/options.cli
+++ b/odb/options.cli
@@ -54,8 +54,15 @@ class options
bool --generate-query | -q
{
- "Generate query support code. Without this support you cannot use
- views and can only load objects via their ids."
+ "Generate query support code. Without this support you cannot use views
+ and can only load objects via their ids."
+ };
+
+ bool --generate-session | -e
+ {
+ "Generate session support code. With this option session support will
+ be enabled by default for all the persistent classes except those for
+ which it was explicitly disabled using the \cb{db session} pragma."
};
bool --generate-schema | -s
diff --git a/odb/pragma.cxx b/odb/pragma.cxx
index 698551a..e2dc4cc 100644
--- a/odb/pragma.cxx
+++ b/odb/pragma.cxx
@@ -493,6 +493,17 @@ check_spec_decl_type (tree d,
return false;
}
}
+ else if (p == "session")
+ {
+ // Session can be used only for namespaces and objects.
+ //
+ if (tc != NAMESPACE_DECL && !CLASS_TYPE_P (d))
+ {
+ error (l) << "name '" << name << "' in db pragma " << p << " does "
+ << "not refer to a namespace or class" << endl;
+ return false;
+ }
+ }
else if (p == "schema")
{
// For now schema can be used only for namespaces and objects.
@@ -727,6 +738,42 @@ handle_pragma (cpp_reader* reader,
tt = pragma_lex (&t);
}
+ else if (p == "session")
+ {
+ // session
+ // session (true|false)
+ //
+
+ // Make sure we've got the correct declaration type.
+ //
+ if (decl != 0 && !check_spec_decl_type (decl, decl_name, p, loc))
+ return;
+
+ tt = pragma_lex (&t);
+
+ if (tt == CPP_OPEN_PAREN)
+ {
+ tt = pragma_lex (&t);
+
+ string s;
+ if (tt != CPP_NAME ||
+ ((s = IDENTIFIER_POINTER (t)) != "true" && s != "false"))
+ {
+ error () << "true or false expected in db pragma " << p << endl;
+ return;
+ }
+
+ tt = pragma_lex (&t);
+ if (tt != CPP_CLOSE_PAREN)
+ {
+ error () << "')' expected at the end of db pragma " << p << endl;
+ return;
+ }
+
+ val = (s == "true");
+ tt = pragma_lex (&t);
+ }
+ }
else if (p == "schema")
{
// schema (<name>)
diff --git a/odb/relational/header.cxx b/odb/relational/header.cxx
index 46ba722..48bca91 100644
--- a/odb/relational/header.cxx
+++ b/odb/relational/header.cxx
@@ -384,25 +384,31 @@ traverse_object (type& c)
<< "reference_cache_traits;"
<< endl;
}
- else if (poly_derived)
- {
- os << "typedef" << endl
- << "odb::pointer_cache_traits<root_traits::pointer_type>" << endl
- << "pointer_cache_traits;"
- << "typedef" << endl
- << "odb::reference_cache_traits<root_type>" << endl
- << "reference_cache_traits;"
- << endl;
- }
else
{
- os << "typedef" << endl
- << "odb::pointer_cache_traits<pointer_type>" << endl
- << "pointer_cache_traits;"
- << "typedef" << endl
- << "odb::reference_cache_traits<object_type>" << endl
- << "reference_cache_traits;"
- << endl;
+ char const* p (session (c) ? "" : "no_op_");
+
+ if (poly_derived)
+ {
+ os << "typedef" << endl
+ << "odb::" << p << "pointer_cache_traits<" <<
+ "root_traits::pointer_type>" << endl
+ << "pointer_cache_traits;"
+ << "typedef" << endl
+ << "odb::" << p << "reference_cache_traits<root_type>" << endl
+ << "reference_cache_traits;"
+ << endl;
+ }
+ else
+ {
+ os << "typedef" << endl
+ << "odb::" << p << "pointer_cache_traits<pointer_type>" << endl
+ << "pointer_cache_traits;"
+ << "typedef" << endl
+ << "odb::" << p << "reference_cache_traits<object_type>" << endl
+ << "reference_cache_traits;"
+ << endl;
+ }
}
// Statements typedefs.
diff --git a/odb/relational/processor.cxx b/odb/relational/processor.cxx
index cdacfd4..c45d71f 100644
--- a/odb/relational/processor.cxx
+++ b/odb/relational/processor.cxx
@@ -1820,13 +1820,63 @@ namespace relational
virtual void
traverse_object_pre (type& c)
{
- if (semantics::class_* root = polymorphic (c))
+ semantics::class_* poly_root (polymorphic (c));
+
+ // Determine whether it is a session object.
+ //
+ if (!c.count ("session"))
+ {
+ // If this is a derived class in a polymorphic hierarchy,
+ // then it should have the same session value as the root.
+ //
+ if (poly_root != 0 && poly_root != &c)
+ c.set ("session", session (*poly_root));
+ else
+ {
+ // See if any of the namespaces containing this class specify
+ // the session value.
+ //
+ bool found (false);
+ for (semantics::scope* s (&c.scope ());; s = &s->scope_ ())
+ {
+ using semantics::namespace_;
+
+ namespace_* ns (dynamic_cast<namespace_*> (s));
+
+ if (ns == 0)
+ continue; // Some other scope.
+
+ if (ns->extension ())
+ ns = &ns->original ();
+
+ if (ns->count ("session"))
+ {
+ c.set ("session", ns->get<bool> ("session"));
+ found = true;
+ break;
+ }
+
+ if (ns->global_scope ())
+ break;
+ }
+
+ // If still not found, then use the default value.
+ //
+ if (!found)
+ c.set ("session", options.generate_session ());
+ }
+ }
+
+ if (session (c))
+ features.session_object = true;
+
+ if (poly_root != 0)
{
using namespace semantics;
- semantics::data_member& idm (*id_member (*root));
+ semantics::data_member& idm (*id_member (*poly_root));
- if (root != &c)
+ if (poly_root != &c)
{
// If we are a derived class in the polymorphic persistent
// class hierarchy, then add a synthesized virtual pointer
@@ -1846,23 +1896,23 @@ namespace relational
// Use the raw pointer as this member's type.
//
- if (!root->pointed_p ())
+ if (!poly_root->pointed_p ())
{
// Create the pointer type in the graph. The pointer node
// in GCC seems to always be present, even if not explicitly
// used in the translation unit.
//
- tree t (root->tree_node ());
+ tree t (poly_root->tree_node ());
tree ptr (TYPE_POINTER_TO (t));
assert (ptr != 0);
ptr = TYPE_MAIN_VARIANT (ptr);
pointer& p (unit.new_node<pointer> (f, l, col, ptr));
unit.insert (ptr, p);
- unit.new_edge<points> (p, *root);
- assert (root->pointed_p ());
+ unit.new_edge<points> (p, *poly_root);
+ assert (poly_root->pointed_p ());
}
- unit.new_edge<belongs> (m, root->pointed ().pointer ());
+ unit.new_edge<belongs> (m, poly_root->pointed ().pointer ());
m.set ("not-null", true);
m.set ("deferred", false);
diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx
index 42ff235..bbea0a7 100644
--- a/odb/relational/source.hxx
+++ b/odb/relational/source.hxx
@@ -3368,8 +3368,6 @@ namespace relational
os << endl;
- os << "#include <odb/cache-traits.hxx>" << endl;
-
if (features.polymorphic_object)
os << "#include <odb/polymorphic-map.hxx>" << endl;
diff --git a/odb/validator.cxx b/odb/validator.cxx
index d346b25..eac5086 100644
--- a/odb/validator.cxx
+++ b/odb/validator.cxx
@@ -1047,7 +1047,7 @@ namespace
if (id != 0)
{
- if (semantics::class_* c = composite_wrapper (utype (*id)))
+ if (semantics::class_* cm = composite_wrapper (utype (*id)))
{
// Composite id cannot be auto.
//
@@ -1065,7 +1065,7 @@ namespace
//
if (valid_)
{
- composite_id_members_.traverse (*c);
+ composite_id_members_.traverse (*cm);
if (!valid_)
os << id->file () << ":" << id->line () << ":" << id->column ()
@@ -1074,28 +1074,29 @@ namespace
// Check that the composite value type is default-constructible.
//
- if (!c->default_ctor ())
+ if (!cm->default_ctor ())
{
- os << c->file () << ":" << c->line () << ":" << c->column ()
+ os << cm->file () << ":" << cm->line () << ":" << cm->column ()
<< ": error: composite value type that is used as object id "
<< "is not default-constructible" << endl;
- os << c->file () << ":" << c->line () << ":" << c->column ()
- << ": info: provide default constructor for this value type"
- << endl;
+ os << cm->file () << ":" << cm->line () << ":" << cm->column ()
+ << ": info: provide default constructor for this value type"
+ << endl;
- os << id->file () << ":" << id->line () << ":" << id->column ()
- << ": info: composite id is defined here" << endl;
+ os << id->file () << ":" << id->line () << ":" << id->column ()
+ << ": info: composite id is defined here" << endl;
- valid_ = false;
+ valid_ = false;
}
- // Check that composite values can be compared (used in session).
+ // If this is a session object, make sure that the composite
+ // value can be compared.
//
- if (has_lt_operator_ != 0)
+ if (session (c) && has_lt_operator_ != 0)
{
tree args (make_tree_vec (1));
- TREE_VEC_ELT (args, 0) = c->tree_node ();
+ TREE_VEC_ELT (args, 0) = cm->tree_node ();
tree inst (
instantiate_template (
@@ -1126,17 +1127,21 @@ namespace
if (!v)
{
- os << c->file () << ":" << c->line () << ":" << c->column ()
+ os << cm->file () << ":" << cm->line () << ":" << cm->column ()
<< ": error: composite value type that is used as object id "
- << "does not support the less than (<) comparison"
+ << "in persistent class with session support does not "
+ << "define the less than (<) comparison"
<< endl;
- os << c->file () << ":" << c->line () << ":" << c->column ()
+ os << cm->file () << ":" << cm->line () << ":" << cm->column ()
<< ": info: provide operator< for this value type" << endl;
os << id->file () << ":" << id->line () << ":" << id->column ()
<< ": info: composite id is defined here" << endl;
+ os << c.file () << ":" << c.line () << ":" << c.column ()
+ << ": info: persistent class is defined here" << endl;
+
valid_ = false;
}
}