From 0441240d2c06cebeffc285d6a7c74de1a19afafe Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 4 Aug 2011 13:34:04 +0200 Subject: Add documentation for new value wrappers New sections: 7.3, "NULL Value Semantics" and 15.3, "Optional Library". --- doc/manual.xhtml | 353 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 309 insertions(+), 44 deletions(-) (limited to 'doc') diff --git a/doc/manual.xhtml b/doc/manual.xhtml index c44c144..1b7b4a7 100644 --- a/doc/manual.xhtml +++ b/doc/manual.xhtml @@ -381,9 +381,17 @@ for consistency. - 7Composite Value Types + 7Value Types - + + + + +
7.1Composite Value Column and Table Names
7.1Simple Value Types
7.2Composite Value Types + + +
7.2.1Composite Value Column and Table Names
+
7.3NULL Value Semantics
@@ -557,12 +565,13 @@ for consistency. + - @@ -707,7 +716,7 @@ for consistency. - + @@ -1790,7 +1799,8 @@ Hello, Joe! contrast, a value can only be stored in the database as part of an object and doesn't have its own unique identifier.

-

An object consists of data members which are either values, pointers +

An object consists of data members which are either values + (Chapter 7, "Value Types"), pointers to other objects (Chapter 6, "Relationships"), or containers of values or pointers to other objects (Chapter 5, "Containers"). Pointers to other objects and containers can @@ -1804,9 +1814,11 @@ Hello, Joe! int or a class type, such as std::string. If a value consists of other values, then it is called a composite value and its type — a - composite value type. Otherwise, the value is + composite value type (Section 7.2, + "Composite Value Types"). Otherwise, the value is called simple value and its type — a - simple value type. Note that the distinction between + simple value type (Section 7.1, + "Simple Value Types"). Note that the distinction between simple and composite values is conceptual rather than representational. For example, std::string is a simple value type because conceptually string is a @@ -1937,7 +1949,7 @@ class name

Composite value types are discussed in more detail in - Chapter 7, "Composite Value Types".

+ Section 7.2, "Composite Value Types".

Normally, you would use object types to model real-world entities, things that have their own identity. For example, in the @@ -3537,8 +3549,9 @@ private: contents of the tables to which they are mapped are discussed in detail in the following sections.

-

Containers in ODB can contain simple value types, composite value - types (Chapter 7, "Composite Value Types"), and pointers +

Containers in ODB can contain simple value types (Section + 7.1, "Simple Value Types"), composite value types + (Section 7.2, "Composite Value Types"), and pointers to objects (Chapter 6, "Relationships"). Containers of containers, either directly or indirectly via a composite value type, are not allowed. A key in a map or multimap container can @@ -4847,9 +4860,28 @@ t.commit (); -


-

7 Composite Value Types

+

7 Value Types

+ +

In Section 3.1, "Concepts and Terminology" we have + already discussed the notion of values and value types as well as the + distinction between simple and composite values. This chapter covers + simple and composite value types in more detail.

+ +

7.1 Simple Value Types

+ +

A simple value type is a fundamental C++ type or a class type that + is mapped to a single database column. For each supported database + system the ODB compiler provides a default mapping to suitable + database types for most fundamental C++ types, such as int + or float as well as some class types, such as + std::string. For more information about the default + 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").

+ +

7.2 Composite Value Types

A composite value type is a class or struct type that is mapped to more than one database column. To declare @@ -4980,7 +5012,7 @@ result r (db->query<person> ( t.commit (); -

7.1 Composite Value Column and Table Names

+

7.2.1 Composite Value Column and Table Names

Customizing a column name for a data member of a simple value type is straightforward: we simply specify the desired name with @@ -5167,6 +5199,169 @@ CREATE TABLE person_nickname (

Similar to columns, we can make the table prefix empty.

+

7.3 NULL Value Semantics

+ +

Relational database systems have a notion of the special + NULL value that is used to indicate the absence + 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, + "null/not_null").

+ +

To properly support the NULL semantics, the + C++ value type must have a notion or a NULL + value or a similar special state concept. Most basic + C++ types, such as int or std::string, + do not have this notion and therefore cannot be used directly + for NULL-enabled data members (in the case of a + NULL value being loaded from the database, + such data members will be default-initialized).

+ +

To allow the easy conversion of value types that do not support + the NULL semantics into the ones that do, ODB + provides the odb::nullable class template. It + allows us to wrap an existing C++ type into a container-like + class that can either be NULL or contain a + value of the wrapped type. ODB also automatically enables + the NULL values for data members of the + odb::nullable type. For example:

+ +
+#include <odb/nullable.hxx>
+
+#pragma db object
+class person
+{
+  ...
+
+  std::string first_;                    // TEXT NOT NULL
+  odb::nullable<std::string> middle_;    // TEXT NULL
+  std::string last_;                     // TEXT NOT NULL
+};
+  
+ +

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

+ +
+namespace odb
+{
+  template <typename T>
+  class nullable
+  {
+  public:
+    typedef T value_type;
+
+    nullable ();
+    nullable (const T&);
+    nullable (const nullable&);
+    template <typename Y> explicit nullable (const nullable<Y>&);
+
+    nullable& operator= (const T&);
+    nullable& operator= (const nullable&);
+    template <typename Y> nullable& operator= (const nullable<Y>&);
+
+    void swap (nullable&);
+
+    // Accessor interface.
+    //
+    bool null () const;
+
+    T&       get ();
+    const T& get () const;
+
+    // Pointer interface.
+    //
+    operator bool_convertible () const;
+
+    T*       operator-> ();
+    const T* operator-> () const;
+
+    T&       operator* ();
+    const T& operator* () const;
+
+    void reset ();
+  };
+}
+  
+ +

The following example shows how we can use this interface:

+ +
+  nullable<string> ns;
+
+  // Using the accessor interface.
+  //
+  if (ns.null ())
+  {
+    s = "abc";
+  }
+  else
+  {
+    string s (ns.get ());
+    ns.reset ();
+  }
+
+  // The same using the pointer interface.
+  //
+  if (ns)
+  {
+    s = "abc";
+  }
+  else
+  {
+    string s (*ns);
+    ns.reset ();
+  }
+  
+ + +

The odb::nullable class template requires the wrapped + type to have public default and copy constructors as well as the + copy assignment operator. Note also that the odb::nullable + implementation is not the most efficient in that it always contains + a fully constructed value of the wrapped type. This is normally + not a concern for simple types such as the C++ fundamental + types or std::string. However, it may become + an issue for more complex types. In such cases you may want to + consider using a more efficient implementation of the + optional value concept such as the + optional class template from Boost + (Section 15.3, "Optional Library").

+ +

Another common C++ representation of a value that can be + NULL is a pointer. ODB will automatically + handle data members that are pointers to values, however, + it will not automatically enable NULL values + for such data members, as is the case for odb::nullable. + Instead, if the NULL value is desired, we will + need to enable it explicitly using the db null + pragma. For example:

+ +
+#pragma db object
+class person
+{
+  ...
+
+  std::string first_;
+
+  #pragma db null
+  std::auto_ptr<std::string> middle_;
+
+  std::string last_;
+};
+  
+ +

The ODB compiler includes built-in support for using + std::auto_ptr and std::tr1::shared_ptr + as pointers to values. 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").

+ @@ -6307,8 +6502,10 @@ typedef shared_ptr<person> person_ptr;

For a more detailed discussion of the NULL semantics - for the object pointers, refer to Chapter 6, - "Relationships".

+ for values, refer to Section 7.3, "NULL + Value Semantics". For a more detailed discussion of the + NULL semantics for object pointers, refer to + Chapter 6, "Relationships".

10.2.4 default

@@ -6857,8 +7054,10 @@ class account not_null specifier), then a warning is issued.

For a more detailed discussion of the NULL semantics - for the object pointers, refer to Chapter 6, - "Relationships".

+ for values, refer to Section 7.3, "NULL + Value Semantics". For a more detailed discussion of the + NULL semantics for object pointers, refer to + Chapter 6, "Relationships".

10.3.5 default

@@ -6893,22 +7092,22 @@ class person ... #pragma db default(null) - nullable<std::string> middle_; // DEFAULT NULL + odb::nullable<std::string> middle_; // DEFAULT NULL #pragma db default(false) - bool married_; // DEFAULT 0/FALSE + bool married_; // DEFAULT 0/FALSE #pragma db default(0.0) - float weight_; // DEFAULT 0.0 + float weight_; // DEFAULT 0.0 #pragma db default("Mr") - string title_; // DEFAULT 'Mr' + string title_; // DEFAULT 'Mr' #pragma db default(undisclosed) - gender gender_; // DEFAULT 2/'undisclosed' + gender gender_; // DEFAULT 2/'undisclosed' #pragma db options("DEFAULT CURRENT_TIMESTAMP()") - date timestamp_; // DEFAULT CURRENT_TIMESTAMP() + date timestamp_; // DEFAULT CURRENT_TIMESTAMP() }; @@ -7039,7 +7238,7 @@ class person

For a member of a composite value type, the column specifier - specifies the column name prefix. Refer to Section 7.1, + 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 @@ -7161,7 +7360,7 @@ class person

The table specifier can also be used for members of composite value types. In this case it specifies the table name prefix for container members inside the composite value type. Refer - to Section 7.1, "Composite Value Column and Table + to Section 7.2.1, "Composite Value Column and Table Names" for details.

10.3.12 index_type

@@ -9396,12 +9595,29 @@ odb --profile boost/date-time ... ODB compiler option.

The currently supported smart pointers are - boost::shared_ptr and boost::weak_ptr. For - more information on using smart pointers with ODB refer to - Section 3.2, "Object Pointers" and - Chapter 6, "Relationships". The smart-ptr - sub-profile also provides the lazy counterparts for the above - pointers: odb::boost::lazy_shared_ptr and + 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 + on using smart pointers as pointers to values, refer to + Section 7.3, "NULL Value Semantics". + When used as a pointer to a value, only boost::shared_ptr + is supported. For example:

+ +
+#pragma db object
+class person
+{
+  ...
+
+  #pragma db null
+  boost::shared_ptr<std::string> middle_name_;
+};
+  
+ +

To provide finer grained control over object relationship loading, + the smart-ptr sub-profile also provides the lazy + counterparts for the above pointers: odb::boost::lazy_shared_ptr and odb::boost::lazy_weak_ptr. You will need to include the <odb/boost/lazy-ptr.hxx> header file to make the lazy variants available in your application. For the description of the lazy @@ -9466,7 +9682,39 @@ class person }; -

15.3 Date Time Library

+

15.3 Optional Library

+ +

The optional sub-profile provides persistence support for + the boost::optional container from the Boost + optional library. To enable only this profile, pass + boost/optional to the --profile ODB compiler + option.

+ +

In a relational database boost::optional is mapped to + a column that can have a NULL value. Similar to + odb::nullable (Section 7.3, + "NULL Value Semantics"), it can be used to add the + NULL semantics to existing C++ types. For example:

+ +
+#include <boost/optional.hpp>
+
+#pragma db object
+class person
+{
+  ...
+
+  std::string first_;                    // TEXT NOT NULL
+  boost::optional<std::string> middle_;  // TEXT NULL
+  std::string last_;                     // TEXT NOT NULL
+};
+  
+ +

Note also that similar to odb::nullable, when + this profile is used, the NULL values are automatically + enabled for data members of the boost::optional type.

+ +

15.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 @@ -9539,7 +9787,7 @@ namespace odb exceptions are thrown are database system dependent and are discussed in more detail in the following sub-sections.

-

15.3.1 MySQL Database Type Mapping

+

15.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 @@ -9600,7 +9848,7 @@ class person the out_of_range exception. Refer to the MySQL documentation for more information on the MySQL data type ranges.

-

15.3.2 SQLite Database Type Mapping

+

15.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 @@ -9678,7 +9926,7 @@ class person will result in the out_of_range exception.

-

15.3.3 PostgreSQL Database Type Mapping

+

15.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 @@ -9887,12 +10135,29 @@ class Person option.

The currently supported smart pointers are - QSharedPointer and QWeakPointer. For - more information on using smart pointers with ODB refer to - Section 3.2, "Object Pointers" and - Chapter 6, "Relationships". The smart-ptr - sub-profile also provides the lazy counterparts for the above - pointers: QLazySharedPointer + 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, "NULL Value Semantics". + When used as a pointer to a value, only QSharedPointer + is supported. For example:

+ +
+#pragma db object
+class person
+{
+  ...
+
+  #pragma db null
+  QSharedPointer<QString> middle_name_;
+};
+  
+ +

To provide finer grained control over object relationship loading, + the smart-ptr sub-profile also provides the lazy + counterparts for the above pointers: QLazySharedPointer and QLazyWeakPointer. You will need to include the <odb/qt/lazy-ptr.hxx> header file to make the lazy variants available in your application. For the description of the lazy -- cgit v1.1

15.1Smart Pointers Library
15.2Unordered Containers Library
15.3Optional Library
15.3Date Time Library + 15.4Date Time Library - - - + + +
15.3.1MySQL Database Type Mapping
15.3.2SQLite Database Type Mapping
15.3.3PostgreSQL Database Type Mapping
15.4.1MySQL Database Type Mapping
15.4.2SQLite Database Type Mapping
15.4.3PostgreSQL Database Type Mapping
4Querying the Database
5Containers
6Relationships
7Composite Value Types
7Value Types
8Inheritance
9Session
10ODB Pragma Language