From f1a2cf2443a8f7eab9c761118d55b90018b50ae1 Mon Sep 17 00:00:00 2001 From: Dave Page Date: Tue, 9 Jun 2026 11:55:21 +0100 Subject: [PATCH] Fix collation/ctype query error for non-default LC_COLLATE. #9798 get_ctypes.sql for PG 16+/17+ wrapped a multi-row UNION inside a scalar subquery in a CASE ELSE branch. When the database is not ICU-based and datcollate != datctype (e.g. LC_COLLATE=C with a different ctype), the scalar subquery returned two rows -> "more than one row returned by a subquery used as an expression", which locked the collation input. Rewrite as a flat UNION of guarded SELECTs returning cname rows, matching how the handler already consumes the result (a list of rows). Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/en_US/release_notes_9_16.rst | 2 ++ .../databases/sql/16_plus/get_ctypes.sql | 16 ++++++++-------- .../databases/sql/17_plus/get_ctypes.sql | 16 ++++++++-------- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/docs/en_US/release_notes_9_16.rst b/docs/en_US/release_notes_9_16.rst index a7ec92e1bee..b1047c52acc 100644 --- a/docs/en_US/release_notes_9_16.rst +++ b/docs/en_US/release_notes_9_16.rst @@ -25,3 +25,5 @@ Housekeeping Bug fixes ********* + + | `Issue #9798 `_ - Fixed an issue where editing or creating a database with a non-default LC_COLLATE/LC_CTYPE (e.g. LC_COLLATE=C) failed with "more than one row returned by a subquery", locking the collation/ctype inputs. diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/16_plus/get_ctypes.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/16_plus/get_ctypes.sql index 8a5347a4070..cd1ed28af9f 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/16_plus/get_ctypes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/16_plus/get_ctypes.sql @@ -1,8 +1,8 @@ -SELECT CASE WHEN datlocprovider = 'i' THEN - (SELECT daticulocale as cname FROM pg_catalog.pg_database WHERE datname = current_database()) -ELSE - (SELECT datcollate as cname FROM pg_catalog.pg_database WHERE datname = current_database() - UNION - SELECT datctype as cname FROM pg_catalog.pg_database WHERE datname = current_database()) -END -FROM pg_catalog.pg_database WHERE datname = current_database(); +SELECT daticulocale AS cname FROM pg_catalog.pg_database +WHERE datname = current_database() AND datlocprovider = 'i' +UNION +SELECT datcollate AS cname FROM pg_catalog.pg_database +WHERE datname = current_database() AND datlocprovider <> 'i' +UNION +SELECT datctype AS cname FROM pg_catalog.pg_database +WHERE datname = current_database() AND datlocprovider <> 'i'; diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/17_plus/get_ctypes.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/17_plus/get_ctypes.sql index 00221883616..ce86401264f 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/17_plus/get_ctypes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/17_plus/get_ctypes.sql @@ -1,8 +1,8 @@ -SELECT CASE WHEN datlocprovider = 'i' THEN - (SELECT datlocale as cname FROM pg_catalog.pg_database WHERE datname = current_database()) -ELSE - (SELECT datcollate as cname FROM pg_catalog.pg_database WHERE datname = current_database() - UNION - SELECT datctype as cname FROM pg_catalog.pg_database WHERE datname = current_database()) -END -FROM pg_catalog.pg_database WHERE datname = current_database(); +SELECT datlocale AS cname FROM pg_catalog.pg_database +WHERE datname = current_database() AND datlocprovider = 'i' +UNION +SELECT datcollate AS cname FROM pg_catalog.pg_database +WHERE datname = current_database() AND datlocprovider <> 'i' +UNION +SELECT datctype AS cname FROM pg_catalog.pg_database +WHERE datname = current_database() AND datlocprovider <> 'i';