aboutsummaryrefslogtreecommitdiff
path: root/odb/sqlite/connection.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'odb/sqlite/connection.hxx')
-rw-r--r--odb/sqlite/connection.hxx143
1 files changed, 132 insertions, 11 deletions
diff --git a/odb/sqlite/connection.hxx b/odb/sqlite/connection.hxx
index a71f07e..dbe4494 100644
--- a/odb/sqlite/connection.hxx
+++ b/odb/sqlite/connection.hxx
@@ -1,5 +1,4 @@
// file : odb/sqlite/connection.hxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_SQLITE_CONNECTION_HXX
@@ -9,6 +8,7 @@
#include <sqlite3.h>
+#include <odb/statement.hxx>
#include <odb/connection.hxx>
#include <odb/details/mutex.hxx>
@@ -30,20 +30,22 @@ namespace odb
namespace sqlite
{
class statement_cache;
+ class generic_statement;
class connection_factory;
+ class attached_connection_factory;
class connection;
typedef details::shared_ptr<connection> connection_ptr;
// SQLite "active object", i.e., an object that needs to be
// "cleared" before the transaction can be committed and the
- // connection release. These form a doubly-linked list.
+ // connection released. These form a doubly-linked list.
//
class LIBODB_SQLITE_EXPORT active_object
{
public:
- // This function should remove the object from the list, since
- // it shall no longer be "active".
+ // This function may remove the object from the list since it may no
+ // longer be "active".
//
virtual void
clear () = 0;
@@ -58,6 +60,8 @@ namespace odb
list_remove ();
protected:
+ friend class connection;
+
// prev_ == 0 means we are the first element.
// next_ == 0 means we are the last element.
// next_ == this means we are not on the list (prev_ should be 0).
@@ -74,15 +78,42 @@ namespace odb
typedef sqlite::statement_cache statement_cache_type;
typedef sqlite::database database_type;
+ // Translate the database schema in the statement text (used to
+ // implement attached databases). If the result is empty, then no
+ // translation is required and the original text should be used as is.
+ //
+ typedef void (statement_translator) (std::string& result,
+ const char* text,
+ std::size_t text_size,
+ connection&);
virtual
~connection ();
- connection (connection_factory&, int extra_flags = 0);
- connection (connection_factory&, sqlite3* handle);
+ connection (connection_factory&,
+ int extra_flags = 0,
+ statement_translator* = 0);
+
+ connection (connection_factory&,
+ sqlite3* handle,
+ statement_translator* = 0);
+
+ // Create an attached connection (see the attached database constructor
+ // for details).
+ //
+ connection (attached_connection_factory&, statement_translator*);
database_type&
database ();
+ // Return the main connection of an attached connection. If this
+ // connection is main, return itself.
+ //
+ connection&
+ main_connection ();
+
+ static connection_ptr
+ main_connection (const connection_ptr&);
+
public:
virtual transaction_impl*
begin ();
@@ -139,10 +170,7 @@ namespace odb
public:
sqlite3*
- handle ()
- {
- return handle_;
- }
+ handle ();
statement_cache_type&
statement_cache ()
@@ -157,11 +185,36 @@ namespace odb
wait ();
public:
- // Reset active statements.
+ // Reset active statements. Also invalidates query results by first
+ // calling invalidate_results().
//
void
clear ();
+ public:
+ // Note: only available on main connection.
+ //
+ generic_statement&
+ begin_statement ();
+
+ generic_statement&
+ begin_immediate_statement ();
+
+ generic_statement&
+ begin_exclusive_statement ();
+
+ generic_statement&
+ commit_statement ();
+
+ generic_statement&
+ rollback_statement ();
+
+ protected:
+ friend class attached_connection_factory;
+
+ connection_factory&
+ factory ();
+
private:
connection (const connection&);
connection& operator= (const connection&);
@@ -171,13 +224,27 @@ namespace odb
init ();
private:
+ // Note that we use NULL handle as an indication of an attached
+ // connection.
+ //
auto_handle<sqlite3> handle_;
+ statement_translator* statement_translator_;
+
// Keep statement_cache_ after handle_ so that it is destroyed before
// the connection is closed.
//
details::unique_ptr<statement_cache_type> statement_cache_;
+ // Note: using odb::statement in order to break the connection-statement
+ // dependency cycle.
+ //
+ details::shared_ptr<odb::statement> begin_;
+ details::shared_ptr<odb::statement> begin_immediate_;
+ details::shared_ptr<odb::statement> begin_exclusive_;
+ details::shared_ptr<odb::statement> commit_;
+ details::shared_ptr<odb::statement> rollback_;
+
// Unlock notification machinery.
//
private:
@@ -189,6 +256,7 @@ namespace odb
connection_unlock_callback (void**, int);
private:
+ friend class statement; // statement_translator_
friend class transaction_impl; // invalidate_results()
// Linked list of active objects currently associated
@@ -219,12 +287,65 @@ namespace odb
connection_factory (): db_ (0) {}
+ // Attach/detach additional databases. Connection is one of the main
+ // connections created by this factory. Note: not called for "main" and
+ // "temp" schemas.
+ //
+ // The default implementations simply execute the ATTACH DATABASE and
+ // DETACH DATABASE SQLite statements.
+ //
+ virtual void
+ attach_database (const connection_ptr&,
+ const std::string& name,
+ const std::string& schema);
+
+ virtual void
+ detach_database (const connection_ptr&, const std::string& schema);
+
// Needed to break the circular connection_factory-database dependency
// (odb::connection_factory has the odb::database member).
//
protected:
database_type* db_;
};
+
+ // The call to database() should cause ATTACH DATABASE (or otherwise make
+ // sure the database is attached). Destruction of the factory should cause
+ // DETACH DATABASE (or otherwise notice that this factory no longer needs
+ // the database attached).
+ //
+ // Note that attached_connection_factory is an active object that
+ // registers itself with the main connection in order to get notified on
+ // transaction finalization.
+ //
+ class LIBODB_SQLITE_EXPORT attached_connection_factory:
+ public connection_factory,
+ public active_object
+ {
+ public:
+ explicit
+ attached_connection_factory (const connection_ptr& main)
+ : active_object (*main), main_connection_ (main) {}
+
+ virtual void
+ detach () = 0;
+
+ protected:
+ friend class database;
+ friend class connection;
+ friend class transaction_impl;
+
+ connection_factory&
+ main_factory ();
+
+ // Note that this essentially establishes a "framework" for all the
+ // attached connection factory implementations: they hold a counted
+ // reference to the main connection and they maintain a single shared
+ // attached connection.
+ //
+ connection_ptr main_connection_;
+ connection_ptr attached_connection_;
+ };
}
}