changeset 256:e184dcadf163

handling of revisions in metadata
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 16 Apr 2021 17:13:33 +0200
parents d663d9e44f8d
children 316f7b981e94
files Framework/Plugins/DatabaseBackendAdapterV2.cpp Framework/Plugins/DatabaseBackendAdapterV3.cpp Framework/Plugins/IDatabaseBackend.h Framework/Plugins/IndexBackend.cpp Framework/Plugins/IndexBackend.h Framework/Plugins/IndexUnitTests.h SQLite/Plugins/PrepareIndex.sql
diffstat 7 files changed, 108 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/Framework/Plugins/DatabaseBackendAdapterV2.cpp	Wed Apr 14 17:57:08 2021 +0200
+++ b/Framework/Plugins/DatabaseBackendAdapterV2.cpp	Fri Apr 16 17:13:33 2021 +0200
@@ -1073,7 +1073,8 @@
       DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
 
       std::string s;
-      if (adapter->GetBackend().LookupMetadata(s, accessor.GetManager(), id, metadata))
+      int64_t revision;  // not handled in this API
+      if (adapter->GetBackend().LookupMetadata(s, revision, accessor.GetManager(), id, metadata))
       {
         OrthancPluginDatabaseAnswerString(adapter->GetBackend().GetContext(),
                                           output->GetDatabase(), s.c_str());
@@ -1244,7 +1245,8 @@
     try
     {
       DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
-      adapter->GetBackend().SetMetadata(accessor.GetManager(), id, metadata, value);
+      adapter->GetBackend().SetMetadata(accessor.GetManager(), id, metadata, value,
+                                        0 /* revision number, unused in old API */);
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
--- a/Framework/Plugins/DatabaseBackendAdapterV3.cpp	Wed Apr 14 17:57:08 2021 +0200
+++ b/Framework/Plugins/DatabaseBackendAdapterV3.cpp	Fri Apr 16 17:13:33 2021 +0200
@@ -1707,6 +1707,7 @@
 
 
   static OrthancPluginErrorCode LookupMetadata(OrthancPluginDatabaseTransaction* transaction,
+                                               int64_t* revision /* out */,
                                                int64_t id,
                                                int32_t metadata)
   {
@@ -1717,7 +1718,7 @@
       t->GetOutput().Clear();
 
       std::string s;
-      if (t->GetBackend().LookupMetadata(s, t->GetManager(), id, metadata))
+      if (t->GetBackend().LookupMetadata(s, *revision, t->GetManager(), id, metadata))
       {
         t->GetOutput().AnswerString(s);
       }
@@ -1913,14 +1914,15 @@
   static OrthancPluginErrorCode SetMetadata(OrthancPluginDatabaseTransaction* transaction,
                                             int64_t id,
                                             int32_t metadata,
-                                            const char* value)
+                                            const char* value,
+                                            int64_t revision)
   {
     DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
 
     try
     {
       t->GetOutput().Clear();
-      t->GetBackend().SetMetadata(t->GetManager(), id, metadata, value);
+      t->GetBackend().SetMetadata(t->GetManager(), id, metadata, value, revision);
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
--- a/Framework/Plugins/IDatabaseBackend.h	Wed Apr 14 17:57:08 2021 +0200
+++ b/Framework/Plugins/IDatabaseBackend.h	Fri Apr 16 17:13:33 2021 +0200
@@ -190,6 +190,7 @@
                                        const char* end) = 0;
 
     virtual bool LookupMetadata(std::string& target /*out*/,
+                                int64_t& revision /*out*/,
                                 DatabaseManager& manager,
                                 int64_t id,
                                 int32_t metadataType) = 0;
@@ -230,7 +231,8 @@
     virtual void SetMetadata(DatabaseManager& manager,
                              int64_t id,
                              int32_t metadataType,
-                             const char* value) = 0;
+                             const char* value,
+                             int64_t revision) = 0;
 
     virtual void SetProtectedPatient(DatabaseManager& manager,
                                      int64_t internalId, 
--- a/Framework/Plugins/IndexBackend.cpp	Wed Apr 14 17:57:08 2021 +0200
+++ b/Framework/Plugins/IndexBackend.cpp	Fri Apr 16 17:13:33 2021 +0200
@@ -446,7 +446,7 @@
     SignalDeletedFiles(output, manager);
   }
 
-    
+
   void IndexBackend::DeleteMetadata(DatabaseManager& manager,
                                     int64_t id,
                                     int32_t metadataType)
@@ -465,7 +465,7 @@
     statement.Execute(args);
   }
 
-    
+
   void IndexBackend::DeleteResource(IDatabaseBackendOutput& output,
                                     DatabaseManager& manager,
                                     int64_t id)
@@ -1256,31 +1256,60 @@
 
     
   bool IndexBackend::LookupMetadata(std::string& target /*out*/,
+                                    int64_t& revision /*out*/,
                                     DatabaseManager& manager,
                                     int64_t id,
                                     int32_t metadataType)
   {
-    DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager,
-      "SELECT value FROM Metadata WHERE id=${id} and type=${type}");
+    std::unique_ptr<DatabaseManager::CachedStatement> statement;
+
+    switch (manager.GetDialect())
+    {
+      case Dialect_MySQL:
+      case Dialect_PostgreSQL:
+        statement.reset(new DatabaseManager::CachedStatement(
+                          STATEMENT_FROM_HERE, manager,
+                          "SELECT value FROM Metadata WHERE id=${id} and type=${type}"));
+        break;
 
-    statement.SetReadOnly(true);
-    statement.SetParameterType("id", ValueType_Integer64);
-    statement.SetParameterType("type", ValueType_Integer64);
+      case Dialect_SQLite:
+        statement.reset(new DatabaseManager::CachedStatement(
+                          STATEMENT_FROM_HERE, manager,
+                          "SELECT value, revision FROM Metadata WHERE id=${id} and type=${type}"));
+        break;
+
+      default:
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
+    }
+    
+    
+    statement->SetReadOnly(true);
+    statement->SetParameterType("id", ValueType_Integer64);
+    statement->SetParameterType("type", ValueType_Integer64);
 
     Dictionary args;
     args.SetIntegerValue("id", id);
     args.SetIntegerValue("type", metadataType);
 
-    statement.Execute(args);
+    statement->Execute(args);
 
-    if (statement.IsDone())
+    if (statement->IsDone())
     {
       return false;
     }
     else
     {
-      target = ReadString(statement, 0);
+      target = ReadString(*statement, 0);
+
+      if (manager.GetDialect() == Dialect_SQLite)
+      {
+        revision = ReadInteger64(*statement, 1);
+      }
+      else
+      {
+        revision = 0;  // TODO - REVISIONS
+      }
+      
       return true;
     }
   } 
@@ -1560,27 +1589,31 @@
   void IndexBackend::SetMetadata(DatabaseManager& manager,
                                  int64_t id,
                                  int32_t metadataType,
-                                 const char* value)
+                                 const char* value,
+                                 int64_t revision)
   {
     if (manager.GetDialect() == Dialect_SQLite)
     {
       DatabaseManager::CachedStatement statement(
         STATEMENT_FROM_HERE, manager,
-        "INSERT OR REPLACE INTO Metadata VALUES (${id}, ${type}, ${value})");
+        "INSERT OR REPLACE INTO Metadata VALUES (${id}, ${type}, ${value}, ${revision})");
         
       statement.SetParameterType("id", ValueType_Integer64);
       statement.SetParameterType("type", ValueType_Integer64);
       statement.SetParameterType("value", ValueType_Utf8String);
+      statement.SetParameterType("revision", ValueType_Integer64);
         
       Dictionary args;
       args.SetIntegerValue("id", id);
       args.SetIntegerValue("type", metadataType);
       args.SetUtf8Value("value", value);
+      args.SetIntegerValue("revision", revision);
         
       statement.Execute(args);
     }
     else
     {
+      // TODO - REVISIONS
       {
         DatabaseManager::CachedStatement statement(
           STATEMENT_FROM_HERE, manager,
@@ -2048,10 +2081,16 @@
       std::string name = "m" + boost::lexical_cast<std::string>(i);
 
       args.SetUtf8Value(name, metadata[i].value);
+
+      std::string revisionSuffix;
+      if (manager.GetDialect() == Dialect_SQLite)
+      {
+        revisionSuffix = ", 0";  // TODO - REVISIONS
+      }
       
       std::string insert = ("(" + boost::lexical_cast<std::string>(metadata[i].resource) + ", " +
                             boost::lexical_cast<std::string>(metadata[i].metadata) + ", " +
-                            "${" + name + "})");
+                            "${" + name + "}" + revisionSuffix + ")");
 
       std::string remove = ("(id=" + boost::lexical_cast<std::string>(metadata[i].resource) +
                             " AND type=" + boost::lexical_cast<std::string>(metadata[i].metadata)
@@ -2121,7 +2160,7 @@
 
     ExecuteSetResourcesContentTags(manager, "MainDicomTags", "t",
                                    countMainDicomTags, mainDicomTags);
-
+    
     ExecuteSetResourcesContentMetadata(manager, countMetadata, metadata);
   }
 #endif
--- a/Framework/Plugins/IndexBackend.h	Wed Apr 14 17:57:08 2021 +0200
+++ b/Framework/Plugins/IndexBackend.h	Fri Apr 16 17:13:33 2021 +0200
@@ -231,6 +231,7 @@
                                        const char* end) ORTHANC_OVERRIDE;
 
     virtual bool LookupMetadata(std::string& target /*out*/,
+                                int64_t& revision /*out*/,
                                 DatabaseManager& manager,
                                 int64_t id,
                                 int32_t metadataType) ORTHANC_OVERRIDE;
@@ -271,7 +272,8 @@
     virtual void SetMetadata(DatabaseManager& manager,
                              int64_t id,
                              int32_t metadataType,
-                             const char* value) ORTHANC_OVERRIDE;
+                             const char* value,
+                             int64_t revision) ORTHANC_OVERRIDE;
     
     virtual void SetProtectedPatient(DatabaseManager& manager,
                                      int64_t internalId, 
--- a/Framework/Plugins/IndexUnitTests.h	Wed Apr 14 17:57:08 2021 +0200
+++ b/Framework/Plugins/IndexUnitTests.h	Fri Apr 16 17:13:33 2021 +0200
@@ -270,32 +270,61 @@
   ASSERT_TRUE(ci.back() == b || ci.back() == c);
   ASSERT_NE(ci.front(), ci.back());
 
-  db.SetMetadata(*manager, a, Orthanc::MetadataType_ModifiedFrom, "modified");
-  db.SetMetadata(*manager, a, Orthanc::MetadataType_LastUpdate, "update2");
-  ASSERT_FALSE(db.LookupMetadata(s, *manager, b, Orthanc::MetadataType_LastUpdate));
-  ASSERT_TRUE(db.LookupMetadata(s, *manager, a, Orthanc::MetadataType_LastUpdate));
+  db.SetMetadata(*manager, a, Orthanc::MetadataType_ModifiedFrom, "modified", 42);
+  db.SetMetadata(*manager, a, Orthanc::MetadataType_LastUpdate, "update2", 43);
+  int64_t revision = -1;
+  ASSERT_FALSE(db.LookupMetadata(s, revision, *manager, b, Orthanc::MetadataType_LastUpdate));
+  ASSERT_TRUE(db.LookupMetadata(s, revision, *manager, a, Orthanc::MetadataType_LastUpdate));
   ASSERT_EQ("update2", s);
-  db.SetMetadata(*manager, a, Orthanc::MetadataType_LastUpdate, "update");
-  ASSERT_TRUE(db.LookupMetadata(s, *manager, a, Orthanc::MetadataType_LastUpdate));
+
+#if ORTHANC_ENABLE_SQLITE == 1
+  ASSERT_EQ(43, revision);  // Only SQLite implements revisions so far
+#else
+  ASSERT_EQ(0, revision);
+#endif
+
+  db.SetMetadata(*manager, a, Orthanc::MetadataType_LastUpdate, "update", 44);
+  ASSERT_TRUE(db.LookupMetadata(s, revision, *manager, a, Orthanc::MetadataType_LastUpdate));
   ASSERT_EQ("update", s);
 
+#if ORTHANC_ENABLE_SQLITE == 1
+  ASSERT_EQ(44, revision);  // Only SQLite implements revisions so far
+#else
+  ASSERT_EQ(0, revision);
+#endif
+
   std::list<int32_t> md;
   db.ListAvailableMetadata(md, *manager, a);
   ASSERT_EQ(2u, md.size());
   ASSERT_TRUE(md.front() == Orthanc::MetadataType_ModifiedFrom || md.back() == Orthanc::MetadataType_ModifiedFrom);
   ASSERT_TRUE(md.front() == Orthanc::MetadataType_LastUpdate || md.back() == Orthanc::MetadataType_LastUpdate);
   std::string mdd;
-  ASSERT_TRUE(db.LookupMetadata(mdd, *manager, a, Orthanc::MetadataType_ModifiedFrom));
+  ASSERT_TRUE(db.LookupMetadata(mdd, revision, *manager, a, Orthanc::MetadataType_ModifiedFrom));
   ASSERT_EQ("modified", mdd);
-  ASSERT_TRUE(db.LookupMetadata(mdd, *manager, a, Orthanc::MetadataType_LastUpdate));
+
+#if ORTHANC_ENABLE_SQLITE == 1
+  ASSERT_EQ(42, revision);  // Only SQLite implements revisions so far
+#else
+  ASSERT_EQ(0, revision);
+#endif
+
+  ASSERT_TRUE(db.LookupMetadata(mdd, revision, *manager, a, Orthanc::MetadataType_LastUpdate));
   ASSERT_EQ("update", mdd);
 
+#if ORTHANC_ENABLE_SQLITE == 1
+  ASSERT_EQ(44, revision);  // Only SQLite implements revisions so far
+#else
+  ASSERT_EQ(0, revision);
+#endif
+
   db.ListAvailableMetadata(md, *manager, b);
   ASSERT_EQ(0u, md.size());
 
+  ASSERT_TRUE(db.LookupMetadata(s, revision, *manager, a, Orthanc::MetadataType_LastUpdate));
   db.DeleteMetadata(*manager, a, Orthanc::MetadataType_LastUpdate);
+  ASSERT_FALSE(db.LookupMetadata(s, revision, *manager, a, Orthanc::MetadataType_LastUpdate));
   db.DeleteMetadata(*manager, b, Orthanc::MetadataType_LastUpdate);
-  ASSERT_FALSE(db.LookupMetadata(s, *manager, a, Orthanc::MetadataType_LastUpdate));
+  ASSERT_FALSE(db.LookupMetadata(s, revision, *manager, a, Orthanc::MetadataType_LastUpdate));
 
   db.ListAvailableMetadata(md, *manager, a);
   ASSERT_EQ(1u, md.size());
--- a/SQLite/Plugins/PrepareIndex.sql	Wed Apr 14 17:57:08 2021 +0200
+++ b/SQLite/Plugins/PrepareIndex.sql	Fri Apr 16 17:13:33 2021 +0200
@@ -30,6 +30,7 @@
        id INTEGER REFERENCES Resources(internalId) ON DELETE CASCADE,
        type INTEGER,
        value TEXT,
+       revision INTEGER,
        PRIMARY KEY(id, type)
        );