diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index d4377ceecbf..f3691eb2f58 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -8306,6 +8306,8 @@ exec_save_simple_expr(PLpgSQL_expr *expr, CachedPlan *cplan) * Gather node. The Gather node's tlist would normally contain a Var * referencing the child node's output, but it could also be a Param, or * it could be a Const that setrefs.c copied as-is. + * Also, in case of scrollable cursor it contains Material node at the top + * of the plan tree. */ plan = stmt->planTree; for (;;) @@ -8338,6 +8340,15 @@ exec_save_simple_expr(PLpgSQL_expr *expr, CachedPlan *cplan) /* Descend to the child node */ plan = plan->lefttree; } + else if (IsA(plan, Material)) + { + Assert(plan->lefttree != NULL && + plan->righttree == NULL && + plan->initPlan == NULL && + plan->qual == NULL); + Assert(plan == stmt->planTree); + plan = plan->lefttree; + } else elog(ERROR, "unexpected plan node type: %d", (int) nodeTag(plan)); diff --git a/src/test/regress/expected/plpgsql.out b/src/test/regress/expected/plpgsql.out index d8ce39dba3c..0e5435ebdfc 100644 --- a/src/test/regress/expected/plpgsql.out +++ b/src/test/regress/expected/plpgsql.out @@ -3656,6 +3656,13 @@ $$ language plpgsql; ERROR: cursor FOR loop must use a bound cursor variable LINE 5: for r in c loop ^ +-- Test scrollable cursor and simple expression optimisation +DO $$ +DECLARE + p_CurData refcursor; +BEGIN + OPEN p_CurData SCROLL FOR SELECT NULL; +END; $$; -- test RETURN QUERY EXECUTE create or replace function return_dquery() returns setof int as $$ diff --git a/src/test/regress/sql/plpgsql.sql b/src/test/regress/sql/plpgsql.sql index d413d995d17..7797beb6e03 100644 --- a/src/test/regress/sql/plpgsql.sql +++ b/src/test/regress/sql/plpgsql.sql @@ -3034,6 +3034,14 @@ begin end; $$ language plpgsql; +-- Test scrollable cursor and simple expression optimisation +DO $$ +DECLARE + p_CurData refcursor; +BEGIN + OPEN p_CurData SCROLL FOR SELECT NULL; +END; $$; + -- test RETURN QUERY EXECUTE create or replace function return_dquery()