Skip to content
Commits on Source (11)
repo: 7cea966b682978aa285eb9b3a7a9cff81df464b3
node: 4b2dab49b6ea1f3369e769b0ce94e00c4ea32f1f
branch: OrthancPostgreSQL-2.2
node: deab01d8e1c85149e9059194bec266abd038c152
branch: OrthancPostgreSQL-3.0
latesttag: null
latesttagdistance: 34
changessincelatesttag: 36
latesttagdistance: 90
changessincelatesttag: 100
......@@ -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.
......
......@@ -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
......
......@@ -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
......
......@@ -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;
}
}
......
......@@ -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
......@@ -111,36 +111,51 @@ namespace OrthancDatabases
};
class CachedStatement : public boost::noncopyable
class StatementBase : public boost::noncopyable
{
private:
DatabaseManager& manager_;
boost::recursive_mutex::scoped_lock lock_;
IDatabase& database_;
StatementLocation location_;
ITransaction& transaction_;
IPrecompiledStatement* statement_;
std::auto_ptr<Query> query_;
std::auto_ptr<IResult> result_;
void Setup(const char* sql);
IResult& GetResult() const;
public:
CachedStatement(const StatementLocation& location,
DatabaseManager& manager,
const char* sql);
protected:
DatabaseManager& GetManager() const
{
return manager_;
}
CachedStatement(const StatementLocation& location,
Transaction& transaction,
const char* sql);
ITransaction& GetTransaction() const
{
return transaction_;
}
void SetQuery(Query* query);
~CachedStatement();
void SetResult(IResult* result);
void ClearResult()
{
result_.reset();
}
Query* ReleaseQuery()
{
return query_.release();
}
public:
explicit StatementBase(DatabaseManager& manager);
virtual ~StatementBase();
// Used only by SQLite
IDatabase& GetDatabase()
{
return database_;
return manager_.GetDatabase();
}
void SetReadOnly(bool readOnly);
......@@ -148,10 +163,6 @@ namespace OrthancDatabases
void SetParameterType(const std::string& parameter,
ValueType type);
void Execute();
void Execute(const Dictionary& parameters);
bool IsDone() const;
void Next();
......@@ -163,5 +174,47 @@ namespace OrthancDatabases
const IValue& GetResultField(size_t index) const;
};
class CachedStatement : public StatementBase
{
private:
StatementLocation location_;
IPrecompiledStatement* statement_;
public:
CachedStatement(const StatementLocation& location,
DatabaseManager& manager,
const std::string& sql);
void Execute()
{
Dictionary parameters;
Execute(parameters);
}
void Execute(const Dictionary& parameters);
};
class StandaloneStatement : public StatementBase
{
private:
std::auto_ptr<IPrecompiledStatement> statement_;
public:
StandaloneStatement(DatabaseManager& manager,
const std::string& sql);
virtual ~StandaloneStatement();
void Execute()
{
Dictionary parameters;
Execute(parameters);
}
void Execute(const Dictionary& parameters);
};
};
}
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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
......