changeset 6157:e77c045e5656 attach-custom-data

fix upgrade from db v3 schema
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 02 Jun 2025 18:34:55 +0200 (2 weeks ago)
parents d6d8c8c2dcc4
children 506fb1e40442
files OrthancServer/Sources/Database/InstallDeletedFiles.sql OrthancServer/Sources/Database/InstallRevisionAndCustomData.sql OrthancServer/Sources/Database/PrepareDatabase.sql OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp OrthancServer/Sources/ServerEnumerations.h
diffstat 5 files changed, 64 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancServer/Sources/Database/InstallDeletedFiles.sql	Mon Jun 02 17:40:24 2025 +0200
+++ b/OrthancServer/Sources/Database/InstallDeletedFiles.sql	Mon Jun 02 18:34:55 2025 +0200
@@ -49,7 +49,3 @@
                            old.uncompressedMD5, old.compressedMD5
                            );
 END;
-
--- Record that this upgrade has been performed
-
-INSERT INTO GlobalProperties VALUES (7, 1);  -- GlobalProperty_SQLiteHasCustomDataAndRevision
--- a/OrthancServer/Sources/Database/InstallRevisionAndCustomData.sql	Mon Jun 02 17:40:24 2025 +0200
+++ b/OrthancServer/Sources/Database/InstallRevisionAndCustomData.sql	Mon Jun 02 18:34:55 2025 +0200
@@ -28,3 +28,7 @@
 
 -- Add new column for customData
 ALTER TABLE AttachedFiles ADD COLUMN customData TEXT;
+
+-- Record that this upgrade has been performed
+
+INSERT INTO GlobalProperties VALUES (7, 1);  -- GlobalProperty_SQLiteHasCustomDataAndRevision
--- a/OrthancServer/Sources/Database/PrepareDatabase.sql	Mon Jun 02 17:40:24 2025 +0200
+++ b/OrthancServer/Sources/Database/PrepareDatabase.sql	Mon Jun 02 18:34:55 2025 +0200
@@ -153,6 +153,11 @@
 ${INSTALL_KEY_VALUE_STORES_AND_QUEUES}
 
 
+-- Track the fact that the "revision" column exists in the "Metadata" and "AttachedFiles"
+-- tables, and that the "customData" column exists in the "AttachedFiles" table
+INSERT INTO GlobalProperties VALUES (7, 1);  -- GlobalProperty_SQLiteHasCustomDataAndRevision
+
+
 -- Set the version of the database schema
 -- The "1" corresponds to the "GlobalProperty_DatabaseSchemaVersion" enumeration
 INSERT INTO GlobalProperties VALUES (1, "6");
--- a/OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp	Mon Jun 02 17:40:24 2025 +0200
+++ b/OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp	Mon Jun 02 18:34:55 2025 +0200
@@ -389,16 +389,19 @@
     boost::recursive_mutex::scoped_lock  lock_;
     IDatabaseListener&         listener_;
     SignalRemainingAncestor&   signalRemainingAncestor_;
+    bool                       hasFastTotalSize_;
 
   public:
     TransactionBase(boost::recursive_mutex& mutex,
                     SQLite::Connection& db,
                     IDatabaseListener& listener,
-                    SignalRemainingAncestor& signalRemainingAncestor) :
+                    SignalRemainingAncestor& signalRemainingAncestor,
+                    bool hasFastTotalSize) :
       UnitTestsTransaction(db),
       lock_(mutex),
       listener_(listener),
-      signalRemainingAncestor_(signalRemainingAncestor)
+      signalRemainingAncestor_(signalRemainingAncestor),
+      hasFastTotalSize_(hasFastTotalSize)
     {
     }
 
@@ -1671,23 +1674,39 @@
 
     virtual uint64_t GetTotalCompressedSize() ORTHANC_OVERRIDE
     {
-      // Old SQL query that was used in Orthanc <= 1.5.0:
-      // SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT SUM(compressedSize) FROM AttachedFiles");
-
-      SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT value FROM GlobalIntegers WHERE key=0");
-      s.Run();
-      return static_cast<uint64_t>(s.ColumnInt64(0));
+      std::unique_ptr<SQLite::Statement> statement;
+
+      if (hasFastTotalSize_)
+      {
+        statement.reset(new SQLite::Statement(db_, SQLITE_FROM_HERE, "SELECT value FROM GlobalIntegers WHERE key=0"));
+      }
+      else
+      {
+        // Old SQL query that was used in Orthanc <= 1.5.0:
+        statement.reset(new SQLite::Statement(db_, SQLITE_FROM_HERE, "SELECT SUM(compressedSize) FROM AttachedFiles"));
+      }
+
+      statement->Run();
+      return static_cast<uint64_t>(statement->ColumnInt64(0));
     }
 
     
     virtual uint64_t GetTotalUncompressedSize() ORTHANC_OVERRIDE
     {
-      // Old SQL query that was used in Orthanc <= 1.5.0:
-      // SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT SUM(uncompressedSize) FROM AttachedFiles");
-
-      SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT value FROM GlobalIntegers WHERE key=1");
-      s.Run();
-      return static_cast<uint64_t>(s.ColumnInt64(0));
+      std::unique_ptr<SQLite::Statement> statement;
+
+      if (hasFastTotalSize_)
+      {
+        statement.reset(new SQLite::Statement(db_, SQLITE_FROM_HERE, "SELECT value FROM GlobalIntegers WHERE key=1"));
+      }
+      else
+      {
+        // Old SQL query that was used in Orthanc <= 1.5.0:
+        statement.reset(new SQLite::Statement(db_, SQLITE_FROM_HERE, "SELECT SUM(uncompressedSize) FROM AttachedFiles"));
+      }
+
+      statement->Run();
+      return static_cast<uint64_t>(statement->ColumnInt64(0));
     }
 
 
@@ -2417,8 +2436,9 @@
 
   public:
     ReadWriteTransaction(SQLiteDatabaseWrapper& that,
-                         IDatabaseListener& listener) :
-      TransactionBase(that.mutex_, that.db_, listener, *that.signalRemainingAncestor_),
+                         IDatabaseListener& listener,
+                         bool hasFastTotalSize) :
+      TransactionBase(that.mutex_, that.db_, listener, *that.signalRemainingAncestor_, hasFastTotalSize),
       that_(that),
       transaction_(new SQLite::Transaction(that_.db_)),
       isNested_(false)
@@ -2496,8 +2516,9 @@
     
   public:
     ReadOnlyTransaction(SQLiteDatabaseWrapper& that,
-                        IDatabaseListener& listener) :
-      TransactionBase(that.mutex_, that.db_, listener, *that.signalRemainingAncestor_),
+                        IDatabaseListener& listener,
+                        bool hasFastTotalSize) :
+      TransactionBase(that.mutex_, that.db_, listener, *that.signalRemainingAncestor_, hasFastTotalSize),
       that_(that),
       isNested_(false)
     {
@@ -2685,11 +2706,16 @@
         }
 
         // New in Orthanc 1.12.8
-        if (!transaction->LookupGlobalProperty(tmp, GlobalProperty_SQLiteHasCustomDataAndRevision, true /* unused in SQLite */) 
+        if (!transaction->LookupGlobalProperty(tmp, GlobalProperty_SQLiteHasRevisionAndCustomData, true /* unused in SQLite */)
             || tmp != "1")
         {
           LOG(INFO) << "Upgrading SQLite schema to support revision and customData";
           ExecuteEmbeddedScript(db_, ServerResources::INSTALL_REVISION_AND_CUSTOM_DATA);
+        }
+
+        // New in Orthanc 1.12.8
+        if (!db_.DoesTableExist("DeletedFiles"))
+        {
           ExecuteEmbeddedScript(db_, ServerResources::INSTALL_DELETED_FILES);
         }
 
@@ -2770,7 +2796,8 @@
       VoidDatabaseListener listener;
       
       {
-        std::unique_ptr<ITransaction> transaction(StartTransaction(TransactionType_ReadWrite, listener));
+        ReadWriteTransaction transaction(*this, listener, false /* GetTotalSizeIsFast necessitates the table "GlobalIntegers" */);
+        transaction.Begin();
 
         // ReconstructMaindDicomTags uses LookupAttachment that needs revision and customData.  Since we don't want to maintain a legacy version
         // of LookupAttachment, we modify the table now)
@@ -2779,13 +2806,13 @@
         ServerResources::GetFileResource(query, ServerResources::INSTALL_REVISION_AND_CUSTOM_DATA);
         db_.Execute(query);
 
-        ServerToolbox::ReconstructMainDicomTags(*transaction, storageArea, ResourceType_Patient);
-        ServerToolbox::ReconstructMainDicomTags(*transaction, storageArea, ResourceType_Study);
-        ServerToolbox::ReconstructMainDicomTags(*transaction, storageArea, ResourceType_Series);
-        ServerToolbox::ReconstructMainDicomTags(*transaction, storageArea, ResourceType_Instance);
+        ServerToolbox::ReconstructMainDicomTags(transaction, storageArea, ResourceType_Patient);
+        ServerToolbox::ReconstructMainDicomTags(transaction, storageArea, ResourceType_Study);
+        ServerToolbox::ReconstructMainDicomTags(transaction, storageArea, ResourceType_Series);
+        ServerToolbox::ReconstructMainDicomTags(transaction, storageArea, ResourceType_Instance);
         db_.Execute("UPDATE GlobalProperties SET value=\"6\" WHERE property=" +
                     boost::lexical_cast<std::string>(GlobalProperty_DatabaseSchemaVersion) + ";");
-        transaction->Commit(0);
+        transaction.Commit(0);
       }
       
       version_ = 6;
@@ -2816,12 +2843,12 @@
     switch (type)
     {
       case TransactionType_ReadOnly:
-        return new ReadOnlyTransaction(*this, listener);  // This is a no-op transaction in SQLite (thanks to mutex)
+        return new ReadOnlyTransaction(*this, listener, true);  // This is a no-op transaction in SQLite (thanks to mutex)
 
       case TransactionType_ReadWrite:
       {
         std::unique_ptr<ReadWriteTransaction> transaction;
-        transaction.reset(new ReadWriteTransaction(*this, listener));
+        transaction.reset(new ReadWriteTransaction(*this, listener, true));
         transaction->Begin();
         return transaction.release();
       }
--- a/OrthancServer/Sources/ServerEnumerations.h	Mon Jun 02 17:40:24 2025 +0200
+++ b/OrthancServer/Sources/ServerEnumerations.h	Mon Jun 02 18:34:55 2025 +0200
@@ -171,7 +171,7 @@
     GlobalProperty_AnonymizationSequence = 3,
     GlobalProperty_JobsRegistry = 5,
     GlobalProperty_GetTotalSizeIsFast = 6,      // New in Orthanc 1.5.2
-    GlobalProperty_SQLiteHasCustomDataAndRevision = 7,     // New in Orthanc 1.12.8
+    GlobalProperty_SQLiteHasRevisionAndCustomData = 7,     // New in Orthanc 1.12.8
     GlobalProperty_Modalities = 20,             // New in Orthanc 1.5.0
     GlobalProperty_Peers = 21,                  // New in Orthanc 1.5.0