From 8f8433c3091ff9c608d9bf26bbc67ce0980ed23c Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 3 Oct 2011 09:23:34 +0200 Subject: Document views --- doc/manual.xhtml | 2180 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 1737 insertions(+), 443 deletions(-) (limited to 'doc') diff --git a/doc/manual.xhtml b/doc/manual.xhtml index 64a0952..22d83b8 100644 --- a/doc/manual.xhtml +++ b/doc/manual.xhtml @@ -308,8 +308,9 @@ for consistency. 2.4Making Objects Persistent 2.5Querying the Database for Objects 2.6Updating Persistent Objects - 2.7Deleting Persistent Objects - 2.8Summary + 2.7Defining and Using Views + 2.8Deleting Persistent Objects + 2.9Summary @@ -318,7 +319,7 @@ for consistency. 3Working with Persistent Objects - + @@ -407,87 +408,112 @@ for consistency. - - + + + +
3.1Concepts and Terminology
3.2Object Pointers
3.2Object and View Pointers
3.3Database
3.4Transactions
3.5Connections
9Session + 9Views - + + + + + +
9.1Object Cache
9.1Object Views
9.2Table Views
9.3Mixed Views
9.4View Query Conditions
9.5Native Views
9.6Other View Features and Limitations
10ODB Pragma Language + 10Session + +
10.1Object Cache
+
11ODB Pragma Language + + + + - - - - @@ -500,31 +526,31 @@ for consistency. - - - + - + - + - + - + - + - - + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - +
11.1Object Type Pragmas + + + + + +
11.1.1table
11.1.2pointer
11.1.3abstract
11.1.4callback
+
10.1Object Type Pragmas + 11.2View Type Pragmas - - - - + + + + +
10.1.1table
10.1.2pointer
10.1.3abstract
10.1.4callback
11.2.1object
11.2.2table
11.2.3query
11.2.4pointer
11.2.5callback
10.2Value Type Pragmas + 11.3Value Type Pragmas - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + +
10.2.1type
10.2.2id_type
10.2.3null/not_null
10.2.4default
10.2.5options
10.2.6unordered
10.2.7index_type
10.2.8key_type
10.2.9value_type
10.2.10value_null/value_not_null
10.2.11id_options
10.2.12index_options
10.2.13key_options
10.2.14value_options
10.2.15id_column
10.2.16index_column
10.2.17key_column
10.2.18value_column
11.3.1type
11.3.2id_type
11.3.3null/not_null
11.3.4default
11.3.5options
11.3.6unordered
11.3.7index_type
11.3.8key_type
11.3.9value_type
11.3.10value_null/value_not_null
11.3.11id_options
11.3.12index_options
11.3.13key_options
11.3.14value_options
11.3.15id_column
11.3.16index_column
11.3.17key_column
11.3.18value_column
10.3Data Member Pragmas + 11.4Data Member Pragmas - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + +
10.3.1id
10.3.2auto
10.3.3type
10.3.4null/not_null
10.3.5default
10.3.6options
10.3.7column
10.3.8transient
10.3.9inverse
10.3.10unordered
10.3.11table
10.3.12index_type
10.3.13key_type
10.3.14value_type
10.3.15value_null/value_not_null
10.3.16id_options
10.3.17index_options
10.3.18key_options
10.3.19value_options
10.3.20id_column
10.3.21index_column
10.3.22key_column
10.3.23value_column
11.4.1id
11.4.2auto
11.4.3type
11.4.4null/not_null
11.4.5default
11.4.6options
11.4.7column (object, composite value)
11.4.8column (view)
11.4.9transient
11.4.10inverse
11.4.11unordered
11.4.12table
11.4.13index_type
11.4.14key_type
11.4.15value_type
11.4.16value_null/value_not_null
11.4.17id_options
11.4.18index_options
11.4.19key_options
11.4.20value_options
11.4.21id_column
11.4.22index_column
11.4.23key_column
11.4.24value_column
10.4C++ Compiler Warnings + 11.5C++ Compiler Warnings - - - - - + + + + +
10.4.1GNU C++
10.4.2Visual C++
10.4.3Sun C++
10.4.4IBM XL C++
10.4.5HP aC++
11.5.1GNU C++
11.5.2Visual C++
11.5.3Sun C++
11.5.4IBM XL C++
11.5.5HP aC++
11MySQL Database + 12MySQL Database - - - - + + + +
11.1MySQL Type Mapping
11.2MySQL Database Class
11.3MySQL Connection and Connection Factory
11.4MySQL Exceptions
12.1MySQL Type Mapping
12.2MySQL Database Class
12.3MySQL Connection and Connection Factory
12.4MySQL Exceptions
12SQLite Database + 13SQLite Database - - - - + + + + - @@ -533,20 +559,20 @@ for consistency. - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - +
12.1SQLite Type Mapping
12.2SQLite Database Class
12.3SQLite Connection and Connection Factory
12.4SQLite Exceptions
13.1SQLite Type Mapping
13.2SQLite Database Class
13.3SQLite Connection and Connection Factory
13.4SQLite Exceptions
12.5SQLite Limitations + 13.5SQLite Limitations - - - - - + + + + +
12.5.1Query Result Caching
12.5.2Automatic Assignment of Object Ids
12.5.3Foreign Key Constraints
12.5.4Constraint Violations
12.5.5Sharing of Queries
13.5.1Query Result Caching
13.5.2Automatic Assignment of Object Ids
13.5.3Foreign Key Constraints
13.5.4Constraint Violations
13.5.5Sharing of Queries
13PostgreSQL Database + 14PostgreSQL Database - - - - + + + + - @@ -559,21 +585,21 @@ for consistency. - + - - + - + - + - +
13.1PostgreSQL Type Mapping
13.2PostgreSQL Database Class
13.3PostgreSQL Connection and Connection Factory
13.4PostgreSQL Exceptions
14.1PostgreSQL Type Mapping
14.2PostgreSQL Database Class
14.3PostgreSQL Connection and Connection Factory
14.4PostgreSQL Exceptions
13.5PostgreSQL Limitations + 14.5PostgreSQL Limitations - - - - - + + + + +
13.5.1Query Result Caching
13.5.2Foreign Key Constraints
13.5.3Date-Time Format
13.5.4Timezones
13.5.5NUMERIC Type Support
14.5.1Query Result Caching
14.5.2Foreign Key Constraints
14.5.3Date-Time Format
14.5.4Timezones
14.5.5NUMERIC Type Support
14Profiles Introduction15Profiles Introduction
15Boost Profile + 16Boost Profile - - - + + + - @@ -582,24 +608,24 @@ for consistency. - - - + + - @@ -720,8 +746,9 @@ for consistency. - - + + +
15.1Smart Pointers Library
15.2Unordered Containers Library
15.3Optional Library
16.1Smart Pointers Library
16.2Unordered Containers Library
16.3Optional Library
15.4Date Time Library + 16.4Date Time Library - - - + + +
15.4.1MySQL Database Type Mapping
15.4.2SQLite Database Type Mapping
15.4.3PostgreSQL Database Type Mapping
16.4.1MySQL Database Type Mapping
16.4.2SQLite Database Type Mapping
16.4.3PostgreSQL Database Type Mapping
16Qt Profile + 17Qt Profile - + +
16.1Basic Types Library + 17.1Basic Types Library - - -
16.1.1MySQL Database Type Mapping
16.1.2SQLite Database Type Mapping
16.1.3PostgreSQL Database Type Mapping
+
17.1.1MySQL Database Type Mapping
17.1.2SQLite Database Type Mapping
17.1.3PostgreSQL Database Type Mapping
16.2Smart Pointers Library
16.3Containers Library
17.2Smart Pointers Library
17.3Containers Library
16.4Date Time Library + 17.4Date Time Library - - - + + +
16.4.1MySQL Database Type Mapping
16.4.2SQLite Database Type Mapping
16.4.3PostgreSQL Database Type Mapping
17.4.1MySQL Database Type Mapping
17.4.2SQLite Database Type Mapping
17.4.3PostgreSQL Database Type Mapping
6Relationships
7Value Types
8Inheritance
9Session
10ODB Pragma Language
9Views
10Session
11ODB Pragma Language
@@ -743,7 +770,9 @@ for consistency. database schema for your persistent classes, and use simple, safe, and yet powerful object query language instead of SQL. Or you can assign SQL types to individual data members, use the existing - database schema, and run native SQL SELECT queries.

+ database schema, and run native SQL SELECT queries. + In fact, at an extreme, ODB can be used as just a convenient + way to handle results of native SQL queries.

ODB is not a framework. It does not dictate how you should write your application. Rather, it is designed to fit into your @@ -943,7 +972,10 @@ for consistency. support code, as well as compile and run our application. We will also learn how to make objects persistent, load, update and delete persistent objects, as well as query the database - for persistent objects that match certain criteria.

+ for persistent objects that match certain criteria. The example + also shows how to define and use views, a mechanism that allows + us to create projections of persistent objects, database tables, + or to handle results of native SQL queries.

The code presented in this chapter is based on the hello example which can be found in the @@ -1333,7 +1365,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 11.2, "MySQL Database Class").

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

Next, we create three person objects. Right now they are transient objects, which means that if we terminate the application @@ -1625,7 +1657,7 @@ main (int argc, char* argv[]) shared_ptr from TR1 or Boost. For more information on the object lifetime management and the smart pointers that we can use for that, see Section 3.2, "Object - Pointers".

+ and View Pointers".

With the instantiated object in hand we increment the age and call the update() function to update @@ -1673,7 +1705,92 @@ Hello, Joe! } -

2.7 Deleting Persistent Objects

+

2.7 Defining and Using Views

+ +

Suppose that we need to gather some basic statistics about the people + stored in our database. Things like the total head count, as well as + the minimum and maximum ages. One way to do it would be to query + the database for all the person objects and then + calculate this information as we iterate over the query result. + While this approach may work fine for our database with just three + people in it, it would be very inefficient if we had a large + number of objects.

+ +

While it may not be conceptually pure from the object-oriented + programming point of view, a relational database can perform + some computations much faster and much more economically than + if we performed the same operations ourselves in the application's + process.

+ +

To support such cases ODB provides the notion of 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.

+ +

Some of the common applications of views include loading a subset of + data members from objects or columns database tables, executing and + handling results of arbitrary SQL queries, including aggregate + queries, as well as joining multiple objects and/or database + 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 + the person_stat view that returns the basic statistics + about the person objects:

+ +
+#pragma db view object(person)
+struct person_stat
+{
+  #pragma db column("count(" + person::id_ + ")")
+  std::size_t count;
+
+  #pragma db column("min(" + person::age_ + ")")
+  unsigned short min_age;
+
+  #pragma db column("max(" + person::age_ + ")")
+  unsigned short max_age;
+};
+  
+ +

To get the result of a view we use the same query() + function as when querying the database for an object. Here is + how we can load and print our statistics using the view we have + just created:

+ +
+    // Print some statistics about all the people in our database.
+    //
+    {
+      transaction t (db->begin ());
+
+      odb::result<person_stat> r (db->query<person_stat> ());
+
+      // The result of this query always has exactly one element.
+      //
+      const person_stat& ps (*r.begin ());
+
+      cout << "count  : " << ps.count << endl
+           << "min age: " << ps.min_age << endl
+           << "max age: " << ps.max_age << endl;
+
+      t.commit ();
+    }
+  
+ +

If we now add the person_stat view to the + person.hxx header, the above transaction + to driver.cxx, as well as re-compile and + re-run our example, then we will see the following + additional lines in the output:

+ +
+count  : 3
+min age: 31
+max age: 33
+  
+ +

2.8 Deleting Persistent Objects

The last operation that we will discuss in this chapter is deleting the persistent object from the database. The following code @@ -1719,7 +1836,7 @@ Hello, Joe! } -

2.8 Summary

+

2.9 Summary

This chapter presented a very simple application which, nevertheless, exercised all of the core database functions: persist(), @@ -1752,10 +1869,12 @@ Hello, Joe! showed how to use it to store C++ objects in a database. In this chapter we will examine the ODB object persistence model as well as the core database APIs in greater detail. We will - start with basic concepts and terminology in Section 3.1 - and continue with the discussion of the odb::database - class in Section 3.3 and transactions in - Section 3.4. The remainder of this chapter + start with basic concepts and terminology in Section + 3.1 and Section 3.2 and continue with the + discussion of the odb::database class in + Section 3.3, transactions in + Section 3.4, and connections in + Section 3.5. The remainder of this chapter deals with the core database operations and concludes with the discussion of ODB exceptions.

@@ -1830,6 +1949,18 @@ Hello, Joe! viewed (and mapped) as both simple and composite by different applications.

+

While not strictly necessary in a purely object-oriented application, + practical considerations often require us to only load a + subset of an object's data members or a combination of members + from several objects. We may also need to factor out some + 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++ + 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.

+

Understanding how all these concepts map to the relational model will hopefully make these distinctions clearer. In a relational database an object type is mapped to a table and a value type is @@ -1838,7 +1969,10 @@ Hello, Joe! several columns. An object is stored as a row in this table and a value is stored as one or more cells in this row. A simple value is stored in a single cell while a composite - value occupies several cells.

+ value occupies several cells. A view is not a persistent + entity and it is not stored in the database. Rather, it is a + data structure that is used to capture a single row of an SQL + query result.

Going back to the distinction between simple and composite values, consider a date type which has three integer @@ -1889,7 +2023,7 @@ class person

These two pragmas are the minimum required to declare a persistent class. Other pragmas can be used to fine-tune the database-related properties of a class and its - members (Chapter 10, "ODB Pragma Language").

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

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

@@ -1996,36 +2130,41 @@ class name application terminates unless and until it is explicitly deleted from the database.

-

3.2 Object Pointers

+

3.2 Object and View Pointers

As we have seen in the previous chapter, some database operations create dynamically allocated instances of persistent classes and 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 9, - "Session").

- -

By default, all these mechanisms use raw pointers to return, - pass, and cache objects. This is normally sufficient for applications + persistent objects in a session (Chapter 10, + "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() + function (Section 4.4, "Query Results").

+ +

By default, all these mechanisms use raw pointers to return + objects and views as well as to pass and cache objects. This + is normally sufficient for applications that have simple object lifetime requirements and do not use sessions or object relationships. In particular, a dynamically allocated object - that is returned as a raw pointer from a database operation can be - assigned to a smart pointer of our choice, for example + or view that is returned as a raw pointer from a database operation + can be assigned to a smart pointer of our choice, for example std::auto_ptr or shared_ptr from TR1 or Boost.

However, to avoid any possibility of a mistake, such as forgetting - to use a smart pointer for a returned object, as well as to simplify the - use of more advanced ODB functionality, such as sessions and bidirectional - object relationships, it is recommended that you use smart pointers - with the sharing semantics as object pointers. The shared_ptr - smart pointer from TR1 or Boost is a good default choice.

- -

ODB provides two mechanisms for changing the object pointer type. We - can use the --default-pointer option to specify the - default object pointer type. All objects that don't have the object - pointer explicitly specified with the db pointer + to use a smart pointer for a returned object or view, as well as to + simplify the use of more advanced ODB functionality, such as sessions + and bidirectional object relationships, it is recommended that you use + smart pointers with the sharing semantics as object and view pointers. + The shared_ptr smart pointer from TR1 or Boost is a good + default choice.

+ +

ODB provides two mechanisms for changing the object or view pointer + type. We can use the --default-pointer option to specify + the default pointer. All objects and views that don't have the pointer + type explicitly specified with the db pointer pragma (see below) will use the default pointer type. Refer to the ODB Compiler Command Line Manual for details on this option's argument. @@ -2035,9 +2174,9 @@ class name --default-pointer std::tr1::shared_ptr -

The second mechanism allows us to specify the object pointer on - an object by object basis using the db pointer - pragma, for example:

+

The second mechanism allows us to specify the pointer type on + the per object and per view basis using the + db pointer pragma, for example:

 #pragma db object pointer(std::tr1::shared_ptr)
@@ -2047,12 +2186,13 @@ class person
 };
   
-

Refer to Section 10.1.2, "pointer" - for more information on this pragma.

+

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

Built-in support that is provided by the ODB runtime library allows us to use the TR1 shared_ptr and std::auto_ptr as - object pointers. Plus, ODB profile libraries, that are available for + pointer types. Plus, ODB profile libraries, that are available for commonly used frameworks and libraries (such as Boost and Qt), provide support for smart pointers found in these frameworks and libraries (Part III, "Profiles"). It is also @@ -2171,7 +2311,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 10, "ODB Pragma + and db type (Chapter 11, "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.

@@ -2615,7 +2755,7 @@ for (unsigned short retry_count (0); ; retry_count++) object_traits<T>::pointer_type and object_traits<T>::const_pointer_type denote the unrestricted and constant object pointer types (Section - 3.2, "Object Pointer"), respectively. + 3.2, "Object and View Pointers"), respectively. Similarly, object_traits<T>::id_type denotes the object id type. The odb::object_traits template is part of the database support code generated by the ODB compiler.

@@ -2623,7 +2763,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 10.3.2, + application-assigned object ids (Section 11.4.2, "auto").

The second and third persist() functions are similar to the @@ -3133,7 +3273,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 9, "Session".

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

The recoverable exception serves as a common base for all the recoverable exceptions, which are: connection_lost, @@ -3867,7 +4007,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 10, "ODB Pragma + these pragmas, refer to Chapter 11, "ODB Pragma Language". The following example shows some of the possible customizations:

@@ -3893,8 +4033,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 10.2.6, - "unordered", Section 10.3.10, + db unordered pragma (Section 11.3.6, + "unordered", Section 11.4.11, "unordered"). For example:

@@ -3955,7 +4095,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 10, "ODB Pragma + these pragmas, refer to Chapter 11, "ODB Pragma Language". The following example shows some of the possible customizations:

@@ -4017,7 +4157,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 10, "ODB Pragma + these pragmas, refer to Chapter 11, "ODB Pragma Language". The following example shows some of the possible customizations:

@@ -4095,8 +4235,8 @@ private: in Section 6.4, "Using Custom Smart Pointers". Any supported smart pointer can be used in a data member as long as it can be explicitly constructed from the canonical object pointer - (Section 3.2, "Object Pointers"). For example, we can - use weak_ptr if the object pointer + (Section 3.2, "Object and View Pointers"). For + example, we can use weak_ptr if the object pointer is shared_ptr.

When an object containing a pointer to another object is loaded, @@ -4144,11 +4284,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 - 10.3.4, "null/not_null") for + use the not_null pragma (Section + 11.4.4, "null/not_null") for single object pointers and the value_not_null pragma - (Section - 10.3.15, "value_null/value_not_null") + (Section + 11.4.16, "value_null/value_not_null") for containers of object pointers. For example:

@@ -4214,7 +4354,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 9, "Session", a session acts as a cache + Chapter 10, "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 @@ -4394,7 +4534,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 10, "ODB Pragma Language"). For example:

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

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

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

@@ -4561,7 +4701,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 10.3.10, "unordered") + (Section 11.4.11, "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).

@@ -5125,7 +5265,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 10.2.1, "type").

+ pragma (Section 11.3.1, "type").

7.2 Composite Value Types

@@ -5264,8 +5404,8 @@ t.commit ();

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

@@ -5366,9 +5506,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 10.3.23, "value_column") or + (Section 11.4.24, "value_column") or db key_column - (Section 10.3.22, "key_column") + (Section 11.4.23, "key_column") pragmas are used to specify the column prefix.

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

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

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

 #pragma db value
@@ -5454,7 +5594,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 10.3.4,
+     pragma (Section 11.4.4,
      "null/not_null").

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

+ (Section 16.3, "Optional Library").

Another common C++ representation of a value that can be NULL is a pointer. ODB will automatically @@ -5637,6 +5777,7 @@ class person };

+ @@ -5767,7 +5908,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 10.1.3, "abstract"). + pragma (Section 11.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 @@ -5876,11 +6017,1040 @@ CREATE TABLE contractor (

Polymorphism inheritance mapping is not yet implemented. Future versions of ODB will add support for this functionality.

+
-

9 Session

+

9 Views

+ +

An ODB view is a C++ class or struct type + 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.

+ +

Some of the common applications of views include loading a subset + of data members from objects or columns from database tables, executing + and handling results of arbitrary SQL queries, including aggregate + queries, as well as joining multiple objects and/or database tables + using object relationships or custom join conditions.

+ +

Many relational databases also define the concept of views. Note, + however, that ODB views are not mapped to database views. Rather, + by default, an ODB view is mapped to an SQL SELECT + query. However, if desired, it is easy to create an ODB view + that is based on a database view.

+ +

Usually, views are defined in terms of other persistent entities, + such as persistent objects, database tables, sequences, etc. + Therefore, before we can examine our first view, we need to + define a few persistent objects and a database table. We will + use this model in examples throughout this chapter. Here we + assume that you are familiar with ODB object relationship + support (Chapter 6, "Relationships").

+ +
+#pragma db object
+class country
+{
+  ...
+
+  #pragma db id
+  std::string code_; // ISO 2-letter country code.
+
+  std::string name_;
+};
+
+#pragma db object
+class employer
+{
+  ...
+
+  #pragma db id
+  unsigned long id_;
+
+  std::string name_;
+};
+
+#pragma db object
+class employee
+{
+  ...
+
+  #pragma db id
+  unsigned long id_;
+
+  std::string first_;
+  std::string last_;
+
+  unsigned short age_;
+
+  shared_ptr<country> residence_;
+  shared_ptr<country> nationality_;
+
+  shared_ptr<employer> employed_by_;
+};
+  
+ +

Besides these objects, we also have the legacy + employee_extra table that is not mapped to any persistent + class. It has the following definition:

+ +
+CREATE TABLE employee_extra(
+  employee_id INTEGER NOT NULL,
+  vacation_days INTEGER NOT NULL,
+  previous_employer_id INTEGER)
+  
+ +

The above persistent objects and database table as well as many of + the views shown in this chapter are based on the + view example which can be found in the + odb-examples package of the ODB distribution.

+ +

To declare a view we use the db view pragma, + for example:

+ +
+#pragma db view object(employee)
+struct employee_name
+{
+  std::string first;
+  std::string last;
+};
+  
+ +

The above example shows one of the simplest views that we can create. + It has a single associated object (employee) and its + purpose is to extract the employee's first and last names without + loading any other data, such as the referenced country + and employer objects.

+ +

Views use the same query facility (Chapter 4, "Querying + the Database") as persistent objects. Because support for queries + is optional and views cannot be used without this support, you need + to compile any header that defines a view with the + --generate-query ODB compiler option.

+ +

To query the database for a view we use the database::query() + function in exactly the same way as we would use it to query the + database for an object. For example, the following code fragment + shows how we can find the names of all the employees that are + younger than 31:

+ +
+typedef odb::query<employee_name> query;
+typedef odb::result<employee_name> result;
+
+transaction t (db.begin ());
+
+result r (db.query<employee_name> (query::age < 31));
+
+for (result::iterator i (r.begin ()); i != r.end (); ++i)
+{
+  const employee_name& en (*i);
+  cout << en.first << " " << en.last << endl;
+}
+
+t.commit ();
+  
+ +

A view can be defined as a projection of one or more objects, one + or more tables, a combination of objects and tables, or it can be + the result of a custom SQL query. The following sections discuss each + of these kinds of view in more detail.

+ +

9.1 Object Views

+ +

To associate one or more objects with a view we use the + db object pragma (Section + 11.2.1, "object"). We have already seen + 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, + for example:

+ +
+#pragma db view object(employee) object(employer)
+struct employee_employer
+{
+  std::string first;
+  std::string last;
+  std::string name;
+};
+  
+ +

The complete syntax of the db object pragma is + shown below:

+ +

object(name + [= alias] + [: join-condition])

+ +

The name part is a potentially qualified persistent class + name that has been defined previously. The optional alias + part gives this object an alias. If provided, the alias is used + in several contexts instead of the object's unqualified name. We + will discuss aliases further as we cover each of these contexts + 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 + while the first associated object can have an alias, it cannot + have a join condition.

+ +

For each subsequent associated object the ODB compiler needs + a join condition and there are several ways to specify + it. The easiest way is to omit it altogether and let the ODB + compiler try to come up with a join condition automatically. + To do this the ODB compiler will examine each previously + associated object for object relationships + (Chapter 6, "Relationships") that + may exist between these objects and the object being associated. + If such a relationship exists and is unambiguous, that is + there is only one such relationship, then the ODB compiler + will automatically use it to come up with the join condition for + this object. This is exactly what happens in the previous + example: there is a single relationship + (employee::employed_by) between the + employee and employer objects.

+ +

On the other hand, consider this view:

+ +
+#pragma db view object(employee) object(country)
+struct employee_residence
+{
+  std::string first;
+  std::string last;
+  std::string name;
+};
+  
+ +

While there is a relationship between country and + employee, it is ambiguous. It can be + employee::residence_ (which is what we want) or + it can be employee::location_ (which we don't + want). As result, when compiling the above view, the ODB + compiler will issue an error indicating an ambiguous object + relationship. To resolve this ambiguity, we can explicitly + specify the object relationship that should be used to create + the join condition as the name of the corresponding data member. + Here is how we can fix the employee_residence + view:

+ +
+#pragma db view object(employee) object(country: employee::residence_)
+struct employee_residence
+{
+  std::string first;
+  std::string last;
+  std::string name;
+};
+  
+ +

It is possible to associate the same object with a single view + more than once using different join conditions. However, in + this case, we have to use aliases to assign different names + for each association. For example:

+ +
+#pragma db view object(employee) \
+  object(country = res_country: employee::residence_) \
+  object(country = nat_country: employee::nationality_)
+struct employee_country
+{
+  ...
+};
+  
+ +

If we assign an alias to an object and refer to a data member of + this object in one of the join conditions, we have to use the + unqualified alias name instead of the potentially qualified + object name. For example:

+ +
+#pragma db view object(employee = ee) object(country: ee::residence_)
+struct employee_residence
+{
+  ...
+};
+  
+ +

The last way to specify a join condition is to provide a custom + query expression. This method is primarily useful if you would + like to associate an object using a condition that does not + involve an object relationship. Consider, for example, a + modified employee object from the beginning of + the chapter with an added country of birth member. For one + reason or another we have decided not to use a relationship to + the country object, as we have done with + residence and nationality.

+ +
+#pragma db object
+class employee
+{
+  ...
+
+  std::string birth_place_; // Country name.
+};
+  
+ +

If we now want to create a view that returns the birth country code + for an employee, then we have to use a custom join condition when + associating the country object. For example:

+ +
+#pragma db view object(employee) \
+  object(country: employee::birth_place_ == country::name_)
+struct employee_birth_code
+{
+  std::string first;
+  std::string last;
+  std::string code;
+};
+  
+ +

The syntax of the query expression in custom join conditions + is the same as in the query facility used to query the database + for objects (Chapter 4, "Querying the Database") + except that for query members, instead of using + odb::query<object>::member names, we refer directly + to object members.

+ +

Looking at the views we have defined so far, you may be wondering + how the ODB compiler knows which view data members correspond to which + object data members. While the names are similar, they are not exactly + the same, for example employee_name::first and + employee::first_.

+ +

As with join conditions, when it comes to associating data members, + the ODB compiler tries to do this automatically. It first searches + all the associated objects for an exact name match. If no match is + found, then the ODB compiler compares the so-called public names. + A public name of a member is obtained by removing the common member + name decorations, such as leading and trailing underscores, the + m_ prefix, etc. In both of these searches the ODB + compiler also makes sure that the types of the two members are the + same or compatible.

+ +

If one of the above searches returned a match and it is unambiguous, that + is there is only one match, then the ODB compiler will automatically + associate the two members. On the other hand, if no match is found + or the match is ambiguous, the ODB compiler will issue an error. + To associate two differently-named members or to resolve an ambiguity, + we can explicitly specify the member association using the + db column pragma (Section 11.4.7, + "column"). For example:

+ +
+#pragma db view object(employee) object(employer)
+struct employee_employer
+{
+  std::string first;
+  std::string last;
+
+  #pragma db column(employer::name_)
+  std::string employer_name;
+};
+  
+ +

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

+ +

Note also that similar to join conditions, if we assign an alias to + an object and refer to a data member of this object in one of the + db column pragmas, then we have to use the + unqualified alias name instead of the potentially qualified + object name. For example:

+ +
+#pragma db view object(employee) \
+  object(country = res_country: employee::residence_) \
+  object(country = nat_country: employee::nationality_)
+struct employee_country
+{
+  std::string first;
+  std::string last;
+
+  #pragma db column(res_country::name_)
+  std::string res_country_name;
+
+  #pragma db column(nat_country::name_)
+  std::string nat_country_name;
+};
+  
+ +

Besides specifying just the object member, we can also specify a + +-expression in the db column pragma. A + +-expression consists of string literals and object + member references connected using the + operator. + It is primarily useful for defining aggregate views based on + SQL aggregate functions, for example:

+ +
+#pragma db view object(employee)
+struct employee_count
+{
+  #pragma db column("count(" + employee::id_ + ")")
+  std::size_t count;
+};
+  
+ +

When querying the database for a view, we may want to provide + additional query criteria based on the objects associated with + this view. To support this a view defines query members for all + the associated objects which allows us to refer to such objects' + members using the odb::query<view>::member expressions. + This is similar to how we can refer to object members using the + odb::query<object>::member expressions when + querying the database for an object. For example:

+ +
+typedef odb::result<employee_count> result;
+typedef odb::query<employee_count> query;
+
+transaction t (db.begin ());
+
+// Find the number of employees with the Doe last name.
+//
+result r (db.query<employee_count> (query::last == "Doe"));
+
+// Result of this aggregate query contains only one element.
+//
+cout << r.begin ()->count << endl;
+
+t.commit ();
+  
+ +

In the above query we used the last name data member from the associated + employee object to only count employees with the specific + name.

+ +

When a view has only one associated object, the query members + corresponding to this object are defined directly in the + odb::query<view> scope. For instance, + in the above example, we referred to the last name member as + odb::query<employee_count>::last. However, if + a view has multiple associated objects, then query members + corresponding to each such object are defined in a nested + scope named after the object. As an example, consider + the employee_employer view again:

+ +
+#pragma db view object(employee) object(employer)
+struct employee_employer
+{
+  std::string first;
+  std::string last;
+
+  #pragma db column(employer::name_)
+  std::string employer_name;
+};
+  
+ +

Now, to refer to the last name data member from the employee + object we use the + odb::query<...>::employee::last expression. + Similarly, to refer to the employer name, we use the + odb::query<...>::employer::name expression. + For example:

+ +
+typedef odb::result<employee_employer> result;
+typedef odb::query<employee_employer> query;
+
+transaction t (db.begin ());
+
+result r (db.query<employee_employer> (
+  query::employee::last == "Doe" &&
+  query::employer::name == "Simple Tech Ltd"));
+
+for (result::iterator i (r.begin ()); i != r.end (); ++i)
+  cout << i->first << " " << i->last <<  " " << i->employer_name << endl;
+
+t.commit ();
+  
+ +

If we assign an alias to an object, then this alias is used to + name the query members scope instead of the object name. As an + example, consider the employee_country view again:

+ +
+#pragma db view object(employee) \
+  object(country = res_country: employee::residence_) \
+  object(country = nat_country: employee::nationality_)
+struct employee_country
+{
+  ...
+};
+  
+ +

And a query which returns all the employees that have the same + country of residence and nationality:

+ +
+typedef odb::query<employee_country> query;
+typedef odb::result<employee_country> result;
+
+transaction t (db.begin ());
+
+result r (db.query<employee_country> (
+  query::res_country::name == query::nat_country::name));
+
+for (result::iterator i (r.begin ()); i != r.end (); ++i)
+  cout << i->first << " " << i->last << " " << i->res_country_name << endl;
+
+t.commit ();
+  
+ +

Note also that unlike object query members, view query members do + no support referencing members in related objects. For example, + the following query is invalid:

+ +
+typedef odb::query<employee_name> query;
+typedef odb::result<employee_name> result;
+
+transaction t (db.begin ());
+
+result r (db.query<employee_name> (
+  query::employed_by->name == "Simple Tech Ltd"));
+
+t.commit ();
+  
+ +

To get this behavior, we would instead need to associate the + employer object with this view and then use the + query::employer::name expression instead of + query::employed_by->name.

+ +

As we have discussed above, if specified, an object alias is + used instead of the object name in the join condition, data + member references in the db column pragma, + as well as to name the query members scope. The object alias + is also used as a table name alias in the underlying + SELECT statement generated by the ODB compiler. + Normally, you would not use the table alias directly with + object views. However, if for some reason you need to refer + to a table column directly, for example, as part of a native + 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

+ +

A table view is similar to an object view except that it is + based on one or more database tables instead of persistent + objects. Table views are primarily useful when dealing with + ad-hoc tables that are not mapped to persistent classes.

+ +

To associate one or more tables with a view we use the + db table pragma (Section 11.2.2, + "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 + employee_extra legacy table we have defined at the + beginning of the chapter.

+ +
+#pragma db view table("employee_extra")
+struct employee_vacation
+{
+  #pragma db column("employee_id") type("INTEGER")
+  unsigned long employee_id;
+
+  #pragma db column("vacation_days") type("INTEGER")
+  unsigned short vacation_days;
+};
+  
+ +

Besides the table name in the db table pragma + we also have to specify the column name for each view data + member. Note that unlike for object views, the ODB compiler + does not try to automatically come up with column names for + table views. Furthermore, we cannot use references to object + members either, since there are no associated objects in table + views. Instead, the actual column name or column expression + must be specified as a string literal. The column name can + also be qualified with a table name either in the + "table.column" form or, if either a table + or a column name contains a period, in the + "table"."column" form. The following example + illustrates the use of a column expression:

+ +
+#pragma db view table("employee_extra")
+struct employee_max_vacation
+{
+  #pragma db column("max(vacation_days)") type("INTEGER")
+  unsigned short max_vacation_days;
+};
+  
+ +

Note also that in the above examples we specified the SQL type + for each of the columns to make sure that the ODB compiler + has knowledge of the actual types as specified in the database + schema. This is required to obtain correct and optimal + generated code.

+ + +

The complete syntax of the db table pragma + is similar to the db object pragma and is shown + below:

+ +

table("name" + [= "alias"] + [: join-condition])

+ +

The name part is a database table name. The optional + alias part gives this table an alias. If provided, the + alias must be used instead of the table whenever a reference + to a table is used. Contexts where such a reference may + be needed include the join condition (discussed below), + 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 + while the first associated table can have an alias, it cannot have + a join condition.

+ +

Similar to object views, for each subsequent associated table the + ODB compiler needs a join condition. However, unlike for object views, + for table views the ODB compiler does not try to come up with one + automatically. Furthermore, we cannot use references to object + members corresponding to object relationships either, since there + are no associated objects in table views. Instead, for each + subsequent associated table, a join condition must be + specified as a custom query expression. While the syntax of the + query expression is the same as in the query facility used to query + the database for objects (Chapter 4, "Querying the + Database"), a join condition for a table is normally specified + as a single string literal containing a native SQL query expression.

+ +

As an example of a multi-table view, consider the + employee_health table that we define in addition + to employee_extra:

+ +
+CREATE TABLE employee_health(
+  employee_id INTEGER NOT NULL,
+  sick_leave_days INTEGER NOT NULL)
+  
+ +

Given these two tables we can now define a view that returns both + the vacation and sick leave information for each employee:

+ +
+#pragma db view table("employee_extra" = "extra") \
+  table("employee_health" = "health": \
+        "extra.employee_id = health.employee_id")
+struct employee_leave
+{
+  #pragma db column("extra.employee_id") type("INTEGER")
+  unsigned long employee_id;
+
+  #pragma db column("vacation_days") type("INTEGER")
+  unsigned short vacation_days;
+
+  #pragma db column("sick_leave_days") type("INTEGER")
+  unsigned short sick_leave_days;
+};
+  
+ +

Querying the database for a table view is the same as for an + object view except that we can only use native query expressions. + For example:

+ +
+typedef odb::query<employee_leave> query;
+typedef odb::result<employee_leave> result;
+
+transaction t (db.begin ());
+
+unsigned short v_min = ...
+unsigned short l_min = ...
+
+result r (db.query<employee_leave> (
+  "vacation_days > " + query::_val(v_min) + "AND"
+  "sick_leave_days > " + query::_val(l_min)));
+
+t.commit ();
+  
+ + +

9.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 + from the previous section to return the employee's first + and last names instead of the employee id. To achieve this we + have to associate both the employee object and + the employee_extra table with the view:

+ +
+#pragma db view object(employee) \
+  table("employee_extra" = "extra": "extra.employee_id = " + employee::id_)
+struct employee_vacation
+{
+  std::string first;
+  std::string last;
+
+  #pragma db column("extra.vacation_days") type("INTEGER")
+  unsigned short vacation_days;
+};
+  
+ +

When querying the database for a mixed view, we can use query members + for the parts of the query expression that involves object members + but have to fall back to using the native syntax for the parts that + involve table columns. For example:

+ +
+typedef odb::query<employee_vacation> query;
+typedef odb::result<employee_vacation> result;
+
+transaction t (db.begin ());
+
+result r (db.query<employee_vacation> (
+  (query::last == "Doe") + "AND extra.vacation_days <> 0"));
+
+for (result::iterator i (r.begin ()); i != r.end (); ++i)
+  cout << i->first << " " << i->last << " " << i->vacation_days << endl;
+
+t.commit ();
+  
+ +

As another example, consider a more advanced view that associates + two objects via a legacy table. This view allows us to find the + previous employer name for each employee:

+ +
+#pragma db view object(employee) \
+  table("employee_extra" = "extra": "extra.employee_id = " + employee::id_) \
+  object(employer: "extra.previous_employer_id = " + employer::id_)
+struct employee_prev_employer
+{
+  std::string first;
+  std::string last;
+
+  // If previous_employer_id is NULL, then the name will be NULL as well.
+  // We use the odb::nullable wrapper to handle this.
+  //
+  #pragma db column(employer::name_)
+  odb::nullable<std::string> prev_employer_name;
+};
+  
+ +

9.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 11.2.3, + "query").

+ +

As an example, consider a view that returns some information about + all the employees that are over a predefined retirement age. + One way to implement this would be to define a standard object + view as we have done in the previous sections and then use a + query like this:

+ +
+result r (db.query<employee_retirement> (query::age > 50));
+  
+ +

The problem with the above approach is that we have to keep + repeating the query::age > 50 expression every + time we execute the query, even though this expression always + stays the same. View query conditions allow us to solve this + problem. For example:

+ +
+#pragma db view object(employee) query(employee::age > 50)
+struct employee_retirement
+{
+  std::string first;
+  std::string last;
+  unsigned short age;
+};
+  
+ +

With this improvement we can rewrite our query like this:

+ +
+result r (db.query<employee_retirement> ());
+  
+ +

But what if we may also need to restrict the result set based on + some varying criteria, such as the employee's last name? Or, in other + words, we may need to combine a constant query expression specified + in the db query pragma with the varying expression + specified at the query execution time. To allow this, the + db query pragma syntax supports the use of a special + (?) placeholder that indicates the position in the + constant query expression where the runtime expression should be + inserted. For example:

+ +
+#pragma db view object(employee) query(employee::age > 50 && (?))
+struct employee_retirement
+{
+  std::string first;
+  std::string last;
+  unsigned short name;
+};
+  
+ +

With this change we can now use additional query criteria in our + view:

+ +
+result r (db.query<employee_retirement> (query::last == "Doe"));
+  
+ +

The syntax of the expression in a query condition is the same as in + the query facility used to query the database for objects + (Chapter 4, "Querying the Database") except for + two differences. Firstly, for query members, instead of + using odb::query<object>::member names, we refer + directly to object members, using the object alias instead of the + object name if an alias was assigned. Secondly, query conditions + support the special (?) placeholder which can be used + both in the C++-integrated query expressions as was shown above + and in native SQL expressions specified as string literals. The + following view is an example of the latter case:

+ +
+#pragma db view table("employee_extra") \
+  query("vacation_days <> 0 AND (?)")
+struct employee_vacation
+{
+  ...
+};
+  
+ +

Another common use case for query conditions are views with the + ORDER BY or GROUP BY clause. Such + clauses are normally present in the same form in every query + involving such views. As an example, consider an aggregate + view which calculate the minimum and maximum ages of employees + for each employer:

+ +
+#pragma db view object(employee) object(employer) \
+  query ((?) + "GROUP BY" + employer::name_)
+struct employer_age
+{
+  #pragma db column(employer::name_)
+  std::string employer_name;
+
+  #pragma db column("min(" + employee::age_ + ")")
+  unsigned short min_age;
+
+  #pragma db column("max(" + employee::age_ + ")")
+  unsigned short max_age;
+};
+  
+ +

9.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 + SQL queries. Native views don't have associated tables or objects. + Instead, we use the db query pragma to specify + 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:

+ +
+#pragma db view query("SELECT employee_id, vacation_days " \
+                      "FROM employee_extra")
+struct employee_vacation
+{
+  #pragma db type("INTEGER")
+  unsigned long employee_id;
+
+  #pragma db type("INTEGER")
+  unsigned short vacation_days;
+};
+  
+ +

In native views the columns in the query select-list are + associated with the view data members in the order specified. + That is, the first column is stored in the first member, the + second column — in the second member, and so on. The ODB compiler + does not perform any error checking in this association. As a result + you must make sure that the number and order of columns in the + query select-list match the number and order of data members + in the view. This is also the reason why we are not + required to provide the column name for each data member in native + views, as is the case for object and table views.

+ +

Note also that while it is always possible to implement a table + view as a native view, the table views must be preferred since + they are safer. In a native view, if you add, remove, or + rearrange data members without updating the column list in the + query, or vice versa, at best, this will result in a runtime + error. In contrast, in a table view such changes will result + in the query being automatically updated.

+ +

Similar to object and table views, the query specified for + a native view can contain the special (?) + placeholder which is replaced with the query expression + specified at the query execution time. + If the native query does not contain a placeholder, as in + the example above, then any query expression specified at + the query execution time is appended to the query text + along with the WHERE keyword, if required. + The following example shows the usage of the placeholder:

+ +
+#pragma db view query("SELECT employee_id, vacation_days " \
+                      "FROM employee_extra " \
+                      "WHERE vacation_days <> 0 AND (?)")
+struct employee_vacation
+{
+  ...
+};
+  
+ +

As another example, consider a view that returns the next + value of a database sequence:

+ +
+#pragma db view query("SELECT nextval('my_seq')")
+struct sequence_value
+{
+  unsigned long long value;
+};
+  
+ +

While this implementation can be acceptable in some cases, it has + a number of drawbacks. Firstly, the name of the sequence is + fixed in the view, which means if we have a second sequence, we + will have to define another, almost identical view. Similarly, + the operation that we perform on the sequence is also fixed. + In some situations, instead of returning the next value, we may + need the last value.

+ +

Note that we cannot use the placeholder mechanism to resolve + these problems since placeholders can only be used in the + WHERE, GROUP BY, and similar + clauses. In other words, the following won't work:

+ +
+#pragma db view query("SELECT nextval('(?)')")
+struct sequence_value
+{
+  unsigned long long value;
+};
+
+result r (db.query<sequence_value> ("my_seq"));
+  
+ +

To support these kinds of use cases, ODB allows us to specify the + complete query for a native view at runtime rather than at the view + definition. To indicate that a native view has a runtime query, + we can either specify the empty db query + pragma or omit the pragma altogether. For example:

+ +
+#pragma db view
+struct sequence_value
+{
+  unsigned long long value;
+};
+  
+ +

Given this view, we can perform the following queries:

+ +
+typedef odb::query<sequence_value> query;
+typedef odb::result<sequence_value> result;
+
+string seq_name = ...
+
+result l (db.query<sequence_value> (
+  "SELECT lastval('" + seq_name + "')"));
+
+result n (db.query<sequence_value> (
+  "SELECT nextval('" + seq_name + "')"));
+  
+ + +

9.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 + object pointers. If you need to access data from a pointed-to + object, then you will need to associate such an object with + the view. Similarly, view data members cannot be containers. + These two limitations also apply to composite value types that + contain object pointers or containers. Such composite values + cannot be used as view data members.

+ +

On the other hand, composite values that do not contain object + pointers or containers can be used in views. As an example, + consider a modified version of the employee persistent + class that stores a person's name as a composite value:

+ +
+#pragma db value
+class person_name
+{
+  std::string first_;
+  std::string last_;
+};
+
+#pragma db object
+class employee
+{
+  ...
+
+  person_name name_;
+
+  ...
+};
+  
+ +

Given this change, we can re-implement the employee_name + view like this:

+ +
+#pragma db view object(employee)
+struct employee_name
+{
+  person_name name;
+};
+  
+ +

It is also possible to extract some or all of the nested members + of a composite value into individual view data members. Here is + how we could have defined the employee_name view + if we wanted to keep its original structure:

+ +
+#pragma db view object(employee)
+struct employee_name
+{
+  #pragma db column(employee::name.first_)
+  std::string first;
+
+  #pragma db column(employee::name.last_)
+  std::string last;
+};
+  
+ + + + + +
+

10 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 @@ -6002,7 +7172,7 @@ namespace odb it could be useful in some cases, for example, to find out whether an object has already been loaded.

-

9.1 Object Cache

+

10.1 Object Cache

A session is an object cache. Every time an object is made persistent by calling the database::persist() function @@ -6012,7 +7182,7 @@ namespace odb or loaded by iterating over a query result (Section 4.4, "Query Result"), the pointer to the persistent object, in the form of the canonical object pointer (Section 3.2, "Object - Pointers"), is stored in the session. For as long as the + and View Pointers"), is stored in the session. For as long as the session is in effect, any subsequent calls to load the same object will return the cached instance. When an object's state is deleted from the database with the database::erase() function @@ -6087,7 +7257,7 @@ unsigned long id2 (save (db, p2)); // p2 is cached in s as non-const.


-

10 ODB Pragma Language

+

11 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. @@ -6103,13 +7273,14 @@ unsigned long id2 (save (db, p2)); // p2 is cached in s as non-const.

The qualifier tells the ODB compiler what kind of C++ construct this pragma describes. Valid qualifiers are object, - value, and member. Pragmas with the - object qualifier describe persistent object types. - It tells the ODB compiler that the C++ class it describes is a - persistent class. Similarly, pragmas with the value + view, value, and member. + A pragma with the object qualifier describes a persistent + object type. It tells the ODB compiler that the C++ class it + describes is a persistent class. Similarly, pragmas with the + view qualifier describe view types, the value qualifier describes value types and the member - qualifier is used to describe data members of persistent object - and value types.

+ qualifier is used to describe data members of persistent object, + view, and value types.

The specifier informs the ODB compiler about a particular database-related property of the C++ declaration. For example, the @@ -6250,10 +7421,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 10.4, + at the end of this chapter in Section 11.5, "C++ Compiler Warnings".

-

10.1 Object Type Pragmas

+

11.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, @@ -6270,30 +7441,30 @@ class person

table table name for a persistent class10.1.111.1.1
pointer pointer type for a persistent class10.1.211.1.2
abstract persistent class is abstract10.1.311.1.3
callback database operations callback10.1.411.1.4
-

10.1.1 table

+

11.1.1 table

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

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

-

10.1.2 pointer

+

11.1.2 pointer

The pointer specifier specifies the object pointer type for a persistent class. The object pointer type is used to return, @@ -6358,9 +7529,9 @@ class person either, then the raw pointer is used by default.

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

+ Section 3.2, "Object and View Pointers".

-

10.1.3 abstract

+

11.1.3 abstract

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

-

10.1.4 callback

+

11.1.4 callback

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

10.2 Value Type Pragmas

+

11.2 View Type Pragmas

+ +

A pragma with the view qualifier declares a C++ class + as a view type. The qualifier can be optionally followed, + in any order, by one or more specifiers summarized in the + table below:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SpecifierSummarySection
objectobject associated with a view11.2.1
tabletable associated with a view11.2.2
queryview query condition11.2.3
pointerpointer type for a view11.2.4
callbackdatabase operations callback11.2.5
+ +

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

+ +

11.2.1 object

+ +

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

+ +

11.2.2 table

+ +

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

+ +

11.2.3 query

+ +

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 + Query Conditions". For more information on native SQL queries, + refer to Section 9.5, "Native Views".

+ +

11.2.4 pointer

+ +

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

+ +

11.2.5 callback

+ +

The callback specifier specifies the view class + member function that should be called before and after an + instance of this view class is created as part of the query + result iteration. The semantics of the callback + specifier for a view are similar to those of the + callback specifier for an object + (Section 11.1.4, "callback") + except that the only events that can trigger a callback + call in the case of a view are pre_load and + post_load.

+ + +

11.3 Value Type Pragmas

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

type database type for a value type10.2.111.3.1
id_type database type for a value type when used as an object id10.2.211.3.2
null/not_null type can/cannot be NULL10.2.311.3.3
default default value for a value type10.2.411.3.4
options database options for a value type10.2.511.3.5
unordered ordered container should be stored unordered10.2.611.3.6
index_type database type for a container's index type10.2.711.3.7
key_type database type for a container's key type10.2.811.3.8
value_type database type for a container's value type10.2.911.3.9
value_null/value_not_null container's value can/cannot be NULL10.2.1011.3.10
id_options database options for a container's id column10.2.1111.3.11
index_options database options for a container's index column10.2.1211.3.12
key_options database options for a container's key column10.2.1311.3.13
value_options database options for a container's value column10.2.1411.3.14
id_column column name for a container's object id10.2.1511.3.15
index_column column name for a container's index10.2.1611.3.16
key_column column name for a container's key10.2.1711.3.17
value_column column name for a container's value10.2.1811.3.18

Many of the value type specifiers have corresponding member type - specifiers with the same names (Section 10.3, + specifiers with the same names (Section 11.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 @@ -6645,7 +7913,7 @@ private: take precedence over and override parameters specified with value specifiers.

-

10.2.1 type

+

11.3.1 type

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

@@ -6667,8 +7935,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 - 10.2.3, "null/not_null") specifiers + null and not_null (Section + 11.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 @@ -6695,13 +7963,13 @@ class person mapping example in the odb-examples package shows how to do this for all the supported database systems.

-

10.2.2 id_type

+

11.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 10.3.1, + object identifiers (Section 11.4.1, "id"). In combination with the type - specifier (Section 10.2.1, "type") + specifier (Section 11.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:

@@ -6736,7 +8004,7 @@ class person }; -

10.2.3 null/not_null

+

11.3.3 null/not_null

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

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

-

10.2.4 default

+

11.3.4 default

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

@@ -6818,10 +8086,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 10.3.5, + data member (Section 11.4.5, "default").

-

10.2.5 options

+

11.3.5 options

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

-

10.2.6 unordered

+

11.3.6 unordered

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

-

10.2.7 index_type

+

11.3.7 index_type

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

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

10.2.8 key_type

+

11.3.8 key_type

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

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

10.2.9 value_type

+

11.3.9 value_type

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

@@ -6904,18 +8172,18 @@ typedef std::vector<std::string> names;
   

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

-

10.2.10 value_null/value_not_null

+

11.3.10 value_null/value_not_null

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

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

-

10.2.11 id_options

+

11.3.11 id_options

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

-

10.2.12 index_options

+

11.3.12 index_options

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

-

10.2.13 key_options

+

11.3.13 key_options

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

-

10.2.14 value_options

+

11.3.14 value_options

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

-

10.2.15 id_column

+

11.3.15 id_column

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

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

-

10.2.16 index_column

+

11.3.16 index_column

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

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

-

10.2.17 key_column

+

11.3.17 key_column

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

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

-

10.2.18 value_column

+

11.3.18 value_column

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

10.3 Data Member Pragmas

+

11.4 Data Member Pragmas

A pragma with the member qualifier or a positioned pragma without a qualifier describes a data member. It can @@ -7081,145 +8349,151 @@ typedef std::map<unsigned short, float> age_weight_map;

id member is an object id10.3.111.4.1
auto id is assigned by the database10.3.211.4.2
type database type for a member10.3.311.4.3
null/not_null member can/cannot be NULL10.3.411.4.4
default default value for a member10.3.511.4.5
options database options for a member10.3.611.4.6
columncolumn name for a member10.3.7column name for a member of an object or composite value11.4.7
columncolumn name for a member of a view11.4.8
transient member is not stored in the database10.3.811.4.9
inverse member is an inverse side of a bidirectional relationship10.3.911.4.10
unordered ordered container should be stored unordered10.3.1011.4.11
table table name for a container10.3.1111.4.12
index_type database type for a container's index type10.3.1211.4.13
key_type database type for a container's key type10.3.1311.4.14
value_type database type for a container's value type10.3.1411.4.15
value_null/value_not_null container's value can/cannot be NULL10.3.1511.4.16
id_options database options for a container's id column10.3.1611.4.17
index_options database options for a container's index column10.3.1711.4.18
key_options database options for a container's key column10.3.1811.4.19
value_options database options for a container's value column10.3.1911.4.20
id_column column name for a container's object id10.3.2011.4.21
index_column column name for a container's index10.3.2111.4.22
key_column column name for a container's key10.3.2211.4.23
value_column column name for a container's value10.3.2311.4.24

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

-

10.3.1 id

+

11.4.1 id

The id specifier specifies that a data member contains the object id. Every persistent class must have a member designated @@ -7249,7 +8523,10 @@ class person

In a relational database, an identifier member is mapped to a primary key.

-

10.3.2 auto

+

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

+ +

11.4.2 auto

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

For additional information on the automatic identifier assignment, refer to Section 3.7, "Making Objects Persistent".

-

10.3.3 type

+

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

+ +

11.4.3 type

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

@@ -7292,11 +8572,11 @@ class person }; -

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

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

-

10.3.4 null/not_null

+

11.4.4 null/not_null

The null and not_null specifiers specify that a data member can or cannot be NULL, respectively. @@ -7308,8 +8588,8 @@ class person not allow NULL values, depending on the semantics of each value type. Consult the relevant documentation to find out more about the NULL semantics for such value - types. A data member containing the object id (Section - 10.3.1, "id" ) is automatically treated as not + types. A data member containing the object id (Section + 11.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:

@@ -7337,7 +8617,7 @@ class account

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

-

10.3.5 default

+

11.4.5 default

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

@@ -7372,8 +8652,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 - 10.3.6, "options") instead. For example:

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

 enum gender {male, female, undisclosed};
@@ -7426,7 +8706,7 @@ class person
   

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

@@ -7444,8 +8724,8 @@ class person }; -

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

A data member containing the object id (Section + 11.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 @@ -7456,8 +8736,10 @@ class person affect the generated database schemas and, in the context of ODB, are primarily useful for schema evolution.

+

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

-

10.3.6 options

+

11.4.6 options

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

Options can also be specified on the per-type basis - (Section 10.2.5, "options"). + (Section 11.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 @@ -7504,19 +8786,22 @@ class person

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

-

10.3.7 column

+

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

+ +

11.4.7 column (object, composite value)

The column specifier specifies the column name - that should be used to store a data member in a relational database. - For example:

+ that should be used to store a data member of a persistent class + or composite value type in a relational database. For example:

 #pragma db object
@@ -7533,11 +8818,20 @@ class person
      specifies the column name prefix. Refer to Section 7.2.1,
      "Composite Value Column and Table Names" for details.

-

If the column name is not specified, it is derived from the member - name by removing the common data member name decorations, such as leading - and trailing underscores, the m_ prefix, etc.

+

If the column name is not specified, it is derived from the member's + so-called public name. A public member name is obtained by removing + the common data member name decorations, such as leading and trailing + underscores, the m_ prefix, etc.

+ +

11.4.8 column (view)

+ +

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

-

10.3.8 transient

+

11.4.9 transient

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

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

-

10.3.9 inverse

+

11.4.10 inverse

The inverse specifier specifies that a data member of an object pointer or a container of object pointers type is an @@ -7597,12 +8891,12 @@ class person relationship information. Only ordered and set containers can be used for inverse members. If an inverse member is of an ordered container type, it is automatically marked as unordered - (Section 10.3.10, "unordered").

+ (Section 11.4.11, "unordered").

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

-

10.3.10 unordered

+

11.4.11 unordered

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

-

10.3.11 table

+

11.4.12 table

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

@@ -7643,7 +8937,7 @@ class person

If the table name is not specified, then the container table name is constructed by concatenating the object's table name, underscore, - and the sanitized member name. The sanitized member name is obtained + and the public member name. The public member name is obtained by removing the common member name decorations, such as leading and trailing underscores, the m_ prefix, etc. In the example above, without the table specifier, the container's @@ -7655,13 +8949,13 @@ class person to Section 7.2.1, "Composite Value Column and Table Names" for details.

-

10.3.12 index_type

+

11.4.13 index_type

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

@@ -7675,13 +8969,13 @@ class person
 };
   
-

10.3.13 key_type

+

11.4.14 key_type

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

@@ -7695,13 +8989,13 @@ class person
 };
   
-

10.3.14 value_type

+

11.4.15 value_type

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

@@ -7716,18 +9010,18 @@ class person
   

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

-

10.3.15 value_null/value_not_null

+

11.4.16 value_null/value_not_null

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

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

-

10.3.16 id_options

+

11.4.17 id_options

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

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

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

-

10.3.17 index_options

+

11.4.18 index_options

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

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

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

-

10.3.18 key_options

+

11.4.19 key_options

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

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

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

-

10.3.19 value_options

+

11.4.20 value_options

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

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

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

-

10.3.20 id_column

+

11.4.21 id_column

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

@@ -7864,14 +9158,14 @@ class person
   

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

-

10.3.21 index_column

+

11.4.22 index_column

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

@@ -7888,14 +9182,14 @@ class person
   

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

-

10.3.22 key_column

+

11.4.23 key_column

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

@@ -7912,14 +9206,14 @@ class person
   

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

-

10.3.23 value_column

+

11.4.24 value_column

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

@@ -7936,7 +9230,7 @@ class person
   

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

-

10.4 C++ Compiler Warnings

+

11.5 C++ Compiler Warnings

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

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

-

10.4.1 GNU C++

+

11.5.1 GNU C++

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

-

10.4.2 Visual C++

+

11.5.2 Visual C++

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

-

10.4.3 Sun C++

+

11.5.3 Sun C++

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

-

10.4.4 IBM XL C++

+

11.5.4 IBM XL C++

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

-

10.4.5 HP aC++

+

11.5.5 HP aC++

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

- - - + + +
11MySQL Database
12SQLite Database
13PostgreSQL Database
12MySQL Database
13SQLite Database
14PostgreSQL Database
@@ -8093,7 +9387,7 @@ aCC +W2161 ...
-

11 MySQL Database

+

12 MySQL Database

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

-

11.1 MySQL Type Mapping

+

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

@@ -8222,7 +9516,7 @@ aCC +W2161 ... std::vector<char> will be treated as a container). To enable the BLOB mapping for this type we need to specify the database type explicitly using the db type - pragma (Section 10.3.3, "type"), + pragma (Section 11.4.3, "type"), for example:

@@ -8278,7 +9572,7 @@ class object
 };
   
-

11.2 MySQL Database Class

+

12.2 MySQL Database Class

The MySQL database class has the following interface:

@@ -8439,7 +9733,7 @@ namespace odb

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

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

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

-

11.3 MySQL Connection and Connection Factory

+

12.3 MySQL Connection and Connection Factory

The mysql::connection class has the following interface:

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

11.4 MySQL Exceptions

+

12.4 MySQL Exceptions

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

@@ -8710,7 +10004,7 @@ namespace odb
-

12 SQLite Database

+

13 SQLite Database

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

-

12.1 SQLite Type Mapping

+

13.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 10, "ODB Pragma + Pragma Language (Chapter 11, "ODB Pragma Language").

@@ -8832,7 +10126,7 @@ namespace odb std::vector<char> will be treated as a container). To enable the BLOB mapping for this type we need to specify the database type explicitly using the db type - pragma (Section 10.3.3, "type"), + pragma (Section 11.4.3, "type"), for example:

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

-

12.2 SQLite Database Class

+

13.2 SQLite Database Class

The SQLite database class has the following interface:

@@ -8933,7 +10227,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 12.5.3, + should be enabled. See Section 13.5.3, "Foreign Key Constraints" for more information on foreign keys.

@@ -8981,7 +10275,7 @@ auto_ptr<odb::database> db (

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

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

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

-

12.3 SQLite Connection and Connection Factory

+

13.3 SQLite Connection and Connection Factory

The sqlite::connection class has the following interface:

@@ -9057,7 +10351,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 12.2, + sqlite::database class (Section 13.2, "SQLite Database Class"). The handle() accessor returns the SQLite handle corresponding to the connection.

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

12.4 SQLite Exceptions

+

13.4 SQLite Exceptions

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

@@ -9310,12 +10604,12 @@ namespace odb of an error.

-

12.5 SQLite Limitations

+

13.5 SQLite Limitations

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

-

12.5.1 Query Result Caching

+

13.5.1 Query Result Caching

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

-

12.5.2 Automatic Assignment of Object Ids

+

13.5.2 Automatic Assignment of Object Ids

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

@@ -9356,7 +10650,7 @@ class person
 };
 
-

12.5.3 Foreign Key Constraints

+

13.5.3 Foreign Key Constraints

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

12.5.4 Constraint Violations

+

13.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 @@ -9428,7 +10722,7 @@ CREATE TABLE Employee ( object_not_persistent exception (Section 3.12, "ODB Exceptions").

-

12.5.5 Sharing of Queries

+

13.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 @@ -9442,7 +10736,7 @@ CREATE TABLE Employee (


-

13 PostgreSQL Database

+

14 PostgreSQL Database

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

-

13.1 PostgreSQL Type Mapping

+

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

@@ -9564,12 +10858,12 @@ CREATE TABLE Employee (

The PostgreSQL ODB runtime library also provides support for mapping the - std::vector<char> type to the PostgreSQL BYTEA type. - However, this mapping is not enabled by default (by default, + std::vector<char> type to the PostgreSQL BYTEA + type. However, this mapping is not enabled by default (by default, std::vector<char> will be treated as a container). - To enable the BYTEA mapping for this type we need to specify + To enable the BYTEA mapping for this type we need to specify the database type explicitly using the db type - pragma (Section 10.3.3, "type"), + pragma (Section 11.4.3, "type"), for example:

@@ -9611,7 +10905,7 @@ class object
      the most significant bit of the actual unsigned value being
      persisted.

-

13.2 PostgreSQL Database Class

+

14.2 PostgreSQL Database Class

The PostgreSQL database class has the following interface:

@@ -9732,7 +11026,7 @@ namespace odb

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

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

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

-

13.3 PostgreSQL Connection and Connection Factory

+

14.3 PostgreSQL Connection and Connection Factory

The pgsql::connection class has the following interface:

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

13.4 PostgreSQL Exceptions

+

14.4 PostgreSQL Exceptions

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

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

-

13.5 PostgreSQL Limitations

+

14.5 PostgreSQL Limitations

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

-

13.5.1 Query Result Caching

+

14.5.1 Query Result Caching

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

-

13.5.2 Foreign Key Constraints

+

14.5.2 Foreign Key Constraints

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

13.5.3 Date-Time Format

+

14.5.3 Date-Time Format

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

13.5.4 Timezones

+

14.5.4 Timezones

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

-

13.5.5 NUMERIC Type Support

+

14.5.5 NUMERIC Type Support

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

- - - + + +
14Profiles Introduction
15Boost Profile
16Qt Profile
15Profiles Introduction
16Boost Profile
17Qt Profile
@@ -10070,7 +11364,7 @@ SHOW integer_datetimes
-

14 Profiles Introduction

+

15 Profiles Introduction

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


-

15 Boost Profile

+

16 Boost Profile

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

-

15.1 Smart Pointers Library

+

16.1 Smart Pointers Library

The smart-ptr sub-profile provides persistence support for a subset of smart pointers from the Boost @@ -10159,9 +11453,9 @@ odb --profile boost/date-time ...

The currently supported smart pointers are boost::shared_ptr and boost::weak_ptr. For - more information on using smart pointers as pointers to objects, - refer to Section 3.2, "Object Pointers" and - Chapter 6, "Relationships". For more information + more information on using smart pointers as pointers to objects and + views, refer to Section 3.2, "Object and View Pointers" + and Chapter 6, "Relationships". For more information on using smart pointers as pointers to values, refer to Section 7.3, "Pointers and NULL Value Semantics". When used as a pointer to a value, only @@ -10211,15 +11505,15 @@ class employee

Besides providing persistence support for the above smart pointers, - the smart-ptr sub-profile also changes the default object - pointer (Section 3.2, "Object Pointers") - to boost::shared_ptr. In particular, this means that - database functions that return dynamically allocated objects will return - them as boost::shared_ptr pointers. To override this - behavior, add the --default-pointer option specifying the - alternative object pointer after the --profile option.

+ the smart-ptr sub-profile also changes the default + pointer (Section 3.2, "Object and View Pointers") + to boost::shared_ptr. In particular, this means that + database functions that return dynamically allocated objects and views + will return them as boost::shared_ptr pointers. To override + this behavior, add the --default-pointer option specifying + the alternative pointer type after the --profile option.

-

15.2 Unordered Containers Library

+

16.2 Unordered Containers Library

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

15.3 Optional Library

+

16.3 Optional Library

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

-

15.4 Date Time Library

+

16.4 Date Time Library

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

-

15.4.1 MySQL Database Type Mapping

+

16.4.1 MySQL Database Type Mapping

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

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

-

15.4.2 SQLite Database Type Mapping

+

16.4.2 SQLite Database Type Mapping

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

@@ -10489,7 +11783,7 @@ class person
      will result in the out_of_range exception.

-

15.4.3 PostgreSQL Database Type Mapping

+

16.4.3 PostgreSQL Database Type Mapping

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


-

16 Qt Profile

+

17 Qt Profile

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

-

16.1 Basic Types

+

17.1 Basic Types

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

-

16.1.1 MySQL Database Type Mapping

+

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

@@ -10630,7 +11924,7 @@ class Person it is mapped to TEXT.

-

16.1.2 SQLite Database Type Mapping

+

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

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

-

16.1.3 PostgreSQL Database Type Mapping

+

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

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

-

16.2 Smart Pointers

+

17.2 Smart Pointers

The smart-ptr sub-profile provides persistence support the Qt smart pointers. To enable only this profile, pass @@ -10699,11 +11993,11 @@ class Person

The currently supported smart pointers are QSharedPointer and QWeakPointer. - For more information on using smart pointers as pointers to objects, - refer to Section 3.2, "Object Pointers" and - Chapter 6, "Relationships". For more information - on using smart pointers as pointers to values, refer to - Section 7.3, "Pointers and NULL Value + For more information on using smart pointers as pointers to objects + and views, refer to Section 3.2, "Object and View + Pointers" and Chapter 6, "Relationships". For + more information on using smart pointers as pointers to values, refer + to Section 7.3, "Pointers and NULL Value Semantics". When used as a pointer to a value, only QSharedPointer is supported. For example:

@@ -10751,15 +12045,15 @@ class Employee

Besides providing persistence support for the above smart pointers, - the smart-ptr sub-profile also changes the default object - pointer (Section 3.2, "Object Pointers") + the smart-ptr sub-profile also changes the default + pointer (Section 3.2, "Object and View Pointers") to QSharedPointer. In particular, this means that - database functions that return dynamically allocated objects will return - them as QSharedPointer pointers. To override this - behavior, add the --default-pointer option specifying the - alternative object pointer after the --profile option.

+ database functions that return dynamically allocated objects and views + will return them as QSharedPointer pointers. To override + this behavior, add the --default-pointer option specifying + the alternative pointer type after the --profile option.

-

16.3 Containers Library

+

17.3 Containers Library

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

16.4 Date Time Types

+

17.4 Date Time Types

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

-

16.4.1 MySQL Database Type Mapping

+

17.4.1 MySQL Database Type Mapping

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

@@ -10877,7 +12171,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 10.3.3, "type"), as shown in + (Section 11.4.3, "type"), as shown in the following example:

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

-

16.4.2 SQLite Database Type Mapping

+

17.4.2 SQLite Database Type Mapping

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

@@ -10939,7 +12233,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 10.3.3, "type"), as shown + (Section 11.4.3, "type"), as shown in the following example:

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

-

16.4.3 PostgreSQL Database Type Mapping

+

17.4.3 PostgreSQL Database Type Mapping

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

-- cgit v1.1