From fa3f14db14671b4c37c400880d097b17aa12b824 Mon Sep 17 00:00:00 2001
From: Boris Kolpackov <boris@codesynthesis.com>
Date: Thu, 29 Apr 2021 11:55:45 +0200
Subject: Move begin/commit/rollback statements to connection

---
 odb/sqlite/connection.cxx       | 46 +++++++++++++++++++++++++++++++++++
 odb/sqlite/connection.hxx       | 27 +++++++++++++++++++++
 odb/sqlite/connection.ixx       |  2 +-
 odb/sqlite/statement-cache.cxx  | 39 -----------------------------
 odb/sqlite/statement-cache.hxx  | 54 +++--------------------------------------
 odb/sqlite/transaction-impl.cxx | 15 +++++-------
 6 files changed, 83 insertions(+), 100 deletions(-)
 delete mode 100644 odb/sqlite/statement-cache.cxx

diff --git a/odb/sqlite/connection.cxx b/odb/sqlite/connection.cxx
index cdd4c20..57ce860 100644
--- a/odb/sqlite/connection.cxx
+++ b/odb/sqlite/connection.cxx
@@ -25,6 +25,8 @@ odb_sqlite_connection_unlock_callback (void**, int);
 
 namespace odb
 {
+  using namespace details;
+
   namespace sqlite
   {
     connection::
@@ -105,6 +107,12 @@ namespace odb
         db.foreign_keys () ? 22 : 23);
       st.execute ();
 
+      // String lengths include '\0', as per the SQLite manual suggestion.
+      //
+      begin_.reset (new (shared) generic_statement (*this, "BEGIN", 6));
+      commit_.reset (new (shared) generic_statement (*this, "COMMIT", 7));
+      rollback_.reset (new (shared) generic_statement (*this, "ROLLBACK", 9));
+
       // Create statement cache.
       //
       statement_cache_.reset (new statement_cache_type (*this));
@@ -119,6 +127,44 @@ namespace odb
       clear_prepared_map ();
     }
 
+    generic_statement& connection::
+    begin_statement ()
+    {
+      return static_cast<generic_statement&> (*begin_);
+    }
+
+    generic_statement& connection::
+    begin_immediate_statement ()
+    {
+      if (!begin_immediate_)
+        begin_immediate_.reset (
+          new (shared) generic_statement (*this, "BEGIN IMMEDIATE", 16));
+
+      return static_cast<generic_statement&> (*begin_immediate_);
+    }
+
+    generic_statement& connection::
+    begin_exclusive_statement ()
+    {
+      if (!begin_exclusive_)
+        begin_exclusive_.reset (
+          new (shared) generic_statement (*this, "BEGIN EXCLUSIVE", 16));
+
+      return static_cast<generic_statement&> (*begin_exclusive_);
+    }
+
+    generic_statement& connection::
+    commit_statement ()
+    {
+      return static_cast<generic_statement&> (*commit_);
+    }
+
+    generic_statement& connection::
+    rollback_statement ()
+    {
+      return static_cast<generic_statement&> (*rollback_);
+    }
+
     transaction_impl* connection::
     begin ()
     {
diff --git a/odb/sqlite/connection.hxx b/odb/sqlite/connection.hxx
index 254a002..30bb467 100644
--- a/odb/sqlite/connection.hxx
+++ b/odb/sqlite/connection.hxx
@@ -8,6 +8,7 @@
 
 #include <sqlite3.h>
 
+#include <odb/statement.hxx>
 #include <odb/connection.hxx>
 
 #include <odb/details/mutex.hxx>
@@ -29,6 +30,7 @@ namespace odb
   namespace sqlite
   {
     class statement_cache;
+    class generic_statement;
     class connection_factory;
 
     class connection;
@@ -164,6 +166,22 @@ namespace odb
       void
       clear ();
 
+    public:
+      generic_statement&
+      begin_statement ();
+
+      generic_statement&
+      begin_immediate_statement ();
+
+      generic_statement&
+      begin_exclusive_statement ();
+
+      generic_statement&
+      commit_statement ();
+
+      generic_statement&
+      rollback_statement ();
+
     private:
       connection (const connection&);
       connection& operator= (const connection&);
@@ -180,6 +198,15 @@ namespace odb
       //
       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:
diff --git a/odb/sqlite/connection.ixx b/odb/sqlite/connection.ixx
index c1bf77a..69739b7 100644
--- a/odb/sqlite/connection.ixx
+++ b/odb/sqlite/connection.ixx
@@ -5,7 +5,7 @@ namespace odb
 {
   namespace sqlite
   {
-    // active_objects
+    // active_object
     //
     inline void active_object::
     list_add ()
diff --git a/odb/sqlite/statement-cache.cxx b/odb/sqlite/statement-cache.cxx
deleted file mode 100644
index 095dcad..0000000
--- a/odb/sqlite/statement-cache.cxx
+++ /dev/null
@@ -1,39 +0,0 @@
-// file      : odb/sqlite/statement-cache.cxx
-// license   : GNU GPL v2; see accompanying LICENSE file
-
-#include <odb/sqlite/statement-cache.hxx>
-
-namespace odb
-{
-  using namespace details;
-
-  namespace sqlite
-  {
-    statement_cache::
-    statement_cache (connection& conn)
-        : conn_ (conn),
-          version_seq_ (conn.database ().schema_version_sequence ()),
-          // String lengths below include '\0', as per SQLite manual
-          // suggestions.
-          //
-          begin_ (new (shared) generic_statement (conn_, "BEGIN", 6)),
-          commit_ (new (shared) generic_statement (conn_, "COMMIT", 7)),
-          rollback_ (new (shared) generic_statement (conn_, "ROLLBACK", 9))
-    {
-    }
-
-    void statement_cache::
-    begin_immediate_statement_ () const
-    {
-      begin_immediate_.reset (
-        new (shared) generic_statement (conn_, "BEGIN IMMEDIATE", 16));
-    }
-
-    void statement_cache::
-    begin_exclusive_statement_ () const
-    {
-      begin_exclusive_.reset (
-        new (shared) generic_statement (conn_, "BEGIN EXCLUSIVE", 16));
-    }
-  }
-}
diff --git a/odb/sqlite/statement-cache.hxx b/odb/sqlite/statement-cache.hxx
index b42bda4..923b428 100644
--- a/odb/sqlite/statement-cache.hxx
+++ b/odb/sqlite/statement-cache.hxx
@@ -29,43 +29,9 @@ namespace odb
     class LIBODB_SQLITE_EXPORT statement_cache
     {
     public:
-      statement_cache (connection&);
-
-      generic_statement&
-      begin_statement () const
-      {
-        return *begin_;
-      }
-
-      generic_statement&
-      begin_immediate_statement () const
-      {
-        if (!begin_immediate_)
-          begin_immediate_statement_ ();
-
-        return *begin_immediate_;
-      }
-
-      generic_statement&
-      begin_exclusive_statement () const
-      {
-        if (!begin_exclusive_)
-          begin_exclusive_statement_ ();
-
-        return *begin_exclusive_;
-      }
-
-      generic_statement&
-      commit_statement () const
-      {
-        return *commit_;
-      }
-
-      generic_statement&
-      rollback_statement () const
-      {
-        return *rollback_;
-      }
+      statement_cache (connection& conn)
+          : conn_ (conn),
+            version_seq_ (conn.database ().schema_version_sequence ()) {}
 
       template <typename T>
       typename object_traits_impl<T, id_sqlite>::statements_type&
@@ -76,26 +42,12 @@ namespace odb
       find_view ();
 
     private:
-      void
-      begin_immediate_statement_ () const;
-
-      void
-      begin_exclusive_statement_ () const;
-
-    private:
       typedef std::map<const std::type_info*,
                        details::shared_ptr<statements_base>,
                        details::type_info_comparator> map;
 
       connection& conn_;
       unsigned int version_seq_;
-
-      details::shared_ptr<generic_statement> begin_;
-      mutable details::shared_ptr<generic_statement> begin_immediate_;
-      mutable details::shared_ptr<generic_statement> begin_exclusive_;
-      details::shared_ptr<generic_statement> commit_;
-      details::shared_ptr<generic_statement> rollback_;
-
       map map_;
     };
   }
diff --git a/odb/sqlite/transaction-impl.cxx b/odb/sqlite/transaction-impl.cxx
index b1b83c8..721b3fe 100644
--- a/odb/sqlite/transaction-impl.cxx
+++ b/odb/sqlite/transaction-impl.cxx
@@ -6,7 +6,6 @@
 #include <odb/sqlite/database.hxx>
 #include <odb/sqlite/connection.hxx>
 #include <odb/sqlite/statement.hxx>
-#include <odb/sqlite/statement-cache.hxx>
 #include <odb/sqlite/transaction-impl.hxx>
 
 namespace odb
@@ -43,23 +42,21 @@ namespace odb
         odb::transaction_impl::connection_ = connection_.get ();
       }
 
-      statement_cache& sc (connection_->statement_cache ());
-
       switch (lock_)
       {
       case deferred:
         {
-          sc.begin_statement ().execute ();
+          connection_->begin_statement ().execute ();
           break;
         }
       case immediate:
         {
-          sc.begin_immediate_statement ().execute ();
+          connection_->begin_immediate_statement ().execute ();
           break;
         }
       case exclusive:
         {
-          sc.begin_exclusive_statement ().execute ();
+          connection_->begin_exclusive_statement ().execute ();
           break;
         }
       }
@@ -82,7 +79,7 @@ namespace odb
           //
           try
           {
-            c_->statement_cache ().rollback_statement ().execute ();
+            c_->rollback_statement ().execute ();
           }
           catch (...) {}
         }
@@ -106,7 +103,7 @@ namespace odb
 
       {
         commit_guard cg (*connection_);
-        connection_->statement_cache ().commit_statement ().execute ();
+        connection_->commit_statement ().execute ();
         cg.release ();
       }
 
@@ -123,7 +120,7 @@ namespace odb
       //
       connection_->clear ();
 
-      connection_->statement_cache ().rollback_statement ().execute ();
+      connection_->rollback_statement ().execute ();
 
       // Release the connection.
       //
-- 
cgit v1.1