|
24 | 24 | *values plus row-locating info for UPDATE and MERGE cases, or just the
|
25 | 25 | *row-locating info for DELETE cases.
|
26 | 26 | *
|
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, |
33 | 34 | *automatically updatable views.
|
34 | 35 | *
|
35 | 36 | *MERGE runs a join between the source relation and the target table.
|
@@ -2726,10 +2727,10 @@ ExecMerge(ModifyTableContext *context, ResultRelInfo *resultRelInfo,
|
2726 | 2727 |
|
2727 | 2728 | /*-----
|
2728 | 2729 | * 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. |
2733 | 2734 | *
|
2734 | 2735 | * Similarly, in the WHEN NOT MATCHED BY SOURCE case, tupleid or oldtuple
|
2735 | 2736 | * is valid, and we look at the given WHEN NOT MATCHED BY SOURCE actions
|
@@ -2820,8 +2821,8 @@ ExecMerge(ModifyTableContext *context, ResultRelInfo *resultRelInfo,
|
2820 | 2821 | * Check and execute the first qualifying MATCHED or NOT MATCHED BY SOURCE
|
2821 | 2822 | * action, depending on whether the join quals are satisfied. If the target
|
2822 | 2823 | * 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. |
2825 | 2826 | *
|
2826 | 2827 | * We start from the first WHEN MATCHED or WHEN NOT MATCHED BY SOURCE action
|
2827 | 2828 | * 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,
|
2887 | 2888 | */
|
2888 | 2889 | Assert(tupleid!=NULL||oldtuple!=NULL);
|
2889 | 2890 | if (oldtuple!=NULL)
|
2890 |
| -{ |
2891 |
| -Assert(resultRelInfo->ri_TrigDesc); |
2892 | 2891 | ExecForceStoreHeapTuple(oldtuple,resultRelInfo->ri_oldTupleSlot,
|
2893 | 2892 | false);
|
2894 |
| -} |
2895 | 2893 | elseif (!table_tuple_fetch_row_version(resultRelInfo->ri_RelationDesc,
|
2896 | 2894 | tupleid,
|
2897 | 2895 | SnapshotAny,
|
@@ -2983,6 +2981,9 @@ ExecMergeMatched(ModifyTableContext *context, ResultRelInfo *resultRelInfo,
|
2983 | 2981 | }
|
2984 | 2982 | else
|
2985 | 2983 | {
|
| 2984 | +/* called table_tuple_fetch_row_version() above */ |
| 2985 | +Assert(oldtuple==NULL); |
| 2986 | + |
2986 | 2987 | result=ExecUpdateAct(context,resultRelInfo,tupleid,
|
2987 | 2988 | NULL,newslot,canSetTag,
|
2988 | 2989 | &updateCxt);
|
@@ -3031,8 +3032,13 @@ ExecMergeMatched(ModifyTableContext *context, ResultRelInfo *resultRelInfo,
|
3031 | 3032 | returnNULL;/* "do nothing" */
|
3032 | 3033 | }
|
3033 | 3034 | else
|
| 3035 | +{ |
| 3036 | +/* called table_tuple_fetch_row_version() above */ |
| 3037 | +Assert(oldtuple==NULL); |
| 3038 | + |
3034 | 3039 | result=ExecDeleteAct(context,resultRelInfo,tupleid,
|
3035 | 3040 | false);
|
| 3041 | +} |
3036 | 3042 |
|
3037 | 3043 | if (result==TM_Ok)
|
3038 | 3044 | {
|
@@ -4004,8 +4010,8 @@ ExecModifyTable(PlanState *pstate)
|
4004 | 4010 | * know enough here to set t_tableOid. Quite separately from
|
4005 | 4011 | * this, the FDW may fetch its own junk attrs to identify the row.
|
4006 | 4012 | *
|
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. |
4009 | 4015 | */
|
4010 | 4016 | elseif (AttributeNumberIsValid(resultRelInfo->ri_RowIdAttNo))
|
4011 | 4017 | {
|
|