aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2012-09-01 11:49:15 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2012-09-01 11:49:15 +0200
commit9a1ab7cbfc723909bc96211046cbd8a189dc0d23 (patch)
tree865d99b6f7e83f1458d4376d0bd2bf52a2bf61d0
parent7e29dc5b25177beb7d96099643a4f7e057ebe8e5 (diff)
Document virtual data members
-rw-r--r--doc/manual.xhtml543
1 files changed, 418 insertions, 125 deletions
diff --git a/doc/manual.xhtml b/doc/manual.xhtml
index 972b26a..203fe53 100644
--- a/doc/manual.xhtml
+++ b/doc/manual.xhtml
@@ -460,6 +460,7 @@ for consistency.
<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>
<tr><th>12.1.11</th><td><a href="#12.1.11"><code>definition</code></a></td></tr>
+ <tr><th>12.1.12</th><td><a href="#12.1.12"><code>transient</code></a></td></tr>
</table>
</td>
</tr>
@@ -472,6 +473,7 @@ for consistency.
<tr><th>12.2.4</th><td><a href="#12.2.4"><code>pointer</code></a></td></tr>
<tr><th>12.2.5</th><td><a href="#12.2.5"><code>callback</code></a></td></tr>
<tr><th>12.2.6</th><td><a href="#12.2.6"><code>definition</code></a></td></tr>
+ <tr><th>12.2.7</th><td><a href="#12.2.7"><code>transient</code></a></td></tr>
</table>
</td>
</tr>
@@ -485,19 +487,20 @@ for consistency.
<tr><th>12.3.5</th><td><a href="#12.3.5"><code>options</code></a></td></tr>
<tr><th>12.3.6</th><td><a href="#12.3.6"><code>readonly</code></a></td></tr>
<tr><th>12.3.7</th><td><a href="#12.3.7"><code>definition</code></a></td></tr>
- <tr><th>12.3.8</th><td><a href="#12.3.8"><code>unordered</code></a></td></tr>
- <tr><th>12.3.9</th><td><a href="#12.3.9"><code>index_type</code></a></td></tr>
- <tr><th>12.3.10</th><td><a href="#12.3.10"><code>key_type</code></a></td></tr>
- <tr><th>12.3.11</th><td><a href="#12.3.11"><code>value_type</code></a></td></tr>
- <tr><th>12.3.12</th><td><a href="#12.3.12"><code>value_null</code>/<code>value_not_null</code></a></td></tr>
- <tr><th>12.3.13</th><td><a href="#12.3.13"><code>id_options</code></a></td></tr>
- <tr><th>12.3.14</th><td><a href="#12.3.14"><code>index_options</code></a></td></tr>
- <tr><th>12.3.15</th><td><a href="#12.3.15"><code>key_options</code></a></td></tr>
- <tr><th>12.3.16</th><td><a href="#12.3.16"><code>value_options</code></a></td></tr>
- <tr><th>12.3.17</th><td><a href="#12.3.17"><code>id_column</code></a></td></tr>
- <tr><th>12.3.18</th><td><a href="#12.3.18"><code>index_column</code></a></td></tr>
- <tr><th>12.3.19</th><td><a href="#12.3.19"><code>key_column</code></a></td></tr>
- <tr><th>12.3.20</th><td><a href="#12.3.20"><code>value_column</code></a></td></tr>
+ <tr><th>12.3.8</th><td><a href="#12.3.8"><code>transient</code></a></td></tr>
+ <tr><th>12.3.9</th><td><a href="#12.3.9"><code>unordered</code></a></td></tr>
+ <tr><th>12.3.10</th><td><a href="#12.3.10"><code>index_type</code></a></td></tr>
+ <tr><th>12.3.11</th><td><a href="#12.3.11"><code>key_type</code></a></td></tr>
+ <tr><th>12.3.12</th><td><a href="#12.3.12"><code>value_type</code></a></td></tr>
+ <tr><th>12.3.13</th><td><a href="#12.3.13"><code>value_null</code>/<code>value_not_null</code></a></td></tr>
+ <tr><th>12.3.14</th><td><a href="#12.3.14"><code>id_options</code></a></td></tr>
+ <tr><th>12.3.15</th><td><a href="#12.3.15"><code>index_options</code></a></td></tr>
+ <tr><th>12.3.16</th><td><a href="#12.3.16"><code>key_options</code></a></td></tr>
+ <tr><th>12.3.17</th><td><a href="#12.3.17"><code>value_options</code></a></td></tr>
+ <tr><th>12.3.18</th><td><a href="#12.3.18"><code>id_column</code></a></td></tr>
+ <tr><th>12.3.19</th><td><a href="#12.3.19"><code>index_column</code></a></td></tr>
+ <tr><th>12.3.20</th><td><a href="#12.3.20"><code>key_column</code></a></td></tr>
+ <tr><th>12.3.21</th><td><a href="#12.3.21"><code>value_column</code></a></td></tr>
</table>
</td>
</tr>
@@ -516,24 +519,25 @@ for consistency.
<tr><th>12.4.10</th><td><a href="#12.4.10"><code>column</code> (view)</a></td></tr>
<tr><th>12.4.11</th><td><a href="#12.4.11"><code>transient</code></a></td></tr>
<tr><th>12.4.12</th><td><a href="#12.4.12"><code>readonly</code></a></td></tr>
- <tr><th>12.4.13</th><td><a href="#12.4.13"><code>inverse</code></a></td></tr>
- <tr><th>12.4.14</th><td><a href="#12.4.14"><code>version</code></a></td></tr>
- <tr><th>12.4.15</th><td><a href="#12.4.15"><code>index</code></a></td></tr>
- <tr><th>12.4.16</th><td><a href="#12.4.16"><code>unique</code></a></td></tr>
- <tr><th>12.4.17</th><td><a href="#12.4.17"><code>unordered</code></a></td></tr>
- <tr><th>12.4.18</th><td><a href="#12.4.18"><code>table</code></a></td></tr>
- <tr><th>12.4.19</th><td><a href="#12.4.19"><code>index_type</code></a></td></tr>
- <tr><th>12.4.20</th><td><a href="#12.4.20"><code>key_type</code></a></td></tr>
- <tr><th>12.4.21</th><td><a href="#12.4.21"><code>value_type</code></a></td></tr>
- <tr><th>12.4.22</th><td><a href="#12.4.22"><code>value_null</code>/<code>value_not_null</code></a></td></tr>
- <tr><th>12.4.23</th><td><a href="#12.4.23"><code>id_options</code></a></td></tr>
- <tr><th>12.4.24</th><td><a href="#12.4.24"><code>index_options</code></a></td></tr>
- <tr><th>12.4.25</th><td><a href="#12.4.25"><code>key_options</code></a></td></tr>
- <tr><th>12.4.26</th><td><a href="#12.4.26"><code>value_options</code></a></td></tr>
- <tr><th>12.4.27</th><td><a href="#12.4.27"><code>id_column</code></a></td></tr>
- <tr><th>12.4.28</th><td><a href="#12.4.28"><code>index_column</code></a></td></tr>
- <tr><th>12.4.29</th><td><a href="#12.4.29"><code>key_column</code></a></td></tr>
- <tr><th>12.4.30</th><td><a href="#12.4.30"><code>value_column</code></a></td></tr>
+ <tr><th>12.4.13</th><td><a href="#12.4.13"><code>virtual</code></a></td></tr>
+ <tr><th>12.4.14</th><td><a href="#12.4.14"><code>inverse</code></a></td></tr>
+ <tr><th>12.4.15</th><td><a href="#12.4.15"><code>version</code></a></td></tr>
+ <tr><th>12.4.16</th><td><a href="#12.4.16"><code>index</code></a></td></tr>
+ <tr><th>12.4.17</th><td><a href="#12.4.17"><code>unique</code></a></td></tr>
+ <tr><th>12.4.18</th><td><a href="#12.4.18"><code>unordered</code></a></td></tr>
+ <tr><th>12.4.19</th><td><a href="#12.4.19"><code>table</code></a></td></tr>
+ <tr><th>12.4.20</th><td><a href="#12.4.20"><code>index_type</code></a></td></tr>
+ <tr><th>12.4.21</th><td><a href="#12.4.21"><code>key_type</code></a></td></tr>
+ <tr><th>12.4.22</th><td><a href="#12.4.22"><code>value_type</code></a></td></tr>
+ <tr><th>12.4.23</th><td><a href="#12.4.23"><code>value_null</code>/<code>value_not_null</code></a></td></tr>
+ <tr><th>12.4.24</th><td><a href="#12.4.24"><code>id_options</code></a></td></tr>
+ <tr><th>12.4.25</th><td><a href="#12.4.25"><code>index_options</code></a></td></tr>
+ <tr><th>12.4.26</th><td><a href="#12.4.26"><code>key_options</code></a></td></tr>
+ <tr><th>12.4.27</th><td><a href="#12.4.27"><code>value_options</code></a></td></tr>
+ <tr><th>12.4.28</th><td><a href="#12.4.28"><code>id_column</code></a></td></tr>
+ <tr><th>12.4.29</th><td><a href="#12.4.29"><code>index_column</code></a></td></tr>
+ <tr><th>12.4.30</th><td><a href="#12.4.30"><code>key_column</code></a></td></tr>
+ <tr><th>12.4.31</th><td><a href="#12.4.31"><code>value_column</code></a></td></tr>
</table>
</td>
</tr>
@@ -4748,8 +4752,8 @@ private:
the order information. In the example above, for instance, the order
of person's nicknames is probably not important. To instruct the ODB
compiler to ignore the order in ordered containers we can use the
- <code>db&nbsp;unordered</code> pragma (<a href="#12.3.8">Section 12.3.8,
- "<code>unordered</code>"</a>, <a href="#12.4.17">Section 12.4.17,
+ <code>db&nbsp;unordered</code> pragma (<a href="#12.3.9">Section 12.3.9,
+ "<code>unordered</code>"</a>, <a href="#12.4.18">Section 12.4.18,
"<code>unordered</code>"</a>). For example:</p>
<pre class="cxx">
@@ -5015,8 +5019,8 @@ class employee
use the <code>not_null</code> pragma (<a href="#12.4.6">Section
12.4.6, "<code>null</code>/<code>not_null</code>"</a>) for
single object pointers and the <code>value_not_null</code> pragma
- (<a href="#12.4.22">Section
- 12.4.22, "<code>value_null</code>/<code>value_not_null</code>"</a>)
+ (<a href="#12.4.23">Section
+ 12.4.23, "<code>value_null</code>/<code>value_not_null</code>"</a>)
for containers of object pointers. For example:</p>
<pre class="cxx">
@@ -5429,7 +5433,7 @@ CREATE TABLE employee (
of these references.</p>
<p>To eliminate redundant database schema references we can use the
- <code>inverse</code> pragma (<a href="#12.4.13">Section 12.4.13,
+ <code>inverse</code> pragma (<a href="#12.4.14">Section 12.4.14,
"<code>inverse</code>"</a>) which tells the ODB compiler that
a pointer is the inverse side of a bidirectional relationship.
Either side of a relationship can be made inverse. For example:</p>
@@ -5473,7 +5477,7 @@ CREATE TABLE employee (
pointer. Also note that an ordered container (<a href="#5.1">Section
5.1, "Ordered Containers"</a>) of pointers that is an inverse side
of a bidirectional relationship is always treated as unordered
- (<a href="#12.4.17">Section 12.4.17, "<code>unordered</code>"</a>)
+ (<a href="#12.4.18">Section 12.4.18, "<code>unordered</code>"</a>)
because the contents of such a container are implicitly built from
the direct side of the relationship which does not contain the
element order (index).</p>
@@ -6373,9 +6377,9 @@ CREATE TABLE person (
<p>The same principle applies when a composite value type is used
as an element of a container, except that instead of
<code>db&nbsp;column</code>, either the <code>db&nbsp;value_column</code>
- (<a href="#12.4.30">Section 12.4.30, "<code>value_column</code>"</a>) or
+ (<a href="#12.4.31">Section 12.4.31, "<code>value_column</code>"</a>) or
<code>db&nbsp;key_column</code>
- (<a href="#12.4.29">Section 12.4.29, "<code>key_column</code>"</a>)
+ (<a href="#12.4.30">Section 12.4.30, "<code>key_column</code>"</a>)
pragmas are used to specify the column prefix.</p>
<p>When a composite value type contains a container, an extra table
@@ -6419,8 +6423,8 @@ CREATE TABLE person (
</pre>
<p>To customize the container table name we can use the
- <code>db&nbsp;table</code> pragma (<a href="#12.4.18">Section
- 12.4.18, "<code>table</code>"</a>), for example:</p>
+ <code>db&nbsp;table</code> pragma (<a href="#12.4.19">Section
+ 12.4.19, "<code>table</code>"</a>), for example:</p>
<pre class="cxx">
#pragma db value
@@ -8779,7 +8783,7 @@ p.age (age);
<p>To declare a persistent class with the optimistic concurrency model we
use the <code>optimistic</code> pragma (<a href="#12.1.5">Section 12.1.5,
"<code>optimistic</code>"</a>). We also use the <code>version</code>
- pragma (<a href="#12.4.14">Section 12.4.14, "<code>version</code>"</a>)
+ pragma (<a href="#12.4.15">Section 12.4.15, "<code>version</code>"</a>)
to specify which data member will store the object version. For
example:</p>
@@ -9240,6 +9244,12 @@ class person
<td><a href="#12.1.11">12.1.11</a></td>
</tr>
+ <tr>
+ <td><code>transient</code></td>
+ <td>all non-virtual data members in a persistent class are transient</td>
+ <td><a href="#12.1.12">12.1.12</a></td>
+ </tr>
+
</table>
<h3><a name="12.1.1">12.1.1 <code>table</code></a></h3>
@@ -9390,7 +9400,7 @@ class person
has the optimistic concurrency model. A class with the optimistic
concurrency model must also specify the data member that is used to
store the object version using the <code>version</code> pragma
- (<a href="#12.4.14">Section 12.4.14, "<code>version</code>"</a>).
+ (<a href="#12.4.15">Section 12.4.15, "<code>version</code>"</a>).
For example:</p>
<pre class="cxx">
@@ -9850,6 +9860,15 @@ class employer
<p>For more information on this functionality, refer to
<a href="#12.3.7">Section 12.3.7, "<code>definition</code>"</a>.</p>
+ <h3><a name="12.1.12">12.1.12 <code>transient</code></a></h3>
+
+ <p>The <code>transient</code> specifier instructs the ODB compiler to
+ treat all non-virtual data member in the persistent class as transient
+ (<a href="#12.4.1">Section 12.4.1, "<code>transient</code>"</a>).
+ This specifier is primarily useful when declaring virtual data
+ members, as discussed in <a href="#12.4.13">Section 12.4.13,
+ "<code>virtual</code>"</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
@@ -9901,6 +9920,12 @@ class employer
<td><a href="#12.2.6">12.2.6</a></td>
</tr>
+ <tr>
+ <td><code>transient</code></td>
+ <td>all non-virtual data members in a view are transient</td>
+ <td><a href="#12.2.7">12.2.7</a></td>
+ </tr>
+
</table>
<p>For more information on view types refer to <a href="#9"> Chapter 9,
@@ -9966,6 +9991,15 @@ class employer
<p>For more information on this functionality, refer to
<a href="#12.3.7">Section 12.3.7, "<code>definition</code>"</a>.</p>
+ <h3><a name="12.2.7">12.2.7 <code>transient</code></a></h3>
+
+ <p>The <code>transient</code> specifier instructs the ODB compiler
+ to treat all non-virtual data member in the view class as transient
+ (<a href="#12.4.1">Section 12.4.1, "<code>transient</code>"</a>).
+ This specifier is primarily useful when declaring virtual data
+ members, as discussed in <a href="#12.4.13">Section 12.4.13,
+ "<code>virtual</code>"</a>.</p>
+
<h2><a name="12.3">12.3 Value Type Pragmas</a></h2>
<p>A pragma with the <code>value</code> qualifier describes a value
@@ -10023,81 +10057,87 @@ class employer
</tr>
<tr>
+ <td><code>transient</code></td>
+ <td>all non-virtual data members in a composite value are transient</td>
+ <td><a href="#12.3.8">12.3.8</a></td>
+ </tr>
+
+ <tr>
<td><code>unordered</code></td>
<td>ordered container should be stored unordered</td>
- <td><a href="#12.3.8">12.3.8</a></td>
+ <td><a href="#12.3.9">12.3.9</a></td>
</tr>
<tr>
<td><code>index_type</code></td>
<td>database type for a container's index type</td>
- <td><a href="#12.3.9">12.3.9</a></td>
+ <td><a href="#12.3.10">12.3.10</a></td>
</tr>
<tr>
<td><code>key_type</code></td>
<td>database type for a container's key type</td>
- <td><a href="#12.3.10">12.3.10</a></td>
+ <td><a href="#12.3.11">12.3.11</a></td>
</tr>
<tr>
<td><code>value_type</code></td>
<td>database type for a container's value type</td>
- <td><a href="#12.3.11">12.3.11</a></td>
+ <td><a href="#12.3.12">12.3.12</a></td>
</tr>
<tr>
<td><code>value_null</code>/<code>value_not_null</code></td>
<td>container's value can/cannot be <code>NULL</code></td>
- <td><a href="#12.3.12">12.3.12</a></td>
+ <td><a href="#12.3.13">12.3.13</a></td>
</tr>
<tr>
<td><code>id_options</code></td>
<td>database options for a container's id column</td>
- <td><a href="#12.3.13">12.3.13</a></td>
+ <td><a href="#12.3.14">12.3.14</a></td>
</tr>
<tr>
<td><code>index_options</code></td>
<td>database options for a container's index column</td>
- <td><a href="#12.3.14">12.3.14</a></td>
+ <td><a href="#12.3.15">12.3.15</a></td>
</tr>
<tr>
<td><code>key_options</code></td>
<td>database options for a container's key column</td>
- <td><a href="#12.3.15">12.3.15</a></td>
+ <td><a href="#12.3.16">12.3.16</a></td>
</tr>
<tr>
<td><code>value_options</code></td>
<td>database options for a container's value column</td>
- <td><a href="#12.3.16">12.3.16</a></td>
+ <td><a href="#12.3.17">12.3.17</a></td>
</tr>
<tr>
<td><code>id_column</code></td>
<td>column name for a container's object id</td>
- <td><a href="#12.3.17">12.3.17</a></td>
+ <td><a href="#12.3.18">12.3.18</a></td>
</tr>
<tr>
<td><code>index_column</code></td>
<td>column name for a container's index</td>
- <td><a href="#12.3.18">12.3.18</a></td>
+ <td><a href="#12.3.19">12.3.19</a></td>
</tr>
<tr>
<td><code>key_column</code></td>
<td>column name for a container's key</td>
- <td><a href="#12.3.19">12.3.19</a></td>
+ <td><a href="#12.3.20">12.3.20</a></td>
</tr>
<tr>
<td><code>value_column</code></td>
<td>column name for a container's value</td>
- <td><a href="#12.3.20">12.3.20</a></td>
+ <td><a href="#12.3.21">12.3.21</a></td>
</tr>
</table>
@@ -10407,7 +10447,16 @@ class object
};
</pre>
- <h3><a name="12.3.8">12.3.8 <code>unordered</code></a></h3>
+ <h3><a name="12.3.8">12.3.8 <code>transient</code></a></h3>
+
+ <p>The <code>transient</code> specifier instructs the ODB compiler
+ to treat all non-virtual data member in the composite value type
+ as transient (<a href="#12.4.1">Section 12.4.1,
+ "<code>transient</code>"</a>). This specifier is primarily useful
+ when declaring virtual data members, as discussed in
+ <a href="#12.4.13">Section 12.4.13, "<code>virtual</code>"</a>.</p>
+
+ <h3><a name="12.3.9">12.3.9 <code>unordered</code></a></h3>
<p>The <code>unordered</code> specifier specifies that the ordered
container should be stored unordered in the database. The database
@@ -10424,7 +10473,7 @@ typedef std::vector&lt;std::string> names;
storage in the database, refer to <a href="#5.1">Section 5.1,
"Ordered Containers"</a>.</p>
- <h3><a name="12.3.9">12.3.9 <code>index_type</code></a></h3>
+ <h3><a name="12.3.10">12.3.10 <code>index_type</code></a></h3>
<p>The <code>index_type</code> specifier specifies the native
database type that should be used for the ordered container's
@@ -10438,7 +10487,7 @@ typedef std::vector&lt;std::string> names;
#pragma db value(names) index_type("SMALLINT UNSIGNED")
</pre>
- <h3><a name="12.3.10">12.3.10 <code>key_type</code></a></h3>
+ <h3><a name="12.3.11">12.3.11 <code>key_type</code></a></h3>
<p>The <code>key_type</code> specifier specifies the native
database type that should be used for the map container's
@@ -10452,7 +10501,7 @@ typedef std::map&lt;unsigned short, float> age_weight_map;
#pragma db value(age_weight_map) key_type("INT UNSIGNED")
</pre>
- <h3><a name="12.3.11">12.3.11 <code>value_type</code></a></h3>
+ <h3><a name="12.3.12">12.3.12 <code>value_type</code></a></h3>
<p>The <code>value_type</code> specifier specifies the native
database type that should be used for the container's
@@ -10467,11 +10516,11 @@ typedef std::vector&lt;std::string> names;
</pre>
<p>The <code>value_null</code> and <code>value_not_null</code>
- (<a href="#12.3.12">Section 12.3.12,
+ (<a href="#12.3.13">Section 12.3.13,
"<code>value_null</code>/<code>value_not_null</code>"</a>) specifiers
can be used to control the NULL semantics of a value column.</p>
- <h3><a name="12.3.12">12.3.12 <code>value_null</code>/<code>value_not_null</code></a></h3>
+ <h3><a name="12.3.13">12.3.13 <code>value_null</code>/<code>value_not_null</code></a></h3>
<p>The <code>value_null</code> and <code>value_not_null</code> specifiers
specify that the container type's element value can or cannot be
@@ -10499,7 +10548,7 @@ typedef std::vector&lt;shared_ptr&lt;account> > accounts;
as not allowing a <code>NULL</code> value.</p>
- <h3><a name="12.3.13">12.3.13 <code>id_options</code></a></h3>
+ <h3><a name="12.3.14">12.3.14 <code>id_options</code></a></h3>
<p>The <code>id_options</code> specifier specifies additional
column definition options that should be used for the container's
@@ -10512,11 +10561,11 @@ typedef std::vector&lt;std::string> nicknames;
<p>The semantics of the <code>id_options</code> specifier for a container
type are similar to those of the <code>id_options</code> specifier for
- a container data member (<a href="#12.4.23">Section 12.4.23,
+ a container data member (<a href="#12.4.24">Section 12.4.24,
"<code>id_options</code>"</a>).</p>
- <h3><a name="12.3.14">12.3.14 <code>index_options</code></a></h3>
+ <h3><a name="12.3.15">12.3.15 <code>index_options</code></a></h3>
<p>The <code>index_options</code> specifier specifies additional
column definition options that should be used for the container's
@@ -10529,11 +10578,11 @@ typedef std::vector&lt;std::string> nicknames;
<p>The semantics of the <code>index_options</code> specifier for a container
type are similar to those of the <code>index_options</code> specifier for
- a container data member (<a href="#12.4.24">Section 12.4.24,
+ a container data member (<a href="#12.4.25">Section 12.4.25,
"<code>index_options</code>"</a>).</p>
- <h3><a name="12.3.15">12.3.15 <code>key_options</code></a></h3>
+ <h3><a name="12.3.16">12.3.16 <code>key_options</code></a></h3>
<p>The <code>key_options</code> specifier specifies additional
column definition options that should be used for the container's
@@ -10546,11 +10595,11 @@ typedef std::map&lt;std::string, std::string> properties;
<p>The semantics of the <code>key_options</code> specifier for a container
type are similar to those of the <code>key_options</code> specifier for
- a container data member (<a href="#12.4.25">Section 12.4.25,
+ a container data member (<a href="#12.4.26">Section 12.4.26,
"<code>key_options</code>"</a>).</p>
- <h3><a name="12.3.16">12.3.16 <code>value_options</code></a></h3>
+ <h3><a name="12.3.17">12.3.17 <code>value_options</code></a></h3>
<p>The <code>value_options</code> specifier specifies additional
column definition options that should be used for the container's
@@ -10563,11 +10612,11 @@ typedef std::set&lt;std::string> nicknames;
<p>The semantics of the <code>value_options</code> specifier for a container
type are similar to those of the <code>value_options</code> specifier for
- a container data member (<a href="#12.4.26">Section 12.4.26,
+ a container data member (<a href="#12.4.27">Section 12.4.27,
"<code>value_options</code>"</a>).</p>
- <h3><a name="12.3.17">12.3.17 <code>id_column</code></a></h3>
+ <h3><a name="12.3.18">12.3.18 <code>id_column</code></a></h3>
<p>The <code>id_column</code> specifier specifies the column
name that should be used to store the object id in the
@@ -10581,7 +10630,7 @@ typedef std::vector&lt;std::string> names;
<p>If the column name is not specified, then <code>object_id</code>
is used by default.</p>
- <h3><a name="12.3.18">12.3.18 <code>index_column</code></a></h3>
+ <h3><a name="12.3.19">12.3.19 <code>index_column</code></a></h3>
<p>The <code>index_column</code> specifier specifies the column
name that should be used to store the element index in the
@@ -10595,7 +10644,7 @@ typedef std::vector&lt;std::string> names;
<p>If the column name is not specified, then <code>index</code>
is used by default.</p>
- <h3><a name="12.3.19">12.3.19 <code>key_column</code></a></h3>
+ <h3><a name="12.3.20">12.3.20 <code>key_column</code></a></h3>
<p>The <code>key_column</code> specifier specifies the column
name that should be used to store the key in the map
@@ -10609,7 +10658,7 @@ typedef std::map&lt;unsigned short, float> age_weight_map;
<p>If the column name is not specified, then <code>key</code>
is used by default.</p>
- <h3><a name="12.3.20">12.3.20 <code>value_column</code></a></h3>
+ <h3><a name="12.3.21">12.3.21 <code>value_column</code></a></h3>
<p>The <code>value_column</code> specifier specifies the column
name that should be used to store the element value in the
@@ -10714,111 +10763,117 @@ typedef std::map&lt;unsigned short, float> age_weight_map;
</tr>
<tr>
+ <td><code>virtual</code></td>
+ <td>declare a virtual data member</td>
+ <td><a href="#12.4.13">12.4.13</a></td>
+ </tr>
+
+ <tr>
<td><code>inverse</code></td>
<td>member is an inverse side of a bidirectional relationship</td>
- <td><a href="#12.4.13">12.4.13</a></td>
+ <td><a href="#12.4.14">12.4.14</a></td>
</tr>
<tr>
<td><code>version</code></td>
<td>member stores object version</td>
- <td><a href="#12.4.14">12.4.14</a></td>
+ <td><a href="#12.4.15">12.4.15</a></td>
</tr>
<tr>
<td><code>index</code></td>
<td>define database index for a member</td>
- <td><a href="#12.4.15">12.4.15</a></td>
+ <td><a href="#12.4.16">12.4.16</a></td>
</tr>
<tr>
<td><code>unique</code></td>
<td>define unique database index for a member</td>
- <td><a href="#12.4.16">12.4.16</a></td>
+ <td><a href="#12.4.17">12.4.17</a></td>
</tr>
<tr>
<td><code>unordered</code></td>
<td>ordered container should be stored unordered</td>
- <td><a href="#12.4.17">12.4.17</a></td>
+ <td><a href="#12.4.18">12.4.18</a></td>
</tr>
<tr>
<td><code>table</code></td>
<td>table name for a container</td>
- <td><a href="#12.4.18">12.4.18</a></td>
+ <td><a href="#12.4.19">12.4.19</a></td>
</tr>
<tr>
<td><code>index_type</code></td>
<td>database type for a container's index type</td>
- <td><a href="#12.4.19">12.4.19</a></td>
+ <td><a href="#12.4.20">12.4.20</a></td>
</tr>
<tr>
<td><code>key_type</code></td>
<td>database type for a container's key type</td>
- <td><a href="#12.4.20">12.4.20</a></td>
+ <td><a href="#12.4.21">12.4.21</a></td>
</tr>
<tr>
<td><code>value_type</code></td>
<td>database type for a container's value type</td>
- <td><a href="#12.4.21">12.4.21</a></td>
+ <td><a href="#12.4.22">12.4.22</a></td>
</tr>
<tr>
<td><code>value_null</code>/<code>value_not_null</code></td>
<td>container's value can/cannot be <code>NULL</code></td>
- <td><a href="#12.4.22">12.4.22</a></td>
+ <td><a href="#12.4.23">12.4.23</a></td>
</tr>
<tr>
<td><code>id_options</code></td>
<td>database options for a container's id column</td>
- <td><a href="#12.4.23">12.4.23</a></td>
+ <td><a href="#12.4.24">12.4.24</a></td>
</tr>
<tr>
<td><code>index_options</code></td>
<td>database options for a container's index column</td>
- <td><a href="#12.4.24">12.4.24</a></td>
+ <td><a href="#12.4.25">12.4.25</a></td>
</tr>
<tr>
<td><code>key_options</code></td>
<td>database options for a container's key column</td>
- <td><a href="#12.4.25">12.4.25</a></td>
+ <td><a href="#12.4.26">12.4.26</a></td>
</tr>
<tr>
<td><code>value_options</code></td>
<td>database options for a container's value column</td>
- <td><a href="#12.4.26">12.4.26</a></td>
+ <td><a href="#12.4.27">12.4.27</a></td>
</tr>
<tr>
<td><code>id_column</code></td>
<td>column name for a container's object id</td>
- <td><a href="#12.4.27">12.4.27</a></td>
+ <td><a href="#12.4.28">12.4.28</a></td>
</tr>
<tr>
<td><code>index_column</code></td>
<td>column name for a container's index</td>
- <td><a href="#12.4.28">12.4.28</a></td>
+ <td><a href="#12.4.29">12.4.29</a></td>
</tr>
<tr>
<td><code>key_column</code></td>
<td>column name for a container's key</td>
- <td><a href="#12.4.29">12.4.29</a></td>
+ <td><a href="#12.4.30">12.4.30</a></td>
</tr>
<tr>
<td><code>value_column</code></td>
<td>column name for a container's value</td>
- <td><a href="#12.4.30">12.4.30</a></td>
+ <td><a href="#12.4.31">12.4.31</a></td>
</tr>
</table>
@@ -11128,15 +11183,20 @@ class person
<p>Accessor and modifier expressions can be used with data members
of simple value, composite value, container, and object pointer
- types. They can also be used for data members in persistent classes,
- composite value types, and views. There are, however, certain
- limitations when it comes to using by-value accessor and modifier
- expressions. First of all, if a by-value modifier is used, then
- the data member type should be default-constructible. Furthermore,
- a composite value type that has a container member cannot
- be modified with a by-value modifier. Only a by-reference modifier
- expression can be used. The ODB compiler will detect such cases
- and issue diagnostics. For example:</p>
+ types. They can be used for data members in persistent classes,
+ composite value types, and views. There is also a related to
+ accessors and modifiers mechanism called virtual data members
+ which is discussed in <a href="#12.4.13">Section 12.4.13,
+ "<code>virtual</code>"</a>.</p>
+
+ <p>There are, however, certain limitations when it comes to using
+ by-value accessor and modifier expressions. First of all, if a
+ by-value modifier is used, then the data member type should be
+ default-constructible. Furthermore, a composite value type that
+ has a container member cannot be modified with a by-value modifier.
+ Only a by-reference modifier expression can be used. The ODB
+ compiler will detect such cases and issue diagnostics. For
+ example:</p>
<pre class="cxx">
#pragma db value
@@ -11455,7 +11515,7 @@ class person
containing such a member. Since views are read-only, it is not
necessary to use this specifier for view data members. Object id
(<a href="#12.4.1">Section 12.4.1, "<code>id</code>"</a>)
- and inverse (<a href="#12.4.13">Section 12.4.13,
+ and inverse (<a href="#12.4.14">Section 12.4.14,
"<code>inverse</code>"</a>) data members are automatically treated
as read-only and must not be explicitly declared as such. For
example:</p>
@@ -11539,7 +11599,240 @@ class person
as well as whole objects (<a href="#12.1.4">Section 12.1.4,
"<code>readonly</code>"</a>) as read-only.</p>
- <h3><a name="12.4.13">12.4.13 <code>inverse</code></a></h3>
+ <h3><a name="12.4.13">12.4.13 <code>virtual</code></a></h3>
+
+ <p>The <code>virtual</code> specifier is used to declare a virtual
+ data member in an object, view, or composite value type. A virtual
+ data member is an <em>imaginary</em> data member that is only
+ used for the purpose of database persistence. A virtual data
+ member does not actually exist (that is, occupy space) in the
+ C++ class. Note also that virtual data members have nothing to
+ do with C++ virtual functions or virtual inheritance. Specifically,
+ no virtual function call overhead is incurred when using virtual
+ data members.</p>
+
+ <p>To declare a virtual data members we must specify the data
+ member name using the <code>member</code> specifier. We must
+ also specify the data member type with the <code>virtual</code>
+ specifier. Finally, the virtual data member declaration must
+ also specify the accessor and modifier expressions, unless
+ suitable accessor and modifier functions can be automatically
+ found by the ODB compiler (<a href="#12.4.5">Section 12.4.5,
+ "<code>get</code>/<code>set</code>/<code>access</code>"</a>).
+ For example:</p>
+
+ <pre class="cxx">
+#pragma db object
+class person
+{
+ ...
+
+ // Transient real data member that actually stores the data.
+ //
+ #pragma db transient
+ std::string name_;
+
+ // Virtual data member.
+ //
+ #pragma db member(name) virtual(std::string) access(name_)
+};
+ </pre>
+
+ <p>From the pragma language point of view, a virtual data member
+ behaves exactly like a normal data member. Specifically, we
+ can reference the virtual data member after it has been
+ declared and use positioned pragmas before its declaration.
+ For example:</p>
+
+ <pre class="cxx">
+#pragma db object
+class person
+{
+ ...
+
+ #pragma db transient
+ std::string name_;
+
+ #pragma db access(name_)
+ #pragma db member(name) virtual(std::string)
+};
+
+#pragma db member(person::name) column("person_name")
+#pragma db index member(person::name)
+ </pre>
+
+ <p>We can also declare a virtual data member outside the class
+ scope:</p>
+
+ <pre class="cxx">
+#pragma db object
+class person
+{
+ ...
+
+ std::string name_;
+};
+
+#pragma db member(person::name_) transient
+#pragma db member(person::name) virtual(std::string) access(name_)
+ </pre>
+
+ <p>While in the above examples using virtual data members doesn't
+ seem to yield any benefits, this mechanism can be useful in a
+ number of situations. As one example, consider the need to
+ aggregate or dis-aggregate a data member:</p>
+
+ <pre class="cxx">
+#pragma db object
+class person
+{
+ ...
+
+ #pragma db transient
+ std::pair&lt;std::string, std::string> name_;
+
+ #pragma db member(first) virtual(std::string) access(name_.first)
+ #pragma db member(last) virtual(std::string) access(name_.second)
+};
+ </pre>
+
+ <p>We can also use virtual data members to implement composite
+ object ids that are spread over multiple data members:</p>
+
+ <pre class="cxx">
+#pragma db value
+struct name
+{
+ name () {}
+ name (std::string const&amp; f, std::string const&amp; l)
+ : first (f), last(l) {}
+
+ std::string first;
+ std::string last;
+};
+
+#pragma db object
+class person
+{
+ ...
+
+ #pragma db transient
+ std::string first_;
+
+ #pragma db transient
+ std::string last_;
+
+ #pragma db member(name) virtual(name) id \
+ get(::name (this.first_, this.last_)) \
+ set(this.first_ = (?).first; this.last_ = (?).last)
+};
+ </pre>
+
+ <p>Another common situation that calls for virtual data members is
+ a class that uses the pimpl idiom. While the following code
+ fragment outlines the idea, for details refer to the
+ <code>pimpl</code> example in the <code>odb-examples</code>
+ package.</p>
+
+ <pre class="cxx">
+#pragma db object
+class person
+{
+public:
+ std::string const&amp; name () const;
+ void name (std::string const&amp;);
+
+ unsigned short age () const;
+ void age (unsigned short);
+
+ ...
+
+private:
+ class impl;
+
+ #pragma db transient
+ impl* pimpl_;
+
+ #pragma db member(name) virtual(std::string) // Uses name().
+ #pragma db member(age) virtual(unsigned short) // Uses age().
+};
+ </pre>
+
+ <p>The above example also shows that names used for virtual data
+ members (<code>name</code> and <code>age</code> in our case) can
+ be the same as the names of accessor/modifier functions. The only
+ names that virtual data members cannot clash with are those of
+ other data members, virtual or real.</p>
+
+ <p>A common pattern in the above examples is the need to
+ declare the real data member that actually stores the
+ data as transient. If all the real data members in a
+ class are treated as transient, then we can use the
+ class-level <code>transient</code> specifier
+ (<a href="#12.1.12">Section 12.1.12, "<code>transient</code>
+ (object)"</a>,
+ <a href="#12.3.8">Section 12.3.8, "<code>transient</code>
+ (composite value)"</a>,
+ <a href="#12.2.7">Section 12.2.7, "<code>transient</code>
+ (view)"</a>)
+ instead of doing it for each individual member. For example: </p>
+
+ <pre class="cxx">
+#pragma db object transient
+class person
+{
+ ...
+
+ std::string first_; // Transient.
+ std::string last_; // Transient.
+
+ #pragma db member(name) virtual(name) ...
+};
+ </pre>
+
+ <p>The ability to treat all the real data members as transient
+ becomes more important if we don't know the names of these
+ data members. This is often the case when we are working
+ with third-party types that document the accessor and
+ modifier functions but not the names of their private data
+ members. As an example, consider the <code>point</code> class
+ defined in a third-party <code>&lt;point></code> header file:</p>
+
+ <pre class="cxx">
+class point
+{
+public:
+ point ();
+ point (int x, int y);
+
+ int x () const;
+ int y () const;
+
+ void x (int);
+ void y (int);
+
+private:
+ ...
+};
+ </pre>
+
+ <p>To convert this class to an ODB composite value type we could
+ create the <code>point-mapping.hxx</code> file with the following
+ content:</p>
+
+ <pre class="cxx">
+#include &lt;point>
+
+#pragma db value(point) transient definition
+#pragma db member(point::x) virtual(int)
+#pragma db member(point::y) virtual(int)
+ </pre>
+
+ <p>Virtual data members can be of simple value, composite value,
+ container, or object pointer types. They can be used in persistent
+ classes, composite value types, and views.</p>
+
+ <h3><a name="12.4.14">12.4.14 <code>inverse</code></a></h3>
<p>The <code>inverse</code> specifier specifies that the data member of
an object pointer or a container of object pointers type is an
@@ -11577,12 +11870,12 @@ class person
relationship information. Only ordered and set containers can be used
for inverse members. If an inverse member is of an ordered container
type, it is automatically marked as unordered
- (<a href="#12.4.17">Section 12.4.17, "<code>unordered</code>"</a>).</p>
+ (<a href="#12.4.18">Section 12.4.18, "<code>unordered</code>"</a>).</p>
<p>For a more detailed discussion of inverse members, refer to
<a href="#6.2">Section 6.2, "Bidirectional Relationships"</a>.</p>
- <h3><a name="12.4.14">12.4.14 <code>version</code></a></h3>
+ <h3><a name="12.4.15">12.4.15 <code>version</code></a></h3>
<p>The <code>version</code> specifier specifies that the data member stores
the object version used to support optimistic concurrency. If a class
@@ -11612,7 +11905,7 @@ class person
<p>For a more detailed discussion of optimistic concurrency, refer to
<a href="#11">Chapter 11, "Optimistic Concurrency"</a>.</p>
- <h3><a name="12.4.15">12.4.15 <code>index</code></a></h3>
+ <h3><a name="12.4.16">12.4.16 <code>index</code></a></h3>
<p>The <code>index</code> specifier instructs the ODB compiler to define
a database index for the data member. For example:</p>
@@ -11631,7 +11924,7 @@ class person
<p>For more information on defining database indexes, refer to
<a href="#12.6">Section 12.6, "Index Definition Pragmas"</a>.</p>
- <h3><a name="12.4.16">12.4.16 <code>unique</code></a></h3>
+ <h3><a name="12.4.17">12.4.17 <code>unique</code></a></h3>
<p>The <code>index</code> specifier instructs the ODB compiler to define
a unique database index for the data member. For example:</p>
@@ -11650,7 +11943,7 @@ class person
<p>For more information on defining database indexes, refer to
<a href="#12.6">Section 12.6, "Index Definition Pragmas"</a>.</p>
- <h3><a name="12.4.17">12.4.17 <code>unordered</code></a></h3>
+ <h3><a name="12.4.18">12.4.18 <code>unordered</code></a></h3>
<p>The <code>unordered</code> specifier specifies that the member of
an ordered container type should be stored unordered in the database.
@@ -11673,7 +11966,7 @@ class person
storage in the database, refer to <a href="#5.1">Section 5.1,
"Ordered Containers"</a>.</p>
- <h3><a name="12.4.18">12.4.18 <code>table</code></a></h3>
+ <h3><a name="12.4.19">12.4.19 <code>table</code></a></h3>
<p>The <code>table</code> specifier specifies the table name that should
be used to store the contents of the container member. For example:</p>
@@ -11721,7 +12014,7 @@ class person
qualified names, refer to <a href="#12.1.8">Section 12.1.8,
"<code>schema</code>"</a>.</p>
- <h3><a name="12.4.19">12.4.19 <code>index_type</code></a></h3>
+ <h3><a name="12.4.20">12.4.20 <code>index_type</code></a></h3>
<p>The <code>index_type</code> specifier specifies the native
database type that should be used for an ordered container's
@@ -11741,7 +12034,7 @@ class person
};
</pre>
- <h3><a name="12.4.20">12.4.20 <code>key_type</code></a></h3>
+ <h3><a name="12.4.21">12.4.21 <code>key_type</code></a></h3>
<p>The <code>key_type</code> specifier specifies the native
database type that should be used for a map container's
@@ -11761,7 +12054,7 @@ class person
};
</pre>
- <h3><a name="12.4.21">12.4.21 <code>value_type</code></a></h3>
+ <h3><a name="12.4.22">12.4.22 <code>value_type</code></a></h3>
<p>The <code>value_type</code> specifier specifies the native
database type that should be used for a container's
@@ -11782,11 +12075,11 @@ class person
</pre>
<p>The <code>value_null</code> and <code>value_not_null</code>
- (<a href="#12.4.22">Section 12.4.22,
+ (<a href="#12.4.23">Section 12.4.23,
"<code>value_null</code>/<code>value_not_null</code>"</a>) specifiers
can be used to control the NULL semantics of a value column.</p>
- <h3><a name="12.4.22">12.4.22 <code>value_null</code>/<code>value_not_null</code></a></h3>
+ <h3><a name="12.4.23">12.4.23 <code>value_null</code>/<code>value_not_null</code></a></h3>
<p>The <code>value_null</code> and <code>value_not_null</code> specifiers
specify that a container's element value for the data member can or
@@ -11819,7 +12112,7 @@ class account
Multiset Containers"</a>) the element value is automatically treated
as not allowing a <code>NULL</code> value.</p>
- <h3><a name="12.4.23">12.4.23 <code>id_options</code></a></h3>
+ <h3><a name="12.4.24">12.4.24 <code>id_options</code></a></h3>
<p>The <code>id_options</code> specifier specifies additional
column definition options that should be used for a container's
@@ -11843,7 +12136,7 @@ class person
of the <code>options</code> specifier (<a href="#12.4.8">Section
12.4.8, "<code>options</code>"</a>).</p>
- <h3><a name="12.4.24">12.4.24 <code>index_options</code></a></h3>
+ <h3><a name="12.4.25">12.4.25 <code>index_options</code></a></h3>
<p>The <code>index_options</code> specifier specifies additional
column definition options that should be used for a container's
@@ -11864,7 +12157,7 @@ class person
of the <code>options</code> specifier (<a href="#12.4.8">Section
12.4.8, "<code>options</code>"</a>).</p>
- <h3><a name="12.4.25">12.4.25 <code>key_options</code></a></h3>
+ <h3><a name="12.4.26">12.4.26 <code>key_options</code></a></h3>
<p>The <code>key_options</code> specifier specifies additional
column definition options that should be used for a container's
@@ -11885,7 +12178,7 @@ class person
of the <code>options</code> specifier (<a href="#12.4.8">Section
12.4.8, "<code>options</code>"</a>).</p>
- <h3><a name="12.4.26">12.4.26 <code>value_options</code></a></h3>
+ <h3><a name="12.4.27">12.4.27 <code>value_options</code></a></h3>
<p>The <code>value_options</code> specifier specifies additional
column definition options that should be used for a container's
@@ -11906,7 +12199,7 @@ class person
of the <code>options</code> specifier (<a href="#12.4.8">Section
12.4.8, "<code>options</code>"</a>).</p>
- <h3><a name="12.4.27">12.4.27 <code>id_column</code></a></h3>
+ <h3><a name="12.4.28">12.4.28 <code>id_column</code></a></h3>
<p>The <code>id_column</code> specifier specifies the column
name that should be used to store the object id in a
@@ -11930,7 +12223,7 @@ class person
<p>If the column name is not specified, then <code>object_id</code>
is used by default.</p>
- <h3><a name="12.4.28">12.4.28 <code>index_column</code></a></h3>
+ <h3><a name="12.4.29">12.4.29 <code>index_column</code></a></h3>
<p>The <code>index_column</code> specifier specifies the column
name that should be used to store the element index in an
@@ -11954,7 +12247,7 @@ class person
<p>If the column name is not specified, then <code>index</code>
is used by default.</p>
- <h3><a name="12.4.29">12.4.29 <code>key_column</code></a></h3>
+ <h3><a name="12.4.30">12.4.30 <code>key_column</code></a></h3>
<p>The <code>key_column</code> specifier specifies the column
name that should be used to store the key in a map
@@ -11978,7 +12271,7 @@ class person
<p>If the column name is not specified, then <code>key</code>
is used by default.</p>
- <h3><a name="12.4.30">12.4.30 <code>value_column</code></a></h3>
+ <h3><a name="12.4.31">12.4.31 <code>value_column</code></a></h3>
<p>The <code>value_column</code> specifier specifies the column
name that should be used to store the element value in a
@@ -12297,9 +12590,9 @@ class object
<p>ODB also offers a shortcut for defining an index with the default
method and options for a single data member. Such an index can
- be defined using the <code>index</code> (<a href="#12.4.15">Section
- 12.4.15, "<code>index</code>"</a>) or <code>unique</code>
- (<a href="#12.4.16">Section 12.4.16, "<code>unique</code>"</a>)
+ be defined using the <code>index</code> (<a href="#12.4.16">Section
+ 12.4.16, "<code>index</code>"</a>) or <code>unique</code>
+ (<a href="#12.4.17">Section 12.4.17, "<code>unique</code>"</a>)
member specifier. For example:</p>
<pre class="cxx">