From 9825b7b79eb73c5cfdd1bb1daa66dc6a699de7e5 Mon Sep 17 00:00:00 2001
From: Boris Kolpackov 5 ODB Pragma Language
@@ -797,7 +796,7 @@ private:
of core ODB declarations, such as odb::access
, that
are used to define persistent classes.
The second change is the addition of db object
+
The second change is the addition of db object
pragma just before the class definition. This pragma tells the
ODB compiler that the class that follows is persistent. Note
that making a class persistent does not mean that all objects
@@ -826,7 +825,7 @@ private:
have a unique, within its class, identifier. Or, in other words,
no two persistent instances of the same type have equal
identifiers. For our class we use an integer id. The
- db id auto
pragma that precedes the id_
+ db id auto
pragma that precedes the id_
member tells the ODB compiler that the following member is the
object's identifier. The auto
specifier indicates that it
is a database-assigned id. A unique id will be automatically generated
@@ -1641,8 +1640,8 @@ class person
Normally, an object class should define the default constructor. The
generated database support code uses this constructor when
- instantiating an object from the persistent state. If you add the
- default constructor only for the database support code, then you
+ instantiating an object from the persistent state. If we add the
+ default constructor only for the database support code, then we
can make it private. It is also possible to have an object type
without the default constructor. However, in this case, the database
operations can only load the persistent state into an existing instance
@@ -1680,11 +1679,11 @@ private:
types such as int
or std::string
since the
ODB compiler knows how to map them to suitable database system types and
how to convert between the two. On the other hand, if a simple value
- is unknown to the ODB compiler then you will need to provide the
+ is unknown to the ODB compiler then we will need to provide the
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 (Section
- 5.3.1, "type
"). Similar to object types, composite
+ this refer to the db type
pragma (Section
+ 5.2.1, "type
"). Similar to object types, composite
value types have to be explicitly declared as persistent using the
db value
pragma, for example:
shared_ptr
mentioned
previously, as object pointers.
- ODB provides two mechanisms for changing the object pointer type. You +
ODB provides two mechanisms for changing the object pointer type. We
can use the --default-pointer
option to specify the
alternate default object pointer type. All objects that don't
have the object pointer explicitly specified with the
- db pointer
pragma (see below) will use the default
+ 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.
@@ -1784,8 +1783,8 @@ class name
--default-pointer std::tr1::shared_ptr
-
The second mechanism allows you to specify the object pointer on
- an object by object basis using the db pointer
+
The second mechanism allows us to specify the object pointer on
+ an object by object basis using the db pointer
pragma, for example:
@@ -1796,7 +1795,7 @@ class person };-
Refer to Section 5.2.2, "pointer
"
+
Refer to Section 5.1.2, "pointer
"
for more information on this pragma.
Built-in support, provided by the ODB runtime, library allows us to use @@ -1813,10 +1812,10 @@ class person
Before an application can make use of persistence services
offered by ODB, it has to create a database class instance. A
database instance is the representation of the place where
- the application stores its persistent objects. You create
+ the application stores its persistent objects. We create
a database instance by instantiating one of the database
system-specific classes. For example, odb::mysql::database
- would be such a class for the MySQL database system. You will
+ would be such a class for the MySQL database system. We will
also normally pass a database name as an argument to the
class' constructor. The following code fragment
shows how we can create a database instance for the MySQL
@@ -1930,7 +1929,7 @@ namespace odb
has been finalized, that is, explicitly committed or rolled
back, the destructor of the odb::transaction
class will
automatically roll it back when the transaction instance goes
- out of scope. If you try to commit or roll back a finalized
+ out of scope. If we try to commit or roll back a finalized
transaction, the odb::transaction_already_finalized
exception is thrown.
odb::not_in_transaction
exception.
- You can check whether there is a transaction in effect in
+ We can check whether there is a transaction in effect in
this thread using the has_current()
static function.
If two or more transactions access or modify more than one object @@ -2095,7 +2094,7 @@ update_age (database& db, person& p)
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 5.4.2,
+ application-assigned object ids (Section 5.3.2,
"auto
").
The second and third persist()
versions are similar to the
@@ -2369,7 +2368,7 @@ namespace odb
}
-
Catching this exception guarantees that you will catch all the +
Catching this exception guarantees that we will catch all the
exceptions thrown by ODB. The what()
function
returns a human-readable description of the condition that
triggered the exception.
The null_pointer
exception is thrown when a
pointer to a persistent object declared non-NULL
- with the db not_null
pragma has the NULL
+ with the db not_null
pragma has the NULL
value. See Chapter Y, "Relationships" for details.
The next three exceptions (already_in_transaction
,
@@ -2528,7 +2527,7 @@ namespace odb
container types as discussed later in Section X.4,
"Using Custom Containers".
You don't need to do anything special to declare a member of a +
We don't need to do anything special to declare a member of a container type in a persistent class. For example:
@@ -2637,7 +2636,7 @@ private: (called-index
), and the value column of typestd::string
(calledvalue
). -A number of ODB pragmas allow you to customize the table name, +
A number of ODB pragmas allow us to customize the table name, column names, and native database types for the container both on the per-container and per-member basis. For more information on these pragmas, refer to Chapter 5, "ODB Pragma @@ -2730,7 +2729,7 @@ private: (called
-object_id
) and the value column of typestd::string
(calledvalue
).A number of ODB pragmas allow you to customize the table name, +
A number of ODB pragmas allow us to customize the table name, column names, and native database types for the container both on the per-container and per-member basis. For more information on these pragmas, refer to Chapter 5, "ODB Pragma @@ -2795,7 +2794,7 @@ private:
-unsigned short
(calledkey
), and the value column of typestd::string
(calledvalue
).A number of ODB pragmas allow you to customize the table name, +
A number of ODB pragmas allow us to customize the table name, column names, and native database types for the container both on the per-container and per-member basis. For more information on these pragmas, refer to Chapter 5, "ODB Pragma @@ -2878,7 +2877,7 @@ private: Section Y.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 (@@ ref). - For example, you can use
weak_ptr
if the object pointer + For example, we can useweak_ptr
if the object pointer isshared_ptr
.When an object containing a pointer to another object is loaded, @@ -3277,7 +3276,7 @@ CREATE TABLE employee ( of these references.
To eliminate redundant database schema references we can use the -
@@ -3321,7 +3320,7 @@ CREATE TABLE employee ( pointer. Also note that an ordered container (Section X.1, "Ordered Containers") of pointers that is an inverse side of a bidirectional relationship is always treated as unordered - (Section 5.4.8, "inverse
pragma (Section 5.4.7, +inverse
pragma (Section 5.3.7, "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:unordered
") + (Section 5.3.8, "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). @@ -3863,7 +3862,7 @@ t.commit ();Composite value type is a
class
orstruct
type that is mapped to more than one database column. To declare - a composite value type we use thedb value
pragma, + a composite value type we use thedb value
pragma, for example:@@ -3993,7 +3992,7 @@ 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
@@ -4034,7 +4033,7 @@ CREATE TABLE person (db column
pragma (@@ ref). For composite value + thedb column
pragma (@@ ref). For composite value types things are slightly more complicated since it is mapped to multiple columns. Consider the following example:We can customize both the prefix and the suffix using the -
db column
pragma as shown in the following +db column
pragma as shown in the following example:@@ -4093,8 +4092,8 @@ CREATE TABLE person (The same principal applies when a composite value type is used as an element of a container, except that instead of -
db column
either thedb value_column
- (@@ ref) ordb key_column
(@@ ref) pragmas are used to +db column
either thedb value_column
+ (@@ ref) ordb key_column
(@@ ref) pragmas are used to specify the column prefix.When a composite value type contains a container, an extra table @@ -4138,7 +4137,7 @@ CREATE TABLE person (
To customize the container table name we can use the -
+db table
(@@ ref) pragma, for example:db table
(@@ ref) pragma, for example:#pragma db value @@ -4275,7 +4274,7 @@ namespace odbThe session constructor creates a new session and sets it as a - current session for this thread. If you try to create a session + current session for this thread. If we try to create a session while there is already a current session in effect, this constructor throws the
odb::already_in_session
exception. The destructor clears the current session for this thread if this @@ -4283,11 +4282,11 @@ namespace odbThe static
-current()
accessor returns the currently active session for this thread. If there is no active session, this function - throws theodb::not_in_session
exception. You can check + throws theodb::not_in_session
exception. We can check whether there is a session in effect in this thread using thehas_current()
static function.The static
current()
modifier allows you to set the +The static
current()
modifier allows us to set the current session for this thread. Thereset_current
static function clears the current session. These two functions allow for more advanced use cases, such as multiplexing @@ -4361,18 +4360,18 @@ t.commit ();4 Querying the Database
-If you don't know the identifiers of the objects that you are looking - for, you can use queries to search the database for objects matching - certain criteria. The ODB query facility is optional and you need to +
If we don't know the identifiers of the objects that we are looking + for, we can use queries to search the database for objects matching + certain criteria. The ODB query facility is optional and we need to explicitly request the generation of the necessary database support code with the
--generate-query
ODB compiler option.ODB provides a flexible query API that offers two distinct levels of abstraction from the database system query language such as SQL. - At the high level you are presented with an easy to use yet powerful + At the high level we are presented with an easy to use yet powerful object-oriented query language, called ODB Query Language. This query language is modeled after and is integrated into C++ allowing - you to write expressive and safe queries that look and feel like + us to write expressive and safe queries that look and feel like ordinary C++. We have already seen examples of these queries in the introductory chapters. Below is another, more interesting, example:
@@ -4403,7 +4402,7 @@ t.commit (); query q ("first = 'John' AND age = " + query::_ref (age));
Note that at this level you lose the static typing of +
Note that at this level we lose the static typing of query expressions. For example, if we wrote something like this:
@@ -4423,7 +4422,7 @@ t.commit ();-It would compile fine and would trigger an error only when executed by the database system.
-You can also combine the two query languages in a single query, for +
We can also combine the two query languages in a single query, for example:
@@ -4447,7 +4446,7 @@ t.commit ();At the core of every query expression lie simple expressions which involve one or more object members, values, or parameters. To - refer to an object member you use an expression such as + refer to an object member we use an expression such as
query::first
above. The names of members in thequery
class are derived from the names of data members in the object class by removing the common member name decorations, @@ -4550,7 +4549,7 @@ t.commit ();The operator precedence in the query expressions are the same - as for equivalent C++ operators. You can use parentheses to + as for equivalent C++ operators. We can use parentheses to make sure the expression is evaluated in the desired order. For example:
@@ -4589,7 +4588,7 @@ t.commit ();The
odb::query
class provides two special functions, -_val()
and_ref()
, that allow you to +_val()
and_ref()
, that allow us to bind the parameter either by value or by reference, respectively. In the ODB query language, if the binding is not specified explicitly, the value semantic is used by default. In the @@ -4610,7 +4609,7 @@ t.commit (); other variables and is self-sufficient once constructed. A query that has one or more by-reference parameters depends on the bound variables until the query is executed. If one such variable - goes out of scope and you execute the query, the behavior is + goes out of scope and we execute the query, the behavior is undefined.4.3 Executing a Query
@@ -4661,7 +4660,7 @@ t.commit (); result r1 (db.query<person> (query::first == "John"));
Normally you would create a named query instance if you are +
Normally we would create a named query instance if we are planning to run the same query multiple times and would use the in-line version for those that are executed only once.
@@ -4692,7 +4691,7 @@ result r (find_underage (db, query::first == "John"));It is best to view an instance of odb::result
- as a handle to a stream, such as a file stream. While you can
+ as a handle to a stream, such as a file stream. While we can
make a copy of a result or assign one result to another, the
two instances will refer to the same result stream. Advancing
the current position in one instance will also advance it in
@@ -4750,7 +4749,7 @@ namespace odb
result caching when we talked about query execution. As you
may remember the database::query()
function
caches the result unless instructed not to by the caller.
- The cache()
function allows you to
+ The cache()
function allows us to
cache the result at a later stage if it wasn't already
cached during query execution.
Uncached results can improve the performance of both the application - and the database system in situations where you have a large - number of objects in the result or if you will only examine + and the database system in situations where we have a large + number of objects in the result or if we will only examine a small portion of the returned objects. However, uncached results have a number of limitations. There can only be one uncached result in a transaction. Creating another result @@ -4776,7 +4775,7 @@ namespace odb
The empty()
function returns true
if
there are no objects in the result and false
otherwise.
The size()
function can only be called for cached results.
- It returns the number of objects in the result. If you call this
+ It returns the number of objects in the result. If we call this
function on an uncached result, the odb::result_not_cached
exception is thrown.
The result iterator has the following dereference functions that can be used to access the pointed-to object:
@@ -4831,13 +4830,13 @@ namespace odb } -When you call the *
or ->
operator,
+
When we call the *
or ->
operator,
the iterator will allocate a new instance of the object class
in the dynamic memory, load its state from the database
state, and return a reference or pointer to the new instance. The
iterator maintains the ownership of the returned object and will
return the same pointer for subsequent calls to either of these
- operators until it is advanced to the next object or you call
+ operators until it is advanced to the next object or we call
the first load()
function (see below). For example:
@@ -4859,7 +4858,7 @@ namespace odb as a result of an earlier call to the*
or->
operator, then it relinquishes the ownership of this object and returns it instead. - This allows you to write code like this without worrying about + This allows us to write code like this without worrying about a double allocation:@@ -4880,7 +4879,7 @@ namespace odb operator results in the allocation of a new object.-The second
load()
function allows - you to load the current object's state into an existing instance. + us to load the current object's state into an existing instance. For example:@@ -4963,9 +4962,8 @@ private: unsigned long id_;-While keeping the C++ declarations and database declarations close - together eases maintenance and increases readability, you can also + together eases maintenance and increases readability, we can also place them in different parts of the same header file or even factor them to a separate file. To achieve this we use the so called named pragmas. Unlike positioned pragmas, named pragmas @@ -5026,143 +5024,20 @@ private: };
5.1 C++ Compiler Warnings
+The following three sections cover the specifiers applicable + to the
-object
,value
, andmember
+ qualifiers.The C++ header file that defines your persistent classes and +
The C++ header file that defines our persistent classes and normally contains one or more ODB pragmas is compiled by both the ODB compiler to generate the database support code and - the C++ compiler to build your application. Some C++ compilers + the C++ compiler to build our application. Some C++ compilers issue warnings about pragmas that they do not recognize. There - are several ways to deal with this problem. The easiest is to - disable such warnings using one of the compiler-specific command - line options or warning control pragmas. This method is described - in the following sub-section for popular C++ compilers.
+ are several ways to deal with this problem which are covered + at the end of this chapter in Section 5.4, + "C++ Compiler Warnings". -There are also several C++ compiler-independent methods that you - can employ. The first is to use the
- -PRAGMA_DB
macro, - defined in<odb/core.hxx>
, instead of using -#pragma db
directly. This macro expands to the - ODB pragma when compiled with the ODB compiler and to an empty - declaration when compiled with other compilers. The following example - shows how we can use this macro:-#include <odb/core.hxx> - -PRAGMA_DB(object) -class person -{ - ... -private: - PRAGMA_DB(id) - unsigned long id_; - ... -}; -- -An alternative to using the
- -PRAGMA_DB
macro is to - group the#pragma db
directives in blocks that are - conditionally included into compilation only when compiled with the - ODB compiler. For example:-class person -{ - ... -private: - unsigned long id_; - ... -}; - -#ifdef ODB_COMPILER -# pragma db object(person) -# pragma db member(person::id_) id -#endif -- -The disadvantage of this approach is that it can quickly become - overly verbose when positioned pragmas are used.
- -5.1.1 GNU C++
- -GNU g++ does not issue warnings about unknown pragmas - unless requested with the
- --Wall
command line option. - To disable only the unknown pragma warning, you can add the --Wno-unknown-pragmas
option after-Wall
, - for example:-g++ -Wall -Wno-unknown-pragmas ... -- -5.1.2 Visual C++
- -Microsoft Visual C++ issues an unknown pragma warning (C4068) at - warning level 1 or higher. This means that unless you have disabled - the warnings altogether (level 0), you will see this warning.
- -To disable this warning via the compiler command line, you can add - the
- -/wd4068
C++ compiler option in Visual Studio 2008 - and earlier. In Visual Studio 2010 there is now a special GUI field - where you can enter warning numbers that should be disabled. Simply - enter 4068 into this field.You can also disable this warning for only a specific header or - a fragment of a header using the warning control pragma. For - example:
- --#include <odb/core.hxx> - -#pragma warning (push) -#pragma warning (disable:4068) - -#pragma db object -class person -{ - ... -private: - #pragma db id - unsigned long id_; - ... -}; - -#pragma warning (pop) -- -5.1.3 Sun C++
- -The Sun C++ compiler does not issue warnings about unknown pragmas - unless the
- -+w
or+w2
option is specified. - To disable only the unknown pragma warning you can add the --erroff=unknownpragma
option anywhere on the - command line, for example:-CC +w -erroff=unknownpragma ... -- -5.1.4 IBM XL C++
- -IBM XL C++ issues an unknown pragma warning (1540-1401) by default. - To disable this warning you can add the
- --qsuppress=1540-1401
- command line option, for example:-xlC -qsuppress=1540-1401 ... -- -5.1.5 HP aC++
- -HP aC++ (aCC) issues an unknown pragma warning (2161) by default. - To disable this warning you can add the
- -+W2161
- command line option, for example:-aCC +W2161 ... -- -5.2 Object Type Pragmas
+5.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, @@ -5179,19 +5054,19 @@ aCC +W2161 ...table
the table name for the persistent class -5.2.1 +5.1.1 - pointer
the pointer type for the persistent class -5.2.2 +5.1.2 5.2.1
+table
5.1.1
table
The
table
specifier specifies the table name that should be used to store objects of the class in a relational database. For @@ -5208,7 +5083,7 @@ class personIf the table name is not specified, the class name is used as the table name.
-5.2.2
+pointer
5.1.2
pointer
The
pointer
specifier specifies the object pointer type for the persistent class. The object pointer type is used to return, @@ -5224,8 +5099,8 @@ class person
There are several ways to specify an object pointer with the
- pointer
specifier. You can use a complete pointer
- type as shown in the example above. Alternatively, you can
+ pointer
specifier. We can use a complete pointer
+ type as shown in the example above. Alternatively, we can
specify only the template name of a smart pointer in which
case the ODB compiler will automatically append the class
name as a template argument. The following example is
@@ -5258,7 +5133,7 @@ class person
For additional information on object pointers, refer to Section @@, "".
-A pragma with the value
qualifier describes a value
type. It can be optionally followed, in any order, by one or more
@@ -5275,67 +5150,67 @@ class person
type
not_null
NULL
unordered
index_type
key_type
value_type
id_column
index_column
key_column
value_column
Many of the value type specifiers have corresponding member type - specifiers with the same names (see Section 5.4, + specifiers with the same names (see Section 5.3, "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 @@ -5344,7 +5219,7 @@ class person to a single member. In other words, member specifiers take precedence over values specified with value specifiers.
-type
type
The type
specifier specifies the native database type
that should be used for data members of this type. For example:
mapping
example in the odb-examples
package shows how to do this for all the supported database systems.
- not_null
not_null
The not_null
specifier specifies that an object pointer
or a container of object pointers type cannot have or contain the
@@ -5420,7 +5295,7 @@ typedef std::vector<shared_ptr<account> > accounts;
#pragma db value(accounts) not_null
-
unordered
unordered
The unordered
specifier specifies that the ordered
container should be stored in the database unordered. The database
@@ -5433,13 +5308,13 @@ typedef std::vector<std::string> names;
#pragma db value(names) unordered
-
index_type
index_type
The index_type
specifier specifies the native
database type that should be used for the ordered container's
index column. The semantics of index_type
are similar to that of the type
specifier (see
- Section 5.3.1, "type
"). The native
+ Section 5.2.1, "type
"). The native
database type is expected to be an integer type. For example:
@@ -5447,13 +5322,13 @@ typedef std::vector<std::string> names; #pragma db value(names) index_type("SMALLINT UNSIGNED NOT NULL")-
key_type
key_type
The key_type
specifier specifies the native
database type that should be used for the map container's
key column. The semantics of key_type
are similar to that of the type
specifier (see
- Section 5.3.1, "type
"). For
+ Section 5.2.1, "type
"). For
example:
@@ -5461,13 +5336,13 @@ typedef std::map<unsigned short, float> age_weight_map; #pragma db value(age_weight_map) key_type("INT UNSIGNED NOT NULL")-
value_type
value_type
The value_type
specifier specifies the native
database type that should be used for the container's
value column. The semantics of value_type
are similar to that of the type
specifier (see
- Section 5.3.1, "type
"). For
+ Section 5.2.1, "type
"). For
example:
@@ -5475,7 +5350,7 @@ typedef std::vector<std::string> names; #pragma db value(names) value_type("VARCHAR(255) NOT NULL")-
id_column
id_column
The id_column
specifier specifies the column
name that should be used to store the object id in the
@@ -5489,7 +5364,7 @@ typedef std::vector<std::string> names;
If the column name is not specified, then object_id
is used by default.
index_column
index_column
The index_column
specifier specifies the column
name that should be used to store the element index in the
@@ -5503,7 +5378,7 @@ typedef std::vector<std::string> names;
If the column name is not specified, then index
is used by default.
key_column
key_column
The key_column
specifier specifies the column
name that should be used to store the key in the map
@@ -5517,7 +5392,7 @@ typedef std::map<unsigned short, float> age_weight_map;
If the column name is not specified, then key
is used by default.
value_column
value_column
The value_column
specifier specifies the column
name that should be used to store the element value in the
@@ -5534,7 +5409,7 @@ typedef std::map<unsigned short, float> age_weight_map;
-
A pragma with the member
qualifier or a positioned
pragma without a qualifier describes a data member. It can
@@ -5552,104 +5427,104 @@ typedef std::map<unsigned short, float> age_weight_map;
id
auto
type
column
transient
not_null
inverse
unordered
table
index_type
key_type
value_type
id_column
index_column
key_column
value_column
Many of the member specifiers have corresponding value type - specifiers with the same names (see Section 5.3, + specifiers with the same names (see Section 5.2, "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 @@ -5658,7 +5533,7 @@ typedef std::map<unsigned short, float> age_weight_map; to a single member. In other words, member specifiers take precedence over values specified with value specifiers.
-id
id
The id
specifier specifies that the data member contains
the object id. Every persistent class must have a member designated
@@ -5679,7 +5554,7 @@ private:
In a relational database, an identifier member is mapped to a primary key.
-auto
auto
The auto
specifier specifies that the object's identifier
is automatically assigned by the database. Only a member that was
@@ -5707,7 +5582,7 @@ private:
For additional information on the automatic identifier assignment, refer to Section 3.5, "Making Objects Persistent".
-type
type
The type
specifier specifies the native database type
that should be used for the data member. For example:
column
column
The column
specifier specifies the column name
that should be used to store the member in a relational database.
@@ -5750,7 +5625,7 @@ private:
name by removing the common member name decorations, such as leading
and trailing underscores, the m_
prefix, etc.
transient
transient
The transient
specifier instructs the ODB compiler
not to store the data member in the database. For example:
not_null
not_null
The not_null
specifier specifies that the member of
an object pointer or a container of object pointers type cannot
@@ -5802,7 +5677,7 @@ private:
};
-
inverse
inverse
The inverse
specifier specifies that the member of
an object pointer or a container of object pointers type is an
@@ -5842,9 +5717,9 @@ private:
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 (see
- Section 5.4.8, "unordered
").
unordered
").
- unordered
unordered
The unordered
specifier specifies that the member of
an ordered container type should be stored in the database unordered.
@@ -5864,7 +5739,7 @@ private:
};
-
table
table
The table
specifier specifies the table name that should
be used to store the contents of the container member. For example:
index_type
index_type
The index_type
specifier specifies the native
database type that should be used for the ordered container's
index column of the data member. The semantics of index_type
are similar to that of the type
specifier (see
- Section 5.4.3, "type
"). The native
+ Section 5.3.3, "type
"). The native
database type is expected to be an integer type. For example:
@@ -5916,13 +5791,13 @@ private: };-
key_type
key_type
The key_type
specifier specifies the native
database type that should be used for the map container's
key column of the data member. The semantics of key_type
are similar to that of the type
specifier (see
- Section 5.4.3, "type
"). For
+ Section 5.3.3, "type
"). For
example:
@@ -5937,13 +5812,13 @@ private: };-
value_type
value_type
The value_type
specifier specifies the native
database type that should be used for the container's
value column of the data member. The semantics of value_type
are similar to that of the type
specifier (see
- Section 5.4.3, "type
"). For
+ Section 5.3.3, "type
"). For
example:
@@ -5958,14 +5833,14 @@ private: };-
id_column
id_column
The id_column
specifier specifies the column
name that should be used to store the object id in the
container's table for the member. The semantics of
id_column
are similar to that of the
column
specifier (see
- Section 5.4.4, "column
").
+ Section 5.3.4, "column
").
For example:
@@ -5983,14 +5858,14 @@ private:If the column name is not specified, then
-object_id
is used by default.5.4.14
+index_column
5.3.14
index_column
The
index_column
specifier specifies the column name that should be used to store the element index in the ordered container's table for the member. The semantics ofindex_column
are similar to that of thecolumn
specifier (see - Section 5.4.4, "column
"). + Section 5.3.4, "column
"). For example:@@ -6008,14 +5883,14 @@ private:If the column name is not specified, then
-index
is used by default.5.4.15
+key_column
5.3.15
key_column
The
key_column
specifier specifies the column name that should be used to store the key in the map container's table for the member. The semantics ofkey_column
are similar to that of thecolumn
specifier (see - Section 5.4.4, "column
"). + Section 5.3.4, "column
"). For example:@@ -6033,14 +5908,14 @@ private:If the column name is not specified, then
-key
is used by default.5.4.16
+value_column
5.3.16
value_column
The
value_column
specifier specifies the column name that should be used to store the element value in the container's table for the member. The semantics ofvalue_column
are similar to that of thecolumn
specifier (see - Section 5.4.4, "column
"). + Section 5.3.4, "column
"). For example:@@ -6058,6 +5933,141 @@ private:-If the column name is not specified, then
+value
is used by default.5.4 C++ Compiler Warnings
+ +When the C++ header file defining our persistent classes and + containing ODB pragmas is processed by a C++ compiler, it + may issue warnings about pragmas that it doesn't recognize. There + are several ways to deal with this problem. The easiest is to + disable such warnings using one of the compiler-specific command + line options or warning control pragmas. This method is described + in the following sub-section for popular C++ compilers.
+ +There are also several C++ compiler-independent methods that we + can employ. The first is to use the
+ +PRAGMA_DB
macro, + defined in<odb/core.hxx>
, instead of using +#pragma db
directly. This macro expands to the + ODB pragma when compiled with the ODB compiler and to an empty + declaration when compiled with other compilers. The following example + shows how we can use this macro:+#include <odb/core.hxx> + +PRAGMA_DB(object) +class person +{ + ... +private: + PRAGMA_DB(id) + unsigned long id_; + ... +}; ++ +An alternative to using the
+ +PRAGMA_DB
macro is to + group the#pragma db
directives in blocks that are + conditionally included into compilation only when compiled with the + ODB compiler. For example:+class person +{ + ... +private: + unsigned long id_; + ... +}; + +#ifdef ODB_COMPILER +# pragma db object(person) +# pragma db member(person::id_) id +#endif ++ +The disadvantage of this approach is that it can quickly become + overly verbose when positioned pragmas are used.
+ +5.4.1 GNU C++
+ +GNU g++ does not issue warnings about unknown pragmas + unless requested with the
+ +-Wall
command line option. + To disable only the unknown pragma warning, we can add the +-Wno-unknown-pragmas
option after-Wall
, + for example:+g++ -Wall -Wno-unknown-pragmas ... ++ +5.4.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 + the warnings altogether (level 0), we will see this warning.
+ +To disable this warning via the compiler command line, we can add + the
+ +/wd4068
C++ compiler option in Visual Studio 2008 + and earlier. In Visual Studio 2010 there is now a special GUI field + where we can enter warning numbers that should be disabled. Simply + enter 4068 into this field.We can also disable this warning for only a specific header or + a fragment of a header using the warning control pragma. For + example:
+ ++#include <odb/core.hxx> + +#pragma warning (push) +#pragma warning (disable:4068) + +#pragma db object +class person +{ + ... +private: + #pragma db id + unsigned long id_; + ... +}; + +#pragma warning (pop) ++ +5.4.3 Sun C++
+ +The Sun C++ compiler does not issue warnings about unknown pragmas + unless the
+ ++w
or+w2
option is specified. + To disable only the unknown pragma warning we can add the +-erroff=unknownpragma
option anywhere on the + command line, for example:+CC +w -erroff=unknownpragma ... ++ +5.4.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
+ command line option, for example:+xlC -qsuppress=1540-1401 ... ++ +5.4.5 HP aC++
+ +HP aC++ (aCC) issues an unknown pragma warning (2161) by default. + To disable this warning we can add the
+ ++W2161
+ command line option, for example:+aCC +W2161 ... ++ + @@ -6278,13 +6288,13 @@ namespace odbYou will need to include the
-<odb/mysql/database.hxx>
header file to make this class available in your application.The overloaded
database
constructors allow you +The overloaded
database
constructors allow us to specify MySQL database parameters that should be used when connecting to the database. In MySQLNULL
and an empty string are treated as the same values for all the string parameters exceptpassword
andsocket
. Theclient_flags
argument - allows you to specify various MySQL client library flags. For more + allows us to specify various MySQL client library flags. For more information on the possible values, refer to the MySQL C API documentation. TheCLIENT_FOUND_ROWS
flag is always set by the MySQL ODB runtime regardless of whether it was passed in the @@ -6303,7 +6313,7 @@ namespace odb --options-file <file>The
--options-file
option allows you to specify some +The
@@ -6323,13 +6333,13 @@ namespace odb with short descriptions that are recognized by this constructor.--options-file
option allows us to specify some or all of the database options in a file with each option appearing on a separate line followed by space and an option value.The last argument to all of the constructors is the - pointer to the connection factory. If you pass a + pointer to the connection factory. If we pass a non-
-NULL
value, the database instance assumes ownership of the factory instance. The connection factory interface as well as the available implementations are described in the next section.The set of accessor functions following the constructors allow you +
The set of accessor functions following the constructors allow us to query the parameters of the
database
instance.The
connection()
function returns the MySQL database -- cgit v1.1