From 94b63f35a5231d1809ef09977c8b39508eb5e0d7 Mon Sep 17 00:00:00 2001 From: Hanefi Onaldi Date: Tue, 24 Jan 2023 20:07:43 +0300 Subject: [PATCH] Prevent crashes on update with returning clauses (#6643) If an update query on a reference table has a returns clause with a subquery that accesses some other local table, we end-up with an crash. This commit prevents the crash, but does not prevent other error messages from happening due to Citus not being able to pushdown the results of that subquery in a valid SQL command. Related: #6634 --- .../distributed/planner/combine_query_planner.c | 4 ++++ .../regress/expected/coordinator_evaluation.out | 13 +++++++++++++ src/test/regress/sql/coordinator_evaluation.sql | 8 ++++++++ 3 files changed, 25 insertions(+) diff --git a/src/backend/distributed/planner/combine_query_planner.c b/src/backend/distributed/planner/combine_query_planner.c index 1ada6bcc0..e61ff8daf 100644 --- a/src/backend/distributed/planner/combine_query_planner.c +++ b/src/backend/distributed/planner/combine_query_planner.c @@ -338,6 +338,10 @@ FindCitusExtradataContainerRTE(Node *node, RangeTblEntry **result) { RangeTblFunction *rangeTblFunction = (RangeTblFunction *) linitial( rangeTblEntry->functions); + if (!IsA(rangeTblFunction->funcexpr, FuncExpr)) + { + return false; + } FuncExpr *funcExpr = castNode(FuncExpr, rangeTblFunction->funcexpr); if (funcExpr->funcid == CitusExtraDataContainerFuncId()) { diff --git a/src/test/regress/expected/coordinator_evaluation.out b/src/test/regress/expected/coordinator_evaluation.out index f7c648d97..513822af3 100644 --- a/src/test/regress/expected/coordinator_evaluation.out +++ b/src/test/regress/expected/coordinator_evaluation.out @@ -609,5 +609,18 @@ SELECT * FROM reference_table ORDER BY 1; (5) (5 rows) +-- failing UPDATE on a reference table with a subquery in RETURNING clause that needs to be pushed-down. +-- the error message is not great, but at least we no longer see crashes. +CREATE TABLE ref (a int); +SELECT create_reference_table('ref'); + create_reference_table +--------------------------------------------------------------------- + +(1 row) + +UPDATE ref SET a = 1 RETURNING + (SELECT pg_catalog.max(latest_end_time) FROM pg_catalog.pg_stat_wal_receiver) + as c3; +ERROR: a column definition list is required for functions returning "record" SET client_min_messages TO ERROR; DROP SCHEMA coordinator_evaluation CASCADE; diff --git a/src/test/regress/sql/coordinator_evaluation.sql b/src/test/regress/sql/coordinator_evaluation.sql index 10bea8842..75f3e3d1f 100644 --- a/src/test/regress/sql/coordinator_evaluation.sql +++ b/src/test/regress/sql/coordinator_evaluation.sql @@ -223,5 +223,13 @@ INSERT INTO reference_table VALUES ('(4)'), ('(5)'); SELECT * FROM reference_table ORDER BY 1; +-- failing UPDATE on a reference table with a subquery in RETURNING clause that needs to be pushed-down. +-- the error message is not great, but at least we no longer see crashes. +CREATE TABLE ref (a int); +SELECT create_reference_table('ref'); +UPDATE ref SET a = 1 RETURNING + (SELECT pg_catalog.max(latest_end_time) FROM pg_catalog.pg_stat_wal_receiver) + as c3; + SET client_min_messages TO ERROR; DROP SCHEMA coordinator_evaluation CASCADE;