Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitd5e6891

Browse files
committed
Fix new assertion for MERGE view_name ... DO NOTHING.
Such queries don't expand automatically updatable views, and ModifyTableuses the wholerow attribute unconditionally. The user-visible behavioris fine, so change to more-specific assertions. Commitd5f788b added the wrong assertion.Back-patch to v17, where commit5f2e179introduced MERGE view_name.Reported by Alexander Lakhin.Discussion:https://postgr.es/m/e4b40a88-c134-6926-3196-bc4501cb87a2@gmail.com
1 parent7102070 commitd5e6891

File tree

3 files changed

+33
-17
lines changed

3 files changed

+33
-17
lines changed

‎src/backend/executor/nodeModifyTable.c

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,13 @@
2424
*values plus row-locating info for UPDATE and MERGE cases, or just the
2525
*row-locating info for DELETE cases.
2626
*
27-
*The relation to modify can be an ordinary table, a view having an
28-
*INSTEAD OF trigger, or a foreign table. Earlier processing already
29-
*pointed ModifyTable to the underlying relations of any automatically
30-
*updatable view not using an INSTEAD OF trigger, so code here can
31-
*assume it won't have one as a modification target. This node does
32-
*process ri_WithCheckOptions, which may have expressions from those
27+
*The relation to modify can be an ordinary table, a foreign table, or a
28+
*view. If it's a view, either it has sufficient INSTEAD OF triggers or
29+
*this node executes only MERGE ... DO NOTHING. If the original MERGE
30+
*targeted a view not in one of those two categories, earlier processing
31+
*already pointed the ModifyTable result relation to an underlying
32+
*relation of that other view. This node does process
33+
*ri_WithCheckOptions, which may have expressions from those other,
3334
*automatically updatable views.
3435
*
3536
*MERGE runs a join between the source relation and the target table.
@@ -2726,10 +2727,10 @@ ExecMerge(ModifyTableContext *context, ResultRelInfo *resultRelInfo,
27262727

27272728
/*-----
27282729
* If we are dealing with a WHEN MATCHED case, tupleid or oldtuple is
2729-
* valid, depending on whether the result relation is a table or a view
2730-
*having an INSTEAD OF trigger.We execute the first action for which
2731-
*the additional WHEN MATCHED ANDquals pass. If an action without quals
2732-
*is found, that action isexecuted.
2730+
* valid, depending on whether the result relation is a table or a view.
2731+
* We execute the first action for which the additional WHEN MATCHED AND
2732+
* quals pass. If an action without quals is found, that action is
2733+
* executed.
27332734
*
27342735
* Similarly, in the WHEN NOT MATCHED BY SOURCE case, tupleid or oldtuple
27352736
* is valid, and we look at the given WHEN NOT MATCHED BY SOURCE actions
@@ -2820,8 +2821,8 @@ ExecMerge(ModifyTableContext *context, ResultRelInfo *resultRelInfo,
28202821
* Check and execute the first qualifying MATCHED or NOT MATCHED BY SOURCE
28212822
* action, depending on whether the join quals are satisfied. If the target
28222823
* relation is a table, the current target tuple is identified by tupleid.
2823-
* Otherwise, if the target relation is a view having an INSTEAD OF trigger,
2824-
*oldtuple is the current targettuple from the view.
2824+
* Otherwise, if the target relation is a view, oldtuple is the current target
2825+
* tuple from the view.
28252826
*
28262827
* We start from the first WHEN MATCHED or WHEN NOT MATCHED BY SOURCE action
28272828
* and check if the WHEN quals pass, if any. If the WHEN quals for the first
@@ -2887,11 +2888,8 @@ ExecMergeMatched(ModifyTableContext *context, ResultRelInfo *resultRelInfo,
28872888
*/
28882889
Assert(tupleid!=NULL||oldtuple!=NULL);
28892890
if (oldtuple!=NULL)
2890-
{
2891-
Assert(resultRelInfo->ri_TrigDesc);
28922891
ExecForceStoreHeapTuple(oldtuple,resultRelInfo->ri_oldTupleSlot,
28932892
false);
2894-
}
28952893
elseif (!table_tuple_fetch_row_version(resultRelInfo->ri_RelationDesc,
28962894
tupleid,
28972895
SnapshotAny,
@@ -2983,6 +2981,9 @@ ExecMergeMatched(ModifyTableContext *context, ResultRelInfo *resultRelInfo,
29832981
}
29842982
else
29852983
{
2984+
/* called table_tuple_fetch_row_version() above */
2985+
Assert(oldtuple==NULL);
2986+
29862987
result=ExecUpdateAct(context,resultRelInfo,tupleid,
29872988
NULL,newslot,canSetTag,
29882989
&updateCxt);
@@ -3031,8 +3032,13 @@ ExecMergeMatched(ModifyTableContext *context, ResultRelInfo *resultRelInfo,
30313032
returnNULL;/* "do nothing" */
30323033
}
30333034
else
3035+
{
3036+
/* called table_tuple_fetch_row_version() above */
3037+
Assert(oldtuple==NULL);
3038+
30343039
result=ExecDeleteAct(context,resultRelInfo,tupleid,
30353040
false);
3041+
}
30363042

30373043
if (result==TM_Ok)
30383044
{
@@ -4004,8 +4010,8 @@ ExecModifyTable(PlanState *pstate)
40044010
* know enough here to set t_tableOid. Quite separately from
40054011
* this, the FDW may fetch its own junk attrs to identify the row.
40064012
*
4007-
* Other relevant relkinds, currently limited to views having
4008-
*INSTEAD OF triggers, alwayshave a wholerow attribute.
4013+
* Other relevant relkinds, currently limited to views, always
4014+
* have a wholerow attribute.
40094015
*/
40104016
elseif (AttributeNumberIsValid(resultRelInfo->ri_RowIdAttNo))
40114017
{

‎src/test/regress/expected/updatable_views.out

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,9 @@ MERGE INTO ro_view13 AS t USING (VALUES (3, 'Row 3')) AS v(a,b) ON t.a = v.a
199199
ERROR: cannot insert into view "ro_view13"
200200
DETAIL: Views that do not select from a single table or view are not automatically updatable.
201201
HINT: To enable inserting into the view using MERGE, provide an INSTEAD OF INSERT trigger.
202+
MERGE INTO ro_view13 AS t USING (VALUES (2, 'Row 2')) AS v(a,b) ON t.a = v.a
203+
WHEN MATCHED THEN DO NOTHING
204+
WHEN NOT MATCHED THEN DO NOTHING; -- should be OK to do nothing
202205
MERGE INTO ro_view13 AS t USING (VALUES (3, 'Row 3')) AS v(a,b) ON t.a = v.a
203206
WHEN MATCHED THEN DO NOTHING
204207
WHEN NOT MATCHED THEN DO NOTHING; -- should be OK to do nothing
@@ -375,6 +378,8 @@ DELETE FROM ro_view18;
375378
ERROR: cannot delete from view "ro_view18"
376379
DETAIL: Views that do not select from a single table or view are not automatically updatable.
377380
HINT: To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an unconditional ON DELETE DO INSTEAD rule.
381+
MERGE INTO ro_view18 AS t USING (VALUES (1, 'Row 1')) AS v(a,b) ON t.a = v.a
382+
WHEN MATCHED THEN DO NOTHING; -- should be OK to do nothing
378383
UPDATE ro_view19 SET last_value=1000;
379384
ERROR: cannot update view "ro_view19"
380385
DETAIL: Views that do not select from a single table or view are not automatically updatable.

‎src/test/regress/sql/updatable_views.sql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ MERGE INTO ro_view13 AS t USING (VALUES (2, 'Row 2')) AS v(a,b) ON t.a = v.a
6868
WHEN MATCHED THENUPDATESET b=v.b;
6969
MERGE INTO ro_view13AS t USING (VALUES (3,'Row 3'))AS v(a,b)ONt.a=v.a
7070
WHEN NOT MATCHED THEN INSERTVALUES (v.a,v.b);
71+
MERGE INTO ro_view13AS t USING (VALUES (2,'Row 2'))AS v(a,b)ONt.a=v.a
72+
WHEN MATCHED THEN DO NOTHING
73+
WHEN NOT MATCHED THEN DO NOTHING;-- should be OK to do nothing
7174
MERGE INTO ro_view13AS t USING (VALUES (3,'Row 3'))AS v(a,b)ONt.a=v.a
7275
WHEN MATCHED THEN DO NOTHING
7376
WHEN NOT MATCHED THEN DO NOTHING;-- should be OK to do nothing
@@ -121,6 +124,8 @@ DELETE FROM rw_view16 WHERE a=-3; -- should be OK
121124
-- Read-only views
122125
INSERT INTO ro_view17VALUES (3,'ROW 3');
123126
DELETEFROM ro_view18;
127+
MERGE INTO ro_view18AS t USING (VALUES (1,'Row 1'))AS v(a,b)ONt.a=v.a
128+
WHEN MATCHED THEN DO NOTHING;-- should be OK to do nothing
124129
UPDATE ro_view19SET last_value=1000;
125130
UPDATE ro_view20SET b=upper(b);
126131

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp