Subject: Reject invalid databases in pg_get_database_ddl()

From: Lakshmi N <[email-masked]>
Date: Thu, 16 Apr 2026 01:19:44 -0700

Hi,

pg_get_database_ddl() is not checking for databases in an invalid state
before producing ddl statements. This caused the function to emit
CONNECTION_LIMIT = -2, which is invalid SQL that Postgres rejects.
A database row can be in this inconsistent state longer, for example
server crashed during a drop database.

Attached patch to fix this issue by doing a database_is_invalid_form()
check early in pg_get_database_ddl_internal().

Regards,
Lakshmi

---

From: Amit Langote <[email-masked]>
Date: Thu, 16 Apr 2026 18:28:47 +0900

Hi,

> check early in pg_get_database_ddl_internal().

Thanks for the report.

Hmm, I see that the function will happily emit datconnlimit = -2 and
your patch catches that at the top instead of down below near this
code:

/* CONNECTION LIMIT */
if (dbform->datconnlimit != -1)
{
    resetStringInfo(&buf);
    appendStringInfo(&buf, "ALTER DATABASE %s CONNECTION LIMIT = %d;",
                     quote_identifier(dbname), dbform->datconnlimit);
    statements = lappend(statements, pstrdup(buf.data));
}

which, I guess, makes sense.

The comment is correct but could be more explicit:

    /*
     * Reject invalid databases: datconnlimit = -2 would be emitted as
     * CONNECTION LIMIT = -2, which fails on replay.
     */

-- 
Thanks, Amit Langote

---

From: Lakshmi N <[email-masked]>
Date: Thu, 16 Apr 2026 09:46:45 -0700

Hi Amit,

>      * CONNECTION LIMIT = -2, which fails on replay.
Thank you for reviewing! Please find the attached v2 addressing this.

Regards,
Lakshmi

---

From: Amit Langote <[email-masked]>
Date: Fri, 17 Apr 2026 08:46:07 +0900

On Fri, Apr 17, 2026 at 1:46 AM Lakshmi N <[email-masked]> wrote:
> On Thu, Apr 16, 2026 at 2:29 AM Amit Langote <[email-masked]> wrote:
>>
>> Hi,
>>

Thanks.  Will push the attached shortly.

-- 
Thanks, Amit Langote

---

From: Japin Li <[email-masked]>
Date: Fri, 17 Apr 2026 09:40:07 +0800

Hi, Lakshmi

> Thank you for reviewing! Please find the attached v2 addressing this.

Thanks for updating the patch.  Is it possible to cover this with a test case?

> Regards,
> Lakshmi 
>
> [4. text/x-diff; v2-0001-Reject-pg_get_database_ddl-for-invalid-databases.patch]...

-- 
Regards,
Japin Li
ChengDu WenWu Information Technology Co., Ltd.

---

From: "Euler Taveira" <[email-masked]>
Date: Thu, 16 Apr 2026 22:46:51 -0300

> Thanks.  Will push the attached shortly.

I think the errhint() is excessive in this context. It makes sense if you are
executing ALTER DATABASE, for example. I suggest a message like

  database \"%s\" is an invalid database

Regarding the test case suggested by Japin Li, I don't think it is worth because
it is a transient state (unless something bad happened and pg_database contains
a dangling row.)

-- 
Euler Taveira
EDB   https://www.enterprisedb.com/

---

From: Amit Langote <[email-masked]>
Date: Fri, 17 Apr 2026 11:15:39 +0900

On Fri, Apr 17, 2026 at 10:47 AM Euler Taveira <[email-masked]> wrote:
> executing ALTER DATABASE, for example.

Yeah, agreed.

> I suggest a message like

Or just drop it, because the errmsg already says "invalid database %s".

> it is a transient state (unless something bad happened and pg_database contains

Agreed.

Patch updated.

-- 
Thanks, Amit Langote

---

From: Japin Li <[email-masked]>
Date: Fri, 17 Apr 2026 10:30:44 +0800

> it is a transient state (unless something bad happened and pg_database contains

Thanks for clarifying. Got it.

---

From: Hu Xunqi <[email-masked]>
Date: Fri, 17 Apr 2026 10:49:26 +0800

> > it is a transient state (unless something bad happened and pg_database

+1. As this is an edge case failure, it’s not worth extending test time.

> Patch updated.

+       /*
+        * Reject invalid databases: datconnlimit = -2 would be emitted as
+        * CONNECTION LIMIT = -2, which cannot be executed.
+        */

This comment looks a bit too centered on datconnlimit=-2, but the real
issue is that an invalid pg_database row should not be deparsed into DDL.
So, maybe rephrase like:

/*
* Reject invalid databases. Deparsing a pg_database row in invalid state
* can produce SQL that is not executable, such as CONNECTION LIMIT = -2.
*/

Regards,
Xunqi Hu

---

From: Amit Langote <[email-masked]>
Date: Fri, 17 Apr 2026 12:30:59 +0900

Hi,

On Fri, Apr 17, 2026 at 11:49 AM Hu Xunqi <[email-masked]> wrote:
> On Fri, Apr 17, 2026 at 10:16 AM Amit Langote <[email-masked]> wrote:
> +       /*
> This comment looks a bit too centered on datconnlimit=-2, but the real issue is that an invalid pg_database row should not be deparsed into DDL. So, maybe rephrase like:
>
> /*

I was trying to be precise about datconnlimit = -2 being the thing
that produces invalid SQL. But your version covers that with the "such
as CONNECTION LIMIT = -2" example, and it's closer to the original,
which was on the right track, just needed to be more precise. Let's go
with it.

-- 
Thanks, Amit Langote

---

From: Lakshmi N <[email-masked]>
Date: Thu, 16 Apr 2026 21:20:52 -0700

Hi,

> which was on the right track, just needed to be more precise. Let's go

This looks good to me. Thank you for reviewing and making the changes!

Regards,
Lakshmi

---

From: Amit Langote <[email-masked]>
Date: Fri, 17 Apr 2026 13:22:19 +0900

On Fri, Apr 17, 2026 at 1:21 PM Lakshmi N <[email-masked]> wrote:
> On Thu, Apr 16, 2026 at 8:31 PM Amit Langote <[email-masked]> wrote:

Pushed.

-- 
Thanks, Amit Langote

---

From: Andrew Dunstan <[email-masked]>
Date: Fri, 17 Apr 2026 08:40:41 -0400

>> This looks good to me. Thank you for reviewing and making the changes!

Thanks for jumping on this.

cheers

andrew

--
Andrew Dunstan
EDB: https://www.enterprisedb.com