Commit 1fad9471 authored by Sebastien Jodogne's avatar Sebastien Jodogne
Browse files

New upstream version 3.0

parent ab5bf362
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
repo: 7cea966b682978aa285eb9b3a7a9cff81df464b3
node: 4b2dab49b6ea1f3369e769b0ce94e00c4ea32f1f
branch: OrthancPostgreSQL-2.2
node: deab01d8e1c85149e9059194bec266abd038c152
branch: OrthancPostgreSQL-3.0
latesttag: null
latesttagdistance: 34
changessincelatesttag: 36
latesttagdistance: 90
changessincelatesttag: 100
+1 −1
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@ Database plugins for Orthanc
Authors
-------

* Sebastien Jodogne <s.jodogne@gmail.com>
* Sebastien Jodogne <s.jodogne@orthanc-labs.com>

  Overall design and lead developer.

+1 −1
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@
 * Orthanc - A Lightweight, RESTful DICOM Store
 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
 * Department, University Hospital of Liege, Belgium
 * Copyright (C) 2017-2018 Osimis S.A., Belgium
 * Copyright (C) 2017-2019 Osimis S.A., Belgium
 *
 * This program is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License
+1 −1
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@
 * Orthanc - A Lightweight, RESTful DICOM Store
 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
 * Department, University Hospital of Liege, Belgium
 * Copyright (C) 2017-2018 Osimis S.A., Belgium
 * Copyright (C) 2017-2019 Osimis S.A., Belgium
 *
 * This program is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License
+137 −87
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@
 * Orthanc - A Lightweight, RESTful DICOM Store
 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
 * Department, University Hospital of Liege, Belgium
 * Copyright (C) 2017-2018 Osimis S.A., Belgium
 * Copyright (C) 2017-2019 Osimis S.A., Belgium
 *
 * This program is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License
@@ -279,34 +279,6 @@ namespace OrthancDatabases
  }


  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),
@@ -348,39 +320,71 @@ namespace OrthancDatabases
  }


  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
  {
    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::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)
    {
    Setup(sql);
      throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
    }

    query_.reset(protection.release());
  }

  DatabaseManager::CachedStatement::CachedStatement(const StatementLocation& location,
                                                    Transaction& transaction,
                                                    const char* sql) :
    manager_(transaction.GetManager()),
  
  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_),
    database_(manager_.GetDatabase()),
    location_(location),
    transaction_(manager_.GetTransaction())
  {
    Setup(sql);
  }


  DatabaseManager::CachedStatement::~CachedStatement()
  DatabaseManager::StatementBase::~StatementBase()
  {
    manager_.ReleaseImplicitTransaction();
  }

  
  void DatabaseManager::CachedStatement::SetReadOnly(bool readOnly)
  void DatabaseManager::StatementBase::SetReadOnly(bool readOnly)
  {
    if (query_.get() != NULL)
    {
@@ -389,7 +393,7 @@ namespace OrthancDatabases
  }


  void DatabaseManager::CachedStatement::SetParameterType(const std::string& parameter,
  void DatabaseManager::StatementBase::SetParameterType(const std::string& parameter,
                                                        ValueType type)
  {
    if (query_.get() != NULL)
@@ -398,34 +402,25 @@ namespace OrthancDatabases
    }
  }
      
      
  void DatabaseManager::CachedStatement::Execute()
  bool DatabaseManager::StatementBase::IsDone() const
  {
    Dictionary parameters;
    Execute(parameters);
  }


  void DatabaseManager::CachedStatement::Execute(const Dictionary& parameters)
    try
    {
    if (result_.get() != NULL)
      return GetResult().IsDone();
    }
    catch (Orthanc::OrthancException& e)
    {
      LOG(ERROR) << "Cannot execute twice a statement";
      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
      manager_.CloseIfUnavailable(e.GetErrorCode());
      throw;
    }
  }

    try

  void DatabaseManager::StatementBase::Next()
  {
      if (query_.get() != NULL)
    try
    {
        // 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));
      GetResult().Next();
    }
    catch (Orthanc::OrthancException& e)
    {
@@ -435,11 +430,11 @@ namespace OrthancDatabases
  }


  bool DatabaseManager::CachedStatement::IsDone() const
  size_t DatabaseManager::StatementBase::GetResultFieldsCount() const
  {
    try
    {
      return GetResult().IsDone();
      return GetResult().GetFieldsCount();
    }
    catch (Orthanc::OrthancException& e)
    {
@@ -449,11 +444,15 @@ namespace OrthancDatabases
  }


  void DatabaseManager::CachedStatement::Next()
  void DatabaseManager::StatementBase::SetResultFieldType(size_t field,
                                                          ValueType type)
  {
    try
    {
      GetResult().Next();
      if (!GetResult().IsDone())
      {
        GetResult().SetExpectedType(field, type);
      }
    }
    catch (Orthanc::OrthancException& e)
    {
@@ -463,11 +462,11 @@ namespace OrthancDatabases
  }


  size_t DatabaseManager::CachedStatement::GetResultFieldsCount() const
  const IValue& DatabaseManager::StatementBase::GetResultField(size_t index) const
  {
    try
    {
      return GetResult().GetFieldsCount();
      return GetResult().GetField(index);
    }
    catch (Orthanc::OrthancException& e)
    {
@@ -477,33 +476,84 @@ namespace OrthancDatabases
  }  
  
  
  void DatabaseManager::CachedStatement::SetResultFieldType(size_t field,
                                                            ValueType type)
  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
    {
      if (!GetResult().IsDone())
      std::auto_ptr<Query> query(ReleaseQuery());
      
      if (query.get() != NULL)
      {
        GetResult().SetExpectedType(field, type);
        // 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)
    {
      manager_.CloseIfUnavailable(e.GetErrorCode());
      GetManager().CloseIfUnavailable(e.GetErrorCode());
      throw;
    }
  }
  
  
  const IValue& DatabaseManager::CachedStatement::GetResultField(size_t index) const
  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
    {
      return GetResult().GetField(index);
      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)
    {
      manager_.CloseIfUnavailable(e.GetErrorCode());
      GetManager().CloseIfUnavailable(e.GetErrorCode());
      throw;
    }
  }
Loading