aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/optimizer/plan/analyzejoins.c8
-rw-r--r--src/test/regress/expected/merge.out35
-rw-r--r--src/test/regress/sql/merge.sql20
3 files changed, 63 insertions, 0 deletions
diff --git a/src/backend/optimizer/plan/analyzejoins.c b/src/backend/optimizer/plan/analyzejoins.c
index 0dfefd71f21..f79bc4430c1 100644
--- a/src/backend/optimizer/plan/analyzejoins.c
+++ b/src/backend/optimizer/plan/analyzejoins.c
@@ -183,6 +183,14 @@ join_is_removable(PlannerInfo *root, SpecialJoinInfo *sjinfo)
if (!bms_get_singleton_member(sjinfo->min_righthand, &innerrelid))
return false;
+ /*
+ * Never try to eliminate a left join to the query result rel. Although
+ * the case is syntactically impossible in standard SQL, MERGE will build
+ * a join tree that looks exactly like that.
+ */
+ if (innerrelid == root->parse->resultRelation)
+ return false;
+
innerrel = find_base_rel(root, innerrelid);
/*
diff --git a/src/test/regress/expected/merge.out b/src/test/regress/expected/merge.out
index bc53b2105b4..2cf1409470b 100644
--- a/src/test/regress/expected/merge.out
+++ b/src/test/regress/expected/merge.out
@@ -1773,6 +1773,41 @@ SELECT * FROM pa_target ORDER BY tid;
ROLLBACK;
DROP TABLE pa_source;
DROP TABLE pa_target CASCADE;
+-- Partitioned table with primary key
+CREATE TABLE pa_target (tid integer PRIMARY KEY) PARTITION BY LIST (tid);
+CREATE TABLE pa_targetp PARTITION OF pa_target DEFAULT;
+CREATE TABLE pa_source (sid integer);
+INSERT INTO pa_source VALUES (1), (2);
+EXPLAIN (VERBOSE, COSTS OFF)
+MERGE INTO pa_target t USING pa_source s ON t.tid = s.sid
+ WHEN NOT MATCHED THEN INSERT VALUES (s.sid);
+ QUERY PLAN
+-------------------------------------------------------------
+ Merge on public.pa_target t
+ Merge on public.pa_targetp t_1
+ -> Hash Left Join
+ Output: s.sid, t_1.tableoid, t_1.ctid
+ Inner Unique: true
+ Hash Cond: (s.sid = t_1.tid)
+ -> Seq Scan on public.pa_source s
+ Output: s.sid
+ -> Hash
+ Output: t_1.tid, t_1.tableoid, t_1.ctid
+ -> Seq Scan on public.pa_targetp t_1
+ Output: t_1.tid, t_1.tableoid, t_1.ctid
+(12 rows)
+
+MERGE INTO pa_target t USING pa_source s ON t.tid = s.sid
+ WHEN NOT MATCHED THEN INSERT VALUES (s.sid);
+TABLE pa_target;
+ tid
+-----
+ 1
+ 2
+(2 rows)
+
+DROP TABLE pa_source;
+DROP TABLE pa_target CASCADE;
-- some complex joins on the source side
CREATE TABLE cj_target (tid integer, balance float, val text)
WITH (autovacuum_enabled=off);
diff --git a/src/test/regress/sql/merge.sql b/src/test/regress/sql/merge.sql
index fdbcd708823..cef37e57d92 100644
--- a/src/test/regress/sql/merge.sql
+++ b/src/test/regress/sql/merge.sql
@@ -1116,6 +1116,26 @@ ROLLBACK;
DROP TABLE pa_source;
DROP TABLE pa_target CASCADE;
+-- Partitioned table with primary key
+
+CREATE TABLE pa_target (tid integer PRIMARY KEY) PARTITION BY LIST (tid);
+CREATE TABLE pa_targetp PARTITION OF pa_target DEFAULT;
+CREATE TABLE pa_source (sid integer);
+
+INSERT INTO pa_source VALUES (1), (2);
+
+EXPLAIN (VERBOSE, COSTS OFF)
+MERGE INTO pa_target t USING pa_source s ON t.tid = s.sid
+ WHEN NOT MATCHED THEN INSERT VALUES (s.sid);
+
+MERGE INTO pa_target t USING pa_source s ON t.tid = s.sid
+ WHEN NOT MATCHED THEN INSERT VALUES (s.sid);
+
+TABLE pa_target;
+
+DROP TABLE pa_source;
+DROP TABLE pa_target CASCADE;
+
-- some complex joins on the source side
CREATE TABLE cj_target (tid integer, balance float, val text)