Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package orthanc-postgresql for 
openSUSE:Factory checked in at 2026-09-22 15:50:28
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/orthanc-postgresql (Old)
 and      /work/SRC/openSUSE:Factory/.orthanc-postgresql.new.383539 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "orthanc-postgresql"

Tue Sep 22 15:50:28 2026 rev:20 rq:1379472 version:11.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/orthanc-postgresql/orthanc-postgresql.changes    
2026-08-28 20:01:37.976866406 +0200
+++ 
/work/SRC/openSUSE:Factory/.orthanc-postgresql.new.383539/orthanc-postgresql.changes
        2026-09-22 15:50:33.164583847 +0200
@@ -1,0 +2,11 @@
+Mon Sep 21 08:43:13 UTC 2026 - Axel Braun <[email protected]>
+
+- version 11.0
+  * DB schema revision: 11
+  * Added an index on AttachedFiles uuids to speed-up the SDK calls 
+    SetAttachmentCustomData and GetAttachmentCustomData that are used by,
+    notably, the advanced-storage plugin.
+  * Small update of the "DeleteResource" function to avoid a warning when 
multiple
+    clients are trying to delete the same resource at the same time.
+
+-------------------------------------------------------------------

Old:
----
  OrthancPostgreSQL-10.3.tar.gz

New:
----
  OrthancPostgreSQL-11.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ orthanc-postgresql.spec ++++++
--- /var/tmp/diff_new_pack.KvJDBJ/_old  2026-09-22 15:50:33.915615179 +0200
+++ /var/tmp/diff_new_pack.KvJDBJ/_new  2026-09-22 15:50:33.920615387 +0200
@@ -21,7 +21,7 @@
 Summary:        Database plugin for Orthanc
 License:        AGPL-3.0-or-later
 Group:          Productivity/Databases/Tools
-Version:        10.3
+Version:        11.0
 Release:        0
 URL:            https://orthanc-server.com
 Source0:        
https://orthanc.uclouvain.be/downloads/sources/%{name}/OrthancPostgreSQL-%{version}.tar.gz

++++++ OrthancPostgreSQL-10.3.tar.gz -> OrthancPostgreSQL-11.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/OrthancPostgreSQL-10.3/.hg_archival.txt 
new/OrthancPostgreSQL-11.0/.hg_archival.txt
--- old/OrthancPostgreSQL-10.3/.hg_archival.txt 2026-08-19 10:08:42.000000000 
+0200
+++ new/OrthancPostgreSQL-11.0/.hg_archival.txt 2026-09-19 10:50:13.000000000 
+0200
@@ -1,6 +1,6 @@
 repo: 7cea966b682978aa285eb9b3a7a9cff81df464b3
-node: 72d6105363adb88626482e5d477e310632db38ba
-branch: OrthancPostgreSQL-10.3
+node: 118b81d73b62a99ebcc9655e53d13577a18ef2af
+branch: OrthancPostgreSQL-11.0
 latesttag: null
-latesttagdistance: 693
-changessincelatesttag: 793
+latesttagdistance: 704
+changessincelatesttag: 807
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/OrthancPostgreSQL-10.3/Framework/Plugins/ISqlLookupFormatter.cpp 
new/OrthancPostgreSQL-11.0/Framework/Plugins/ISqlLookupFormatter.cpp
--- old/OrthancPostgreSQL-10.3/Framework/Plugins/ISqlLookupFormatter.cpp        
2026-08-19 10:08:42.000000000 +0200
+++ new/OrthancPostgreSQL-11.0/Framework/Plugins/ISqlLookupFormatter.cpp        
2026-09-19 10:50:13.000000000 +0200
@@ -807,6 +807,11 @@
     assert(upperLevel <= queryLevel &&
            queryLevel <= lowerLevel);
 
+    const bool isOrthancIdentifiersDefined = 
(!request.orthanc_id_patient().empty() ||
+                                              
!request.orthanc_id_study().empty() ||
+                                              
!request.orthanc_id_series().empty() ||
+                                              
!request.orthanc_id_instance().empty());
+
     std::string orderingSql;
     std::string orderingJoins;
 
@@ -878,7 +883,14 @@
     }
     else
     {
-      orderingSql = "ROW_NUMBER() OVER (ORDER BY " + strQueryLevel + 
".publicId) AS rowNumber";  // we need a default ordering in order to make 
default queries repeatable when using since&limit
+      if (isOrthancIdentifiersDefined && DetectLevel(request) == queryLevel)
+      { // this is a single resource, no need for ordering (ordering may 
prevents a lot of optimizations from the query planner)
+        orderingSql = "0 AS rowNumber";
+      }
+      else
+      {
+        orderingSql = "ROW_NUMBER() OVER (ORDER BY " + strQueryLevel + 
".publicId) AS rowNumber";  // we need a default ordering in order to make 
default queries repeatable when using since&limit
+      }
     }
 
     sql = ("SELECT " +
@@ -890,11 +902,6 @@
 
     std::string joins, comparisons;
 
-    const bool isOrthancIdentifiersDefined = 
(!request.orthanc_id_patient().empty() ||
-                                              
!request.orthanc_id_study().empty() ||
-                                              
!request.orthanc_id_series().empty() ||
-                                              
!request.orthanc_id_instance().empty());
-
     // handle parent constraints
     if (isOrthancIdentifiersDefined && 
Orthanc::IsResourceLevelAboveOrEqual(DetectLevel(request), queryLevel))
     {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/OrthancPostgreSQL-10.3/Framework/PostgreSQL/PostgreSQLDatabase.cpp 
new/OrthancPostgreSQL-11.0/Framework/PostgreSQL/PostgreSQLDatabase.cpp
--- old/OrthancPostgreSQL-10.3/Framework/PostgreSQL/PostgreSQLDatabase.cpp      
2026-08-19 10:08:42.000000000 +0200
+++ new/OrthancPostgreSQL-11.0/Framework/PostgreSQL/PostgreSQLDatabase.cpp      
2026-09-19 10:50:13.000000000 +0200
@@ -189,7 +189,7 @@
       PQclear(result);
 
       LOG(ERROR) << "PostgreSQL error: " << message;
-      ThrowException(false);
+      ThrowException(true);
     }
   }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/OrthancPostgreSQL-10.3/PostgreSQL/CMakeLists.txt 
new/OrthancPostgreSQL-11.0/PostgreSQL/CMakeLists.txt
--- old/OrthancPostgreSQL-10.3/PostgreSQL/CMakeLists.txt        2026-08-19 
10:08:42.000000000 +0200
+++ new/OrthancPostgreSQL-11.0/PostgreSQL/CMakeLists.txt        2026-09-19 
10:50:13.000000000 +0200
@@ -22,7 +22,7 @@
 cmake_minimum_required(VERSION 2.8...4.0)
 project(OrthancPostgreSQL)
 
-set(ORTHANC_PLUGIN_VERSION "10.3")
+set(ORTHANC_PLUGIN_VERSION "11.0")
 
 # This is the preferred version of the Orthanc SDK for this plugin
 set(ORTHANC_SDK_DEFAULT_VERSION "1.13.0")
@@ -96,7 +96,8 @@
   POSTGRESQL_UPGRADE_REV3_TO_REV4    
${CMAKE_SOURCE_DIR}/Plugins/SQL/Upgrades/Rev3ToRev4.sql
   POSTGRESQL_UPGRADE_REV4_TO_REV5    
${CMAKE_SOURCE_DIR}/Plugins/SQL/Upgrades/Rev4ToRev5.sql
   POSTGRESQL_UPGRADE_REV5_TO_REV6    
${CMAKE_SOURCE_DIR}/Plugins/SQL/Upgrades/Rev5ToRev6.sql
-  POSTGRESQL_UPGRADE_REV6_TO_REV10  
${CMAKE_SOURCE_DIR}/Plugins/SQL/Upgrades/Rev6ToRev10.sql
+  POSTGRESQL_UPGRADE_REV6_TO_REV10   
${CMAKE_SOURCE_DIR}/Plugins/SQL/Upgrades/Rev6ToRev10.sql
+  POSTGRESQL_UPGRADE_REV10_TO_REV11  
${CMAKE_SOURCE_DIR}/Plugins/SQL/Upgrades/Rev10ToRev11.sql
   )
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/OrthancPostgreSQL-10.3/PostgreSQL/NEWS 
new/OrthancPostgreSQL-11.0/PostgreSQL/NEWS
--- old/OrthancPostgreSQL-10.3/PostgreSQL/NEWS  2026-08-19 10:08:42.000000000 
+0200
+++ new/OrthancPostgreSQL-11.0/PostgreSQL/NEWS  2026-09-19 10:50:13.000000000 
+0200
@@ -1,3 +1,16 @@
+Release 11.0 (2026-09-19)
+=========================
+
+DB schema revision: 11
+
+Changes:
+* Added an index on AttachedFiles uuids to speed-up the SDK calls 
+  SetAttachmentCustomData and GetAttachmentCustomData that are used by,
+  notably, the advanced-storage plugin.
+* Small update of the "DeleteResource" function to avoid a warning when 
multiple
+  clients are trying to delete the same resource at the same time.
+
+
 Release 10.3 (2026-08-19)
 =========================
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/OrthancPostgreSQL-10.3/PostgreSQL/Plugins/PostgreSQLIndex.cpp 
new/OrthancPostgreSQL-11.0/PostgreSQL/Plugins/PostgreSQLIndex.cpp
--- old/OrthancPostgreSQL-10.3/PostgreSQL/Plugins/PostgreSQLIndex.cpp   
2026-08-19 10:08:42.000000000 +0200
+++ new/OrthancPostgreSQL-11.0/PostgreSQL/Plugins/PostgreSQLIndex.cpp   
2026-09-19 10:50:13.000000000 +0200
@@ -49,7 +49,7 @@
   static const GlobalProperty GlobalProperty_HasComputeStatisticsReadOnly = 
GlobalProperty_DatabaseInternal4;
 }
 
-#define CURRENT_DB_REVISION 10
+#define CURRENT_DB_REVISION 11
 
 namespace OrthancDatabases
 {
@@ -283,6 +283,19 @@
             currentRevision = 10;
           }
 
+          if (currentRevision == 10)
+          {
+            LOG(WARNING) << "Upgrading DB schema from revision 10 to revision 
11";
+
+            std::string query;
+
+            Orthanc::EmbeddedResources::GetFileResource
+              (query, 
Orthanc::EmbeddedResources::POSTGRESQL_UPGRADE_REV10_TO_REV11);
+            t.GetDatabaseTransaction().ExecuteMultiLines(query);
+            hasAppliedAnUpgrade = true;
+            currentRevision = 11;
+          }
+
           if (hasAppliedAnUpgrade)
           {
             LOG(WARNING) << "Upgrading DB schema by applying PrepareIndex.sql";
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/OrthancPostgreSQL-10.3/PostgreSQL/Plugins/SQL/Downgrades/Rev11ToRev10.sql 
new/OrthancPostgreSQL-11.0/PostgreSQL/Plugins/SQL/Downgrades/Rev11ToRev10.sql
--- 
old/OrthancPostgreSQL-10.3/PostgreSQL/Plugins/SQL/Downgrades/Rev11ToRev10.sql   
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/OrthancPostgreSQL-11.0/PostgreSQL/Plugins/SQL/Downgrades/Rev11ToRev10.sql   
    2026-09-19 10:50:13.000000000 +0200
@@ -0,0 +1,114 @@
+-- restore the old DeleteResource function
+
+CREATE OR REPLACE FUNCTION DeleteResource(
+    IN id BIGINT,
+    OUT remaining_ancestor_resource_type INTEGER,
+    OUT remaining_anncestor_public_id TEXT) AS $body$
+DECLARE
+    deleted_resource_row RECORD;
+    deleted_parent_row RECORD;
+    deleted_grand_parent_row RECORD;
+    deleted_grand_grand_parent_row RECORD;
+    locked_parent_row RECORD;
+    locked_resource_row RECORD;
+BEGIN
+    SET client_min_messages = warning;   -- suppress NOTICE:  relation 
"deletedresources" already exists, skipping
+    -- note: temporary tables are created at connection level -> they are 
likely to exist.
+    -- These tables are used by the triggers
+    CREATE TEMPORARY TABLE IF NOT EXISTS DeletedResources(
+        resourceType INTEGER NOT NULL,
+        publicId VARCHAR(64) NOT NULL
+        );
+    RESET client_min_messages;
+    -- clear the temporary table in case it has been created earlier in the 
connection
+    DELETE FROM DeletedResources;
+    -- create/clear the DeletedFiles temporary table
+    PERFORM CreateDeletedFilesTemporaryTable();
+    -- Before deleting an object, we need to lock its parent until the end of 
the transaction to avoid that
+    -- 2 threads deletes the last 2 instances of a series at the same time -> 
none of them would realize
+    -- that they are deleting the last instance and the parent resources would 
not be deleted.
+    -- Locking only the immediate parent is sufficient to prevent from this.
+    SELECT * INTO locked_parent_row FROM resources WHERE internalid = (SELECT 
parentid FROM resources WHERE internalid = id) FOR UPDATE;
+    -- Before deleting the resource itself, we lock it to retrieve the 
resourceType and to make sure not 2 connections try to
+    -- delete it at the same time
+    SELECT * INTO locked_resource_row FROM resources WHERE internalid = id FOR 
UPDATE;
+    -- before delete the resource itself, we must delete its 
grand-grand-children, the grand-children and its children no to violate 
+    -- the parentId referencing an existing primary key constrain.  This is 
actually implementing the ON DELETE CASCADE that was on the parentId in 
previous revisions.
+    
+    -- If this resource has grand-grand-children, delete them
+    if locked_resource_row.resourceType < 1 THEN
+        WITH grand_grand_children_to_delete AS (SELECT 
grandGrandChildLevel.internalId, grandGrandChildLevel.resourceType, 
grandGrandChildLevel.publicId
+                                                FROM Resources childLevel
+                                                INNER JOIN Resources 
grandChildLevel ON childLevel.internalId = grandChildLevel.parentId
+                                                INNER JOIN Resources 
grandGrandChildLevel ON grandChildLevel.internalId = 
grandGrandChildLevel.parentId
+                                                WHERE childLevel.parentId = 
id),
+        
+        deleted_grand_grand_children_rows AS (DELETE FROM Resources WHERE 
internalId IN (SELECT internalId FROM grand_grand_children_to_delete)
+                                              RETURNING resourceType, publicId)
+        INSERT INTO DeletedResources SELECT resourceType, publicId FROM 
deleted_grand_grand_children_rows; 
+    END IF;
+    -- If this resource has grand-children, delete them
+    if locked_resource_row.resourceType < 2 THEN
+        WITH grand_children_to_delete AS (SELECT grandChildLevel.internalId, 
grandChildLevel.resourceType, grandChildLevel.publicId
+                                          FROM Resources childLevel
+                                          INNER JOIN Resources grandChildLevel 
ON childLevel.internalId = grandChildLevel.parentId
+                                          WHERE childLevel.parentId = id),
+        
+        deleted_grand_children_rows AS (DELETE FROM Resources WHERE internalId 
IN (SELECT internalId FROM grand_children_to_delete)
+                                        RETURNING resourceType, publicId)
+        INSERT INTO DeletedResources SELECT resourceType, publicId FROM 
deleted_grand_children_rows; 
+    END IF;
+    -- If this resource has children, delete them
+    if locked_resource_row.resourceType < 3 THEN
+        WITH deleted_children AS (DELETE FROM Resources 
+                                  WHERE parentId = id
+                                  RETURNING resourceType, publicId)
+        INSERT INTO DeletedResources SELECT resourceType, publicId FROM 
deleted_children; 
+    END IF;
+    -- delete the resource itself
+    DELETE FROM Resources WHERE internalId=id RETURNING * INTO 
deleted_resource_row;
+
+    -- keep track of the deleted resources for C++ code
+    INSERT INTO DeletedResources VALUES (deleted_resource_row.resourceType, 
deleted_resource_row.publicId);
+
+    -- If this resource still has siblings, keep track of the remaining parent
+    -- (a parent that must not be deleted but whose LastUpdate must be updated)
+    SELECT resourceType, publicId INTO remaining_ancestor_resource_type, 
remaining_anncestor_public_id
+        FROM Resources 
+        WHERE internalId = deleted_resource_row.parentId
+            AND EXISTS (SELECT 1 FROM Resources WHERE parentId = 
deleted_resource_row.parentId);
+       IF deleted_resource_row.resourceType > 0 THEN
+        -- If this resource is the latest child, delete the parent
+        DELETE FROM Resources WHERE internalId = deleted_resource_row.parentId
+                                    AND NOT EXISTS (SELECT 1 FROM Resources 
WHERE parentId = deleted_resource_row.parentId)
+                                    RETURNING * INTO deleted_parent_row;
+        IF FOUND THEN
+            INSERT INTO DeletedResources VALUES 
(deleted_parent_row.resourceType, deleted_parent_row.publicId);
+            IF deleted_parent_row.resourceType > 0 THEN
+                -- If this resource is the latest child, delete the parent
+                DELETE FROM Resources WHERE internalId = 
deleted_parent_row.parentId
+                                    AND NOT EXISTS (SELECT 1 FROM Resources 
WHERE parentId = deleted_parent_row.parentId)
+                                    RETURNING * INTO deleted_grand_parent_row;
+                IF FOUND THEN
+                    INSERT INTO DeletedResources VALUES 
(deleted_grand_parent_row.resourceType, deleted_grand_parent_row.publicId);
+                    IF deleted_grand_parent_row.resourceType > 0 THEN
+                        -- If this resource is the latest child, delete the 
parent
+                        DELETE FROM Resources WHERE internalId = 
deleted_grand_parent_row.parentId
+                                            AND NOT EXISTS (SELECT 1 FROM 
Resources WHERE parentId = deleted_grand_parent_row.parentId)
+                                            RETURNING * INTO 
deleted_grand_parent_row;
+                        IF FOUND THEN
+                            INSERT INTO DeletedResources VALUES 
(deleted_grand_parent_row.resourceType, deleted_grand_parent_row.publicId);
+                        END IF;
+                    END IF;
+                END IF;
+            END IF;
+        END IF;
+    END IF;
+END;
+
+DROP INDEX IF EXISTS AttachedFilesUuid;
+
+-- set the global properties that actually documents the DB version, revision 
and some of the capabilities
+-- modify only the ones that have changed
+DELETE FROM GlobalProperties WHERE property IN (4);
+INSERT INTO GlobalProperties VALUES (4, 10); -- 
GlobalProperty_DatabasePatchLevel
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/OrthancPostgreSQL-10.3/PostgreSQL/Plugins/SQL/PrepareIndex.sql 
new/OrthancPostgreSQL-11.0/PostgreSQL/Plugins/SQL/PrepareIndex.sql
--- old/OrthancPostgreSQL-10.3/PostgreSQL/Plugins/SQL/PrepareIndex.sql  
2026-08-19 10:08:42.000000000 +0200
+++ new/OrthancPostgreSQL-11.0/PostgreSQL/Plugins/SQL/PrepareIndex.sql  
2026-09-19 10:50:13.000000000 +0200
@@ -260,9 +260,11 @@
     -- delete the resource itself
     DELETE FROM Resources WHERE internalId=id RETURNING * INTO 
deleted_resource_row;
 
-    -- keep track of the deleted resources for C++ code
-    INSERT INTO DeletedResources VALUES (deleted_resource_row.resourceType, 
deleted_resource_row.publicId);
-  
+    IF FOUND THEN
+        -- keep track of the deleted resources for C++ code
+        INSERT INTO DeletedResources VALUES 
(deleted_resource_row.resourceType, deleted_resource_row.publicId);
+    END IF;
+
     -- If this resource still has siblings, keep track of the remaining parent
     -- (a parent that must not be deleted but whose LastUpdate must be updated)
     SELECT resourceType, publicId INTO remaining_ancestor_resource_type, 
remaining_anncestor_public_id
@@ -852,12 +854,16 @@
 
 CREATE INDEX IF NOT EXISTS InvalidChildCountsId ON InvalidChildCounts (id); -- 
see 
https://discourse.orthanc-server.org/t/increase-in-cpu-usage-of-database-after-update-to-orthanc-1-12-7/6057/6
 
+-- new in rev 11
+
+CREATE INDEX IF NOT EXISTS AttachedFilesUuid ON AttachedFiles (uuid);
 
+----------------------------------
 
 -- set the global properties that actually documents the DB version, revision 
and some of the capabilities
 DELETE FROM GlobalProperties WHERE property IN (1, 4, 6, 10, 11, 12, 13, 14);
 INSERT INTO GlobalProperties VALUES (1, 6); -- 
GlobalProperty_DatabaseSchemaVersion
-INSERT INTO GlobalProperties VALUES (4, 10); -- 
GlobalProperty_DatabasePatchLevel
+INSERT INTO GlobalProperties VALUES (4, 11); -- 
GlobalProperty_DatabasePatchLevel
 INSERT INTO GlobalProperties VALUES (6, 1); -- 
GlobalProperty_GetTotalSizeIsFast
 INSERT INTO GlobalProperties VALUES (10, 1); -- GlobalProperty_HasTrigramIndex
 INSERT INTO GlobalProperties VALUES (11, 3); -- 
GlobalProperty_HasCreateInstance  -- this is actually the 3rd version of 
HasCreateInstance
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/OrthancPostgreSQL-10.3/PostgreSQL/Plugins/SQL/Upgrades/Rev10ToRev11.sql 
new/OrthancPostgreSQL-11.0/PostgreSQL/Plugins/SQL/Upgrades/Rev10ToRev11.sql
--- old/OrthancPostgreSQL-10.3/PostgreSQL/Plugins/SQL/Upgrades/Rev10ToRev11.sql 
1970-01-01 01:00:00.000000000 +0100
+++ new/OrthancPostgreSQL-11.0/PostgreSQL/Plugins/SQL/Upgrades/Rev10ToRev11.sql 
2026-09-19 10:50:13.000000000 +0200
@@ -0,0 +1,5 @@
+-- Update from Rev 10 to Rev 11
+
+-- the DeleteResource function is updated in PrepareIndex.sql
+-- the AttachedFilesUuid index is created in PrepareIndex.sql
+SELECT 1;
\ No newline at end of file

Reply via email to