From 6a4faf610de03a270c45379c84a36bc228ba739e Mon Sep 17 00:00:00 2001
From: Boris Kolpackov The ODB runtime library provides built-in persistence support for
+ all commonly used standard C++ containers, namely,
+ You don't need to do anything special to declare a member of a
+ container type in a persistent class. For example: A data member in a persistent class that is of a container type
+ behaves like a value type. That is, when an object is made persistent,
+ the elements of the container are store in the database. Similarly,
+ when a persistent object is loaded from the database, the contents
+ of the container are automatically loaded as well. While an ordinary member is mapped to one or more columns in the
+ object's table, a member of a container type is mapped to a seperate
+ table. The exact schema of such a table depends on the kind of
+ a container. ODB defines the following container kinds: ordered,
+ set, multiset, map, and multimap. The container kinds and the
+ 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 (see @@), and object pointers (see @@). Containers of
+ containers are not supported. A key in map and multimap
+ containers can be a simple or composite value type but not
+ an object pointer. An index in the ordered container should
+ be a simple integer type. The value type in the ordered, set, and map containers as well as
+ the key type in the map containers should be default-constructible.
+ The default constructor in these types can be made private in which
+ case the In ODB an ordered container is any container that maintains (explicitly
+ or implicitly) an order of its elements in the form of an integer index.
+ Standard C++ containers that are ordered include The database table for an ordered container consists of at least
+ three columns. The first column contains the object id of a
+ persistent class instance of which the container is a member.
+ The second column contains the element index within a container.
+ And the last column contains the element value. If the object
+ id or element value are composite, then instead of a single
+ column they can occupy multiple columns. Consider the following persistent object as an example: The resulting database table (called A number of ODB pragmas allow you 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
+ Language". The following example shows some of the possible
+ customizations: While the C++ container used in the persistent class may be ordered,
+ sometimes we may wish to store such a container in the database without
+ 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
+ The table for the ordered container that is marked unordered will
+ miss the index column and the order in which elements are retrieved
+ from the database may not be the same as the order in which they
+ were stored. In ODB set and multiset containers (referred to as just set
+ containers) are associative containers that contain elements
+ based on some relationship between them. A set container may
+ or may not guarantee a particular order of the elements that
+ it stores. Standard C++ containers that are considered set
+ containers for the purpose of persistence include
+ The database table for a set container consists of at least
+ two columns. The first column contains the object id of a
+ persistent class instance of which the container is a member.
+ And the second column contains the element value. If the object
+ id or element value are composite, then instead of a single
+ column they can occupy multiple columns. Consider the following persistent object as an example: The resulting database table (called A number of ODB pragmas allow you 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
+ Language". The following example shows some of the possible
+ customizations: In ODB map and multimap containers (referred to as just set
+ containers) are associative containers that contain key-value
+ elemenst based on some relationship between keys. A map container
+ may or may not guarantee a particular order of the elements that
+ it stores. Standard C++ containers that are considered map
+ containers for the purpose of persistence include
+ The database table for a map container consists of at least
+ three columns. The first column contains the object id of a
+ persistent class instance of which the container is a member.
+ The second column contains the element key. And the last column
+ contains the element value. If the object id, element key, or
+ element value are composite, then instead of a single column
+ they can occupy multiple columns. Consider the following persistent object as an example: The resulting database table (called A number of ODB pragmas allow you 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
+ Language". The following example shows some of the possible
+ customizations: While the ODB runtime and profile libraries provide support for
+ a wide range of containers, it is also easy to persist custom
+ container types. To achieve this you will need to implement the
+ Once the container traits specialization is ready for your container,
+ you will need to include it into the ODB compilation process using
+ the Now, whenever we compile a header file that uses the hashtable
+ container, we can pass the following option to make sure it
+ is recognized by the ODB compiler as a container and the traits
+ file is included in the generated code: An ODB query is an expression that tells the database system whether
@@ -3344,7 +3691,7 @@ typedef std::vector<std::string> names;
example:X Containers
+
+ std::vector
, std::list
, std::set
,
+ std::multiset
, std::map
, and
+ std::multimap
. Plus, ODB profile libraries are available
+ for commonly used frameworks and libraries (such as Boost and Qt)
+ that provide persistence support for containers found in these
+ frameworks and libraries. It is also easy to persist custom
+ container types as discussed later in Section X.4,
+ "Using Custom Containers".
+#pragma db object
+class person
+{
+ ...
+private:
+ std::vector<std::name> nicknames_;
+ ...
+};
+
+
+ odb::access
class should be made a friend of
+ the value or key type. For example:
+#pragma db value
+class name
+{
+public:
+ name (const std::string&, const std::string&);
+ ...
+private:
+ friend class odb::access;
+ name ();
+ ...
+};
+
+#pragma db object
+class person
+{
+ ...
+private:
+ #pragma db id auto
+ unsigned long id_;
+
+ std::vector<name> aliases_;
+ ...
+};
+
+
+
+ X.1 Ordered Containers
+
+ std::vector
+ and std::list
. While elements in std::set
+ are also kept in a specific order, this order is not based on an
+ integer index but rather on the relationship between elements. As
+ a result, std::set
is not considered an ordered
+ container for the purpose of persistence.
+#pragma db object
+class person
+{
+ ...
+private:
+ #pragma db id auto
+ unsigned long id_;
+
+ std::vector<std::string> nicknames_;
+ ...
+};
+
+
+ person_nicknames
) will
+ contain the object id column of type unsigned long
+ (called object_id
), the index column of an integer type
+ (called index
), and the value column of type
+ std::string
(called value
).
+#pragma db object
+class person
+{
+ ...
+private:
+ #pragma db id auto
+ unsigned long id_;
+
+ #pragma db table("nicknames") \
+ id_column ("person_id") \
+ index_type ("SMALLINT UNSIGNED NOT NULL") \
+ index_column ("nickname_number") \
+ value_type ("VARCHAR(255) NOT NULL") \
+ value_column ("nickname")
+ std::vector<std::string> nicknames_;
+ ...
+};
+
+
+ unordered
pragma (see Chapter 5, "ODB
+ Pragma Language" for details). For example:
+#pragma db object
+class person
+{
+ ...
+private:
+ #pragma db id auto
+ unsigned long id_;
+
+ #pragma db unordered
+ std::vector<std::string> nicknames_;
+ ...
+};
+
+
+ X.2 Set and Multiset Containers
+
+ std::set
and std::multiset
.
+#pragma db object
+class person
+{
+ ...
+private:
+ #pragma db id auto
+ unsigned long id_;
+
+ std::set<std::string> emails_;
+ ...
+};
+
+
+ person_emails
) will
+ contain the object id column of type unsigned long
+ (called object_id
) and the value column of type
+ std::string
(called value
).
+#pragma db object
+class person
+{
+ ...
+private:
+ #pragma db id auto
+ unsigned long id_;
+
+ #pragma db table("emails") \
+ id_column ("person_id") \
+ value_type ("VARCHAR(255) NOT NULL") \
+ value_column ("email")
+ std::set<std::string> emails_;
+ ...
+};
+
+
+ X.3 Map and Multimap Containers
+
+ std::map
and std::multimap
.
+#pragma db object
+class person
+{
+ ...
+private:
+ #pragma db id auto
+ unsigned long id_;
+
+ std::map<unsigned short, float> age_weight_map_;
+ ...
+};
+
+
+ person_age_weight_map
)
+ will contain the object id column of type unsigned long
+ (called object_id
), the key column of type
+ unsigned short
(called key
), and the value
+ column of type std::string
(called value
).
+#pragma db object
+class person
+{
+ ...
+private:
+ #pragma db id auto
+ unsigned long id_;
+
+ #pragma db table("weight_map") \
+ id_column ("person_id") \
+ key_type ("INT UNSIGNED NOT NULL") \
+ key_column ("age") \
+ value_type ("DOUBLE NOT NULL") \
+ value_column ("weight")
+ std::map<unsigned short, float> age_weight_map_;
+ ...
+};
+
+
+ X.4 Using Custom Containers
+
+ container_traits
class template specialization for
+ your container. First determine the container kind (ordered, set,
+ multiset, map, or multimap) for your container type. Then use a
+ specialization for one of the standard C++ containers found in
+ the common ODB runtime library (libodb
) as a base
+ for your own implementation.--odb-epilogue
option and into the generated header
+ file with the --hxx-prologue
option. As an example,
+ suppose we have a hash table container for which we have the traits
+ specialization implemented in the hashtable-traits.hxx
+ file. Then, we can create an ODB compiler options file for this
+ container and save it to hashtable.options
:
+# Options file for the hash table container.
+#
+--odb-epilogue '#include "hashtable-traits.hxx"'
+--hxx-prologue '#include "hashtable-traits.hxx"'
+
+
+
+--options-file hashtable.options
+
+
+
+
4 Querying the Database
@@ -2359,7 +2707,6 @@ namespace odb
query q ("first = 'John'" + (query::age < query::_ref (age)));
-
4.1 ODB Query Language
-typedef std::map<unsigned short, double> age_weight_map;
+typedef std::map<unsigned short, float> age_weight_map;
#pragma db value(age_weight_map) key_type("INT UNSIGNED NOT NULL")
@@ -3397,7 +3744,7 @@ typedef std::vector<std::string> names;
container's table. For example:
-typedef std::map<unsigned short, double> age_weight_map; +typedef std::map<unsigned short, float> age_weight_map; #pragma db value(age_weight_map) key_column("age")@@ -3411,7 +3758,7 @@ typedef std::map<unsigned short, double> age_weight_map; container's table. For example:
-typedef std::map<unsigned short, double> age_weight_map; +typedef std::map<unsigned short, float> age_weight_map; #pragma db value(age_weight_map) value_column("weight")@@ -3774,7 +4121,7 @@ class person ... private: #pragma db key_type("INT UNSIGNED NOT NULL") - std::map<unsigned short, double> age_weight_map_; + std::map<unsigned short, float> age_weight_map_; ... }; @@ -3867,7 +4214,7 @@ class person ... private: #pragma db key_column("age") - std::map<unsigned short, double> age_weight_map_; + std::map<unsigned short, float> age_weight_map_; ... }; @@ -3892,7 +4239,7 @@ class person ... private: #pragma db value_column("weight") - std::map<unsigned short, double> age_weight_map_; + std::map<unsigned short, float> age_weight_map_; ... }; -- cgit v1.1