From f22c9c10eb07c93be47549410e0352b0dfbd598a Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 8 Nov 2011 09:58:33 +0200 Subject: Document optimistic concurrency --- NEWS | 11 +- doc/manual.xhtml | 1297 ++++++++++++++++++++++++++++++++++++------------------ 2 files changed, 873 insertions(+), 435 deletions(-) diff --git a/NEWS b/NEWS index 1f6e87d..b6e1ca0 100644 --- a/NEWS +++ b/NEWS @@ -1,18 +1,19 @@ Version 1.7.0 - * Support for optimistic concurrency. For more information refer to the - 'optimistic' example in the odb-examples package. + * Support for optimistic concurrency. For more information refer to Chapter + 11, "Optimistic Concurrency" in the ODB manual as well as the 'optimistic' + example in the odb-examples package. * Support for read-only objects, composite value types, and data members. The new readonly pragma can be used to declare one of these entities as read-only. Constant data members are automatically treated as read-only. - For more information, refer to Section 11.1.4 "readonly (object)", - Section 11.3.6 "readonly (composite value)", and Section 11.4.10 + For more information, refer to Section 12.1.4 "readonly (object)", + Section 12.3.6 "readonly (composite value)", and Section 12.4.10 "readonly (data member)" in the ODB manual. * Support for persistent classes without object ids. Such objects have to be explicitly declared as not having object id and they have limited - functionality. For more information, refer to Section 11.1.5 "id", in + functionality. For more information, refer to Section 12.1.5 "id", in the ODB manual. * Support for mapping char[N], unsigned char[N], and std::vector - 11ODB Pragma Language + 11Optimistic Concurrency + + + + 12ODB Pragma Language - - - - - @@ -530,16 +536,16 @@ for consistency. - - + - + - + - + - + - + - + - + - + - + - + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - +
11.1Object Type Pragmas + 12.1Object Type Pragmas - - - - - - + + + + + + +
11.1.1table
11.1.2pointer
11.1.3abstract
11.1.4readonly
11.1.5id
11.1.6callback
12.1.1table
12.1.2pointer
12.1.3abstract
12.1.4readonly
12.1.5optimistic
12.1.6id
12.1.7callback
11.2View Type Pragmas + 12.2View Type Pragmas - - - - - + + + + +
11.2.1object
11.2.2table
11.2.3query
11.2.4pointer
11.2.5callback
12.2.1object
12.2.2table
12.2.3query
12.2.4pointer
12.2.5callback
11.3Value Type Pragmas + 12.3Value Type Pragmas - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + +
11.3.1type
11.3.2id_type
11.3.3null/not_null
11.3.4default
11.3.5options
11.3.6readonly
11.3.7unordered
11.3.8index_type
11.3.9key_type
11.3.10value_type
11.3.11value_null/value_not_null
11.3.12id_options
11.3.13index_options
11.3.14key_options
11.3.15value_options
11.3.16id_column
11.3.17index_column
11.3.18key_column
11.3.19value_column
12.3.1type
12.3.2id_type
12.3.3null/not_null
12.3.4default
12.3.5options
12.3.6readonly
12.3.7unordered
12.3.8index_type
12.3.9key_type
12.3.10value_type
12.3.11value_null/value_not_null
12.3.12id_options
12.3.13index_options
12.3.14key_options
12.3.15value_options
12.3.16id_column
12.3.17index_column
12.3.18key_column
12.3.19value_column
11.4Data Member Pragmas + 12.4Data Member Pragmas - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + +
11.4.1id
11.4.2auto
11.4.3type
11.4.4null/not_null
11.4.5default
11.4.6options
11.4.7column (object, composite value)
11.4.8column (view)
11.4.9transient
11.4.10readonly
11.4.11inverse
11.4.12unordered
11.4.13table
11.4.14index_type
11.4.15key_type
11.4.16value_type
11.4.17value_null/value_not_null
11.4.18id_options
11.4.19index_options
11.4.20key_options
11.4.21value_options
11.4.22id_column
11.4.23index_column
11.4.24key_column
11.4.25value_column
12.4.1id
12.4.2auto
12.4.3type
12.4.4null/not_null
12.4.5default
12.4.6options
12.4.7column (object, composite value)
12.4.8column (view)
12.4.9transient
12.4.10readonly
12.4.11inverse
12.4.12version
12.4.13unordered
12.4.14table
12.4.15index_type
12.4.16key_type
12.4.17value_type
12.4.18value_null/value_not_null
12.4.19id_options
12.4.20index_options
12.4.21key_options
12.4.22value_options
12.4.23id_column
12.4.24index_column
12.4.25key_column
12.4.26value_column
11.5C++ Compiler Warnings + 12.5C++ Compiler Warnings - - - - - + + + + +
11.5.1GNU C++
11.5.2Visual C++
11.5.3Sun C++
11.5.4IBM XL C++
11.5.5HP aC++
12.5.1GNU C++
12.5.2Visual C++
12.5.3Sun C++
12.5.4IBM XL C++
12.5.5HP aC++
12MySQL Database + 13MySQL Database - - - - + + + + - @@ -548,20 +554,20 @@ for consistency. - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - +
12.1MySQL Type Mapping
12.2MySQL Database Class
12.3MySQL Connection and Connection Factory
12.4MySQL Exceptions
13.1MySQL Type Mapping
13.2MySQL Database Class
13.3MySQL Connection and Connection Factory
13.4MySQL Exceptions
12.5MySQL Limitations + 13.5MySQL Limitations - +
12.5.1Foreign Key Constraints
13.5.1Foreign Key Constraints
13SQLite Database + 14SQLite Database - - - - + + + + - @@ -570,20 +576,20 @@ for consistency. - - + - + - + - + - +
13.1SQLite Type Mapping
13.2SQLite Database Class
13.3SQLite Connection and Connection Factory
13.4SQLite Exceptions
14.1SQLite Type Mapping
14.2SQLite Database Class
14.3SQLite Connection and Connection Factory
14.4SQLite Exceptions
13.5SQLite Limitations + 14.5SQLite Limitations - - - - - + + + + +
13.5.1Query Result Caching
13.5.2Automatic Assignment of Object Ids
13.5.3Foreign Key Constraints
13.5.4Constraint Violations
13.5.5Sharing of Queries
14.5.1Query Result Caching
14.5.2Automatic Assignment of Object Ids
14.5.3Foreign Key Constraints
14.5.4Constraint Violations
14.5.5Sharing of Queries
14PostgreSQL Database + 15PostgreSQL Database - - - - + + + + - @@ -596,21 +602,21 @@ for consistency. - + - - + - + - + - + + + + + + + - + - +
14.1PostgreSQL Type Mapping
14.2PostgreSQL Database Class
14.3PostgreSQL Connection and Connection Factory
14.4PostgreSQL Exceptions
15.1PostgreSQL Type Mapping
15.2PostgreSQL Database Class
15.3PostgreSQL Connection and Connection Factory
15.4PostgreSQL Exceptions
14.5PostgreSQL Limitations + 15.5PostgreSQL Limitations - - - - - + + + + +
14.5.1Query Result Caching
14.5.2Foreign Key Constraints
14.5.3Date-Time Format
14.5.4Timezones
14.5.5NUMERIC Type Support
15.5.1Query Result Caching
15.5.2Foreign Key Constraints
15.5.3Date-Time Format
15.5.4Timezones
15.5.5NUMERIC Type Support
15Profiles Introduction16Profiles Introduction
16Boost Profile + 17Boost Profile - - - + + + - @@ -619,24 +625,25 @@ for consistency. - - - + + - @@ -759,7 +766,8 @@ for consistency. - + +
16.1Smart Pointers Library
16.2Unordered Containers Library
16.3Optional Library
17.1Smart Pointers Library
17.2Unordered Containers Library
17.3Optional Library
16.4Date Time Library + 17.4Date Time Library - - - + + +
16.4.1MySQL Database Type Mapping
16.4.2SQLite Database Type Mapping
16.4.3PostgreSQL Database Type Mapping
17.4.1MySQL Database Type Mapping
17.4.2SQLite Database Type Mapping
17.4.3PostgreSQL Database Type Mapping
17Qt Profile + 18Qt Profile - + + +
17.1Basic Types Library + 18.1Basic Types Library - - -
17.1.1MySQL Database Type Mapping
17.1.2SQLite Database Type Mapping
17.1.3PostgreSQL Database Type Mapping
+
18.1.1MySQL Database Type Mapping
18.1.2SQLite Database Type Mapping
18.1.3PostgreSQL Database Type Mapping
17.2Smart Pointers Library
17.3Containers Library
18.2Smart Pointers Library
18.3Containers Library
17.4Date Time Library + 18.4Date Time Library - - - + + +
17.4.1MySQL Database Type Mapping
17.4.2SQLite Database Type Mapping
17.4.3PostgreSQL Database Type Mapping
18.4.1MySQL Database Type Mapping
18.4.2SQLite Database Type Mapping
18.4.3PostgreSQL Database Type Mapping
8Inheritance
9Views
10Session
11ODB Pragma Language
11Optimistic Concurrency
12ODB Pragma Language
@@ -1376,7 +1384,7 @@ main (int argc, char* argv[]) database name, etc., from the command line. In your own applications you may prefer to use other mysql::database constructors which allow you to pass this information directly - (Section 12.2, "MySQL Database Class").

+ (Section 13.2, "MySQL Database Class").

Next, we create three person objects. Right now they are transient objects, which means that if we terminate the application @@ -2033,12 +2041,12 @@ class person

While it is possible to declare a persistent class without an object id, such a class will have limited functionality - (Section 11.1.5, "id").

+ (Section 12.1.6, "id").

The above two pragmas are the minimum required to declare a persistent class with an object id. Other pragmas can be used to fine-tune the database-related properties of a class and its - members (Chapter 11, "ODB Pragma Language").

+ members (Chapter 12, "ODB Pragma Language").

Normally, an object class should define the default constructor. The generated database support code uses this constructor when @@ -2084,7 +2092,7 @@ private: mapping to the database system type and, possibly, the code to convert between the two. For more information on how to achieve this refer to the db type pragma description - in Section 11.3.1, "type". Similar + in Section 12.3.1, "type". Similar to object types, composite value types have to be explicitly declared as persistent using the db value pragma, for example:

@@ -2201,8 +2209,8 @@ class person }; -

Refer to Section 11.1.2, "pointer - (object)" and Section 11.2.4, "pointer +

Refer to Section 12.1.2, "pointer + (object)" and Section 12.2.4, "pointer (view)" for more information on this pragma.

Built-in support that is provided by the ODB runtime library allows us @@ -2326,7 +2334,7 @@ namespace odb our application. To map persistent classes to custom database schemas, ODB provides a wide range of mapping customization pragmas, such as db table, db column, - and db type (Chapter 11, "ODB Pragma + and db type (Chapter 12, "ODB Pragma Language"). For sample code that shows how to perform such mapping for various C++ constructs, refer to the schema/custom example in the odb-examples package.

@@ -2778,7 +2786,7 @@ for (unsigned short retry_count (0); ; retry_count++)

The first persist() function expects a constant reference to an instance being persisted. The second function expects a constant object pointer. Both of these functions can only be used on objects with - application-assigned object ids (Section 11.4.2, + application-assigned object ids (Section 12.4.2, "auto").

The second and third persist() functions are similar to the @@ -2866,6 +2874,47 @@ db.load (jane_id, *jane); t.commit (); +

In certain situations it may be necessary to reload the state + of an object from the database. While this is easy to achieve + using the second load() function, ODB provides + the database::reload() function template that + has a number of special properties. This function has two + overloaded versions with the following signatures:

+ +
+  template <typename T>
+  void
+  reload (T& object);
+
+  template <typename T>
+  void
+  reload (const object_traits<T>::pointer_type& object);
+  
+ +

The first reload() function expects an object + reference, while the second expects an object pointer. Both + functions expect the id member in the passed object to contain + a valid object identifier and, similar to load(), + both will throw odb::object_not_persistent if + there is no object of this type with this id in the database.

+ +

The first special property of reload() + compared to the load() function is that it + does not interact with the session object cache + (Section 10.1, "Object Cache"). That is, if + the object being reloaded is already in the cache, then it will + remain there after reload() returns. Similarly, if the + object is not in the cache, then reload() won't + put it there either.

+ +

The second special property of the reload() function + only manifests itself when operating on object with optimistic + concurrency model. In this case, if the states of the object + in the application memory and in the database are the same, then + no reloading will occur. For more information on optimistic + concurrency, refer to Chapter 11, "Optimistic + Concurrency".

+

If we don't know for sure whether an object with a given id is persistent, we can use the find() function instead of load(), for example:

@@ -2917,7 +2966,7 @@ t.commit (); while the other two expect object pointers. If the object passed to one of these functions does not exist in the database, update() throws the odb::object_not_persistent - exception.

+ exception (but see a note on optimistic concurrency below).

Below is an example of the funds transfer that we talked about in the earlier section on transactions. It uses the hypothetical @@ -2974,11 +3023,23 @@ db.update (from); t.commit (); -

In ODB persistent classes, composite value types, as well as individual - data members can be declared read-only (see Section - 11.1.4, "readonly (object)", Section - 11.3.6, "readonly (composite value)", and - Section 11.4.10, "readonly +

If any of the update() functions are operating on a + persistent class with optimistic concurrency model, then they will throw + the odb::object_changed exception if the state of the + object in the database has changed since it was last loaded into the + application memory. Furthermore, for such classes, update() + no longer throws the object_not_persistent exception if + there is no such object in the database. Instead, this condition is + treated as a change of object state and object_changed + is thrown instead. For a more detailed discussion of optimistic + concurrency, refer to Chapter 11, "Optimistic + Concurrency".

+ +

In ODB, persistent classes, composite value types, as well as individual + data members can be declared read-only (see Section + 12.1.4, "readonly (object)", Section + 12.3.6, "readonly (composite value)", and + Section 12.4.10, "readonly (data member)").

If an individual data member is declared read-only, then @@ -3026,7 +3087,8 @@ t.commit (); object unchanged. It simply becomes transient. The last function uses the object id to identify the object to be deleted. If the object does not exist in the database, then all four functions - throw the odb::object_not_persistent exception.

+ throw the odb::object_not_persistent exception + (but see a note on optimistic concurrency below).

We have to specify the object type when calling the last erase() function. The same is unnecessary for the @@ -3048,6 +3110,18 @@ db.erase<person> (joe_id); t.commit (); +

If any of the erase() functions except the last + one are operating on a persistent class with optimistic concurrency + model, then they will throw the odb::object_changed exception + if the state of the object in the database has changed since it was + last loaded into the application memory. Furthermore, for such + classes, erase() no longer throws the + object_not_persistent exception if there is no such + object in the database. Instead, this condition is treated as a + change of object state and object_changed is thrown + instead. For a more detailed discussion of optimistic concurrency, + refer to Chapter 11, "Optimistic Concurrency".

+

The erase_query() function allows us to delete the state of multiple objects matching certain criteria. It uses the query expression of the database::query() function @@ -3270,6 +3344,12 @@ namespace odb what () const throw (); }; + struct object_changed: exception + { + virtual const char* + what () const throw (); + }; + struct result_not_cached: exception { virtual const char* @@ -3327,12 +3407,19 @@ namespace odb for details.

The object_not_persistent exception is thrown - by the load() and update() - database functions. Refer to - Section 3.8, "Loading Persistent Objects" and - Section 3.9, "Updating Persistent Objects" for + by the load(), update(), and + erase() database functions. Refer to + Section 3.8, "Loading Persistent Objects", + Section 3.9, "Updating Persistent Objects", and + Section 3.10, "Deleting Persistent Objects" for more information.

+

The object_changed exception is thrown + by the update() database function and certain + erase() database functions when + operating on objects with optimistic concurrency model. See + Chapter 11, "Optimistic Concurrency" for details.

+

The result_not_cached exception is thrown by the query result class. Refer to Section 4.4, "Query Result" for details.

@@ -4063,7 +4150,7 @@ private:

A number of ODB pragmas allow us to customize the table name, column names, and native database types of an ordered container both, on the per-container and per-member basis. For more information on - these pragmas, refer to Chapter 11, "ODB Pragma + these pragmas, refer to Chapter 12, "ODB Pragma Language". The following example shows some of the possible customizations:

@@ -4089,8 +4176,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 11.3.7, - "unordered", Section 11.4.12, + db unordered pragma (Section 12.3.7, + "unordered", Section 12.4.13, "unordered"). For example:

@@ -4151,7 +4238,7 @@ private:
   

A number of ODB pragmas allow us to customize the table name, column names, and native database types of a set container, both on the per-container and per-member basis. For more information on - these pragmas, refer to Chapter 11, "ODB Pragma + these pragmas, refer to Chapter 12, "ODB Pragma Language". The following example shows some of the possible customizations:

@@ -4213,7 +4300,7 @@ private:

A number of ODB pragmas allow us to customize the table name, column names, and native database types of a map container, both on the per-container and per-member basis. For more information on - these pragmas, refer to Chapter 11, "ODB Pragma + these pragmas, refer to Chapter 12, "ODB Pragma Language". The following example shows some of the possible customizations:

@@ -4340,11 +4427,11 @@ class employee

By default, an object pointer can be NULL. To specify that a pointer always points to a valid object we can - use the not_null pragma (Section - 11.4.4, "null/not_null") for + use the not_null pragma (Section + 12.4.4, "null/not_null") for single object pointers and the value_not_null pragma - (Section - 11.4.17, "value_null/value_not_null") + (Section + 12.4.18, "value_null/value_not_null") for containers of object pointers. For example:

@@ -4590,7 +4677,7 @@ CREATE TABLE employee_projects (
 
   

To obtain a more canonical database schema, the names of tables and columns above can be customized using ODB pragmas - (Chapter 11, "ODB Pragma Language"). For example:

+ (Chapter 12, "ODB Pragma Language"). For example:

 #pragma db object
@@ -4713,7 +4800,7 @@ CREATE TABLE employee (
      of these references.

To eliminate redundant database schema references we can use the - inverse pragma (Section 11.4.11, + inverse pragma (Section 12.4.11, "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:

@@ -4757,7 +4844,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 11.4.12, "unordered") + (Section 12.4.13, "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).

@@ -5321,7 +5408,7 @@ t.commit (); mapping for each database system refer to Part II, Database Systems. We can also provide a custom mapping for these or our own value types using the db type - pragma (Section 11.3.1, "type").

+ pragma (Section 12.3.1, "type").

7.2 Composite Value Types

@@ -5460,8 +5547,8 @@ t.commit ();

Customizing a column name for a data member of a simple value type is straightforward: we simply specify the desired name with - the db column pragma (Section - 11.4.7, "column"). For composite value + the db column pragma (Section + 12.4.7, "column"). For composite value types things are slightly more complex since they are mapped to multiple columns. Consider the following example:

@@ -5562,9 +5649,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 11.4.25, "value_column") or + (Section 12.4.26, "value_column") or db key_column - (Section 11.4.24, "key_column") + (Section 12.4.25, "key_column") pragmas are used to specify the column prefix.

When a composite value type contains a container, an extra table @@ -5608,8 +5695,8 @@ CREATE TABLE person (

To customize the container table name we can use the - db table pragma (Section - 11.4.13, "table"), for example:

+ db table pragma (Section + 12.4.14, "table"), for example:

 #pragma db value
@@ -5650,7 +5737,7 @@ CREATE TABLE person_nickname (
      of a valid value in a column. While by default ODB maps
      values to columns that do not allow NULL values,
      it is possible to change that with the db null
-     pragma (Section 11.4.4,
+     pragma (Section 12.4.4,
      "null/not_null").

To properly support the NULL semantics, the @@ -5775,7 +5862,7 @@ namespace odb consider using a more efficient implementation of the optional value concept such as the optional class template from Boost - (Section 16.3, "Optional Library").

+ (Section 17.3, "Optional Library").

Another common C++ representation of a value that can be NULL is a pointer. ODB will automatically @@ -5964,7 +6051,7 @@ public: instances of a base class from being stored in the database. To achieve this a persistent class can be declared abstract using the db abstract - pragma (Section 11.1.3, "abstract"). + pragma (Section 12.1.3, "abstract"). Note that a C++-abstract class, or a class that has one or more pure virtual functions and therefore cannot be instantiated, is also database-abstract. However, a @@ -6219,8 +6306,8 @@ t.commit ();

9.1 Object Views

To associate one or more objects with a view we use the - db object pragma (Section - 11.2.1, "object"). We have already seen + db object pragma (Section + 12.2.1, "object"). We have already seen a simple, single-object view in the introduction to this chapter. To associate the second and subsequent objects we repeat the db object pragma for each additional object, @@ -6401,7 +6488,7 @@ struct employee_birth_code or the match is ambiguous, the ODB compiler will issue an error. To associate two differently-named members or to resolve an ambiguity, we can explicitly specify the member association using the - db column pragma (Section 11.4.7, + db column pragma (Section 12.4.7, "column"). For example:

@@ -6417,8 +6504,8 @@ struct employee_employer
   

If an object data member specifies the SQL type with - the db type pragma (Section - 11.4.3, "type"), then this type is also used for + the db type pragma (Section + 12.4.3, "type"), then this type is also used for the associated view data members.

Note also that similar to join conditions, if we assign an alias to @@ -6608,7 +6695,7 @@ t.commit (); ad-hoc tables that are not mapped to persistent classes.

To associate one or more tables with a view we use the - db table pragma (Section 11.2.2, + db table pragma (Section 12.2.2, "table"). To associate the second and subsequent tables we repeat the db table pragma for each additional table. For example, the following view is based on the @@ -6809,7 +6896,7 @@ struct employee_prev_employer

Object, table, and mixed views can also specify an optional query condition that should be used whenever the database is queried for this view. To specify a query condition we use the - db query pragma (Section 11.2.3, + db query pragma (Section 12.2.3, "query").

As an example, consider a view that returns some information about @@ -7115,8 +7202,7 @@ struct employee_name

A session is an application's unit of work that may encompass several database transactions. In this version of ODB a session is just an object cache. In future versions it will provide additional - functionality, such as automatic object state change tracking - and optimistic concurrency.

+ functionality, such as automatic object state change tracking.

Each thread of execution in an application can have only one active session at a time. A session is started by creating an instance of @@ -7300,6 +7386,7 @@ unsigned long id1 (save (db, p1)); // p1 is cached in s as non-const. transaction t (db.begin ()); shared_ptr<person> p (db.load<person> (id1)); // p == p1 p->age (30); // Undefined behavior since p1 was created const. + t.commit (); } shared_ptr<const person> p2 (new person ("Jane", "Doe")); @@ -7309,15 +7396,294 @@ unsigned long id2 (save (db, p2)); // p2 is cached in s as non-const. transaction t (db.begin ()); shared_ptr<person> p (db.load<person> (id2)); // p == p2 p->age (30); // Ok, since p2 was not created const. + t.commit (); +} +

+ + + + +
+

11 Optimistic Concurrency

+ +

The ODB transaction model (Section 3.4, + "Transactions") guarantees consistency as long as we perform all the + database operations corresponding to a specific application transaction + in a single database transaction. That is, if we load an object within a + database transaction and update it in the same transaction, then we are + guaranteed that the object state that we are updating in the database is + exactly the same as the state we have loaded. In other words, it is + impossible for another process or thread to modify the object state + in the database between these load and update operations.

+ +

In this chapter we use the term application transaction + to refer to a set of operations on persistent objects that an + application needs to perform in order to implement some + application-specific functionality. The term database + transaction refers to the set of database operations + performed between the ODB begin() and commit() + calls. Up until now we treated application transactions and database + transactions as essentially the same thing.

+ +

While this model is easy to understand and straightforward to use, + it may not be suitable for applications that have long application + transactions. The canonical example of such a situation is an + application transaction that requires user input between loading + an object and updating it. Such an operation may take an arbitrary + long time to complete and performing it within a single database + transaction will consume database resources as well as prevent + other processes/threads from updating the object for too long.

+ +

The solution to this problem is to break up the long-lived + application transaction into several short-lived database + transaction. In our example that would mean loading the object + in one database transaction, waiting for user input, and then + updating the object in another database transaction. For example:

+ +
+unsigned long id = ...;
+person p;
+
+{
+  transaction t (db.begin ());
+  db.load (id, p);
+  t.commit ();
+}
+
+unsigned short age;
+cin >> age;
+p.age (age);
+
+{
+  transaction t (db.begin ());
+  db.update (p);
+  t.commit ();
+}
+  
+ +

This approach works well if we have only one process/thread that can ever + update the object. However, if we have multiple processes/threads + modifying the same object, then this approach does not guarantee + consistency anymore. Consider what happens in the above example if + another process updates the person's last name while we are waiting for + the user input. Since we loaded the object before this change occured, + our version of the person's data will still have the old name. Once we + receive the input from the user, we go ahead and update the object, + overwriting both the old age with the new one (correct) and the new name + with the old one (incorrect).

+ +

While there is no way to restore the consistency guarantee in + an application transaction that consists of multiple database + transactions, ODB provides a mechanism, called optimistic + concurrency, that allows applications to detect and potentially + recover from such inconsistencies.

+ +

In essence, optimistic concurrency model detects mismatches + between the current object state in the database and the state + when it was loaded into the application memory. Such a mismatch + would mean that the object was changed by another process or + thread. There are several ways to implement such state mismatch + detection. Currently, ODB uses object versioning while other + methods, such as timestamps, may be supported in the future.

+ +

To declare a persistent class with optimistic concurrency model we use + the optimistic pragma (Section 12.1.5, + "optimistic"). We also use the version + pragma (Section 12.4.12, "version") + to specify which data member will store the object version. For + example:

+ +
+#pragma db object optimistic
+class person
+{
+  ...
+
+  #pragma db version
+  unsigned long version_;
+};
+  
+ +

The version data members is managed by ODB. It is initialized to + 1 when the object is made persistent and incremented + by 1 with each update. The 0 version value + is not used by ODB and the application can use it as a special value, + for example, to indicate that the object is transient. Note that + for optimistic concurrency to function properly, the application + should not modify the version member after making the object persistent + or loading it from the database and until deleting the state of this + object from the database.

+ +

When we call the database::update() function + (Section 3.9, "Updating Persistent Objects") and pass + an object that has outdated state, the odb::object_changed + exception is thrown. At this point the application has two + recovery options: it can abort and potentially restart the + application transaction or it can reload the new object + state from the database, re-apply or merge the changes, and call + update() again. Note that aborting an application + transaction that performs updates in multiple database transactions + may requires reverting changes that has already been committed to + the database. As a result, this strategy works best if all the + updates are performed in the last database transaction of the + application transaction. This way the changes can be reverted + by simply rolling back this last database transaction.

+ +

The following example shows how we can reimplement the above + transaction using the second recovery option:

+ +
+unsigned long id = ...;
+person p;
+
+{
+  transaction t (db.begin ());
+  db.load (id, p);
+  t.commit ();
+}
+
+unsigned short age;
+cin >> age;
+p.age (age);
+
+{
+  transaction t (db.begin ());
+
+  try
+  {
+    db.update (p);
+  }
+  catch (const object_changed&)
+  {
+    db.reload (p);
+    p.age (age);
+    db.update (p);
+  }
+
+  t.commit ();
+}
+  
+ +

An important point to note in the above code fragment is that the second + update() call cannot throw the object_changed + exception because we are reloading the state of the object + and updating it within the same database transaction.

+ +

Depending on the recovery strategy employed by the application, + an application transaction with a failed update can be significantly + more expensive than a successful one. As a result, optimistic + concurrency works best for situations with low to medium contention + levels where the majority of the application transactions complete + without update conflicts.

+ +

In addition to updates, ODB also performs state mismatch detection + when we are deleting an object from the database + (Section 3.10, "Deleting Persistent Objects"). + To understand why this can be important, consider the following + application transaction:

+ +
+unsigned long id = ...;
+person p;
+
+{
+  transaction t (db.begin ());
+  db.load (id, p);
+  t.commit ();
+}
+
+string answer;
+cerr << "age is " << p.age () << ", delete?" << endl;
+getline (cin, answer);
+
+if (answer == "yes")
+{
+  transaction t (db.begin ());
+  db.erase (p);
+  t.commit ();
 }
   
+

Consider again what happens if another process or thread updates + the object by changing the person's age while we are waiting for + the user input. In this case, the user makes the decision based on + certain age while we may delete (or not delete) an object that has + a completely different age. Here is how we can fix this problem + using optimistic concurrency:

+ +
+unsigned long id = ...;
+person p;
+
+{
+  transaction t (db.begin ());
+  db.load (id, p);
+  t.commit ();
+}
+
+string answer;
+for (bool done (false); !done; )
+{
+  if (answer.empty ())
+    cerr << "age is " << p.age () << ", delete?" << endl;
+  else
+    cerr << "age changed to " << p.age () << ", still delete?" << endl;
+
+  getline (cin, answer);
+
+  if (answer == "yes")
+  {
+    transaction t (db.begin ());
+
+    try
+    {
+      db.erase (p);
+      done = true;
+    }
+    catch (const object_changed&)
+    {
+      db.reload (p);
+    }
+
+    t.commit ();
+  }
+  else
+    done = true;
+}
+  
+ +

Note that the state mismatch detection is performed only if we delete + an object by passing the object instance to the erase() + function. If we want to delete an object with optimistic concurrency + model regardless of its state, then we need to use the erase() + function that deletes an object given its id, for example:

+ +
+{
+  transaction t (db.begin ());
+  db.erase (p.id ());
+  t.commit ();
+}
+  
+ +

Finally note that for persistent classes with optimistic concurrency + model both the update() function and the + erase() function that accepts an object instance as its + argument no longer throw the object_not_persistent + exception if there is no such object in the database. Instead, + this condition is treated as a change of object state and the + object_changed exception is thrown instead.

+ +

For complete sample code that shows how to use optimistic + concurrency, refer to the optimistic example in + the odb-examples package.

+
-

11 ODB Pragma Language

+

12 ODB Pragma Language

As we have already seen in previous chapters, ODB uses a pragma-based language to capture database-specific information about C++ types. @@ -7481,10 +7847,10 @@ class person the C++ compiler to build the application. Some C++ compilers issue warnings about pragmas that they do not recognize. There are several ways to deal with this problem which are covered - at the end of this chapter in Section 11.5, + at the end of this chapter in Section 12.5, "C++ Compiler Warnings".

-

11.1 Object Type Pragmas

+

12.1 Object Type Pragmas

A pragma with the object qualifier declares a C++ class as a persistent object type. The qualifier can be optionally followed, @@ -7501,42 +7867,48 @@ class person

table table name for a persistent class11.1.112.1.1
pointer pointer type for a persistent class11.1.212.1.2
abstract persistent class is abstract11.1.312.1.3
readonly persistent class is read-only11.1.412.1.4
optimisticpersistent class with optimistic concurrency model12.1.5
id persistent class has no object id11.1.512.1.6
callback database operations callback11.1.612.1.7
-

11.1.1 table

+

12.1.1 table

The table specifier specifies the table name that should be used to store objects of a class in a relational database. For @@ -7553,7 +7925,7 @@ class person

If the table name is not specified, the class name is used as the table name.

-

11.1.2 pointer

+

12.1.2 pointer

The pointer specifier specifies the object pointer type for a persistent class. The object pointer type is used to return, @@ -7603,7 +7975,7 @@ class person

For a more detailed discussion of object pointers, refer to Section 3.2, "Object and View Pointers".

-

11.1.3 abstract

+

12.1.3 abstract

The abstract specifier specifies that a persistent class is abstract. An instance of an abstract class cannot be stored in @@ -7635,7 +8007,7 @@ class contractor: public person discussion of persistent class inheritance, refer to Chapter 8, "Inheritance".

-

11.1.4 readonly

+

12.1.4 readonly

The readonly specifier specifies that the persistent class is read-only. The database state of read-only objects cannot be @@ -7660,11 +8032,40 @@ class person read-only while the rest is treated as read-write.

Note that it is also possible to declare individual data members - (Section 11.4.10, "readonly") - as well as composite value types (Section 11.3.6, + (Section 12.4.10, "readonly") + as well as composite value types (Section 12.3.6, "readonly") as read-only.

-

11.1.5 id

+

12.1.5 optimistic

+ +

The optimistic specifier specifies that the persistent class + has optimistic concurrency model. A class with optimistic concurrency + model must also specify the data member that is used to store the + object version using the version pragma + (Section 12.4.12, "version"). + For example:

+ +
+#pragma db object optimistic
+class person
+{
+  ...
+
+  #pragma db version
+  unsigned long version_;
+};
+  
+ +

If a base class has optimistic concurrency model then all its derived + classes will automatically have optimistic concurrency model. The + current implementation also requires that in any given inheritance + hierarchy the object id and the version data members reside in the + same class.

+ +

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

+ +

12.1.6 id

The id specifier specifies that the persistent class has no object id. It should be followed by opening and closing @@ -7700,10 +8101,10 @@ class person (Section 10.1, "Object Cache") either.

To declare a persistent class with an object id, use the data member - id specifier (Section 11.4.1, + id specifier (Section 12.4.1, "id").

-

11.1.6 callback

+

12.1.7 callback

The callback specifier specifies the persist class member function that should be called before and after a @@ -7821,7 +8222,7 @@ private: }; -

11.2 View Type Pragmas

+

12.2 View Type Pragmas

A pragma with the view qualifier declares a C++ class as a view type. The qualifier can be optionally followed, @@ -7839,31 +8240,31 @@ private:

object object associated with a view11.2.112.2.1
table table associated with a view11.2.212.2.2
query view query condition11.2.312.2.3
pointer pointer type for a view11.2.412.2.4
callback database operations callback11.2.512.2.5
@@ -7871,21 +8272,21 @@ private:

For more information on view types refer to Chapter 9, "Views".

-

11.2.1 object

+

12.2.1 object

The object specifier specifies a persistent class that should be associated with a view. For more information on object associations refer to Section 9.1, "Object Views".

-

11.2.2 table

+

12.2.2 table

The table specifier specifies a database table that should be associated with a view. For more information on table associations refer to Section 9.2, "Table Views".

-

11.2.3 query

+

12.2.3 query

The query specifier specifies a query condition for an object or table view or a native SQL query for a native @@ -7895,16 +8296,16 @@ private: Query Conditions". For more information on native SQL queries, refer to Section 9.5, "Native Views".

-

11.2.4 pointer

+

12.2.4 pointer

The pointer specifier specifies the view pointer type for a view class. Similar to objects, the view pointer type is used to return dynamically allocated instances of a view class. The semantics of the pointer specifier for a view are the same as those of the pointer specifier for an object - (Section 11.1.2, "pointer").

+ (Section 12.1.2, "pointer").

-

11.2.5 callback

+

12.2.5 callback

The callback specifier specifies the view class member function that should be called before and after an @@ -7912,13 +8313,13 @@ private: result iteration. The semantics of the callback specifier for a view are similar to those of the callback specifier for an object - (Section 11.1.6, "callback") + (Section 12.1.7, "callback") except that the only events that can trigger a callback call in the case of a view are pre_load and post_load.

-

11.3 Value Type Pragmas

+

12.3 Value Type Pragmas

A pragma with the value qualifier describes a value type. It can be optionally followed, in any order, by one or more @@ -7935,121 +8336,121 @@ private:

type database type for a value type11.3.112.3.1
id_type database type for a value type when used as an object id11.3.212.3.2
null/not_null type can/cannot be NULL11.3.312.3.3
default default value for a value type11.3.412.3.4
options database options for a value type11.3.512.3.5
readonly composite value type is read-only11.3.612.3.6
unordered ordered container should be stored unordered11.3.712.3.7
index_type database type for a container's index type11.3.812.3.8
key_type database type for a container's key type11.3.912.3.9
value_type database type for a container's value type11.3.1012.3.10
value_null/value_not_null container's value can/cannot be NULL11.3.1112.3.11
id_options database options for a container's id column11.3.1212.3.12
index_options database options for a container's index column11.3.1312.3.13
key_options database options for a container's key column11.3.1412.3.14
value_options database options for a container's value column11.3.1512.3.15
id_column column name for a container's object id11.3.1612.3.16
index_column column name for a container's index11.3.1712.3.17
key_column column name for a container's key11.3.1812.3.18
value_column column name for a container's value11.3.1912.3.19

Many of the value type specifiers have corresponding member type - specifiers with the same names (Section 11.4, + specifiers with the same names (Section 12.4, "Data Member Pragmas"). The behavior of such specifiers for members is similar to that for value types. The only difference is the scope. A particular value type specifier applies to all the @@ -8059,7 +8460,7 @@ private: take precedence over and override parameters specified with value specifiers.

-

11.3.1 type

+

12.3.1 type

The type specifier specifies the native database type that should be used for data members of this type. For example:

@@ -8081,8 +8482,8 @@ class person std::string and the database types for each supported database system. For more information on the default mapping, refer to Part II, "Database Systems". The - null and not_null (Section - 11.3.3, "null/not_null") specifiers + null and not_null (Section + 12.3.3, "null/not_null") specifiers can be used to control the NULL semantics of a type.

In the above example we changed the mapping for the bool @@ -8109,13 +8510,13 @@ class person mapping example in the odb-examples package shows how to do this for all the supported database systems.

-

11.3.2 id_type

+

12.3.2 id_type

The id_type specifier specifies the native database type that should be used for data members of this type that are designated as - object identifiers (Section 11.4.1, + object identifiers (Section 12.4.1, "id"). In combination with the type - specifier (Section 11.3.1, "type") + specifier (Section 12.3.1, "type") id_type allows you to map a C++ type differently depending on whether it is used in an ordinary member or an object id. For example:

@@ -8150,7 +8551,7 @@ class person }; -

11.3.3 null/not_null

+

12.3.3 null/not_null

The null and not_null specifiers specify that a value type or object pointer can or cannot be NULL, @@ -8179,7 +8580,7 @@ typedef shared_ptr<person> person_ptr;

The NULL semantics can also be specified on the - per-member basis (Section 11.4.4, + per-member basis (Section 12.4.4, "null/not_null"). If both a type and a member have null/not_null specifiers, then the member specifier takes precedence. If a member specifier @@ -8213,7 +8614,7 @@ typedef shared_ptr<person> person_ptr; discussion of the NULL semantics for object pointers, refer to Chapter 6, "Relationships".

-

11.3.4 default

+

12.3.4 default

The default specifier specifies the database default value that should be used for data members of this type. For example:

@@ -8232,10 +8633,10 @@ class person

The semantics of the default specifier for a value type are similar to those of the default specifier for a - data member (Section 11.4.5, + data member (Section 12.4.5, "default").

-

11.3.5 options

+

12.3.5 options

The options specifier specifies additional column definition options that should be used for data members of this @@ -8255,10 +8656,10 @@ class person

The semantics of the options specifier for a value type are similar to those of the options specifier for a - data member (Section 11.4.6, + data member (Section 12.4.6, "options").

-

11.3.6 readonly

+

12.3.6 readonly

The readonly specifier specifies that the composite value type is read-only. Changes to data members of a read-only @@ -8284,11 +8685,11 @@ class person_name read-only while the rest is treated as read-write.

Note that it is also possible to declare individual data members - (Section 11.4.10, "readonly") - as well as whole objects (Section 11.1.4, + (Section 12.4.10, "readonly") + as well as whole objects (Section 12.1.4, "readonly") as read-only.

-

11.3.7 unordered

+

12.3.7 unordered

The unordered specifier specifies that the ordered container should be stored unordered in the database. The database @@ -8305,13 +8706,13 @@ typedef std::vector<std::string> names; storage in the database, refer to Section 5.1, "Ordered Containers".

-

11.3.8 index_type

+

12.3.8 index_type

The index_type specifier specifies the native database type that should be used for an ordered container's index column. The semantics of index_type are similar to those of the type specifier - (Section 11.3.1, "type"). The native + (Section 12.3.1, "type"). The native database type is expected to be an integer type. For example:

@@ -8319,13 +8720,13 @@ typedef std::vector<std::string> names;
 #pragma db value(names) index_type("SMALLINT UNSIGNED")
   
-

11.3.9 key_type

+

12.3.9 key_type

The key_type specifier specifies the native database type that should be used for a map container's key column. The semantics of key_type are similar to those of the type specifier - (Section 11.3.1, "type"). For + (Section 12.3.1, "type"). For example:

@@ -8333,13 +8734,13 @@ typedef std::map<unsigned short, float> age_weight_map;
 #pragma db value(age_weight_map) key_type("INT UNSIGNED")
   
-

11.3.10 value_type

+

12.3.10 value_type

The value_type specifier specifies the native database type that should be used for a container's value column. The semantics of value_type are similar to those of the type specifier - (Section 11.3.1, "type"). For + (Section 12.3.1, "type"). For example:

@@ -8348,18 +8749,18 @@ typedef std::vector<std::string> names;
   

The value_null and value_not_null - (Section 11.3.11, + (Section 12.3.11, "value_null/value_not_null") specifiers can be used to control the NULL semantics of a value column.

-

11.3.11 value_null/value_not_null

+

12.3.11 value_null/value_not_null

The value_null and value_not_null specifiers specify that a container type's element value can or cannot be NULL, respectively. The semantics of value_null and value_not_null are similar to those of the null and not_null specifiers - (Section 11.3.3, "null/not_null"). + (Section 12.3.3, "null/not_null"). For example:

@@ -8380,7 +8781,7 @@ typedef std::vector<shared_ptr<account> > accounts;
      as not allowing a NULL value.

-

11.3.12 id_options

+

12.3.12 id_options

The id_options specifier specifies additional column definition options that should be used for a container's @@ -8393,11 +8794,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 11.4.18, + a container data member (Section 12.4.19, "id_options").

-

11.3.13 index_options

+

12.3.13 index_options

The index_options specifier specifies additional column definition options that should be used for a container's @@ -8410,11 +8811,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 11.4.19, + a container data member (Section 12.4.20, "index_options").

-

11.3.14 key_options

+

12.3.14 key_options

The key_options specifier specifies additional column definition options that should be used for a container's @@ -8427,11 +8828,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 11.4.20, + a container data member (Section 12.4.21, "key_options").

-

11.3.15 value_options

+

12.3.15 value_options

The value_options specifier specifies additional column definition options that should be used for a container's @@ -8444,11 +8845,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 11.4.21, + a container data member (Section 12.4.22, "value_options").

-

11.3.16 id_column

+

12.3.16 id_column

The id_column specifier specifies the column name that should be used to store the object id in a @@ -8462,7 +8863,7 @@ typedef std::vector<std::string> names;

If the column name is not specified, then object_id is used by default.

-

11.3.17 index_column

+

12.3.17 index_column

The index_column specifier specifies the column name that should be used to store the element index in an @@ -8476,7 +8877,7 @@ typedef std::vector<std::string> names;

If the column name is not specified, then index is used by default.

-

11.3.18 key_column

+

12.3.18 key_column

The key_column specifier specifies the column name that should be used to store the key in a map @@ -8490,7 +8891,7 @@ typedef std::map<unsigned short, float> age_weight_map;

If the column name is not specified, then key is used by default.

-

11.3.19 value_column

+

12.3.19 value_column

The value_column specifier specifies the column name that should be used to store the element value in a @@ -8507,7 +8908,7 @@ typedef std::map<unsigned short, float> age_weight_map; -

11.4 Data Member Pragmas

+

12.4 Data Member Pragmas

A pragma with the member qualifier or a positioned pragma without a qualifier describes a data member. It can @@ -8525,157 +8926,163 @@ typedef std::map<unsigned short, float> age_weight_map;

id member is an object id11.4.112.4.1
auto id is assigned by the database11.4.212.4.2
type database type for a member11.4.312.4.3
null/not_null member can/cannot be NULL11.4.412.4.4
default default value for a member11.4.512.4.5
options database options for a member11.4.612.4.6
column column name for a member of an object or composite value11.4.712.4.7
column column name for a member of a view11.4.812.4.8
transient member is not stored in the database11.4.912.4.9
readonly member is read-only11.4.1012.4.10
inverse member is an inverse side of a bidirectional relationship11.4.1112.4.11
versionmember stores object version12.4.12
unordered ordered container should be stored unordered11.4.1212.4.13
table table name for a container11.4.1312.4.14
index_type database type for a container's index type11.4.1412.4.15
key_type database type for a container's key type11.4.1512.4.16
value_type database type for a container's value type11.4.1612.4.17
value_null/value_not_null container's value can/cannot be NULL11.4.1712.4.18
id_options database options for a container's id column11.4.1812.4.19
index_options database options for a container's index column11.4.1912.4.20
key_options database options for a container's key column11.4.2012.4.21
value_options database options for a container's value column11.4.2112.4.22
id_column column name for a container's object id11.4.2212.4.23
index_column column name for a container's index11.4.2312.4.24
key_column column name for a container's key11.4.2412.4.25
value_column column name for a container's value11.4.2512.4.26

Many of the member specifiers have corresponding value type - specifiers with the same names (Section 11.3, + specifiers with the same names (Section 12.3, "Value Type Pragmas"). The behavior of such specifiers for members is similar to that for value types. The only difference is the scope. A particular value type specifier applies to all the @@ -8685,7 +9092,7 @@ typedef std::map<unsigned short, float> age_weight_map; take precedence over and override parameters specified with value specifiers.

-

11.4.1 id

+

12.4.1 id

The id specifier specifies that a data member contains the object id. In a relational database, an identifier member is @@ -8705,12 +9112,12 @@ class person

Normally, every persistent class has a data member designated as an object's identifier. However, it is possible to declare a persistent class without an id using the object id - specifier (Section 11.1.5, "id").

+ specifier (Section 12.1.6, "id").

Note also that the id specifier cannot be used for data members of composite value types or views.

-

11.4.2 auto

+

12.4.2 auto

The auto specifier specifies that the object's identifier is automatically assigned by the database. Only a member that was @@ -8740,7 +9147,7 @@ class person

Note also that the auto specifier cannot be specified for data members of composite value types or views.

-

11.4.3 type

+

12.4.3 type

The type specifier specifies the native database type that should be used for a data member. For example:

@@ -8756,11 +9163,11 @@ class person }; -

The null and not_null (Section - 11.4.4, "null/not_null") specifiers +

The null and not_null (Section + 12.4.4, "null/not_null") specifiers can be used to control the NULL semantics of a data member.

-

11.4.4 null/not_null

+

12.4.4 null/not_null

The null and not_null specifiers specify that a data member can or cannot be NULL, respectively. @@ -8772,8 +9179,8 @@ class person not allow NULL values, depending on the semantics of each value type. Consult the relevant documentation to find out more about the NULL semantics for such value - types. A data member containing the object id (Section - 11.4.1, "id" ) is automatically treated as not + types. A data member containing the object id (Section + 12.4.1, "id" ) is automatically treated as not allowing a NULL value. Data members that allow NULL values are mapped in a relational database to columns that allow NULL values. For example:

@@ -8801,7 +9208,7 @@ class account

The NULL semantics can also be specified on the - per-type basis (Section 11.3.3, + per-type basis (Section 12.3.3, "null/not_null"). If both a type and a member have null/not_null specifiers, then the member specifier takes precedence. If a member specifier @@ -8815,7 +9222,7 @@ class account discussion of the NULL semantics for object pointers, refer to Chapter 6, "Relationships".

-

11.4.5 default

+

12.4.5 default

The default specifier specifies the database default value that should be used for a data member. For example:

@@ -8836,8 +9243,8 @@ class person an integer literal, a floating point literal, a string literal, or an enumerator name. If you need to specify a default value that is an expression, for example an SQL function call, then you can use - the options specifier (Section - 11.4.6, "options") instead. For example:

+ the options specifier (Section + 12.4.6, "options") instead. For example:

 enum gender {male, female, undisclosed};
@@ -8890,7 +9297,7 @@ class person
   

A default value can also be specified on the per-type basis - (Section 11.3.4, "default"). + (Section 12.3.4, "default"). An empty default specifier can be used to reset a default value that was previously specified on the per-type basis. For example:

@@ -8908,8 +9315,8 @@ class person }; -

A data member containing the object id (Section - 11.4.1, "id" ) is automatically treated as not +

A data member containing the object id (Section + 12.4.1, "id" ) is automatically treated as not having a default value even if its type specifies a default value.

Note also that default values do not affect the generated C++ code @@ -8923,7 +9330,7 @@ class person

Additionally, the default specifier cannot be specified for view data members.

-

11.4.6 options

+

12.4.6 options

The options specifier specifies additional column definition options that should be used for a data member. For @@ -8941,7 +9348,7 @@ class person

Options can also be specified on the per-type basis - (Section 11.3.5, "options"). + (Section 12.3.5, "options"). By default, options are accumulating. That is, the ODB compiler first adds all the options specified for a value type followed by all the options specified for a data member. To clear the @@ -8970,10 +9377,10 @@ class person

ODB provides dedicated specifiers for specifying column types - (Section 11.4.3, "type"), - NULL constraints (Section 11.4.4, + (Section 12.4.3, "type"), + NULL constraints (Section 12.4.4, "null/not_null"), and default - values (Section 11.4.5, "default"). + values (Section 12.4.5, "default"). For ODB to function correctly these specifiers should always be used instead of the opaque options specifier for these components of a column definition.

@@ -8981,7 +9388,7 @@ class person

Note also that the options specifier cannot be specified for view data members.

-

11.4.7 column (object, composite value)

+

12.4.7 column (object, composite value)

The column specifier specifies the column name that should be used to store a data member of a persistent class @@ -9007,7 +9414,7 @@ class person the common data member name decorations, such as leading and trailing underscores, the m_ prefix, etc.

-

11.4.8 column (view)

+

12.4.8 column (view)

The column specifier can be used to specify the associated object data member, the potentially qualified column name, or the column @@ -9015,7 +9422,7 @@ class person refer to Section 9.1, "Object Views" and Section 9.2, "Table Views".

-

11.4.9 transient

+

12.4.9 transient

The transient specifier instructs the ODB compiler not to store a data member in the database. For example:

@@ -9037,7 +9444,7 @@ class person references that are only meaningful in the application's memory, as well as utility members such as mutexes, etc.

-

11.4.10 readonly

+

12.4.10 readonly

The readonly specifier specifies that a data member of an object or composite value type is read-only. Changes to a read-only @@ -9045,8 +9452,8 @@ class person (Section 3.9, "Updating Persistent Objects") containing such a member. Since views are read-only, it is not necessary to use this specifier for view data members. Object id - (Section 11.4.1, "id") - and inverse (Section 11.4.11, + (Section 12.4.1, "id") + and inverse (Section 12.4.11, "inverse") data members are automatically treated as read-only and must not be explicitly declared as such. For example:

@@ -9126,11 +9533,11 @@ class person as read-only.

Note that it is also possible to declare composite value types - (Section 11.3.6, "readonly") - as well as whole objects (Section 11.1.4, + (Section 12.3.6, "readonly") + as well as whole objects (Section 12.1.4, "readonly") as read-only.

-

11.4.11 inverse

+

12.4.11 inverse

The inverse specifier specifies that a data member of an object pointer or a container of object pointers type is an @@ -9168,12 +9575,42 @@ 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 11.4.12, "unordered").

+ (Section 12.4.13, "unordered").

For a more detailed discussion of inverse members, refer to Section 6.2, "Bidirectional Relationships".

-

11.4.12 unordered

+

12.4.12 version

+ +

The version specifier specifies that the data member + stores the object version used to support optimistic concurrency. + If a class has a version data member then it must also be declared + as having optimistic concurrency model using the optimistic + pragma (Section 12.1.5, "optimistic"). + For example:

+ +
+#pragma db object optimistic
+class person
+{
+  ...
+
+  #pragma db version
+  unsigned long version_;
+};
+  
+ +

A version member must be of an integral C++ type and must map to + an integer or similar database type. Note also that object versions + are not reused. If you have a high update frequency, then care must + be taken not to run out of versions. In such situations, using + unsigned long long as the version type is a safe + choice.

+ +

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

+ +

12.4.13 unordered

The unordered specifier specifies that a member of an ordered container type should be stored unordered in the database. @@ -9196,7 +9633,7 @@ class person storage in the database, refer to Section 5.1, "Ordered Containers".

-

11.4.13 table

+

12.4.14 table

The table specifier specifies the table name that should be used to store the contents of a container member. For example:

@@ -9226,13 +9663,13 @@ class person to Section 7.2.1, "Composite Value Column and Table Names" for details.

-

11.4.14 index_type

+

12.4.15 index_type

The index_type specifier specifies the native database type that should be used for an ordered container's index column of a data member. The semantics of index_type are similar to those of the type specifier - (Section 11.4.3, "type"). The native + (Section 12.4.3, "type"). The native database type is expected to be an integer type. For example:

@@ -9246,13 +9683,13 @@ class person
 };
   
-

11.4.15 key_type

+

12.4.16 key_type

The key_type specifier specifies the native database type that should be used for a map container's key column of a data member. The semantics of key_type are similar to those of the type specifier - (Section 11.4.3, "type"). For + (Section 12.4.3, "type"). For example:

@@ -9266,13 +9703,13 @@ class person
 };
   
-

11.4.16 value_type

+

12.4.17 value_type

The value_type specifier specifies the native database type that should be used for a container's value column of a data member. The semantics of value_type are similar to those of the type specifier - (Section 11.4.3, "type"). For + (Section 12.4.3, "type"). For example:

@@ -9287,18 +9724,18 @@ class person
   

The value_null and value_not_null - (Section 11.4.17, + (Section 12.4.18, "value_null/value_not_null") specifiers can be used to control the NULL semantics of a value column.

-

11.4.17 value_null/value_not_null

+

12.4.18 value_null/value_not_null

The value_null and value_not_null specifiers specify that a container's element value for a data member can or cannot be NULL, respectively. The semantics of value_null and value_not_null are similar to those of the null and not_null specifiers - (Section 11.4.4, "null/not_null"). + (Section 12.4.4, "null/not_null"). For example:

@@ -9324,7 +9761,7 @@ class account
      Multiset Containers") the element value is automatically treated
      as not allowing a NULL value.

-

11.4.18 id_options

+

12.4.19 id_options

The id_options specifier specifies additional column definition options that should be used for a container's @@ -9345,10 +9782,10 @@ class person

The semantics of id_options are similar to those - of the options specifier (Section - 11.4.6, "options").

+ of the options specifier (Section + 12.4.6, "options").

-

11.4.19 index_options

+

12.4.20 index_options

The index_options specifier specifies additional column definition options that should be used for a container's @@ -9366,10 +9803,10 @@ class person

The semantics of index_options are similar to those - of the options specifier (Section - 11.4.6, "options").

+ of the options specifier (Section + 12.4.6, "options").

-

11.4.20 key_options

+

12.4.21 key_options

The key_options specifier specifies additional column definition options that should be used for a container's @@ -9387,10 +9824,10 @@ class person

The semantics of key_options are similar to those - of the options specifier (Section - 11.4.6, "options").

+ of the options specifier (Section + 12.4.6, "options").

-

11.4.21 value_options

+

12.4.22 value_options

The value_options specifier specifies additional column definition options that should be used for a container's @@ -9408,17 +9845,17 @@ class person

The semantics of value_options are similar to those - of the options specifier (Section - 11.4.6, "options").

+ of the options specifier (Section + 12.4.6, "options").

-

11.4.22 id_column

+

12.4.23 id_column

The id_column specifier specifies the column name that should be used to store the object id in a container's table for a data member. The semantics of id_column are similar to those of the column specifier - (Section 11.4.7, "column"). + (Section 12.4.7, "column"). For example:

@@ -9435,14 +9872,14 @@ class person
   

If the column name is not specified, then object_id is used by default.

-

11.4.23 index_column

+

12.4.24 index_column

The index_column specifier specifies the column name that should be used to store the element index in an ordered container's table for a data member. The semantics of index_column are similar to those of the column specifier - (Section 11.4.7, "column"). + (Section 12.4.7, "column"). For example:

@@ -9459,14 +9896,14 @@ class person
   

If the column name is not specified, then index is used by default.

-

11.4.24 key_column

+

12.4.25 key_column

The key_column specifier specifies the column name that should be used to store the key in a map container's table for a data member. The semantics of key_column are similar to those of the column specifier - (Section 11.4.7, "column"). + (Section 12.4.7, "column"). For example:

@@ -9483,14 +9920,14 @@ class person
   

If the column name is not specified, then key is used by default.

-

11.4.25 value_column

+

12.4.26 value_column

The value_column specifier specifies the column name that should be used to store the element value in a container's table for a data member. The semantics of value_column are similar to those of the column specifier - (Section 11.4.7, "column"). + (Section 12.4.7, "column"). For example:

@@ -9507,7 +9944,7 @@ class person
   

If the column name is not specified, then value is used by default.

-

11.5 C++ Compiler Warnings

+

12.5 C++ Compiler Warnings

When a C++ header file defining persistent classes and containing ODB pragmas is used to build the application, the C++ compiler may @@ -9560,7 +9997,7 @@ class person

The disadvantage of this approach is that it can quickly become overly verbose when positioned pragmas are used.

-

11.5.1 GNU C++

+

12.5.1 GNU C++

GNU g++ does not issue warnings about unknown pragmas unless requested with the -Wall command line option. @@ -9572,7 +10009,7 @@ class person g++ -Wall -Wno-unknown-pragmas ...

-

11.5.2 Visual C++

+

12.5.2 Visual C++

Microsoft Visual C++ issues an unknown pragma warning (C4068) at warning level 1 or higher. This means that unless we have disabled @@ -9606,7 +10043,7 @@ class person #pragma warning (pop)

-

11.5.3 Sun C++

+

12.5.3 Sun C++

The Sun C++ compiler does not issue warnings about unknown pragmas unless the +w or +w2 option is specified. @@ -9618,7 +10055,7 @@ class person CC +w -erroff=unknownpragma ...

-

11.5.4 IBM XL C++

+

12.5.4 IBM XL C++

IBM XL C++ issues an unknown pragma warning (1540-1401) by default. To disable this warning we can add the -qsuppress=1540-1401 @@ -9628,7 +10065,7 @@ CC +w -erroff=unknownpragma ... xlC -qsuppress=1540-1401 ...

-

11.5.5 HP aC++

+

12.5.5 HP aC++

HP aC++ (aCC) issues an unknown pragma warning (2161) by default. To disable this warning we can add the +W2161 @@ -9654,9 +10091,9 @@ aCC +W2161 ... chapters.

- - - + + +
12MySQL Database
13SQLite Database
14PostgreSQL Database
13MySQL Database
14SQLite Database
15PostgreSQL Database
@@ -9664,7 +10101,7 @@ aCC +W2161 ...
-

12 MySQL Database

+

13 MySQL Database

To generate support code for the MySQL database you will need to pass the "--database mysql" @@ -9673,12 +10110,12 @@ aCC +W2161 ... library (libodb-mysql). All MySQL-specific ODB classes are defined in the odb::mysql namespace.

-

12.1 MySQL Type Mapping

+

13.1 MySQL Type Mapping

The following table summarizes the default mapping between basic C++ value types and MySQL database types. This mapping can be customized on the per-type and per-member basis using the ODB - Pragma Language (Chapter 11, "ODB Pragma + Pragma Language (Chapter 12, "ODB Pragma Language").

@@ -9795,8 +10232,8 @@ aCC +W2161 ... default (in particular, by default, std::vector will be treated as a container). To enable the BLOB mapping for these types we need to specify the database type explicitly using the - db type pragma (Section - 11.4.3, "type"), for example:

+ db type pragma (Section + 12.4.3, "type"), for example:

 #pragma db object
@@ -9854,7 +10291,7 @@ class object
 };
   
-

12.2 MySQL Database Class

+

13.2 MySQL Database Class

The MySQL database class has the following interface:

@@ -10015,7 +10452,7 @@ namespace odb

This constructor throws the odb::mysql::cli_exception exception if the MySQL option values are missing or invalid. - See section Section 12.4, "MySQL Exceptions" + See section Section 13.4, "MySQL Exceptions" for more information on this exception.

The static print_usage() function prints the list of options @@ -10034,10 +10471,10 @@ namespace odb

The connection() function returns a pointer to the MySQL database connection encapsulated by the odb::mysql::connection class. For more information - on mysql::connection, refer to Section - 12.3, "MySQL Connection and Connection Factory".

+ on mysql::connection, refer to Section + 13.3, "MySQL Connection and Connection Factory".

-

12.3 MySQL Connection and Connection Factory

+

13.3 MySQL Connection and Connection Factory

The mysql::connection class has the following interface:

@@ -10229,7 +10666,7 @@ main (int argc, char* argv[]) } -

12.4 MySQL Exceptions

+

13.4 MySQL Exceptions

The MySQL ODB runtime library defines the following MySQL-specific exceptions:

@@ -10281,12 +10718,12 @@ namespace odb what() function returns a human-readable description of an error.

-

12.5 MySQL Limitations

+

13.5 MySQL Limitations

The following sections describe MySQL-specific limitations imposed by the current MySQL and ODB runtime versions.

-

12.5.1 Foreign Key Constraints

+

13.5.1 Foreign Key Constraints

ODB relies on standard SQL behavior which requires that foreign key constraints checking is deferred until the transaction is @@ -10301,7 +10738,7 @@ namespace odb


-

13 SQLite Database

+

14 SQLite Database

To generate support code for the SQLite database you will need to pass the "--database sqlite" @@ -10310,12 +10747,12 @@ namespace odb library (libodb-sqlite). All SQLite-specific ODB classes are defined in the odb::sqlite namespace.

-

13.1 SQLite Type Mapping

+

14.1 SQLite Type Mapping

The following table summarizes the default mapping between basic C++ value types and SQLite database types. This mapping can be customized on the per-type and per-member basis using the ODB - Pragma Language (Chapter 11, "ODB Pragma + Pragma Language (Chapter 12, "ODB Pragma Language").

@@ -10425,7 +10862,7 @@ namespace odb (in particular, by default, std::vector will be treated as a container). To enable the BLOB mapping for these types we need to specify the database type explicitly using the - db type pragma (Section 11.4.3, + db type pragma (Section 12.4.3, "type"), for example:

@@ -10466,7 +10903,7 @@ class object
      a result, greater unsigned long long values will be
      represented in the database as negative values.

-

13.2 SQLite Database Class

+

14.2 SQLite Database Class

The SQLite database class has the following interface:

@@ -10529,7 +10966,7 @@ namespace odb values, refer to the sqlite3_open_v2() function description in the SQLite C API documentation. The foreign_keys argument specifies whether foreign key constraints checking - should be enabled. See Section 13.5.3, + should be enabled. See Section 14.5.3, "Foreign Key Constraints" for more information on foreign keys.

@@ -10577,7 +11014,7 @@ auto_ptr<odb::database> db (

The second constructor throws the odb::sqlite::cli_exception exception if the SQLite option values are missing or invalid. - See Section 13.4, "SQLite Exceptions" + See Section 14.4, "SQLite Exceptions" for more information on this exception.

The static print_usage() function prints the list of options @@ -10605,10 +11042,10 @@ auto_ptr<odb::database> db (

The connection() function returns a pointer to the SQLite database connection encapsulated by the odb::sqlite::connection class. For more information - on sqlite::connection, refer to Section - 13.3, "SQLite Connection and Connection Factory".

+ on sqlite::connection, refer to Section + 14.3, "SQLite Connection and Connection Factory".

-

13.3 SQLite Connection and Connection Factory

+

14.3 SQLite Connection and Connection Factory

The sqlite::connection class has the following interface:

@@ -10653,7 +11090,7 @@ namespace odb functions allow us to start an immediate and an exclusive SQLite transaction on the connection, respectively. Their semantics are equivalent to the corresponding functions defined in the - sqlite::database class (Section 13.2, + sqlite::database class (Section 14.2, "SQLite Database Class"). The handle() accessor returns the SQLite handle corresponding to the connection.

@@ -10853,7 +11290,7 @@ main (int argc, char* argv[]) }
-

13.4 SQLite Exceptions

+

14.4 SQLite Exceptions

The SQLite ODB runtime library defines the following SQLite-specific exceptions:

@@ -10906,12 +11343,12 @@ namespace odb of an error.

-

13.5 SQLite Limitations

+

14.5 SQLite Limitations

The following sections describe SQLite-specific limitations imposed by the current SQLite and ODB runtime versions.

-

13.5.1 Query Result Caching

+

14.5.1 Query Result Caching

SQLite ODB runtime implementation does not perform query result caching (Section 4.4, "Query Result") even when explicitly @@ -10926,17 +11363,17 @@ namespace odb thrown. Future versions of the SQLite ODB runtime library may add support for result caching.

-

13.5.2 Automatic Assignment of Object Ids

+

14.5.2 Automatic Assignment of Object Ids

Due to SQLite API limitations, every automatically assigned object id - (Section 11.4.2, "auto") should have + (Section 12.4.2, "auto") should have the INTEGER SQLite type. While SQLite will treat other integer type names (such as INT, BIGINT, etc.) as INTEGER, automatic id assignment will not work. By default, ODB maps all C++ integral types to INTEGER. This means that the only situation that requires consideration is the assignment of a custom database type using the db type pragma - (Section 11.4.3, "type"). For + (Section 12.4.3, "type"). For example:

@@ -10952,7 +11389,7 @@ class person
 };
 
-

13.5.3 Foreign Key Constraints

+

14.5.3 Foreign Key Constraints

By default the SQLite ODB runtime enables foreign key constraints checking (PRAGMA foreign_keys=ON). You can disable foreign @@ -11015,7 +11452,7 @@ CREATE TABLE Employee ( -

13.5.4 Constraint Violations

+

14.5.4 Constraint Violations

Due to the granularity of the SQLite error codes, it is impossible to distinguish between the duplicate primary key and other constraint @@ -11024,7 +11461,7 @@ CREATE TABLE Employee ( object_not_persistent exception (Section 3.12, "ODB Exceptions").

-

13.5.5 Sharing of Queries

+

14.5.5 Sharing of Queries

As discussed in Section 4.3, "Executing a Query", a query instance that does not have any by-reference parameters is @@ -11038,7 +11475,7 @@ CREATE TABLE Employee (


-

14 PostgreSQL Database

+

15 PostgreSQL Database

To generate support code for the PostgreSQL database you will need to pass the "--database pgsql" @@ -11052,12 +11489,12 @@ CREATE TABLE Employee ( of the messaging protocol version 3.0. For this reason, ODB supports only PostgreSQL version 7.4 and later.

-

14.1 PostgreSQL Type Mapping

+

15.1 PostgreSQL Type Mapping

The following table summarizes the default mapping between basic C++ value types and PostgreSQL database types. This mapping can be customized on the per-type and per-member basis using the ODB - Pragma Language (Chapter 11, "ODB Pragma + Pragma Language (Chapter 12, "ODB Pragma Language").

@@ -11167,8 +11604,8 @@ CREATE TABLE Employee ( enabled by default (in particular, by default, std::vector will be treated as a container). To enable the BYTEA mapping for these types we need to specify the database type explicitly - using the db type pragma (Section - 11.4.3, "type"), for example:

+ using the db type pragma (Section + 12.4.3, "type"), for example:

 #pragma db object
@@ -11212,7 +11649,7 @@ class object
      the most significant bit of the actual unsigned value being
      persisted.

-

14.2 PostgreSQL Database Class

+

15.2 PostgreSQL Database Class

The PostgreSQL database class has the following interface:

@@ -11333,7 +11770,7 @@ namespace odb

This constructor throws the odb::pgsql::cli_exception exception if the PostgreSQL option values are missing or invalid. - See section Section 14.4, "PostgreSQL Exceptions" + See section Section 15.4, "PostgreSQL Exceptions" for more information on this exception.

The static print_usage() function prints the list of options @@ -11358,10 +11795,10 @@ namespace odb

The connection() function returns a pointer to the PostgreSQL database connection encapsulated by the odb::pgsql::connection class. For more information - on pgsql::connection, refer to Section - 14.3, "PostgreSQL Connection and Connection Factory".

+ on pgsql::connection, refer to Section + 15.3, "PostgreSQL Connection and Connection Factory".

-

14.3 PostgreSQL Connection and Connection Factory

+

15.3 PostgreSQL Connection and Connection Factory

The pgsql::connection class has the following interface:

@@ -11542,7 +11979,7 @@ main (int argc, char* argv[]) }
-

14.4 PostgreSQL Exceptions

+

15.4 PostgreSQL Exceptions

The PostgreSQL ODB runtime library defines the following PostgreSQL-specific exceptions:

@@ -11591,12 +12028,12 @@ namespace odb what() function returns a human-readable description of an error.

-

14.5 PostgreSQL Limitations

+

15.5 PostgreSQL Limitations

The following sections describe PostgreSQL-specific limitations imposed by the current PostgreSQL and ODB runtime versions.

-

14.5.1 Query Result Caching

+

15.5.1 Query Result Caching

The PostgreSQL ODB runtime implementation will always return a cached query result (Section 4.4, "Query Result") @@ -11604,7 +12041,7 @@ namespace odb PostgreSQL client library (libpq) which does not support uncached (streaming) query results.

-

14.5.2 Foreign Key Constraints

+

15.5.2 Foreign Key Constraints

ODB relies on standard SQL behavior which requires that foreign key constraints checking is deferred until the @@ -11622,7 +12059,7 @@ CREATE TABLE Employee ( employer BIGINT REFERENCES Employer (name) INITIALLY DEFERRED); -

14.5.3 Date-Time Format

+

15.5.3 Date-Time Format

ODB expects the PostgreSQL server to use integers as a binary format for the date-time types, which is the default for most @@ -11637,12 +12074,12 @@ CREATE TABLE Employee ( SHOW integer_datetimes -

14.5.4 Timezones

+

15.5.4 Timezones

ODB does not currently support the PostgreSQL date-time types with timezone information.

-

14.5.5 NUMERIC Type Support

+

15.5.5 NUMERIC Type Support

Support for the PostgreSQL NUMERIC type is limited to providing a binary buffer containing the binary representation @@ -11661,9 +12098,9 @@ SHOW integer_datetimes and libraries. It consists of the following chapters.

- - - + + +
15Profiles Introduction
16Boost Profile
17Qt Profile
16Profiles Introduction
17Boost Profile
18Qt Profile
@@ -11671,7 +12108,7 @@ SHOW integer_datetimes
-

15 Profiles Introduction

+

16 Profiles Introduction

ODB profiles are a generic mechanism for integrating ODB with widely-used C++ frameworks and libraries. A profile provides glue @@ -11725,7 +12162,7 @@ odb --profile boost/date-time ...


-

16 Boost Profile

+

17 Boost Profile

The ODB profile implementation for Boost is provided by the libodb-boost library and consists of multiple sub-profiles @@ -11750,7 +12187,7 @@ odb --profile boost/date-time ... that can be thrown by the Boost sub-profiles are described in the following sections.

-

16.1 Smart Pointers Library

+

17.1 Smart Pointers Library

The smart-ptr sub-profile provides persistence support for a subset of smart pointers from the Boost @@ -11820,7 +12257,7 @@ class employee this behavior, add the --default-pointer option specifying the alternative pointer type after the --profile option.

-

16.2 Unordered Containers Library

+

17.2 Unordered Containers Library

The unordered sub-profile provides persistence support for the containers from the Boost unordered library. To enable @@ -11846,7 +12283,7 @@ class person }; -

16.3 Optional Library

+

17.3 Optional Library

The optional sub-profile provides persistence support for the boost::optional container from the Boost @@ -11878,7 +12315,7 @@ class person this profile is used, the NULL values are automatically enabled for data members of the boost::optional type.

-

16.4 Date Time Library

+

17.4 Date Time Library

The date-time sub-profile provides persistence support for a subset of types from the Boost date_time library. It is @@ -11951,7 +12388,7 @@ namespace odb exceptions are thrown are database system dependent and are discussed in more detail in the following sub-sections.

-

16.4.1 MySQL Database Type Mapping

+

17.4.1 MySQL Database Type Mapping

The following table summarizes the default mapping between the currently supported Boost date_time types and the MySQL database @@ -11991,7 +12428,7 @@ namespace odb support for mapping posix_time::ptime to the TIMESTAMP MySQL type. However, this mapping has to be explicitly requested using the db type pragma - (Section 11.4.3, "type"), as shown in + (Section 12.4.3, "type"), as shown in the following example:

@@ -12012,7 +12449,7 @@ class person
      the out_of_range exception.  Refer to the MySQL
      documentation for more information on the MySQL data type ranges.

-

16.4.2 SQLite Database Type Mapping

+

17.4.2 SQLite Database Type Mapping

The following table summarizes the default mapping between the currently supported Boost date_time types and the SQLite database @@ -12055,7 +12492,7 @@ class person alternative mapping for posix_time::time_duration to the INTEGER type represents the duration as a number of seconds. These mappings have to be explicitly requested using the - db type pragma (Section 11.4.3, + db type pragma (Section 12.4.3, "type"), as shown in the following example:

@@ -12090,7 +12527,7 @@ class person
      will result in the out_of_range exception.

-

16.4.3 PostgreSQL Database Type Mapping

+

17.4.3 PostgreSQL Database Type Mapping

The following table summarizes the default mapping between the currently supported Boost date_time types and the PostgreSQL database @@ -12145,7 +12582,7 @@ class person


-

17 Qt Profile

+

18 Qt Profile

The ODB profile implementation for Qt is provided by the libodb-qt library and consists of multiple sub-profiles @@ -12171,7 +12608,7 @@ class person that can be thrown by the Qt sub-profiles are described in the following sections.

-

17.1 Basic Types

+

18.1 Basic Types

The basic sub-profile provides persistence support for basic types defined by Qt. To enable only this profile, pass @@ -12193,7 +12630,7 @@ class Person };

-

17.1.1 MySQL Database Type Mapping

+

18.1.1 MySQL Database Type Mapping

The following table summarizes the default mapping between the currently supported basic Qt types and the MySQL database types.

@@ -12231,7 +12668,7 @@ class Person it is mapped to TEXT.

-

17.1.2 SQLite Database Type Mapping

+

18.1.2 SQLite Database Type Mapping

The following table summarizes the default mapping between the currently supported basic Qt types and the SQLite database types.

@@ -12261,7 +12698,7 @@ class Person are stored as a NULL value if their isNull() member function returns true.

-

17.1.3 PostgreSQL Database Type Mapping

+

18.1.3 PostgreSQL Database Type Mapping

The following table summarizes the default mapping between the currently supported basic Qt types and the PostgreSQL database types.

@@ -12291,7 +12728,7 @@ class Person are stored as a NULL value if their isNull() member function returns true.

-

17.2 Smart Pointers

+

18.2 Smart Pointers

The smart-ptr sub-profile provides persistence support the Qt smart pointers. To enable only this profile, pass @@ -12360,7 +12797,7 @@ class Employee this behavior, add the --default-pointer option specifying the alternative pointer type after the --profile option.

-

17.3 Containers Library

+

18.3 Containers Library

The container sub-profile provides persistence support for Qt containers. To enable only this profile, pass @@ -12385,7 +12822,7 @@ class Person };

-

17.4 Date Time Types

+

18.4 Date Time Types

The date-time sub-profile provides persistence support for the Qt date-time types. To enable only this profile, pass @@ -12438,7 +12875,7 @@ namespace odb system dependent and is discussed in more detail in the following sub-sections.

-

17.4.1 MySQL Database Type Mapping

+

18.4.1 MySQL Database Type Mapping

The following table summarizes the default mapping between the currently supported Qt date-time types and the MySQL database types.

@@ -12478,7 +12915,7 @@ namespace odb support for mapping QDateTime to the TIMESTAMP MySQL type. However, this mapping has to be explicitly requested using the db type pragma - (Section 11.4.3, "type"), as shown in + (Section 12.4.3, "type"), as shown in the following example:

@@ -12497,7 +12934,7 @@ class Person
      the MySQL documentation for more information on the MySQL data type
      ranges.

-

17.4.2 SQLite Database Type Mapping

+

18.4.2 SQLite Database Type Mapping

The following table summarizes the default mapping between the currently supported Qt date-time types and the SQLite database types.

@@ -12540,7 +12977,7 @@ class Person the INTEGER type represents a clock time as the number of seconds since midnight. These mappings have to be explicitly requested using the db type pragma - (Section 11.4.3, "type"), as shown + (Section 12.4.3, "type"), as shown in the following example:

@@ -12559,7 +12996,7 @@ class Person
      epoch) as an SQLite INTEGER will result in the
      out_of_range exception.

-

17.4.3 PostgreSQL Database Type Mapping

+

18.4.3 PostgreSQL Database Type Mapping

The following table summarizes the default mapping between the currently supported Qt date-time types and the PostgreSQL database types.

-- cgit v1.1