From 9a1ab7cbfc723909bc96211046cbd8a189dc0d23 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sat, 1 Sep 2012 11:49:15 +0200 Subject: Document virtual data members --- doc/manual.xhtml | 543 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 418 insertions(+), 125 deletions(-) (limited to 'doc') 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. 12.1.9polymorphic 12.1.10session 12.1.11definition + 12.1.12transient @@ -472,6 +473,7 @@ for consistency. 12.2.4pointer 12.2.5callback 12.2.6definition + 12.2.7transient @@ -485,19 +487,20 @@ for consistency. 12.3.5options 12.3.6readonly 12.3.7definition - 12.3.8unordered - 12.3.9index_type - 12.3.10key_type - 12.3.11value_type - 12.3.12value_null/value_not_null - 12.3.13id_options - 12.3.14index_options - 12.3.15key_options - 12.3.16value_options - 12.3.17id_column - 12.3.18index_column - 12.3.19key_column - 12.3.20value_column + 12.3.8transient + 12.3.9unordered + 12.3.10index_type + 12.3.11key_type + 12.3.12value_type + 12.3.13value_null/value_not_null + 12.3.14id_options + 12.3.15index_options + 12.3.16key_options + 12.3.17value_options + 12.3.18id_column + 12.3.19index_column + 12.3.20key_column + 12.3.21value_column @@ -516,24 +519,25 @@ for consistency. 12.4.10column (view) 12.4.11transient 12.4.12readonly - 12.4.13inverse - 12.4.14version - 12.4.15index - 12.4.16unique - 12.4.17unordered - 12.4.18table - 12.4.19index_type - 12.4.20key_type - 12.4.21value_type - 12.4.22value_null/value_not_null - 12.4.23id_options - 12.4.24index_options - 12.4.25key_options - 12.4.26value_options - 12.4.27id_column - 12.4.28index_column - 12.4.29key_column - 12.4.30value_column + 12.4.13virtual + 12.4.14inverse + 12.4.15version + 12.4.16index + 12.4.17unique + 12.4.18unordered + 12.4.19table + 12.4.20index_type + 12.4.21key_type + 12.4.22value_type + 12.4.23value_null/value_not_null + 12.4.24id_options + 12.4.25index_options + 12.4.26key_options + 12.4.27value_options + 12.4.28id_column + 12.4.29index_column + 12.4.30key_column + 12.4.31value_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 - 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 the value_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 - 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:

@@ -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, "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 the db value_column - (Section 12.4.30, "value_column") or + (Section 12.4.31, "value_column") or db 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 optimistic pragma (Section 12.1.5, "optimistic"). We also use the version - pragma (Section 12.4.14, "version") + pragma (Section 12.4.15, "version") to specify which data member will store the object version. For example:

@@ -9240,6 +9244,12 @@ class person 12.1.11 + + transient + all non-virtual data members in a persistent class are transient + 12.1.12 + +

12.1.1 table

@@ -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 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 employer 12.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 value_column column name for a container's value - 12.3.20 + 12.3.21 @@ -10407,7 +10447,16 @@ class object };

-

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")

-

12.3.11 value_type

+

12.3.12 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.

-

12.3.12 value_null/value_not_null

+

12.3.13 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.

-

12.3.13 id_options

+

12.3.14 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").

-

12.3.14 index_options

+

12.3.15 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").

-

12.3.15 key_options

+

12.3.16 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").

-

12.3.16 value_options

+

12.3.17 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").

-

12.3.17 id_column

+

12.3.18 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.

-

12.3.18 index_column

+

12.3.19 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.

-

12.3.19 key_column

+

12.3.20 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.

-

12.3.20 value_column

+

12.3.21 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 + declare a virtual data member + 12.4.13 + + + inverse member is an inverse side of a bidirectional relationship - 12.4.13 + 12.4.14 version member stores object version - 12.4.14 + 12.4.15 index define database index for a member - 12.4.15 + 12.4.16 unique define unique database index for a member - 12.4.16 + 12.4.17 unordered ordered container should be stored unordered - 12.4.17 + 12.4.18 table table name for a container - 12.4.18 + 12.4.19 index_type database type for a container's index type - 12.4.19 + 12.4.20 key_type database type for a container's key type - 12.4.20 + 12.4.21 value_type database type for a container's value type - 12.4.21 + 12.4.22 value_null/value_not_null container's value can/cannot be NULL - 12.4.22 + 12.4.23 id_options database options for a container's id column - 12.4.23 + 12.4.24 index_options database options for a container's index column - 12.4.24 + 12.4.25 key_options database options for a container's key column - 12.4.25 + 12.4.26 value_options database options for a container's value column - 12.4.26 + 12.4.27 id_column column name for a container's object id - 12.4.27 + 12.4.28 index_column column name for a container's index - 12.4.28 + 12.4.29 key_column column name for a container's key - 12.4.29 + 12.4.30 value_column column name for a container's value - 12.4.30 + 12.4.31 @@ -11128,15 +11183,20 @@ class person

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 the virtual + 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 the odb-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 and age 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 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").

+ (Section 12.4.18, "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 person

For a more detailed discussion of optimistic concurrency, refer to Chapter 11, "Optimistic Concurrency".

-

12.4.15 index

+

12.4.16 index

The index specifier instructs the ODB compiler to define a database index for the data member. For example:

@@ -11631,7 +11924,7 @@ class person

For more information on defining database indexes, refer to Section 12.6, "Index Definition Pragmas".

-

12.4.16 unique

+

12.4.17 unique

The index specifier instructs the ODB compiler to define a unique database index for the data member. For example:

@@ -11650,7 +11943,7 @@ class person

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 table specifier specifies the table name that should be used to store the contents of the container member. For example:

@@ -11721,7 +12014,7 @@ class person qualified names, refer to Section 12.1.8, "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 };

-

12.4.20 key_type

+

12.4.21 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 }; -

12.4.21 value_type

+

12.4.22 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.

-

12.4.22 value_null/value_not_null

+

12.4.23 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.

-

12.4.23 id_options

+

12.4.24 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").

-

12.4.24 index_options

+

12.4.25 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").

-

12.4.25 key_options

+

12.4.26 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").

-

12.4.26 value_options

+

12.4.27 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").

-

12.4.27 id_column

+

12.4.28 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.

-

12.4.28 index_column

+

12.4.29 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.

-

12.4.29 key_column

+

12.4.30 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.

-

12.4.30 value_column

+

12.4.31 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