From 8cb69e3a143e8dc5be84348545295d088ca902be Mon Sep 17 00:00:00 2001 From: Jason Petersen Date: Fri, 18 Aug 2017 17:08:46 -0600 Subject: [PATCH] Add alias for target in multi-row INSERTs This is necessary for multi-row INSERTs for the same reasons we use it in e.g. UPSERTs: if the range table list has more than one entry, then PostgreSQL's deparse logic requires that vars be prefixed by the name of their corresponding range table entry. This of course doesn't affect single-row INSERTs, but since multi-row INSERTs have a VALUE RTE, they were affected. The piece of ruleutils which builds range table names wasn't modified to handle shard extension; instead UPSERT/INSERT INTO ... SELECT added an alias to the RTE. When present, this alias is favored. Doing the same in the multi-row INSERT case fixes RETURNING for such commands. --- .../distributed/planner/deparse_shard_query.c | 8 ++++++-- src/test/regress/expected/multi_explain.out | 2 +- src/test/regress/expected/multi_explain_0.out | 2 +- src/test/regress/expected/multi_modifications.out | 12 ++++++++++-- src/test/regress/sql/multi_modifications.sql | 5 +++-- 5 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/backend/distributed/planner/deparse_shard_query.c b/src/backend/distributed/planner/deparse_shard_query.c index 07aa37729..c06ff794c 100644 --- a/src/backend/distributed/planner/deparse_shard_query.c +++ b/src/backend/distributed/planner/deparse_shard_query.c @@ -82,11 +82,15 @@ RebuildQueryStrings(Query *originalQuery, List *taskList) UpdateRelationToShardNames((Node *) copiedSubquery, relationShardList); } - else if (task->upsertQuery) + else if (task->upsertQuery || valuesRTE != NULL) { RangeTblEntry *rangeTableEntry = NULL; - /* setting an alias simplifies deparsing of UPSERTs */ + /* + * Always an alias in UPSERTs and multi-row INSERTs to avoid + * deparsing issues (e.g. RETURNING might reference the original + * table name, which has been replaced by a shard name). + */ rangeTableEntry = linitial(query->rtable); if (rangeTableEntry->alias == NULL) { diff --git a/src/test/regress/expected/multi_explain.out b/src/test/regress/expected/multi_explain.out index 4ce4b795d..ebe3f5573 100644 --- a/src/test/regress/expected/multi_explain.out +++ b/src/test/regress/expected/multi_explain.out @@ -305,7 +305,7 @@ Custom Scan (Citus Router) Tasks Shown: All -> Task Node: host=localhost port=57638 dbname=regression - -> Insert on lineitem_290000 + -> Insert on lineitem_290000 citus_table_alias -> Values Scan on "*VALUES*" -- Test update EXPLAIN (COSTS FALSE) diff --git a/src/test/regress/expected/multi_explain_0.out b/src/test/regress/expected/multi_explain_0.out index f44ac8d9c..09ec08e33 100644 --- a/src/test/regress/expected/multi_explain_0.out +++ b/src/test/regress/expected/multi_explain_0.out @@ -305,7 +305,7 @@ Custom Scan (Citus Router) Tasks Shown: All -> Task Node: host=localhost port=57638 dbname=regression - -> Insert on lineitem_290000 + -> Insert on lineitem_290000 citus_table_alias -> Values Scan on "*VALUES*" -- Test update EXPLAIN (COSTS FALSE) diff --git a/src/test/regress/expected/multi_modifications.out b/src/test/regress/expected/multi_modifications.out index 606d329da..874b54a42 100644 --- a/src/test/regress/expected/multi_modifications.out +++ b/src/test/regress/expected/multi_modifications.out @@ -211,10 +211,18 @@ SELECT COUNT(*) FROM limit_orders WHERE id BETWEEN 12037 AND 12039; 3 (1 row) --- even those with functions +-- even those with functions and returning INSERT INTO limit_orders VALUES (22037, 'GOOG', 5634, now(), 'buy', 0.50), (22038, 'GOOG', 5634, now(), 'buy', 2.50), - (22039, 'GOOG', 5634, now(), 'buy', 1.50); + (22039, 'GOOG', 5634, now(), 'buy', 1.50) +RETURNING id; + id +------- + 22038 + 22039 + 22037 +(3 rows) + SELECT COUNT(*) FROM limit_orders WHERE id BETWEEN 22037 AND 22039; count ------- diff --git a/src/test/regress/sql/multi_modifications.sql b/src/test/regress/sql/multi_modifications.sql index cfe2df393..b105fb189 100644 --- a/src/test/regress/sql/multi_modifications.sql +++ b/src/test/regress/sql/multi_modifications.sql @@ -153,10 +153,11 @@ INSERT INTO limit_orders VALUES (12037, 'GOOG', 5634, '2001-04-16 03:37:28', 'bu SELECT COUNT(*) FROM limit_orders WHERE id BETWEEN 12037 AND 12039; --- even those with functions +-- even those with functions and returning INSERT INTO limit_orders VALUES (22037, 'GOOG', 5634, now(), 'buy', 0.50), (22038, 'GOOG', 5634, now(), 'buy', 2.50), - (22039, 'GOOG', 5634, now(), 'buy', 1.50); + (22039, 'GOOG', 5634, now(), 'buy', 1.50) +RETURNING id; SELECT COUNT(*) FROM limit_orders WHERE id BETWEEN 22037 AND 22039;