BUG #18984: Empty prepared statement from psql \parse triggers assert in PortalRunMulti

Lists: pgsql-bugs
From: PG Bug reporting form <noreply(at)postgresql(dot)org>
To: pgsql-bugs(at)lists(dot)postgresql(dot)org
Cc: exclusion(at)gmail(dot)com
Subject: BUG #18984: Empty prepared statement from psql \parse triggers assert in PortalRunMulti
Date: 2025-07-14 19:00:02
Message-ID: [email protected]
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-bugs

The following bug has been logged on the website:

Bug reference: 18984
Logged by: Alexander Lakhin
Email address: exclusion(at)gmail(dot)com
PostgreSQL version: 18beta1
Operating system: Ubuntu 24.04
Description:

The following psql script:
\parse s

execute s;

invokes:
TRAP: failed Assert("qc->commandTag != CMDTAG_UNKNOWN"), File: "pquery.c",
Line: 1369, PID: 1123863
ExceptionalCondition at assert.c:52:13
PortalRunMulti at pquery.c:1371:1
PortalRun at pquery.c:792:5
ExecuteQuery at prepare.c:260:2
standard_ProcessUtility at utility.c:757:4
ProcessUtility at utility.c:523:3
PortalRunUtility at pquery.c:1153:2
PortalRunMulti at pquery.c:1310:5
PortalRun at pquery.c:792:5
exec_simple_query at postgres.c:1280:11
...

Reproduced starting from d55322b0d.


From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: exclusion(at)gmail(dot)com
Cc: pgsql-bugs(at)lists(dot)postgresql(dot)org
Subject: Re: BUG #18984: Empty prepared statement from psql \parse triggers assert in PortalRunMulti
Date: 2025-07-14 19:23:12
Message-ID: [email protected]
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-bugs

PG Bug reporting form <noreply(at)postgresql(dot)org> writes:
> The following psql script:
> \parse s

> execute s;

> invokes:
> TRAP: failed Assert("qc->commandTag != CMDTAG_UNKNOWN"), File: "pquery.c",
> Line: 1369, PID: 1123863

What this is complaining about, essentially, is that we don't know how
to construct a command tag to send back to the client. Maybe we could
invent some new command tag out of whole cloth, but I'm inclined to
think it'd be better to forbid empty prepared statements. Not sure
where that should be enforced, but probably on the server side.

regards, tom lane


From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: exclusion(at)gmail(dot)com
Cc: pgsql-bugs(at)lists(dot)postgresql(dot)org
Subject: Re: BUG #18984: Empty prepared statement from psql \parse triggers assert in PortalRunMulti
Date: 2025-07-14 19:36:01
Message-ID: [email protected]
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-bugs

PG Bug reporting form <noreply(at)postgresql(dot)org> writes:
> Reproduced starting from d55322b0d.

BTW, d55322b0d simply made it easy to trigger the bug from psql.
If I use current psql to connect to older servers, I can demonstrate
crashes (or sometimes "stack depth limit exceeded") back to v12.
Pre-v12 is immune because it just returns a command tag of EXECUTE
regardless of what is in the prepared statement.

That being the case, maybe we should band-aid this by returning
EXECUTE if the prepared statement is empty.

regards, tom lane


From: Aleksander Alekseev <aleksander(at)tigerdata(dot)com>
To: pgsql-bugs(at)lists(dot)postgresql(dot)org
Cc: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, exclusion(at)gmail(dot)com
Subject: Re: BUG #18984: Empty prepared statement from psql \parse triggers assert in PortalRunMulti
Date: 2025-07-14 21:11:31
Message-ID: CAJ7c6TOoGUosKwdXt1LwJpThvP2-ZNpuv0H=owYdp6omwQ=keA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-bugs

Hi,

> That being the case, maybe we should band-aid this by returning
> EXECUTE if the prepared statement is empty.

This sounds pretty straightforward and seems to solve the problem.
Patch attached.

```
eax=# \parse s
eax=# execute s;
ERROR: EXECUTE can't execute an empty query
eax=# select 1 \parse s2

eax=# execute s2;
?column?
----------
1
(1 row)
```

Attachment Content-Type Size
v1-0001-Don-t-allow-to-execute-an-empty-query.patch text/x-patch 863 bytes

From: Aleksander Alekseev <aleksander(at)tigerdata(dot)com>
To: pgsql-bugs(at)lists(dot)postgresql(dot)org
Cc: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, exclusion(at)gmail(dot)com
Subject: Re: BUG #18984: Empty prepared statement from psql \parse triggers assert in PortalRunMulti
Date: 2025-07-14 21:33:11
Message-ID: CAJ7c6TNPM+ctgAyuU1nqsCym70UjFSXM6XeU-OGWTVSZT3Z2nw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-bugs

Hi,

> This sounds pretty straightforward and seems to solve the problem.
> Patch attached.

Interestingly enough EXPLAIN EXECUTE is not affected, thus there is no
need to modify ExplainExecuteQuery.

```
eax=# explain execute s;
QUERY PLAN
------------
(0 rows)
```


From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Aleksander Alekseev <aleksander(at)tigerdata(dot)com>
Cc: pgsql-bugs(at)lists(dot)postgresql(dot)org, exclusion(at)gmail(dot)com
Subject: Re: BUG #18984: Empty prepared statement from psql \parse triggers assert in PortalRunMulti
Date: 2025-07-14 21:40:22
Message-ID: [email protected]
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-bugs

Aleksander Alekseev <aleksander(at)tigerdata(dot)com> writes:
>> That being the case, maybe we should band-aid this by returning
>> EXECUTE if the prepared statement is empty.

> This sounds pretty straightforward and seems to solve the problem.
> Patch attached.

Hmm, throwing an error is exactly not what I was suggesting above.
The attached quick draft (needs attention to comments) results in

regression=# \parse s

regression=# execute s;
EXECUTE

which matches the behavior of pre-v12 servers.

(BTW, I wonder why psql is emitting an extra newline after \parse.)

regards, tom lane

Attachment Content-Type Size
wip-avoid-failure-with-empty-prepared-query.patch text/x-diff 482 bytes

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Aleksander Alekseev <aleksander(at)tigerdata(dot)com>
Cc: pgsql-bugs(at)lists(dot)postgresql(dot)org, exclusion(at)gmail(dot)com
Subject: Re: BUG #18984: Empty prepared statement from psql \parse triggers assert in PortalRunMulti
Date: 2025-07-14 22:05:50
Message-ID: [email protected]
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-bugs

I wrote:
> The attached quick draft (needs attention to comments) results in
> regression=# \parse s
> regression=# execute s;
> EXECUTE
> which matches the behavior of pre-v12 servers.

Another way that's perhaps a bit less magical is to make
ExecuteQuery substitute the right thing, as attached.

I'm not entirely sure whether this leaves any other code
paths that can reach that Assert; but on the other hand,
if there are any, CMDTAG_EXECUTE is probably wrong for them.

BTW, the reason why EXPLAIN EXECUTE isn't at risk is that it's
going to return CMDTAG_EXPLAIN.

regards, tom lane

Attachment Content-Type Size
wip2-avoid-failure-with-empty-prepared-query.patch text/x-diff 1.2 KB

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: exclusion(at)gmail(dot)com
Cc: pgsql-bugs(at)lists(dot)postgresql(dot)org
Subject: Re: BUG #18984: Empty prepared statement from psql \parse triggers assert in PortalRunMulti
Date: 2025-07-14 23:17:47
Message-ID: [email protected]
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-bugs

I wrote:
> BTW, d55322b0d simply made it easy to trigger the bug from psql.
> If I use current psql to connect to older servers, I can demonstrate
> crashes (or sometimes "stack depth limit exceeded") back to v12.

I think I fat-fingered something, because now I can only reproduce back
to v13. Bisecting says the crash started at the v13-era commit

commit 2f9661311b83dc481fc19f6e3bda015392010a40
Author: Alvaro Herrera <alvherre(at)alvh(dot)no-ip(dot)org>
Date: Mon Mar 2 18:19:51 2020 -0300

Represent command completion tags as structs

which is unsurprising because that's what introduced the
Assert we're hitting.

BTW, with Asserts disabled it works fine:

$ psql postgres
psql (19devel)
Type "help" for help.

postgres=# \parse s

postgres=# execute s;
EXECUTE

which is another reason not to start throwing an error.
(I did not look into how come that works... the correct
command tag must be getting filled in later, but where?)

regards, tom lane


From: Michael Paquier <michael(at)paquier(dot)xyz>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: exclusion(at)gmail(dot)com, pgsql-bugs(at)lists(dot)postgresql(dot)org
Subject: Re: BUG #18984: Empty prepared statement from psql \parse triggers assert in PortalRunMulti
Date: 2025-07-15 03:54:46
Message-ID: [email protected]
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-bugs

On Mon, Jul 14, 2025 at 03:36:01PM -0400, Tom Lane wrote:
> BTW, d55322b0d simply made it easy to trigger the bug from psql.
> If I use current psql to connect to older servers, I can demonstrate
> crashes (or sometimes "stack depth limit exceeded") back to v12.
> Pre-v12 is immune because it just returns a command tag of EXECUTE
> regardless of what is in the prepared statement.

Oh. It's pretty cool to see that these new meta-commands are able to
find such problems more easily. That was one of the reasons to have
them in v18.
--
Michael


From: Michael Paquier <michael(at)paquier(dot)xyz>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: exclusion(at)gmail(dot)com, pgsql-bugs(at)lists(dot)postgresql(dot)org
Subject: Re: BUG #18984: Empty prepared statement from psql \parse triggers assert in PortalRunMulti
Date: 2025-07-15 04:52:37
Message-ID: [email protected]
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-bugs

On Mon, Jul 14, 2025 at 07:17:47PM -0400, Tom Lane wrote:
> I think I fat-fingered something, because now I can only reproduce back
> to v13. Bisecting says the crash started at the v13-era commit
>
> which is unsurprising because that's what introduced the
> Assert we're hitting.

Yep.

> which is another reason not to start throwing an error.
> (I did not look into how come that works... the correct
> command tag must be getting filled in later, but where?)

With some extra logs:
WARNING: 01000: BOOBOO exec_simple_query commandTag = EXECUTE
LOCATION: exec_simple_query, postgres.c:1120
WARNING: 01000: BOOBOO PortalDefineQuery commandTag = EXECUTE
LOCATION: PortalDefineQuery, portalmem.c:301
WARNING: 01000: BOOBOO PortalDefineQuery commandTag = ???
LOCATION: PortalDefineQuery, portalmem.c:301

The first pass in PortalDefineQuery() is done in exec_simple_query().
The second pass of PortalDefineQuery() is the relevant one, I guess:
#0 PortalDefineQuery (portal=0x564cf7cc9240, prepStmtName=0x0,
sourceText=0x564cf7c74d80 "", commandTag=CMDTAG_UNKNOWN, stmts=0x0,
cplan=0x564cf7c817a8) at portalmem.c:289
#1 0x0000564cd98d4328 in ExecuteQuery (pstate=0x564cf7c7b740,
stmt=0x564cf7c48d38, intoClause=0x0, params=0x0, dest=0x564cf7c48de0,
qc=0x7fffb8e7b4a0) at prepare.c:203
#2 0x0000564cda3f6427 in standard_ProcessUtility
(pstmt=0x564cf7c48550, queryString=0x564cf7c47590 "execute s;",
readOnlyTree=false, context=PROCESS_UTILITY_TOPLEVEL, params=0x0,
queryEnv=0x0, dest=0x564cf7c48de0, qc=0x7fffb8e7b4a0) at utility.c:759
#3 0x0000564cda3f541f in ProcessUtility (pstmt=0x564cf7c48550,
queryString=0x564cf7c47590 "execute s;", readOnlyTree=false,
context=PROCESS_UTILITY_TOPLEVEL, params=0x0, queryEnv=0x0,
dest=0x564cf7c48de0, qc=0x7fffb8e7b4a0) at utility.c:523
#4 0x0000564cda3f2214 in PortalRunUtility (portal=0x564cf7cc9130,
pstmt=0x564cf7c48550, isTopLevel=true, setHoldSnapshot=false,
dest=0x564cf7c48de0, qc=0x7fffb8e7b4a0) at pquery.c:1153
#5 0x0000564cda3f2a40 in PortalRunMulti (portal=0x564cf7cc9130,
isTopLevel=true, setHoldSnapshot=false, dest=0x564cf7c48de0,
altdest=0x564cf7c48de0, qc=0x7fffb8e7b4a0) at pquery.c:1310
#6 0x0000564cda3f09a4 in PortalRun (portal=0x564cf7cc9130,
count=9223372036854775807, isTopLevel=true, dest=0x564cf7c48de0,
altdest=0x564cf7c48de0, qc=0x7fffb8e7b4a0) at pquery.c:788
#7 0x0000564cda3e240a in exec_simple_query
(query_string=0x564cf7c47590 "execute s;") at postgres.c:1274
#8 0x0000564cda3eb78f in PostgresMain (dbname=0x564cf7c84730
"ioltas", username=0x564cf7c84718 "ioltas") at postgres.c:4767

So the QueryCompletion given to PortalRunMulti() is initialized at the
beginning of PortalRun with an unknown tag, and we miss to fill it
when running the individual queries because CopyQueryCompletion()
happens at the end of PortalRunMulti(). We can be more proactive when
updating the tag by doing one in ExecuteQuery() as you are suggesting,
but I am wondering if we should not just nuke the assertion at the end
of PortalRunMulti() instead, relying on the same check done at the
beginning of ProcessUtility().
--
Michael


From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Michael Paquier <michael(at)paquier(dot)xyz>
Cc: Álvaro Herrera <alvherre(at)kurilemu(dot)de>, exclusion(at)gmail(dot)com, pgsql-bugs(at)lists(dot)postgresql(dot)org
Subject: Re: BUG #18984: Empty prepared statement from psql \parse triggers assert in PortalRunMulti
Date: 2025-07-15 04:59:26
Message-ID: [email protected]
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-bugs

Michael Paquier <michael(at)paquier(dot)xyz> writes:
> ... I am wondering if we should not just nuke the assertion at the end
> of PortalRunMulti() instead, relying on the same check done at the
> beginning of ProcessUtility().

Yeah, I was starting to think about that solution too. Removing
code seems nicer than adding more.

CC'ing Alvaro as the original author...

regards, tom lane


From: Álvaro Herrera <alvherre(at)kurilemu(dot)de>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: Michael Paquier <michael(at)paquier(dot)xyz>, exclusion(at)gmail(dot)com, pgsql-bugs(at)lists(dot)postgresql(dot)org
Subject: Re: BUG #18984: Empty prepared statement from psql \parse triggers assert in PortalRunMulti
Date: 2025-07-15 12:33:14
Message-ID: [email protected]
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-bugs

On 2025-Jul-15, Tom Lane wrote:

> Michael Paquier <michael(at)paquier(dot)xyz> writes:
> > ... I am wondering if we should not just nuke the assertion at the end
> > of PortalRunMulti() instead, relying on the same check done at the
> > beginning of ProcessUtility().
>
> Yeah, I was starting to think about that solution too. Removing
> code seems nicer than adding more.

Yeah, this makes sense to me too. I'd rewrite the comment while at it,
because what's being described as "printing 0 0" no longer occurs in
this form in this place anymore. Maybe we could discuss adding
some commentary to EndCommand where this now happens, but I don't think
we really need it.

--
Álvaro Herrera 48°01'N 7°57'E — https://www.EnterpriseDB.com/

Attachment Content-Type Size
0001-Remove-assertion-in-PortalRunMulti-simplify-comment.patch text/x-diff 1.8 KB

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Álvaro Herrera <alvherre(at)kurilemu(dot)de>
Cc: Michael Paquier <michael(at)paquier(dot)xyz>, exclusion(at)gmail(dot)com, pgsql-bugs(at)lists(dot)postgresql(dot)org
Subject: Re: BUG #18984: Empty prepared statement from psql \parse triggers assert in PortalRunMulti
Date: 2025-07-15 14:57:54
Message-ID: [email protected]
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-bugs

=?utf-8?Q?=C3=81lvaro?= Herrera <alvherre(at)kurilemu(dot)de> writes:
> On 2025-Jul-15, Tom Lane wrote:
>> Yeah, I was starting to think about that solution too. Removing
>> code seems nicer than adding more.

> Yeah, this makes sense to me too. I'd rewrite the comment while at it,
> because what's being described as "printing 0 0" no longer occurs in
> this form in this place anymore. Maybe we could discuss adding
> some commentary to EndCommand where this now happens, but I don't think
> we really need it.

Right, I was giving that comment the side eye too. I agree that its
second para is no longer useful: the logic it describes certainly
isn't here anymore, and there doesn't seem to be an identifiable place
where we could move it to. (I think the concern it describes is now
baked into the table design for command tags, specifically that any
given CMDTAG either has or doesn't have a count.) I might write the
replacement comment more like

* If query completion data is requested and not yet filled in,
* and the portal has a default command tag, copy it from there.
* See QueryRewrite(), step 3, for motivation.

regards, tom lane


From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Álvaro Herrera <alvherre(at)kurilemu(dot)de>
Cc: Michael Paquier <michael(at)paquier(dot)xyz>, exclusion(at)gmail(dot)com, pgsql-bugs(at)lists(dot)postgresql(dot)org
Subject: Re: BUG #18984: Empty prepared statement from psql \parse triggers assert in PortalRunMulti
Date: 2025-07-15 16:05:34
Message-ID: [email protected]
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-bugs

I wrote:
> BTW, with Asserts disabled it works fine:
> ...
> (I did not look into how come that works... the correct
> command tag must be getting filled in later, but where?)

I traced through this, and the answer is that there are two levels
of Portal, an outer one that holds the EXECUTE command (and has
portal->qc.commandTag = CMDTAG_EXECUTE) and an inner one that runs
the prepared statement's list (and has portal->qc.commandTag =
CMDTAG_UNKNOWN, because that list is empty). But ExecuteQuery
passes down the outer "qc" parameter to the inner recursion level.
So without the Assert, the inner invocation of PortalRunMulti leaves
qc->commandTag = CMDTAG_UNKNOWN, and then the very same stanza
of PortalRunMulti replaces that with CMDTAG_EXECUTE in the outer
recursion level.

So it's just wrong for PortalRunMulti to assert that the
computation of qc->commandTag is necessarily complete.

If we wanted to replace that, it might be appropriate to have an
assertion at the top level (exec_simple_query) but I'm not very sure
what that would buy us. It'll be apparent enough what happened from
the reported "???" command tag, and the top-level assertion would
contribute exactly nada to identifying where we'd missed setting it.

In short, Alvaro's patch definitely seems like the right one,
modulo quibbles about rewriting the comment. Perhaps we should
add something about the possibility that an outer Portal level
can supply a default command tag if we lack one now?

regards, tom lane


From: Michael Paquier <michael(at)paquier(dot)xyz>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: Ã?lvaro Herrera <alvherre(at)kurilemu(dot)de>, exclusion(at)gmail(dot)com, pgsql-bugs(at)lists(dot)postgresql(dot)org
Subject: Re: BUG #18984: Empty prepared statement from psql \parse triggers assert in PortalRunMulti
Date: 2025-07-15 23:32:00
Message-ID: [email protected]
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-bugs

On Tue, Jul 15, 2025 at 12:05:34PM -0400, Tom Lane wrote:
> In short, Alvaro's patch definitely seems like the right one,
> modulo quibbles about rewriting the comment.

+++ b/src/backend/tcop/pquery.c
@@ -1350,24 +1350,14 @@ PortalRunMulti(Portal portal,
[...]
- if (qc && qc->commandTag == CMDTAG_UNKNOWN)
- {
- if (portal->qc.commandTag != CMDTAG_UNKNOWN)
- CopyQueryCompletion(qc, &portal->qc);
- /* If the caller supplied a qc, we should have set it by now. */
- Assert(qc->commandTag != CMDTAG_UNKNOWN);
- }
+ if (qc &&
+ qc->commandTag == CMDTAG_UNKNOWN &&
+ portal->qc.commandTag != CMDTAG_UNKNOWN)
+ CopyQueryCompletion(qc, &portal->qc);

Indeed this change looks OK.

> Perhaps we should
> add something about the possibility that an outer Portal level
> can supply a default command tag if we lack one now?

You mean as an extra assertion? I am not sure that this is strongly
necessary but why not.
--
Michael


From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Michael Paquier <michael(at)paquier(dot)xyz>
Cc: Ã?lvaro Herrera <alvherre(at)kurilemu(dot)de>, exclusion(at)gmail(dot)com, pgsql-bugs(at)lists(dot)postgresql(dot)org
Subject: Re: BUG #18984: Empty prepared statement from psql \parse triggers assert in PortalRunMulti
Date: 2025-07-15 23:40:19
Message-ID: [email protected]
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-bugs

Michael Paquier <michael(at)paquier(dot)xyz> writes:
> On Tue, Jul 15, 2025 at 12:05:34PM -0400, Tom Lane wrote:
>> Perhaps we should
>> add something about the possibility that an outer Portal level
>> can supply a default command tag if we lack one now?

> You mean as an extra assertion? I am not sure that this is strongly
> necessary but why not.

No, I meant that the comment could explain that if we fail to assign a
non-unknown CMDTAG here, there's still a possibility of an outer
Portal level supplying one. But I don't see how to make a useful
assertion about that.

regards, tom lane


From: Michael Paquier <michael(at)paquier(dot)xyz>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: Ã?lvaro Herrera <alvherre(at)kurilemu(dot)de>, exclusion(at)gmail(dot)com, pgsql-bugs(at)lists(dot)postgresql(dot)org
Subject: Re: BUG #18984: Empty prepared statement from psql \parse triggers assert in PortalRunMulti
Date: 2025-07-16 04:45:55
Message-ID: [email protected]
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-bugs

On Tue, Jul 15, 2025 at 07:40:19PM -0400, Tom Lane wrote:
> Michael Paquier <michael(at)paquier(dot)xyz> writes:
>> You mean as an extra assertion? I am not sure that this is strongly
>> necessary but why not.
>
> No, I meant that the comment could explain that if we fail to assign a
> non-unknown CMDTAG here, there's still a possibility of an outer
> Portal level supplying one. But I don't see how to make a useful
> assertion about that.

Oh, OK, I was not sure about your point here. Thanks for clarifying.
--
Michael


From: Álvaro Herrera <alvherre(at)kurilemu(dot)de>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: Michael Paquier <michael(at)paquier(dot)xyz>, exclusion(at)gmail(dot)com, pgsql-bugs(at)lists(dot)postgresql(dot)org
Subject: Re: BUG #18984: Empty prepared statement from psql \parse triggers assert in PortalRunMulti
Date: 2025-07-17 12:03:11
Message-ID: [email protected]
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-bugs

On 2025-Jul-15, Tom Lane wrote:

> I might write the replacement comment more like
>
> * If query completion data is requested and not yet filled in,
> * and the portal has a default command tag, copy it from there.
> * See QueryRewrite(), step 3, for motivation.

I've been wondering what does the "a default command tag" mean there.
I couldn't find a reference for a command tag being default. Would it
work to say "... and the portal has acquired a command tag [during
execution above?], ..." ?

Thanks,

--
Álvaro Herrera PostgreSQL Developer — https://www.EnterpriseDB.com/
"Once again, thank you and all of the developers for your hard work on
PostgreSQL. This is by far the most pleasant management experience of
any database I've worked on." (Dan Harris)
http://archives.postgresql.org/pgsql-performance/2006-04/msg00247.php


From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Álvaro Herrera <alvherre(at)kurilemu(dot)de>
Cc: Michael Paquier <michael(at)paquier(dot)xyz>, exclusion(at)gmail(dot)com, pgsql-bugs(at)lists(dot)postgresql(dot)org
Subject: Re: BUG #18984: Empty prepared statement from psql \parse triggers assert in PortalRunMulti
Date: 2025-07-17 13:45:34
Message-ID: [email protected]
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-bugs

=?utf-8?Q?=C3=81lvaro?= Herrera <alvherre(at)kurilemu(dot)de> writes:
> I've been wondering what does the "a default command tag" mean there.
> I couldn't find a reference for a command tag being default. Would it
> work to say "... and the portal has acquired a command tag [during
> execution above?], ..." ?

I think that where the Portal gets a tag is in PortalDefineQuery,
and that's normally set as a result of parsing. The code earlier in
PortalRunMulti is meant to supply run-time-determined tags, such
as INSERT/UPDATE/DELETE with a row count. I guess if you hold
your head at the right angle, the case we're considering now is
a run-time-determined tag for the outer EXECUTE.

regards, tom lane


From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Álvaro Herrera <alvherre(at)kurilemu(dot)de>
Cc: Michael Paquier <michael(at)paquier(dot)xyz>, exclusion(at)gmail(dot)com, pgsql-bugs(at)lists(dot)postgresql(dot)org
Subject: Re: BUG #18984: Empty prepared statement from psql \parse triggers assert in PortalRunMulti
Date: 2025-07-17 15:00:56
Message-ID: [email protected]
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-bugs

I wrote:
> =?utf-8?Q?=C3=81lvaro?= Herrera <alvherre(at)kurilemu(dot)de> writes:

> I think that where the Portal gets a tag is in PortalDefineQuery,
> and that's normally set as a result of parsing.

So rather than using the word "default", maybe like

* If a command tag was requested and we did not fill in a
* run-time-determined tag above, copy the parse-time tag
* from the Portal. (There might not be any tag there either,
* in edge cases such as empty prepared statements. That's OK.)

regards, tom lane


From: Álvaro Herrera <alvherre(at)kurilemu(dot)de>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: Michael Paquier <michael(at)paquier(dot)xyz>, exclusion(at)gmail(dot)com, pgsql-bugs(at)lists(dot)postgresql(dot)org
Subject: Re: BUG #18984: Empty prepared statement from psql \parse triggers assert in PortalRunMulti
Date: 2025-07-17 15:48:27
Message-ID: [email protected]
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-bugs

On 2025-Jul-17, Tom Lane wrote:

> So rather than using the word "default", maybe like
>
> * If a command tag was requested and we did not fill in a
> * run-time-determined tag above, copy the parse-time tag
> * from the Portal. (There might not be any tag there either,
> * in edge cases such as empty prepared statements. That's OK.)

Oh yeah, this seems very clear. Pushed that way, thanks.

--
Álvaro Herrera Breisgau, Deutschland — https://www.EnterpriseDB.com/
"Oh, great altar of passive entertainment, bestow upon me thy discordant images
at such speed as to render linear thought impossible" (Calvin a la TV)