scrollable-fix.diff

text/plain

Filename: scrollable-fix.diff
Type: text/plain
Part: 0
Message: Re: BUG #18859: ERROR: unexpected plan node type: 356

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: unified
File+
src/pl/plpgsql/src/pl_exec.c 11 0
src/test/regress/expected/plpgsql.out 7 0
src/test/regress/sql/plpgsql.sql 8 0
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()