Skip to content

Commit ec02439

Browse files
dreamedchengwuchengwen
andauthored
Fix the invalid oidAssignments list for CTAS query with initplan (#12472)
If a query is a CTAS with initplan, it may reset 'Oid dispatch context' when an exception occurs in preprocess_initplans, which will further cause invlid list reference during the serialization of oidAssignments when dispatching plan. In this fix, we copy an extra list for oidAssignments for querys that contain CTAS and initplan. Co-authored-by: wuchengwen <wcw190496@alibaba-inc.com>
1 parent e2f2312 commit ec02439

File tree

3 files changed

+68
-8
lines changed

3 files changed

+68
-8
lines changed

src/backend/executor/execMain.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ standard_ExecutorStart(QueryDesc *queryDesc, int eflags)
206206
GpExecIdentity exec_identity;
207207
bool shouldDispatch;
208208
bool needDtx;
209+
List *toplevelOidCache = NIL;
209210

210211
/* sanity checks: queryDesc must not be started already */
211212
Assert(queryDesc != NULL);
@@ -581,11 +582,16 @@ standard_ExecutorStart(QueryDesc *queryDesc, int eflags)
581582
*
582583
* For details please see github issue https://github.com/greenplum-db/gpdb/issues/10760
583584
*/
584-
List *toplevelOidCache = NIL;
585585
if (queryDesc->ddesc != NULL)
586586
{
587587
queryDesc->ddesc->sliceTable = estate->es_sliceTable;
588-
toplevelOidCache = GetAssignedOidsForDispatch();
588+
/*
589+
* For CTAS querys that contain initplan, we need to copy a new oid dispatch list,
590+
* since the preprocess_initplan will start a subtransaction, and if it's rollbacked,
591+
* the memory context of 'Oid dispatch context' will be reset, which will cause invalid
592+
* list reference during the serialization of dispatch_oids when dispatching plan.
593+
*/
594+
toplevelOidCache = copyObject(GetAssignedOidsForDispatch());
589595
}
590596

591597
/*
@@ -641,6 +647,12 @@ standard_ExecutorStart(QueryDesc *queryDesc, int eflags)
641647
estate->es_param_exec_vals,
642648
needDtx, true);
643649
}
650+
651+
if (toplevelOidCache != NIL)
652+
{
653+
list_free(toplevelOidCache);
654+
toplevelOidCache = NIL;
655+
}
644656
}
645657

646658
/*
@@ -701,6 +713,11 @@ standard_ExecutorStart(QueryDesc *queryDesc, int eflags)
701713
}
702714
PG_CATCH();
703715
{
716+
if (toplevelOidCache != NIL)
717+
{
718+
list_free(toplevelOidCache);
719+
toplevelOidCache = NIL;
720+
}
704721
mppExecutorCleanup(queryDesc);
705722
PG_RE_THROW();
706723
}

src/test/regress/expected/gpctas.out

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -146,17 +146,16 @@ ALTER TABLE ctas_src DROP COLUMN col2;
146146
INSERT INTO ctas_src(col1, col3,col4,col5)
147147
SELECT g, 'a',True,g from generate_series(1,5) g;
148148
CREATE TABLE ctas_dst as SELECT col1,col3,col4,col5 FROM ctas_src order by 1;
149-
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column(s) named 'col4' as the Greenplum Database data distribution key for this table.
150-
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
149+
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause. Creating a NULL policy entry.
151150
-- This will fail to find some of the rows, if they're distributed incorrectly.
152151
SELECT * FROM ctas_src, ctas_dst WHERE ctas_src.col1 = ctas_dst.col1;
153152
col1 | col3 | col4 | col5 | col1 | col3 | col4 | col5
154153
------+------+------+------+------+------+------+------
155-
1 | a | t | 1 | 1 | a | t | 1
154+
5 | a | t | 5 | 5 | a | t | 5
156155
2 | a | t | 2 | 2 | a | t | 2
157156
3 | a | t | 3 | 3 | a | t | 3
158157
4 | a | t | 4 | 4 | a | t | 4
159-
5 | a | t | 5 | 5 | a | t | 5
158+
1 | a | t | 1 | 1 | a | t | 1
160159
(5 rows)
161160

162161
-- Github Issue 9365: https://github.com/greenplum-db/gpdb/issues/9365
@@ -203,8 +202,7 @@ CREATE TABLE ctas_base(a int, b int);
203202
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Greenplum Database data distribution key for this table.
204203
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
205204
CREATE TABLE ctas_aocs WITH (appendonly=true, orientation=column) AS SELECT * FROM ctas_base WITH NO DATA;
206-
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column(s) named 'a' as the Greenplum Database data distribution key for this table.
207-
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
205+
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause. Creating a NULL policy entry.
208206
SELECT * FROM ctas_aocs;
209207
a | b
210208
---+---
@@ -303,3 +301,29 @@ from
303301
refresh materialized view sro_mv_issue_11999;
304302
ERROR: division by zero
305303
CONTEXT: SQL function "mv_action_select_issue_11999" statement 1
304+
-- Test CTAS + initplan, and an exception was raised in preprocess_initplans
305+
CREATE OR REPLACE FUNCTION public.exception_func()
306+
RETURNS refcursor
307+
LANGUAGE plpgsql
308+
AS $function$declare cname refcursor = 'result'; begin open cname for select 1; raise sqlstate '02000'; return cname; exception when sqlstate '02000' then return cname; end;$function$;
309+
SELECT exception_func() INTO TEMPORARY test_tmp1;
310+
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column(s) named '' as the Greenplum Database data distribution key for this table.
311+
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
312+
SELECT * FROM test_tmp1;
313+
exception_func
314+
----------------
315+
result
316+
(1 row)
317+
318+
CREATE TEMPORARY TABLE test_tmp2 AS SELECT exception_func();
319+
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column(s) named '' as the Greenplum Database data distribution key for this table.
320+
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
321+
SELECT * FROM test_tmp2;
322+
exception_func
323+
----------------
324+
result
325+
(1 row)
326+
327+
DROP FUNCTION public.exception_func();
328+
DROP TABLE test_tmp1;
329+
DROP TABLE test_tmp2;

src/test/regress/sql/gpctas.sql

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,3 +199,22 @@ from
199199

200200
-- then refresh should error out
201201
refresh materialized view sro_mv_issue_11999;
202+
203+
204+
-- Test CTAS + initplan, and an exception was raised in preprocess_initplans
205+
CREATE OR REPLACE FUNCTION public.exception_func()
206+
RETURNS refcursor
207+
LANGUAGE plpgsql
208+
AS $function$declare cname refcursor = 'result'; begin open cname for select 1; raise sqlstate '02000'; return cname; exception when sqlstate '02000' then return cname; end;$function$;
209+
210+
SELECT exception_func() INTO TEMPORARY test_tmp1;
211+
212+
SELECT * FROM test_tmp1;
213+
214+
CREATE TEMPORARY TABLE test_tmp2 AS SELECT exception_func();
215+
216+
SELECT * FROM test_tmp2;
217+
218+
DROP FUNCTION public.exception_func();
219+
DROP TABLE test_tmp1;
220+
DROP TABLE test_tmp2;

0 commit comments

Comments
 (0)