Mercurial > hg > orthanc-databases
diff PostgreSQL/Plugins/PostgreSQLIndex.cpp @ 97:66fd0d587773
integration db-changes->mainline
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 21 Jan 2019 14:38:12 +0100 |
parents | e61587582cef |
children | cc3dc759c989 |
line wrap: on
line diff
--- a/PostgreSQL/Plugins/PostgreSQLIndex.cpp Thu Jan 17 11:42:24 2019 +0100 +++ b/PostgreSQL/Plugins/PostgreSQLIndex.cpp Mon Jan 21 14:38:12 2019 +0100 @@ -35,6 +35,9 @@ { // Some aliases for internal properties static const GlobalProperty GlobalProperty_HasTrigramIndex = GlobalProperty_DatabaseInternal0; + static const GlobalProperty GlobalProperty_HasCreateInstance = GlobalProperty_DatabaseInternal1; + static const GlobalProperty GlobalProperty_HasFastCountResources = GlobalProperty_DatabaseInternal2; + static const GlobalProperty GlobalProperty_GetLastChangeIndex = GlobalProperty_DatabaseInternal3; } @@ -126,7 +129,8 @@ PostgreSQLTransaction t(*db); int hasTrigram = 0; - if (!LookupGlobalIntegerProperty(hasTrigram, *db, t, Orthanc::GlobalProperty_HasTrigramIndex) || + if (!LookupGlobalIntegerProperty(hasTrigram, *db, t, + Orthanc::GlobalProperty_HasTrigramIndex) || hasTrigram != 1) { /** @@ -162,6 +166,89 @@ << "PostgreSQL server, e.g. on Debian: sudo apt install postgresql-contrib"; } } + else + { + t.Commit(); + } + } + + { + PostgreSQLTransaction t(*db); + + int property = 0; + if (!LookupGlobalIntegerProperty(property, *db, t, + Orthanc::GlobalProperty_HasCreateInstance) || + property != 2) + { + LOG(INFO) << "Installing the CreateInstance extension"; + + if (property == 1) + { + // Drop older, experimental versions of this extension + db->Execute("DROP FUNCTION CreateInstance(" + "IN patient TEXT, IN study TEXT, IN series TEXT, in instance TEXT)"); + } + + std::string query; + Orthanc::EmbeddedResources::GetFileResource + (query, Orthanc::EmbeddedResources::POSTGRESQL_CREATE_INSTANCE); + db->Execute(query); + + SetGlobalIntegerProperty(*db, t, Orthanc::GlobalProperty_HasCreateInstance, 2); + } + + + if (!LookupGlobalIntegerProperty(property, *db, t, + Orthanc::GlobalProperty_GetTotalSizeIsFast) || + property != 1) + { + LOG(INFO) << "Installing the FastTotalSize extension"; + + std::string query; + Orthanc::EmbeddedResources::GetFileResource + (query, Orthanc::EmbeddedResources::POSTGRESQL_FAST_TOTAL_SIZE); + db->Execute(query); + + SetGlobalIntegerProperty(*db, t, Orthanc::GlobalProperty_GetTotalSizeIsFast, 1); + } + + + // Installing this extension requires the "GlobalIntegers" table + // created by the "FastTotalSize" extension + property = 0; + if (!LookupGlobalIntegerProperty(property, *db, t, + Orthanc::GlobalProperty_HasFastCountResources) || + property != 1) + { + LOG(INFO) << "Installing the FastCountResources extension"; + + std::string query; + Orthanc::EmbeddedResources::GetFileResource + (query, Orthanc::EmbeddedResources::POSTGRESQL_FAST_COUNT_RESOURCES); + db->Execute(query); + + SetGlobalIntegerProperty(*db, t, Orthanc::GlobalProperty_HasFastCountResources, 1); + } + + + // Installing this extension requires the "GlobalIntegers" table + // created by the "GetLastChangeIndex" extension + property = 0; + if (!LookupGlobalIntegerProperty(property, *db, t, + Orthanc::GlobalProperty_GetLastChangeIndex) || + property != 1) + { + LOG(INFO) << "Installing the GetLastChangeIndex extension"; + + std::string query; + Orthanc::EmbeddedResources::GetFileResource + (query, Orthanc::EmbeddedResources::POSTGRESQL_GET_LAST_CHANGE_INDEX); + db->Execute(query); + + SetGlobalIntegerProperty(*db, t, Orthanc::GlobalProperty_GetLastChangeIndex, 1); + } + + t.Commit(); } return db.release(); @@ -195,4 +282,152 @@ return ReadInteger64(statement, 0); } + + + uint64_t PostgreSQLIndex::GetTotalCompressedSize() + { + // Fast version if extension "./FastTotalSize.sql" is installed + uint64_t result; + + { + DatabaseManager::CachedStatement statement( + STATEMENT_FROM_HERE, GetManager(), + "SELECT value FROM GlobalIntegers WHERE key = 0"); + + statement.SetReadOnly(true); + statement.Execute(); + + result = static_cast<uint64_t>(ReadInteger64(statement, 0)); + } + + assert(result == IndexBackend::GetTotalCompressedSize()); + return result; + } + + + uint64_t PostgreSQLIndex::GetTotalUncompressedSize() + { + // Fast version if extension "./FastTotalSize.sql" is installed + uint64_t result; + + { + DatabaseManager::CachedStatement statement( + STATEMENT_FROM_HERE, GetManager(), + "SELECT value FROM GlobalIntegers WHERE key = 1"); + + statement.SetReadOnly(true); + statement.Execute(); + + result = static_cast<uint64_t>(ReadInteger64(statement, 0)); + } + + assert(result == IndexBackend::GetTotalUncompressedSize()); + return result; + } + + +#if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1 + void PostgreSQLIndex::CreateInstance(OrthancPluginCreateInstanceResult& result, + const char* hashPatient, + const char* hashStudy, + const char* hashSeries, + const char* hashInstance) + { + DatabaseManager::CachedStatement statement( + STATEMENT_FROM_HERE, GetManager(), + "SELECT * FROM CreateInstance(${patient}, ${study}, ${series}, ${instance})"); + + statement.SetParameterType("patient", ValueType_Utf8String); + statement.SetParameterType("study", ValueType_Utf8String); + statement.SetParameterType("series", ValueType_Utf8String); + statement.SetParameterType("instance", ValueType_Utf8String); + + Dictionary args; + args.SetUtf8Value("patient", hashPatient); + args.SetUtf8Value("study", hashStudy); + args.SetUtf8Value("series", hashSeries); + args.SetUtf8Value("instance", hashInstance); + + statement.Execute(args); + + if (statement.IsDone() || + statement.GetResultFieldsCount() != 8) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); + } + + for (size_t i = 0; i < 8; i++) + { + statement.SetResultFieldType(i, ValueType_Integer64); + } + + result.isNewInstance = (ReadInteger64(statement, 3) == 1); + result.instanceId = ReadInteger64(statement, 7); + + if (result.isNewInstance) + { + result.isNewPatient = (ReadInteger64(statement, 0) == 1); + result.isNewStudy = (ReadInteger64(statement, 1) == 1); + result.isNewSeries = (ReadInteger64(statement, 2) == 1); + result.patientId = ReadInteger64(statement, 4); + result.studyId = ReadInteger64(statement, 5); + result.seriesId = ReadInteger64(statement, 6); + } + } +#endif + + + uint64_t PostgreSQLIndex::GetResourceCount(OrthancPluginResourceType resourceType) + { + // Optimized version thanks to the "FastCountResources.sql" extension + + assert(OrthancPluginResourceType_Patient == 0 && + OrthancPluginResourceType_Study == 1 && + OrthancPluginResourceType_Series == 2 && + OrthancPluginResourceType_Instance == 3); + + uint64_t result; + + { + DatabaseManager::CachedStatement statement( + STATEMENT_FROM_HERE, GetManager(), + "SELECT value FROM GlobalIntegers WHERE key = ${key}"); + + statement.SetParameterType("key", ValueType_Integer64); + + Dictionary args; + + // For an explanation of the "+ 2" below, check out "FastCountResources.sql" + args.SetIntegerValue("key", static_cast<int>(resourceType + 2)); + + statement.SetReadOnly(true); + statement.Execute(args); + + result = static_cast<uint64_t>(ReadInteger64(statement, 0)); + } + + assert(result == IndexBackend::GetResourceCount(resourceType)); + return result; + } + + + int64_t PostgreSQLIndex::GetLastChangeIndex() + { + DatabaseManager::CachedStatement statement( + STATEMENT_FROM_HERE, GetManager(), + "SELECT value FROM GlobalIntegers WHERE key = 6"); + + statement.SetReadOnly(true); + statement.Execute(); + + return ReadInteger64(statement, 0); + } + + + void PostgreSQLIndex::TagMostRecentPatient(int64_t patient) + { + // This behavior is implemented in "CreateInstance()", and no + // backward compatibility is necessary + throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); + } }