]> granicus.if.org Git - postgresql/blob - src/backend/parser/parse_merge.c
Improve parse representation for MERGE
[postgresql] / src / backend / parser / parse_merge.c
1 /*-------------------------------------------------------------------------
2  *
3  * parse_merge.c
4  *        handle merge-statement in parser
5  *
6  * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        src/backend/parser/parse_merge.c
12  *
13  *-------------------------------------------------------------------------
14  */
15
16 #include "postgres.h"
17
18 #include "miscadmin.h"
19
20 #include "access/sysattr.h"
21 #include "nodes/makefuncs.h"
22 #include "parser/analyze.h"
23 #include "parser/parse_collate.h"
24 #include "parser/parsetree.h"
25 #include "parser/parser.h"
26 #include "parser/parse_clause.h"
27 #include "parser/parse_cte.h"
28 #include "parser/parse_merge.h"
29 #include "parser/parse_relation.h"
30 #include "parser/parse_target.h"
31 #include "utils/rel.h"
32 #include "utils/relcache.h"
33
34 static int transformMergeJoinClause(ParseState *pstate, Node *merge,
35                                                 List **mergeSourceTargetList);
36 static void setNamespaceForMergeWhen(ParseState *pstate,
37                                                 MergeWhenClause *mergeWhenClause);
38 static void setNamespaceVisibilityForRTE(List *namespace, RangeTblEntry *rte,
39                                                          bool rel_visible,
40                                                          bool cols_visible);
41 static List *expandSourceTL(ParseState *pstate, RangeTblEntry *rte,
42                                                         int rtindex);
43
44 /*
45  *      Special handling for MERGE statement is required because we assemble
46  *      the query manually. This is similar to setTargetTable() followed
47  *      by transformFromClause() but with a few less steps.
48  *
49  *      Process the FROM clause and add items to the query's range table,
50  *      joinlist, and namespace.
51  *
52  *      A special targetlist comprising of the columns from the right-subtree of
53  *      the join is populated and returned. Note that when the JoinExpr is
54  *      setup by transformMergeStmt, the left subtree has the target result
55  *      relation and the right subtree has the source relation.
56  *
57  *      Returns the rangetable index of the target relation.
58  */
59 static int
60 transformMergeJoinClause(ParseState *pstate, Node *merge,
61                                                  List **mergeSourceTargetList)
62 {
63         RangeTblEntry *rte,
64                            *rt_rte;
65         List       *namespace;
66         int                     rtindex,
67                                 rt_rtindex;
68         Node       *n;
69         int                     mergeTarget_relation = list_length(pstate->p_rtable) + 1;
70         Var                *var;
71         TargetEntry *te;
72
73         n = transformFromClauseItem(pstate, merge,
74                                                                 &rte,
75                                                                 &rtindex,
76                                                                 &rt_rte,
77                                                                 &rt_rtindex,
78                                                                 &namespace);
79
80         pstate->p_joinlist = list_make1(n);
81
82         /*
83          * We created an internal join between the target and the source relation
84          * to carry out the MERGE actions. Normally such an unaliased join hides
85          * the joining relations, unless the column references are qualified.
86          * Also, any unqualified column references are resolved to the Join RTE, if
87          * there is a matching entry in the targetlist. But the way MERGE
88          * execution is later setup, we expect all column references to resolve to
89          * either the source or the target relation. Hence we must not add the
90          * Join RTE to the namespace.
91          *
92          * The last entry must be for the top-level Join RTE. We don't want to
93          * resolve any references to the Join RTE. So discard that.
94          *
95          * We also do not want to resolve any references from the leftside of the
96          * Join since that corresponds to the target relation. References to the
97          * columns of the target relation must be resolved from the result
98          * relation and not the one that is used in the join. So the
99          * mergeTarget_relation is marked invisible to both qualified as well as
100          * unqualified references.
101          */
102         Assert(list_length(namespace) > 1);
103         namespace = list_truncate(namespace, list_length(namespace) - 1);
104         pstate->p_namespace = list_concat(pstate->p_namespace, namespace);
105
106         setNamespaceVisibilityForRTE(pstate->p_namespace,
107                                                                  rt_fetch(mergeTarget_relation, pstate->p_rtable), false, false);
108
109         /*
110          * Expand the right relation and add its columns to the
111          * mergeSourceTargetList. Note that the right relation can either be a
112          * plain relation or a subquery or anything that can have a
113          * RangeTableEntry.
114          */
115         *mergeSourceTargetList = expandSourceTL(pstate, rt_rte, rt_rtindex);
116
117         /*
118          * Add a whole-row-Var entry to support references to "source.*".
119          */
120         var = makeWholeRowVar(rt_rte, rt_rtindex, 0, false);
121         te = makeTargetEntry((Expr *) var, list_length(*mergeSourceTargetList) + 1,
122                                                  NULL, true);
123         *mergeSourceTargetList = lappend(*mergeSourceTargetList, te);
124
125         return mergeTarget_relation;
126 }
127
128 /*
129  * Make appropriate changes to the namespace visibility while transforming
130  * individual action's quals and targetlist expressions. In particular, for
131  * INSERT actions we must only see the source relation (since INSERT action is
132  * invoked for NOT MATCHED tuples and hence there is no target tuple to deal
133  * with). On the other hand, UPDATE and DELETE actions can see both source and
134  * target relations.
135  *
136  * Also, since the internal Join node can hide the source and target
137  * relations, we must explicitly make the respective relation as visible so
138  * that columns can be referenced unqualified from these relations.
139  */
140 static void
141 setNamespaceForMergeWhen(ParseState *pstate, MergeWhenClause *mergeWhenClause)
142 {
143         RangeTblEntry *targetRelRTE,
144                            *sourceRelRTE;
145
146         /* Assume target relation is at index 1 */
147         targetRelRTE = rt_fetch(1, pstate->p_rtable);
148
149         /*
150          * Assume that the top-level join RTE is at the end. The source relation
151          * is just before that.
152          */
153         sourceRelRTE = rt_fetch(list_length(pstate->p_rtable) - 1, pstate->p_rtable);
154
155         switch (mergeWhenClause->commandType)
156         {
157                 case CMD_INSERT:
158
159                         /*
160                          * Inserts can't see target relation, but they can see source
161                          * relation.
162                          */
163                         setNamespaceVisibilityForRTE(pstate->p_namespace,
164                                                                                  targetRelRTE, false, false);
165                         setNamespaceVisibilityForRTE(pstate->p_namespace,
166                                                                                  sourceRelRTE, true, true);
167                         break;
168
169                 case CMD_UPDATE:
170                 case CMD_DELETE:
171
172                         /*
173                          * Updates and deletes can see both target and source relations.
174                          */
175                         setNamespaceVisibilityForRTE(pstate->p_namespace,
176                                                                                  targetRelRTE, true, true);
177                         setNamespaceVisibilityForRTE(pstate->p_namespace,
178                                                                                  sourceRelRTE, true, true);
179                         break;
180
181                 case CMD_NOTHING:
182                         break;
183                 default:
184                         elog(ERROR, "unknown action in MERGE WHEN clause");
185         }
186 }
187
188 /*
189  * transformMergeStmt -
190  *        transforms a MERGE statement
191  */
192 Query *
193 transformMergeStmt(ParseState *pstate, MergeStmt *stmt)
194 {
195         Query              *qry = makeNode(Query);
196         ListCell           *l;
197         AclMode                 targetPerms = ACL_NO_RIGHTS;
198         bool                    is_terminal[2];
199         JoinExpr           *joinexpr;
200         RangeTblEntry  *resultRelRTE, *mergeRelRTE;
201         List               *mergeActionList;
202
203         /* There can't be any outer WITH to worry about */
204         Assert(pstate->p_ctenamespace == NIL);
205
206         qry->commandType = CMD_MERGE;
207         qry->hasRecursive = false;
208
209         /* process the WITH clause independently of all else */
210         if (stmt->withClause)
211         {
212                 if (stmt->withClause->recursive)
213                         ereport(ERROR,
214                                         (errcode(ERRCODE_SYNTAX_ERROR),
215                                          errmsg("WITH RECURSIVE is not supported for MERGE statement")));
216
217                 qry->cteList = transformWithClause(pstate, stmt->withClause);
218                 qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
219         }
220
221         /*
222          * Check WHEN clauses for permissions and sanity
223          */
224         is_terminal[0] = false;
225         is_terminal[1] = false;
226         foreach(l, stmt->mergeWhenClauses)
227         {
228                 MergeWhenClause *mergeWhenClause = (MergeWhenClause *) lfirst(l);
229                 int             when_type = (mergeWhenClause->matched ? 0 : 1);
230
231                 /*
232                  * Collect action types so we can check Target permissions
233                  */
234                 switch (mergeWhenClause->commandType)
235                 {
236                         case CMD_INSERT:
237                                 targetPerms |= ACL_INSERT;
238                                 break;
239                         case CMD_UPDATE:
240                                 targetPerms |= ACL_UPDATE;
241                                 break;
242                         case CMD_DELETE:
243                                 targetPerms |= ACL_DELETE;
244                                 break;
245                         case CMD_NOTHING:
246                                 break;
247                         default:
248                                 elog(ERROR, "unknown action in MERGE WHEN clause");
249                 }
250
251                 /*
252                  * Check for unreachable WHEN clauses
253                  */
254                 if (mergeWhenClause->condition == NULL)
255                         is_terminal[when_type] = true;
256                 else if (is_terminal[when_type])
257                         ereport(ERROR,
258                                         (errcode(ERRCODE_SYNTAX_ERROR),
259                                          errmsg("unreachable WHEN clause specified after unconditional WHEN clause")));
260         }
261
262         /*
263          * Construct a query of the form
264          *      SELECT relation.ctid    --junk attribute
265          *                ,relation.tableoid    --junk attribute
266          *                ,source_relation.<somecols>
267          *                ,relation.<somecols>
268          *  FROM relation RIGHT JOIN source_relation
269          *  ON  join_condition; -- no WHERE clause - all conditions are applied in
270          * executor
271          *
272          * stmt->relation is the target relation, given as a RangeVar
273          * stmt->source_relation is a RangeVar or subquery
274          *
275          * We specify the join as a RIGHT JOIN as a simple way of forcing the
276          * first (larg) RTE to refer to the target table.
277          *
278          * The MERGE query's join can be tuned in some cases, see below for these
279          * special case tweaks.
280          *
281          * We set QSRC_PARSER to show query constructed in parse analysis
282          *
283          * Note that we have only one Query for a MERGE statement and the planner
284          * is called only once. That query is executed once to produce our stream
285          * of candidate change rows, so the query must contain all of the columns
286          * required by each of the targetlist or conditions for each action.
287          *
288          * As top-level statements INSERT, UPDATE and DELETE have a Query, whereas
289          * with MERGE the individual actions do not require separate planning,
290          * only different handling in the executor. See nodeModifyTable handling
291          * of commandType CMD_MERGE.
292          *
293          * A sub-query can include the Target, but otherwise the sub-query cannot
294          * reference the outermost Target table at all.
295          */
296         qry->querySource = QSRC_PARSER;
297
298         /*
299          * Setup the target table. Unlike regular UPDATE/DELETE, we don't expand
300          * inheritance for the target relation in case of MERGE.
301          *
302          * This special arrangement is required for handling partitioned tables
303          * because we perform an JOIN between the target and the source relation to
304          * identify the matching and not-matching rows. If we take the usual path
305          * of expanding the target table's inheritance and create one subplan per
306          * partition, then we we won't be able to correctly identify the matching
307          * and not-matching rows since for a given source row, there may not be a
308          * matching row in one partition, but it may exists in some other
309          * partition. So we must first append all the qualifying rows from all the
310          * partitions and then do the matching.
311          *
312          * Once a target row is returned by the underlying join, we find the
313          * correct partition and setup required state to carry out UPDATE/DELETE.
314          * All of this happens during execution.
315          */
316         qry->resultRelation = setTargetTable(pstate, stmt->relation,
317                                                                                  false, /* do not expand inheritance */
318                                                                                  true, targetPerms);
319
320         /*
321          * Create a JOIN between the target and the source relation.
322          */
323         joinexpr = makeNode(JoinExpr);
324         joinexpr->isNatural = false;
325         joinexpr->alias = NULL;
326         joinexpr->usingClause = NIL;
327         joinexpr->quals = stmt->join_condition;
328         joinexpr->larg = (Node *) stmt->relation;
329         joinexpr->rarg = (Node *) stmt->source_relation;
330
331         /*
332          * Simplify the MERGE query as much as possible
333          *
334          * These seem like things that could go into Optimizer, but they are
335          * semantic simplifications rather than optimizations, per se.
336          *
337          * If there are no INSERT actions we won't be using the non-matching
338          * candidate rows for anything, so no need for an outer join. We do still
339          * need an inner join for UPDATE and DELETE actions.
340          */
341         if (targetPerms & ACL_INSERT)
342                 joinexpr->jointype = JOIN_RIGHT;
343         else
344                 joinexpr->jointype = JOIN_INNER;
345
346         /*
347          * We use a special purpose transformation here because the normal
348          * routines don't quite work right for the MERGE case.
349          *
350          * A special mergeSourceTargetList is setup by transformMergeJoinClause().
351          * It refers to all the attributes provided by the source relation. This
352          * is later used by set_plan_refs() to fix the UPDATE/INSERT target lists
353          * to so that they can correctly fetch the attributes from the source
354          * relation.
355          *
356          * The target relation when used in the underlying join, gets a new RTE
357          * with rte->inh set to true. We remember this RTE (and later pass on to
358          * the planner and executor) for two main reasons:
359          *
360          * 1. If we ever need to run EvalPlanQual while performing MERGE, we must
361          * make the modified tuple available to the underlying join query, which is
362          * using a different RTE from the resultRelation RTE.
363          *
364          * 2. rewriteTargetListMerge() requires the RTE of the underlying join in
365          * order to add junk CTID and TABLEOID attributes.
366          */
367         qry->mergeTarget_relation = transformMergeJoinClause(pstate, (Node *) joinexpr,
368                                                                                                                  &qry->mergeSourceTargetList);
369
370         /*
371          * The target table referenced in the MERGE is looked up twice; once while
372          * setting it up as the result relation and again when it's used in the
373          * underlying the join query. In some rare situations, it may happen that
374          * these lookups return different results, for example, if a new relation
375          * with the same name gets created in a schema which is ahead in the
376          * search_path, in between the two lookups.
377          *
378          * It's a very narrow case, but nevertheless we guard against it by simply
379          * checking if the OIDs returned by the two lookups is the same. If not, we
380          * just throw an error.
381          */
382         Assert(qry->resultRelation > 0);
383         Assert(qry->mergeTarget_relation > 0);
384
385         /* Fetch both the RTEs */
386         resultRelRTE = rt_fetch(qry->resultRelation, pstate->p_rtable);
387         mergeRelRTE = rt_fetch(qry->mergeTarget_relation, pstate->p_rtable);
388
389         if (resultRelRTE->relid != mergeRelRTE->relid)
390                 ereport(ERROR,
391                                 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
392                                  errmsg("relation referenced by MERGE statement has changed")));
393
394         /*
395          * This query should just provide the source relation columns. Later, in
396          * preprocess_targetlist(), we shall also add "ctid" attribute of the
397          * target relation to ensure that the target tuple can be fetched
398          * correctly.
399          */
400         qry->targetList = qry->mergeSourceTargetList;
401
402         /* qry has no WHERE clause so absent quals are shown as NULL */
403         qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
404         qry->rtable = pstate->p_rtable;
405
406         /*
407          * XXX MERGE is unsupported in various cases
408          */
409         if (!(pstate->p_target_relation->rd_rel->relkind == RELKIND_RELATION ||
410                   pstate->p_target_relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE))
411                 ereport(ERROR,
412                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
413                                  errmsg("MERGE is not supported for this relation type")));
414
415         if (pstate->p_target_relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE &&
416                 pstate->p_target_relation->rd_rel->relhassubclass)
417                 ereport(ERROR,
418                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
419                                  errmsg("MERGE is not supported for relations with inheritance")));
420
421         if (pstate->p_target_relation->rd_rel->relhasrules)
422                 ereport(ERROR,
423                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
424                                  errmsg("MERGE is not supported for relations with rules")));
425
426         /*
427          * We now have a good query shape, so now look at the when conditions and
428          * action targetlists.
429          *
430          * Overall, the MERGE Query's targetlist is NIL.
431          *
432          * Each individual action has its own targetlist that needs separate
433          * transformation. These transforms don't do anything to the overall
434          * targetlist, since that is only used for resjunk columns.
435          *
436          * We can reference any column in Target or Source, which is OK because
437          * both of those already have RTEs. There is nothing like the EXCLUDED
438          * pseudo-relation for INSERT ON CONFLICT.
439          */
440         mergeActionList = NIL;
441         foreach(l, stmt->mergeWhenClauses)
442         {
443                 MergeWhenClause *mergeWhenClause = (MergeWhenClause *) lfirst(l);
444                 MergeAction               *action = makeNode(MergeAction);
445
446                 action->commandType = mergeWhenClause->commandType;
447                 action->matched = mergeWhenClause->matched;
448
449                 /*
450                  * Set namespace for the specific action. This must be done before
451                  * analyzing the WHEN quals and the action targetlisst.
452                  */
453                 setNamespaceForMergeWhen(pstate, mergeWhenClause);
454
455                 /*
456                  * Transform the when condition.
457                  *
458                  * Note that these quals are NOT added to the join quals; instead they
459                  * are evaluated separately during execution to decide which of the
460                  * WHEN MATCHED or WHEN NOT MATCHED actions to execute.
461                  */
462                 action->qual = transformWhereClause(pstate, mergeWhenClause->condition,
463                                                                                         EXPR_KIND_MERGE_WHEN_AND, "WHEN");
464
465                 /*
466                  * Transform target lists for each INSERT and UPDATE action stmt
467                  */
468                 switch (action->commandType)
469                 {
470                         case CMD_INSERT:
471                                 {
472                                         List       *exprList = NIL;
473                                         ListCell   *lc;
474                                         RangeTblEntry *rte;
475                                         ListCell   *icols;
476                                         ListCell   *attnos;
477                                         List       *icolumns;
478                                         List       *attrnos;
479
480                                         pstate->p_is_insert = true;
481
482                                         icolumns = checkInsertTargets(pstate,
483                                                                                                   mergeWhenClause->cols,
484                                                                                                   &attrnos);
485                                         Assert(list_length(icolumns) == list_length(attrnos));
486
487                                         action->override = mergeWhenClause->override;
488
489                                         /*
490                                          * Handle INSERT much like in transformInsertStmt
491                                          */
492                                         if (mergeWhenClause->values == NIL)
493                                         {
494                                                 /*
495                                                  * We have INSERT ... DEFAULT VALUES.  We can handle
496                                                  * this case by emitting an empty targetlist --- all
497                                                  * columns will be defaulted when the planner expands
498                                                  * the targetlist.
499                                                  */
500                                                 exprList = NIL;
501                                         }
502                                         else
503                                         {
504                                                 /*
505                                                  * Process INSERT ... VALUES with a single VALUES
506                                                  * sublist.  We treat this case separately for
507                                                  * efficiency.  The sublist is just computed directly
508                                                  * as the Query's targetlist, with no VALUES RTE.  So
509                                                  * it works just like a SELECT without any FROM.
510                                                  */
511
512                                                 /*
513                                                  * Do basic expression transformation (same as a ROW()
514                                                  * expr, but allow SetToDefault at top level)
515                                                  */
516                                                 exprList = transformExpressionList(pstate,
517                                                                                                                    mergeWhenClause->values,
518                                                                                                                    EXPR_KIND_VALUES_SINGLE,
519                                                                                                                    true);
520
521                                                 /* Prepare row for assignment to target table */
522                                                 exprList = transformInsertRow(pstate, exprList,
523                                                                                                           mergeWhenClause->cols,
524                                                                                                           icolumns, attrnos,
525                                                                                                           false);
526                                         }
527
528                                         /*
529                                          * Generate action's target list using the computed list
530                                          * of expressions. Also, mark all the target columns as
531                                          * needing insert permissions.
532                                          */
533                                         rte = pstate->p_target_rangetblentry;
534                                         icols = list_head(icolumns);
535                                         attnos = list_head(attrnos);
536                                         foreach(lc, exprList)
537                                         {
538                                                 Expr       *expr = (Expr *) lfirst(lc);
539                                                 ResTarget  *col;
540                                                 AttrNumber      attr_num;
541                                                 TargetEntry *tle;
542
543                                                 col = lfirst_node(ResTarget, icols);
544                                                 attr_num = (AttrNumber) lfirst_int(attnos);
545
546                                                 tle = makeTargetEntry(expr,
547                                                                                           attr_num,
548                                                                                           col->name,
549                                                                                           false);
550                                                 action->targetList = lappend(action->targetList, tle);
551
552                                                 rte->insertedCols = bms_add_member(rte->insertedCols,
553                                                                                                                    attr_num - FirstLowInvalidHeapAttributeNumber);
554
555                                                 icols = lnext(icols);
556                                                 attnos = lnext(attnos);
557                                         }
558                                 }
559                                 break;
560                         case CMD_UPDATE:
561                                 {
562                                         pstate->p_is_insert = false;
563                                         action->targetList = transformUpdateTargetList(pstate,
564                                                                                                                                    mergeWhenClause->targetList);
565                                 }
566                                 break;
567                         case CMD_DELETE:
568                                 break;
569
570                         case CMD_NOTHING:
571                                 action->targetList = NIL;
572                                 break;
573                         default:
574                                 elog(ERROR, "unknown action in MERGE WHEN clause");
575                 }
576
577                 mergeActionList = lappend(mergeActionList, action);
578         }
579
580         qry->mergeActionList = mergeActionList;
581
582         /* XXX maybe later */
583         qry->returningList = NULL;
584
585         qry->hasTargetSRFs = false;
586         qry->hasSubLinks = pstate->p_hasSubLinks;
587
588         assign_query_collations(pstate, qry);
589
590         return qry;
591 }
592
593 static void
594 setNamespaceVisibilityForRTE(List *namespace, RangeTblEntry *rte,
595                                                          bool rel_visible,
596                                                          bool cols_visible)
597 {
598         ListCell   *lc;
599
600         foreach(lc, namespace)
601         {
602                 ParseNamespaceItem *nsitem = (ParseNamespaceItem *) lfirst(lc);
603
604                 if (nsitem->p_rte == rte)
605                 {
606                         nsitem->p_rel_visible = rel_visible;
607                         nsitem->p_cols_visible = cols_visible;
608                         break;
609                 }
610         }
611
612 }
613
614 /*
615  * Expand the source relation to include all attributes of this RTE.
616  *
617  * This function is very similar to expandRelAttrs except that we don't mark
618  * columns for SELECT privileges. That will be decided later when we transform
619  * the action targetlists and the WHEN quals for actual references to the
620  * source relation.
621  */
622 static List *
623 expandSourceTL(ParseState *pstate, RangeTblEntry *rte, int rtindex)
624 {
625         List       *names,
626                            *vars;
627         ListCell   *name,
628                            *var;
629         List       *te_list = NIL;
630
631         expandRTE(rte, rtindex, 0, -1, false, &names, &vars);
632
633         /*
634          * Require read access to the table.
635          */
636         rte->requiredPerms |= ACL_SELECT;
637
638         forboth(name, names, var, vars)
639         {
640                 char       *label = strVal(lfirst(name));
641                 Var                *varnode = (Var *) lfirst(var);
642                 TargetEntry *te;
643
644                 te = makeTargetEntry((Expr *) varnode,
645                                                          (AttrNumber) pstate->p_next_resno++,
646                                                          label,
647                                                          false);
648                 te_list = lappend(te_list, te);
649         }
650
651         Assert(name == NULL && var == NULL);    /* lists not the same length? */
652
653         return te_list;
654 }