changeset 110:441a472bfd93

new extension implemented for MySQL: CreateInstance
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 23 Jan 2019 16:28:43 +0100
parents 3f31e3fa5114
children 1525539ce5d9
files MySQL/CMakeLists.txt MySQL/Plugins/CreateInstance.sql MySQL/Plugins/MySQLIndex.cpp MySQL/Plugins/MySQLIndex.h
diffstat 4 files changed, 186 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- 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
--- /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;
--- 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
 }
--- 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
   };
 }