From 09d7377f81aeb8fde4aa1698e946457f03380d45 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 6 May 2013 12:05:39 +0200 Subject: Add support for object sections Sections are an optimization mechanism that allows the partitioning of data members of a persistent class into groups that can be separately loaded and/or updated. --- doc/manual.xhtml | 2401 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 1600 insertions(+), 801 deletions(-) (limited to 'doc/manual.xhtml') diff --git a/doc/manual.xhtml b/doc/manual.xhtml index 2746a0c..f754e40 100644 --- a/doc/manual.xhtml +++ b/doc/manual.xhtml @@ -429,154 +429,168 @@ for consistency. - 9Views + 9Sections - - - - - - + + + +
9.1Object Views
9.2Table Views
9.3Mixed Views
9.4View Query Conditions
9.5Native Views
9.6Other View Features and Limitations
9.1Sections and Inheritance
9.2Sections and Optimistic Concurrency
9.3Sections and Lazy Pointers
9.4Sections and Change-Tracking Containers
- 10Session + 10Views - - + + + + + +
10.1Object Cache
10.2Custom Sessions
10.1Object Views
10.2Table Views
10.3Mixed Views
10.4View Query Conditions
10.5Native Views
10.6Other View Features and Limitations
- 11Optimistic Concurrency + 11Session + + + +
11.1Object Cache
11.2Custom Sessions
+ - 12ODB Pragma Language + 12Optimistic Concurrency + + + + 14ODB Pragma Language - - - - - - + - + - @@ -585,9 +599,9 @@ for consistency. - @@ -597,13 +611,13 @@ for consistency. - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - +
12.1Object Type Pragmas + 14.1Object Type Pragmas - - - - - - - - - - - - + + + + + + + + + + + + +
12.1.1table
12.1.2pointer
12.1.3abstract
12.1.4readonly
12.1.5optimistic
12.1.6no_id
12.1.7callback
12.1.8schema
12.1.9polymorphic
12.1.10session
12.1.11definition
12.1.12transient
14.1.1table
14.1.2pointer
14.1.3abstract
14.1.4readonly
14.1.5optimistic
14.1.6no_id
14.1.7callback
14.1.8schema
14.1.9polymorphic
14.1.10session
14.1.11definition
14.1.12transient
14.1.13sectionable
12.2View Type Pragmas + 14.2View Type Pragmas - - - - - - - + + + + + + +
12.2.1object
12.2.2table
12.2.3query
12.2.4pointer
12.2.5callback
12.2.6definition
12.2.7transient
14.2.1object
14.2.2table
14.2.3query
14.2.4pointer
14.2.5callback
14.2.6definition
14.2.7transient
12.3Value Type Pragmas + 14.3Value Type Pragmas - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + +
12.3.1type
12.3.2id_type
12.3.3null/not_null
12.3.4default
12.3.5options
12.3.6readonly
12.3.7definition
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
14.3.1type
14.3.2id_type
14.3.3null/not_null
14.3.4default
14.3.5options
14.3.6readonly
14.3.7definition
14.3.8transient
14.3.9unordered
14.3.10index_type
14.3.11key_type
14.3.12value_type
14.3.13value_null/value_not_null
14.3.14id_options
14.3.15index_options
14.3.16key_options
14.3.17value_options
14.3.18id_column
14.3.19index_column
14.3.20key_column
14.3.21value_column
12.4Data Member Pragmas + 14.4Data Member Pragmas - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
12.4.1id
12.4.2auto
12.4.3type
12.4.4id_type
12.4.5get/set/access
12.4.6null/not_null
12.4.7default
12.4.8options
12.4.9column (object, composite value)
12.4.10column (view)
12.4.11transient
12.4.12readonly
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
14.4.1id
14.4.2auto
14.4.3type
14.4.4id_type
14.4.5get/set/access
14.4.6null/not_null
14.4.7default
14.4.8options
14.4.9column (object, composite value)
14.4.10column (view)
14.4.11transient
14.4.12readonly
14.4.13virtual
14.4.14inverse
14.4.15version
14.4.16index
14.4.17unique
14.4.18unordered
14.4.19table
14.4.20load/update
14.4.21section
14.4.22index_type
14.4.23key_type
14.4.24value_type
14.4.25value_null/value_not_null
14.4.26id_options
14.4.27index_options
14.4.28key_options
14.4.29value_options
14.4.30id_column
14.4.31index_column
14.4.32key_column
14.4.33value_column
12.5Namespace Pragmas + 14.5Namespace Pragmas - - - - + + + +
12.5.1pointer
12.5.2table
12.5.3schema
12.5.4session
14.5.1pointer
14.5.2table
14.5.3schema
14.5.4session
12.6Index Definition Pragmas14.6Index Definition Pragmas
12.7Database Type Mapping Pragmas14.7Database Type Mapping Pragmas
12.8C++ Compiler Warnings + 14.8C++ Compiler Warnings - - - - - - + + + + + +
12.8.1GNU C++
12.8.2Visual C++
12.8.3Sun C++
12.8.4IBM XL C++
12.8.5HP aC++
12.8.6Clang
14.8.1GNU C++
14.8.2Visual C++
14.8.3Sun C++
14.8.4IBM XL C++
14.8.5HP aC++
14.8.6Clang
13Advanced Techniques and Mechanisms + 15Advanced Techniques and Mechanisms - +
13.1Transaction Callbacks
15.1Transaction Callbacks
14Multi-Database Support + 16Multi-Database Support - + - @@ -612,156 +626,156 @@ for consistency. - - - - - @@ -771,35 +785,35 @@ for consistency. - + - - + - + - + - + - + - + - +
14.1Static Multi-Database Support
16.1Static Multi-Database Support
14.2Dynamic Multi-Database Support + 16.2Dynamic Multi-Database Support - +
14.2.214.2.2 Dynamic Loading of Database Support Code
16.2.216.2.2 Dynamic Loading of Database Support Code
15MySQL Database + 17MySQL Database - - - - + + + - - +
15.1MySQL Type Mapping + 17.1MySQL Type Mapping - - + +
15.1.1String Type Mapping
15.1.2Binary Type Mapping
17.1.1String Type Mapping
17.1.2Binary Type Mapping
15.2MySQL Database Class
15.3MySQL Connection and Connection Factory
15.4MySQL Exceptions
17.2MySQL Database Class
17.3MySQL Connection and Connection Factory
17.4MySQL Exceptions
15.5MySQL Limitations + 17.5MySQL Limitations - +
15.5.1Foreign Key Constraints
17.5.1Foreign Key Constraints
15.6MySQL Index Definition
17.6MySQL Index Definition
16SQLite Database + 18SQLite Database - - - - + + + - - +
16.1SQLite Type Mapping + 18.1SQLite Type Mapping - - + +
16.1.1String Type Mapping
16.1.2Binary Type Mapping
18.1.1String Type Mapping
18.1.2Binary Type Mapping
16.2SQLite Database Class
16.3SQLite Connection and Connection Factory
16.4SQLite Exceptions
18.2SQLite Database Class
18.3SQLite Connection and Connection Factory
18.4SQLite Exceptions
16.5SQLite Limitations + 18.5SQLite Limitations - - - - - - + + + + + +
16.5.1Query Result Caching
16.5.2Automatic Assignment of Object Ids
16.5.3Foreign Key Constraints
16.5.4Constraint Violations
16.5.5Sharing of Queries
16.5.6Forced Rollback
18.5.1Query Result Caching
18.5.2Automatic Assignment of Object Ids
18.5.3Foreign Key Constraints
18.5.4Constraint Violations
18.5.5Sharing of Queries
18.5.6Forced Rollback
16.6SQLite Index Definition
18.6SQLite Index Definition
17PostgreSQL Database + 19PostgreSQL Database - - - - + + + - - +
17.1PostgreSQL Type Mapping + 19.1PostgreSQL Type Mapping - - + +
17.1.1String Type Mapping
17.1.2Binary Type and UUID Mapping
19.1.1String Type Mapping
19.1.2Binary Type and UUID Mapping
17.2PostgreSQL Database Class
17.3PostgreSQL Connection and Connection Factory
17.4PostgreSQL Exceptions
19.2PostgreSQL Database Class
19.3PostgreSQL Connection and Connection Factory
19.4PostgreSQL Exceptions
17.5PostgreSQL Limitations + 19.5PostgreSQL Limitations - - - - - - + + + + + +
17.5.1Query Result Caching
17.5.2Foreign Key Constraints
17.5.3Unique Constraint Violations
17.5.4Date-Time Format
17.5.5Timezones
17.5.6NUMERIC Type Support
19.5.1Query Result Caching
19.5.2Foreign Key Constraints
19.5.3Unique Constraint Violations
19.5.4Date-Time Format
19.5.5Timezones
19.5.6NUMERIC Type Support
17.6PostgreSQL Index Definition
19.6PostgreSQL Index Definition
18Oracle Database + 20Oracle Database - - - - + + + - - +
18.1Oracle Type Mapping + 20.1Oracle Type Mapping - - + +
18.1.1String Type Mapping
18.1.2Binary Type Mapping
20.1.1String Type Mapping
20.1.2Binary Type Mapping
18.2Oracle Database Class
18.3Oracle Connection and Connection Factory
18.4Oracle Exceptions
20.2Oracle Database Class
20.3Oracle Connection and Connection Factory
20.4Oracle Exceptions
18.5Oracle Limitations + 20.5Oracle Limitations - - - - - - - - + + + + + + + +
18.5.1Identifier Truncation
18.5.2Query Result Caching
18.5.3Foreign Key Constraints
18.5.4Unique Constraint Violations
18.5.5Large FLOAT and NUMBER Types
18.5.6Timezones
18.5.7LONG Types
18.5.8LOB Types and By-Value Accessors/Modifiers
20.5.1Identifier Truncation
20.5.2Query Result Caching
20.5.3Foreign Key Constraints
20.5.4Unique Constraint Violations
20.5.5Large FLOAT and NUMBER Types
20.5.6Timezones
20.5.7LONG Types
20.5.8LOB Types and By-Value Accessors/Modifiers
18.6Oracle Index Definition
20.6Oracle Index Definition
19Microsoft SQL Server Database + 21Microsoft SQL Server Database - - - - + + + - - +
19.1SQL Server Type Mapping + 21.1SQL Server Type Mapping - - - - + + + +
19.1.1String Type Mapping
19.1.2Binary Type and UNIQUEIDENTIFIER Mapping
19.1.3ROWVERSION Mapping
19.1.4Long String and Binary Types
21.1.1String Type Mapping
21.1.2Binary Type and UNIQUEIDENTIFIER Mapping
21.1.3ROWVERSION Mapping
21.1.4Long String and Binary Types
19.2SQL Server Database Class
19.3SQL Server Connection and Connection Factory
19.4SQL Server Exceptions
21.2SQL Server Database Class
21.3SQL Server Connection and Connection Factory
21.4SQL Server Exceptions
19.5SQL Server Limitations + 21.5SQL Server Limitations - - - - - - - + + + + + + +
19.5.1Query Result Caching
19.5.2Foreign Key Constraints
19.5.3Unique Constraint Violations
19.5.4Multi-threaded Windows Applications
19.5.5Affected Row Count and DDL Statements
19.5.6Long Data and Auto Object Ids, ROWVERSION
19.5.7Long Data and By-Value Accessors/Modifiers
21.5.1Query Result Caching
21.5.2Foreign Key Constraints
21.5.3Unique Constraint Violations
21.5.4Multi-threaded Windows Applications
21.5.5Affected Row Count and DDL Statements
21.5.6Long Data and Auto Object Ids, ROWVERSION
21.5.7Long Data and By-Value Accessors/Modifiers
19.6SQL Server Index Definition
21.6SQL Server Index Definition
20Profiles Introduction22Profiles Introduction
21Boost Profile + 23Boost Profile - - - - + + + + - - @@ -808,35 +822,35 @@ for consistency. - - + - + - + - + - + - + - + - + - + - + - + - + + + + + + +
21.1Smart Pointers Library
21.2Unordered Containers Library
21.3Multi-Index Container Library
21.4Optional Library
23.1Smart Pointers Library
23.2Unordered Containers Library
23.3Multi-Index Container Library
23.4Optional Library
21.5Date Time Library + 23.5Date Time Library - - - - - + + + + +
21.5.1MySQL Database Type Mapping
21.5.2SQLite Database Type Mapping
21.5.3PostgreSQL Database Type Mapping
21.5.4Oracle Database Type Mapping
21.5.5SQL Server Database Type Mapping
23.5.1MySQL Database Type Mapping
23.5.2SQLite Database Type Mapping
23.5.3PostgreSQL Database Type Mapping
23.5.4Oracle Database Type Mapping
23.5.5SQL Server Database Type Mapping
21.6Uuid Library + 23.6Uuid Library - - - - - + + + + +
21.6.1MySQL Database Type Mapping
21.6.2SQLite Database Type Mapping
21.6.3PostgreSQL Database Type Mapping
21.6.4Oracle Database Type Mapping
21.6.5SQL Server Database Type Mapping
23.6.1MySQL Database Type Mapping
23.6.2SQLite Database Type Mapping
23.6.3PostgreSQL Database Type Mapping
23.6.4Oracle Database Type Mapping
23.6.5SQL Server Database Type Mapping
22Qt Profile + 24Qt Profile - - + - - @@ -957,10 +971,10 @@ for consistency. - - - - + + + +
22.1Basic Types Library + 24.1Basic Types Library - - - - - + + + + +
22.1.1MySQL Database Type Mapping
22.1.2SQLite Database Type Mapping
22.1.3PostgreSQL Database Type Mapping
22.1.4Oracle Database Type Mapping
22.1.5SQL Server Database Type Mapping
24.1.1MySQL Database Type Mapping
24.1.2SQLite Database Type Mapping
24.1.3PostgreSQL Database Type Mapping
24.1.4Oracle Database Type Mapping
24.1.5SQL Server Database Type Mapping
22.2Smart Pointers Library
24.2Smart Pointers Library
22.3Containers Library + 24.3Containers Library - +
22.3.1Change-Tracking QList
24.3.1Change-Tracking QList
22.4Date Time Library + 24.4Date Time Library - - - - - + + + + +
22.4.1MySQL Database Type Mapping
22.4.2SQLite Database Type Mapping
22.4.3PostgreSQL Database Type Mapping
22.4.4Oracle Database Type Mapping
22.4.5SQL Server Database Type Mapping
24.4.1MySQL Database Type Mapping
24.4.2SQLite Database Type Mapping
24.4.3PostgreSQL Database Type Mapping
24.4.4Oracle Database Type Mapping
24.4.5SQL Server Database Type Mapping
6Relationships
7Value Types
8Inheritance
9Views
10Session
11Optimistic Concurrency
12ODB Pragma Language
10Views
11Session
12Optimistic Concurrency
14ODB Pragma Language
@@ -1333,7 +1347,7 @@ private: placed after the class definition. They could have also been moved into a separate header leaving the original class completely unchanged (for more information on such a non-intrusive conversion - refer to Chapter 12, "ODB Pragma Language").

+ refer to Chapter 14, "ODB Pragma Language").

 class person
@@ -1606,7 +1620,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 15.2, "MySQL Database Class").

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

Next, we create three person objects. Right now they are transient objects, which means that if we terminate the application @@ -2014,7 +2028,7 @@ Hello, Joe! tables using object relationships or custom join conditions.

While you can find a much more detailed description of views in - Chapter 9, "Views", here is how we can define + Chapter 10, "Views", here is how we can define the person_stat view that returns the basic statistics about the person objects:

@@ -2138,7 +2152,7 @@ odb::mysql::database db2 ("john", "secret", "test_db2"); tight integration with specific database systems to being able to write database-agnostic code and loading individual database systems support dynamically. While all these aspects are covered in detail - in Chapter 14, "Multi-Database Support", in this + in Chapter 16, "Multi-Database Support", in this section we will get a taste of this functionality by extending our "Hello World" example to be able to store its data either in MySQL or PostgreSQL (other database systems supported by ODB can be added @@ -2156,7 +2170,7 @@ odb --multi-database dynamic -d common -d mysql -d pgsql \

The --multi-database ODB compiler option turns on multi-database support. For now it is not important what the dynamic value that we passed to this option means, but - if you are curious, see Chapter 14. The result of this + if you are curious, see Chapter 16. The result of this command are three sets of generated files: person-odb.?xx (common interface; corresponds to the common database), person-odb-mysql.?xx (MySQL support code), and @@ -2384,7 +2398,7 @@ psql --user=odb_test --dbname=odb_test -f person-pgsql.sql computations to the relational database instead of performing them in the application's process. To support such requirements ODB distinguishes a third kind of C++ types, called views - (Chapter 9, "Views"). An ODB view is a C++ + (Chapter 10, "Views"). An ODB view is a C++ class that embodies a light-weight, read-only projection of one or more persistent objects or database tables or the result of a native SQL query execution.

@@ -2497,13 +2511,13 @@ class person 7.2.1, "Composite Object Ids") value type. This type should be default-constructible. It is also possible to declare a persistent class without an object id, however, such a class will have limited - functionality (Section 12.1.6, + functionality (Section 14.1.6, "no_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 12, "ODB Pragma Language").

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

Normally, a persistent class should define the default constructor. The generated database support code uses this constructor when @@ -2534,7 +2548,7 @@ private: Section 4.4, "Query Result").

The ODB compiler also needs access to the non-transient - (Section 12.4.11, "transient") + (Section 14.4.11, "transient") data members of a persistent class. The ODB compiler can access such data members directly if they are public. It can also do so if they are private or protected and the odb::access @@ -2607,9 +2621,14 @@ private: and modifier expressions using the db get and db set pragmas. For more information on custom accessor and modifier expressions refer to - Section 12.4.5, + Section 14.4.5, "get/set/access".

+

Data members of a persistent class can also be split into + separately-loaded and/or separately-updated sections. + For more information on this functionality, refer to + Chapter 9, "Sections".

+

You may be wondering whether we also have to declare value types as persistent. We don't need to do anything special for simple value types such as int or std::string since the @@ -2619,7 +2638,7 @@ private: mapping to the database 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 12.3.1, "type".

+ in Section 14.3.1, "type".

Similar to object classes, composite value types have to be explicitly declared as persistent using the db value @@ -2652,7 +2671,7 @@ class name return pointers to these instances. As we will see in later chapters, pointers are also used to establish relationships between objects (Chapter 6, "Relationships") as well as to cache - persistent objects in a session (Chapter 10, + persistent objects in a session (Chapter 11, "Session"). While in most cases you won't need to deal with pointers to views, it is possible to a obtain a dynamically allocated instance of a view using the result_iterator::load() @@ -2751,9 +2770,9 @@ namespace accounting }

-

Refer to Section 12.1.2, "pointer - (object)", Section 12.2.4, "pointer - (view)", and Section 12.5.1, "pointer +

Refer to Section 14.1.2, "pointer + (object)", Section 14.2.4, "pointer + (view)", and Section 14.5.1, "pointer (namespace)" for more information on these mechanisms.

Built-in support that is provided by the ODB runtime library allows us @@ -2899,7 +2918,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 12, "ODB Pragma + and db type (Chapter 14, "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.

@@ -3106,7 +3125,7 @@ t.commit ();

For more information on the transaction callback support, refer - to Section 13.1, "Transaction Callbacks".

+ to Section 15.1, "Transaction Callbacks".

Note that in the above discussion of atomicity, consistency, isolation, and durability, all of those guarantees only apply @@ -3185,7 +3204,7 @@ update_age (database& db, person& p) } -

See also Section 13.1, "Transaction Callbacks" +

See also Section 15.1, "Transaction Callbacks" for an alternative approach.

3.6 Connections

@@ -3403,7 +3422,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 12.4.2, + application-assigned object ids (Section 14.4.2, "auto").

The second and third persist() functions are similar to the @@ -3518,7 +3537,7 @@ t.commit ();

The first special property of reload() compared to the load() function is that it does not interact with the session's object cache - (Section 10.1, "Object Cache"). That is, if + (Section 11.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 @@ -3529,7 +3548,7 @@ t.commit (); 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, refer to Chapter 12, "Optimistic Concurrency".

If we don't know for sure whether an object with a given id @@ -3649,14 +3668,14 @@ t.commit (); 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, refer to Chapter 12, "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.12, "readonly + data members can be declared read-only (see Section + 14.1.4, "readonly (object)", Section + 14.3.6, "readonly (composite value)", and + Section 14.4.12, "readonly (data member)").

If an individual data member is declared read-only, then @@ -3737,7 +3756,7 @@ t.commit (); 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".

+ refer to Chapter 12, "Optimistic Concurrency".

The erase_query() function allows us to delete the state of multiple objects matching certain criteria. It uses @@ -4195,6 +4214,20 @@ namespace odb virtual const char* what () const throw (); }; + + // Section exceptions. + // + struct section_not_loaded: exception + { + virtual const char* + what () const throw (); + }; + + struct section_not_in_object: exception + { + virtual const char* + what () const throw (); + }; } @@ -4212,7 +4245,7 @@ namespace odb

The next two exceptions (already_in_session, and not_in_session) are thrown by the odb::session - class and are discussed in Chapter 10, "Session".

+ class and are discussed in Chapter 11, "Session".

The session_required exception is thrown when ODB detects that correctly loading a bidirectional object relationship requires a @@ -4249,7 +4282,7 @@ namespace odb by the update() database function and certain erase() database functions when operating on objects with the optimistic concurrency model. See - Chapter 11, "Optimistic Concurrency" for details.

+ Chapter 12, "Optimistic Concurrency" for details.

The result_not_cached exception is thrown by the query result class. Refer to Section 4.4, @@ -4263,7 +4296,7 @@ namespace odb

The abstract_class exception is thrown by the database functions when we attempt to persist, update, load, or erase an instance of a polymorphic abstract class. For more information - on abstract classes, refer to Section 12.1.3, + on abstract classes, refer to Section 14.1.3, "abstract".

The no_type_info exception is thrown by the database @@ -4289,6 +4322,13 @@ namespace odb name is not found. Refer to Section 3.4, "Database" for details.

+

The section_not_loaded exception is thrown if we + attempt to update an object section that hasn't been loaded. + The section_not_in_object exception is thrown if + the section instance being loaded or updated does not belong + to the corresponding object. See Chapter 9, + "Sections" for more information on these exceptions.

+

The odb::exception class is defined in the <odb/exception.hxx> header file. All the concrete ODB exceptions are defined in @@ -4746,7 +4786,10 @@ namespace odb (cached or uncached) by calling database::query() will invalidate the existing uncached result. Furthermore, calling any other database functions, such as update() - or erase() will also invalidate the uncached result.

+ or erase() will also invalidate the uncached result. + It also follows that uncached results cannot be used on objects + with containers (Chapter 5, "Containers") since + loading a container would invalidate the uncached result.

The empty() function returns true if there are no objects in the result and false otherwise. @@ -5470,7 +5513,7 @@ private: column, they can occupy multiple columns. For an ordered container table the ODB compiler also defines two indexes: one for the object id column(s) and the other for the index - column. Refer to Section 12.6, "Index Definition + column. Refer to Section 14.6, "Index Definition Pragmas" for more information on how to customize these indexes.

@@ -5499,7 +5542,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 12, "ODB Pragma + these pragmas, refer to Chapter 14, "ODB Pragma Language". The following example shows some of the possible customizations:

@@ -5525,8 +5568,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.9, - "unordered", Section 12.4.18, + db unordered pragma (Section 14.3.9, + "unordered", Section 14.4.18, "unordered"). For example:

@@ -5565,7 +5608,7 @@ private:
      id or element value are composite, then, instead of a single
      column, they can occupy multiple columns. ODB compiler also
      defines an index on a set container table for the object id
-     column(s). Refer to Section 12.6, "Index Definition
+     column(s). Refer to Section 14.6, "Index Definition
      Pragmas" for more information on how to customize this
      index.

@@ -5593,7 +5636,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 12, "ODB Pragma + these pragmas, refer to Chapter 14, "ODB Pragma Language". The following example shows some of the possible customizations:

@@ -5632,7 +5675,7 @@ private: element value are composite, then instead of a single column they can occupy multiple columns. ODB compiler also defines an index on a map container table for the object id - column(s). Refer to Section 12.6, "Index Definition + column(s). Refer to Section 14.6, "Index Definition Pragmas" for more information on how to customize this index.

@@ -5661,7 +5704,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 12, "ODB Pragma + these pragmas, refer to Chapter 14, "ODB Pragma Language". The following example shows some of the possible customizations:

@@ -5812,6 +5855,10 @@ for (;;) }
+

For the interaction of change-tracking containers with change-updated + object sections, refer to Section 9.4, "Sections and + Change-Tracking Containers".

+

5.4.1 Change-Tracking vector

Class template odb::vector, defined in @@ -5828,8 +5875,8 @@ for (;;)

odb::vector incurs 2-bit per element overhead in order to store the change state. It cannot - be stored unordered in the database (Section - 12.4.18 "unordered") but can be used as an inverse + be stored unordered in the database (Section + 14.4.18 "unordered") but can be used as an inverse side of a relationship (6.2 "Bidirectional Relationships"). In this case, no change tracking is performed since no state for such a container is stored in the database.

@@ -6085,11 +6132,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 - 12.4.6, "null/not_null") for + use the not_null pragma (Section + 14.4.6, "null/not_null") for single object pointers and the value_not_null pragma - (Section - 12.4.23, "value_null/value_not_null") + (Section + 14.4.25, "value_null/value_not_null") for containers of object pointers. For example:

@@ -6156,7 +6203,7 @@ unsigned long john_id, jane_id;
 
   

The only notable line in the above code is the creation of a session before the second transaction starts. As discussed in - Chapter 10, "Session", a session acts as a cache + Chapter 11, "Session", a session acts as a cache of persistent objects. By creating a session before loading the employee objects we make sure that their employer_ pointers @@ -6336,7 +6383,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 12, "ODB Pragma Language"). For example:

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

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

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

@@ -6547,7 +6594,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.18, "unordered") + (Section 14.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).

@@ -7198,6 +7245,10 @@ db.persist (e); t.commit ();
+

For the interaction of lazy pointers with lazy-loaded object + sections, refer to Section 9.3, "Sections and + Lazy Pointers".

+

6.5 Using Custom Smart Pointers

While the ODB runtime and profile libraries provide support for @@ -7279,7 +7330,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 12.3.1, "type").

+ pragma (Section 14.3.1, "type").

7.2 Composite Value Types

@@ -7331,7 +7382,7 @@ private:

The ODB compiler also needs access to the non-transient - (Section 12.4.11, "transient") + (Section 14.4.11, "transient") data members of a composite value type. It uses the same mechanisms as for persistent classes which are discussed in Section 3.2, "Declaring Persistent Objects and @@ -7497,15 +7548,15 @@ class person pointer, or read-only data members. It also must be default-constructible. Furthermore, if the persistent class in which this composite value type is used as object id has session support - enabled (Chapter 10, "Session"), then it must also + enabled (Chapter 11, "Session"), then it must also implement the less-than comparison operator (operator<).

7.2.2 Composite Value Column and Table Names

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 - 12.4.9, "column"). For composite value + the db column pragma (Section + 14.4.9, "column"). For composite value types things are slightly more complex since they are mapped to multiple columns. Consider the following example:

@@ -7606,9 +7657,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.31, "value_column") or + (Section 14.4.33, "value_column") or db key_column - (Section 12.4.30, "key_column") + (Section 14.4.32, "key_column") pragmas are used to specify the column prefix.

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

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

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

 #pragma db value
@@ -7694,7 +7745,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 12.4.6,
+     pragma (Section 14.4.6,
      "null/not_null").

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

+ (Section 23.4, "Optional Library").

Another common C++ representation of a value that can be NULL is a pointer. ODB will automatically @@ -8020,7 +8071,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 12.1.3, "abstract"). + pragma (Section 14.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 @@ -8267,7 +8318,7 @@ class contractor: public person

Similarly, if we enable or disable session support - (Chapter 10, "Session") for the root class, then + (Chapter 11, "Session") for the root class, then the ODB compiler will automatically enable or disable it for all the derived classes.

@@ -8500,9 +8551,9 @@ t.commit (); to ordinary objects. These include containers (Chapter 5, "Containers"), object relationships, including to polymorphic objects (Chapter 6, "Relationships"), views - (Chapter 9, "Views"), session (Chapter - 10, "Session"), and optimistic concurrency (Chapter - 11, "Optimistic Concurrency"). There are, however, a few + (Chapter 10, "Views"), session (Chapter + 11, "Session"), and optimistic concurrency (Chapter + 12, "Optimistic Concurrency"). There are, however, a few limitations, mainly due to the underlying use of SQL to access the data.

@@ -8622,11 +8673,713 @@ class permanent_employee: public employee // Polymorphism inheritance. }; + + + + +
+

9 Sections

+ +

ODB sections are an optimization mechanism that allows us to + partition data members of a persistent class into groups that + can be separately loaded and/or updated. This can be useful, + for example, if an object contains expensive to load or update + data members (such as BLOBs or containers) and + that are accessed or modified infrequently. For example:

+ +
+#include <odb/section.hxx>
+
+#pragma db object
+class person
+{
+  ...
+
+  #pragma db load(lazy) update(manual)
+  odb::section keys_;
+
+  #pragma db section(keys_) type("BLOB")
+  char public_key_[1024];
+
+  #pragma db section(keys_) type("BLOB")
+  char private_key_[1024];
+};
+
+transaction t (db.begin ());
+
+auto_ptr<person> p (db.load<person> (...)); // Keys are not loaded.
+
+if (need_keys)
+{
+  db.load (*p, p->keys_); // Load keys.
+  ...
+}
+
+db.update (*p); // Keys are not updated.
+
+if (update_keys)
+{
+  ...
+  db.update (*p, p->keys_); // Update keys.
+}
+
+t.commit ();
+  
+ +

A complete example that shows how to use sections is available in + the section directory in the odb-examples + package.

+ +

Why do we need to group data members into sections? Why can't + each data member be loaded and updated independently if and + when necessary? The reason for this requirement is that loading + or updating a group of data members with a single database + statement is significantly more efficient than loading or updating + each data member with a separate statement. Because ODB + prepares and caches statements used to load and update + persistent objects, generating a custom statement for + a specific set of data members that need to be loaded or + updated together is not a viable approach either. To resolve + this, ODB allows us to group data members that are + often updated and/or loaded together into sections. To + achieve the best performance, we should aim to find a balance + between having too many sections with too few data + members and too few sections with too many data + members. We can use the access and modification patterns + of our application as a base for this decision.

+ +

To add a new section to a persistent class we declare a new + data member of the odb::section type. At this + point we also need to specify the loading and updating behavior + of this section with the db load and + db update pragmas, respectively.

+ +

The loading behavior of a section can be either eager + or lazy. An eager-loaded section is always loaded as + part of the object load. A lazy-loaded section is not loaded + as part of the object load and has to be explicitly loaded with + the database::load() function (discussed below) if + and when necessary.

+ +

The updating behavior of a section can be always, + change, or manual. An always-updated + section is always updated as part of the object update, + provided it has been loaded. A change-updated section + is only updated as part of the object update if it has been loaded + and marked as changed. A manually-updated section is never updated + as part of the object update and has to be explicitly updated with + the database::update() function (discussed below) if + and when necessary.

+ +

If no loading behavior is specified explicitly, then an eager-loaded + section is assumed. Similarly, if no updating behavior is specified, + then an always-updated section is assumed. An eager-loaded, always-updated + section is pointless and therefore illegal. Only persistent classes + with an object id can have sections.

+ +

To specify that a data member belongs to a section we use the + db section pragma with the section's member + name as its single argument. Except for special data members + such as the object id and optimistic concurrency version, any + direct, non-transient member of a persistent class can belong + to a section, including composite values, containers, and + pointers to objects. For example:

+ +
+#pragma db value
+class text
+{
+  std::string data;
+  std::string lang;
+};
+
+#pragma db object
+class person
+{
+  ...
+
+  #pragma db load(lazy)
+  odb::section extras_;
+
+  #pragma db section(extras_)
+  text bio_;
+
+  #pragma db section(extras_)
+  std::vector<std::string> nicknames_;
+
+  #pragma db section(extras_)
+  std::shared_ptr<person> emergency_contact_;
+};
+  
+ +

An empty section is pointless and therefore illegal, except + in abstract or polymorphic classes where data members can be + added to a section by derived classes (see Section + 9.1, "Sections and Inheritance").

+ +

The odb::section class is defined in the + <odb/section.hxx> header file and has the + following interface:

+ +
+namespace odb
+{
+  class section
+  {
+  public:
+    // Load state.
+    //
+    bool
+    loaded () const;
+
+    void
+    unload ();
+
+    // Change state.
+    //
+    bool
+    changed () const;
+
+    void
+    change ();
+
+    // User data.
+    //
+    unsigned char
+    user_data () const;
+
+    void
+    user_data (unsigned char);
+  };
+}
+  
+ +

The loaded() accessor can be used to determine + whether a section is already loaded. The unload() + modifier marks a loaded section as not loaded. This, for example, + can be useful if you don't want the section to be reloaded during + the object reload.

+ +

The changed() accessor can be used to query the + section's change state. The change() modifier + marks the section as changed. It is valid to call this modifier + for an unloaded (or transient) section, however, the state will + be reset back to unchanged once the section (or object) is loaded. + The change state is only relevant to sections with change-updated + behavior and is ignored for all other sections.

+ +

The size of the section class is one byte with four bits available + to store a custom state via the user_data() accessor + and modifier.

+ +

The odb::database class provides special + versions of the load() and update() + functions that allow us to load and update sections of a + persistent class. Their signatures are as follows:

+ +
+  template <typename T>
+  void
+  load (T& object, section&);
+
+  template <typename T>
+  void
+  update (const T& object, const section&);
+  
+ +

Before calling the section load() function, the + object itself must already be loaded. If the section is already + loaded, then the call to load() will reload its + data members. It is illegal to explicitly load an eager-loaded + section.

+ +

Before calling the section update() function, the + section (and therefore the object) must be in the loaded state. + If the section is not loaded, the odb::section_not_loaded + exception is thrown. The section update() function + does not check but does clear the section's change state. In + other words, section update() will always update + section data members in the database and clear the change flag. + Note also that any section, that is, always-, change-, or + manually-updated, can be explicitly updated with this function.

+ +

Both section load() and update(), just + like the rest of the database operations, must be performed within + a transaction. Notice also that both load() and + update() expect a reference to the section as + their second argument. This reference must refer to the data + member in the object passed as the first argument. If instead + it refers to some other instance of the section + class, for example, a local copy or a temporary, then the + odb::section_not_in_object exception is thrown. + For example:

+ +
+#pragma db object
+class person
+{
+public:
+  ...
+
+  odb::section
+  keys () const {return keys_;}
+
+private:
+  odb::section keys_;
+
+  ...
+};
+
+auto_ptr<person> p (db.load<person> (...));
+
+section s (p->keys ());
+db.load (*p, s);            // Throw section_not_in_object, copy.
+
+db.update (*p, p->keys ()); // Throw section_not_in_object, copy.
+  
+ +

At first glance it may seem more appropriate to make the + section class non-copyable in order to prevent + such errors from happening. However, it is perfectly reasonable + to expect to be able to copy (or assign) sections as part of + the object copying (or assignment). As a result, sections are + left copyable and copy-assignable, however, this functionality + should not be used in accessors or modifiers. Instead, section + accessors and modifiers should always be by-reference. Here is + how we can fix our previous example:

+ +
+#pragma db object
+class person
+{
+public:
+  ...
+
+  const odb::section&
+  keys () const {return keys_;}
+
+  odb::section&
+  keys () {return keys_;}
+
+private:
+  odb::section keys_;
+
+  ...
+};
+
+auto_ptr<person> p (db.load<person> (...));
+
+section& s (p->keys ());
+db.load (*p, s);            // Ok, reference.
+
+db.update (*p, p->keys ()); // Ok, reference.
+  
+ +

Several other database operations affect sections. The state of + a section in a transient object is undefined. That is, before + the call to object persist() or load() + functions, or after the call to object erase() + function, the values returned by the section::loaded() and + section::changed() accessors are undefined.

+ +

After the call to persist(), all sections, including + eager-loaded ones, are marked as loaded and unchanged. If instead we + are loading an object with the load() call or as + a result of a query, then eager-loaded sections are loaded + and marked as loaded and unchanged while lazy-loaded ones are marked + as unloaded. If a lazy-loaded section is later loaded with the + section load() call, then it is marked as loaded and + unchanged.

+ +

When we update an object with the update() call, + manually-updated sections are ignored while always-updated + sections are updated if they are loaded. Change-updated + sections are only updated if they are both loaded and marked + as changed. After the update, such sections are reset to the + unchanged state. When we reload an object with the + reload() call, sections that were loaded are + automatically reloaded and reset to the unchanged state.

+ +

To further illustrate the state transitions of a section, + consider this example:

+ +
+#pragma db object
+class person
+{
+  ...
+
+  #pragma db load(lazy) update(change)
+  odb::section keys_;
+
+  ...
+};
+
+transaction t (db.begin ());
+
+person p ("John", "Doe"); // Section state is undefined (transient).
+
+db.persist (p);           // Section state: loaded, unchanged.
+
+auto_ptr<person> l (
+  db.load<person> (...)); // Section state: unloaded, unchanged.
+
+db.update (*l);           // Section not updated since not loaded.
+db.update (p);            // Section not updated since not changed.
+
+p.keys_.change ();        // Section state: loaded, changed.
+db.update (p);            // Section updated, state: loaded, unchanged.
+
+db.update (*l, l->keys_); // Throw section_not_loaded.
+db.update (p, p.keys_);   // Section updated even though not changed.
+
+db.reload (*l);           // Section not reloaded since not loaded.
+db.reload (p);            // Section reloaded, state: loaded, unchanged.
+
+db.load (*l, l->keys_);   // Section loaded, state: loaded, unchanged.
+db.load (p, p.keys_);     // Section reloaded, state: loaded, unchanged.
+
+db.erase (p);             // Section state is undefined (transient).
+
+t.commit ();
+  
+ +

When using change-updated behavior, it is our responsibility to + mark the section as changed when any of the data members belonging + to this section is modified. A natural place to mark the section + as changed is the modifiers for section data members, for example:

+ +
+#pragma db object
+class person
+{
+  ...
+
+  typedef std::array<char, 1024> key_type;
+
+  const key_type&
+  public_key () const {return public_key_;}
+
+  void
+  public_key (const key_type& k)
+  {
+    public_key_ = k;
+    keys_.change ();
+  }
+
+  const key_type&
+  private_key () const {return private_key_;}
+
+  void
+  private_key (const key_type& k)
+  {
+    private_key_ = k;
+    keys_.change ();
+  }
+
+private:
+  #pragma db load(lazy) update(change)
+  odb::section keys_;
+
+  #pragma db section(keys_) type("BLOB")
+  key_type public_key_;
+
+  #pragma db section(keys_) type("BLOB")
+  key_type private_key_;
+
+  ...
+};
+  
+ +

One interesting aspect of change-updated sections is what happens + when a transaction that performed an object or section update is + later rolled back. In this case, while the change state of a + section has been reset (after update), actual changes were not + committed to the database. Change-updated sections handle this + case by automatically registering a rollback callback and then, + if it is called, restoring the original change state. The + following code illustrates this semantics (continuing with + the previous example):

+ +
+auto_ptr<person> p;
+
+try
+{
+  transaction t (db.begin ());
+  p = db.load<person> (...);
+  db.load (*p, p->keys_);
+
+  p->private_key (new_key); // The section is marked changed.
+  db.update (*p);           // The section is reset to unchanged.
+
+  throw failed ();          // Triggers rollback.
+  t.commit ();
+}
+catch (const failed&)
+{
+  // The section is restored back to changed.
+}
+  
+ + +

9.1 Sections and Inheritance

+ +

With both reuse and polymorphism inheritance (Chapter 8, + "Inheritance") it is possible to add new sections to derived + classes. It is also possible to add data members from derived + classes to sections declared in the base. For example:

+ +
+#pragma db object polymorphic
+class person
+{
+  ...
+
+  virtual void
+  print ();
+
+  #pragma db load(lazy)
+  odb::section print_;
+
+  #pragma db section(print_)
+  std::string bio_;
+};
+
+#pragma db object
+class employee: public person
+{
+  ...
+
+  virtual void
+  print ();
+
+  #pragma db section(print_)
+  std::vector<std::string> employment_history_;
+};
+
+transaction t (db.begin ());
+
+auto_ptr<person> p (db.load<person> (...)); // Person or employee.
+db.load (*p, p->print_); // Load data members needed for print.
+p->print ();
+
+t.commit ();
+  
+ +

When data members of a section are spread over several classes in a + reuse inheritance hierarchy, both section load and update are + performed with a single database statement. In contrast, with + polymorphism inheritance, section load is performed with a + single statement while update requires a separate statement + for each class that adds to the section.

+ +

Note also that in polymorphism inheritance the section-to-object + association is static. Or, in other words, you can load a section + via an object only if its static type actually contains this + section. The following example will help illustrate this + point further:

+ +
+#pragma db object polymorphic
+class person
+{
+  ...
+};
+
+#pragma db object
+class employee: public person
+{
+  ...
+
+  #pragma db load(lazy)
+  odb::section extras_;
+
+  ...
+};
+
+#pragma db object
+class manager: public employee
+{
+  ...
+};
+
+auto_ptr<manager> m (db.load<manager> (...));
+
+person& p (*m);
+employee& e (*m);
+section& s (m->extras_);
+
+db.load (p, s); // Error: extras_ is not in person.
+db.load (e, s); // Ok: extras_ is in employee.
+  
+ +

9.2 Sections and Optimistic Concurrency

+ +

When sections are used in a class with the optimistic concurrency + model (Chapter 12, "Optimistic Concurrency"), + both section update and load operations compare the object version + to that in the database and throw the odb::object_changed + exception if they do not match. In addition, the section update + operation increments the version to indicate that the object state + has changed. For example:

+ +
+#pragma db object optimistic
+class person
+{
+  ...
+
+  #pragma db version
+  unsigned long long version_;
+
+  #pragma db load(lazy)
+  odb::section extras_;
+
+  #pragma db section(extras_)
+  std::string bio_;
+};
+
+auto_ptr<person> p;
+
+{
+  transaction t (db.begin ());
+  p = db.load<person> (...);
+  t.commit ();
+}
+
+{
+  transaction t (db.begin ());
+
+  try
+  {
+    db.load (*p, p->extras_); // Throws if object state has changed.
+  }
+  catch (const object_changed&)
+  {
+    db.reload (*p);
+    db.load (*p, p->extras_); // Cannot fail.
+  }
+
+  t.commit ();
+}
+  
+ +

Note also that if an object update triggers one or more + section updates, then each such update will increment the + object version. As a result, an update of an object that + contains sections may result in a version increment by + more than one.

+ +

When sections are used together with optimistic concurrency and + inheritance, an extra step may be required to enable this + functionality. If you plan to add new sections to derived + classes, then the root class of the hierarchy + (the one that declares the version data member) must be + declared as sectionable with the db sectionable + pragma. For example:

+ +
+#pragma db object polymorphic sectionable
+class person
+{
+  ...
+
+  #pragma db version
+  unsigned long long version_;
+};
+
+#pragma db object
+class employee: public person
+{
+  ...
+
+  #pragma db load(lazy)
+  odb::section extras_;
+
+  #pragma db section(extras_)
+  std::vector<std::string> employment_history_;
+};
+  
+ +

This requirement has to do with the need to generate extra + version increment code in the root class that will be used + by sections added in the derived classes. If you forget to + declare the root class as sectionable and later add a + section to one of the derived classes, the ODB compiler + will issue diagnostics.

+ +

9.3 Sections and Lazy Pointers

+ +

If a lazy pointer (Section 6.4, "Lazy Pointers") + belongs to a lazy-loaded section, then we end up with two levels of + lazy loading. Specifically, when the section is loaded, the lazy + pointer is initialized with the object id but the object itself + is not loaded. For example:

+ +
+#pragma db object
+class employee
+{
+  ...
+
+  #pragma db load(lazy)
+  odb::section extras_;
+
+  #pragma db section(extras_)
+  odb::lazy_shared_ptr<employer> employer_;
+};
+
+transaction t (db.begin ());
+
+auto_ptr<employee> e (db.load<employee> (...)); // employer_ is NULL.
+
+db.load (*e, e->extras_); // employer_ contains valid employer id.
+
+e->employer_.load (); // employer_ points to employer object.
+
+t.commit ();
+  
+ +

9.4 Sections and Change-Tracking Containers

+ +

If a change-tracking container (Section 5.4, + "Change-Tracking Containers") belongs to a change-updated + section, then prior to an object update ODB will check if the + container has been changed and if so, automatically mark the + section as changed. For example:

+ +
+#pragma db object
+class person
+{
+  ...
+
+  #pragma db load(lazy) update(change)
+  odb::section extras_;
+
+  #pragma db section(extras_)
+  odb::vector<std::string> nicknames_;
+};
+
+transaction t (db.begin ());
+
+auto_ptr<person> p (db.load<person> (...));
+db.load (*p, p->extras_);
+
+p->nicknames_.push_back ("JD");
+
+db.update (*p); // Section is automatically updated even
+                // though it was not marked as changed.
+t.commit ();
+  
+ +
-

9 Views

+

10 Views

An ODB view is a C++ class or struct type that embodies a light-weight, read-only projection of one or more @@ -8764,11 +9517,11 @@ t.commit (); the result of a custom SQL query. The following sections discuss each of these kinds of view in more detail.

-

9.1 Object Views

+

10.1 Object Views

To associate one or more objects with a view we use the - db object pragma (Section - 12.2.1, "object"). We have already seen + db object pragma (Section + 14.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, @@ -8799,7 +9552,7 @@ struct employee_employer below. The optional join-condition part provides the criteria which should be used to associate this object with any of the previously associated objects or, as we will see in - Section 9.3, "Mixed Views", tables. Note that + Section 10.3, "Mixed Views", tables. Note that while the first associated object can have an alias, it cannot have a join condition.

@@ -8949,7 +9702,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 12.4.9, + db column pragma (Section 14.4.9, "column"). For example:

@@ -8965,8 +9718,8 @@ struct employee_employer
   

If an object data member specifies the SQL type with - the db type pragma (Section - 12.4.3, "type"), then this type is also used for + the db type pragma (Section + 14.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 @@ -9148,7 +9901,7 @@ t.commit (); query expression, and you need to qualify the column with the table, then you will need to use the table alias instead.

-

9.2 Table Views

+

10.2 Table Views

A table view is similar to an object view except that it is based on one or more database tables instead of persistent @@ -9156,7 +9909,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 12.2.2, + db table pragma (Section 14.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 @@ -9211,7 +9964,7 @@ struct employee_max_vacation

For more information on database schemas and the format of the - qualified names, refer to Section 12.1.8, + qualified names, refer to Section 14.1.8, "schema".

Note also that in the above examples we specified the SQL type @@ -9237,7 +9990,7 @@ struct employee_max_vacation column names, and query expressions. The optional join-condition part provides the criteria which should be used to associate this table with any of the previously associated tables or, as we will see in - Section 9.3, "Mixed Views", objects. Note that + Section 10.3, "Mixed Views", objects. Note that while the first associated table can have an alias, it cannot have a join condition.

@@ -9305,7 +10058,7 @@ t.commit (); -

9.3 Mixed Views

+

10.3 Mixed Views

A mixed view has both associated objects and tables. As a first example of a mixed view, let us improve employee_vacation @@ -9368,12 +10121,12 @@ struct employee_prev_employer }; -

9.4 View Query Conditions

+

10.4 View Query Conditions

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 12.2.3, + db query pragma (Section 14.2.3, "query").

As an example, consider a view that returns some information about @@ -9479,7 +10232,7 @@ struct employer_age }; -

9.5 Native Views

+

10.5 Native Views

The last kind of view supported by ODB is a native view. Native views are a low-level mechanism for capturing results of native @@ -9488,7 +10241,7 @@ struct employer_age the native SQL query, which must at a minimum include the select-list and, if applicable, the from-list. For example, here is how we can re-implement the employee_vacation table - view from Section 9.2 above as a native view:

+ view from Section 10.2 above as a native view:

 #pragma db view query("SELECT employee_id, vacation_days " \
@@ -9606,7 +10359,7 @@ result n (db.query<sequence_value> (
   
-

9.6 Other View Features and Limitations

+

10.6 Other View Features and Limitations

Views cannot be derived from other views. However, you can derive a view from a transient C++ class. View data members cannot be @@ -9674,14 +10427,14 @@ struct employee_name


-

10 Session

+

11 Session

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 may provide additional functionality, such as delayed database operations and automatic object state change tracking. As discussed later in - Section 10.2, "Custom Sessions", it is also + Section 11.2, "Custom Sessions", it is also possible to provide a custom session implementation that provides these or other features.

@@ -9868,7 +10621,7 @@ namespace odb iterate over the objects store in the cache. Refer to the ODB runtime header files for more details on this direct access.

-

10.1 Object Cache

+

11.1 Object Cache

A session is an object cache. Every time a session-enabled object is made persistent by calling the database::persist() function @@ -9950,7 +10703,7 @@ unsigned long id2 (save (db, p2)); // p2 is cached in s as non-const. } -

10.2 Custom Sessions

+

11.2 Custom Sessions

ODB can use a custom session implementation instead of the default odb::session. There could be multiple @@ -10070,7 +10823,7 @@ public:


-

11 Optimistic Concurrency

+

12 Optimistic Concurrency

The ODB transaction model (Section 3.5, "Transactions") guarantees consistency as long as we perform all the @@ -10154,9 +10907,9 @@ p.age (age); methods, such as timestamps, may be supported in the future.

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

@@ -10365,7 +11118,7 @@ for (bool done (false); !done; )
-

12 ODB Pragma Language

+

14 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. @@ -10534,10 +11287,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 12.8, + at the end of this chapter in Section 14.8, "C++ Compiler Warnings".

-

12.1 Object Type Pragmas

+

14.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, @@ -10554,78 +11307,84 @@ class person

table table name for a persistent class12.1.114.1.1
pointer pointer type for a persistent class12.1.214.1.2
abstract persistent class is abstract12.1.314.1.3
readonly persistent class is read-only12.1.414.1.4
optimistic persistent class with the optimistic concurrency model12.1.514.1.5
no_id persistent class has no object id12.1.614.1.6
callback database operations callback12.1.714.1.7
schema database schema for a persistent class12.1.814.1.8
polymorphic persistent class is polymorphic12.1.914.1.9
session enable/disable session support for a persistent class12.1.1014.1.10
definition definition location for a persistent class12.1.1114.1.11
transient all non-virtual data members in a persistent class are transient12.1.1214.1.12
sectionablesupport addition of new sections in derived classes14.1.13
-

12.1.1 table

+

14.1.1 table

The table specifier specifies the table name that should be used to store objects of the persistent class in a relational @@ -10652,10 +11411,10 @@ class person

For more information on database schemas and the format of the - qualified names, refer to Section 12.1.8, + qualified names, refer to Section 14.1.8, "schema".

-

12.1.2 pointer

+

14.1.2 pointer

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

If a pointer type is not explicitly specified, the default pointer, - specified at the namespace level (Section 12.5.1, + specified at the namespace level (Section 14.5.1, "pointer") or with the --default-pointer ODB compiler option, is used. If neither of these two mechanisms is used to specify the pointer, then the raw pointer is used by default.

@@ -10706,7 +11465,7 @@ class person

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

-

12.1.3 abstract

+

14.1.3 abstract

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

-

12.1.4 readonly

+

14.1.4 readonly

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

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

-

12.1.5 optimistic

+

14.1.5 optimistic

The optimistic specifier specifies that the persistent class 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.15, "version"). + (Section 14.4.15, "version"). For example:

@@ -10794,9 +11553,9 @@ class person
      same class.

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

+ Chapter 12, "Optimistic Concurrency".

-

12.1.6 no_id

+

14.1.6 no_id

The no_id specifier specifies that the persistent class has no object id. For example:

@@ -10828,13 +11587,13 @@ class person

Furthermore, persistent classes without object ids cannot have container data members nor can they be used in object relationships. Such objects are not entered into the session object cache - (Section 10.1, "Object Cache") either.

+ (Section 11.1, "Object Cache") either.

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

-

12.1.7 callback

+

14.1.7 callback

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

-

12.1.8 schema

+

14.1.8 schema

The schema specifier specifies a database schema that should be used for the persistent class.

@@ -11147,8 +11906,8 @@ class employee

The standard syntax for qualified names used in the schema and table specifiers as well - as the view column specifier (Section - 12.4.10, "column (view)") has the + as the view column specifier (Section + 14.4.10, "column (view)") has the "name.name..." form where, as discussed above, the leading name component can be empty to denote a fully qualified name. This form, however, @@ -11176,17 +11935,17 @@ class employee }; -

Table prefixes (Section 12.5.2, "table") +

Table prefixes (Section 14.5.2, "table") can be used as an alternative to database schemas if the target database system does not support schemas.

-

12.1.9 polymorphic

+

14.1.9 polymorphic

The polymorphic specifier specifies that the persistent class is polymorphic. For more information on polymorphism support, refer to Chapter 8, "Inheritance".

-

12.1.10 session

+

14.1.10 session

The session specifier specifies whether to enable session support for the persistent class. For example:

@@ -11214,11 +11973,11 @@ class employer

Session support is disabled by default unless the --generate-session ODB compiler option is specified or session support is enabled at the namespace level - (Section 12.5.4, "session"). - For more information on sessions, refer to Chapter - 10, "Session".

+ (Section 14.5.4, "session"). + For more information on sessions, refer to Chapter + 11, "Session".

-

12.1.11 definition

+

14.1.11 definition

The definition specifier specifies an alternative definition location for the persistent class. By @@ -11230,18 +11989,27 @@ class employer containing this pragma.

For more information on this functionality, refer to - Section 12.3.7, "definition".

+ Section 14.3.7, "definition".

-

12.1.12 transient

+

14.1.12 transient

The transient specifier instructs the ODB compiler to treat all non-virtual data members in the persistent class as transient - (Section 12.4.1, "transient"). + (Section 14.4.1, "transient"). This specifier is primarily useful when declaring virtual data - members, as discussed in Section 12.4.13, + members, as discussed in Section 14.4.13, "virtual".

-

12.2 View Type Pragmas

+

14.1.13 sectionable

+ +

The sectionable specifier instructs the ODB compiler + to generate support for the addition of new object sections in + derived classes in a hierarchy with the optimistic concurrency + model. For more information on this functionality, refer to + Section 9.2, "Sections and Optimistic + Concurrency".

+ +

14.2 View Type Pragmas

A pragma with the view qualifier declares a C++ class as a view type. The qualifier can be optionally followed, @@ -11259,84 +12027,84 @@ class employer

object object associated with a view12.2.114.2.1
table table associated with a view12.2.214.2.2
query view query condition12.2.314.2.3
pointer pointer type for a view12.2.414.2.4
callback database operations callback12.2.514.2.5
definition definition location for a view12.2.614.2.6
transient all non-virtual data members in a view are transient12.2.714.2.7
-

For more information on view types refer to Chapter 9, +

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

-

12.2.1 object

+

14.2.1 object

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

-

12.2.2 table

+

14.2.2 table

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

-

12.2.3 query

+

14.2.3 query

The query specifier specifies a query condition for an object or table view or a native SQL query for a native view. An empty query specifier indicates that a native SQL query is provided at runtime. For more information - on query conditions refer to Section 9.4, "View + on query conditions refer to Section 10.4, "View Query Conditions". For more information on native SQL queries, - refer to Section 9.5, "Native Views".

+ refer to Section 10.5, "Native Views".

-

12.2.4 pointer

+

14.2.4 pointer

The pointer specifier specifies the view pointer type for the 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 12.1.2, "pointer").

+ (Section 14.1.2, "pointer").

-

12.2.5 callback

+

14.2.5 callback

The callback specifier specifies the view class member function that should be called before and after an @@ -11344,12 +12112,12 @@ class employer result iteration. The semantics of the callback specifier for a view are similar to those of the callback specifier for an object - (Section 12.1.7, "callback") + (Section 14.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.

-

12.2.6 definition

+

14.2.6 definition

The definition specifier specifies an alternative definition location for the view class. By @@ -11361,18 +12129,18 @@ class employer containing this pragma.

For more information on this functionality, refer to - Section 12.3.7, "definition".

+ Section 14.3.7, "definition".

-

12.2.7 transient

+

14.2.7 transient

The transient specifier instructs the ODB compiler to treat all non-virtual data members in the view class as transient - (Section 12.4.1, "transient"). + (Section 14.4.1, "transient"). This specifier is primarily useful when declaring virtual data - members, as discussed in Section 12.4.13, + members, as discussed in Section 14.4.13, "virtual".

-

12.3 Value Type Pragmas

+

14.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 @@ -11389,133 +12157,133 @@ class employer

type database type for a value type12.3.114.3.1
id_type database type for a value type when used as an object id12.3.214.3.2
null/not_null type can/cannot be NULL12.3.314.3.3
default default value for a value type12.3.414.3.4
options database options for a value type12.3.514.3.5
readonly composite value type is read-only12.3.614.3.6
definition definition location for a composite value type12.3.714.3.7
transient all non-virtual data members in a composite value are transient12.3.814.3.8
unordered ordered container should be stored unordered12.3.914.3.9
index_type database type for a container's index type12.3.1014.3.10
key_type database type for a container's key type12.3.1114.3.11
value_type database type for a container's value type12.3.1214.3.12
value_null/value_not_null container's value can/cannot be NULL12.3.1314.3.13
id_options database options for a container's id column12.3.1414.3.14
index_options database options for a container's index column12.3.1514.3.15
key_options database options for a container's key column12.3.1614.3.16
value_options database options for a container's value column12.3.1714.3.17
id_column column name for a container's object id12.3.1814.3.18
index_column column name for a container's index12.3.1914.3.19
key_column column name for a container's key12.3.2014.3.20
value_column column name for a container's value12.3.2114.3.21

Many of the value type specifiers have corresponding member type - specifiers with the same names (Section 12.4, + specifiers with the same names (Section 14.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 @@ -11525,7 +12293,7 @@ class employer take precedence over and override parameters specified with value specifiers.

-

12.3.1 type

+

14.3.1 type

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

@@ -11547,8 +12315,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 - 12.3.3, "null/not_null") specifiers + null and not_null (Section + 14.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 @@ -11575,13 +12343,13 @@ class person mapping example in the odb-examples package shows how to do this for all the supported database systems.

-

12.3.2 id_type

+

14.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 12.4.1, + object identifiers (Section 14.4.1, "id"). In combination with the type - specifier (Section 12.3.1, "type") + specifier (Section 14.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:

@@ -11616,7 +12384,7 @@ class person }; -

12.3.3 null/not_null

+

14.3.3 null/not_null

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

The NULL semantics can also be specified on the - per-member basis (Section 12.4.6, + per-member basis (Section 14.4.6, "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 @@ -11679,7 +12447,7 @@ typedef shared_ptr<person> person_ptr; discussion of the NULL semantics for object pointers, refer to Chapter 6, "Relationships".

-

12.3.4 default

+

14.3.4 default

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

@@ -11698,10 +12466,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 12.4.7, + data member (Section 14.4.7, "default").

-

12.3.5 options

+

14.3.5 options

The options specifier specifies additional column definition options that should be used for data members of this @@ -11721,10 +12489,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 12.4.8, + data member (Section 14.4.8, "options").

-

12.3.6 readonly

+

14.3.6 readonly

The readonly specifier specifies that the composite value type is read-only. Changes to data members of a read-only @@ -11750,11 +12518,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 12.4.12, "readonly") - as well as whole objects (Section 12.1.4, + (Section 14.4.12, "readonly") + as well as whole objects (Section 14.1.4, "readonly") as read-only.

-

12.3.7 definition

+

14.3.7 definition

The definition specifier specifies an alternative definition location for the composite value type. By @@ -11819,16 +12587,16 @@ class object }; -

12.3.8 transient

+

14.3.8 transient

The transient specifier instructs the ODB compiler to treat all non-virtual data members in the composite value type - as transient (Section 12.4.1, + as transient (Section 14.4.1, "transient"). This specifier is primarily useful when declaring virtual data members, as discussed in - Section 12.4.13, "virtual".

+ Section 14.4.13, "virtual".

-

12.3.9 unordered

+

14.3.9 unordered

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

-

12.3.10 index_type

+

14.3.10 index_type

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

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

12.3.11 key_type

+

14.3.11 key_type

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

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

12.3.12 value_type

+

14.3.12 value_type

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

@@ -11888,18 +12656,18 @@ typedef std::vector<std::string> names;
   

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

-

12.3.13 value_null/value_not_null

+

14.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 NULL, respectively. The semantics of value_null and value_not_null are similar to those of the null and not_null specifiers - (Section 12.3.3, "null/not_null"). + (Section 14.3.3, "null/not_null"). For example:

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

-

12.3.14 id_options

+

14.3.14 id_options

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

-

12.3.15 index_options

+

14.3.15 index_options

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

-

12.3.16 key_options

+

14.3.16 key_options

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

-

12.3.17 value_options

+

14.3.17 value_options

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

-

12.3.18 id_column

+

14.3.18 id_column

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

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

-

12.3.19 index_column

+

14.3.19 index_column

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

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

-

12.3.20 key_column

+

14.3.20 key_column

The key_column specifier specifies the column name that should be used to store the key in the map @@ -12030,7 +12798,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.21 value_column

+

14.3.21 value_column

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

12.4 Data Member Pragmas

+

14.4 Data Member Pragmas

A pragma with the member qualifier or a positioned pragma without a qualifier describes a data member. It can @@ -12065,193 +12833,205 @@ typedef std::map<unsigned short, float> age_weight_map; id member is an object id - 12.4.1 + 14.4.1 auto id is assigned by the database - 12.4.2 + 14.4.2 type database type for a member - 12.4.3 + 14.4.3 id_type database type for a member when used as an object id - 12.4.4 + 14.4.4 get/set/access member accessor/modifier expressions - 12.4.5 + 14.4.5 null/not_null member can/cannot be NULL - 12.4.6 + 14.4.6 default default value for a member - 12.4.7 + 14.4.7 options database options for a member - 12.4.8 + 14.4.8 column column name for a member of an object or composite value - 12.4.9 + 14.4.9 column column name for a member of a view - 12.4.10 + 14.4.10 transient member is not stored in the database - 12.4.11 + 14.4.11 readonly member is read-only - 12.4.12 + 14.4.12 virtual declare a virtual data member - 12.4.13 + 14.4.13 inverse member is an inverse side of a bidirectional relationship - 12.4.14 + 14.4.14 version member stores object version - 12.4.15 + 14.4.15 index define database index for a member - 12.4.16 + 14.4.16 unique define unique database index for a member - 12.4.17 + 14.4.17 unordered ordered container should be stored unordered - 12.4.18 + 14.4.18 table table name for a container - 12.4.19 + 14.4.19 + + + + load/update + loading/updating behavior for a section + 14.4.20 + + + + section + member belongs to a section + 14.4.21 index_type database type for a container's index type - 12.4.20 + 14.4.22 key_type database type for a container's key type - 12.4.21 + 14.4.23 value_type database type for a container's value type - 12.4.22 + 14.4.24 value_null/value_not_null container's value can/cannot be NULL - 12.4.23 + 14.4.25 id_options database options for a container's id column - 12.4.24 + 14.4.26 index_options database options for a container's index column - 12.4.25 + 14.4.27 key_options database options for a container's key column - 12.4.26 + 14.4.28 value_options database options for a container's value column - 12.4.27 + 14.4.29 id_column column name for a container's object id - 12.4.28 + 14.4.30 index_column column name for a container's index - 12.4.29 + 14.4.31 key_column column name for a container's key - 12.4.30 + 14.4.32 value_column column name for a container's value - 12.4.31 + 14.4.33

Many of the member specifiers have corresponding value type - specifiers with the same names (Section 12.3, + specifiers with the same names (Section 14.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 @@ -12261,7 +13041,7 @@ typedef std::map<unsigned short, float> age_weight_map; take precedence over and override parameters specified with value specifiers.

-

12.4.1 id

+

14.4.1 id

The id specifier specifies that the data member contains the object id. In a relational database, an identifier member is @@ -12281,12 +13061,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 no_id - specifier (Section 12.1.6, "no_id").

+ specifier (Section 14.1.6, "no_id").

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

-

12.4.2 auto

+

14.4.2 auto

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

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

-

12.4.3 type

+

14.4.3 type

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

@@ -12332,14 +13112,14 @@ class person };
-

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

The null and not_null (Section + 14.4.6, "null/not_null") specifiers can be used to control the NULL semantics of a data member. It is also possible to specify the database type on the per-type instead of the per-member basis using the value type - specifier (Section 12.3.1, "type").

+ specifier (Section 14.3.1, "type").

-

12.4.4 id_type

+

14.4.4 id_type

The id_type specifier specifies the native database type that should be used for the data member when it is part of an @@ -12372,7 +13152,7 @@ class person }; -

12.4.5 get/set/access

+

14.4.5 get/set/access

The get and set specifiers specify the data member accessor and modifier expressions, respectively. If @@ -12561,7 +13341,7 @@ class person types. They can be used for data members in persistent classes, composite value types, and views. There is also a mechanism related to accessors and modifiers called virtual data members - and which is discussed in Section 12.4.13, + and which is discussed in Section 14.4.13, "virtual".

There are, however, certain limitations when it comes to using @@ -12604,7 +13384,7 @@ private: limitations, refer to the "Limitations" sections in Part II, "Database Systems".

-

12.4.6 null/not_null

+

14.4.6 null/not_null

The null and not_null specifiers specify that the data member can or cannot be NULL, respectively. @@ -12616,8 +13396,8 @@ private: 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 - 12.4.1, "id") is automatically treated as not + types. A data member containing the object id (Section + 14.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:

@@ -12645,7 +13425,7 @@ class account

The NULL semantics can also be specified on the - per-type basis (Section 12.3.3, + per-type basis (Section 14.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 @@ -12659,7 +13439,7 @@ class account discussion of the NULL semantics for object pointers, refer to Chapter 6, "Relationships".

-

12.4.7 default

+

14.4.7 default

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

@@ -12680,8 +13460,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 - 12.4.8, "options") instead. For example:

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

 enum gender {male, female, undisclosed};
@@ -12734,7 +13514,7 @@ class person
   

A default value can also be specified on the per-type basis - (Section 12.3.4, "default"). + (Section 14.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:

@@ -12752,8 +13532,8 @@ class person }; -

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

A data member containing the object id (Section + 14.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 @@ -12767,7 +13547,7 @@ class person

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

-

12.4.8 options

+

14.4.8 options

The options specifier specifies additional column definition options that should be used for the data member. For @@ -12785,7 +13565,7 @@ class person

Options can also be specified on the per-type basis - (Section 12.3.5, "options"). + (Section 14.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 @@ -12814,10 +13594,10 @@ class person

ODB provides dedicated specifiers for specifying column types - (Section 12.4.3, "type"), - NULL constraints (Section 12.4.6, + (Section 14.4.3, "type"), + NULL constraints (Section 14.4.6, "null/not_null"), and default - values (Section 12.4.7, "default"). + values (Section 14.4.7, "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.

@@ -12825,7 +13605,7 @@ class person

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

-

12.4.9 column (object, composite value)

+

14.4.9 column (object, composite value)

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

-

12.4.10 column (view)

+

14.4.10 column (view)

The column specifier can be used to specify the associated object data member, the potentially qualified column name, or the column expression for the data member of a view class. For more information, - refer to Section 9.1, "Object Views" and - Section 9.2, "Table Views".

+ refer to Section 10.1, "Object Views" and + Section 10.2, "Table Views".

-

12.4.11 transient

+

14.4.11 transient

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

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

-

12.4.12 readonly

+

14.4.12 readonly

The readonly specifier specifies that the data member of an object or composite value type is read-only. Changes to a read-only @@ -12889,8 +13669,8 @@ class person (Section 3.10, "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 12.4.1, "id") - and inverse (Section 12.4.14, + (Section 14.4.1, "id") + and inverse (Section 14.4.14, "inverse") data members are automatically treated as read-only and must not be explicitly declared as such. For example:

@@ -12970,11 +13750,11 @@ class person as read-only.

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

-

12.4.13 virtual

+

14.4.13 virtual

The virtual specifier is used to declare a virtual data member in an object, view, or composite value type. A virtual @@ -12992,7 +13772,7 @@ class person specifier. Finally, the virtual data member declaration must also specify the accessor and modifier expressions, unless suitable accessor and modifier functions can automatically be - found by the ODB compiler (Section 12.4.5, + found by the ODB compiler (Section 14.4.5, "get/set/access"). For example:

@@ -13144,11 +13924,11 @@ private: 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 + (Section 14.1.12, "transient (object)", - Section 12.3.8, "transient + Section 14.3.8, "transient (composite value)", - Section 12.2.7, "transient + Section 14.2.7, "transient (view)") instead of doing it for each individual member. For example:

@@ -13207,7 +13987,7 @@ private: container, or object pointer types. They can be used in persistent classes, composite value types, and views.

-

12.4.14 inverse

+

14.4.14 inverse

The inverse specifier specifies that the data member of an object pointer or a container of object pointers type is an @@ -13245,18 +14025,18 @@ 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.18, "unordered").

+ (Section 14.4.18, "unordered").

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

-

12.4.15 version

+

14.4.15 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 the optimistic concurrency model using the optimistic pragma - (Section 12.1.5, "optimistic"). For + (Section 14.1.5, "optimistic"). For example:

@@ -13278,9 +14058,9 @@ class person
      choice.

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

+ Chapter 12, "Optimistic Concurrency".

-

12.4.16 index

+

14.4.16 index

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

@@ -13297,9 +14077,9 @@ class person

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

+ Section 14.6, "Index Definition Pragmas".

-

12.4.17 unique

+

14.4.17 unique

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

@@ -13316,9 +14096,9 @@ class person

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

+ Section 14.6, "Index Definition Pragmas".

-

12.4.18 unordered

+

14.4.18 unordered

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

-

12.4.19 table

+

14.4.19 table

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

@@ -13386,16 +14166,35 @@ class person

For more information on database schemas and the format of the - qualified names, refer to Section 12.1.8, + qualified names, refer to Section 14.1.8, "schema".

-

12.4.20 index_type

+

14.4.20 load/update

+ +

The load and update specifiers specify the + loading and updating behavior for an object section, respectively. + Valid values for the load specifier are + eager (default) and lazy. Valid values for + the update specifier are always (default), + change, and manual. For more information + on object sections, refer to Chapter 9, "Sections".

+ +

14.4.21 section

+ +

The section specifier indicates that a data member + of a persistent class belongs to an object section. The single + required argument to this specifier is the name of the section + data member. This specifier can only be used on direct data + members of a persistent class. For more information on object + sections, refer to Chapter 9, "Sections".

+ +

14.4.22 index_type

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

@@ -13409,13 +14208,13 @@ class person
 };
   
-

12.4.21 key_type

+

14.4.23 key_type

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

@@ -13429,13 +14228,13 @@ class person
 };
   
-

12.4.22 value_type

+

14.4.24 value_type

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

@@ -13450,18 +14249,18 @@ class person
   

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

-

12.4.23 value_null/value_not_null

+

14.4.25 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 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 12.4.6, "null/not_null"). + (Section 14.4.6, "null/not_null"). For example:

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

-

12.4.24 id_options

+

14.4.26 id_options

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

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

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

-

12.4.25 index_options

+

14.4.27 index_options

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

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

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

-

12.4.26 key_options

+

14.4.28 key_options

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

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

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

-

12.4.27 value_options

+

14.4.29 value_options

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

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

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

-

12.4.28 id_column

+

14.4.30 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 the data member. The semantics of id_column are similar to those of the column specifier - (Section 12.4.9, "column"). + (Section 14.4.9, "column"). For example:

@@ -13598,14 +14397,14 @@ class person
   

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

-

12.4.29 index_column

+

14.4.31 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 the data member. The semantics of index_column are similar to those of the column specifier - (Section 12.4.9, "column"). + (Section 14.4.9, "column"). For example:

@@ -13622,14 +14421,14 @@ class person
   

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

-

12.4.30 key_column

+

14.4.32 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 the data member. The semantics of key_column are similar to those of the column specifier - (Section 12.4.9, "column"). + (Section 14.4.9, "column"). For example:

@@ -13646,14 +14445,14 @@ class person
   

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

-

12.4.31 value_column

+

14.4.33 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 the data member. The semantics of value_column are similar to those of the column specifier - (Section 12.4.9, "column"). + (Section 14.4.9, "column"). For example:

@@ -13670,7 +14469,7 @@ class person
   

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

-

12.5 Namespace Pragmas

+

14.5 Namespace Pragmas

A pragma with the namespace qualifier describes a C++ namespace. Similar to other qualifiers, namespace @@ -13707,30 +14506,30 @@ namespace test pointer pointer type for persistent classes and views inside a namespace - 12.5.1 + 14.5.1 table table name prefix for persistent classes inside a namespace - 12.5.2 + 14.5.2 schema database schema for persistent classes inside a namespace - 12.5.3 + 14.5.3 session enable/disable session support for persistent classes inside a namespace - 12.5.4 + 14.5.4 -

12.5.1 pointer

+

14.5.1 pointer

The pointer specifier specifies the default pointer type for persistent classes and views inside the namespace. For @@ -13786,7 +14585,7 @@ namespace accounting

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

-

12.5.2 table

+

14.5.2 table

The table specifier specifies a table prefix that should be added to table names of persistent classes inside @@ -13845,17 +14644,17 @@ class employer test_audit_employers.

Table prefixes can be used as an alternative to database schemas - (Section 12.1.8, "schema") if + (Section 14.1.8, "schema") if the target database system does not support schemas.

-

12.5.3 schema

+

14.5.3 schema

The schema specifier specifies a database schema that should be used for persistent classes inside the namespace. For more information on specifying a database schema refer to - Section 12.1.8, "schema".

+ Section 14.1.8, "schema".

-

12.5.4 session

+

14.5.4 session

The session specifier specifies whether to enable session support for persistent classes inside the namespace. For @@ -13882,11 +14681,11 @@ namespace hr

Session support is disabled by default unless the --generate-session ODB compiler option is specified. Session support specified at the namespace level can be overridden - on the per object basis (Section 12.1.10, + on the per object basis (Section 14.1.10, "session"). For more information on sessions, - refer to Chapter 10, "Session".

+ refer to Chapter 11, "Session".

-

12.6 Index Definition Pragmas

+

14.6 Index Definition Pragmas

While it is possible to manually add indexes to the generated database schema, it is more convenient to do this as part of @@ -13965,9 +14764,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.16, "index") or unique - (Section 12.4.17, "unique") + be defined using the index (Section + 14.4.16, "index") or unique + (Section 14.4.17, "unique") member specifier. For example:

@@ -14086,7 +14885,7 @@ class object
 };
 
-

12.7 Database Type Mapping Pragmas

+

14.7 Database Type Mapping Pragmas

A pragma with the map qualifier describes a mapping between two database types. For each database system @@ -14287,7 +15086,7 @@ class object for each database, shows how to provide custom mapping for some of the extended types.

-

12.8 C++ Compiler Warnings

+

14.8 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 @@ -14340,7 +15139,7 @@ class person

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

-

12.8.1 GNU C++

+

14.8.1 GNU C++

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

-

12.8.2 Visual C++

+

14.8.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 @@ -14386,7 +15185,7 @@ class person #pragma warning (pop)

-

12.8.3 Sun C++

+

14.8.3 Sun C++

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

-

12.8.4 IBM XL C++

+

14.8.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 @@ -14408,7 +15207,7 @@ CC +w -erroff=unknownpragma ... xlC -qsuppress=1540-1401 ...

-

12.8.5 HP aC++

+

14.8.5 HP aC++

HP aC++ (aCC) issues an unknown pragma warning (2161) by default. To disable this warning we can add the +W2161 @@ -14418,7 +15217,7 @@ xlC -qsuppress=1540-1401 ... aCC +W2161 ... -

12.8.6 Clang

+

14.8.6 Clang

Clang does not issue warnings about unknown pragmas unless requested with the -Wall command line option. @@ -14457,12 +15256,12 @@ class person


-

13 Advanced Techniques and Mechanisms

+

15 Advanced Techniques and Mechanisms

This chapter covers more advanced techniques and mechanisms provided by ODB that may be useful in certain situations.

-

13.1 Transaction Callbacks

+

15.1 Transaction Callbacks

The ODB transaction class (odb::transaction) allows an application to register a callback that will be called after @@ -14559,7 +15358,7 @@ namespace odb

The following example shows how we can use transaction callbacks together with database operation callbacks - (Section 12.1.7, "callback") + (Section 14.1.7, "callback") to manage the object's "dirty" flag.

@@ -14639,12 +15438,12 @@ class object
      II consists of the following chapters.

- - - - - - + + + + + +
14Multi-Database Support
15MySQL Database
16SQLite Database
17PostgreSQL Database
18Oracle Database
19Microsoft SQL Server Database
16Multi-Database Support
17MySQL Database
18SQLite Database
19PostgreSQL Database
20Oracle Database
21Microsoft SQL Server Database
@@ -14652,7 +15451,7 @@ class object
-

14 Multi-Database Support

+

16 Multi-Database Support

Some applications may need to access multiple database systems, either simultaneously or one at a time. For example, an application may @@ -14713,7 +15512,7 @@ class object separate libraries and loaded dynamically by the application. The disadvantages of dynamic support are slight overhead and certain limitations in functionality compared to static support (see - Section 14.2, "Dynamic Multi-Database Support" + Section 16.2, "Dynamic Multi-Database Support" for details). As a result, dynamic multi-database support is most suitable to situations where we need the same code to work with a range of database systems. For example, if your @@ -14843,7 +15642,7 @@ odb --odb-file-suffix common:-odb-common ... support in more detail.

-

14.1 Static Multi-Database Support

+

16.1 Static Multi-Database Support

With static multi-database support, instead of including person-odb.hxx, application source code has @@ -15015,7 +15814,7 @@ odb -m static -d common -d pgsql -d sqlite --default-database pgsql ... support is enabled, then the common (dynamic) interface is always made the default database.

-

14.2 Dynamic Multi-Database Support

+

16.2 Dynamic Multi-Database Support

With dynamic multi-database support, application source code only needs to include the person-odb.hxx header file, just @@ -15186,7 +15985,7 @@ namespace odb expression). Every odb::<db>::query class provides such a translation constructor.

-

14.2.2 Dynamic Loading of Database Support Code

+

16.2.2 Dynamic Loading of Database Support Code

With dynamic multi-database support, the generated database support code automatically registers itself with the function tables that @@ -15364,7 +16163,7 @@ person.hxx


-

15 MySQL Database

+

17 MySQL Database

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

-

15.1 MySQL Type Mapping

+

17.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 12, "ODB Pragma + Pragma Language (Chapter 14, "ODB Pragma Language").

@@ -15488,7 +16287,7 @@ person.hxx

It is possible to map the char C++ type to an integer database type (for example, TINYINT) using the - db type pragma (Section 12.4.3, + db type pragma (Section 14.4.3, "type").

Note that the std::string type is mapped @@ -15527,10 +16326,10 @@ class object

It is also possible to add support for additional MySQL types, such as geospatial types. For more information, refer to - Section 12.7, "Database Type Mapping + Section 14.7, "Database Type Mapping Pragmas".

-

15.1.1 String Type Mapping

+

17.1.1 String Type Mapping

The MySQL ODB runtime library provides support for mapping the std::string, char[N], and @@ -15540,8 +16339,8 @@ class object by default (in particular, by default, std::array will be treated as a container). To enable the alternative mappings for these types we need to specify the database type explicitly using - the db type pragma (Section - 12.4.3, "type"), for example:

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

 #pragma db object
@@ -15576,7 +16375,7 @@ class object
      database, ODB will append the zero terminator if there is enough
      space.

-

15.1.2 Binary Type Mapping

+

17.1.2 Binary Type Mapping

The MySQL ODB runtime library provides support for mapping the std::vector<char>, @@ -15590,7 +16389,7 @@ class object std::array will be treated as containers). To enable the alternative mappings for these types we need to specify the database type explicitly using the db type pragma - (Section 12.4.3, "type"), for + (Section 14.4.3, "type"), for example:

@@ -15637,7 +16436,7 @@ db.query<object> ("uuid = " + query::_val<odb::mysql::id_blob> (u));
 db.query<object> (query::uuid == query::_ref (u));
   
-

15.2 MySQL Database Class

+

17.2 MySQL Database Class

The MySQL database class has the following interface:

@@ -15797,7 +16596,7 @@ namespace odb

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

The static print_usage() function prints the list of options @@ -15816,10 +16615,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 - 15.3, "MySQL Connection and Connection Factory".

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

-

15.3 MySQL Connection and Connection Factory

+

17.3 MySQL Connection and Connection Factory

The mysql::connection class has the following interface:

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

15.4 MySQL Exceptions

+

17.4 MySQL Exceptions

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

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

-

15.5 MySQL Limitations

+

17.5 MySQL Limitations

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

-

15.5.1 Foreign Key Constraints

+

17.5.1 Foreign Key Constraints

ODB relies on standard SQL behavior which requires that foreign key constraints checking is deferred until the transaction is @@ -16086,9 +16885,9 @@ namespace odb which you persist, update, and erase objects within a transaction becomes important.

-

15.6 MySQL Index Definitions

+

17.6 MySQL Index Definitions

-

When the index pragma (Section 12.6, +

When the index pragma (Section 14.6, "Index Definition Pragmas") is used to define a MySQL index, the type clause specifies the index type (for example, UNIQUE, FULLTEXT, SPATIAL), @@ -16115,7 +16914,7 @@ class object


-

16 SQLite Database

+

18 SQLite Database

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

-

16.1 SQLite Type Mapping

+

18.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 12, "ODB Pragma + Pragma Language (Chapter 14, "ODB Pragma Language").

@@ -16251,15 +17050,15 @@ class object

It is possible to map the char C++ type to the INTEGER SQLite type using the db type - pragma (Section 12.4.3, "type").

+ pragma (Section 14.4.3, "type").

SQLite represents the NaN FLOAT value as a NULL value. As a result, columns of the float and double types are by default declared as NULL. However, you can override this by explicitly declaring them as NOT NULL with the - db not_null pragma (Section - 12.4.6, "null/not_null").

+ db not_null pragma (Section + 14.4.6, "null/not_null").

Additionally, by default, C++ enumerations are automatically mapped to the SQLite INTEGER type with the default NULL @@ -16273,10 +17072,10 @@ class object

It is also possible to add support for additional SQLite types, such as NUMERIC. For more information, refer to - Section 12.7, "Database Type Mapping + Section 14.7, "Database Type Mapping Pragmas".

-

16.1.1 String Type Mapping

+

18.1.1 String Type Mapping

The SQLite ODB runtime library provides support for mapping the std::array<char, N> and, on Windows, @@ -16285,8 +17084,8 @@ class object default (in particular, by default, std::array will be treated as a container). To enable the alternative mapping for this type we need to specify the database type explicitly using - the db type pragma (Section - 12.4.3, "type"), for example:

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

 #pragma db object
@@ -16320,7 +17119,7 @@ class object
      from the database, ODB will append the zero terminator if there is
      enough space.

-

16.1.2 Binary Type Mapping

+

18.1.2 Binary Type Mapping

The SQLite ODB runtime library provides support for mapping the std::vector<char>, @@ -16333,7 +17132,7 @@ class object std::vector and std::array will be treated as containers). To enable the alternative mappings for these types we need to specify the database type explicitly using the - db type pragma (Section 12.4.3, + db type pragma (Section 14.4.3, "type"), for example:

@@ -16380,7 +17179,7 @@ db.query<object> ("uuid = " + query::_val<odb::sqlite::id_blob> (u));
 db.query<object> (query::uuid == query::_ref (u));
   
-

16.2 SQLite Database Class

+

18.2 SQLite Database Class

The SQLite database class has the following interface:

@@ -16453,7 +17252,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 16.5.3, + should be enabled. See Section 18.5.3, "Foreign Key Constraints" for more information on foreign keys. The vfs argument specifies the SQLite virtual file system module that should be used to access the @@ -16509,7 +17308,7 @@ auto_ptr<odb::database> db (

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

The static print_usage() function prints the list of options @@ -16538,10 +17337,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 - 16.3, "SQLite Connection and Connection Factory".

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

-

16.3 SQLite Connection and Connection Factory

+

18.3 SQLite Connection and Connection Factory

The sqlite::connection class has the following interface:

@@ -16586,7 +17385,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 16.2, + sqlite::database class (Section 18.2, "SQLite Database Class"). The handle() accessor returns the SQLite handle corresponding to the connection.

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

16.4 SQLite Exceptions

+

18.4 SQLite Exceptions

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

@@ -16834,7 +17633,7 @@ namespace odb

The odb::sqlite::forced_rollback exception is thrown if SQLite is forcing the current transaction to roll back. For more - information on this behavior refer to Section 16.5.6, + information on this behavior refer to Section 18.5.6, "Forced Rollback".

The odb::sqlite::database_exception is thrown if @@ -16851,12 +17650,12 @@ namespace odb of an error.

-

16.5 SQLite Limitations

+

18.5 SQLite Limitations

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

-

16.5.1 Query Result Caching

+

18.5.1 Query Result Caching

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

-

16.5.2 Automatic Assignment of Object Ids

+

18.5.2 Automatic Assignment of Object Ids

Due to SQLite API limitations, every automatically assigned object id - (Section 12.4.2, "auto") should have + (Section 14.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 12.4.3, "type"). For + (Section 14.4.3, "type"). For example:

@@ -16897,7 +17696,7 @@ class person
 };
   
-

16.5.3 Foreign Key Constraints

+

18.5.3 Foreign Key Constraints

By default the SQLite ODB runtime enables foreign key constraints checking (PRAGMA foreign_keys=ON). You can disable foreign @@ -16967,7 +17766,7 @@ CREATE TABLE Employee ( which you persist, update, and erase objects within a transaction becomes important.

-

16.5.4 Constraint Violations

+

18.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 @@ -16976,7 +17775,7 @@ CREATE TABLE Employee ( object_already_persistent exception (Section 3.14, "ODB Exceptions").

-

16.5.5 Sharing of Queries

+

18.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 @@ -16985,7 +17784,7 @@ CREATE TABLE Employee ( functionality. Future versions of the library will remove this limitation.

-

16.5.6 Forced Rollback

+

18.5.6 Forced Rollback

In SQLite 3.7.11 or later, if one of the connections participating in the shared cache rolls back a transaction, then ongoing transactions @@ -16996,14 +17795,14 @@ CREATE TABLE Employee (

If a transaction is being forced to roll back by SQLite, then ODB throws odb::sqlite::forced_rollback - (Section 16.4, "SQLite Exceptions") which is + (Section 18.4, "SQLite Exceptions") which is a recoverable exception (3.7 Error Handling and Recovery). As a result, the recommended way to handle this exception is to re-execute the affected transaction.

-

16.6 SQLite Index Definitions

+

18.6 SQLite Index Definitions

-

When the index pragma (Section 12.6, +

When the index pragma (Section 14.6, "Index Definition Pragmas") is used to define an SQLite index, the type clause specifies the index type (for example, UNIQUE) while the method and @@ -17030,7 +17829,7 @@ class object


-

17 PostgreSQL Database

+

19 PostgreSQL Database

To generate support code for the PostgreSQL database you will need to pass the "--database pgsql" @@ -17044,12 +17843,12 @@ class object of the messaging protocol version 3.0. For this reason, ODB supports only PostgreSQL version 7.4 and later.

-

17.1 PostgreSQL Type Mapping

+

19.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 12, "ODB Pragma + Pragma Language (Chapter 14, "ODB Pragma Language").

@@ -17159,7 +17958,7 @@ class object

It is possible to map the char C++ type to an integer database type (for example, SMALLINT) using the - db type pragma (Section 12.4.3, + db type pragma (Section 14.4.3, "type").

Additionally, by default, C++ enumerations are automatically @@ -17179,10 +17978,10 @@ class object such as NUMERIC, geometry types, XML, JSON, enumeration types, composite types, arrays, geospatial types, and the key-value store (HSTORE). - For more information, refer to Section 12.7, + For more information, refer to Section 14.7, "Database Type Mapping Pragmas".

-

17.1.1 String Type Mapping

+

19.1.1 String Type Mapping

The PostgreSQL ODB runtime library provides support for mapping the std::string, char[N], and @@ -17192,7 +17991,7 @@ class object particular, by default, std::array will be treated as a container). To enable the alternative mappings for these types we need to specify the database type explicitly using the - db type pragma (Section 12.4.3, + db type pragma (Section 14.4.3, "type"), for example:

@@ -17228,7 +18027,7 @@ class object
      database, ODB will append the zero terminator if there is enough
      space.

-

17.1.2 Binary Type and UUID Mapping

+

19.1.2 Binary Type and UUID Mapping

The PostgreSQL ODB runtime library provides support for mapping the std::vector<char>, @@ -17242,7 +18041,7 @@ class object default, std::vector and std::array will be treated as containers). To enable the alternative mappings for these types we need to specify the database type explicitly using the - db type pragma (Section 12.4.3, + db type pragma (Section 14.4.3, "type"), for example:

@@ -17293,7 +18092,7 @@ db.query<object> ("buf = " + query::_val<odb::pgsql::id_bytea> (u));
 db.query<object> (query::uuid == query::_ref (u));
   
-

17.2 PostgreSQL Database Class

+

19.2 PostgreSQL Database Class

The PostgreSQL database class has the following interface:

@@ -17413,7 +18212,7 @@ namespace odb

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

The static print_usage() function prints the list of options @@ -17439,10 +18238,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 - 17.3, "PostgreSQL Connection and Connection Factory".

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

-

17.3 PostgreSQL Connection and Connection Factory

+

19.3 PostgreSQL Connection and Connection Factory

The pgsql::connection class has the following interface:

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

17.4 PostgreSQL Exceptions

+

19.4 PostgreSQL Exceptions

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

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

-

17.5 PostgreSQL Limitations

+

19.5 PostgreSQL Limitations

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

-

17.5.1 Query Result Caching

+

19.5.1 Query Result Caching

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

-

17.5.2 Foreign Key Constraints

+

19.5.2 Foreign Key Constraints

ODB assumes the standard SQL behavior which requires that foreign key constraints checking is deferred until the @@ -17710,7 +18509,7 @@ CREATE TABLE Employee ( which you persist, update, and erase objects within a transaction becomes important.

-

17.5.3 Unique Constraint Violations

+

19.5.3 Unique Constraint Violations

Due to the granularity of the PostgreSQL error codes, it is impossible to distinguish between the duplicate primary key and other unique @@ -17719,7 +18518,7 @@ CREATE TABLE Employee ( errors to the object_already_persistent exception (Section 3.14, "ODB Exceptions").

-

17.5.4 Date-Time Format

+

19.5.4 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 @@ -17734,14 +18533,14 @@ CREATE TABLE Employee ( SHOW integer_datetimes

-

17.5.5 Timezones

+

19.5.5 Timezones

ODB does not currently natively support the PostgreSQL date-time types with timezone information. However, these types can be accessed by mapping them to one of the natively supported types, as discussed - in Section 12.7, "Database Type Mapping Pragmas".

+ in Section 14.7, "Database Type Mapping Pragmas".

-

17.5.6 NUMERIC Type Support

+

19.5.6 NUMERIC Type Support

Support for the PostgreSQL NUMERIC type is limited to providing a binary buffer containing the binary representation @@ -17749,13 +18548,13 @@ SHOW integer_datetimes store NUMERIC values refer to the PostgreSQL documentation. An alternative approach to accessing NUMERIC values is to map this type to one of the natively supported - ones, as discussed in Section 12.7, "Database + ones, as discussed in Section 14.7, "Database Type Mapping Pragmas".

-

17.6 PostgreSQL Index Definitions

+

19.6 PostgreSQL Index Definitions

-

When the index pragma (Section 12.6, +

When the index pragma (Section 14.6, "Index Definition Pragmas") is used to define a PostgreSQL index, the type clause specifies the index type (for example, UNIQUE), the method clause specifies the @@ -17792,7 +18591,7 @@ class object


-

18 Oracle Database

+

20 Oracle Database

To generate support code for the Oracle database you will need to pass the "--database oracle" @@ -17801,12 +18600,12 @@ class object library (libodb-oracle). All Oracle-specific ODB classes are defined in the odb::oracle namespace.

-

18.1 Oracle Type Mapping

+

20.1 Oracle Type Mapping

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

@@ -17916,7 +18715,7 @@ class object

It is possible to map the char C++ type to an integer database type (for example, NUMBER(3)) using the - db type pragma (Section 12.4.3, + db type pragma (Section 14.4.3, "type").

In Oracle empty VARCHAR2 and NVARCHAR2 @@ -17925,8 +18724,8 @@ class object types are by default declared as NULL except for primary key columns. However, you can override this by explicitly declaring such columns as NOT NULL with the - db not_null pragma (Section - 12.4.6, "null/not_null"). This also means that for + db not_null pragma (Section + 14.4.6, "null/not_null"). This also means that for object ids that are mapped to these Oracle types, an empty string is an invalid value.

@@ -17937,10 +18736,10 @@ class object

It is also possible to add support for additional Oracle types, such as XML, geospatial types, user-defined types, and collections (arrays, table types). For more information, refer to - Section 12.7, "Database Type Mapping + Section 14.7, "Database Type Mapping Pragmas".

-

18.1.1 String Type Mapping

+

20.1.1 String Type Mapping

The Oracle ODB runtime library provides support for mapping the std::string, char[N], and @@ -17951,7 +18750,7 @@ class object default, std::array will be treated as a container). To enable the alternative mappings for these types we need to specify the database type explicitly using the db type - pragma (Section 12.4.3, "type"), + pragma (Section 14.4.3, "type"), for example:

@@ -17993,7 +18792,7 @@ class object
      database, ODB will append the zero terminator if there is enough
      space.

-

18.1.2 Binary Type Mapping

+

20.1.2 Binary Type Mapping

The Oracle ODB runtime library provides support for mapping the std::vector<char>, @@ -18006,7 +18805,7 @@ class object default, std::vector and std::array will be treated as containers). To enable the alternative mappings for these types we need to specify the database type explicitly using the - db type pragma (Section 12.4.3, + db type pragma (Section 14.4.3, "type"), for example:

@@ -18053,7 +18852,7 @@ db.query<object> ("uuid = " + query::_val<odb::oracle::id_raw> (u));
 db.query<object> (query::uuid == query::_ref (u));
   
-

18.2 Oracle Database Class

+

20.2 Oracle Database Class

The Oracle database class encapsulates the OCI environment handle as well as the database connection string and user credentials @@ -18178,7 +18977,7 @@ namespace odb

This constructor throws the odb::oracle::cli_exception exception if the Oracle option values are missing or invalid. See section - Section 18.4, "Oracle Exceptions" for more + Section 20.4, "Oracle Exceptions" for more information on this exception.

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

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

+ on oracle::connection, refer to Section + 20.3, "Oracle Connection and Connection Factory".

-

18.3 Oracle Connection and Connection Factory

+

20.3 Oracle Connection and Connection Factory

The oracle::connection class has the following interface:

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

18.4 Oracle Exceptions

+

20.4 Oracle Exceptions

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

@@ -18514,12 +19313,12 @@ namespace odb condition. The what() function returns a human-readable description of an error.

-

18.5 Oracle Limitations

+

20.5 Oracle Limitations

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

-

18.5.1 Identifier Truncation

+

20.5.1 Identifier Truncation

Oracle limits the length of database identifiers (table, column, etc., names) to 30 characters. The ODB compiler automatically truncates @@ -18529,7 +19328,7 @@ namespace odb that a database object with the same name already exists. To resolve this problem we can assign custom, shorter identifiers using the db table and db column - pragmas (Chapter 12, "ODB Pragma Language"). For + pragmas (Chapter 14, "ODB Pragma Language"). For example:

@@ -18564,7 +19363,7 @@ class long_class_name
 };
   
-

18.5.2 Query Result Caching

+

20.5.2 Query Result Caching

Oracle ODB runtime implementation does not perform query result caching (Section 4.4, "Query Result") even when explicitly @@ -18579,7 +19378,7 @@ class long_class_name always thrown. Future versions of the Oracle ODB runtime library may add support for result caching.

-

18.5.3 Foreign Key Constraints

+

20.5.3 Foreign Key Constraints

ODB assumes the standard SQL behavior which requires that foreign key constraints checking is deferred until the @@ -18605,7 +19404,7 @@ CREATE TABLE Employee ( which you persist, update, and erase objects within a transaction becomes important.

-

18.5.4 Unique Constraint Violations

+

20.5.4 Unique Constraint Violations

Due to the granularity of the Oracle error codes, it is impossible to distinguish between the duplicate primary key and other unique @@ -18614,7 +19413,7 @@ CREATE TABLE Employee ( errors to the object_already_persistent exception (Section 3.14, "ODB Exceptions").

-

18.5.5 Large FLOAT and +

20.5.5 Large FLOAT and NUMBER Types

The Oracle FLOAT type with a binary precision greater @@ -18632,31 +19431,31 @@ CREATE TABLE Employee (

An alternative approach to accessing large FLOAT and NUMBER values is to map these type to one of the - natively supported ones, as discussed in Section - 12.7, "Database Type Mapping Pragmas".

+ natively supported ones, as discussed in Section + 14.7, "Database Type Mapping Pragmas".

Note that a NUMBER type that is used to represent a floating point number (declared by specifying NUMBER without any range and scale) can be extracted into the C++ float and double types.

-

18.5.6 Timezones

+

20.5.6 Timezones

ODB does not currently support the Oracle date-time types with timezone information. However, these types can be accessed by mapping them to one of the natively supported types, as discussed in - Section 12.7, "Database Type Mapping Pragmas".

+ Section 14.7, "Database Type Mapping Pragmas".

-

18.5.7 LONG Types

+

20.5.7 LONG Types

ODB does not support the deprecated Oracle LONG and LONG RAW data types. However, these types can be accessed by mapping them to one of the natively supported types, as discussed - in Section 12.7, "Database Type Mapping Pragmas".

+ in Section 14.7, "Database Type Mapping Pragmas".

-

18.5.8 LOB Types and By-Value Accessors/Modifiers

+

20.5.8 LOB Types and By-Value Accessors/Modifiers

-

As discussed in Section 12.4.5, +

As discussed in Section 14.4.5, "get/set/access", by-value accessor and modifier expressions cannot be used with data members of Oracle large object (LOB) data types: BLOB, @@ -18665,9 +19464,9 @@ CREATE TABLE Employee ( data members. As a result, by-reference accessors and modifiers should be used for these data types.

-

18.6 Oracle Index Definitions

+

20.6 Oracle Index Definitions

-

When the index pragma (Section 12.6, +

When the index pragma (Section 14.6, "Index Definition Pragmas") is used to define an Oracle index, the type clause specifies the index type (for example, UNIQUE, BITMAP), the method @@ -18699,7 +19498,7 @@ class object


-

19 Microsoft SQL Server Database

+

21 Microsoft SQL Server Database

To generate support code for the SQL Server database you will need to pass the "--database mssql" @@ -18708,12 +19507,12 @@ class object library (libodb-mssql). All SQL Server-specific ODB classes are defined in the odb::mssql namespace.

-

19.1 SQL Server Type Mapping

+

21.1 SQL Server Type Mapping

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

+ Pragma Language (Chapter 14, "ODB Pragma Language").

@@ -18841,7 +19640,7 @@ class object

It is possible to map the char C++ type to an integer database type (for example, TINYINT) using the - db type pragma (Section 12.4.3, + db type pragma (Section 14.4.3, "type").

Note that the std::string and std::wstring @@ -18853,7 +19652,7 @@ class object is mapped to VARCHAR(512) and std::wstring — to NVARCHAR(512). Note also that you can always change this mapping using the db type pragma - (Section 12.4.3, "type").

+ (Section 14.4.3, "type").

Additionally, by default, C++ enumerations are automatically mapped to INT with the default NULL @@ -18875,10 +19674,10 @@ class object

It is also possible to add support for additional SQL Server types, such as geospatial types, XML, and user-defined types. - For more information, refer to Section 12.7, "Database + For more information, refer to Section 14.7, "Database Type Mapping Pragmas".

-

19.1.1 String Type Mapping

+

21.1.1 String Type Mapping

The SQL Server ODB runtime library provides support for mapping the std::string, char[N], and @@ -18891,7 +19690,7 @@ class object std::array will be treated as a container). To enable the alternative mappings for these types we need to specify the database type explicitly using the db type pragma - (Section 12.4.3, "type"), for + (Section 14.4.3, "type"), for example:

@@ -18928,10 +19727,10 @@ class object
      from the database, ODB will append the zero terminator if there is
      enough space.

-

See also Section 19.1.4, "Long String and Binary +

See also Section 21.1.4, "Long String and Binary Types" for certain limitations of long string types.

-

19.1.2 Binary Type and UNIQUEIDENTIFIER Mapping

+

21.1.2 Binary Type and UNIQUEIDENTIFIER Mapping

The SQL Server ODB runtime library also provides support for mapping the std::vector<char>, @@ -18945,7 +19744,7 @@ class object by default, std::vector and std::array will be treated as containers). To enable the alternative mappings for these types we need to specify the database type explicitly using the - db type pragma (Section 12.4.3, + db type pragma (Section 14.4.3, "type"), for example:

@@ -18997,17 +19796,17 @@ db.query<object> (
 db.query<object> (query::uuid == query::_ref (u));
   
-

See also Section 19.1.4, "Long String and Binary +

See also Section 21.1.4, "Long String and Binary Types" for certain limitations of long binary types.

-

19.1.3 ROWVERSION Mapping

+

21.1.3 ROWVERSION Mapping

ROWVERSION is a special SQL Server data type that is automatically incremented by the database server whenever a row is inserted or updated. As such, it is normally used to implement optimistic concurrency and ODB provides support for using ROWVERSION instead of the more portable approach - for optimistic concurrency (Chapter 11, "Optimistic + for optimistic concurrency (Chapter 12, "Optimistic Concurrency").

ROWVERSION is a 64-bit value which is mapped by ODB @@ -19029,7 +19828,7 @@ class person };

-

19.1.4 Long String and Binary Types

+

21.1.4 Long String and Binary Types

For SQL Server, ODB handles character, national character, and binary data in two different ways depending on its maximum length. @@ -19052,7 +19851,7 @@ class person than once as part of a query result iteration (Section 4.4, "Query Result"). Any such attempt will result in the odb::mssql::long_data_reload exception - (Section 19.4, "SQL Server Exceptions"). For + (Section 21.4, "SQL Server Exceptions"). For example:

@@ -19086,12 +19885,12 @@ for (result::iterator i (r.begin ()); i != r.end (); ++i)
 t.commit ();
   
-

Finally, if a native view (Section 9.5, "Native +

Finally, if a native view (Section 10.5, "Native Views") contains one or more long data members, then such members should come last both in the select-list of the native SQL query and the list of data members in the C++ class.

-

19.2 SQL Server Database Class

+

21.2 SQL Server Database Class

The SQL Server database class encapsulates the ODBC environment handle as well as the server instance address and @@ -19388,7 +20187,7 @@ odb::mssql::database dbA ("test",

This constructor throws the odb::mssql::cli_exception exception if the SQL Server option values are missing or invalid. See - section Section 19.4, "SQL Server Exceptions" for + section Section 21.4, "SQL Server Exceptions" for more information on this exception.

The static print_usage() function prints the list of options @@ -19419,10 +20218,10 @@ odb::mssql::database dbA ("test",

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

+ on mssql::connection, refer to Section + 21.3, "SQL Server Connection and Connection Factory".

-

19.3 SQL Server Connection and Connection Factory

+

21.3 SQL Server Connection and Connection Factory

The mssql::connection class has the following interface:

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

19.4 SQL Server Exceptions

+

21.4 SQL Server Exceptions

The SQL Server ODB runtime library defines the following SQL Server-specific exceptions:

@@ -19698,14 +20497,14 @@ namespace odb

The odb::mssql::long_data_reload is thrown if an attempt is made to re-load an object or view with long data as part of a query result iteration. For more information, refer - to Section 19.1, "SQL Server Type Mapping".

+ to Section 21.1, "SQL Server Type Mapping".

-

19.5 SQL Server Limitations

+

21.5 SQL Server Limitations

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

-

19.5.1 Query Result Caching

+

21.5.1 Query Result Caching

SQL Server ODB runtime implementation does not perform query result caching (Section 4.4, "Query Result") even when @@ -19720,7 +20519,7 @@ namespace odb 3.14, "ODB Exceptions") is always thrown. Future versions of the SQL Server ODB runtime library may add support for result caching.

-

19.5.2 Foreign Key Constraints

+

21.5.2 Foreign Key Constraints

ODB assumes the standard SQL behavior which requires that foreign key constraints checking is deferred until the transaction is @@ -19736,7 +20535,7 @@ namespace odb which you persist, update, and erase objects within a transaction becomes important.

-

19.5.3 Unique Constraint Violations

+

21.5.3 Unique Constraint Violations

Due to the granularity of the ODBC error codes, it is impossible to distinguish between the duplicate primary key and other unique @@ -19745,7 +20544,7 @@ namespace odb errors to the object_already_persistent exception (Section 3.14, "ODB Exceptions").

-

19.5.4 Multi-threaded Windows Applications

+

21.5.4 Multi-threaded Windows Applications

Multi-threaded Windows applications must use the _beginthread()/_beginthreadex() and @@ -19754,7 +20553,7 @@ namespace odb Win32 functions to start and terminate threads. This is a limitation of the ODBC implementation on Windows.

-

19.5.5 Affected Row Count and DDL Statements

+

21.5.5 Affected Row Count and DDL Statements

SQL Server always returns zero as the number of affected rows for DDL statements. In particular, this means that the @@ -19762,7 +20561,7 @@ namespace odb "Executing Native SQL Statements") function will always return zero for such statements.

-

19.5.6 Long Data and Auto Object Ids, ROWVERSION

+

21.5.6 Long Data and Auto Object Ids, ROWVERSION

SQL Server 2005 has a bug that causes it to fail on an INSERT or UPDATE statement with the OUTPUT clause @@ -19772,7 +20571,7 @@ namespace odb by the database::persist() or database::update() function when used on an object that contains long data and has an automatically assigned object id or uses ROWVERSION-based - optimistic concurrency (Section 19.1.1, + optimistic concurrency (Section 21.1.1, "ROWVERSION Support"). The error message reads "This operation conflicts with another pending operation on this transaction. The operation failed."

@@ -19789,9 +20588,9 @@ namespace odb objects that use ROWVERSION for optimistic concurrency and containing long data.

-

19.5.7 Long Data and By-Value Accessors/Modifiers

+

21.5.7 Long Data and By-Value Accessors/Modifiers

-

As discussed in Section 12.4.5, +

As discussed in Section 14.4.5, "get/set/access", by-value accessor and modifier expressions cannot be used with data members of long data types. The SQL Server ODB runtime uses streaming for @@ -19799,9 +20598,9 @@ namespace odb by-reference accessors and modifiers should be used for these data types.

-

19.6 SQL Server Index Definitions

+

21.6 SQL Server Index Definitions

-

When the index pragma (Section 12.6, +

When the index pragma (Section 14.6, "Index Definition Pragmas") is used to define an SQL Server index, the type clause specifies the index type (for example, UNIQUE, CLUSTERED), the method @@ -19836,9 +20635,9 @@ class object and libraries. It consists of the following chapters.

- - - + + +
20Profiles Introduction
21Boost Profile
22Qt Profile
22Profiles Introduction
23Boost Profile
24Qt Profile
@@ -19846,7 +20645,7 @@ class object
-

20 Profiles Introduction

+

22 Profiles Introduction

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


-

21 Boost Profile

+

23 Boost Profile

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

-

21.1 Smart Pointers Library

+

23.1 Smart Pointers Library

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

-

21.2 Unordered Containers Library

+

23.2 Unordered Containers Library

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

21.3 Multi-Index Container Library

+

23.3 Multi-Index Container Library

The multi-index sub-profile provides persistence support for boost::multi_index_container from the Boost Multi-Index @@ -20106,7 +20905,7 @@ class person }; -

21.4 Optional Library

+

23.4 Optional Library

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

-

21.5 Date Time Library

+

23.5 Date Time Library

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

-

21.5.1 MySQL Database Type Mapping

+

23.5.1 MySQL Database Type Mapping

The following table summarizes the default mapping between the currently supported Boost date_time types and the MySQL database @@ -20251,7 +21050,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 12.4.3, "type"), as shown in + (Section 14.4.3, "type"), as shown in the following example:

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

-

21.5.2 SQLite Database Type Mapping

+

23.5.2 SQLite Database Type Mapping

The following table summarizes the default mapping between the currently supported Boost date_time types and the SQLite database @@ -20347,7 +21146,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 12.4.3, + db type pragma (Section 14.4.3, "type"), as shown in the following example:

@@ -20382,7 +21181,7 @@ class person
      will result in the out_of_range exception.

-

21.5.3 PostgreSQL Database Type Mapping

+

23.5.3 PostgreSQL Database Type Mapping

The following table summarizes the default mapping between the currently supported Boost date_time types and the PostgreSQL database @@ -20433,7 +21232,7 @@ class person result in the special_value exception.

-

21.5.4 Oracle Database Type Mapping

+

23.5.4 Oracle Database Type Mapping

The following table summarizes the default mapping between the currently supported Boost date_time types and the Oracle database @@ -20474,7 +21273,7 @@ class person DATE Oracle type with fractional seconds that may be stored in a ptime instance being ignored. This alternative mapping has to be explicitly requested using the - db type pragma (Section 12.4.3, + db type pragma (Section 14.4.3, "type"), as shown in the following example:

@@ -20495,7 +21294,7 @@ class person
      the special_value exception.

-

21.5.5 SQL Server Database Type Mapping

+

23.5.5 SQL Server Database Type Mapping

The following table summarizes the default mapping between the currently supported Boost date_time types and the SQL Server database @@ -20542,7 +21341,7 @@ class person support for mapping posix_time::ptime to the DATETIME and SMALLDATETIME types, however, this mapping has to be explicitly requested using the - db type pragma (Section 12.4.3, + db type pragma (Section 14.4.3, "type"), as shown in the following example:

@@ -20566,7 +21365,7 @@ class person
      posix_time::time_duration value out of this range will
      result in the value_out_of_range exception.

-

21.6 Uuid Library

+

23.6 Uuid Library

The uuid sub-profile provides persistence support for the uuid type from the Boost uuid library. To @@ -20579,8 +21378,8 @@ class person database column with NULL enabled and nil uuid instances are stored as a NULL value. However, you can change this behavior by declaring the data member NOT NULL - with the not_null pragma (Section - 12.4.6, "null/not_null"). In this + with the not_null pragma (Section + 14.4.6, "null/not_null"). In this case, or if the data member is an object id, the implementation will store nil uuid instances as zero UUID values ({00000000-0000-0000-0000-000000000000}). For example:

@@ -20598,7 +21397,7 @@ class object };
-

21.6.1 MySQL Database Type Mapping

+

23.6.1 MySQL Database Type Mapping

The following table summarizes the default mapping between the Boost uuid type and the MySQL database type.

@@ -20618,7 +21417,7 @@ class object -

21.6.2 SQLite Database Type Mapping

+

23.6.2 SQLite Database Type Mapping

The following table summarizes the default mapping between the Boost uuid type and the SQLite database type.

@@ -20638,7 +21437,7 @@ class object -

21.6.3 PostgreSQL Database Type Mapping

+

23.6.3 PostgreSQL Database Type Mapping

The following table summarizes the default mapping between the Boost uuid type and the PostgreSQL database type.

@@ -20658,7 +21457,7 @@ class object -

21.6.4 Oracle Database Type Mapping

+

23.6.4 Oracle Database Type Mapping

The following table summarizes the default mapping between the Boost uuid type and the Oracle database type.

@@ -20678,7 +21477,7 @@ class object -

21.6.5 SQL Server Database Type Mapping

+

23.6.5 SQL Server Database Type Mapping

The following table summarizes the default mapping between the Boost uuid type and the SQL Server database type.

@@ -20703,7 +21502,7 @@ class object
-

22 Qt Profile

+

24 Qt Profile

The ODB profile implementation for Qt is provided by the libodb-qt library. Both Qt4 and Qt5 as well @@ -20732,7 +21531,7 @@ class object that can be thrown by the Qt sub-profiles are described in the following sections.

-

22.1 Basic Types Library

+

24.1 Basic Types Library

The basic sub-profile provides persistence support for basic types defined by Qt. To enable only this profile, pass @@ -20759,8 +21558,8 @@ class Person database column with NULL enabled and null QUuid instances are stored as a NULL value. However, you can change this behavior by declaring the data member NOT NULL - with the not_null pragma (Section - 12.4.6, "null/not_null"). In this + with the not_null pragma (Section + 14.4.6, "null/not_null"). In this case, or if the data member is an object id, the implementation will store null QUuid instances as zero UUID values ({00000000-0000-0000-0000-000000000000}). For example:

@@ -20778,7 +21577,7 @@ class object };
-

22.1.1 MySQL Database Type Mapping

+

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

@@ -20826,7 +21625,7 @@ class object NCHAR, and NVARCHAR MySQL types. However, these alternative mappings have to be explicitly requested using the db type pragma - (Section 12.4.3, "type"), as shown in + (Section 14.4.3, "type"), as shown in the following example:

@@ -20841,7 +21640,7 @@ class Person
   
-

22.1.2 SQLite Database Type Mapping

+

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

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

-

22.1.3 PostgreSQL Database Type Mapping

+

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

@@ -20918,7 +21717,7 @@ class Person and VARCHAR PostgreSQL types. However, these alternative mappings have to be explicitly requested using the db type pragma - (Section 12.4.3, "type"), as shown in + (Section 14.4.3, "type"), as shown in the following example:

@@ -20932,7 +21731,7 @@ class Person
 };
   
-

22.1.4 Oracle Database Type Mapping

+

24.1.4 Oracle Database Type Mapping

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

@@ -20974,7 +21773,7 @@ class Person NCLOB Oracle types, and for mapping QByteArray to the RAW Oracle type. However, these alternative mappings have to be explicitly requested using the db type - pragma (Section 12.4.3, "type"), as shown in the + pragma (Section 14.4.3, "type"), as shown in the following example:

@@ -20991,7 +21790,7 @@ class Person
 };
   
-

22.1.5 SQL Server Database Type Mapping

+

24.1.5 SQL Server Database Type Mapping

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

@@ -21041,7 +21840,7 @@ class Person QByteArray to the BINARY and IMAGE SQL Server types. However, these alternative mappings have to be explicitly requested using the db type - pragma (Section 12.4.3, "type"), as shown in the + pragma (Section 14.4.3, "type"), as shown in the following example:

@@ -21058,7 +21857,7 @@ class Person
 };
   
-

22.2 Smart Pointers Library

+

24.2 Smart Pointers Library

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

-

22.3 Containers Library

+

24.3 Containers Library

The containers sub-profile provides persistence support for Qt containers. To enable only this profile, pass @@ -21153,13 +21952,13 @@ class Person

The containers sub-profile also provide a change-tracking - equivalent for QList (Section 22.3.1, + equivalent for QList (Section 24.3.1, "Change-Tracking QList") with support for other Qt container equivalents planned for future releases. For general information on change-tracking containers refer to Section 5.4, "Change-Tracking Containers".

-

22.3.1 Change-Tracking QList

+

24.3.1 Change-Tracking QList

Class template QOdbList, defined in <odb/qt/list.hxx>, is a change-tracking @@ -21175,8 +21974,8 @@ class Person

QOdbList incurs 2-bit per element overhead in order to store the change state. It cannot - be stored unordered in the database (Section - 12.4.18 "unordered") but can be used as an inverse + be stored unordered in the database (Section + 14.4.18 "unordered") but can be used as an inverse side of a relationship (6.2 "Bidirectional Relationships"). In this case, no change tracking is performed since no state for such a container is stored in the database.

@@ -21340,7 +22139,7 @@ qSort (l.modifyBegin (), l.modifyEnd ()); that any element that such an iterator passes over with the call to next() is marked as modified.

-

22.4 Date Time Library

+

24.4 Date Time Library

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

-

22.4.1 MySQL Database Type Mapping

+

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

@@ -21433,7 +22232,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 12.4.3, "type"), as shown in + (Section 14.4.3, "type"), as shown in the following example:

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

-

22.4.2 SQLite Database Type Mapping

+

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

@@ -21527,7 +22326,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 12.4.3, "type"), as shown + (Section 14.4.3, "type"), as shown in the following example:

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

-

22.4.3 PostgreSQL Database Type Mapping

+

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

@@ -21582,7 +22381,7 @@ class Person QDateTime types are stored as a NULL value if their isNull() member function returns true.

-

22.4.4 Oracle Database Type Mapping

+

24.4.4 Oracle Database Type Mapping

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

@@ -21623,7 +22422,7 @@ class Person DATE Oracle type with fractional seconds that may be stored in a QDateTime instance being ignored. This alternative mapping has to be explicitly requested using the - db type pragma (Section 12.4.3, + db type pragma (Section 14.4.3, "type"), as shown in the following example:

@@ -21636,7 +22435,7 @@ class person
 };
   
-

22.4.5 SQL Server Database Type Mapping

+

24.4.5 SQL Server Database Type Mapping

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

@@ -21683,7 +22482,7 @@ class person support for mapping QDateTime to the DATETIME and SMALLDATETIME types, however, this mapping has to be explicitly requested using the db type pragma - (Section 12.4.3, "type"), as + (Section 14.4.3, "type"), as shown in the following example:

-- 
cgit v1.1