BUG #18859: ERROR: unexpected plan node type: 356

Started by PG Bug reporting formabout 1 year ago7 messagesbugs
Jump to latest
#1PG Bug reporting form
noreply@postgresql.org

The following bug has been logged on the website:

Bug reference: 18859
Logged by: Olleg Samoylov
Email address: splarv@ya.ru
PostgreSQL version: 17.4
Operating system: RedOS 8
Description:

This working.
postgres=> do $$ declare p_CurData refcursor; begin OPEN p_CurData FOR
SELECT NULL::int id; end;$$;
DO
But this is not. Internal error.
postgres=> do $$ declare p_CurData refcursor; begin OPEN p_CurData SCROLL
FOR SELECT NULL::int id; end;$$;
ERROR: unexpected plan node type: 356
CONTEXT: PL/pgSQL function inline_code_block line 1 at OPEN

#2Andrei Lepikhov
lepihov@gmail.com
In reply to: PG Bug reporting form (#1)
Re: BUG #18859: ERROR: unexpected plan node type: 356

On 20/3/2025 14:53, PG Bug reporting form wrote:

The following bug has been logged on the website:

Bug reference: 18859
Logged by: Olleg Samoylov
Email address: splarv@ya.ru
PostgreSQL version: 17.4
Operating system: RedOS 8
Description:

This working.
postgres=> do $$ declare p_CurData refcursor; begin OPEN p_CurData FOR
SELECT NULL::int id; end;$$;
DO
But this is not. Internal error.
postgres=> do $$ declare p_CurData refcursor; begin OPEN p_CurData SCROLL
FOR SELECT NULL::int id; end;$$;
ERROR: unexpected plan node type: 356
CONTEXT: PL/pgSQL function inline_code_block line 1 at OPEN

It may be reproduced with any expression, treated as a simple
expression. For example:

DO $$
DECLARE
p_CurData refcursor;
BEGIN
OPEN p_CurData SCROLL FOR SELECT now();
END; $$;

The problem here is in the scrollable cursors code which inserts
Material node:

if (cursorOptions & CURSOR_OPT_SCROLL)
{
if (!ExecSupportsBackwardScan(top_plan))
top_plan = materialize_finished_plan(top_plan);
}

But the exec_save_simple_expr() doesn't process Material node and causes
the ERROR.

--
regards, Andrei Lepikhov

#3Tom Lane
tgl@sss.pgh.pa.us
In reply to: Andrei Lepikhov (#2)
Re: BUG #18859: ERROR: unexpected plan node type: 356

Andrei Lepikhov <lepihov@gmail.com> writes:

The problem here is in the scrollable cursors code which inserts
Material node:

Yeah, I'd just come to the same conclusion. I guess we can make
this code look through a Material node as well as Gather.

regards, tom lane

#4Andrei Lepikhov
lepihov@gmail.com
In reply to: Tom Lane (#3)
Re: BUG #18859: ERROR: unexpected plan node type: 356

On 21/3/2025 14:00, Tom Lane wrote:

Andrei Lepikhov <lepihov@gmail.com> writes:

The problem here is in the scrollable cursors code which inserts
Material node:

Yeah, I'd just come to the same conclusion. I guess we can make
this code look through a Material node as well as Gather.

Yes, as I see there are no additional corner cases. See the code in
attachment.

--
regards, Andrei Lepikhov

Attachments:

scrollable-fix.difftext/plain; charset=UTF-8; name=scrollable-fix.diffDownload+26-0
#5Richard Guo
guofenglinux@gmail.com
In reply to: Andrei Lepikhov (#4)
Re: BUG #18859: ERROR: unexpected plan node type: 356

On Fri, Mar 21, 2025 at 11:49 PM Andrei Lepikhov <lepihov@gmail.com> wrote:

On 21/3/2025 14:00, Tom Lane wrote:

Andrei Lepikhov <lepihov@gmail.com> writes:

The problem here is in the scrollable cursors code which inserts
Material node:

Yeah, I'd just come to the same conclusion. I guess we can make
this code look through a Material node as well as Gather.

Yes, as I see there are no additional corner cases. See the code in
attachment.

A Material's tlist could also be a Const copied up by setrefs.c, in
which case we can avoid looking further, similar to what Gather does.
I wonder if we could have Material use the same handle as Gather.

-       else if (IsA(plan, Gather))
+       else if (IsA(plan, Gather) || IsA(plan, Material))

Thanks
Richard

#6Tom Lane
tgl@sss.pgh.pa.us
In reply to: Andrei Lepikhov (#4)
Re: BUG #18859: ERROR: unexpected plan node type: 356

Andrei Lepikhov <lepihov@gmail.com> writes:

On 21/3/2025 14:00, Tom Lane wrote:

Yeah, I'd just come to the same conclusion. I guess we can make
this code look through a Material node as well as Gather.

Yes, as I see there are no additional corner cases. See the code in
attachment.

I think actually we want to use the same processing as for Gather,
in particular the check for a Const. That's all about what
setrefs.c will do to the plan tree, and it'll do the same things
to Material as it would to Gather. Since that stanza doesn't
actually do anything that's specific to Gather, the code change
can be as simple as

@@ -8323,7 +8325,7 @@ exec_save_simple_expr(PLpgSQL_expr *expr, CachedPlan *cplan)
 				   ((Result *) plan)->resconstantqual == NULL);
 			break;
 		}
-		else if (IsA(plan, Gather))
+		else if (IsA(plan, Gather) || IsA(plan, Material))
 		{
 			Assert(plan->lefttree != NULL &&
 				   plan->righttree == NULL &&

I fixed that, did some cosmetic fooling with the comment
and test case, and pushed it. Thanks for the report,
and for the patch!

regards, tom lane

#7Tom Lane
tgl@sss.pgh.pa.us
In reply to: Richard Guo (#5)
Re: BUG #18859: ERROR: unexpected plan node type: 356

Richard Guo <guofenglinux@gmail.com> writes:

A Material's tlist could also be a Const copied up by setrefs.c, in
which case we can avoid looking further, similar to what Gather does.
I wonder if we could have Material use the same handle as Gather.

Right, I'd come to the same conclusion before seeing your message.

regards, tom lane