# HG changeset patch # User Sebastien Jodogne # Date 1548257323 -3600 # Node ID 441a472bfd934deea5a959cfcddf03909f2f0926 # Parent 3f31e3fa5114ea46f2a5cb648bd158deb6cd3efa new extension implemented for MySQL: CreateInstance diff -r 3f31e3fa5114 -r 441a472bfd93 MySQL/CMakeLists.txt --- a/MySQL/CMakeLists.txt Wed Jan 23 15:14:30 2019 +0100 +++ b/MySQL/CMakeLists.txt Wed Jan 23 16:28:43 2019 +0100 @@ -53,6 +53,7 @@ EmbedResources( MYSQL_PREPARE_INDEX ${CMAKE_SOURCE_DIR}/Plugins/PrepareIndex.sql MYSQL_GET_LAST_CHANGE_INDEX ${CMAKE_SOURCE_DIR}/Plugins/GetLastChangeIndex.sql + MYSQL_CREATE_INSTANCE ${CMAKE_SOURCE_DIR}/Plugins/CreateInstance.sql ) add_library(OrthancMySQLIndex SHARED diff -r 3f31e3fa5114 -r 441a472bfd93 MySQL/Plugins/CreateInstance.sql --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MySQL/Plugins/CreateInstance.sql Wed Jan 23 16:28:43 2019 +0100 @@ -0,0 +1,93 @@ +CREATE PROCEDURE CreateInstance( + IN patient TEXT, + IN study TEXT, + IN series TEXT, + IN instance TEXT, + OUT isNewPatient BOOLEAN, + OUT isNewStudy BOOLEAN, + OUT isNewSeries BOOLEAN, + OUT isNewInstance BOOLEAN, + OUT patientKey BIGINT, + OUT studyKey BIGINT, + OUT seriesKey BIGINT, + OUT instanceKey BIGINT) +BEGIN + DECLARE recyclingSeq BIGINT@ + + SELECT internalId INTO instanceKey FROM Resources WHERE publicId = instance AND resourceType = 3@ + + IF NOT instanceKey IS NULL THEN + -- This instance already exists, stop here + SELECT 0 INTO isNewInstance@ + ELSE + SELECT internalId INTO patientKey FROM Resources WHERE publicId = patient AND resourceType = 0@ + SELECT internalId INTO studyKey FROM Resources WHERE publicId = study AND resourceType = 1@ + SELECT internalId INTO seriesKey FROM Resources WHERE publicId = series AND resourceType = 2@ + + IF patientKey IS NULL THEN + -- Must create a new patient + IF NOT (studyKey IS NULL AND seriesKey IS NULL AND instanceKey IS NULL) THEN + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Broken invariant 1'@ + END IF@ + + INSERT INTO Resources VALUES (DEFAULT, 0, patient, NULL)@ + SELECT LAST_INSERT_ID() INTO patientKey@ + SELECT 1 INTO isNewPatient@ + ELSE + SELECT 0 INTO isNewPatient@ + END IF@ + + IF patientKey IS NULL THEN + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Broken invariant 2'@ + END IF@ + + IF studyKey IS NULL THEN + -- Must create a new study + IF NOT (seriesKey IS NULL AND instanceKey IS NULL) THEN + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Broken invariant 3'@ + END IF@ + + INSERT INTO Resources VALUES (DEFAULT, 1, study, patientKey)@ + SELECT LAST_INSERT_ID() INTO studyKey@ + SELECT 1 INTO isNewStudy@ + ELSE + SELECT 0 INTO isNewStudy@ + END IF@ + + IF studyKey IS NULL THEN + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Broken invariant 4'@ + END IF@ + + IF seriesKey IS NULL THEN + -- Must create a new series + IF NOT (instanceKey IS NULL) THEN + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Broken invariant 5'@ + END IF@ + + INSERT INTO Resources VALUES (DEFAULT, 2, series, studyKey)@ + SELECT LAST_INSERT_ID() INTO seriesKey@ + SELECT 1 INTO isNewSeries@ + ELSE + SELECT 0 INTO isNewSeries@ + END IF@ + + IF (seriesKey IS NULL OR NOT instanceKey IS NULL) THEN + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Broken invariant 6'@ + END IF@ + + INSERT INTO Resources VALUES (DEFAULT, 3, instance, seriesKey)@ + SELECT LAST_INSERT_ID() INTO instanceKey@ + SELECT 1 INTO isNewInstance@ + + -- Move the patient to the end of the recycling order + IF NOT isNewPatient THEN + SELECT seq FROM PatientRecyclingOrder WHERE patientId = patientKey INTO recyclingSeq@ + + IF NOT recyclingSeq IS NULL THEN + -- The patient is not protected + DELETE FROM PatientRecyclingOrder WHERE seq = recyclingSeq@ + INSERT INTO PatientRecyclingOrder VALUES (DEFAULT, patientKey)@ + END IF@ + END IF@ + END IF@ +END; diff -r 3f31e3fa5114 -r 441a472bfd93 MySQL/Plugins/MySQLIndex.cpp --- a/MySQL/Plugins/MySQLIndex.cpp Wed Jan 23 15:14:30 2019 +0100 +++ b/MySQL/Plugins/MySQLIndex.cpp Wed Jan 23 16:28:43 2019 +0100 @@ -130,6 +130,7 @@ if (revision == 2) { + // Install the "GetLastChangeIndex" extension std::string query; Orthanc::EmbeddedResources::GetFileResource @@ -153,7 +154,20 @@ SetGlobalIntegerProperty(*db, t, Orthanc::GlobalProperty_DatabasePatchLevel, revision); } - if (revision != 4) + if (revision == 4) + { + // Install the "CreateInstance" extension + std::string query; + + Orthanc::EmbeddedResources::GetFileResource + (query, Orthanc::EmbeddedResources::MYSQL_CREATE_INSTANCE); + db->Execute(query, true); + + revision = 5; + SetGlobalIntegerProperty(*db, t, Orthanc::GlobalProperty_DatabasePatchLevel, revision); + } + + if (revision != 5) { LOG(ERROR) << "MySQL plugin is incompatible with database schema revision: " << revision; throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); @@ -299,4 +313,67 @@ return ReadInteger64(statement, 0); } + + +#if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1 + void MySQLIndex::CreateInstance(OrthancPluginCreateInstanceResult& result, + const char* hashPatient, + const char* hashStudy, + const char* hashSeries, + const char* hashInstance) + { + { + DatabaseManager::CachedStatement statement( + STATEMENT_FROM_HERE, GetManager(), + "CALL CreateInstance(${patient}, ${study}, ${series}, ${instance}, " + "@isNewPatient, @isNewStudy, @isNewSeries, @isNewInstance, " + "@patientKey, @studyKey, @seriesKey, @instanceKey)"); + + 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()) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); + } + } + + { + DatabaseManager::CachedStatement statement( + STATEMENT_FROM_HERE, GetManager(), + "SELECT @isNewPatient, @isNewStudy, @isNewSeries, @isNewInstance, " + "@patientKey, @studyKey, @seriesKey, @instanceKey"); + + statement.Execute(); + + 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 } diff -r 3f31e3fa5114 -r 441a472bfd93 MySQL/Plugins/MySQLIndex.h --- a/MySQL/Plugins/MySQLIndex.h Wed Jan 23 15:14:30 2019 +0100 +++ b/MySQL/Plugins/MySQLIndex.h Wed Jan 23 16:28:43 2019 +0100 @@ -76,5 +76,19 @@ virtual void DeleteResource(int64_t id); virtual int64_t GetLastChangeIndex(); + + virtual bool HasCreateInstance() const ORTHANC_OVERRIDE + { + return true; + } + +#if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1 + virtual void CreateInstance(OrthancPluginCreateInstanceResult& result, + const char* hashPatient, + const char* hashStudy, + const char* hashSeries, + const char* hashInstance) + ORTHANC_OVERRIDE; +#endif }; }