From e4d52fddfcd32de4dfa3dccf70fba0f667bad905 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 22 Aug 2011 14:32:09 +0200 Subject: Document odb::connection --- doc/manual.xhtml | 368 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 278 insertions(+), 90 deletions(-) (limited to 'doc') diff --git a/doc/manual.xhtml b/doc/manual.xhtml index e5c7419..d5ef0a5 100644 --- a/doc/manual.xhtml +++ b/doc/manual.xhtml @@ -321,13 +321,14 @@ for consistency. 3.2Object Pointers 3.3Database 3.4Transactions - 3.5Error Handling and Recovery - 3.6Making Objects Persistent - 3.7Loading Persistent Objects - 3.8Updating Persistent Objects - 3.9Deleting Persistent Objects - 3.10Executing Native SQL Statements - 3.11ODB Exceptions + 3.5Connections + 3.6Error Handling and Recovery + 3.7Making Objects Persistent + 3.8Loading Persistent Objects + 3.9Updating Persistent Objects + 3.10Deleting Persistent Objects + 3.11Executing Native SQL Statements + 3.12ODB Exceptions @@ -503,7 +504,7 @@ for consistency. - +
11.1MySQL Type Mapping
11.2MySQL Database Class
11.3MySQL Connection Factory
11.3MySQL Connection and Connection Factory
11.4MySQL Exceptions
@@ -514,7 +515,7 @@ for consistency. - +
12.1SQLite Type Mapping
12.2SQLite Database Class
12.3SQLite Connection Factory
12.3SQLite Connection and Connection Factory
12.4SQLite Exceptions
12.5SQLite Limitations @@ -536,7 +537,7 @@ for consistency. - +
13.1PostgreSQL Type Mapping
13.2PostgreSQL Database Class
13.3PostgreSQL Connection Factory
13.3PostgreSQL Connection and Connection Factory
13.4PostgreSQL Exceptions
13.5PostgreSQL Limitations @@ -1384,7 +1385,7 @@ main (int argc, char* argv[])

The final bit of code in our example is the catch block that handles the database exceptions. We do this by catching - the base ODB exception (Section 3.11, "ODB + the base ODB exception (Section 3.12, "ODB Exceptions") and printing the diagnostics.

Let's now compile (Section 2.3, "Compiling and @@ -1897,7 +1898,7 @@ class person 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 - (Section 3.7, "Loading Persistent Objects", + (Section 3.8, "Loading Persistent Objects", Section 4.4, "Query Result").

The object id type should be default-constructible.

@@ -2084,7 +2085,7 @@ auto_ptr<odb::database> db (

The odb::database class is a common interface for - all database system-specific classes provided by ODB. You + all the database system-specific classes provided by ODB. You would normally work with the database instance via this interface unless there is a specific functionality that your application depends on and which is @@ -2229,6 +2230,7 @@ namespace odb { public: typedef odb::database database_type; + typedef odb::connection connection_type; void commit (); @@ -2239,6 +2241,9 @@ namespace odb database_type& database (); + connection_type& + connection (); + static transaction& current (); @@ -2257,11 +2262,13 @@ namespace odb transaction, the odb::transaction_already_finalized exception is thrown.

-

The database() function returns the database this - transaction is working on. The current() static - function returns the currently active transaction for this - thread. If there is no active transaction, this function - throws the odb::not_in_transaction exception. +

The database() accessor returns the database this + transaction is working on. Similarly, the connection() + accessor returns the database connection this transaction is on + (Section 3.5, "Connections"). The + current() static function returns the currently active + transaction for this thread. If there is no active transaction, this + function throws the odb::not_in_transaction exception. We can check whether there is a transaction in effect in this thread using the has_current() static function.

@@ -2342,8 +2349,107 @@ update_age (database& db, person& p) } +

3.5 Connections

+ +

The odb::connection class represents a connection + to the database. Normally, you wouldn't work with connections + directly but rather let the ODB runtime obtain and release + connections as needed. However, certain use cases may require + obtaining a connection manually. For completeness, this section + describes the connection class and discusses some + of its use cases. You may want to skip this section if you are + reading through the manual for the first time.

+ +

Similar to odb::database, the odb::connection + class is a common interface for all the database system-specific + classes provided by ODB. For details on the system-specific + connection classes, refer to Part II, + "Database Systems".

+ +

To make the odb::connection class available in your + application you will need to include the <odb/connection.hxx> + header file. The odb::connection class has the + following interface:

+ +
+namespace odb
+{
+  class connection
+  {
+  public:
+    typedef odb::database database_type;
+
+    transaction
+    begin () = 0;
 
-  

3.5 Error Handling and Recovery

+ unsigned long long + execute (const char* statement); + + unsigned long long + execute (const std::string& statement); + + unsigned long long + execute (const char* statement, std::size_t length); + + database_type& + database (); + }; + + typedef details::shared_ptr<connection> connection_ptr; +} +
+ +

The begin() function is used to start a transaction + on the connection. The execute() functions allow + us to execute native database statements on the connection. + Their semantics are equivalent to the database::execute() + functions (Section 3.11, "Executing Native SQL + Statements") except that they can be legally called outside + a transaction. Finally, the database() accessor + returns a reference to the odb::database instance + to which this connection corresponds.

+ +

To obtain a connection we call the database::connection() + function. The connection is returned as odb::connection_ptr, + which is an implementation-specific smart pointer with the shared + pointer semantics. This, in particular, means that the connection + pointer can be copied and returned from functions. Once the last + instance of connection_ptr pointing to the same + connection is destroyed, the connection is returned to the + database instance. The following code fragment + shows how we can obtain, use, and release a connection:

+ +
+using namespace odb::core;
+
+database& db = ...
+connection_ptr c (db.connection ());
+
+// Temporarily disable foreign key constraints.
+//
+c->execute ("SET FOREIGN_KEY_CHECKS = 0");
+
+// Start a transaction on this connection.
+//
+transaction t (c->begin ());
+...
+t.commit ();
+
+// Restore foreign key constraints.
+//
+c->execute ("SET FOREIGN_KEY_CHECKS = 1");
+
+// When 'c' goes out of scope, the connection is returned to 'db'.
+  
+ +

Some of the use cases which may require direct manipulation of + connections include out-of-transaction statement execution, + such as execution of connection configuration statements, + implementation of a connection-per-thread policy, and making + sure that a set of transactions is executed on the same + connection.

+ +

3.6 Error Handling and Recovery

ODB uses C++ exceptions to report database operation errors. Most ODB exceptions signify hard errors or errors that cannot @@ -2354,7 +2460,7 @@ update_age (database& db, person& p) instance, by obtaining a valid object id and trying again. The hard errors and corresponding ODB exceptions that can be thrown by each database function are described in the remainder - of this chapter with Section 3.11, "ODB Exceptions" + of this chapter with Section 3.12, "ODB Exceptions" providing a quick reference for all the ODB exceptions.

The second group of ODB exceptions signify soft or @@ -2421,7 +2527,7 @@ for (unsigned short retry_count (0); ; retry_count++) } -

3.6 Making Objects Persistent

+

3.7 Making Objects Persistent

A newly created instance of a persistent class is transient. We use the database::persist() function template @@ -2507,7 +2613,7 @@ cerr << "Jane's id: " << jane_id << endl; threads in your application and to other applications as soon as possible.

-

3.7 Loading Persistent Objects

+

3.8 Loading Persistent Objects

Once an object is made persistent, and you know its object id, it can be loaded by the application using the database::load() @@ -2572,7 +2678,7 @@ t.commit (); identifier can be significantly faster than executing a query.

-

3.8 Updating Persistent Objects

+

3.9 Updating Persistent Objects

If a persistent object has been modified, we can store the updated state in the database using the database::update() @@ -2636,25 +2742,25 @@ transfer (database& db, for example:

-  transaction t (db.begin ());
+transaction t (db.begin ());
 
-  shared_ptr<bank_account> from (db.load<bank_account> (from_acc));
+shared_ptr<bank_account> from (db.load<bank_account> (from_acc));
 
-  if (from->balance () < amount)
-    throw insufficient_funds ();
+if (from->balance () < amount)
+  throw insufficient_funds ();
 
-  shared_ptr<bank_account> to (db.load<bank_account> (to_acc));
+shared_ptr<bank_account> to (db.load<bank_account> (to_acc));
 
-  to->balance (to->balance () + amount);
-  from->balance (from->balance () - amount);
+to->balance (to->balance () + amount);
+from->balance (from->balance () - amount);
 
-  db.update (to);
-  db.update (from);
+db.update (to);
+db.update (from);
 
-  t.commit ();
+t.commit ();
   
-

3.9 Deleting Persistent Objects

+

3.10 Deleting Persistent Objects

To delete a persistent object's state from the database we use the database::erase() or database::erase_query() @@ -2746,7 +2852,7 @@ db.erase_query<person> (query::last == "Doe" && query::are < 30); t.commit (); -

3.10 Executing Native SQL Statements

+

3.11 Executing Native SQL Statements

In some situations we may need to execute native SQL statements instead of using the object-oriented database API described above. @@ -2784,7 +2890,13 @@ db.execute ("CREATE TABLE test (n INT PRIMARY KEY)"); t.commit (); -

3.11 ODB Exceptions

+

While these functions must always be called within a transaction, + it may be necessary to execute a native statement outside any + transaction. This can be done using the + connection::execute() functions as described in + Section 3.5, "Connections".

+ +

3.12 ODB Exceptions

In the previous sections we have already mentioned some of the exceptions that can be thrown by the database functions. In this @@ -2951,19 +3063,19 @@ namespace odb has timed out. The deadlock exception is thrown when a transaction deadlock is detected by the database system. These exceptions can be thrown by any database function. See - Section 3.5, "Error Handling and Recovery" + Section 3.6, "Error Handling and Recovery" for details.

The object_already_persistent exception is thrown by the persist() database function. See - Section 3.6, "Making Objects Persistent" + Section 3.7, "Making Objects Persistent" for details.

The object_not_persistent exception is thrown by the load() and update() database functions. Refer to - Section 3.7, "Loading Persistent Objects" and - Section 3.8, "Updating Persistent Objects" for + Section 3.8, "Loading Persistent Objects" and + Section 3.9, "Updating Persistent Objects" for more information.

The result_not_cached exception is thrown by @@ -5769,9 +5881,9 @@ namespace odb

A session is an object cache. Every time an object is made persistent by calling the database::persist() function - (Section 3.6, "Making Objects Persistent"), loaded + (Section 3.7, "Making Objects Persistent"), loaded by calling the database::load() or database::find() - function (Section 3.7, "Loading Persistent Objects"), + function (Section 3.8, "Loading Persistent Objects"), 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 @@ -5779,7 +5891,7 @@ namespace odb 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 - (Section 3.9, "Deleting Persistent Objects"), the + (Section 3.10, "Deleting Persistent Objects"), the cached object pointer is removed from the session. For example:

@@ -7020,7 +7132,7 @@ class person
      choice.

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

+ refer to Section 3.7, "Making Objects Persistent".

10.3.3 type

@@ -8115,7 +8227,7 @@ namespace odb client_flags () const; public: - details::shared_ptr<mysql::connection> + connection_ptr connection (); }; } @@ -8179,17 +8291,39 @@ namespace odb

The set of accessor functions following the constructors allows us to query the parameters of the database instance.

-

The connection() function returns the MySQL database - connection encapsulated by the odb::mysql::connection - class. Normally, we wouldn't call this function directly and - instead let the ODB runtime manage the database connections. However, - if for some reason you need to access the underlying MySQL connection - handle, refer to the MySQL ODB runtime source code for the interface - of the connection class.

+

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

+ +

11.3 MySQL Connection and Connection Factory

-

11.3 MySQL Connection Factory

+

The mysql::connection class has the following interface:

-

The connection_factory abstract class has the +

+namespace odb
+{
+  namespace mysql
+  {
+    class connection: public odb::connection
+    {
+    public:
+      MYSQL*
+      handle ();
+    };
+
+    typedef details::shared_ptr<connection> connection_ptr;
+  }
+}
+  
+ +

For more information on the odb::connection interface, + refer to Section 3.5, "Connections". The + handle() accessor returns the native MySQL handle + corresponding to the connection.

+ +

The mysql::connection_factory abstract class has the following interface:

@@ -8201,9 +8335,9 @@ namespace odb
     {
     public:
       virtual void
-      database (mysql::database&) = 0;
+      database (database&) = 0;
 
-      virtual details::shared_ptr<mysql::connection>
+      virtual connection_ptr
       connect () = 0;
     };
   }
@@ -8224,7 +8358,6 @@ namespace odb
      header file to make the connection_factory interface
      and these implementation classes available in your application.

-

The new_connection_factory class creates a new connection whenever one is requested. When a connection is no longer needed, it is released and closed. The @@ -8582,14 +8715,14 @@ namespace odb flags () const; public: - transaction_impl* + transaction begin_immediate (); - transaction_impl* + transaction begin_exclusive (); public: - details::shared_ptr&lt;sqlite::connection> + connection_ptr connection (); }; } @@ -8682,17 +8815,50 @@ auto_ptr<odb::database> db ( transactions, refer to the BEGIN statement description in the SQLite documentation.

-

The connection() function returns the SQLite database - connection encapsulated by the odb::sqlite::connection - class. Normally, we wouldn't call this function directly and - instead let the ODB runtime manage the database connections. However, - if for some reason you need to access the underlying SQLite connection - handle, refer to the SQLite ODB runtime source code for the interface - of the connection class.

+

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

+ +

12.3 SQLite Connection and Connection Factory

+ +

The sqlite::connection class has the following interface:

+ +
+namespace odb
+{
+  namespace sqlite
+  {
+    class connection: public odb::connection
+    {
+    public:
+      transaction
+      begin_immediate ();
+
+      transaction
+      begin_exclusive ();
+
+      sqlite3*
+      handle ();
+    };
+
+    typedef details::shared_ptr<connection> connection_ptr;
+  }
+}
+  
-

12.3 SQLite Connection Factory

+

For more information on the odb::connection interface, + refer to Section 3.5, "Connections". The + begin_immediate() and begin_exclusive() + 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"). The handle() accessor + returns the native SQLite handle corresponding to the connection.

-

The connection_factory abstract class has the +

The sqlite::connection_factory abstract class has the following interface:

@@ -8704,9 +8870,9 @@ namespace odb
     {
     public:
       virtual void
-      database (sqlite::database&) = 0;
+      database (database&) = 0;
 
-      virtual details::shared_ptr<sqlite::connection>
+      virtual connection_ptr
       connect () = 0;
     };
   }
@@ -8919,7 +9085,7 @@ namespace odb
      SQLite results is the unavailability of the result::size()
      function. If you call this function on an SQLite query result, then
      the odb::result_not_cached exception
-     (Section 3.11, "ODB Exceptions") is always
+     (Section 3.12, "ODB Exceptions") is always
      thrown. Future versions of the SQLite ODB runtime library may add support
      for result caching.

@@ -8964,7 +9130,7 @@ class person

If foreign key constraints checking is disabled or not available, then inconsistencies in object relationships will not be detected. Furthermore, using the erase_query() function - (Section 3.9, "Deleting Persistent Objects") + (Section 3.10, "Deleting Persistent Objects") to delete persistent objects that contain containers will not work correctly. Container data for such objects will not be deleted.

@@ -9018,8 +9184,8 @@ CREATE TABLE Employee ( to distinguish between the duplicate primary key and other constraint violations. As a result, when making an object persistent, The SQLite ODB runtime will translate all constraint violation errors to the - object_not_persistent exception (Section - 3.11, "ODB Exceptions").

+ object_not_persistent exception (Section + 3.12, "ODB Exceptions").

12.5.5 Sharing of Queries

@@ -9272,7 +9438,7 @@ namespace odb conninfo () const; public: - details::shared_ptr<pgsql::connection> + connection_ptr connection (); }; } @@ -9290,7 +9456,7 @@ namespace odb The socket_ext argument in the second constructor is a string value specifying the UNIX-domain socket file name extension.

-

The third constructor allows us to specify all database parameters +

The third constructor allows us to specify all the database parameters as a single conninfo string. All other constructors accept additional database connection parameters as the extra_conninfo argument. For more information @@ -9347,17 +9513,39 @@ namespace odb conninfo string as passed in the extra_conninfo argument.

-

The connection() function returns the PostgreSQL database - connection encapsulated by the odb::pgsql::connection - class. Normally, we wouldn't call this function directly and - instead let the ODB runtime manage the database connections. However, - if for some reason you need to access the underlying PostgreSQL connection - handle, refer to the PostgreSQL ODB runtime source code for the interface - of the connection class.

+

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

+ +

13.3 PostgreSQL Connection and Connection Factory

+ +

The pgsql::connection class has the following interface:

+ +
+namespace odb
+{
+  namespace pgsql
+  {
+    class connection: public odb::connection
+    {
+    public:
+      PGconn*
+      handle ();
+    };
+
+    typedef details::shared_ptr<connection> connection_ptr;
+  }
+}
+  
-

13.3 PostgreSQL Connection Factory

+

For more information on the odb::connection interface, + refer to Section 3.5, "Connections". The + handle() accessor returns the native PostgreSQL handle + corresponding to the connection.

-

The connection_factory abstract class has the +

The pgsql::connection_factory abstract class has the following interface:

@@ -9369,9 +9557,9 @@ namespace odb
     {
     public:
       virtual void
-      database (pgsql::database&) = 0;
+      database (database&) = 0;
 
-      virtual details::shared_ptr<pgsql::connection>
+      virtual connection_ptr
       connect () = 0;
     };
   }
@@ -9686,7 +9874,7 @@ odb --profile boost/date-time ...
      system. All such exceptions derive from the
      odb::boost::exception class which in turn derives from
      the root of the ODB exception hierarchy, class odb::exception
-     (Section 3.11, "ODB Exceptions"). The
+     (Section 3.12, "ODB Exceptions"). The
      odb::boost::exception class is defined in the
      <odb/boost/exception.hxx> header file and has the
      same interface as odb::exception. The concrete exceptions
@@ -10107,7 +10295,7 @@ class person
      system. All such exceptions derive from the
      odb::qt::exception class which in turn derives from
      the root of the ODB exception hierarchy, class odb::exception
-     (Section 3.11, "ODB Exceptions"). The
+     (Section 3.12, "ODB Exceptions"). The
      odb::qt::exception class is defined in the
      <odb/qt/exception.hxx> header file and has the
      same interface as odb::exception. The concrete exceptions
-- 
cgit v1.1