* Normally we remove quals that are implied by a partial index's
* predicate from indrestrictinfo, indicating that they need not be
* checked explicitly by an indexscan plan using this index. However, if
- * the rel is a target relation of UPDATE/DELETE/SELECT FOR UPDATE, we
- * cannot remove such quals from the plan, because they need to be in the
- * plan so that they will be properly rechecked by EvalPlanQual testing.
- * Some day we might want to remove such quals from the main plan anyway
- * and pass them through to EvalPlanQual via a side channel; but for now,
- * we just don't remove implied quals at all for target relations.
+ * the rel is a target relation of UPDATE/DELETE/MERGE/SELECT FOR UPDATE,
+ * we cannot remove such quals from the plan, because they need to be in
+ * the plan so that they will be properly rechecked by EvalPlanQual
+ * testing. Some day we might want to remove such quals from the main
+ * plan anyway and pass them through to EvalPlanQual via a side channel;
+ * but for now, we just don't remove implied quals at all for target
+ * relations.
*/
is_target_rel = (bms_is_member(rel->relid, root->all_result_relids) ||
get_plan_rowmark(root->rowMarks, rel->relid) != NULL);
add_other_rels_to_query(root);
/*
- * Distribute any UPDATE/DELETE row identity variables to the target
+ * Distribute any UPDATE/DELETE/MERGE row identity variables to the target
* relations. This can't be done till we've finished expansion of
* appendrels.
*/
if (bms_membership(root->all_result_relids) == BMS_MULTIPLE)
{
- /* Inherited UPDATE/DELETE */
+ /* Inherited UPDATE/DELETE/MERGE */
RelOptInfo *top_result_rel = find_base_rel(root,
parse->resultRelation);
int resultRelation = -1;
}
else
{
- /* Single-relation INSERT/UPDATE/DELETE. */
+ /* Single-relation INSERT/UPDATE/DELETE/MERGE. */
resultRelations = list_make1_int(parse->resultRelation);
if (parse->commandType == CMD_UPDATE)
updateColnosLists = list_make1(root->update_colnos);
/*
* add_row_identity_var
- * Register a row-identity column to be used in UPDATE/DELETE.
+ * Register a row-identity column to be used in UPDATE/DELETE/MERGE.
*
* The Var must be equal(), aside from varno, to any other row-identity
* column with the same rowid_name. Thus, for example, "wholerow"
* distribute_row_identity_vars
*
* After we have finished identifying all the row identity columns
- * needed by an inherited UPDATE/DELETE query, make sure that these
- * columns will be generated by all the target relations.
+ * needed by an inherited UPDATE/DELETE/MERGE query, make sure that
+ * these columns will be generated by all the target relations.
*
* This is more or less like what build_base_rel_tlists() does,
* except that it would not understand what to do with ROWID_VAR Vars.
/*
* If we are creating a child of the query target relation (only possible
- * in UPDATE/DELETE), add it to all_result_relids, as well as
+ * in UPDATE/DELETE/MERGE), add it to all_result_relids, as well as
* leaf_result_relids if appropriate, and make sure that we generate
* required row-identity data.
*/
/*
* create_modifytable_path
- * Creates a pathnode that represents performing INSERT/UPDATE/DELETE mods
+ * Creates a pathnode that represents performing INSERT/UPDATE/DELETE/MERGE
+ * mods
*
* 'rel' is the parent relation associated with the result
* 'subpath' is a Path producing source data
if (var->varno == ROWID_VAR)
{
- /* UPDATE/DELETE row identity vars are always needed */
+ /* UPDATE/DELETE/MERGE row identity vars are always needed */
RowIdentityVarInfo *ridinfo = (RowIdentityVarInfo *)
list_nth(root->row_identity_vars, var->varattno - 1);
/*
* setTargetTable
- * Add the target relation of INSERT/UPDATE/DELETE to the range table,
+ * Add the target relation of INSERT/UPDATE/DELETE/MERGE to the range table,
* and make the special links to it in the ParseState.
*
* We also open the target relation and acquire a write lock on it.
*
* If alsoSource is true, add the target to the query's joinlist and
* namespace. For INSERT, we don't want the target to be joined to;
- * it's a destination of tuples, not a source. For UPDATE/DELETE,
+ * it's a destination of tuples, not a source. MERGE is actually
+ * both, but we'll add it separately to joinlist and namespace, so
+ * doing nothing (like INSERT) is correct here. For UPDATE/DELETE,
* we do need to scan or join the target. (NOTE: we do not bother
* to check for namespace conflict; we assume that the namespace was
* initially empty in these cases.)
/*
* Check to see if the sublink is in an invalid place within the query. We
- * allow sublinks everywhere in SELECT/INSERT/UPDATE/DELETE, but generally
- * not in utility statements.
+ * allow sublinks everywhere in SELECT/INSERT/UPDATE/DELETE/MERGE, but
+ * generally not in utility statements.
*/
err = NULL;
switch (pstate->p_expr_kind)
errmsg("unreachable WHEN clause specified after unconditional WHEN clause")));
}
- /* Set up the MERGE target table. */
+ /*
+ * Set up the MERGE target table. The target table is added to the
+ * namespace below and to joinlist in transform_MERGE_to_join, so don't
+ * do it here.
+ */
qry->resultRelation = setTargetTable(pstate, stmt->relation,
stmt->relation->inh,
false, targetPerms);
*
* rellockmode is really LOCKMODE, but it's declared int to avoid having
* to include lock-related headers here. It must be RowExclusiveLock if
- * the RTE is an INSERT/UPDATE/DELETE target, else RowShareLock if the RTE
- * is a SELECT FOR UPDATE/FOR SHARE target, else AccessShareLock.
+ * the RTE is an INSERT/UPDATE/DELETE/MERGE target, else RowShareLock if
+ * the RTE is a SELECT FOR UPDATE/FOR SHARE target, else AccessShareLock.
*
* Note: in some cases, rule expansion may result in RTEs that are marked
* with RowExclusiveLock even though they are not the target of the
/*
* all_result_relids is empty for SELECT, otherwise it contains at least
- * parse->resultRelation. For UPDATE/DELETE across an inheritance or
- * partitioning tree, the result rel's child relids are added. When using
- * multi-level partitioning, intermediate partitioned rels are included.
- * leaf_result_relids is similar except that only actual result tables,
- * not partitioned tables, are included in it.
+ * parse->resultRelation. For UPDATE/DELETE/MERGE across an inheritance
+ * or partitioning tree, the result rel's child relids are added. When
+ * using multi-level partitioning, intermediate partitioned rels are
+ * included. leaf_result_relids is similar except that only actual result
+ * tables, not partitioned tables, are included in it.
*/
/* set of all result relids */
Relids all_result_relids;
} AppendRelInfo;
/*
- * Information about a row-identity "resjunk" column in UPDATE/DELETE.
+ * Information about a row-identity "resjunk" column in UPDATE/DELETE/MERGE.
*
- * In partitioned UPDATE/DELETE it's important for child partitions to share
- * row-identity columns whenever possible, so as not to chew up too many
+ * In partitioned UPDATE/DELETE/MERGE it's important for child partitions to
+ * share row-identity columns whenever possible, so as not to chew up too many
* targetlist columns. We use these structs to track which identity columns
* have been requested. In the finished plan, each of these will give rise
* to one resjunk entry in the targetlist of the ModifyTable's subplan node.
List *rtable; /* list of RangeTblEntry nodes */
- /* rtable indexes of target relations for INSERT/UPDATE/DELETE */
+ /* rtable indexes of target relations for INSERT/UPDATE/DELETE/MERGE */
List *resultRelations; /* integer list of RT indexes, or NIL */
List *appendRelations; /* list of AppendRelInfo nodes */
* nominalRelation and rootRelation contain the RT index of the partition
* root, which is not otherwise mentioned in the plan. Otherwise rootRelation
* is zero. However, nominalRelation will always be set, as it's the rel that
- * EXPLAIN should claim is the INSERT/UPDATE/DELETE target.
+ * EXPLAIN should claim is the INSERT/UPDATE/DELETE/MERGE target.
*
* Note that rowMarks and epqParam are presumed to be valid for all the
* table(s); they can't contain any info that varies across tables.
* is abused to signify references to columns of a custom scan tuple type.)
*
* ROWID_VAR is used in the planner to identify nonce variables that carry
- * row identity information during UPDATE/DELETE. This value should never
- * be seen outside the planner.
+ * row identity information during UPDATE/DELETE/MERGE. This value should
+ * never be seen outside the planner.
*
* In the parser, varnosyn and varattnosyn are either identical to
* varno/varattno, or they specify the column's position in an aliased JOIN