summaryrefslogtreecommitdiff
path: root/src/backend/executor
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor')
-rw-r--r--src/backend/executor/execMain.c23
-rw-r--r--src/backend/executor/execPartition.c8
-rw-r--r--src/backend/executor/nodeModifyTable.c3
3 files changed, 30 insertions, 4 deletions
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index c3d497e3fa5..00bbcea2a5a 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -981,11 +981,15 @@ InitPlan(QueryDesc *queryDesc, int eflags)
* Generally the parser and/or planner should have noticed any such mistake
* already, but let's make sure.
*
+ * For INSERT ON CONFLICT, the result relation is required to support the
+ * onConflictAction, regardless of whether a conflict actually occurs.
+ *
* Note: when changing this function, you probably also need to look at
* CheckValidRowMarkRel.
*/
void
-CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation)
+CheckValidResultRelNew(ResultRelInfo *resultRelInfo, CmdType operation,
+ OnConflictAction onConflictAction)
{
Relation resultRel = resultRelInfo->ri_RelationDesc;
TriggerDesc *trigDesc = resultRel->trigdesc;
@@ -1000,6 +1004,13 @@ CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation)
case RELKIND_RELATION:
case RELKIND_PARTITIONED_TABLE:
CheckCmdReplicaIdentity(resultRel, operation);
+
+ /*
+ * For INSERT ON CONFLICT DO UPDATE, additionally check that the
+ * target relation supports UPDATE.
+ */
+ if (onConflictAction == ONCONFLICT_UPDATE)
+ CheckCmdReplicaIdentity(resultRel, CMD_UPDATE);
break;
case RELKIND_SEQUENCE:
ereport(ERROR,
@@ -1119,6 +1130,16 @@ CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation)
}
/*
+ * ABI-compatible wrapper to emulate old version of the above function.
+ * Do not call this version in new code.
+ */
+void
+CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation)
+{
+ return CheckValidResultRelNew(resultRelInfo, operation, ONCONFLICT_NONE);
+}
+
+/*
* Check that a proposed rowmark target relation is a legal target
*
* In most cases parser and/or planner should have noticed this already, but
diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c
index 2fe21b7f2de..535ae2f09ff 100644
--- a/src/backend/executor/execPartition.c
+++ b/src/backend/executor/execPartition.c
@@ -360,8 +360,11 @@ ExecFindPartition(ModifyTableState *mtstate,
true, false);
if (rri)
{
+ ModifyTable *node = (ModifyTable *) mtstate->ps.plan;
+
/* Verify this ResultRelInfo allows INSERTs */
- CheckValidResultRel(rri, CMD_INSERT);
+ CheckValidResultRelNew(rri, CMD_INSERT,
+ node ? node->onConflictAction : ONCONFLICT_NONE);
/*
* Initialize information needed to insert this and
@@ -527,7 +530,8 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate,
* partition-key becomes a DELETE+INSERT operation, so this check is still
* required when the operation is CMD_UPDATE.
*/
- CheckValidResultRel(leaf_part_rri, CMD_INSERT);
+ CheckValidResultRelNew(leaf_part_rri, CMD_INSERT,
+ node ? node->onConflictAction : ONCONFLICT_NONE);
/*
* Open partition indices. The user may have asked to check for conflicts
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 1bd0ff60c12..fc10729a6ef 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -4241,7 +4241,8 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
/*
* Verify result relation is a valid target for the current operation
*/
- CheckValidResultRel(resultRelInfo, operation);
+ CheckValidResultRelNew(resultRelInfo, operation,
+ node->onConflictAction);
resultRelInfo++;
i++;