bug18634-fix.patch
text/x-patch
Filename: bug18634-fix.patch
Type: text/x-patch
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/optimizer/prep/prepjointree.c | 38 | 0 |
| src/test/regress/expected/merge.out | 21 | 0 |
| src/test/regress/sql/merge.sql | 20 | 0 |
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
new file mode 100644
index a704045..322d511
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -257,6 +257,44 @@ transform_MERGE_to_join(Query *parse)
bms_make_singleton(joinrti));
/*
+ * Similarly, any non-target Vars in the join condition will be added to
+ * the targetlist by preprocess_targetlist(), and so must be marked as
+ * nullable by the join, for LEFT and FULL joins. The same goes for Vars
+ * in action quals, action targetlists and the RETURNING list.
+ */
+ if (jointype == JOIN_LEFT || jointype == JOIN_FULL)
+ {
+ Bitmapset *nontargetrels = NULL;
+
+ for (int i = 1; i < joinrti; i++)
+ if (i != parse->mergeTargetRelation)
+ nontargetrels = bms_add_member(nontargetrels, i);
+
+ parse->mergeJoinCondition =
+ add_nulling_relids(parse->mergeJoinCondition,
+ nontargetrels,
+ bms_make_singleton(joinrti));
+
+ foreach_node(MergeAction, action, parse->mergeActionList)
+ {
+ action->qual =
+ add_nulling_relids(action->qual,
+ nontargetrels,
+ bms_make_singleton(joinrti));
+
+ action->targetList = (List *)
+ add_nulling_relids((Node *) action->targetList,
+ nontargetrels,
+ bms_make_singleton(joinrti));
+ }
+
+ parse->returningList = (List *)
+ add_nulling_relids((Node *) parse->returningList,
+ nontargetrels,
+ bms_make_singleton(joinrti));
+ }
+
+ /*
* If there are any WHEN NOT MATCHED BY SOURCE actions, the executor will
* use the join condition to distinguish between MATCHED and NOT MATCHED
* BY SOURCE cases. Otherwise, it's no longer needed, and we set it to
diff --git a/src/test/regress/expected/merge.out b/src/test/regress/expected/merge.out
new file mode 100644
index 3d33259..ff0e167
--- a/src/test/regress/expected/merge.out
+++ b/src/test/regress/expected/merge.out
@@ -2689,6 +2689,27 @@ DETAIL: drop cascades to table measurem
drop cascades to table measurement_y2006m03
drop cascades to table measurement_y2007m01
DROP FUNCTION measurement_insert_trigger();
+--
+-- test for bug #18634
+--
+CREATE TABLE bug18634t (a int, b int);
+INSERT INTO bug18634t VALUES(1, 10), (2, 20);
+CREATE VIEW bug18634v AS
+ SELECT * FROM bug18634t WHERE EXISTS (SELECT 1 FROM bug18634t);
+CREATE TABLE bug18634s (a int, b int);
+INSERT INTO bug18634s VALUES (1, 2);
+MERGE INTO bug18634v t USING bug18634s s ON s.a = t.a
+WHEN MATCHED THEN UPDATE SET b = s.b
+WHEN NOT MATCHED BY SOURCE THEN DELETE;
+SELECT * FROM bug18634t;
+ a | b
+---+---
+ 1 | 2
+(1 row)
+
+DROP TABLE bug18634t CASCADE;
+NOTICE: drop cascades to view bug18634v
+DROP TABLE bug18634s;
-- prepare
RESET SESSION AUTHORIZATION;
-- try a system catalog
diff --git a/src/test/regress/sql/merge.sql b/src/test/regress/sql/merge.sql
new file mode 100644
index 92163ec..020d22e
--- a/src/test/regress/sql/merge.sql
+++ b/src/test/regress/sql/merge.sql
@@ -1710,6 +1710,26 @@ SELECT * FROM new_measurement ORDER BY c
DROP TABLE measurement, new_measurement CASCADE;
DROP FUNCTION measurement_insert_trigger();
+--
+-- test for bug #18634
+--
+CREATE TABLE bug18634t (a int, b int);
+INSERT INTO bug18634t VALUES(1, 10), (2, 20);
+CREATE VIEW bug18634v AS
+ SELECT * FROM bug18634t WHERE EXISTS (SELECT 1 FROM bug18634t);
+
+CREATE TABLE bug18634s (a int, b int);
+INSERT INTO bug18634s VALUES (1, 2);
+
+MERGE INTO bug18634v t USING bug18634s s ON s.a = t.a
+WHEN MATCHED THEN UPDATE SET b = s.b
+WHEN NOT MATCHED BY SOURCE THEN DELETE;
+
+SELECT * FROM bug18634t;
+
+DROP TABLE bug18634t CASCADE;
+DROP TABLE bug18634s;
+
-- prepare
RESET SESSION AUTHORIZATION;