]> granicus.if.org Git - postgresql/blob - src/backend/optimizer/prep/prepunion.c
Fix PARAM_EXEC assignment mechanism to be safe in the presence of WITH.
[postgresql] / src / backend / optimizer / prep / prepunion.c
1 /*-------------------------------------------------------------------------
2  *
3  * prepunion.c
4  *        Routines to plan set-operation queries.  The filename is a leftover
5  *        from a time when only UNIONs were implemented.
6  *
7  * There are two code paths in the planner for set-operation queries.
8  * If a subquery consists entirely of simple UNION ALL operations, it
9  * is converted into an "append relation".      Otherwise, it is handled
10  * by the general code in this module (plan_set_operations and its
11  * subroutines).  There is some support code here for the append-relation
12  * case, but most of the heavy lifting for that is done elsewhere,
13  * notably in prepjointree.c and allpaths.c.
14  *
15  * There is also some code here to support planning of queries that use
16  * inheritance (SELECT FROM foo*).      Inheritance trees are converted into
17  * append relations, and thenceforth share code with the UNION ALL case.
18  *
19  *
20  * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
21  * Portions Copyright (c) 1994, Regents of the University of California
22  *
23  *
24  * IDENTIFICATION
25  *        src/backend/optimizer/prep/prepunion.c
26  *
27  *-------------------------------------------------------------------------
28  */
29 #include "postgres.h"
30
31 #include <limits.h>
32
33 #include "access/heapam.h"
34 #include "access/htup_details.h"
35 #include "access/sysattr.h"
36 #include "catalog/pg_inherits_fn.h"
37 #include "catalog/pg_type.h"
38 #include "miscadmin.h"
39 #include "nodes/makefuncs.h"
40 #include "nodes/nodeFuncs.h"
41 #include "optimizer/cost.h"
42 #include "optimizer/pathnode.h"
43 #include "optimizer/planmain.h"
44 #include "optimizer/planner.h"
45 #include "optimizer/prep.h"
46 #include "optimizer/tlist.h"
47 #include "parser/parse_coerce.h"
48 #include "parser/parsetree.h"
49 #include "utils/lsyscache.h"
50 #include "utils/rel.h"
51 #include "utils/selfuncs.h"
52
53
54 typedef struct
55 {
56         PlannerInfo *root;
57         AppendRelInfo *appinfo;
58 } adjust_appendrel_attrs_context;
59
60 static Plan *recurse_set_operations(Node *setOp, PlannerInfo *root,
61                                            double tuple_fraction,
62                                            List *colTypes, List *colCollations,
63                                            bool junkOK,
64                                            int flag, List *refnames_tlist,
65                                            List **sortClauses, double *pNumGroups);
66 static Plan *generate_recursion_plan(SetOperationStmt *setOp,
67                                                 PlannerInfo *root, double tuple_fraction,
68                                                 List *refnames_tlist,
69                                                 List **sortClauses);
70 static Plan *generate_union_plan(SetOperationStmt *op, PlannerInfo *root,
71                                         double tuple_fraction,
72                                         List *refnames_tlist,
73                                         List **sortClauses, double *pNumGroups);
74 static Plan *generate_nonunion_plan(SetOperationStmt *op, PlannerInfo *root,
75                                            double tuple_fraction,
76                                            List *refnames_tlist,
77                                            List **sortClauses, double *pNumGroups);
78 static List *recurse_union_children(Node *setOp, PlannerInfo *root,
79                                            double tuple_fraction,
80                                            SetOperationStmt *top_union,
81                                            List *refnames_tlist);
82 static Plan *make_union_unique(SetOperationStmt *op, Plan *plan,
83                                   PlannerInfo *root, double tuple_fraction,
84                                   List **sortClauses);
85 static bool choose_hashed_setop(PlannerInfo *root, List *groupClauses,
86                                         Plan *input_plan,
87                                         double dNumGroups, double dNumOutputRows,
88                                         double tuple_fraction,
89                                         const char *construct);
90 static List *generate_setop_tlist(List *colTypes, List *colCollations,
91                                          int flag,
92                                          Index varno,
93                                          bool hack_constants,
94                                          List *input_tlist,
95                                          List *refnames_tlist);
96 static List *generate_append_tlist(List *colTypes, List *colCollations,
97                                           bool flag,
98                                           List *input_plans,
99                                           List *refnames_tlist);
100 static List *generate_setop_grouplist(SetOperationStmt *op, List *targetlist);
101 static void expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte,
102                                                  Index rti);
103 static void make_inh_translation_list(Relation oldrelation,
104                                                   Relation newrelation,
105                                                   Index newvarno,
106                                                   List **translated_vars);
107 static Bitmapset *translate_col_privs(const Bitmapset *parent_privs,
108                                         List *translated_vars);
109 static Node *adjust_appendrel_attrs_mutator(Node *node,
110                                                            adjust_appendrel_attrs_context *context);
111 static Relids adjust_relid_set(Relids relids, Index oldrelid, Index newrelid);
112 static List *adjust_inherited_tlist(List *tlist,
113                                            AppendRelInfo *context);
114
115
116 /*
117  * plan_set_operations
118  *
119  *        Plans the queries for a tree of set operations (UNION/INTERSECT/EXCEPT)
120  *
121  * This routine only deals with the setOperations tree of the given query.
122  * Any top-level ORDER BY requested in root->parse->sortClause will be added
123  * when we return to grouping_planner.
124  *
125  * tuple_fraction is the fraction of tuples we expect will be retrieved.
126  * tuple_fraction is interpreted as for grouping_planner(); in particular,
127  * zero means "all the tuples will be fetched".  Any LIMIT present at the
128  * top level has already been factored into tuple_fraction.
129  *
130  * *sortClauses is an output argument: it is set to a list of SortGroupClauses
131  * representing the result ordering of the topmost set operation.  (This will
132  * be NIL if the output isn't ordered.)
133  */
134 Plan *
135 plan_set_operations(PlannerInfo *root, double tuple_fraction,
136                                         List **sortClauses)
137 {
138         Query      *parse = root->parse;
139         SetOperationStmt *topop = (SetOperationStmt *) parse->setOperations;
140         Node       *node;
141         RangeTblEntry *leftmostRTE;
142         Query      *leftmostQuery;
143
144         Assert(topop && IsA(topop, SetOperationStmt));
145
146         /* check for unsupported stuff */
147         Assert(parse->jointree->fromlist == NIL);
148         Assert(parse->jointree->quals == NULL);
149         Assert(parse->groupClause == NIL);
150         Assert(parse->havingQual == NULL);
151         Assert(parse->windowClause == NIL);
152         Assert(parse->distinctClause == NIL);
153
154         /*
155          * We'll need to build RelOptInfos for each of the leaf subqueries, which
156          * are RTE_SUBQUERY rangetable entries in this Query.  Prepare the index
157          * arrays for that.
158          */
159         setup_simple_rel_arrays(root);
160
161         /*
162          * Find the leftmost component Query.  We need to use its column names for
163          * all generated tlists (else SELECT INTO won't work right).
164          */
165         node = topop->larg;
166         while (node && IsA(node, SetOperationStmt))
167                 node = ((SetOperationStmt *) node)->larg;
168         Assert(node && IsA(node, RangeTblRef));
169         leftmostRTE = root->simple_rte_array[((RangeTblRef *) node)->rtindex];
170         leftmostQuery = leftmostRTE->subquery;
171         Assert(leftmostQuery != NULL);
172
173         /*
174          * If the topmost node is a recursive union, it needs special processing.
175          */
176         if (root->hasRecursion)
177                 return generate_recursion_plan(topop, root, tuple_fraction,
178                                                                            leftmostQuery->targetList,
179                                                                            sortClauses);
180
181         /*
182          * Recurse on setOperations tree to generate plans for set ops. The final
183          * output plan should have just the column types shown as the output from
184          * the top-level node, plus possibly resjunk working columns (we can rely
185          * on upper-level nodes to deal with that).
186          */
187         return recurse_set_operations((Node *) topop, root, tuple_fraction,
188                                                                   topop->colTypes, topop->colCollations,
189                                                                   true, -1,
190                                                                   leftmostQuery->targetList,
191                                                                   sortClauses, NULL);
192 }
193
194 /*
195  * recurse_set_operations
196  *        Recursively handle one step in a tree of set operations
197  *
198  * tuple_fraction: fraction of tuples we expect to retrieve from node
199  * colTypes: OID list of set-op's result column datatypes
200  * colCollations: OID list of set-op's result column collations
201  * junkOK: if true, child resjunk columns may be left in the result
202  * flag: if >= 0, add a resjunk output column indicating value of flag
203  * refnames_tlist: targetlist to take column names from
204  *
205  * Returns a plan for the subtree, as well as these output parameters:
206  * *sortClauses: receives list of SortGroupClauses for result plan, if any
207  * *pNumGroups: if not NULL, we estimate the number of distinct groups
208  *              in the result, and store it there
209  *
210  * We don't have to care about typmods here: the only allowed difference
211  * between set-op input and output typmods is input is a specific typmod
212  * and output is -1, and that does not require a coercion.
213  */
214 static Plan *
215 recurse_set_operations(Node *setOp, PlannerInfo *root,
216                                            double tuple_fraction,
217                                            List *colTypes, List *colCollations,
218                                            bool junkOK,
219                                            int flag, List *refnames_tlist,
220                                            List **sortClauses, double *pNumGroups)
221 {
222         if (IsA(setOp, RangeTblRef))
223         {
224                 RangeTblRef *rtr = (RangeTblRef *) setOp;
225                 RangeTblEntry *rte = root->simple_rte_array[rtr->rtindex];
226                 Query      *subquery = rte->subquery;
227                 RelOptInfo *rel;
228                 PlannerInfo *subroot;
229                 Plan       *subplan,
230                                    *plan;
231
232                 Assert(subquery != NULL);
233
234                 /*
235                  * We need to build a RelOptInfo for each leaf subquery.  This isn't
236                  * used for anything here, but it carries the subroot data structures
237                  * forward to setrefs.c processing.
238                  */
239                 rel = build_simple_rel(root, rtr->rtindex, RELOPT_BASEREL);
240
241                 /* plan_params should not be in use in current query level */
242                 Assert(root->plan_params == NIL);
243
244                 /*
245                  * Generate plan for primitive subquery
246                  */
247                 subplan = subquery_planner(root->glob, subquery,
248                                                                    root,
249                                                                    false, tuple_fraction,
250                                                                    &subroot);
251
252                 /* Save subroot and subplan in RelOptInfo for setrefs.c */
253                 rel->subplan = subplan;
254                 rel->subroot = subroot;
255
256                 /*
257                  * It should not be possible for the primitive query to contain any
258                  * cross-references to other primitive queries in the setop tree.
259                  */
260                 if (root->plan_params)
261                         elog(ERROR, "unexpected outer reference in set operation subquery");
262
263                 /*
264                  * Estimate number of groups if caller wants it.  If the subquery used
265                  * grouping or aggregation, its output is probably mostly unique
266                  * anyway; otherwise do statistical estimation.
267                  */
268                 if (pNumGroups)
269                 {
270                         if (subquery->groupClause || subquery->distinctClause ||
271                                 subroot->hasHavingQual || subquery->hasAggs)
272                                 *pNumGroups = subplan->plan_rows;
273                         else
274                                 *pNumGroups = estimate_num_groups(subroot,
275                                                                 get_tlist_exprs(subquery->targetList, false),
276                                                                                                   subplan->plan_rows);
277                 }
278
279                 /*
280                  * Add a SubqueryScan with the caller-requested targetlist
281                  */
282                 plan = (Plan *)
283                         make_subqueryscan(generate_setop_tlist(colTypes, colCollations,
284                                                                                                    flag,
285                                                                                                    rtr->rtindex,
286                                                                                                    true,
287                                                                                                    subplan->targetlist,
288                                                                                                    refnames_tlist),
289                                                           NIL,
290                                                           rtr->rtindex,
291                                                           subplan);
292
293                 /*
294                  * We don't bother to determine the subquery's output ordering since
295                  * it won't be reflected in the set-op result anyhow.
296                  */
297                 *sortClauses = NIL;
298
299                 return plan;
300         }
301         else if (IsA(setOp, SetOperationStmt))
302         {
303                 SetOperationStmt *op = (SetOperationStmt *) setOp;
304                 Plan       *plan;
305
306                 /* UNIONs are much different from INTERSECT/EXCEPT */
307                 if (op->op == SETOP_UNION)
308                         plan = generate_union_plan(op, root, tuple_fraction,
309                                                                            refnames_tlist,
310                                                                            sortClauses, pNumGroups);
311                 else
312                         plan = generate_nonunion_plan(op, root, tuple_fraction,
313                                                                                   refnames_tlist,
314                                                                                   sortClauses, pNumGroups);
315
316                 /*
317                  * If necessary, add a Result node to project the caller-requested
318                  * output columns.
319                  *
320                  * XXX you don't really want to know about this: setrefs.c will apply
321                  * fix_upper_expr() to the Result node's tlist. This would fail if the
322                  * Vars generated by generate_setop_tlist() were not exactly equal()
323                  * to the corresponding tlist entries of the subplan. However, since
324                  * the subplan was generated by generate_union_plan() or
325                  * generate_nonunion_plan(), and hence its tlist was generated by
326                  * generate_append_tlist(), this will work.  We just tell
327                  * generate_setop_tlist() to use varno 0.
328                  */
329                 if (flag >= 0 ||
330                         !tlist_same_datatypes(plan->targetlist, colTypes, junkOK) ||
331                         !tlist_same_collations(plan->targetlist, colCollations, junkOK))
332                 {
333                         plan = (Plan *)
334                                 make_result(root,
335                                                         generate_setop_tlist(colTypes, colCollations,
336                                                                                                  flag,
337                                                                                                  0,
338                                                                                                  false,
339                                                                                                  plan->targetlist,
340                                                                                                  refnames_tlist),
341                                                         NULL,
342                                                         plan);
343                 }
344                 return plan;
345         }
346         else
347         {
348                 elog(ERROR, "unrecognized node type: %d",
349                          (int) nodeTag(setOp));
350                 return NULL;                    /* keep compiler quiet */
351         }
352 }
353
354 /*
355  * Generate plan for a recursive UNION node
356  */
357 static Plan *
358 generate_recursion_plan(SetOperationStmt *setOp, PlannerInfo *root,
359                                                 double tuple_fraction,
360                                                 List *refnames_tlist,
361                                                 List **sortClauses)
362 {
363         Plan       *plan;
364         Plan       *lplan;
365         Plan       *rplan;
366         List       *tlist;
367         List       *groupList;
368         long            numGroups;
369
370         /* Parser should have rejected other cases */
371         if (setOp->op != SETOP_UNION)
372                 elog(ERROR, "only UNION queries can be recursive");
373         /* Worktable ID should be assigned */
374         Assert(root->wt_param_id >= 0);
375
376         /*
377          * Unlike a regular UNION node, process the left and right inputs
378          * separately without any intention of combining them into one Append.
379          */
380         lplan = recurse_set_operations(setOp->larg, root, tuple_fraction,
381                                                                    setOp->colTypes, setOp->colCollations,
382                                                                    false, -1,
383                                                                    refnames_tlist, sortClauses, NULL);
384         /* The right plan will want to look at the left one ... */
385         root->non_recursive_plan = lplan;
386         rplan = recurse_set_operations(setOp->rarg, root, tuple_fraction,
387                                                                    setOp->colTypes, setOp->colCollations,
388                                                                    false, -1,
389                                                                    refnames_tlist, sortClauses, NULL);
390         root->non_recursive_plan = NULL;
391
392         /*
393          * Generate tlist for RecursiveUnion plan node --- same as in Append cases
394          */
395         tlist = generate_append_tlist(setOp->colTypes, setOp->colCollations, false,
396                                                                   list_make2(lplan, rplan),
397                                                                   refnames_tlist);
398
399         /*
400          * If UNION, identify the grouping operators
401          */
402         if (setOp->all)
403         {
404                 groupList = NIL;
405                 numGroups = 0;
406         }
407         else
408         {
409                 double          dNumGroups;
410
411                 /* Identify the grouping semantics */
412                 groupList = generate_setop_grouplist(setOp, tlist);
413
414                 /* We only support hashing here */
415                 if (!grouping_is_hashable(groupList))
416                         ereport(ERROR,
417                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
418                                          errmsg("could not implement recursive UNION"),
419                                          errdetail("All column datatypes must be hashable.")));
420
421                 /*
422                  * For the moment, take the number of distinct groups as equal to the
423                  * total input size, ie, the worst case.
424                  */
425                 dNumGroups = lplan->plan_rows + rplan->plan_rows * 10;
426
427                 /* Also convert to long int --- but 'ware overflow! */
428                 numGroups = (long) Min(dNumGroups, (double) LONG_MAX);
429         }
430
431         /*
432          * And make the plan node.
433          */
434         plan = (Plan *) make_recursive_union(tlist, lplan, rplan,
435                                                                                  root->wt_param_id,
436                                                                                  groupList, numGroups);
437
438         *sortClauses = NIL;                     /* RecursiveUnion result is always unsorted */
439
440         return plan;
441 }
442
443 /*
444  * Generate plan for a UNION or UNION ALL node
445  */
446 static Plan *
447 generate_union_plan(SetOperationStmt *op, PlannerInfo *root,
448                                         double tuple_fraction,
449                                         List *refnames_tlist,
450                                         List **sortClauses, double *pNumGroups)
451 {
452         List       *planlist;
453         List       *tlist;
454         Plan       *plan;
455
456         /*
457          * If plain UNION, tell children to fetch all tuples.
458          *
459          * Note: in UNION ALL, we pass the top-level tuple_fraction unmodified to
460          * each arm of the UNION ALL.  One could make a case for reducing the
461          * tuple fraction for later arms (discounting by the expected size of the
462          * earlier arms' results) but it seems not worth the trouble. The normal
463          * case where tuple_fraction isn't already zero is a LIMIT at top level,
464          * and passing it down as-is is usually enough to get the desired result
465          * of preferring fast-start plans.
466          */
467         if (!op->all)
468                 tuple_fraction = 0.0;
469
470         /*
471          * If any of my children are identical UNION nodes (same op, all-flag, and
472          * colTypes) then they can be merged into this node so that we generate
473          * only one Append and unique-ification for the lot.  Recurse to find such
474          * nodes and compute their children's plans.
475          */
476         planlist = list_concat(recurse_union_children(op->larg, root,
477                                                                                                   tuple_fraction,
478                                                                                                   op, refnames_tlist),
479                                                    recurse_union_children(op->rarg, root,
480                                                                                                   tuple_fraction,
481                                                                                                   op, refnames_tlist));
482
483         /*
484          * Generate tlist for Append plan node.
485          *
486          * The tlist for an Append plan isn't important as far as the Append is
487          * concerned, but we must make it look real anyway for the benefit of the
488          * next plan level up.
489          */
490         tlist = generate_append_tlist(op->colTypes, op->colCollations, false,
491                                                                   planlist, refnames_tlist);
492
493         /*
494          * Append the child results together.
495          */
496         plan = (Plan *) make_append(planlist, tlist);
497
498         /*
499          * For UNION ALL, we just need the Append plan.  For UNION, need to add
500          * node(s) to remove duplicates.
501          */
502         if (op->all)
503                 *sortClauses = NIL;             /* result of UNION ALL is always unsorted */
504         else
505                 plan = make_union_unique(op, plan, root, tuple_fraction, sortClauses);
506
507         /*
508          * Estimate number of groups if caller wants it.  For now we just assume
509          * the output is unique --- this is certainly true for the UNION case, and
510          * we want worst-case estimates anyway.
511          */
512         if (pNumGroups)
513                 *pNumGroups = plan->plan_rows;
514
515         return plan;
516 }
517
518 /*
519  * Generate plan for an INTERSECT, INTERSECT ALL, EXCEPT, or EXCEPT ALL node
520  */
521 static Plan *
522 generate_nonunion_plan(SetOperationStmt *op, PlannerInfo *root,
523                                            double tuple_fraction,
524                                            List *refnames_tlist,
525                                            List **sortClauses, double *pNumGroups)
526 {
527         Plan       *lplan,
528                            *rplan,
529                            *plan;
530         List       *tlist,
531                            *groupList,
532                            *planlist,
533                            *child_sortclauses;
534         double          dLeftGroups,
535                                 dRightGroups,
536                                 dNumGroups,
537                                 dNumOutputRows;
538         long            numGroups;
539         bool            use_hash;
540         SetOpCmd        cmd;
541         int                     firstFlag;
542
543         /* Recurse on children, ensuring their outputs are marked */
544         lplan = recurse_set_operations(op->larg, root,
545                                                                    0.0 /* all tuples needed */ ,
546                                                                    op->colTypes, op->colCollations,
547                                                                    false, 0,
548                                                                    refnames_tlist,
549                                                                    &child_sortclauses, &dLeftGroups);
550         rplan = recurse_set_operations(op->rarg, root,
551                                                                    0.0 /* all tuples needed */ ,
552                                                                    op->colTypes, op->colCollations,
553                                                                    false, 1,
554                                                                    refnames_tlist,
555                                                                    &child_sortclauses, &dRightGroups);
556
557         /*
558          * For EXCEPT, we must put the left input first.  For INTERSECT, either
559          * order should give the same results, and we prefer to put the smaller
560          * input first in order to minimize the size of the hash table in the
561          * hashing case.  "Smaller" means the one with the fewer groups.
562          */
563         if (op->op == SETOP_EXCEPT || dLeftGroups <= dRightGroups)
564         {
565                 planlist = list_make2(lplan, rplan);
566                 firstFlag = 0;
567         }
568         else
569         {
570                 planlist = list_make2(rplan, lplan);
571                 firstFlag = 1;
572         }
573
574         /*
575          * Generate tlist for Append plan node.
576          *
577          * The tlist for an Append plan isn't important as far as the Append is
578          * concerned, but we must make it look real anyway for the benefit of the
579          * next plan level up.  In fact, it has to be real enough that the flag
580          * column is shown as a variable not a constant, else setrefs.c will get
581          * confused.
582          */
583         tlist = generate_append_tlist(op->colTypes, op->colCollations, true,
584                                                                   planlist, refnames_tlist);
585
586         /*
587          * Append the child results together.
588          */
589         plan = (Plan *) make_append(planlist, tlist);
590
591         /* Identify the grouping semantics */
592         groupList = generate_setop_grouplist(op, tlist);
593
594         /* punt if nothing to group on (can this happen?) */
595         if (groupList == NIL)
596         {
597                 *sortClauses = NIL;
598                 return plan;
599         }
600
601         /*
602          * Estimate number of distinct groups that we'll need hashtable entries
603          * for; this is the size of the left-hand input for EXCEPT, or the smaller
604          * input for INTERSECT.  Also estimate the number of eventual output rows.
605          * In non-ALL cases, we estimate each group produces one output row; in
606          * ALL cases use the relevant relation size.  These are worst-case
607          * estimates, of course, but we need to be conservative.
608          */
609         if (op->op == SETOP_EXCEPT)
610         {
611                 dNumGroups = dLeftGroups;
612                 dNumOutputRows = op->all ? lplan->plan_rows : dNumGroups;
613         }
614         else
615         {
616                 dNumGroups = Min(dLeftGroups, dRightGroups);
617                 dNumOutputRows = op->all ? Min(lplan->plan_rows, rplan->plan_rows) : dNumGroups;
618         }
619
620         /* Also convert to long int --- but 'ware overflow! */
621         numGroups = (long) Min(dNumGroups, (double) LONG_MAX);
622
623         /*
624          * Decide whether to hash or sort, and add a sort node if needed.
625          */
626         use_hash = choose_hashed_setop(root, groupList, plan,
627                                                                    dNumGroups, dNumOutputRows, tuple_fraction,
628                                            (op->op == SETOP_INTERSECT) ? "INTERSECT" : "EXCEPT");
629
630         if (!use_hash)
631                 plan = (Plan *) make_sort_from_sortclauses(root, groupList, plan);
632
633         /*
634          * Finally, add a SetOp plan node to generate the correct output.
635          */
636         switch (op->op)
637         {
638                 case SETOP_INTERSECT:
639                         cmd = op->all ? SETOPCMD_INTERSECT_ALL : SETOPCMD_INTERSECT;
640                         break;
641                 case SETOP_EXCEPT:
642                         cmd = op->all ? SETOPCMD_EXCEPT_ALL : SETOPCMD_EXCEPT;
643                         break;
644                 default:
645                         elog(ERROR, "unrecognized set op: %d", (int) op->op);
646                         cmd = SETOPCMD_INTERSECT;       /* keep compiler quiet */
647                         break;
648         }
649         plan = (Plan *) make_setop(cmd, use_hash ? SETOP_HASHED : SETOP_SORTED,
650                                                            plan, groupList,
651                                                            list_length(op->colTypes) + 1,
652                                                            use_hash ? firstFlag : -1,
653                                                            numGroups, dNumOutputRows);
654
655         /* Result is sorted only if we're not hashing */
656         *sortClauses = use_hash ? NIL : groupList;
657
658         if (pNumGroups)
659                 *pNumGroups = dNumGroups;
660
661         return plan;
662 }
663
664 /*
665  * Pull up children of a UNION node that are identically-propertied UNIONs.
666  *
667  * NOTE: we can also pull a UNION ALL up into a UNION, since the distinct
668  * output rows will be lost anyway.
669  *
670  * NOTE: currently, we ignore collations while determining if a child has
671  * the same properties.  This is semantically sound only so long as all
672  * collations have the same notion of equality.  It is valid from an
673  * implementation standpoint because we don't care about the ordering of
674  * a UNION child's result: UNION ALL results are always unordered, and
675  * generate_union_plan will force a fresh sort if the top level is a UNION.
676  */
677 static List *
678 recurse_union_children(Node *setOp, PlannerInfo *root,
679                                            double tuple_fraction,
680                                            SetOperationStmt *top_union,
681                                            List *refnames_tlist)
682 {
683         List       *child_sortclauses;
684
685         if (IsA(setOp, SetOperationStmt))
686         {
687                 SetOperationStmt *op = (SetOperationStmt *) setOp;
688
689                 if (op->op == top_union->op &&
690                         (op->all == top_union->all || op->all) &&
691                         equal(op->colTypes, top_union->colTypes))
692                 {
693                         /* Same UNION, so fold children into parent's subplan list */
694                         return list_concat(recurse_union_children(op->larg, root,
695                                                                                                           tuple_fraction,
696                                                                                                           top_union,
697                                                                                                           refnames_tlist),
698                                                            recurse_union_children(op->rarg, root,
699                                                                                                           tuple_fraction,
700                                                                                                           top_union,
701                                                                                                           refnames_tlist));
702                 }
703         }
704
705         /*
706          * Not same, so plan this child separately.
707          *
708          * Note we disallow any resjunk columns in child results.  This is
709          * necessary since the Append node that implements the union won't do any
710          * projection, and upper levels will get confused if some of our output
711          * tuples have junk and some don't.  This case only arises when we have an
712          * EXCEPT or INTERSECT as child, else there won't be resjunk anyway.
713          */
714         return list_make1(recurse_set_operations(setOp, root,
715                                                                                          tuple_fraction,
716                                                                                          top_union->colTypes,
717                                                                                          top_union->colCollations,
718                                                                                          false, -1,
719                                                                                          refnames_tlist,
720                                                                                          &child_sortclauses, NULL));
721 }
722
723 /*
724  * Add nodes to the given plan tree to unique-ify the result of a UNION.
725  */
726 static Plan *
727 make_union_unique(SetOperationStmt *op, Plan *plan,
728                                   PlannerInfo *root, double tuple_fraction,
729                                   List **sortClauses)
730 {
731         List       *groupList;
732         double          dNumGroups;
733         long            numGroups;
734
735         /* Identify the grouping semantics */
736         groupList = generate_setop_grouplist(op, plan->targetlist);
737
738         /* punt if nothing to group on (can this happen?) */
739         if (groupList == NIL)
740         {
741                 *sortClauses = NIL;
742                 return plan;
743         }
744
745         /*
746          * XXX for the moment, take the number of distinct groups as equal to the
747          * total input size, ie, the worst case.  This is too conservative, but we
748          * don't want to risk having the hashtable overrun memory; also, it's not
749          * clear how to get a decent estimate of the true size.  One should note
750          * as well the propensity of novices to write UNION rather than UNION ALL
751          * even when they don't expect any duplicates...
752          */
753         dNumGroups = plan->plan_rows;
754
755         /* Also convert to long int --- but 'ware overflow! */
756         numGroups = (long) Min(dNumGroups, (double) LONG_MAX);
757
758         /* Decide whether to hash or sort */
759         if (choose_hashed_setop(root, groupList, plan,
760                                                         dNumGroups, dNumGroups, tuple_fraction,
761                                                         "UNION"))
762         {
763                 /* Hashed aggregate plan --- no sort needed */
764                 plan = (Plan *) make_agg(root,
765                                                                  plan->targetlist,
766                                                                  NIL,
767                                                                  AGG_HASHED,
768                                                                  NULL,
769                                                                  list_length(groupList),
770                                                                  extract_grouping_cols(groupList,
771                                                                                                            plan->targetlist),
772                                                                  extract_grouping_ops(groupList),
773                                                                  numGroups,
774                                                                  plan);
775                 /* Hashed aggregation produces randomly-ordered results */
776                 *sortClauses = NIL;
777         }
778         else
779         {
780                 /* Sort and Unique */
781                 plan = (Plan *) make_sort_from_sortclauses(root, groupList, plan);
782                 plan = (Plan *) make_unique(plan, groupList);
783                 plan->plan_rows = dNumGroups;
784                 /* We know the sort order of the result */
785                 *sortClauses = groupList;
786         }
787
788         return plan;
789 }
790
791 /*
792  * choose_hashed_setop - should we use hashing for a set operation?
793  */
794 static bool
795 choose_hashed_setop(PlannerInfo *root, List *groupClauses,
796                                         Plan *input_plan,
797                                         double dNumGroups, double dNumOutputRows,
798                                         double tuple_fraction,
799                                         const char *construct)
800 {
801         int                     numGroupCols = list_length(groupClauses);
802         bool            can_sort;
803         bool            can_hash;
804         Size            hashentrysize;
805         Path            hashed_p;
806         Path            sorted_p;
807
808         /* Check whether the operators support sorting or hashing */
809         can_sort = grouping_is_sortable(groupClauses);
810         can_hash = grouping_is_hashable(groupClauses);
811         if (can_hash && can_sort)
812         {
813                 /* we have a meaningful choice to make, continue ... */
814         }
815         else if (can_hash)
816                 return true;
817         else if (can_sort)
818                 return false;
819         else
820                 ereport(ERROR,
821                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
822                 /* translator: %s is UNION, INTERSECT, or EXCEPT */
823                                  errmsg("could not implement %s", construct),
824                                  errdetail("Some of the datatypes only support hashing, while others only support sorting.")));
825
826         /* Prefer sorting when enable_hashagg is off */
827         if (!enable_hashagg)
828                 return false;
829
830         /*
831          * Don't do it if it doesn't look like the hashtable will fit into
832          * work_mem.
833          */
834         hashentrysize = MAXALIGN(input_plan->plan_width) + MAXALIGN(sizeof(MinimalTupleData));
835
836         if (hashentrysize * dNumGroups > work_mem * 1024L)
837                 return false;
838
839         /*
840          * See if the estimated cost is no more than doing it the other way.
841          *
842          * We need to consider input_plan + hashagg versus input_plan + sort +
843          * group.  Note that the actual result plan might involve a SetOp or
844          * Unique node, not Agg or Group, but the cost estimates for Agg and Group
845          * should be close enough for our purposes here.
846          *
847          * These path variables are dummies that just hold cost fields; we don't
848          * make actual Paths for these steps.
849          */
850         cost_agg(&hashed_p, root, AGG_HASHED, NULL,
851                          numGroupCols, dNumGroups,
852                          input_plan->startup_cost, input_plan->total_cost,
853                          input_plan->plan_rows);
854
855         /*
856          * Now for the sorted case.  Note that the input is *always* unsorted,
857          * since it was made by appending unrelated sub-relations together.
858          */
859         sorted_p.startup_cost = input_plan->startup_cost;
860         sorted_p.total_cost = input_plan->total_cost;
861         /* XXX cost_sort doesn't actually look at pathkeys, so just pass NIL */
862         cost_sort(&sorted_p, root, NIL, sorted_p.total_cost,
863                           input_plan->plan_rows, input_plan->plan_width,
864                           0.0, work_mem, -1.0);
865         cost_group(&sorted_p, root, numGroupCols, dNumGroups,
866                            sorted_p.startup_cost, sorted_p.total_cost,
867                            input_plan->plan_rows);
868
869         /*
870          * Now make the decision using the top-level tuple fraction.  First we
871          * have to convert an absolute count (LIMIT) into fractional form.
872          */
873         if (tuple_fraction >= 1.0)
874                 tuple_fraction /= dNumOutputRows;
875
876         if (compare_fractional_path_costs(&hashed_p, &sorted_p,
877                                                                           tuple_fraction) < 0)
878         {
879                 /* Hashed is cheaper, so use it */
880                 return true;
881         }
882         return false;
883 }
884
885 /*
886  * Generate targetlist for a set-operation plan node
887  *
888  * colTypes: OID list of set-op's result column datatypes
889  * colCollations: OID list of set-op's result column collations
890  * flag: -1 if no flag column needed, 0 or 1 to create a const flag column
891  * varno: varno to use in generated Vars
892  * hack_constants: true to copy up constants (see comments in code)
893  * input_tlist: targetlist of this node's input node
894  * refnames_tlist: targetlist to take column names from
895  */
896 static List *
897 generate_setop_tlist(List *colTypes, List *colCollations,
898                                          int flag,
899                                          Index varno,
900                                          bool hack_constants,
901                                          List *input_tlist,
902                                          List *refnames_tlist)
903 {
904         List       *tlist = NIL;
905         int                     resno = 1;
906         ListCell   *ctlc,
907                            *cclc,
908                            *itlc,
909                            *rtlc;
910         TargetEntry *tle;
911         Node       *expr;
912
913         /* there's no forfour() so we must chase one list manually */
914         rtlc = list_head(refnames_tlist);
915         forthree(ctlc, colTypes, cclc, colCollations, itlc, input_tlist)
916         {
917                 Oid                     colType = lfirst_oid(ctlc);
918                 Oid                     colColl = lfirst_oid(cclc);
919                 TargetEntry *inputtle = (TargetEntry *) lfirst(itlc);
920                 TargetEntry *reftle = (TargetEntry *) lfirst(rtlc);
921
922                 rtlc = lnext(rtlc);
923
924                 Assert(inputtle->resno == resno);
925                 Assert(reftle->resno == resno);
926                 Assert(!inputtle->resjunk);
927                 Assert(!reftle->resjunk);
928
929                 /*
930                  * Generate columns referencing input columns and having appropriate
931                  * data types and column names.  Insert datatype coercions where
932                  * necessary.
933                  *
934                  * HACK: constants in the input's targetlist are copied up as-is
935                  * rather than being referenced as subquery outputs.  This is mainly
936                  * to ensure that when we try to coerce them to the output column's
937                  * datatype, the right things happen for UNKNOWN constants.  But do
938                  * this only at the first level of subquery-scan plans; we don't want
939                  * phony constants appearing in the output tlists of upper-level
940                  * nodes!
941                  */
942                 if (hack_constants && inputtle->expr && IsA(inputtle->expr, Const))
943                         expr = (Node *) inputtle->expr;
944                 else
945                         expr = (Node *) makeVar(varno,
946                                                                         inputtle->resno,
947                                                                         exprType((Node *) inputtle->expr),
948                                                                         exprTypmod((Node *) inputtle->expr),
949                                                                         exprCollation((Node *) inputtle->expr),
950                                                                         0);
951
952                 if (exprType(expr) != colType)
953                 {
954                         /*
955                          * Note: it's not really cool to be applying coerce_to_common_type
956                          * here; one notable point is that assign_expr_collations never
957                          * gets run on any generated nodes.  For the moment that's not a
958                          * problem because we force the correct exposed collation below.
959                          * It would likely be best to make the parser generate the correct
960                          * output tlist for every set-op to begin with, though.
961                          */
962                         expr = coerce_to_common_type(NULL,      /* no UNKNOWNs here */
963                                                                                  expr,
964                                                                                  colType,
965                                                                                  "UNION/INTERSECT/EXCEPT");
966                 }
967
968                 /*
969                  * Ensure the tlist entry's exposed collation matches the set-op. This
970                  * is necessary because plan_set_operations() reports the result
971                  * ordering as a list of SortGroupClauses, which don't carry collation
972                  * themselves but just refer to tlist entries.  If we don't show the
973                  * right collation then planner.c might do the wrong thing in
974                  * higher-level queries.
975                  *
976                  * Note we use RelabelType, not CollateExpr, since this expression
977                  * will reach the executor without any further processing.
978                  */
979                 if (exprCollation(expr) != colColl)
980                 {
981                         expr = (Node *) makeRelabelType((Expr *) expr,
982                                                                                         exprType(expr),
983                                                                                         exprTypmod(expr),
984                                                                                         colColl,
985                                                                                         COERCE_DONTCARE);
986                 }
987
988                 tle = makeTargetEntry((Expr *) expr,
989                                                           (AttrNumber) resno++,
990                                                           pstrdup(reftle->resname),
991                                                           false);
992                 tlist = lappend(tlist, tle);
993         }
994
995         if (flag >= 0)
996         {
997                 /* Add a resjunk flag column */
998                 /* flag value is the given constant */
999                 expr = (Node *) makeConst(INT4OID,
1000                                                                   -1,
1001                                                                   InvalidOid,
1002                                                                   sizeof(int32),
1003                                                                   Int32GetDatum(flag),
1004                                                                   false,
1005                                                                   true);
1006                 tle = makeTargetEntry((Expr *) expr,
1007                                                           (AttrNumber) resno++,
1008                                                           pstrdup("flag"),
1009                                                           true);
1010                 tlist = lappend(tlist, tle);
1011         }
1012
1013         return tlist;
1014 }
1015
1016 /*
1017  * Generate targetlist for a set-operation Append node
1018  *
1019  * colTypes: OID list of set-op's result column datatypes
1020  * colCollations: OID list of set-op's result column collations
1021  * flag: true to create a flag column copied up from subplans
1022  * input_plans: list of sub-plans of the Append
1023  * refnames_tlist: targetlist to take column names from
1024  *
1025  * The entries in the Append's targetlist should always be simple Vars;
1026  * we just have to make sure they have the right datatypes/typmods/collations.
1027  * The Vars are always generated with varno 0.
1028  */
1029 static List *
1030 generate_append_tlist(List *colTypes, List *colCollations,
1031                                           bool flag,
1032                                           List *input_plans,
1033                                           List *refnames_tlist)
1034 {
1035         List       *tlist = NIL;
1036         int                     resno = 1;
1037         ListCell   *curColType;
1038         ListCell   *curColCollation;
1039         ListCell   *ref_tl_item;
1040         int                     colindex;
1041         TargetEntry *tle;
1042         Node       *expr;
1043         ListCell   *planl;
1044         int32      *colTypmods;
1045
1046         /*
1047          * First extract typmods to use.
1048          *
1049          * If the inputs all agree on type and typmod of a particular column, use
1050          * that typmod; else use -1.
1051          */
1052         colTypmods = (int32 *) palloc(list_length(colTypes) * sizeof(int32));
1053
1054         foreach(planl, input_plans)
1055         {
1056                 Plan       *subplan = (Plan *) lfirst(planl);
1057                 ListCell   *subtlist;
1058
1059                 curColType = list_head(colTypes);
1060                 colindex = 0;
1061                 foreach(subtlist, subplan->targetlist)
1062                 {
1063                         TargetEntry *subtle = (TargetEntry *) lfirst(subtlist);
1064
1065                         if (subtle->resjunk)
1066                                 continue;
1067                         Assert(curColType != NULL);
1068                         if (exprType((Node *) subtle->expr) == lfirst_oid(curColType))
1069                         {
1070                                 /* If first subplan, copy the typmod; else compare */
1071                                 int32           subtypmod = exprTypmod((Node *) subtle->expr);
1072
1073                                 if (planl == list_head(input_plans))
1074                                         colTypmods[colindex] = subtypmod;
1075                                 else if (subtypmod != colTypmods[colindex])
1076                                         colTypmods[colindex] = -1;
1077                         }
1078                         else
1079                         {
1080                                 /* types disagree, so force typmod to -1 */
1081                                 colTypmods[colindex] = -1;
1082                         }
1083                         curColType = lnext(curColType);
1084                         colindex++;
1085                 }
1086                 Assert(curColType == NULL);
1087         }
1088
1089         /*
1090          * Now we can build the tlist for the Append.
1091          */
1092         colindex = 0;
1093         forthree(curColType, colTypes, curColCollation, colCollations,
1094                          ref_tl_item, refnames_tlist)
1095         {
1096                 Oid                     colType = lfirst_oid(curColType);
1097                 int32           colTypmod = colTypmods[colindex++];
1098                 Oid                     colColl = lfirst_oid(curColCollation);
1099                 TargetEntry *reftle = (TargetEntry *) lfirst(ref_tl_item);
1100
1101                 Assert(reftle->resno == resno);
1102                 Assert(!reftle->resjunk);
1103                 expr = (Node *) makeVar(0,
1104                                                                 resno,
1105                                                                 colType,
1106                                                                 colTypmod,
1107                                                                 colColl,
1108                                                                 0);
1109                 tle = makeTargetEntry((Expr *) expr,
1110                                                           (AttrNumber) resno++,
1111                                                           pstrdup(reftle->resname),
1112                                                           false);
1113                 tlist = lappend(tlist, tle);
1114         }
1115
1116         if (flag)
1117         {
1118                 /* Add a resjunk flag column */
1119                 /* flag value is shown as copied up from subplan */
1120                 expr = (Node *) makeVar(0,
1121                                                                 resno,
1122                                                                 INT4OID,
1123                                                                 -1,
1124                                                                 InvalidOid,
1125                                                                 0);
1126                 tle = makeTargetEntry((Expr *) expr,
1127                                                           (AttrNumber) resno++,
1128                                                           pstrdup("flag"),
1129                                                           true);
1130                 tlist = lappend(tlist, tle);
1131         }
1132
1133         pfree(colTypmods);
1134
1135         return tlist;
1136 }
1137
1138 /*
1139  * generate_setop_grouplist
1140  *              Build a SortGroupClause list defining the sort/grouping properties
1141  *              of the setop's output columns.
1142  *
1143  * Parse analysis already determined the properties and built a suitable
1144  * list, except that the entries do not have sortgrouprefs set because
1145  * the parser output representation doesn't include a tlist for each
1146  * setop.  So what we need to do here is copy that list and install
1147  * proper sortgrouprefs into it and into the targetlist.
1148  */
1149 static List *
1150 generate_setop_grouplist(SetOperationStmt *op, List *targetlist)
1151 {
1152         List       *grouplist = (List *) copyObject(op->groupClauses);
1153         ListCell   *lg;
1154         ListCell   *lt;
1155         Index           refno = 1;
1156
1157         lg = list_head(grouplist);
1158         foreach(lt, targetlist)
1159         {
1160                 TargetEntry *tle = (TargetEntry *) lfirst(lt);
1161                 SortGroupClause *sgc;
1162
1163                 /* tlist shouldn't have any sortgrouprefs yet */
1164                 Assert(tle->ressortgroupref == 0);
1165
1166                 if (tle->resjunk)
1167                         continue;                       /* ignore resjunk columns */
1168
1169                 /* non-resjunk columns should have grouping clauses */
1170                 Assert(lg != NULL);
1171                 sgc = (SortGroupClause *) lfirst(lg);
1172                 lg = lnext(lg);
1173                 Assert(sgc->tleSortGroupRef == 0);
1174
1175                 /* we could use assignSortGroupRef here, but seems a bit silly */
1176                 sgc->tleSortGroupRef = tle->ressortgroupref = refno++;
1177         }
1178         Assert(lg == NULL);
1179         return grouplist;
1180 }
1181
1182
1183 /*
1184  * expand_inherited_tables
1185  *              Expand each rangetable entry that represents an inheritance set
1186  *              into an "append relation".      At the conclusion of this process,
1187  *              the "inh" flag is set in all and only those RTEs that are append
1188  *              relation parents.
1189  */
1190 void
1191 expand_inherited_tables(PlannerInfo *root)
1192 {
1193         Index           nrtes;
1194         Index           rti;
1195         ListCell   *rl;
1196
1197         /*
1198          * expand_inherited_rtentry may add RTEs to parse->rtable; there is no
1199          * need to scan them since they can't have inh=true.  So just scan as far
1200          * as the original end of the rtable list.
1201          */
1202         nrtes = list_length(root->parse->rtable);
1203         rl = list_head(root->parse->rtable);
1204         for (rti = 1; rti <= nrtes; rti++)
1205         {
1206                 RangeTblEntry *rte = (RangeTblEntry *) lfirst(rl);
1207
1208                 expand_inherited_rtentry(root, rte, rti);
1209                 rl = lnext(rl);
1210         }
1211 }
1212
1213 /*
1214  * expand_inherited_rtentry
1215  *              Check whether a rangetable entry represents an inheritance set.
1216  *              If so, add entries for all the child tables to the query's
1217  *              rangetable, and build AppendRelInfo nodes for all the child tables
1218  *              and add them to root->append_rel_list.  If not, clear the entry's
1219  *              "inh" flag to prevent later code from looking for AppendRelInfos.
1220  *
1221  * Note that the original RTE is considered to represent the whole
1222  * inheritance set.  The first of the generated RTEs is an RTE for the same
1223  * table, but with inh = false, to represent the parent table in its role
1224  * as a simple member of the inheritance set.
1225  *
1226  * A childless table is never considered to be an inheritance set; therefore
1227  * a parent RTE must always have at least two associated AppendRelInfos.
1228  */
1229 static void
1230 expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
1231 {
1232         Query      *parse = root->parse;
1233         Oid                     parentOID;
1234         PlanRowMark *oldrc;
1235         Relation        oldrelation;
1236         LOCKMODE        lockmode;
1237         List       *inhOIDs;
1238         List       *appinfos;
1239         ListCell   *l;
1240
1241         /* Does RT entry allow inheritance? */
1242         if (!rte->inh)
1243                 return;
1244         /* Ignore any already-expanded UNION ALL nodes */
1245         if (rte->rtekind != RTE_RELATION)
1246         {
1247                 Assert(rte->rtekind == RTE_SUBQUERY);
1248                 return;
1249         }
1250         /* Fast path for common case of childless table */
1251         parentOID = rte->relid;
1252         if (!has_subclass(parentOID))
1253         {
1254                 /* Clear flag before returning */
1255                 rte->inh = false;
1256                 return;
1257         }
1258
1259         /*
1260          * The rewriter should already have obtained an appropriate lock on each
1261          * relation named in the query.  However, for each child relation we add
1262          * to the query, we must obtain an appropriate lock, because this will be
1263          * the first use of those relations in the parse/rewrite/plan pipeline.
1264          *
1265          * If the parent relation is the query's result relation, then we need
1266          * RowExclusiveLock.  Otherwise, if it's accessed FOR UPDATE/SHARE, we
1267          * need RowShareLock; otherwise AccessShareLock.  We can't just grab
1268          * AccessShareLock because then the executor would be trying to upgrade
1269          * the lock, leading to possible deadlocks.  (This code should match the
1270          * parser and rewriter.)
1271          */
1272         oldrc = get_plan_rowmark(root->rowMarks, rti);
1273         if (rti == parse->resultRelation)
1274                 lockmode = RowExclusiveLock;
1275         else if (oldrc && RowMarkRequiresRowShareLock(oldrc->markType))
1276                 lockmode = RowShareLock;
1277         else
1278                 lockmode = AccessShareLock;
1279
1280         /* Scan for all members of inheritance set, acquire needed locks */
1281         inhOIDs = find_all_inheritors(parentOID, lockmode, NULL);
1282
1283         /*
1284          * Check that there's at least one descendant, else treat as no-child
1285          * case.  This could happen despite above has_subclass() check, if table
1286          * once had a child but no longer does.
1287          */
1288         if (list_length(inhOIDs) < 2)
1289         {
1290                 /* Clear flag before returning */
1291                 rte->inh = false;
1292                 return;
1293         }
1294
1295         /*
1296          * If parent relation is selected FOR UPDATE/SHARE, we need to mark its
1297          * PlanRowMark as isParent = true, and generate a new PlanRowMark for each
1298          * child.
1299          */
1300         if (oldrc)
1301                 oldrc->isParent = true;
1302
1303         /*
1304          * Must open the parent relation to examine its tupdesc.  We need not lock
1305          * it; we assume the rewriter already did.
1306          */
1307         oldrelation = heap_open(parentOID, NoLock);
1308
1309         /* Scan the inheritance set and expand it */
1310         appinfos = NIL;
1311         foreach(l, inhOIDs)
1312         {
1313                 Oid                     childOID = lfirst_oid(l);
1314                 Relation        newrelation;
1315                 RangeTblEntry *childrte;
1316                 Index           childRTindex;
1317                 AppendRelInfo *appinfo;
1318
1319                 /* Open rel if needed; we already have required locks */
1320                 if (childOID != parentOID)
1321                         newrelation = heap_open(childOID, NoLock);
1322                 else
1323                         newrelation = oldrelation;
1324
1325                 /*
1326                  * It is possible that the parent table has children that are temp
1327                  * tables of other backends.  We cannot safely access such tables
1328                  * (because of buffering issues), and the best thing to do seems to be
1329                  * to silently ignore them.
1330                  */
1331                 if (childOID != parentOID && RELATION_IS_OTHER_TEMP(newrelation))
1332                 {
1333                         heap_close(newrelation, lockmode);
1334                         continue;
1335                 }
1336
1337                 /*
1338                  * Build an RTE for the child, and attach to query's rangetable list.
1339                  * We copy most fields of the parent's RTE, but replace relation OID,
1340                  * and set inh = false.  Also, set requiredPerms to zero since all
1341                  * required permissions checks are done on the original RTE.
1342                  */
1343                 childrte = copyObject(rte);
1344                 childrte->relid = childOID;
1345                 childrte->inh = false;
1346                 childrte->requiredPerms = 0;
1347                 parse->rtable = lappend(parse->rtable, childrte);
1348                 childRTindex = list_length(parse->rtable);
1349
1350                 /*
1351                  * Build an AppendRelInfo for this parent and child.
1352                  */
1353                 appinfo = makeNode(AppendRelInfo);
1354                 appinfo->parent_relid = rti;
1355                 appinfo->child_relid = childRTindex;
1356                 appinfo->parent_reltype = oldrelation->rd_rel->reltype;
1357                 appinfo->child_reltype = newrelation->rd_rel->reltype;
1358                 make_inh_translation_list(oldrelation, newrelation, childRTindex,
1359                                                                   &appinfo->translated_vars);
1360                 appinfo->parent_reloid = parentOID;
1361                 appinfos = lappend(appinfos, appinfo);
1362
1363                 /*
1364                  * Translate the column permissions bitmaps to the child's attnums (we
1365                  * have to build the translated_vars list before we can do this). But
1366                  * if this is the parent table, leave copyObject's result alone.
1367                  *
1368                  * Note: we need to do this even though the executor won't run any
1369                  * permissions checks on the child RTE.  The modifiedCols bitmap may
1370                  * be examined for trigger-firing purposes.
1371                  */
1372                 if (childOID != parentOID)
1373                 {
1374                         childrte->selectedCols = translate_col_privs(rte->selectedCols,
1375                                                                                                    appinfo->translated_vars);
1376                         childrte->modifiedCols = translate_col_privs(rte->modifiedCols,
1377                                                                                                    appinfo->translated_vars);
1378                 }
1379
1380                 /*
1381                  * Build a PlanRowMark if parent is marked FOR UPDATE/SHARE.
1382                  */
1383                 if (oldrc)
1384                 {
1385                         PlanRowMark *newrc = makeNode(PlanRowMark);
1386
1387                         newrc->rti = childRTindex;
1388                         newrc->prti = rti;
1389                         newrc->rowmarkId = oldrc->rowmarkId;
1390                         newrc->markType = oldrc->markType;
1391                         newrc->noWait = oldrc->noWait;
1392                         newrc->isParent = false;
1393
1394                         root->rowMarks = lappend(root->rowMarks, newrc);
1395                 }
1396
1397                 /* Close child relations, but keep locks */
1398                 if (childOID != parentOID)
1399                         heap_close(newrelation, NoLock);
1400         }
1401
1402         heap_close(oldrelation, NoLock);
1403
1404         /*
1405          * If all the children were temp tables, pretend it's a non-inheritance
1406          * situation.  The duplicate RTE we added for the parent table is
1407          * harmless, so we don't bother to get rid of it.
1408          */
1409         if (list_length(appinfos) < 2)
1410         {
1411                 /* Clear flag before returning */
1412                 rte->inh = false;
1413                 return;
1414         }
1415
1416         /* Otherwise, OK to add to root->append_rel_list */
1417         root->append_rel_list = list_concat(root->append_rel_list, appinfos);
1418 }
1419
1420 /*
1421  * make_inh_translation_list
1422  *        Build the list of translations from parent Vars to child Vars for
1423  *        an inheritance child.
1424  *
1425  * For paranoia's sake, we match type/collation as well as attribute name.
1426  */
1427 static void
1428 make_inh_translation_list(Relation oldrelation, Relation newrelation,
1429                                                   Index newvarno,
1430                                                   List **translated_vars)
1431 {
1432         List       *vars = NIL;
1433         TupleDesc       old_tupdesc = RelationGetDescr(oldrelation);
1434         TupleDesc       new_tupdesc = RelationGetDescr(newrelation);
1435         int                     oldnatts = old_tupdesc->natts;
1436         int                     newnatts = new_tupdesc->natts;
1437         int                     old_attno;
1438
1439         for (old_attno = 0; old_attno < oldnatts; old_attno++)
1440         {
1441                 Form_pg_attribute att;
1442                 char       *attname;
1443                 Oid                     atttypid;
1444                 int32           atttypmod;
1445                 Oid                     attcollation;
1446                 int                     new_attno;
1447
1448                 att = old_tupdesc->attrs[old_attno];
1449                 if (att->attisdropped)
1450                 {
1451                         /* Just put NULL into this list entry */
1452                         vars = lappend(vars, NULL);
1453                         continue;
1454                 }
1455                 attname = NameStr(att->attname);
1456                 atttypid = att->atttypid;
1457                 atttypmod = att->atttypmod;
1458                 attcollation = att->attcollation;
1459
1460                 /*
1461                  * When we are generating the "translation list" for the parent table
1462                  * of an inheritance set, no need to search for matches.
1463                  */
1464                 if (oldrelation == newrelation)
1465                 {
1466                         vars = lappend(vars, makeVar(newvarno,
1467                                                                                  (AttrNumber) (old_attno + 1),
1468                                                                                  atttypid,
1469                                                                                  atttypmod,
1470                                                                                  attcollation,
1471                                                                                  0));
1472                         continue;
1473                 }
1474
1475                 /*
1476                  * Otherwise we have to search for the matching column by name.
1477                  * There's no guarantee it'll have the same column position, because
1478                  * of cases like ALTER TABLE ADD COLUMN and multiple inheritance.
1479                  * However, in simple cases it will be the same column number, so try
1480                  * that before we go groveling through all the columns.
1481                  *
1482                  * Note: the test for (att = ...) != NULL cannot fail, it's just a
1483                  * notational device to include the assignment into the if-clause.
1484                  */
1485                 if (old_attno < newnatts &&
1486                         (att = new_tupdesc->attrs[old_attno]) != NULL &&
1487                         !att->attisdropped && att->attinhcount != 0 &&
1488                         strcmp(attname, NameStr(att->attname)) == 0)
1489                         new_attno = old_attno;
1490                 else
1491                 {
1492                         for (new_attno = 0; new_attno < newnatts; new_attno++)
1493                         {
1494                                 att = new_tupdesc->attrs[new_attno];
1495                                 if (!att->attisdropped && att->attinhcount != 0 &&
1496                                         strcmp(attname, NameStr(att->attname)) == 0)
1497                                         break;
1498                         }
1499                         if (new_attno >= newnatts)
1500                                 elog(ERROR, "could not find inherited attribute \"%s\" of relation \"%s\"",
1501                                          attname, RelationGetRelationName(newrelation));
1502                 }
1503
1504                 /* Found it, check type and collation match */
1505                 if (atttypid != att->atttypid || atttypmod != att->atttypmod)
1506                         elog(ERROR, "attribute \"%s\" of relation \"%s\" does not match parent's type",
1507                                  attname, RelationGetRelationName(newrelation));
1508                 if (attcollation != att->attcollation)
1509                         elog(ERROR, "attribute \"%s\" of relation \"%s\" does not match parent's collation",
1510                                  attname, RelationGetRelationName(newrelation));
1511
1512                 vars = lappend(vars, makeVar(newvarno,
1513                                                                          (AttrNumber) (new_attno + 1),
1514                                                                          atttypid,
1515                                                                          atttypmod,
1516                                                                          attcollation,
1517                                                                          0));
1518         }
1519
1520         *translated_vars = vars;
1521 }
1522
1523 /*
1524  * translate_col_privs
1525  *        Translate a bitmapset representing per-column privileges from the
1526  *        parent rel's attribute numbering to the child's.
1527  *
1528  * The only surprise here is that we don't translate a parent whole-row
1529  * reference into a child whole-row reference.  That would mean requiring
1530  * permissions on all child columns, which is overly strict, since the
1531  * query is really only going to reference the inherited columns.  Instead
1532  * we set the per-column bits for all inherited columns.
1533  */
1534 static Bitmapset *
1535 translate_col_privs(const Bitmapset *parent_privs,
1536                                         List *translated_vars)
1537 {
1538         Bitmapset  *child_privs = NULL;
1539         bool            whole_row;
1540         int                     attno;
1541         ListCell   *lc;
1542
1543         /* System attributes have the same numbers in all tables */
1544         for (attno = FirstLowInvalidHeapAttributeNumber + 1; attno < 0; attno++)
1545         {
1546                 if (bms_is_member(attno - FirstLowInvalidHeapAttributeNumber,
1547                                                   parent_privs))
1548                         child_privs = bms_add_member(child_privs,
1549                                                                  attno - FirstLowInvalidHeapAttributeNumber);
1550         }
1551
1552         /* Check if parent has whole-row reference */
1553         whole_row = bms_is_member(InvalidAttrNumber - FirstLowInvalidHeapAttributeNumber,
1554                                                           parent_privs);
1555
1556         /* And now translate the regular user attributes, using the vars list */
1557         attno = InvalidAttrNumber;
1558         foreach(lc, translated_vars)
1559         {
1560                 Var                *var = (Var *) lfirst(lc);
1561
1562                 attno++;
1563                 if (var == NULL)                /* ignore dropped columns */
1564                         continue;
1565                 Assert(IsA(var, Var));
1566                 if (whole_row ||
1567                         bms_is_member(attno - FirstLowInvalidHeapAttributeNumber,
1568                                                   parent_privs))
1569                         child_privs = bms_add_member(child_privs,
1570                                                  var->varattno - FirstLowInvalidHeapAttributeNumber);
1571         }
1572
1573         return child_privs;
1574 }
1575
1576 /*
1577  * adjust_appendrel_attrs
1578  *        Copy the specified query or expression and translate Vars referring
1579  *        to the parent rel of the specified AppendRelInfo to refer to the
1580  *        child rel instead.  We also update rtindexes appearing outside Vars,
1581  *        such as resultRelation and jointree relids.
1582  *
1583  * Note: this is only applied after conversion of sublinks to subplans,
1584  * so we don't need to cope with recursion into sub-queries.
1585  *
1586  * Note: this is not hugely different from what pullup_replace_vars() does;
1587  * maybe we should try to fold the two routines together.
1588  */
1589 Node *
1590 adjust_appendrel_attrs(PlannerInfo *root, Node *node, AppendRelInfo *appinfo)
1591 {
1592         Node       *result;
1593         adjust_appendrel_attrs_context context;
1594
1595         context.root = root;
1596         context.appinfo = appinfo;
1597
1598         /*
1599          * Must be prepared to start with a Query or a bare expression tree.
1600          */
1601         if (node && IsA(node, Query))
1602         {
1603                 Query      *newnode;
1604
1605                 newnode = query_tree_mutator((Query *) node,
1606                                                                          adjust_appendrel_attrs_mutator,
1607                                                                          (void *) &context,
1608                                                                          QTW_IGNORE_RC_SUBQUERIES);
1609                 if (newnode->resultRelation == appinfo->parent_relid)
1610                 {
1611                         newnode->resultRelation = appinfo->child_relid;
1612                         /* Fix tlist resnos too, if it's inherited UPDATE */
1613                         if (newnode->commandType == CMD_UPDATE)
1614                                 newnode->targetList =
1615                                         adjust_inherited_tlist(newnode->targetList,
1616                                                                                    appinfo);
1617                 }
1618                 result = (Node *) newnode;
1619         }
1620         else
1621                 result = adjust_appendrel_attrs_mutator(node, &context);
1622
1623         return result;
1624 }
1625
1626 static Node *
1627 adjust_appendrel_attrs_mutator(Node *node,
1628                                                            adjust_appendrel_attrs_context *context)
1629 {
1630         AppendRelInfo *appinfo = context->appinfo;
1631
1632         if (node == NULL)
1633                 return NULL;
1634         if (IsA(node, Var))
1635         {
1636                 Var                *var = (Var *) copyObject(node);
1637
1638                 if (var->varlevelsup == 0 &&
1639                         var->varno == appinfo->parent_relid)
1640                 {
1641                         var->varno = appinfo->child_relid;
1642                         var->varnoold = appinfo->child_relid;
1643                         if (var->varattno > 0)
1644                         {
1645                                 Node       *newnode;
1646
1647                                 if (var->varattno > list_length(appinfo->translated_vars))
1648                                         elog(ERROR, "attribute %d of relation \"%s\" does not exist",
1649                                                  var->varattno, get_rel_name(appinfo->parent_reloid));
1650                                 newnode = copyObject(list_nth(appinfo->translated_vars,
1651                                                                                           var->varattno - 1));
1652                                 if (newnode == NULL)
1653                                         elog(ERROR, "attribute %d of relation \"%s\" does not exist",
1654                                                  var->varattno, get_rel_name(appinfo->parent_reloid));
1655                                 return newnode;
1656                         }
1657                         else if (var->varattno == 0)
1658                         {
1659                                 /*
1660                                  * Whole-row Var: if we are dealing with named rowtypes, we
1661                                  * can use a whole-row Var for the child table plus a coercion
1662                                  * step to convert the tuple layout to the parent's rowtype.
1663                                  * Otherwise we have to generate a RowExpr.
1664                                  */
1665                                 if (OidIsValid(appinfo->child_reltype))
1666                                 {
1667                                         Assert(var->vartype == appinfo->parent_reltype);
1668                                         if (appinfo->parent_reltype != appinfo->child_reltype)
1669                                         {
1670                                                 ConvertRowtypeExpr *r = makeNode(ConvertRowtypeExpr);
1671
1672                                                 r->arg = (Expr *) var;
1673                                                 r->resulttype = appinfo->parent_reltype;
1674                                                 r->convertformat = COERCE_IMPLICIT_CAST;
1675                                                 r->location = -1;
1676                                                 /* Make sure the Var node has the right type ID, too */
1677                                                 var->vartype = appinfo->child_reltype;
1678                                                 return (Node *) r;
1679                                         }
1680                                 }
1681                                 else
1682                                 {
1683                                         /*
1684                                          * Build a RowExpr containing the translated variables.
1685                                          *
1686                                          * In practice var->vartype will always be RECORDOID here,
1687                                          * so we need to come up with some suitable column names.
1688                                          * We use the parent RTE's column names.
1689                                          *
1690                                          * Note: we can't get here for inheritance cases, so there
1691                                          * is no need to worry that translated_vars might contain
1692                                          * some dummy NULLs.
1693                                          */
1694                                         RowExpr    *rowexpr;
1695                                         List       *fields;
1696                                         RangeTblEntry *rte;
1697
1698                                         rte = rt_fetch(appinfo->parent_relid,
1699                                                                    context->root->parse->rtable);
1700                                         fields = (List *) copyObject(appinfo->translated_vars);
1701                                         rowexpr = makeNode(RowExpr);
1702                                         rowexpr->args = fields;
1703                                         rowexpr->row_typeid = var->vartype;
1704                                         rowexpr->row_format = COERCE_IMPLICIT_CAST;
1705                                         rowexpr->colnames = copyObject(rte->eref->colnames);
1706                                         rowexpr->location = -1;
1707
1708                                         return (Node *) rowexpr;
1709                                 }
1710                         }
1711                         /* system attributes don't need any other translation */
1712                 }
1713                 return (Node *) var;
1714         }
1715         if (IsA(node, CurrentOfExpr))
1716         {
1717                 CurrentOfExpr *cexpr = (CurrentOfExpr *) copyObject(node);
1718
1719                 if (cexpr->cvarno == appinfo->parent_relid)
1720                         cexpr->cvarno = appinfo->child_relid;
1721                 return (Node *) cexpr;
1722         }
1723         if (IsA(node, RangeTblRef))
1724         {
1725                 RangeTblRef *rtr = (RangeTblRef *) copyObject(node);
1726
1727                 if (rtr->rtindex == appinfo->parent_relid)
1728                         rtr->rtindex = appinfo->child_relid;
1729                 return (Node *) rtr;
1730         }
1731         if (IsA(node, JoinExpr))
1732         {
1733                 /* Copy the JoinExpr node with correct mutation of subnodes */
1734                 JoinExpr   *j;
1735
1736                 j = (JoinExpr *) expression_tree_mutator(node,
1737                                                                                           adjust_appendrel_attrs_mutator,
1738                                                                                                  (void *) context);
1739                 /* now fix JoinExpr's rtindex (probably never happens) */
1740                 if (j->rtindex == appinfo->parent_relid)
1741                         j->rtindex = appinfo->child_relid;
1742                 return (Node *) j;
1743         }
1744         if (IsA(node, PlaceHolderVar))
1745         {
1746                 /* Copy the PlaceHolderVar node with correct mutation of subnodes */
1747                 PlaceHolderVar *phv;
1748
1749                 phv = (PlaceHolderVar *) expression_tree_mutator(node,
1750                                                                                           adjust_appendrel_attrs_mutator,
1751                                                                                                                  (void *) context);
1752                 /* now fix PlaceHolderVar's relid sets */
1753                 if (phv->phlevelsup == 0)
1754                         phv->phrels = adjust_relid_set(phv->phrels,
1755                                                                                    appinfo->parent_relid,
1756                                                                                    appinfo->child_relid);
1757                 return (Node *) phv;
1758         }
1759         /* Shouldn't need to handle planner auxiliary nodes here */
1760         Assert(!IsA(node, SpecialJoinInfo));
1761         Assert(!IsA(node, LateralJoinInfo));
1762         Assert(!IsA(node, AppendRelInfo));
1763         Assert(!IsA(node, PlaceHolderInfo));
1764         Assert(!IsA(node, MinMaxAggInfo));
1765
1766         /*
1767          * We have to process RestrictInfo nodes specially.  (Note: although
1768          * set_append_rel_pathlist will hide RestrictInfos in the parent's
1769          * baserestrictinfo list from us, it doesn't hide those in joininfo.)
1770          */
1771         if (IsA(node, RestrictInfo))
1772         {
1773                 RestrictInfo *oldinfo = (RestrictInfo *) node;
1774                 RestrictInfo *newinfo = makeNode(RestrictInfo);
1775
1776                 /* Copy all flat-copiable fields */
1777                 memcpy(newinfo, oldinfo, sizeof(RestrictInfo));
1778
1779                 /* Recursively fix the clause itself */
1780                 newinfo->clause = (Expr *)
1781                         adjust_appendrel_attrs_mutator((Node *) oldinfo->clause, context);
1782
1783                 /* and the modified version, if an OR clause */
1784                 newinfo->orclause = (Expr *)
1785                         adjust_appendrel_attrs_mutator((Node *) oldinfo->orclause, context);
1786
1787                 /* adjust relid sets too */
1788                 newinfo->clause_relids = adjust_relid_set(oldinfo->clause_relids,
1789                                                                                                   appinfo->parent_relid,
1790                                                                                                   appinfo->child_relid);
1791                 newinfo->required_relids = adjust_relid_set(oldinfo->required_relids,
1792                                                                                                         appinfo->parent_relid,
1793                                                                                                         appinfo->child_relid);
1794                 newinfo->outer_relids = adjust_relid_set(oldinfo->outer_relids,
1795                                                                                                  appinfo->parent_relid,
1796                                                                                                  appinfo->child_relid);
1797                 newinfo->nullable_relids = adjust_relid_set(oldinfo->nullable_relids,
1798                                                                                                         appinfo->parent_relid,
1799                                                                                                         appinfo->child_relid);
1800                 newinfo->left_relids = adjust_relid_set(oldinfo->left_relids,
1801                                                                                                 appinfo->parent_relid,
1802                                                                                                 appinfo->child_relid);
1803                 newinfo->right_relids = adjust_relid_set(oldinfo->right_relids,
1804                                                                                                  appinfo->parent_relid,
1805                                                                                                  appinfo->child_relid);
1806
1807                 /*
1808                  * Reset cached derivative fields, since these might need to have
1809                  * different values when considering the child relation.  Note we
1810                  * don't reset left_ec/right_ec: each child variable is implicitly
1811                  * equivalent to its parent, so still a member of the same EC if any.
1812                  */
1813                 newinfo->eval_cost.startup = -1;
1814                 newinfo->norm_selec = -1;
1815                 newinfo->outer_selec = -1;
1816                 newinfo->left_em = NULL;
1817                 newinfo->right_em = NULL;
1818                 newinfo->scansel_cache = NIL;
1819                 newinfo->left_bucketsize = -1;
1820                 newinfo->right_bucketsize = -1;
1821
1822                 return (Node *) newinfo;
1823         }
1824
1825         /*
1826          * NOTE: we do not need to recurse into sublinks, because they should
1827          * already have been converted to subplans before we see them.
1828          */
1829         Assert(!IsA(node, SubLink));
1830         Assert(!IsA(node, Query));
1831
1832         return expression_tree_mutator(node, adjust_appendrel_attrs_mutator,
1833                                                                    (void *) context);
1834 }
1835
1836 /*
1837  * Substitute newrelid for oldrelid in a Relid set
1838  */
1839 static Relids
1840 adjust_relid_set(Relids relids, Index oldrelid, Index newrelid)
1841 {
1842         if (bms_is_member(oldrelid, relids))
1843         {
1844                 /* Ensure we have a modifiable copy */
1845                 relids = bms_copy(relids);
1846                 /* Remove old, add new */
1847                 relids = bms_del_member(relids, oldrelid);
1848                 relids = bms_add_member(relids, newrelid);
1849         }
1850         return relids;
1851 }
1852
1853 /*
1854  * Adjust the targetlist entries of an inherited UPDATE operation
1855  *
1856  * The expressions have already been fixed, but we have to make sure that
1857  * the target resnos match the child table (they may not, in the case of
1858  * a column that was added after-the-fact by ALTER TABLE).      In some cases
1859  * this can force us to re-order the tlist to preserve resno ordering.
1860  * (We do all this work in special cases so that preptlist.c is fast for
1861  * the typical case.)
1862  *
1863  * The given tlist has already been through expression_tree_mutator;
1864  * therefore the TargetEntry nodes are fresh copies that it's okay to
1865  * scribble on.
1866  *
1867  * Note that this is not needed for INSERT because INSERT isn't inheritable.
1868  */
1869 static List *
1870 adjust_inherited_tlist(List *tlist, AppendRelInfo *context)
1871 {
1872         bool            changed_it = false;
1873         ListCell   *tl;
1874         List       *new_tlist;
1875         bool            more;
1876         int                     attrno;
1877
1878         /* This should only happen for an inheritance case, not UNION ALL */
1879         Assert(OidIsValid(context->parent_reloid));
1880
1881         /* Scan tlist and update resnos to match attnums of child rel */
1882         foreach(tl, tlist)
1883         {
1884                 TargetEntry *tle = (TargetEntry *) lfirst(tl);
1885                 Var                *childvar;
1886
1887                 if (tle->resjunk)
1888                         continue;                       /* ignore junk items */
1889
1890                 /* Look up the translation of this column: it must be a Var */
1891                 if (tle->resno <= 0 ||
1892                         tle->resno > list_length(context->translated_vars))
1893                         elog(ERROR, "attribute %d of relation \"%s\" does not exist",
1894                                  tle->resno, get_rel_name(context->parent_reloid));
1895                 childvar = (Var *) list_nth(context->translated_vars, tle->resno - 1);
1896                 if (childvar == NULL || !IsA(childvar, Var))
1897                         elog(ERROR, "attribute %d of relation \"%s\" does not exist",
1898                                  tle->resno, get_rel_name(context->parent_reloid));
1899
1900                 if (tle->resno != childvar->varattno)
1901                 {
1902                         tle->resno = childvar->varattno;
1903                         changed_it = true;
1904                 }
1905         }
1906
1907         /*
1908          * If we changed anything, re-sort the tlist by resno, and make sure
1909          * resjunk entries have resnos above the last real resno.  The sort
1910          * algorithm is a bit stupid, but for such a seldom-taken path, small is
1911          * probably better than fast.
1912          */
1913         if (!changed_it)
1914                 return tlist;
1915
1916         new_tlist = NIL;
1917         more = true;
1918         for (attrno = 1; more; attrno++)
1919         {
1920                 more = false;
1921                 foreach(tl, tlist)
1922                 {
1923                         TargetEntry *tle = (TargetEntry *) lfirst(tl);
1924
1925                         if (tle->resjunk)
1926                                 continue;               /* ignore junk items */
1927
1928                         if (tle->resno == attrno)
1929                                 new_tlist = lappend(new_tlist, tle);
1930                         else if (tle->resno > attrno)
1931                                 more = true;
1932                 }
1933         }
1934
1935         foreach(tl, tlist)
1936         {
1937                 TargetEntry *tle = (TargetEntry *) lfirst(tl);
1938
1939                 if (!tle->resjunk)
1940                         continue;                       /* here, ignore non-junk items */
1941
1942                 tle->resno = attrno;
1943                 new_tlist = lappend(new_tlist, tle);
1944                 attrno++;
1945         }
1946
1947         return new_tlist;
1948 }