diff Framework/Common/DatabaseManager.cpp @ 70:e6c13ddd26d9 db-changes

all integration tests passing with LookupResources extension
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 03 Jan 2019 14:04:46 +0100
parents 714c5d2bee76
children 569e17419eae
line wrap: on
line diff
--- a/Framework/Common/DatabaseManager.cpp	Thu Jan 03 10:07:27 2019 +0100
+++ b/Framework/Common/DatabaseManager.cpp	Thu Jan 03 14:04:46 2019 +0100
@@ -279,34 +279,6 @@
   }
 
 
-  IResult& DatabaseManager::CachedStatement::GetResult() const
-  {
-    if (result_.get() == NULL)
-    {
-      LOG(ERROR) << "Accessing the results of a statement without having executed it";
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
-    }
-
-    return *result_;
-  }
-
-
-  void DatabaseManager::CachedStatement::Setup(const char* sql)
-  {
-    statement_ = manager_.LookupCachedStatement(location_);
-
-    if (statement_ == NULL)
-    {
-      query_.reset(new Query(sql));
-    }
-    else
-    {
-      LOG(TRACE) << "Reusing cached statement from "
-                 << location_.GetFile() << ":" << location_.GetLine();
-    }
-  }
-
-
   DatabaseManager::Transaction::Transaction(DatabaseManager& manager) :
     lock_(manager.mutex_),
     manager_(manager),
@@ -347,40 +319,72 @@
     }
   }
 
-  
-  DatabaseManager::CachedStatement::CachedStatement(const StatementLocation& location,
-                                                    DatabaseManager& manager,
-                                                    const char* sql) :
-    manager_(manager),
-    lock_(manager_.mutex_),
-    database_(manager_.GetDatabase()),
-    location_(location),
-    transaction_(manager_.GetTransaction())
+
+  IResult& DatabaseManager::StatementBase::GetResult() const
   {
-    Setup(sql);
-  }
+    if (result_.get() == NULL)
+    {
+      LOG(ERROR) << "Accessing the results of a statement without having executed it";
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+    }
 
-      
-  DatabaseManager::CachedStatement::CachedStatement(const StatementLocation& location,
-                                                    Transaction& transaction,
-                                                    const char* sql) :
-    manager_(transaction.GetManager()),
-    lock_(manager_.mutex_),
-    database_(manager_.GetDatabase()),
-    location_(location),
-    transaction_(manager_.GetTransaction())
-  {
-    Setup(sql);
+    return *result_;
   }
 
 
-  DatabaseManager::CachedStatement::~CachedStatement()
+  void DatabaseManager::StatementBase::SetQuery(Query* query)
+  {
+    std::auto_ptr<Query> protection(query);
+    
+    if (query_.get() != NULL)
+    {
+      LOG(ERROR) << "Cannot set twice a query";
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+    }
+
+    if (query == NULL)
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
+    }
+
+    query_.reset(protection.release());
+  }
+
+  
+  void DatabaseManager::StatementBase::SetResult(IResult* result)
+  {
+    std::auto_ptr<IResult> protection(result);
+    
+    if (result_.get() != NULL)
+    {
+      LOG(ERROR) << "Cannot execute twice a statement";
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+    }
+
+    if (result == NULL)
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
+    }
+
+    result_.reset(protection.release());
+  }
+
+  
+  DatabaseManager::StatementBase::StatementBase(DatabaseManager& manager) :
+    manager_(manager),
+    lock_(manager_.mutex_),
+    transaction_(manager_.GetTransaction())
+  {
+  }
+
+
+  DatabaseManager::StatementBase::~StatementBase()
   {
     manager_.ReleaseImplicitTransaction();
   }
+
   
-      
-  void DatabaseManager::CachedStatement::SetReadOnly(bool readOnly)
+  void DatabaseManager::StatementBase::SetReadOnly(bool readOnly)
   {
     if (query_.get() != NULL)
     {
@@ -389,8 +393,8 @@
   }
 
 
-  void DatabaseManager::CachedStatement::SetParameterType(const std::string& parameter,
-                                                          ValueType type)
+  void DatabaseManager::StatementBase::SetParameterType(const std::string& parameter,
+                                                        ValueType type)
   {
     if (query_.get() != NULL)
     {
@@ -398,44 +402,7 @@
     }
   }
       
-      
-  void DatabaseManager::CachedStatement::Execute()
-  {
-    Dictionary parameters;
-    Execute(parameters);
-  }
-
-
-  void DatabaseManager::CachedStatement::Execute(const Dictionary& parameters)
-  {
-    if (result_.get() != NULL)
-    {
-      LOG(ERROR) << "Cannot execute twice a statement";
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
-    }
-
-    try
-    {
-      if (query_.get() != NULL)
-      {
-        // Register the newly-created statement
-        assert(statement_ == NULL);
-        statement_ = &manager_.CacheStatement(location_, *query_);
-        query_.reset(NULL);
-      }
-        
-      assert(statement_ != NULL);
-      result_.reset(transaction_.Execute(*statement_, parameters));
-    }
-    catch (Orthanc::OrthancException& e)
-    {
-      manager_.CloseIfUnavailable(e.GetErrorCode());
-      throw;
-    }
-  }
-
-
-  bool DatabaseManager::CachedStatement::IsDone() const
+  bool DatabaseManager::StatementBase::IsDone() const
   {
     try
     {
@@ -449,7 +416,7 @@
   }
 
 
-  void DatabaseManager::CachedStatement::Next()
+  void DatabaseManager::StatementBase::Next()
   {
     try
     {
@@ -463,7 +430,7 @@
   }
 
 
-  size_t DatabaseManager::CachedStatement::GetResultFieldsCount() const
+  size_t DatabaseManager::StatementBase::GetResultFieldsCount() const
   {
     try
     {
@@ -477,8 +444,8 @@
   }
 
 
-  void DatabaseManager::CachedStatement::SetResultFieldType(size_t field,
-                                                            ValueType type)
+  void DatabaseManager::StatementBase::SetResultFieldType(size_t field,
+                                                          ValueType type)
   {
     try
     {
@@ -495,7 +462,7 @@
   }
 
 
-  const IValue& DatabaseManager::CachedStatement::GetResultField(size_t index) const
+  const IValue& DatabaseManager::StatementBase::GetResultField(size_t index) const
   {
     try
     {
@@ -506,5 +473,88 @@
       manager_.CloseIfUnavailable(e.GetErrorCode());
       throw;
     }
+  }  
+  
+  
+  DatabaseManager::CachedStatement::CachedStatement(const StatementLocation& location,
+                                                    DatabaseManager& manager,
+                                                    const std::string& sql) :
+    StatementBase(manager),
+    location_(location)
+  {
+    statement_ = GetManager().LookupCachedStatement(location_);
+
+    if (statement_ == NULL)
+    {
+      SetQuery(new Query(sql));
+    }
+    else
+    {
+      LOG(TRACE) << "Reusing cached statement from "
+                 << location_.GetFile() << ":" << location_.GetLine();
+    }
+  }
+
+      
+  void DatabaseManager::CachedStatement::Execute(const Dictionary& parameters)
+  {
+    try
+    {
+      std::auto_ptr<Query> query(ReleaseQuery());
+      
+      if (query.get() != NULL)
+      {
+        // Register the newly-created statement
+        assert(statement_ == NULL);
+        statement_ = &GetManager().CacheStatement(location_, *query);
+      }
+        
+      assert(statement_ != NULL);
+      SetResult(GetTransaction().Execute(*statement_, parameters));
+    }
+    catch (Orthanc::OrthancException& e)
+    {
+      GetManager().CloseIfUnavailable(e.GetErrorCode());
+      throw;
+    }
+  }
+  
+  
+  DatabaseManager::StandaloneStatement::StandaloneStatement(DatabaseManager& manager,
+                                                            const std::string& sql) :
+    StatementBase(manager)
+  {
+    SetQuery(new Query(sql));
+  }
+
+      
+  DatabaseManager::StandaloneStatement::~StandaloneStatement()
+  {
+    // The result must be removed before the statement, cf. (*)
+    ClearResult();
+    statement_.reset();
+  }
+
+
+  void DatabaseManager::StandaloneStatement::Execute(const Dictionary& parameters)
+  {
+    try
+    {
+      std::auto_ptr<Query> query(ReleaseQuery());
+      assert(query.get() != NULL);
+
+      // The "statement_" object must be kept as long as the "IResult"
+      // is not destroyed, as the "IResult" can make calls to the
+      // statement (this is the case for SQLite and MySQL) - (*)
+      statement_.reset(GetManager().GetDatabase().Compile(*query));
+      assert(statement_.get() != NULL);
+
+      SetResult(GetTransaction().Execute(*statement_, parameters));
+    }
+    catch (Orthanc::OrthancException& e)
+    {
+      GetManager().CloseIfUnavailable(e.GetErrorCode());
+      throw;
+    }
   }
 }