Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vJVMm-0095wl-35 for pgsql-hackers@arkaria.postgresql.org; Thu, 13 Nov 2025 11:19:52 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vJVMi-000Xwr-28 for pgsql-hackers@arkaria.postgresql.org; Thu, 13 Nov 2025 11:19:48 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vJVIP-000K4n-2r for pgsql-hackers@lists.postgresql.org; Thu, 13 Nov 2025 11:15:22 +0000 Received: from mail-m16.yeah.net ([1.95.21.15]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vJTkr-006tAL-2l for pgsql-hackers@postgresql.org; Thu, 13 Nov 2025 09:36:41 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yeah.net; s=s110527; h=Message-ID:Date:MIME-Version:Subject:To:From: Content-Type; bh=AVbODGRZz48oLwaBsOm/DSJSlQUmpqBbrRn05u9rWhY=; b=Py60q3huwPwf2Pu6lC9HRlwVO+1U7Jv7vKtnrCBYiMkkJNQsLpdPClKIffFBXA CY+m7izBVJj6BUVGNn0Qvf6JPaVYAL2VGiWKBsDnE3OpbDaReymFoG6L5jFQyrQE pdFmbt1qiJsLbFSEyhKOdGIBN74oonZDsWsV5FNl+LvCU= Received: from [192.168.10.60] (unknown []) by gzsmtp3 (Coremail) with SMTP id M88vCgD3h42TphVpJsPmAQ--.29540S2; Thu, 13 Nov 2025 17:36:19 +0800 (CST) Message-ID: <8b5b3b7b-c2ed-4850-b65c-c504a9982135@yeah.net> Date: Thu, 13 Nov 2025 17:36:19 +0800 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH] Add pg_get_database_ddl() function to reconstruct CREATE DATABASE statement To: Akshay Joshi Cc: pgsql-hackers References: Content-Language: en-US From: Quan Zongliang In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit X-CM-TRANSID: M88vCgD3h42TphVpJsPmAQ--.29540S2 X-Coremail-Antispam: 1Uf129KBjvJXoWxur48WF1fWF43AFWDAFykGrg_yoWrKw43p3 4fJF12yryUJry0yr18Xw18J34Utr15Jw1UKr1UGFW8Ar1UCr42qr4qqr409F98JrW8Jw15 XF1DWryDZr1DA37anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07jOzVbUUUUU= X-Originating-IP: [111.167.159.4] X-CM-SenderInfo: htxd06xrqjzxxdqjq5hhdkh0dhw/1tbiIRhvk2kVppghSgAA3s List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On 11/13/25 4:30 PM, Akshay Joshi wrote: > > On Thu, Nov 13, 2025 at 9:47 AM Quan Zongliang > wrote: > > > > On 11/12/25 8:04 PM, Akshay Joshi wrote: > > Hi Hackers, > > > > I’m submitting a patch as part of the broader Retail DDL Functions > > project described by Andrew Dunstan https://www.postgresql.org/ > message- > > id/945db7c5-be75-45bf-b55b-cb1e56f2e3e9%40dunslane.net > > www.postgresql.org/message-id/945db7c5-be75-45bf-b55b- www.postgresql.org/message-id/945db7c5-be75-45bf-b55b-> > > cb1e56f2e3e9%40dunslane.net > > > > > This patch adds a new system function > pg_get_database_ddl(database_name/ > > database_oid, pretty), which reconstructs the CREATE DATABASE > statement > > for a given database name or database oid. When the pretty flag > is set > > to true, the function returns a neatly formatted, multi-line DDL > > statement instead of a single-line statement. > > > > *Usage examples:* > > > > 1) SELECT pg_get_database_ddl('test_get_database_ddl_builtin');  -- > > *non-pretty formatted DDL* > > > > > > pg_get_database_ddl > > > ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- > >    CREATE DATABASE test_get_database_ddl_builtin WITH OWNER = > > regress_ddl_database ENCODING = "UTF8" LC_COLLATE = "C" LC_CTYPE > = "C" > > BUILTIN_LOCALE = "C.UTF-8" COLLATION_VERSION = "1" LOCALE_PROVIDER = > > 'builtin' TABLESPACE = pg_default ALLOW_CONNECTIONS = true > CONNECTION > > LIMIT = -1; > > > > > > 2) SELECT pg_get_database_ddl('test_get_database_ddl_builtin', > true); > > -- *pretty formatted DDL* > > > > CREATE DATABASE test_get_database_ddl_builtin > >           WITH > >           OWNER = regress_ddl_database > >           ENCODING = "UTF8" > >           LC_COLLATE = "C" > >           LC_CTYPE = "C" > >           BUILTIN_LOCALE = "C.UTF-8" > >           COLLATION_VERSION = "1" > >           LOCALE_PROVIDER = 'builtin' > >           TABLESPACE = pg_default > >           ALLOW_CONNECTIONS = true > >           CONNECTION LIMIT = -1; > > > > 3) SELECT pg_get_database_ddl(16835);      -- *non-pretty > formatted DDL > > for OID* > > 4) SELECT pg_get_database_ddl(16835, true);  -- *pretty formatted > DDL > > for OID* > > > > The patch includes documentation, in-code comments, and regression > > tests, all of which pass successfully. > > * > > **Note:* To run the regression tests, particularly the pg_upgrade > tests > > successfully, I had to add a helper function, ddl_filter (in > > database.sql), which removes locale and collation-related > information > > from the pg_get_database_ddl output. > > > I think we should check the connection permissions here. Otherwise: > > postgres=> SELECT pg_database_size('testdb'); > ERROR:  permission denied for database testdb > postgres=> SELECT pg_get_database_ddl('testdb'); > >                          pg_get_database_ddl > ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- >   CREATE DATABASE testdb WITH OWNER = quanzl ENCODING = "UTF8" > LC_COLLATE = "zh_CN.UTF-8" LC_CTYPE = "zh_CN.UTF-8" LOCALE_PROVIDER = > 'libc' TABLESPACE = pg_default ALLOW_CONNECTIONS = true CONNECTION > LIMIT > = -1; > (1 row) > > Users without connection permissions should not generate DDL. > > > pg_database_size() requires CONNECT or pg_read_all_stats privileges > since it accesses on-disk storage details of a database, which are > treated as sensitive information. In contrast, other system functions > might not need such privileges because they operate within the connected > database or reveal less sensitive data. > > In my view, the pg_get_database_ddl() function *should not* require > CONNECT or pg_read_all_stats privileges for consistency and security. > Agree. But what about the following scenario? If there is no permission to access pg_database. Shouldn't the DDL be returned? postgres=> SELECT * FROM pg_database; ERROR: permission denied for table pg_database postgres=> SELECT pg_get_database_ddl('testdb'); > > Regards, > Quan Zongliang > > > ----- > > Regards, > > Akshay Joshi > > EDB (EnterpriseDB) > > > > > > >