diff options
Diffstat (limited to 'odb/sqlite/connection.hxx')
-rw-r--r-- | odb/sqlite/connection.hxx | 143 |
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_; + }; } } |