Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Update some comments that should've covered MERGE
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Mon, 24 Oct 2022 10:52:43 +0000 (12:52 +0200)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Mon, 24 Oct 2022 10:52:43 +0000 (12:52 +0200)
Oversight in 7103ebb7aae8.  Backpatch to 15.

Author: Richard Guo <guofenglinux@gmail.com>
Discussion: https://postgr.es/m/CAMbWs48gnDjZXq3-b56dVpQCNUJ5hD9kdtWN4QFwKCEapspNsA@mail.gmail.com

14 files changed:
src/backend/optimizer/path/indxpath.c
src/backend/optimizer/plan/planmain.c
src/backend/optimizer/plan/planner.c
src/backend/optimizer/util/appendinfo.c
src/backend/optimizer/util/inherit.c
src/backend/optimizer/util/pathnode.c
src/backend/optimizer/util/relnode.c
src/backend/parser/parse_clause.c
src/backend/parser/parse_expr.c
src/backend/parser/parse_merge.c
src/include/nodes/parsenodes.h
src/include/nodes/pathnodes.h
src/include/nodes/plannodes.h
src/include/nodes/primnodes.h

index 0ef70ad7f1193787b1979566d75ce6c7bf2c2d75..b8000da56d95400da6b512d6efdef47c6ca98916 100644 (file)
@@ -3378,12 +3378,13 @@ check_index_predicates(PlannerInfo *root, RelOptInfo *rel)
     * 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);
index c92ddd27ed10c592b12c907f1cbc16f42637b4e9..5a1d00662fcffea6cab291e9cb65218b3f438973 100644 (file)
@@ -264,7 +264,7 @@ query_planner(PlannerInfo *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
     * appendrels.
     */
index 468105d91ea71dc195aae1ed12ab3a2044128ca2..453a598cad48a601a7d95b4a4a49f2f587f7ef1d 100644 (file)
@@ -1747,7 +1747,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
 
            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;
@@ -1874,7 +1874,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
            }
            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);
index 9d4bb4702700c6e36d2013b5600c0661e530d1c5..38f51b6607b3638a92e3c400b006561a41639ad4 100644 (file)
@@ -748,7 +748,7 @@ find_appinfos_by_relids(PlannerInfo *root, Relids relids, int *nappinfos)
 
 /*
  * 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"
@@ -927,8 +927,8 @@ add_row_identity_columns(PlannerInfo *root, Index rtindex,
  * 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.
index 7e134822f36d122c57cd7ead1faf36d9e4671735..6dbffe121a59488e245cd27ba107a0c09b2be4ba 100644 (file)
@@ -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
-    * 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.
     */
index 2de5b0c8363f7014cfebf842a77a171e1aa43f8c..0762eb232e4034703e47ac66562868b6ae1bb39c 100644 (file)
@@ -3613,7 +3613,8 @@ create_lockrows_path(PlannerInfo *root, RelOptInfo *rel,
 
 /*
  * 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
index 520409f4ba0f9c207e75104def027ec8b520b295..3c75fd56f22593e9b5ebbf09a0c0ad694fb89f9a 100644 (file)
@@ -999,7 +999,7 @@ build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel,
 
        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);
 
index 05df373697b104bc053b601e29f954ae70551d3e..d821969a7d657162aa1c4e0084cf92a40ad670d4 100644 (file)
@@ -153,7 +153,7 @@ transformFromClause(ParseState *pstate, List *frmList)
 
 /*
  * 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.
@@ -163,7 +163,9 @@ transformFromClause(ParseState *pstate, List *frmList)
  *
  *   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.)
index 1c3680793975de690a16cdb256ac9900a98902aa..312d2c7ebaf40a0ab4f618557440c4544112305a 100644 (file)
@@ -1689,8 +1689,8 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
 
    /*
     * 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)
index bb9d76306b74f382bfe7c7cf1fe0b8e00499b572..7913523b1c6ab33a4502639277eb6e52479e1868 100644 (file)
@@ -163,7 +163,11 @@ transformMergeStmt(ParseState *pstate, MergeStmt *stmt)
                     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);
index 3e835b8c4657f2ac3ad313f5ae67f3f22a3b8d41..1e7280340b4b6cbfa3eef08c14601caf4e6ac566 100644 (file)
@@ -1031,8 +1031,8 @@ typedef struct RangeTblEntry
     *
     * 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
index 8556b2ffe72ed6a092c3d5c81dd026703c2befb2..540de8a4a7a60fc912309e6e9b4e0580dcd696aa 100644 (file)
@@ -268,11 +268,11 @@ struct PlannerInfo
 
    /*
     * 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.
     */
    Relids      all_result_relids;  /* set of all result relids */
    Relids      leaf_result_relids; /* set of all leaf relids */
@@ -2361,10 +2361,10 @@ typedef struct 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
- * 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.
index 0ea9a22dfb72282b59a02869704090e5bb405066..493a2a9e4a5ea98c6f1f61ad50a70219753481bb 100644 (file)
@@ -66,7 +66,7 @@ typedef struct PlannedStmt
 
    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 */
@@ -209,7 +209,7 @@ typedef struct ProjectSet
  * 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.
index 439e4b4a9db83ee622171a9af247cfed78379e33..3d48dbb4bd9a4781aedd034a6dd812760cb2152d 100644 (file)
@@ -159,8 +159,8 @@ typedef struct Expr
  * 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