From 9a1ab7cbfc723909bc96211046cbd8a189dc0d23 Mon Sep 17 00:00:00 2001
From: Boris Kolpackov 12.1.9 polymorphic
12.1.10 session
+ 12.1.11 definition
@@ -472,6 +473,7 @@ for consistency.
12.1.12 transient
12.2.4 pointer
12.2.5 callback
+ 12.2.6 definition
@@ -485,19 +487,20 @@ for consistency.
12.2.7 transient
12.3.5 options
12.3.6 readonly
- 12.3.7 definition
- 12.3.8 unordered
- 12.3.9 index_type
- 12.3.10 key_type
- 12.3.11 value_type
- 12.3.12 value_null
/value_not_null
- 12.3.13 id_options
- 12.3.14 index_options
- 12.3.15 key_options
- 12.3.16 value_options
- 12.3.17 id_column
- 12.3.18 index_column
- 12.3.19 key_column
+ 12.3.20 value_column
+ 12.3.8 transient
+ 12.3.9 unordered
+ 12.3.10 index_type
+ 12.3.11 key_type
+ 12.3.12 value_type
+ 12.3.13 value_null
/value_not_null
+ 12.3.14 id_options
+ 12.3.15 index_options
+ 12.3.16 key_options
+ 12.3.17 value_options
+ 12.3.18 id_column
+ 12.3.19 index_column
+ 12.3.20 key_column
@@ -516,24 +519,25 @@ for consistency.
12.3.21 value_column
12.4.10 column
(view)12.4.11 transient
- 12.4.12 readonly
- 12.4.13 inverse
- 12.4.14 version
- 12.4.15 index
- 12.4.16 unique
- 12.4.17 unordered
- 12.4.18 table
- 12.4.19 index_type
- 12.4.20 key_type
- 12.4.21 value_type
- 12.4.22 value_null
/value_not_null
- 12.4.23 id_options
- 12.4.24 index_options
- 12.4.25 key_options
- 12.4.26 value_options
- 12.4.27 id_column
- 12.4.28 index_column
- 12.4.29 key_column
+ 12.4.30 value_column
+ 12.4.13 virtual
+ 12.4.14 inverse
+ 12.4.15 version
+ 12.4.16 index
+ 12.4.17 unique
+ 12.4.18 unordered
+ 12.4.19 table
+ 12.4.20 index_type
+ 12.4.21 key_type
+ 12.4.22 value_type
+ 12.4.23 value_null
/value_not_null
+ 12.4.24 id_options
+ 12.4.25 index_options
+ 12.4.26 key_options
+ 12.4.27 value_options
+ 12.4.28 id_column
+ 12.4.29 index_column
+ 12.4.30 key_column
@@ -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
- 12.4.31 value_column
db unordered
pragma (Section 12.3.8,
- "unordered
", Section 12.4.17,
+ db unordered
pragma (Section 12.3.9,
+ "unordered
", Section 12.4.18,
"unordered
"). For example:
@@ -5015,8 +5019,8 @@ class employee use the-not_null
pragma (Section 12.4.6, "null
/not_null
") for single object pointers and thevalue_not_null
pragma - (Section - 12.4.22, "value_null
/value_not_null
") + (Section + 12.4.23, "value_null
/value_not_null
") for containers of object pointers. For example:@@ -5429,7 +5433,7 @@ CREATE TABLE employee ( of these references.To eliminate redundant database schema references we can use the -
@@ -5473,7 +5477,7 @@ CREATE TABLE employee ( pointer. Also note that an ordered container (Section 5.1, "Ordered Containers") of pointers that is an inverse side of a bidirectional relationship is always treated as unordered - (Section 12.4.17, "inverse
pragma (Section 12.4.13, +inverse
pragma (Section 12.4.14, "inverse
") 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:unordered
") + (Section 12.4.18, "unordered
") 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). @@ -6373,9 +6377,9 @@ CREATE TABLE person (The same principle applies when a composite value type is used as an element of a container, except that instead of
db column
, either thedb value_column
- (Section 12.4.30, "value_column
") or + (Section 12.4.31, "value_column
") ordb key_column
- (Section 12.4.29, "key_column
") + (Section 12.4.30, "key_column
") pragmas are used to specify the column prefix.When a composite value type contains a container, an extra table @@ -6419,8 +6423,8 @@ CREATE TABLE person (
To customize the container table name we can use the -
+db table
pragma (Section - 12.4.18, "table
"), for example:db table
pragma (Section + 12.4.19, "table
"), for example:#pragma db value @@ -8779,7 +8783,7 @@ p.age (age);-To declare a persistent class with the optimistic concurrency model we use the
@@ -9240,6 +9244,12 @@ class personoptimistic
pragma (Section 12.1.5, "optimistic
"). We also use theversion
- pragma (Section 12.4.14, "version
") + pragma (Section 12.4.15, "version
") to specify which data member will store the object version. For example:12.1.11 ++ ++ transient
all non-virtual data members in a persistent class are transient +12.1.12 +12.1.1
@@ -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 thetable
version
pragma - (Section 12.4.14, "version
"). + (Section 12.4.15, "version
"). For example:@@ -9850,6 +9860,15 @@ class employer-For more information on this functionality, refer to Section 12.3.7, "
+definition
".12.1.12
+ +transient
The
+transient
specifier instructs the ODB compiler to + treat all non-virtual data member in the persistent class as transient + (Section 12.4.1, "transient
"). + This specifier is primarily useful when declaring virtual data + members, as discussed in Section 12.4.13, + "virtual
".12.2 View Type Pragmas
A pragma with the
view
qualifier declares a C++ class @@ -9901,6 +9920,12 @@ class employer12.2.6 ++ ++ transient
all non-virtual data members in a view are transient +12.2.7 +For more information on view types refer to Chapter 9, @@ -9966,6 +9991,15 @@ class employer
For more information on this functionality, refer to Section 12.3.7, "
+definition
".12.2.7
+ +transient
The
+transient
specifier instructs the ODB compiler + to treat all non-virtual data member in the view class as transient + (Section 12.4.1, "transient
"). + This specifier is primarily useful when declaring virtual data + members, as discussed in Section 12.4.13, + "virtual
".12.3 Value Type Pragmas
A pragma with the
value
qualifier describes a value @@ -10023,81 +10057,87 @@ class employer+ + ++ transient
all non-virtual data members in a composite value are transient +12.3.8 +unordered
ordered container should be stored unordered -12.3.8 +12.3.9 index_type
database type for a container's index type -12.3.9 +12.3.10 key_type
database type for a container's key type -12.3.10 +12.3.11 value_type
database type for a container's value type -12.3.11 +12.3.12 value_null
/value_not_null
container's value can/cannot be -NULL
12.3.12 +12.3.13 id_options
database options for a container's id column -12.3.13 +12.3.14 index_options
database options for a container's index column -12.3.14 +12.3.15 key_options
database options for a container's key column -12.3.15 +12.3.16 value_options
database options for a container's value column -12.3.16 +12.3.17 id_column
column name for a container's object id -12.3.17 +12.3.18 index_column
column name for a container's index -12.3.18 +12.3.19 key_column
column name for a container's key -12.3.19 +12.3.20 @@ -10407,7 +10447,16 @@ class object }; value_column
column name for a container's value -12.3.20 +12.3.21 12.3.8
+unordered
12.3.8
+ +transient
The
+ +transient
specifier instructs the ODB compiler + to treat all non-virtual data member in the composite value type + as transient (Section 12.4.1, + "transient
"). This specifier is primarily useful + when declaring virtual data members, as discussed in + Section 12.4.13, "virtual
".12.3.9
unordered
The
-unordered
specifier specifies that the ordered container should be stored unordered in the database. The database @@ -10424,7 +10473,7 @@ typedef std::vector<std::string> names; storage in the database, refer to Section 5.1, "Ordered Containers".12.3.9
+index_type
12.3.10
index_type
The
index_type
specifier specifies the native database type that should be used for the ordered container's @@ -10438,7 +10487,7 @@ typedef std::vector<std::string> names; #pragma db value(names) index_type("SMALLINT UNSIGNED")12.3.10
+key_type
12.3.11
key_type
The
key_type
specifier specifies the native database type that should be used for the map container's @@ -10452,7 +10501,7 @@ typedef std::map<unsigned short, float> age_weight_map; #pragma db value(age_weight_map) key_type("INT UNSIGNED")
value_type
value_type
The value_type
specifier specifies the native
database type that should be used for the container's
@@ -10467,11 +10516,11 @@ typedef std::vector<std::string> names;
The value_null
and value_not_null
- (Section 12.3.12,
+ (Section 12.3.13,
"value_null
/value_not_null
") specifiers
can be used to control the NULL semantics of a value column.
value_null
/value_not_null
value_null
/value_not_null
The value_null
and value_not_null
specifiers
specify that the container type's element value can or cannot be
@@ -10499,7 +10548,7 @@ typedef std::vector<shared_ptr<account> > accounts;
as not allowing a NULL
value.
id_options
id_options
The id_options
specifier specifies additional
column definition options that should be used for the container's
@@ -10512,11 +10561,11 @@ typedef std::vector<std::string> nicknames;
The semantics of the id_options
specifier for a container
type are similar to those of the id_options
specifier for
- a container data member (Section 12.4.23,
+ a container data member (Section 12.4.24,
"id_options
").
index_options
index_options
The index_options
specifier specifies additional
column definition options that should be used for the container's
@@ -10529,11 +10578,11 @@ typedef std::vector<std::string> nicknames;
The semantics of the index_options
specifier for a container
type are similar to those of the index_options
specifier for
- a container data member (Section 12.4.24,
+ a container data member (Section 12.4.25,
"index_options
").
key_options
key_options
The key_options
specifier specifies additional
column definition options that should be used for the container's
@@ -10546,11 +10595,11 @@ typedef std::map<std::string, std::string> properties;
The semantics of the key_options
specifier for a container
type are similar to those of the key_options
specifier for
- a container data member (Section 12.4.25,
+ a container data member (Section 12.4.26,
"key_options
").
value_options
value_options
The value_options
specifier specifies additional
column definition options that should be used for the container's
@@ -10563,11 +10612,11 @@ typedef std::set<std::string> nicknames;
The semantics of the value_options
specifier for a container
type are similar to those of the value_options
specifier for
- a container data member (Section 12.4.26,
+ a container data member (Section 12.4.27,
"value_options
").
id_column
id_column
The id_column
specifier specifies the column
name that should be used to store the object id in the
@@ -10581,7 +10630,7 @@ typedef std::vector<std::string> names;
If the column name is not specified, then object_id
is used by default.
index_column
index_column
The index_column
specifier specifies the column
name that should be used to store the element index in the
@@ -10595,7 +10644,7 @@ typedef std::vector<std::string> names;
If the column name is not specified, then index
is used by default.
key_column
key_column
The key_column
specifier specifies the column
name that should be used to store the key in the map
@@ -10609,7 +10658,7 @@ typedef std::map<unsigned short, float> age_weight_map;
If the column name is not specified, then key
is used by default.
value_column
value_column
The value_column
specifier specifies the column
name that should be used to store the element value in the
@@ -10714,111 +10763,117 @@ typedef std::map<unsigned short, float> age_weight_map;
virtual
inverse
version
index
unique
unordered
table
index_type
key_type
value_type
value_null
/value_not_null
NULL
id_options
index_options
key_options
value_options
id_column
index_column
key_column
value_column
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:
+ 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 Section 12.4.13, + "virtual
".
+
+ 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:
#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 (Section 12.4.1, "-id
") - and inverse (Section 12.4.13, + and inverse (Section 12.4.14, "inverse
") data members are automatically treated as read-only and must not be explicitly declared as such. For example: @@ -11539,7 +11599,240 @@ class person as well as whole objects (Section 12.1.4, "readonly
") as read-only. -12.4.13
+inverse
12.4.13
+ +virtual
The
+ +virtual
specifier is used to declare a virtual + data member in an object, view, or composite value type. A virtual + data member is an imaginary 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.To declare a virtual data members we must specify the data + member name using the
+ +member
specifier. We must + also specify the data member type with thevirtual
+ 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 (Section 12.4.5, + "get
/set
/access
"). + For example:+#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_) +}; ++ +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:
+ ++#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) ++ +We can also declare a virtual data member outside the class + scope:
+ ++#pragma db object +class person +{ + ... + + std::string name_; +}; + +#pragma db member(person::name_) transient +#pragma db member(person::name) virtual(std::string) access(name_) ++ +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:
+ ++#pragma db object +class person +{ + ... + + #pragma db transient + std::pair<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) +}; ++ +We can also use virtual data members to implement composite + object ids that are spread over multiple data members:
+ ++#pragma db value +struct name +{ + name () {} + name (std::string const& f, std::string const& 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) +}; ++ +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 +
+ +pimpl
example in theodb-examples
+ package.+#pragma db object +class person +{ +public: + std::string const& name () const; + void name (std::string const&); + + 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(). +}; ++ +The above example also shows that names used for virtual data + members (
+ +name
andage
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.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
+ +transient
specifier + (Section 12.1.12, "transient
+ (object)", + Section 12.3.8, "transient
+ (composite value)", + Section 12.2.7, "transient
+ (view)") + instead of doing it for each individual member. For example:+#pragma db object transient +class person +{ + ... + + std::string first_; // Transient. + std::string last_; // Transient. + + #pragma db member(name) virtual(name) ... +}; ++ +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
+ +point
class + defined in a third-party<point>
header file:+class point +{ +public: + point (); + point (int x, int y); + + int x () const; + int y () const; + + void x (int); + void y (int); + +private: + ... +}; ++ +To convert this class to an ODB composite value type we could + create the
+ +point-mapping.hxx
file with the following + content:+#include <point> + +#pragma db value(point) transient definition +#pragma db member(point::x) virtual(int) +#pragma db member(point::y) virtual(int) ++ +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.
+ +12.4.14
inverse
The
+ (Section 12.4.18, "inverse
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 - (Section 12.4.17, "unordered
").unordered
").For a more detailed discussion of inverse members, refer to Section 6.2, "Bidirectional Relationships".
-12.4.14
+version
12.4.15
version
The
version
specifier specifies that the data member stores the object version used to support optimistic concurrency. If a class @@ -11612,7 +11905,7 @@ class personFor a more detailed discussion of optimistic concurrency, refer to Chapter 11, "Optimistic Concurrency".
-12.4.15
+index
12.4.16
index
The
@@ -11631,7 +11924,7 @@ class personindex
specifier instructs the ODB compiler to define a database index for the data member. For example:For more information on defining database indexes, refer to Section 12.6, "Index Definition Pragmas".
-12.4.16
+unique
12.4.17
unique
The
@@ -11650,7 +11943,7 @@ class personindex
specifier instructs the ODB compiler to define a unique database index for the data member. For example:For more information on defining database indexes, refer to Section 12.6, "Index Definition Pragmas".
-12.4.17
+unordered
12.4.18
unordered
The
-unordered
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 Section 5.1, "Ordered Containers".12.4.18
+table
12.4.19
table
The
@@ -11721,7 +12014,7 @@ class person qualified names, refer to Section 12.1.8, "table
specifier specifies the table name that should be used to store the contents of the container member. For example:schema
". -12.4.19
+index_type
12.4.20
index_type
The
index_type
specifier specifies the native database type that should be used for an ordered container's @@ -11741,7 +12034,7 @@ class person };
key_type
key_type
The key_type
specifier specifies the native
database type that should be used for a map container's
@@ -11761,7 +12054,7 @@ class person
};
-
value_type
value_type
The value_type
specifier specifies the native
database type that should be used for a container's
@@ -11782,11 +12075,11 @@ class person
The value_null
and value_not_null
- (Section 12.4.22,
+ (Section 12.4.23,
"value_null
/value_not_null
") specifiers
can be used to control the NULL semantics of a value column.
value_null
/value_not_null
value_null
/value_not_null
The value_null
and value_not_null
specifiers
specify that a container's element value for the data member can or
@@ -11819,7 +12112,7 @@ class account
Multiset Containers") the element value is automatically treated
as not allowing a NULL
value.
id_options
id_options
The id_options
specifier specifies additional
column definition options that should be used for a container's
@@ -11843,7 +12136,7 @@ class person
of the options
specifier (Section
12.4.8, "options
").
index_options
index_options
The index_options
specifier specifies additional
column definition options that should be used for a container's
@@ -11864,7 +12157,7 @@ class person
of the options
specifier (Section
12.4.8, "options
").
key_options
key_options
The key_options
specifier specifies additional
column definition options that should be used for a container's
@@ -11885,7 +12178,7 @@ class person
of the options
specifier (Section
12.4.8, "options
").
value_options
value_options
The value_options
specifier specifies additional
column definition options that should be used for a container's
@@ -11906,7 +12199,7 @@ class person
of the options
specifier (Section
12.4.8, "options
").
id_column
id_column
The id_column
specifier specifies the column
name that should be used to store the object id in a
@@ -11930,7 +12223,7 @@ class person
If the column name is not specified, then object_id
is used by default.
index_column
index_column
The index_column
specifier specifies the column
name that should be used to store the element index in an
@@ -11954,7 +12247,7 @@ class person
If the column name is not specified, then index
is used by default.
key_column
key_column
The key_column
specifier specifies the column
name that should be used to store the key in a map
@@ -11978,7 +12271,7 @@ class person
If the column name is not specified, then key
is used by default.
value_column
value_column
The value_column
specifier specifies the column
name that should be used to store the element value in a
@@ -12297,9 +12590,9 @@ class object
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 index
(Section
- 12.4.15, "index
") or unique
- (Section 12.4.16, "unique
")
+ be defined using the index
(Section
+ 12.4.16, "index
") or unique
+ (Section 12.4.17, "unique
")
member specifier. For example:
-- cgit v1.1