mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-08-20 11:33:28 +02:00
Update some comments that should've covered MERGE
Oversight in 7103ebb7aa
. Backpatch to 15.
Author: Richard Guo <guofenglinux@gmail.com>
Discussion: https://postgr.es/m/CAMbWs48gnDjZXq3-b56dVpQCNUJ5hD9kdtWN4QFwKCEapspNsA@mail.gmail.com
This commit is contained in:
parent
4a6de748d3
commit
fb2a83b2b7
@ -3378,12 +3378,13 @@ check_index_predicates(PlannerInfo *root, RelOptInfo *rel)
|
|||||||
* Normally we remove quals that are implied by a partial index's
|
* Normally we remove quals that are implied by a partial index's
|
||||||
* predicate from indrestrictinfo, indicating that they need not be
|
* predicate from indrestrictinfo, indicating that they need not be
|
||||||
* checked explicitly by an indexscan plan using this index. However, if
|
* checked explicitly by an indexscan plan using this index. However, if
|
||||||
* the rel is a target relation of UPDATE/DELETE/SELECT FOR UPDATE, we
|
* the rel is a target relation of UPDATE/DELETE/MERGE/SELECT FOR UPDATE,
|
||||||
* cannot remove such quals from the plan, because they need to be in the
|
* we cannot remove such quals from the plan, because they need to be in
|
||||||
* plan so that they will be properly rechecked by EvalPlanQual testing.
|
* the plan so that they will be properly rechecked by EvalPlanQual
|
||||||
* Some day we might want to remove such quals from the main plan anyway
|
* testing. Some day we might want to remove such quals from the main
|
||||||
* and pass them through to EvalPlanQual via a side channel; but for now,
|
* plan anyway and pass them through to EvalPlanQual via a side channel;
|
||||||
* we just don't remove implied quals at all for target relations.
|
* 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) ||
|
is_target_rel = (bms_is_member(rel->relid, root->all_result_relids) ||
|
||||||
get_plan_rowmark(root->rowMarks, rel->relid) != NULL);
|
get_plan_rowmark(root->rowMarks, rel->relid) != NULL);
|
||||||
|
@ -264,7 +264,7 @@ query_planner(PlannerInfo *root,
|
|||||||
add_other_rels_to_query(root);
|
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
|
* relations. This can't be done till we've finished expansion of
|
||||||
* appendrels.
|
* appendrels.
|
||||||
*/
|
*/
|
||||||
|
@ -1747,7 +1747,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
|
|||||||
|
|
||||||
if (bms_membership(root->all_result_relids) == BMS_MULTIPLE)
|
if (bms_membership(root->all_result_relids) == BMS_MULTIPLE)
|
||||||
{
|
{
|
||||||
/* Inherited UPDATE/DELETE */
|
/* Inherited UPDATE/DELETE/MERGE */
|
||||||
RelOptInfo *top_result_rel = find_base_rel(root,
|
RelOptInfo *top_result_rel = find_base_rel(root,
|
||||||
parse->resultRelation);
|
parse->resultRelation);
|
||||||
int resultRelation = -1;
|
int resultRelation = -1;
|
||||||
@ -1874,7 +1874,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Single-relation INSERT/UPDATE/DELETE. */
|
/* Single-relation INSERT/UPDATE/DELETE/MERGE. */
|
||||||
resultRelations = list_make1_int(parse->resultRelation);
|
resultRelations = list_make1_int(parse->resultRelation);
|
||||||
if (parse->commandType == CMD_UPDATE)
|
if (parse->commandType == CMD_UPDATE)
|
||||||
updateColnosLists = list_make1(root->update_colnos);
|
updateColnosLists = list_make1(root->update_colnos);
|
||||||
|
@ -748,7 +748,7 @@ find_appinfos_by_relids(PlannerInfo *root, Relids relids, int *nappinfos)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* add_row_identity_var
|
* 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
|
* The Var must be equal(), aside from varno, to any other row-identity
|
||||||
* column with the same rowid_name. Thus, for example, "wholerow"
|
* column with the same rowid_name. Thus, for example, "wholerow"
|
||||||
@ -927,8 +927,8 @@ add_row_identity_columns(PlannerInfo *root, Index rtindex,
|
|||||||
* distribute_row_identity_vars
|
* distribute_row_identity_vars
|
||||||
*
|
*
|
||||||
* After we have finished identifying all the row identity columns
|
* After we have finished identifying all the row identity columns
|
||||||
* needed by an inherited UPDATE/DELETE query, make sure that these
|
* needed by an inherited UPDATE/DELETE/MERGE query, make sure that
|
||||||
* columns will be generated by all the target relations.
|
* these columns will be generated by all the target relations.
|
||||||
*
|
*
|
||||||
* This is more or less like what build_base_rel_tlists() does,
|
* 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.
|
* except that it would not understand what to do with ROWID_VAR Vars.
|
||||||
|
@ -609,7 +609,7 @@ expand_single_inheritance_child(PlannerInfo *root, RangeTblEntry *parentrte,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* If we are creating a child of the query target relation (only possible
|
* 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
|
* leaf_result_relids if appropriate, and make sure that we generate
|
||||||
* required row-identity data.
|
* required row-identity data.
|
||||||
*/
|
*/
|
||||||
|
@ -3613,7 +3613,8 @@ create_lockrows_path(PlannerInfo *root, RelOptInfo *rel,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* create_modifytable_path
|
* 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
|
* 'rel' is the parent relation associated with the result
|
||||||
* 'subpath' is a Path producing source data
|
* 'subpath' is a Path producing source data
|
||||||
|
@ -999,7 +999,7 @@ build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel,
|
|||||||
|
|
||||||
if (var->varno == ROWID_VAR)
|
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 *)
|
RowIdentityVarInfo *ridinfo = (RowIdentityVarInfo *)
|
||||||
list_nth(root->row_identity_vars, var->varattno - 1);
|
list_nth(root->row_identity_vars, var->varattno - 1);
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ transformFromClause(ParseState *pstate, List *frmList)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* setTargetTable
|
* 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.
|
* and make the special links to it in the ParseState.
|
||||||
*
|
*
|
||||||
* We also open the target relation and acquire a write lock on it.
|
* We also open the target relation and acquire a write lock on it.
|
||||||
@ -163,7 +163,9 @@ transformFromClause(ParseState *pstate, List *frmList)
|
|||||||
*
|
*
|
||||||
* If alsoSource is true, add the target to the query's joinlist and
|
* 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;
|
* 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
|
* 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
|
* to check for namespace conflict; we assume that the namespace was
|
||||||
* initially empty in these cases.)
|
* initially empty in these cases.)
|
||||||
|
@ -1689,8 +1689,8 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Check to see if the sublink is in an invalid place within the query. We
|
* 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
|
* allow sublinks everywhere in SELECT/INSERT/UPDATE/DELETE/MERGE, but
|
||||||
* not in utility statements.
|
* generally not in utility statements.
|
||||||
*/
|
*/
|
||||||
err = NULL;
|
err = NULL;
|
||||||
switch (pstate->p_expr_kind)
|
switch (pstate->p_expr_kind)
|
||||||
|
@ -163,7 +163,11 @@ transformMergeStmt(ParseState *pstate, MergeStmt *stmt)
|
|||||||
errmsg("unreachable WHEN clause specified after unconditional WHEN clause")));
|
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,
|
qry->resultRelation = setTargetTable(pstate, stmt->relation,
|
||||||
stmt->relation->inh,
|
stmt->relation->inh,
|
||||||
false, targetPerms);
|
false, targetPerms);
|
||||||
|
@ -1031,8 +1031,8 @@ typedef struct RangeTblEntry
|
|||||||
*
|
*
|
||||||
* rellockmode is really LOCKMODE, but it's declared int to avoid having
|
* rellockmode is really LOCKMODE, but it's declared int to avoid having
|
||||||
* to include lock-related headers here. It must be RowExclusiveLock if
|
* to include lock-related headers here. It must be RowExclusiveLock if
|
||||||
* the RTE is an INSERT/UPDATE/DELETE target, else RowShareLock if the RTE
|
* the RTE is an INSERT/UPDATE/DELETE/MERGE target, else RowShareLock if
|
||||||
* is a SELECT FOR UPDATE/FOR SHARE target, else AccessShareLock.
|
* 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
|
* Note: in some cases, rule expansion may result in RTEs that are marked
|
||||||
* with RowExclusiveLock even though they are not the target of the
|
* with RowExclusiveLock even though they are not the target of the
|
||||||
|
@ -268,11 +268,11 @@ struct PlannerInfo
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* all_result_relids is empty for SELECT, otherwise it contains at least
|
* all_result_relids is empty for SELECT, otherwise it contains at least
|
||||||
* parse->resultRelation. For UPDATE/DELETE across an inheritance or
|
* parse->resultRelation. For UPDATE/DELETE/MERGE across an inheritance
|
||||||
* partitioning tree, the result rel's child relids are added. When using
|
* or partitioning tree, the result rel's child relids are added. When
|
||||||
* multi-level partitioning, intermediate partitioned rels are included.
|
* using multi-level partitioning, intermediate partitioned rels are
|
||||||
* leaf_result_relids is similar except that only actual result tables,
|
* included. leaf_result_relids is similar except that only actual result
|
||||||
* not partitioned tables, are included in it.
|
* tables, not partitioned tables, are included in it.
|
||||||
*/
|
*/
|
||||||
Relids all_result_relids; /* set of all result relids */
|
Relids all_result_relids; /* set of all result relids */
|
||||||
Relids leaf_result_relids; /* set of all leaf relids */
|
Relids leaf_result_relids; /* set of all leaf relids */
|
||||||
@ -2361,10 +2361,10 @@ typedef struct AppendRelInfo
|
|||||||
} AppendRelInfo;
|
} 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
|
* In partitioned UPDATE/DELETE/MERGE it's important for child partitions to
|
||||||
* row-identity columns whenever possible, so as not to chew up too many
|
* 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
|
* targetlist columns. We use these structs to track which identity columns
|
||||||
* have been requested. In the finished plan, each of these will give rise
|
* 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.
|
* to one resjunk entry in the targetlist of the ModifyTable's subplan node.
|
||||||
|
@ -66,7 +66,7 @@ typedef struct PlannedStmt
|
|||||||
|
|
||||||
List *rtable; /* list of RangeTblEntry nodes */
|
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 *resultRelations; /* integer list of RT indexes, or NIL */
|
||||||
|
|
||||||
List *appendRelations; /* list of AppendRelInfo nodes */
|
List *appendRelations; /* list of AppendRelInfo nodes */
|
||||||
@ -209,7 +209,7 @@ typedef struct ProjectSet
|
|||||||
* nominalRelation and rootRelation contain the RT index of the partition
|
* nominalRelation and rootRelation contain the RT index of the partition
|
||||||
* root, which is not otherwise mentioned in the plan. Otherwise rootRelation
|
* 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
|
* 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
|
* 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.
|
* table(s); they can't contain any info that varies across tables.
|
||||||
|
@ -159,8 +159,8 @@ typedef struct Expr
|
|||||||
* is abused to signify references to columns of a custom scan tuple type.)
|
* 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
|
* ROWID_VAR is used in the planner to identify nonce variables that carry
|
||||||
* row identity information during UPDATE/DELETE. This value should never
|
* row identity information during UPDATE/DELETE/MERGE. This value should
|
||||||
* be seen outside the planner.
|
* never be seen outside the planner.
|
||||||
*
|
*
|
||||||
* In the parser, varnosyn and varattnosyn are either identical to
|
* In the parser, varnosyn and varattnosyn are either identical to
|
||||||
* varno/varattno, or they specify the column's position in an aliased JOIN
|
* varno/varattno, or they specify the column's position in an aliased JOIN
|
||||||
|
Loading…
Reference in New Issue
Block a user