1 /*-------------------------------------------------------------------------
2 *
3 * createplan.c
4 * Routines to create the desired plan for processing a query.
5 * Planning is complete, we just need to convert the selected
6 * Path into a Plan.
7 *
8 * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
9 * Portions Copyright (c) 1994, Regents of the University of California
10 *
11 *
12 * IDENTIFICATION
13 * src/backend/optimizer/plan/createplan.c
14 *
15 *-------------------------------------------------------------------------
16 */
17 #include "postgres.h"
18
19 #include <limits.h>
20 #include <math.h>
21
22 #include "access/sysattr.h"
23 #include "catalog/pg_class.h"
24 #include "foreign/fdwapi.h"
25 #include "miscadmin.h"
26 #include "nodes/extensible.h"
27 #include "nodes/makefuncs.h"
28 #include "nodes/nodeFuncs.h"
29 #include "optimizer/clauses.h"
30 #include "optimizer/cost.h"
31 #include "optimizer/paramassign.h"
32 #include "optimizer/paths.h"
33 #include "optimizer/placeholder.h"
34 #include "optimizer/plancat.h"
35 #include "optimizer/planmain.h"
36 #include "optimizer/predtest.h"
37 #include "optimizer/restrictinfo.h"
38 #include "optimizer/subselect.h"
39 #include "optimizer/tlist.h"
40 #include "optimizer/var.h"
41 #include "parser/parse_clause.h"
42 #include "parser/parsetree.h"
43 #include "utils/lsyscache.h"
44
45
46 /*
47 * Flag bits that can appear in the flags argument of create_plan_recurse().
48 * These can be OR-ed together.
49 *
50 * CP_EXACT_TLIST specifies that the generated plan node must return exactly
51 * the tlist specified by the path's pathtarget (this overrides both
52 * CP_SMALL_TLIST and CP_LABEL_TLIST, if those are set). Otherwise, the
53 * plan node is allowed to return just the Vars and PlaceHolderVars needed
54 * to evaluate the pathtarget.
55 *
56 * CP_SMALL_TLIST specifies that a narrower tlist is preferred. This is
57 * passed down by parent nodes such as Sort and Hash, which will have to
58 * store the returned tuples.
59 *
60 * CP_LABEL_TLIST specifies that the plan node must return columns matching
61 * any sortgrouprefs specified in its pathtarget, with appropriate
62 * ressortgroupref labels. This is passed down by parent nodes such as Sort
63 * and Group, which need these values to be available in their inputs.
64 */
65 #define CP_EXACT_TLIST 0x0001 /* Plan must return specified tlist */
66 #define CP_SMALL_TLIST 0x0002 /* Prefer narrower tlists */
67 #define CP_LABEL_TLIST 0x0004 /* tlist must contain sortgrouprefs */
68
69
70 static Plan *create_plan_recurse(PlannerInfo *root, Path *best_path,
71 int flags);
72 static Plan *create_scan_plan(PlannerInfo *root, Path *best_path,
73 int flags);
74 static List *build_path_tlist(PlannerInfo *root, Path *path);
75 static bool use_physical_tlist(PlannerInfo *root, Path *path, int flags);
76 static List *get_gating_quals(PlannerInfo *root, List *quals);
77 static Plan *create_gating_plan(PlannerInfo *root, Path *path, Plan *plan,
78 List *gating_quals);
79 static Plan *create_join_plan(PlannerInfo *root, JoinPath *best_path);
80 static Plan *create_append_plan(PlannerInfo *root, AppendPath *best_path);
81 static Plan *create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path,
82 int flags);
83 static Result *create_result_plan(PlannerInfo *root, ResultPath *best_path);
84 static Material *create_material_plan(PlannerInfo *root, MaterialPath *best_path,
85 int flags);
86 static Plan *create_unique_plan(PlannerInfo *root, UniquePath *best_path,
87 int flags);
88 static Gather *create_gather_plan(PlannerInfo *root, GatherPath *best_path);
89 static Plan *create_projection_plan(PlannerInfo *root, ProjectionPath *best_path);
90 static Plan *inject_projection_plan(Plan *subplan, List *tlist);
91 static Sort *create_sort_plan(PlannerInfo *root, SortPath *best_path, int flags);
92 static Group *create_group_plan(PlannerInfo *root, GroupPath *best_path);
93 static Unique *create_upper_unique_plan(PlannerInfo *root, UpperUniquePath *best_path,
94 int flags);
95 static Agg *create_agg_plan(PlannerInfo *root, AggPath *best_path);
96 static Plan *create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path);
97 static Result *create_minmaxagg_plan(PlannerInfo *root, MinMaxAggPath *best_path);
98 static WindowAgg *create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path);
99 static SetOp *create_setop_plan(PlannerInfo *root, SetOpPath *best_path,
100 int flags);
101 static RecursiveUnion *create_recursiveunion_plan(PlannerInfo *root, RecursiveUnionPath *best_path);
102 static void get_column_info_for_window(PlannerInfo *root, WindowClause *wc,
103 List *tlist,
104 int numSortCols, AttrNumber *sortColIdx,
105 int *partNumCols,
106 AttrNumber **partColIdx,
107 Oid **partOperators,
108 int *ordNumCols,
109 AttrNumber **ordColIdx,
110 Oid **ordOperators);
111 static LockRows *create_lockrows_plan(PlannerInfo *root, LockRowsPath *best_path,
112 int flags);
113 static ModifyTable *create_modifytable_plan(PlannerInfo *root, ModifyTablePath *best_path);
114 static Limit *create_limit_plan(PlannerInfo *root, LimitPath *best_path,
115 int flags);
116 static SeqScan *create_seqscan_plan(PlannerInfo *root, Path *best_path,
117 List *tlist, List *scan_clauses);
118 static SampleScan *create_samplescan_plan(PlannerInfo *root, Path *best_path,
119 List *tlist, List *scan_clauses);
120 static Scan *create_indexscan_plan(PlannerInfo *root, IndexPath *best_path,
121 List *tlist, List *scan_clauses, bool indexonly);
122 static BitmapHeapScan *create_bitmap_scan_plan(PlannerInfo *root,
123 BitmapHeapPath *best_path,
124 List *tlist, List *scan_clauses);
125 static Plan *create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
126 List **qual, List **indexqual, List **indexECs);
127 static TidScan *create_tidscan_plan(PlannerInfo *root, TidPath *best_path,
128 List *tlist, List *scan_clauses);
129 static SubqueryScan *create_subqueryscan_plan(PlannerInfo *root,
130 SubqueryScanPath *best_path,
131 List *tlist, List *scan_clauses);
132 static FunctionScan *create_functionscan_plan(PlannerInfo *root, Path *best_path,
133 List *tlist, List *scan_clauses);
134 static ValuesScan *create_valuesscan_plan(PlannerInfo *root, Path *best_path,
135 List *tlist, List *scan_clauses);
136 static CteScan *create_ctescan_plan(PlannerInfo *root, Path *best_path,
137 List *tlist, List *scan_clauses);
138 static WorkTableScan *create_worktablescan_plan(PlannerInfo *root, Path *best_path,
139 List *tlist, List *scan_clauses);
140 static ForeignScan *create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path,
141 List *tlist, List *scan_clauses);
142 static CustomScan *create_customscan_plan(PlannerInfo *root,
143 CustomPath *best_path,
144 List *tlist, List *scan_clauses);
145 static NestLoop *create_nestloop_plan(PlannerInfo *root, NestPath *best_path);
146 static MergeJoin *create_mergejoin_plan(PlannerInfo *root, MergePath *best_path);
147 static HashJoin *create_hashjoin_plan(PlannerInfo *root, HashPath *best_path);
148 static Node *replace_nestloop_params(PlannerInfo *root, Node *expr);
149 static Node *replace_nestloop_params_mutator(Node *node, PlannerInfo *root);
150 static List *fix_indexqual_references(PlannerInfo *root, IndexPath *index_path);
151 static List *fix_indexorderby_references(PlannerInfo *root, IndexPath *index_path);
152 static Node *fix_indexqual_operand(Node *node, IndexOptInfo *index, int indexcol);
153 static List *get_switched_clauses(List *clauses, Relids outerrelids);
154 static List *order_qual_clauses(PlannerInfo *root, List *clauses);
155 static void copy_generic_path_info(Plan *dest, Path *src);
156 static void copy_plan_costsize(Plan *dest, Plan *src);
157 static void label_sort_with_costsize(PlannerInfo *root, Sort *plan,
158 double limit_tuples);
159 static SeqScan *make_seqscan(List *qptlist, List *qpqual, Index scanrelid);
160 static SampleScan *make_samplescan(List *qptlist, List *qpqual, Index scanrelid,
161 TableSampleClause *tsc);
162 static IndexScan *make_indexscan(List *qptlist, List *qpqual, Index scanrelid,
163 Oid indexid, List *indexqual, List *indexqualorig,
164 List *indexorderby, List *indexorderbyorig,
165 List *indexorderbyops,
166 ScanDirection indexscandir);
167 static IndexOnlyScan *make_indexonlyscan(List *qptlist, List *qpqual,
168 Index scanrelid, Oid indexid,
169 List *indexqual, List *indexorderby,
170 List *indextlist,
171 ScanDirection indexscandir);
172 static BitmapIndexScan *make_bitmap_indexscan(Index scanrelid, Oid indexid,
173 List *indexqual,
174 List *indexqualorig);
175 static BitmapHeapScan *make_bitmap_heapscan(List *qptlist,
176 List *qpqual,
177 Plan *lefttree,
178 List *bitmapqualorig,
179 Index scanrelid);
180 static TidScan *make_tidscan(List *qptlist, List *qpqual, Index scanrelid,
181 List *tidquals);
182 static SubqueryScan *make_subqueryscan(List *qptlist,
183 List *qpqual,
184 Index scanrelid,
185 Plan *subplan);
186 static FunctionScan *make_functionscan(List *qptlist, List *qpqual,
187 Index scanrelid, List *functions, bool funcordinality);
188 static ValuesScan *make_valuesscan(List *qptlist, List *qpqual,
189 Index scanrelid, List *values_lists);
190 static CteScan *make_ctescan(List *qptlist, List *qpqual,
191 Index scanrelid, int ctePlanId, int cteParam);
192 static WorkTableScan *make_worktablescan(List *qptlist, List *qpqual,
193 Index scanrelid, int wtParam);
194 static Append *make_append(List *appendplans, List *tlist);
195 static RecursiveUnion *make_recursive_union(List *tlist,
196 Plan *lefttree,
197 Plan *righttree,
198 int wtParam,
199 List *distinctList,
200 long numGroups);
201 static BitmapAnd *make_bitmap_and(List *bitmapplans);
202 static BitmapOr *make_bitmap_or(List *bitmapplans);
203 static NestLoop *make_nestloop(List *tlist,
204 List *joinclauses, List *otherclauses, List *nestParams,
205 Plan *lefttree, Plan *righttree,
206 JoinType jointype);
207 static HashJoin *make_hashjoin(List *tlist,
208 List *joinclauses, List *otherclauses,
209 List *hashclauses,
210 Plan *lefttree, Plan *righttree,
211 JoinType jointype);
212 static Hash *make_hash(Plan *lefttree,
213 Oid skewTable,
214 AttrNumber skewColumn,
215 bool skewInherit,
216 Oid skewColType,
217 int32 skewColTypmod);
218 static MergeJoin *make_mergejoin(List *tlist,
219 List *joinclauses, List *otherclauses,
220 List *mergeclauses,
221 Oid *mergefamilies,
222 Oid *mergecollations,
223 int *mergestrategies,
224 bool *mergenullsfirst,
225 Plan *lefttree, Plan *righttree,
226 JoinType jointype);
227 static Sort *make_sort(Plan *lefttree, int numCols,
228 AttrNumber *sortColIdx, Oid *sortOperators,
229 Oid *collations, bool *nullsFirst);
230 static Plan *prepare_sort_from_pathkeys(Plan *lefttree, List *pathkeys,
231 Relids relids,
232 const AttrNumber *reqColIdx,
233 bool adjust_tlist_in_place,
234 int *p_numsortkeys,
235 AttrNumber **p_sortColIdx,
236 Oid **p_sortOperators,
237 Oid **p_collations,
238 bool **p_nullsFirst);
239 static EquivalenceMember *find_ec_member_for_tle(EquivalenceClass *ec,
240 TargetEntry *tle,
241 Relids relids);
242 static Sort *make_sort_from_pathkeys(Plan *lefttree, List *pathkeys);
243 static Sort *make_sort_from_groupcols(List *groupcls,
244 AttrNumber *grpColIdx,
245 Plan *lefttree);
246 static Material *make_material(Plan *lefttree);
247 static WindowAgg *make_windowagg(List *tlist, Index winref,
248 int partNumCols, AttrNumber *partColIdx, Oid *partOperators,
249 int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators,
250 int frameOptions, Node *startOffset, Node *endOffset,
251 Plan *lefttree);
252 static Group *make_group(List *tlist, List *qual, int numGroupCols,
253 AttrNumber *grpColIdx, Oid *grpOperators,
254 Plan *lefttree);
255 static Unique *make_unique_from_sortclauses(Plan *lefttree, List *distinctList);
256 static Unique *make_unique_from_pathkeys(Plan *lefttree,
257 List *pathkeys, int numCols);
258 static Gather *make_gather(List *qptlist, List *qpqual,
259 int nworkers, bool single_copy, Plan *subplan);
260 static SetOp *make_setop(SetOpCmd cmd, SetOpStrategy strategy, Plan *lefttree,
261 List *distinctList, AttrNumber flagColIdx, int firstFlag,
262 long numGroups);
263 static LockRows *make_lockrows(Plan *lefttree, List *rowMarks, int epqParam);
264 static Result *make_result(List *tlist, Node *resconstantqual, Plan *subplan);
265 static ModifyTable *make_modifytable(PlannerInfo *root,
266 CmdType operation, bool canSetTag,
267 Index nominalRelation,
268 List *resultRelations, List *subplans,
269 List *withCheckOptionLists, List *returningLists,
270 List *rowMarks, OnConflictExpr *onconflict, int epqParam);
271
272
273 /*
274 * create_plan
275 * Creates the access plan for a query by recursively processing the
276 * desired tree of pathnodes, starting at the node 'best_path'. For
277 * every pathnode found, we create a corresponding plan node containing
278 * appropriate id, target list, and qualification information.
279 *
280 * The tlists and quals in the plan tree are still in planner format,
281 * ie, Vars still correspond to the parser's numbering. This will be
282 * fixed later by setrefs.c.
283 *
284 * best_path is the best access path
285 *
286 * Returns a Plan tree.
287 */
288 Plan *
create_plan(PlannerInfo * root,Path * best_path)289 create_plan(PlannerInfo *root, Path *best_path)
290 {
291 Plan *plan;
292
293 /* plan_params should not be in use in current query level */
294 Assert(root->plan_params == NIL);
295
296 /* Initialize this module's workspace in PlannerInfo */
297 root->curOuterRels = NULL;
298 root->curOuterParams = NIL;
299
300 /* Recursively process the path tree, demanding the correct tlist result */
301 plan = create_plan_recurse(root, best_path, CP_EXACT_TLIST);
302
303 /*
304 * Make sure the topmost plan node's targetlist exposes the original
305 * column names and other decorative info. Targetlists generated within
306 * the planner don't bother with that stuff, but we must have it on the
307 * top-level tlist seen at execution time. However, ModifyTable plan
308 * nodes don't have a tlist matching the querytree targetlist.
309 */
310 if (!IsA(plan, ModifyTable))
311 apply_tlist_labeling(plan->targetlist, root->processed_tlist);
312
313 /*
314 * Attach any initPlans created in this query level to the topmost plan
315 * node. (In principle the initplans could go in any plan node at or
316 * above where they're referenced, but there seems no reason to put them
317 * any lower than the topmost node for the query level. Also, see
318 * comments for SS_finalize_plan before you try to change this.)
319 */
320 SS_attach_initplans(root, plan);
321
322 /* Check we successfully assigned all NestLoopParams to plan nodes */
323 if (root->curOuterParams != NIL)
324 elog(ERROR, "failed to assign all NestLoopParams to plan nodes");
325
326 /*
327 * Reset plan_params to ensure param IDs used for nestloop params are not
328 * re-used later
329 */
330 root->plan_params = NIL;
331
332 return plan;
333 }
334
335 /*
336 * create_plan_recurse
337 * Recursive guts of create_plan().
338 */
339 static Plan *
create_plan_recurse(PlannerInfo * root,Path * best_path,int flags)340 create_plan_recurse(PlannerInfo *root, Path *best_path, int flags)
341 {
342 Plan *plan;
343
344 /* Guard against stack overflow due to overly complex plans */
345 check_stack_depth();
346
347 switch (best_path->pathtype)
348 {
349 case T_SeqScan:
350 case T_SampleScan:
351 case T_IndexScan:
352 case T_IndexOnlyScan:
353 case T_BitmapHeapScan:
354 case T_TidScan:
355 case T_SubqueryScan:
356 case T_FunctionScan:
357 case T_ValuesScan:
358 case T_CteScan:
359 case T_WorkTableScan:
360 case T_ForeignScan:
361 case T_CustomScan:
362 plan = create_scan_plan(root, best_path, flags);
363 break;
364 case T_HashJoin:
365 case T_MergeJoin:
366 case T_NestLoop:
367 plan = create_join_plan(root,
368 (JoinPath *) best_path);
369 break;
370 case T_Append:
371 plan = create_append_plan(root,
372 (AppendPath *) best_path);
373 break;
374 case T_MergeAppend:
375 plan = create_merge_append_plan(root,
376 (MergeAppendPath *) best_path,
377 flags);
378 break;
379 case T_Result:
380 if (IsA(best_path, ProjectionPath))
381 {
382 plan = create_projection_plan(root,
383 (ProjectionPath *) best_path);
384 }
385 else if (IsA(best_path, MinMaxAggPath))
386 {
387 plan = (Plan *) create_minmaxagg_plan(root,
388 (MinMaxAggPath *) best_path);
389 }
390 else
391 {
392 Assert(IsA(best_path, ResultPath));
393 plan = (Plan *) create_result_plan(root,
394 (ResultPath *) best_path);
395 }
396 break;
397 case T_Material:
398 plan = (Plan *) create_material_plan(root,
399 (MaterialPath *) best_path,
400 flags);
401 break;
402 case T_Unique:
403 if (IsA(best_path, UpperUniquePath))
404 {
405 plan = (Plan *) create_upper_unique_plan(root,
406 (UpperUniquePath *) best_path,
407 flags);
408 }
409 else
410 {
411 Assert(IsA(best_path, UniquePath));
412 plan = create_unique_plan(root,
413 (UniquePath *) best_path,
414 flags);
415 }
416 break;
417 case T_Gather:
418 plan = (Plan *) create_gather_plan(root,
419 (GatherPath *) best_path);
420 break;
421 case T_Sort:
422 plan = (Plan *) create_sort_plan(root,
423 (SortPath *) best_path,
424 flags);
425 break;
426 case T_Group:
427 plan = (Plan *) create_group_plan(root,
428 (GroupPath *) best_path);
429 break;
430 case T_Agg:
431 if (IsA(best_path, GroupingSetsPath))
432 plan = create_groupingsets_plan(root,
433 (GroupingSetsPath *) best_path);
434 else
435 {
436 Assert(IsA(best_path, AggPath));
437 plan = (Plan *) create_agg_plan(root,
438 (AggPath *) best_path);
439 }
440 break;
441 case T_WindowAgg:
442 plan = (Plan *) create_windowagg_plan(root,
443 (WindowAggPath *) best_path);
444 break;
445 case T_SetOp:
446 plan = (Plan *) create_setop_plan(root,
447 (SetOpPath *) best_path,
448 flags);
449 break;
450 case T_RecursiveUnion:
451 plan = (Plan *) create_recursiveunion_plan(root,
452 (RecursiveUnionPath *) best_path);
453 break;
454 case T_LockRows:
455 plan = (Plan *) create_lockrows_plan(root,
456 (LockRowsPath *) best_path,
457 flags);
458 break;
459 case T_ModifyTable:
460 plan = (Plan *) create_modifytable_plan(root,
461 (ModifyTablePath *) best_path);
462 break;
463 case T_Limit:
464 plan = (Plan *) create_limit_plan(root,
465 (LimitPath *) best_path,
466 flags);
467 break;
468 default:
469 elog(ERROR, "unrecognized node type: %d",
470 (int) best_path->pathtype);
471 plan = NULL; /* keep compiler quiet */
472 break;
473 }
474
475 return plan;
476 }
477
478 /*
479 * create_scan_plan
480 * Create a scan plan for the parent relation of 'best_path'.
481 */
482 static Plan *
create_scan_plan(PlannerInfo * root,Path * best_path,int flags)483 create_scan_plan(PlannerInfo *root, Path *best_path, int flags)
484 {
485 RelOptInfo *rel = best_path->parent;
486 List *scan_clauses;
487 List *gating_clauses;
488 List *tlist;
489 Plan *plan;
490
491 /*
492 * Extract the relevant restriction clauses from the parent relation. The
493 * executor must apply all these restrictions during the scan, except for
494 * pseudoconstants which we'll take care of below.
495 *
496 * If this is a plain indexscan or index-only scan, we need not consider
497 * restriction clauses that are implied by the index's predicate, so use
498 * indrestrictinfo not baserestrictinfo. Note that we can't do that for
499 * bitmap indexscans, since there's not necessarily a single index
500 * involved; but it doesn't matter since create_bitmap_scan_plan() will be
501 * able to get rid of such clauses anyway via predicate proof.
502 */
503 switch (best_path->pathtype)
504 {
505 case T_IndexScan:
506 case T_IndexOnlyScan:
507 Assert(IsA(best_path, IndexPath));
508 scan_clauses = ((IndexPath *) best_path)->indexinfo->indrestrictinfo;
509 break;
510 default:
511 scan_clauses = rel->baserestrictinfo;
512 break;
513 }
514
515 /*
516 * If this is a parameterized scan, we also need to enforce all the join
517 * clauses available from the outer relation(s).
518 *
519 * For paranoia's sake, don't modify the stored baserestrictinfo list.
520 */
521 if (best_path->param_info)
522 scan_clauses = list_concat(list_copy(scan_clauses),
523 best_path->param_info->ppi_clauses);
524
525 /*
526 * Detect whether we have any pseudoconstant quals to deal with. Then, if
527 * we'll need a gating Result node, it will be able to project, so there
528 * are no requirements on the child's tlist.
529 */
530 gating_clauses = get_gating_quals(root, scan_clauses);
531 if (gating_clauses)
532 flags = 0;
533
534 /*
535 * For table scans, rather than using the relation targetlist (which is
536 * only those Vars actually needed by the query), we prefer to generate a
537 * tlist containing all Vars in order. This will allow the executor to
538 * optimize away projection of the table tuples, if possible.
539 */
540 if (use_physical_tlist(root, best_path, flags))
541 {
542 if (best_path->pathtype == T_IndexOnlyScan)
543 {
544 /* For index-only scan, the preferred tlist is the index's */
545 tlist = copyObject(((IndexPath *) best_path)->indexinfo->indextlist);
546
547 /*
548 * Transfer sortgroupref data to the replacement tlist, if
549 * requested (use_physical_tlist checked that this will work).
550 */
551 if (flags & CP_LABEL_TLIST)
552 apply_pathtarget_labeling_to_tlist(tlist, best_path->pathtarget);
553 }
554 else
555 {
556 tlist = build_physical_tlist(root, rel);
557 if (tlist == NIL)
558 {
559 /* Failed because of dropped cols, so use regular method */
560 tlist = build_path_tlist(root, best_path);
561 }
562 else
563 {
564 /* As above, transfer sortgroupref data to replacement tlist */
565 if (flags & CP_LABEL_TLIST)
566 apply_pathtarget_labeling_to_tlist(tlist, best_path->pathtarget);
567 }
568 }
569 }
570 else
571 {
572 tlist = build_path_tlist(root, best_path);
573 }
574
575 switch (best_path->pathtype)
576 {
577 case T_SeqScan:
578 plan = (Plan *) create_seqscan_plan(root,
579 best_path,
580 tlist,
581 scan_clauses);
582 break;
583
584 case T_SampleScan:
585 plan = (Plan *) create_samplescan_plan(root,
586 best_path,
587 tlist,
588 scan_clauses);
589 break;
590
591 case T_IndexScan:
592 plan = (Plan *) create_indexscan_plan(root,
593 (IndexPath *) best_path,
594 tlist,
595 scan_clauses,
596 false);
597 break;
598
599 case T_IndexOnlyScan:
600 plan = (Plan *) create_indexscan_plan(root,
601 (IndexPath *) best_path,
602 tlist,
603 scan_clauses,
604 true);
605 break;
606
607 case T_BitmapHeapScan:
608 plan = (Plan *) create_bitmap_scan_plan(root,
609 (BitmapHeapPath *) best_path,
610 tlist,
611 scan_clauses);
612 break;
613
614 case T_TidScan:
615 plan = (Plan *) create_tidscan_plan(root,
616 (TidPath *) best_path,
617 tlist,
618 scan_clauses);
619 break;
620
621 case T_SubqueryScan:
622 plan = (Plan *) create_subqueryscan_plan(root,
623 (SubqueryScanPath *) best_path,
624 tlist,
625 scan_clauses);
626 break;
627
628 case T_FunctionScan:
629 plan = (Plan *) create_functionscan_plan(root,
630 best_path,
631 tlist,
632 scan_clauses);
633 break;
634
635 case T_ValuesScan:
636 plan = (Plan *) create_valuesscan_plan(root,
637 best_path,
638 tlist,
639 scan_clauses);
640 break;
641
642 case T_CteScan:
643 plan = (Plan *) create_ctescan_plan(root,
644 best_path,
645 tlist,
646 scan_clauses);
647 break;
648
649 case T_WorkTableScan:
650 plan = (Plan *) create_worktablescan_plan(root,
651 best_path,
652 tlist,
653 scan_clauses);
654 break;
655
656 case T_ForeignScan:
657 plan = (Plan *) create_foreignscan_plan(root,
658 (ForeignPath *) best_path,
659 tlist,
660 scan_clauses);
661 break;
662
663 case T_CustomScan:
664 plan = (Plan *) create_customscan_plan(root,
665 (CustomPath *) best_path,
666 tlist,
667 scan_clauses);
668 break;
669
670 default:
671 elog(ERROR, "unrecognized node type: %d",
672 (int) best_path->pathtype);
673 plan = NULL; /* keep compiler quiet */
674 break;
675 }
676
677 /*
678 * If there are any pseudoconstant clauses attached to this node, insert a
679 * gating Result node that evaluates the pseudoconstants as one-time
680 * quals.
681 */
682 if (gating_clauses)
683 plan = create_gating_plan(root, best_path, plan, gating_clauses);
684
685 return plan;
686 }
687
688 /*
689 * Build a target list (ie, a list of TargetEntry) for the Path's output.
690 *
691 * This is almost just make_tlist_from_pathtarget(), but we also have to
692 * deal with replacing nestloop params.
693 */
694 static List *
build_path_tlist(PlannerInfo * root,Path * path)695 build_path_tlist(PlannerInfo *root, Path *path)
696 {
697 List *tlist = NIL;
698 Index *sortgrouprefs = path->pathtarget->sortgrouprefs;
699 int resno = 1;
700 ListCell *v;
701
702 foreach(v, path->pathtarget->exprs)
703 {
704 Node *node = (Node *) lfirst(v);
705 TargetEntry *tle;
706
707 /*
708 * If it's a parameterized path, there might be lateral references in
709 * the tlist, which need to be replaced with Params. There's no need
710 * to remake the TargetEntry nodes, so apply this to each list item
711 * separately.
712 */
713 if (path->param_info)
714 node = replace_nestloop_params(root, node);
715
716 tle = makeTargetEntry((Expr *) node,
717 resno,
718 NULL,
719 false);
720 if (sortgrouprefs)
721 tle->ressortgroupref = sortgrouprefs[resno - 1];
722
723 tlist = lappend(tlist, tle);
724 resno++;
725 }
726 return tlist;
727 }
728
729 /*
730 * use_physical_tlist
731 * Decide whether to use a tlist matching relation structure,
732 * rather than only those Vars actually referenced.
733 */
734 static bool
use_physical_tlist(PlannerInfo * root,Path * path,int flags)735 use_physical_tlist(PlannerInfo *root, Path *path, int flags)
736 {
737 RelOptInfo *rel = path->parent;
738 int i;
739 ListCell *lc;
740
741 /*
742 * Forget it if either exact tlist or small tlist is demanded.
743 */
744 if (flags & (CP_EXACT_TLIST | CP_SMALL_TLIST))
745 return false;
746
747 /*
748 * We can do this for real relation scans, subquery scans, function scans,
749 * values scans, and CTE scans (but not for, eg, joins).
750 */
751 if (rel->rtekind != RTE_RELATION &&
752 rel->rtekind != RTE_SUBQUERY &&
753 rel->rtekind != RTE_FUNCTION &&
754 rel->rtekind != RTE_VALUES &&
755 rel->rtekind != RTE_CTE)
756 return false;
757
758 /*
759 * Can't do it with inheritance cases either (mainly because Append
760 * doesn't project; this test may be unnecessary now that
761 * create_append_plan instructs its children to return an exact tlist).
762 */
763 if (rel->reloptkind != RELOPT_BASEREL)
764 return false;
765
766 /*
767 * Also, don't do it to a CustomPath; the premise that we're extracting
768 * columns from a simple physical tuple is unlikely to hold for those.
769 * (When it does make sense, the custom path creator can set up the path's
770 * pathtarget that way.)
771 */
772 if (IsA(path, CustomPath))
773 return false;
774
775 /*
776 * Can't do it if any system columns or whole-row Vars are requested.
777 * (This could possibly be fixed but would take some fragile assumptions
778 * in setrefs.c, I think.)
779 */
780 for (i = rel->min_attr; i <= 0; i++)
781 {
782 if (!bms_is_empty(rel->attr_needed[i - rel->min_attr]))
783 return false;
784 }
785
786 /*
787 * Can't do it if the rel is required to emit any placeholder expressions,
788 * either.
789 */
790 foreach(lc, root->placeholder_list)
791 {
792 PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc);
793
794 if (bms_nonempty_difference(phinfo->ph_needed, rel->relids) &&
795 bms_is_subset(phinfo->ph_eval_at, rel->relids))
796 return false;
797 }
798
799 /*
800 * Also, can't do it if CP_LABEL_TLIST is specified and path is requested
801 * to emit any sort/group columns that are not simple Vars. (If they are
802 * simple Vars, they should appear in the physical tlist, and
803 * apply_pathtarget_labeling_to_tlist will take care of getting them
804 * labeled again.) We also have to check that no two sort/group columns
805 * are the same Var, else that element of the physical tlist would need
806 * conflicting ressortgroupref labels.
807 */
808 if ((flags & CP_LABEL_TLIST) && path->pathtarget->sortgrouprefs)
809 {
810 Bitmapset *sortgroupatts = NULL;
811
812 i = 0;
813 foreach(lc, path->pathtarget->exprs)
814 {
815 Expr *expr = (Expr *) lfirst(lc);
816
817 if (path->pathtarget->sortgrouprefs[i])
818 {
819 if (expr && IsA(expr, Var))
820 {
821 int attno = ((Var *) expr)->varattno;
822
823 attno -= FirstLowInvalidHeapAttributeNumber;
824 if (bms_is_member(attno, sortgroupatts))
825 return false;
826 sortgroupatts = bms_add_member(sortgroupatts, attno);
827 }
828 else
829 return false;
830 }
831 i++;
832 }
833 }
834
835 return true;
836 }
837
838 /*
839 * get_gating_quals
840 * See if there are pseudoconstant quals in a node's quals list
841 *
842 * If the node's quals list includes any pseudoconstant quals,
843 * return just those quals.
844 */
845 static List *
get_gating_quals(PlannerInfo * root,List * quals)846 get_gating_quals(PlannerInfo *root, List *quals)
847 {
848 /* No need to look if we know there are no pseudoconstants */
849 if (!root->hasPseudoConstantQuals)
850 return NIL;
851
852 /* Sort into desirable execution order while still in RestrictInfo form */
853 quals = order_qual_clauses(root, quals);
854
855 /* Pull out any pseudoconstant quals from the RestrictInfo list */
856 return extract_actual_clauses(quals, true);
857 }
858
859 /*
860 * create_gating_plan
861 * Deal with pseudoconstant qual clauses
862 *
863 * Add a gating Result node atop the already-built plan.
864 */
865 static Plan *
create_gating_plan(PlannerInfo * root,Path * path,Plan * plan,List * gating_quals)866 create_gating_plan(PlannerInfo *root, Path *path, Plan *plan,
867 List *gating_quals)
868 {
869 Plan *gplan;
870
871 Assert(gating_quals);
872
873 /*
874 * Since we need a Result node anyway, always return the path's requested
875 * tlist; that's never a wrong choice, even if the parent node didn't ask
876 * for CP_EXACT_TLIST.
877 */
878 gplan = (Plan *) make_result(build_path_tlist(root, path),
879 (Node *) gating_quals,
880 plan);
881
882 /*
883 * Notice that we don't change cost or size estimates when doing gating.
884 * The costs of qual eval were already included in the subplan's cost.
885 * Leaving the size alone amounts to assuming that the gating qual will
886 * succeed, which is the conservative estimate for planning upper queries.
887 * We certainly don't want to assume the output size is zero (unless the
888 * gating qual is actually constant FALSE, and that case is dealt with in
889 * clausesel.c). Interpolating between the two cases is silly, because it
890 * doesn't reflect what will really happen at runtime, and besides which
891 * in most cases we have only a very bad idea of the probability of the
892 * gating qual being true.
893 */
894 copy_plan_costsize(gplan, plan);
895
896 return gplan;
897 }
898
899 /*
900 * create_join_plan
901 * Create a join plan for 'best_path' and (recursively) plans for its
902 * inner and outer paths.
903 */
904 static Plan *
create_join_plan(PlannerInfo * root,JoinPath * best_path)905 create_join_plan(PlannerInfo *root, JoinPath *best_path)
906 {
907 Plan *plan;
908 List *gating_clauses;
909
910 switch (best_path->path.pathtype)
911 {
912 case T_MergeJoin:
913 plan = (Plan *) create_mergejoin_plan(root,
914 (MergePath *) best_path);
915 break;
916 case T_HashJoin:
917 plan = (Plan *) create_hashjoin_plan(root,
918 (HashPath *) best_path);
919 break;
920 case T_NestLoop:
921 plan = (Plan *) create_nestloop_plan(root,
922 (NestPath *) best_path);
923 break;
924 default:
925 elog(ERROR, "unrecognized node type: %d",
926 (int) best_path->path.pathtype);
927 plan = NULL; /* keep compiler quiet */
928 break;
929 }
930
931 /*
932 * If there are any pseudoconstant clauses attached to this node, insert a
933 * gating Result node that evaluates the pseudoconstants as one-time
934 * quals.
935 */
936 gating_clauses = get_gating_quals(root, best_path->joinrestrictinfo);
937 if (gating_clauses)
938 plan = create_gating_plan(root, (Path *) best_path, plan,
939 gating_clauses);
940
941 #ifdef NOT_USED
942
943 /*
944 * * Expensive function pullups may have pulled local predicates * into
945 * this path node. Put them in the qpqual of the plan node. * JMH,
946 * 6/15/92
947 */
948 if (get_loc_restrictinfo(best_path) != NIL)
949 set_qpqual((Plan) plan,
950 list_concat(get_qpqual((Plan) plan),
951 get_actual_clauses(get_loc_restrictinfo(best_path))));
952 #endif
953
954 return plan;
955 }
956
957 /*
958 * create_append_plan
959 * Create an Append plan for 'best_path' and (recursively) plans
960 * for its subpaths.
961 *
962 * Returns a Plan node.
963 */
964 static Plan *
create_append_plan(PlannerInfo * root,AppendPath * best_path)965 create_append_plan(PlannerInfo *root, AppendPath *best_path)
966 {
967 Append *plan;
968 List *tlist = build_path_tlist(root, &best_path->path);
969 List *subplans = NIL;
970 ListCell *subpaths;
971
972 /*
973 * The subpaths list could be empty, if every child was proven empty by
974 * constraint exclusion. In that case generate a dummy plan that returns
975 * no rows.
976 *
977 * Note that an AppendPath with no members is also generated in certain
978 * cases where there was no appending construct at all, but we know the
979 * relation is empty (see set_dummy_rel_pathlist).
980 */
981 if (best_path->subpaths == NIL)
982 {
983 /* Generate a Result plan with constant-FALSE gating qual */
984 Plan *plan;
985
986 plan = (Plan *) make_result(tlist,
987 (Node *) list_make1(makeBoolConst(false,
988 false)),
989 NULL);
990
991 copy_generic_path_info(plan, (Path *) best_path);
992
993 return plan;
994 }
995
996 /* Build the plan for each child */
997 foreach(subpaths, best_path->subpaths)
998 {
999 Path *subpath = (Path *) lfirst(subpaths);
1000 Plan *subplan;
1001
1002 /* Must insist that all children return the same tlist */
1003 subplan = create_plan_recurse(root, subpath, CP_EXACT_TLIST);
1004
1005 subplans = lappend(subplans, subplan);
1006 }
1007
1008 /*
1009 * XXX ideally, if there's just one child, we'd not bother to generate an
1010 * Append node but just return the single child. At the moment this does
1011 * not work because the varno of the child scan plan won't match the
1012 * parent-rel Vars it'll be asked to emit.
1013 */
1014
1015 plan = make_append(subplans, tlist);
1016
1017 copy_generic_path_info(&plan->plan, (Path *) best_path);
1018
1019 return (Plan *) plan;
1020 }
1021
1022 /*
1023 * create_merge_append_plan
1024 * Create a MergeAppend plan for 'best_path' and (recursively) plans
1025 * for its subpaths.
1026 *
1027 * Returns a Plan node.
1028 */
1029 static Plan *
create_merge_append_plan(PlannerInfo * root,MergeAppendPath * best_path,int flags)1030 create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path,
1031 int flags)
1032 {
1033 MergeAppend *node = makeNode(MergeAppend);
1034 Plan *plan = &node->plan;
1035 List *tlist = build_path_tlist(root, &best_path->path);
1036 int orig_tlist_length = list_length(tlist);
1037 bool tlist_was_changed;
1038 List *pathkeys = best_path->path.pathkeys;
1039 List *subplans = NIL;
1040 ListCell *subpaths;
1041
1042 /*
1043 * We don't have the actual creation of the MergeAppend node split out
1044 * into a separate make_xxx function. This is because we want to run
1045 * prepare_sort_from_pathkeys on it before we do so on the individual
1046 * child plans, to make cross-checking the sort info easier.
1047 */
1048 copy_generic_path_info(plan, (Path *) best_path);
1049 plan->targetlist = tlist;
1050 plan->qual = NIL;
1051 plan->lefttree = NULL;
1052 plan->righttree = NULL;
1053
1054 /*
1055 * Compute sort column info, and adjust MergeAppend's tlist as needed.
1056 * Because we pass adjust_tlist_in_place = true, we may ignore the
1057 * function result; it must be the same plan node. However, we then need
1058 * to detect whether any tlist entries were added.
1059 */
1060 (void) prepare_sort_from_pathkeys(plan, pathkeys,
1061 best_path->path.parent->relids,
1062 NULL,
1063 true,
1064 &node->numCols,
1065 &node->sortColIdx,
1066 &node->sortOperators,
1067 &node->collations,
1068 &node->nullsFirst);
1069 tlist_was_changed = (orig_tlist_length != list_length(plan->targetlist));
1070
1071 /*
1072 * Now prepare the child plans. We must apply prepare_sort_from_pathkeys
1073 * even to subplans that don't need an explicit sort, to make sure they
1074 * are returning the same sort key columns the MergeAppend expects.
1075 */
1076 foreach(subpaths, best_path->subpaths)
1077 {
1078 Path *subpath = (Path *) lfirst(subpaths);
1079 Plan *subplan;
1080 int numsortkeys;
1081 AttrNumber *sortColIdx;
1082 Oid *sortOperators;
1083 Oid *collations;
1084 bool *nullsFirst;
1085
1086 /* Build the child plan */
1087 /* Must insist that all children return the same tlist */
1088 subplan = create_plan_recurse(root, subpath, CP_EXACT_TLIST);
1089
1090 /* Compute sort column info, and adjust subplan's tlist as needed */
1091 subplan = prepare_sort_from_pathkeys(subplan, pathkeys,
1092 subpath->parent->relids,
1093 node->sortColIdx,
1094 false,
1095 &numsortkeys,
1096 &sortColIdx,
1097 &sortOperators,
1098 &collations,
1099 &nullsFirst);
1100
1101 /*
1102 * Check that we got the same sort key information. We just Assert
1103 * that the sortops match, since those depend only on the pathkeys;
1104 * but it seems like a good idea to check the sort column numbers
1105 * explicitly, to ensure the tlists really do match up.
1106 */
1107 Assert(numsortkeys == node->numCols);
1108 if (memcmp(sortColIdx, node->sortColIdx,
1109 numsortkeys * sizeof(AttrNumber)) != 0)
1110 elog(ERROR, "MergeAppend child's targetlist doesn't match MergeAppend");
1111 Assert(memcmp(sortOperators, node->sortOperators,
1112 numsortkeys * sizeof(Oid)) == 0);
1113 Assert(memcmp(collations, node->collations,
1114 numsortkeys * sizeof(Oid)) == 0);
1115 Assert(memcmp(nullsFirst, node->nullsFirst,
1116 numsortkeys * sizeof(bool)) == 0);
1117
1118 /* Now, insert a Sort node if subplan isn't sufficiently ordered */
1119 if (!pathkeys_contained_in(pathkeys, subpath->pathkeys))
1120 {
1121 Sort *sort = make_sort(subplan, numsortkeys,
1122 sortColIdx, sortOperators,
1123 collations, nullsFirst);
1124
1125 label_sort_with_costsize(root, sort, best_path->limit_tuples);
1126 subplan = (Plan *) sort;
1127 }
1128
1129 subplans = lappend(subplans, subplan);
1130 }
1131
1132 node->mergeplans = subplans;
1133
1134 /*
1135 * If prepare_sort_from_pathkeys added sort columns, but we were told to
1136 * produce either the exact tlist or a narrow tlist, we should get rid of
1137 * the sort columns again. We must inject a projection node to do so.
1138 */
1139 if (tlist_was_changed && (flags & (CP_EXACT_TLIST | CP_SMALL_TLIST)))
1140 {
1141 tlist = list_truncate(list_copy(plan->targetlist), orig_tlist_length);
1142 return inject_projection_plan(plan, tlist);
1143 }
1144 else
1145 return plan;
1146 }
1147
1148 /*
1149 * create_result_plan
1150 * Create a Result plan for 'best_path'.
1151 * This is only used for degenerate cases, such as a query with an empty
1152 * jointree.
1153 *
1154 * Returns a Plan node.
1155 */
1156 static Result *
create_result_plan(PlannerInfo * root,ResultPath * best_path)1157 create_result_plan(PlannerInfo *root, ResultPath *best_path)
1158 {
1159 Result *plan;
1160 List *tlist;
1161 List *quals;
1162
1163 tlist = build_path_tlist(root, &best_path->path);
1164
1165 /* best_path->quals is just bare clauses */
1166 quals = order_qual_clauses(root, best_path->quals);
1167
1168 plan = make_result(tlist, (Node *) quals, NULL);
1169
1170 copy_generic_path_info(&plan->plan, (Path *) best_path);
1171
1172 return plan;
1173 }
1174
1175 /*
1176 * create_material_plan
1177 * Create a Material plan for 'best_path' and (recursively) plans
1178 * for its subpaths.
1179 *
1180 * Returns a Plan node.
1181 */
1182 static Material *
create_material_plan(PlannerInfo * root,MaterialPath * best_path,int flags)1183 create_material_plan(PlannerInfo *root, MaterialPath *best_path, int flags)
1184 {
1185 Material *plan;
1186 Plan *subplan;
1187
1188 /*
1189 * We don't want any excess columns in the materialized tuples, so request
1190 * a smaller tlist. Otherwise, since Material doesn't project, tlist
1191 * requirements pass through.
1192 */
1193 subplan = create_plan_recurse(root, best_path->subpath,
1194 flags | CP_SMALL_TLIST);
1195
1196 plan = make_material(subplan);
1197
1198 copy_generic_path_info(&plan->plan, (Path *) best_path);
1199
1200 return plan;
1201 }
1202
1203 /*
1204 * create_unique_plan
1205 * Create a Unique plan for 'best_path' and (recursively) plans
1206 * for its subpaths.
1207 *
1208 * Returns a Plan node.
1209 */
1210 static Plan *
create_unique_plan(PlannerInfo * root,UniquePath * best_path,int flags)1211 create_unique_plan(PlannerInfo *root, UniquePath *best_path, int flags)
1212 {
1213 Plan *plan;
1214 Plan *subplan;
1215 List *in_operators;
1216 List *uniq_exprs;
1217 List *newtlist;
1218 int nextresno;
1219 bool newitems;
1220 int numGroupCols;
1221 AttrNumber *groupColIdx;
1222 int groupColPos;
1223 ListCell *l;
1224
1225 /* Unique doesn't project, so tlist requirements pass through */
1226 subplan = create_plan_recurse(root, best_path->subpath, flags);
1227
1228 /* Done if we don't need to do any actual unique-ifying */
1229 if (best_path->umethod == UNIQUE_PATH_NOOP)
1230 return subplan;
1231
1232 /*
1233 * As constructed, the subplan has a "flat" tlist containing just the Vars
1234 * needed here and at upper levels. The values we are supposed to
1235 * unique-ify may be expressions in these variables. We have to add any
1236 * such expressions to the subplan's tlist.
1237 *
1238 * The subplan may have a "physical" tlist if it is a simple scan plan. If
1239 * we're going to sort, this should be reduced to the regular tlist, so
1240 * that we don't sort more data than we need to. For hashing, the tlist
1241 * should be left as-is if we don't need to add any expressions; but if we
1242 * do have to add expressions, then a projection step will be needed at
1243 * runtime anyway, so we may as well remove unneeded items. Therefore
1244 * newtlist starts from build_path_tlist() not just a copy of the
1245 * subplan's tlist; and we don't install it into the subplan unless we are
1246 * sorting or stuff has to be added.
1247 */
1248 in_operators = best_path->in_operators;
1249 uniq_exprs = best_path->uniq_exprs;
1250
1251 /* initialize modified subplan tlist as just the "required" vars */
1252 newtlist = build_path_tlist(root, &best_path->path);
1253 nextresno = list_length(newtlist) + 1;
1254 newitems = false;
1255
1256 foreach(l, uniq_exprs)
1257 {
1258 Node *uniqexpr = lfirst(l);
1259 TargetEntry *tle;
1260
1261 tle = tlist_member(uniqexpr, newtlist);
1262 if (!tle)
1263 {
1264 tle = makeTargetEntry((Expr *) uniqexpr,
1265 nextresno,
1266 NULL,
1267 false);
1268 newtlist = lappend(newtlist, tle);
1269 nextresno++;
1270 newitems = true;
1271 }
1272 }
1273
1274 /* Use change_plan_targetlist in case we need to insert a Result node */
1275 if (newitems || best_path->umethod == UNIQUE_PATH_SORT)
1276 subplan = change_plan_targetlist(subplan, newtlist,
1277 best_path->path.parallel_safe);
1278
1279 /*
1280 * Build control information showing which subplan output columns are to
1281 * be examined by the grouping step. Unfortunately we can't merge this
1282 * with the previous loop, since we didn't then know which version of the
1283 * subplan tlist we'd end up using.
1284 */
1285 newtlist = subplan->targetlist;
1286 numGroupCols = list_length(uniq_exprs);
1287 groupColIdx = (AttrNumber *) palloc(numGroupCols * sizeof(AttrNumber));
1288
1289 groupColPos = 0;
1290 foreach(l, uniq_exprs)
1291 {
1292 Node *uniqexpr = lfirst(l);
1293 TargetEntry *tle;
1294
1295 tle = tlist_member(uniqexpr, newtlist);
1296 if (!tle) /* shouldn't happen */
1297 elog(ERROR, "failed to find unique expression in subplan tlist");
1298 groupColIdx[groupColPos++] = tle->resno;
1299 }
1300
1301 if (best_path->umethod == UNIQUE_PATH_HASH)
1302 {
1303 Oid *groupOperators;
1304
1305 /*
1306 * Get the hashable equality operators for the Agg node to use.
1307 * Normally these are the same as the IN clause operators, but if
1308 * those are cross-type operators then the equality operators are the
1309 * ones for the IN clause operators' RHS datatype.
1310 */
1311 groupOperators = (Oid *) palloc(numGroupCols * sizeof(Oid));
1312 groupColPos = 0;
1313 foreach(l, in_operators)
1314 {
1315 Oid in_oper = lfirst_oid(l);
1316 Oid eq_oper;
1317
1318 if (!get_compatible_hash_operators(in_oper, NULL, &eq_oper))
1319 elog(ERROR, "could not find compatible hash operator for operator %u",
1320 in_oper);
1321 groupOperators[groupColPos++] = eq_oper;
1322 }
1323
1324 /*
1325 * Since the Agg node is going to project anyway, we can give it the
1326 * minimum output tlist, without any stuff we might have added to the
1327 * subplan tlist.
1328 */
1329 plan = (Plan *) make_agg(build_path_tlist(root, &best_path->path),
1330 NIL,
1331 AGG_HASHED,
1332 AGGSPLIT_SIMPLE,
1333 numGroupCols,
1334 groupColIdx,
1335 groupOperators,
1336 NIL,
1337 NIL,
1338 best_path->path.rows,
1339 subplan);
1340 }
1341 else
1342 {
1343 List *sortList = NIL;
1344 Sort *sort;
1345
1346 /* Create an ORDER BY list to sort the input compatibly */
1347 groupColPos = 0;
1348 foreach(l, in_operators)
1349 {
1350 Oid in_oper = lfirst_oid(l);
1351 Oid sortop;
1352 Oid eqop;
1353 TargetEntry *tle;
1354 SortGroupClause *sortcl;
1355
1356 sortop = get_ordering_op_for_equality_op(in_oper, false);
1357 if (!OidIsValid(sortop)) /* shouldn't happen */
1358 elog(ERROR, "could not find ordering operator for equality operator %u",
1359 in_oper);
1360
1361 /*
1362 * The Unique node will need equality operators. Normally these
1363 * are the same as the IN clause operators, but if those are
1364 * cross-type operators then the equality operators are the ones
1365 * for the IN clause operators' RHS datatype.
1366 */
1367 eqop = get_equality_op_for_ordering_op(sortop, NULL);
1368 if (!OidIsValid(eqop)) /* shouldn't happen */
1369 elog(ERROR, "could not find equality operator for ordering operator %u",
1370 sortop);
1371
1372 tle = get_tle_by_resno(subplan->targetlist,
1373 groupColIdx[groupColPos]);
1374 Assert(tle != NULL);
1375
1376 sortcl = makeNode(SortGroupClause);
1377 sortcl->tleSortGroupRef = assignSortGroupRef(tle,
1378 subplan->targetlist);
1379 sortcl->eqop = eqop;
1380 sortcl->sortop = sortop;
1381 sortcl->nulls_first = false;
1382 sortcl->hashable = false; /* no need to make this accurate */
1383 sortList = lappend(sortList, sortcl);
1384 groupColPos++;
1385 }
1386 sort = make_sort_from_sortclauses(sortList, subplan);
1387 label_sort_with_costsize(root, sort, -1.0);
1388 plan = (Plan *) make_unique_from_sortclauses((Plan *) sort, sortList);
1389 }
1390
1391 /* Copy cost data from Path to Plan */
1392 copy_generic_path_info(plan, &best_path->path);
1393
1394 return plan;
1395 }
1396
1397 /*
1398 * create_gather_plan
1399 *
1400 * Create a Gather plan for 'best_path' and (recursively) plans
1401 * for its subpaths.
1402 */
1403 static Gather *
create_gather_plan(PlannerInfo * root,GatherPath * best_path)1404 create_gather_plan(PlannerInfo *root, GatherPath *best_path)
1405 {
1406 Gather *gather_plan;
1407 Plan *subplan;
1408 List *tlist;
1409
1410 /*
1411 * Although the Gather node can project, we prefer to push down such work
1412 * to its child node, so demand an exact tlist from the child.
1413 */
1414 subplan = create_plan_recurse(root, best_path->subpath, CP_EXACT_TLIST);
1415
1416 tlist = build_path_tlist(root, &best_path->path);
1417
1418 gather_plan = make_gather(tlist,
1419 NIL,
1420 best_path->num_workers,
1421 best_path->single_copy,
1422 subplan);
1423
1424 copy_generic_path_info(&gather_plan->plan, &best_path->path);
1425
1426 /* use parallel mode for parallel plans. */
1427 root->glob->parallelModeNeeded = true;
1428
1429 return gather_plan;
1430 }
1431
1432 /*
1433 * create_projection_plan
1434 *
1435 * Create a plan tree to do a projection step and (recursively) plans
1436 * for its subpaths. We may need a Result node for the projection,
1437 * but sometimes we can just let the subplan do the work.
1438 */
1439 static Plan *
create_projection_plan(PlannerInfo * root,ProjectionPath * best_path)1440 create_projection_plan(PlannerInfo *root, ProjectionPath *best_path)
1441 {
1442 Plan *plan;
1443 Plan *subplan;
1444 List *tlist;
1445
1446 /* Since we intend to project, we don't need to constrain child tlist */
1447 subplan = create_plan_recurse(root, best_path->subpath, 0);
1448
1449 tlist = build_path_tlist(root, &best_path->path);
1450
1451 /*
1452 * We might not really need a Result node here, either because the subplan
1453 * can project or because it's returning the right list of expressions
1454 * anyway. Usually create_projection_path will have detected that and set
1455 * dummypp if we don't need a Result; but its decision can't be final,
1456 * because some createplan.c routines change the tlists of their nodes.
1457 * (An example is that create_merge_append_plan might add resjunk sort
1458 * columns to a MergeAppend.) So we have to recheck here. If we do
1459 * arrive at a different answer than create_projection_path did, we'll
1460 * have made slightly wrong cost estimates; but label the plan with the
1461 * cost estimates we actually used, not "corrected" ones. (XXX this could
1462 * be cleaned up if we moved more of the sortcolumn setup logic into Path
1463 * creation, but that would add expense to creating Paths we might end up
1464 * not using.)
1465 */
1466 if (is_projection_capable_path(best_path->subpath) ||
1467 tlist_same_exprs(tlist, subplan->targetlist))
1468 {
1469 /* Don't need a separate Result, just assign tlist to subplan */
1470 plan = subplan;
1471 plan->targetlist = tlist;
1472
1473 /* Label plan with the estimated costs we actually used */
1474 plan->startup_cost = best_path->path.startup_cost;
1475 plan->total_cost = best_path->path.total_cost;
1476 plan->plan_rows = best_path->path.rows;
1477 plan->plan_width = best_path->path.pathtarget->width;
1478 /* ... but be careful not to munge subplan's parallel-aware flag */
1479 }
1480 else
1481 {
1482 /* We need a Result node */
1483 plan = (Plan *) make_result(tlist, NULL, subplan);
1484
1485 copy_generic_path_info(plan, (Path *) best_path);
1486 }
1487
1488 return plan;
1489 }
1490
1491 /*
1492 * inject_projection_plan
1493 * Insert a Result node to do a projection step.
1494 *
1495 * This is used in a few places where we decide on-the-fly that we need a
1496 * projection step as part of the tree generated for some Path node.
1497 * We should try to get rid of this in favor of doing it more honestly.
1498 */
1499 static Plan *
inject_projection_plan(Plan * subplan,List * tlist)1500 inject_projection_plan(Plan *subplan, List *tlist)
1501 {
1502 Plan *plan;
1503
1504 plan = (Plan *) make_result(tlist, NULL, subplan);
1505
1506 /*
1507 * In principle, we should charge tlist eval cost plus cpu_per_tuple per
1508 * row for the Result node. But the former has probably been factored in
1509 * already and the latter was not accounted for during Path construction,
1510 * so being formally correct might just make the EXPLAIN output look less
1511 * consistent not more so. Hence, just copy the subplan's cost.
1512 */
1513 copy_plan_costsize(plan, subplan);
1514
1515 return plan;
1516 }
1517
1518 /*
1519 * change_plan_targetlist
1520 * Externally available wrapper for inject_projection_plan.
1521 *
1522 * This is meant for use by FDW plan-generation functions, which might
1523 * want to adjust the tlist computed by some subplan tree. In general,
1524 * a Result node is needed to compute the new tlist, but we can optimize
1525 * some cases.
1526 *
1527 * In most cases, tlist_parallel_safe can just be passed as the parallel_safe
1528 * flag of the FDW's own Path node. (It's not actually used in this branch.)
1529 */
1530 Plan *
change_plan_targetlist(Plan * subplan,List * tlist,bool tlist_parallel_safe)1531 change_plan_targetlist(Plan *subplan, List *tlist, bool tlist_parallel_safe)
1532 {
1533 /*
1534 * If the top plan node can't do projections and its existing target list
1535 * isn't already what we need, we need to add a Result node to help it
1536 * along.
1537 */
1538 if (!is_projection_capable_plan(subplan) &&
1539 !tlist_same_exprs(tlist, subplan->targetlist))
1540 subplan = inject_projection_plan(subplan, tlist);
1541 else
1542 {
1543 /* Else we can just replace the plan node's tlist */
1544 subplan->targetlist = tlist;
1545 }
1546 return subplan;
1547 }
1548
1549 /*
1550 * create_sort_plan
1551 *
1552 * Create a Sort plan for 'best_path' and (recursively) plans
1553 * for its subpaths.
1554 */
1555 static Sort *
create_sort_plan(PlannerInfo * root,SortPath * best_path,int flags)1556 create_sort_plan(PlannerInfo *root, SortPath *best_path, int flags)
1557 {
1558 Sort *plan;
1559 Plan *subplan;
1560
1561 /*
1562 * We don't want any excess columns in the sorted tuples, so request a
1563 * smaller tlist. Otherwise, since Sort doesn't project, tlist
1564 * requirements pass through.
1565 */
1566 subplan = create_plan_recurse(root, best_path->subpath,
1567 flags | CP_SMALL_TLIST);
1568
1569 plan = make_sort_from_pathkeys(subplan, best_path->path.pathkeys);
1570
1571 copy_generic_path_info(&plan->plan, (Path *) best_path);
1572
1573 return plan;
1574 }
1575
1576 /*
1577 * create_group_plan
1578 *
1579 * Create a Group plan for 'best_path' and (recursively) plans
1580 * for its subpaths.
1581 */
1582 static Group *
create_group_plan(PlannerInfo * root,GroupPath * best_path)1583 create_group_plan(PlannerInfo *root, GroupPath *best_path)
1584 {
1585 Group *plan;
1586 Plan *subplan;
1587 List *tlist;
1588 List *quals;
1589
1590 /*
1591 * Group can project, so no need to be terribly picky about child tlist,
1592 * but we do need grouping columns to be available
1593 */
1594 subplan = create_plan_recurse(root, best_path->subpath, CP_LABEL_TLIST);
1595
1596 tlist = build_path_tlist(root, &best_path->path);
1597
1598 quals = order_qual_clauses(root, best_path->qual);
1599
1600 plan = make_group(tlist,
1601 quals,
1602 list_length(best_path->groupClause),
1603 extract_grouping_cols(best_path->groupClause,
1604 subplan->targetlist),
1605 extract_grouping_ops(best_path->groupClause),
1606 subplan);
1607
1608 copy_generic_path_info(&plan->plan, (Path *) best_path);
1609
1610 return plan;
1611 }
1612
1613 /*
1614 * create_upper_unique_plan
1615 *
1616 * Create a Unique plan for 'best_path' and (recursively) plans
1617 * for its subpaths.
1618 */
1619 static Unique *
create_upper_unique_plan(PlannerInfo * root,UpperUniquePath * best_path,int flags)1620 create_upper_unique_plan(PlannerInfo *root, UpperUniquePath *best_path, int flags)
1621 {
1622 Unique *plan;
1623 Plan *subplan;
1624
1625 /*
1626 * Unique doesn't project, so tlist requirements pass through; moreover we
1627 * need grouping columns to be labeled.
1628 */
1629 subplan = create_plan_recurse(root, best_path->subpath,
1630 flags | CP_LABEL_TLIST);
1631
1632 plan = make_unique_from_pathkeys(subplan,
1633 best_path->path.pathkeys,
1634 best_path->numkeys);
1635
1636 copy_generic_path_info(&plan->plan, (Path *) best_path);
1637
1638 return plan;
1639 }
1640
1641 /*
1642 * create_agg_plan
1643 *
1644 * Create an Agg plan for 'best_path' and (recursively) plans
1645 * for its subpaths.
1646 */
1647 static Agg *
create_agg_plan(PlannerInfo * root,AggPath * best_path)1648 create_agg_plan(PlannerInfo *root, AggPath *best_path)
1649 {
1650 Agg *plan;
1651 Plan *subplan;
1652 List *tlist;
1653 List *quals;
1654
1655 /*
1656 * Agg can project, so no need to be terribly picky about child tlist, but
1657 * we do need grouping columns to be available
1658 */
1659 subplan = create_plan_recurse(root, best_path->subpath, CP_LABEL_TLIST);
1660
1661 tlist = build_path_tlist(root, &best_path->path);
1662
1663 quals = order_qual_clauses(root, best_path->qual);
1664
1665 plan = make_agg(tlist, quals,
1666 best_path->aggstrategy,
1667 best_path->aggsplit,
1668 list_length(best_path->groupClause),
1669 extract_grouping_cols(best_path->groupClause,
1670 subplan->targetlist),
1671 extract_grouping_ops(best_path->groupClause),
1672 NIL,
1673 NIL,
1674 best_path->numGroups,
1675 subplan);
1676
1677 copy_generic_path_info(&plan->plan, (Path *) best_path);
1678
1679 return plan;
1680 }
1681
1682 /*
1683 * Given a groupclause for a collection of grouping sets, produce the
1684 * corresponding groupColIdx.
1685 *
1686 * root->grouping_map maps the tleSortGroupRef to the actual column position in
1687 * the input tuple. So we get the ref from the entries in the groupclause and
1688 * look them up there.
1689 */
1690 static AttrNumber *
remap_groupColIdx(PlannerInfo * root,List * groupClause)1691 remap_groupColIdx(PlannerInfo *root, List *groupClause)
1692 {
1693 AttrNumber *grouping_map = root->grouping_map;
1694 AttrNumber *new_grpColIdx;
1695 ListCell *lc;
1696 int i;
1697
1698 Assert(grouping_map);
1699
1700 new_grpColIdx = palloc0(sizeof(AttrNumber) * list_length(groupClause));
1701
1702 i = 0;
1703 foreach(lc, groupClause)
1704 {
1705 SortGroupClause *clause = lfirst(lc);
1706
1707 new_grpColIdx[i++] = grouping_map[clause->tleSortGroupRef];
1708 }
1709
1710 return new_grpColIdx;
1711 }
1712
1713 /*
1714 * create_groupingsets_plan
1715 * Create a plan for 'best_path' and (recursively) plans
1716 * for its subpaths.
1717 *
1718 * What we emit is an Agg plan with some vestigial Agg and Sort nodes
1719 * hanging off the side. The top Agg implements the last grouping set
1720 * specified in the GroupingSetsPath, and any additional grouping sets
1721 * each give rise to a subsidiary Agg and Sort node in the top Agg's
1722 * "chain" list. These nodes don't participate in the plan directly,
1723 * but they are a convenient way to represent the required data for
1724 * the extra steps.
1725 *
1726 * Returns a Plan node.
1727 */
1728 static Plan *
create_groupingsets_plan(PlannerInfo * root,GroupingSetsPath * best_path)1729 create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path)
1730 {
1731 Agg *plan;
1732 Plan *subplan;
1733 List *rollup_groupclauses = best_path->rollup_groupclauses;
1734 List *rollup_lists = best_path->rollup_lists;
1735 AttrNumber *grouping_map;
1736 int maxref;
1737 List *chain;
1738 ListCell *lc,
1739 *lc2;
1740
1741 /* Shouldn't get here without grouping sets */
1742 Assert(root->parse->groupingSets);
1743 Assert(rollup_lists != NIL);
1744 Assert(list_length(rollup_lists) == list_length(rollup_groupclauses));
1745
1746 /*
1747 * Agg can project, so no need to be terribly picky about child tlist, but
1748 * we do need grouping columns to be available
1749 */
1750 subplan = create_plan_recurse(root, best_path->subpath, CP_LABEL_TLIST);
1751
1752 /*
1753 * Compute the mapping from tleSortGroupRef to column index in the child's
1754 * tlist. First, identify max SortGroupRef in groupClause, for array
1755 * sizing.
1756 */
1757 maxref = 0;
1758 foreach(lc, root->parse->groupClause)
1759 {
1760 SortGroupClause *gc = (SortGroupClause *) lfirst(lc);
1761
1762 if (gc->tleSortGroupRef > maxref)
1763 maxref = gc->tleSortGroupRef;
1764 }
1765
1766 grouping_map = (AttrNumber *) palloc0((maxref + 1) * sizeof(AttrNumber));
1767
1768 /* Now look up the column numbers in the child's tlist */
1769 foreach(lc, root->parse->groupClause)
1770 {
1771 SortGroupClause *gc = (SortGroupClause *) lfirst(lc);
1772 TargetEntry *tle = get_sortgroupclause_tle(gc, subplan->targetlist);
1773
1774 grouping_map[gc->tleSortGroupRef] = tle->resno;
1775 }
1776
1777 /*
1778 * During setrefs.c, we'll need the grouping_map to fix up the cols lists
1779 * in GroupingFunc nodes. Save it for setrefs.c to use.
1780 *
1781 * This doesn't work if we're in an inheritance subtree (see notes in
1782 * create_modifytable_plan). Fortunately we can't be because there would
1783 * never be grouping in an UPDATE/DELETE; but let's Assert that.
1784 */
1785 Assert(!root->hasInheritedTarget);
1786 Assert(root->grouping_map == NULL);
1787 root->grouping_map = grouping_map;
1788
1789 /*
1790 * Generate the side nodes that describe the other sort and group
1791 * operations besides the top one. Note that we don't worry about putting
1792 * accurate cost estimates in the side nodes; only the topmost Agg node's
1793 * costs will be shown by EXPLAIN.
1794 */
1795 chain = NIL;
1796 if (list_length(rollup_groupclauses) > 1)
1797 {
1798 forboth(lc, rollup_groupclauses, lc2, rollup_lists)
1799 {
1800 List *groupClause = (List *) lfirst(lc);
1801 List *gsets = (List *) lfirst(lc2);
1802 AttrNumber *new_grpColIdx;
1803 Plan *sort_plan;
1804 Plan *agg_plan;
1805
1806 /* We want to iterate over all but the last rollup list elements */
1807 if (lnext(lc) == NULL)
1808 break;
1809
1810 new_grpColIdx = remap_groupColIdx(root, groupClause);
1811
1812 sort_plan = (Plan *)
1813 make_sort_from_groupcols(groupClause,
1814 new_grpColIdx,
1815 subplan);
1816
1817 agg_plan = (Plan *) make_agg(NIL,
1818 NIL,
1819 AGG_SORTED,
1820 AGGSPLIT_SIMPLE,
1821 list_length((List *) linitial(gsets)),
1822 new_grpColIdx,
1823 extract_grouping_ops(groupClause),
1824 gsets,
1825 NIL,
1826 0, /* numGroups not needed */
1827 sort_plan);
1828
1829 /*
1830 * Nuke stuff we don't need to avoid bloating debug output.
1831 */
1832 sort_plan->targetlist = NIL;
1833 sort_plan->lefttree = NULL;
1834
1835 chain = lappend(chain, agg_plan);
1836 }
1837 }
1838
1839 /*
1840 * Now make the final Agg node
1841 */
1842 {
1843 List *groupClause = (List *) llast(rollup_groupclauses);
1844 List *gsets = (List *) llast(rollup_lists);
1845 AttrNumber *top_grpColIdx;
1846 int numGroupCols;
1847
1848 top_grpColIdx = remap_groupColIdx(root, groupClause);
1849
1850 numGroupCols = list_length((List *) linitial(gsets));
1851
1852 plan = make_agg(build_path_tlist(root, &best_path->path),
1853 best_path->qual,
1854 (numGroupCols > 0) ? AGG_SORTED : AGG_PLAIN,
1855 AGGSPLIT_SIMPLE,
1856 numGroupCols,
1857 top_grpColIdx,
1858 extract_grouping_ops(groupClause),
1859 gsets,
1860 chain,
1861 0, /* numGroups not needed */
1862 subplan);
1863
1864 /* Copy cost data from Path to Plan */
1865 copy_generic_path_info(&plan->plan, &best_path->path);
1866 }
1867
1868 return (Plan *) plan;
1869 }
1870
1871 /*
1872 * create_minmaxagg_plan
1873 *
1874 * Create a Result plan for 'best_path' and (recursively) plans
1875 * for its subpaths.
1876 */
1877 static Result *
create_minmaxagg_plan(PlannerInfo * root,MinMaxAggPath * best_path)1878 create_minmaxagg_plan(PlannerInfo *root, MinMaxAggPath *best_path)
1879 {
1880 Result *plan;
1881 List *tlist;
1882 ListCell *lc;
1883
1884 /* Prepare an InitPlan for each aggregate's subquery. */
1885 foreach(lc, best_path->mmaggregates)
1886 {
1887 MinMaxAggInfo *mminfo = (MinMaxAggInfo *) lfirst(lc);
1888 PlannerInfo *subroot = mminfo->subroot;
1889 Query *subparse = subroot->parse;
1890 Plan *plan;
1891
1892 /*
1893 * Generate the plan for the subquery. We already have a Path, but we
1894 * have to convert it to a Plan and attach a LIMIT node above it.
1895 * Since we are entering a different planner context (subroot),
1896 * recurse to create_plan not create_plan_recurse.
1897 */
1898 plan = create_plan(subroot, mminfo->path);
1899
1900 plan = (Plan *) make_limit(plan,
1901 subparse->limitOffset,
1902 subparse->limitCount);
1903
1904 /* Must apply correct cost/width data to Limit node */
1905 plan->startup_cost = mminfo->path->startup_cost;
1906 plan->total_cost = mminfo->pathcost;
1907 plan->plan_rows = 1;
1908 plan->plan_width = mminfo->path->pathtarget->width;
1909 plan->parallel_aware = false;
1910
1911 /* Convert the plan into an InitPlan in the outer query. */
1912 SS_make_initplan_from_plan(root, subroot, plan, mminfo->param);
1913 }
1914
1915 /* Generate the output plan --- basically just a Result */
1916 tlist = build_path_tlist(root, &best_path->path);
1917
1918 plan = make_result(tlist, (Node *) best_path->quals, NULL);
1919
1920 copy_generic_path_info(&plan->plan, (Path *) best_path);
1921
1922 /*
1923 * During setrefs.c, we'll need to replace references to the Agg nodes
1924 * with InitPlan output params. (We can't just do that locally in the
1925 * MinMaxAgg node, because path nodes above here may have Agg references
1926 * as well.) Save the mmaggregates list to tell setrefs.c to do that.
1927 *
1928 * This doesn't work if we're in an inheritance subtree (see notes in
1929 * create_modifytable_plan). Fortunately we can't be because there would
1930 * never be aggregates in an UPDATE/DELETE; but let's Assert that.
1931 */
1932 Assert(!root->hasInheritedTarget);
1933 Assert(root->minmax_aggs == NIL);
1934 root->minmax_aggs = best_path->mmaggregates;
1935
1936 return plan;
1937 }
1938
1939 /*
1940 * create_windowagg_plan
1941 *
1942 * Create a WindowAgg plan for 'best_path' and (recursively) plans
1943 * for its subpaths.
1944 */
1945 static WindowAgg *
create_windowagg_plan(PlannerInfo * root,WindowAggPath * best_path)1946 create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
1947 {
1948 WindowAgg *plan;
1949 WindowClause *wc = best_path->winclause;
1950 Plan *subplan;
1951 List *tlist;
1952 int numsortkeys;
1953 AttrNumber *sortColIdx;
1954 Oid *sortOperators;
1955 Oid *collations;
1956 bool *nullsFirst;
1957 int partNumCols;
1958 AttrNumber *partColIdx;
1959 Oid *partOperators;
1960 int ordNumCols;
1961 AttrNumber *ordColIdx;
1962 Oid *ordOperators;
1963
1964 /*
1965 * Choice of tlist here is motivated by the fact that WindowAgg will be
1966 * storing the input rows of window frames in a tuplestore; it therefore
1967 * behooves us to request a small tlist to avoid wasting space. We do of
1968 * course need grouping columns to be available.
1969 */
1970 subplan = create_plan_recurse(root, best_path->subpath,
1971 CP_LABEL_TLIST | CP_SMALL_TLIST);
1972
1973 tlist = build_path_tlist(root, &best_path->path);
1974
1975 /*
1976 * We shouldn't need to actually sort, but it's convenient to use
1977 * prepare_sort_from_pathkeys to identify the input's sort columns.
1978 */
1979 subplan = prepare_sort_from_pathkeys(subplan,
1980 best_path->winpathkeys,
1981 NULL,
1982 NULL,
1983 false,
1984 &numsortkeys,
1985 &sortColIdx,
1986 &sortOperators,
1987 &collations,
1988 &nullsFirst);
1989
1990 /* Now deconstruct that into partition and ordering portions */
1991 get_column_info_for_window(root,
1992 wc,
1993 subplan->targetlist,
1994 numsortkeys,
1995 sortColIdx,
1996 &partNumCols,
1997 &partColIdx,
1998 &partOperators,
1999 &ordNumCols,
2000 &ordColIdx,
2001 &ordOperators);
2002
2003 /* And finally we can make the WindowAgg node */
2004 plan = make_windowagg(tlist,
2005 wc->winref,
2006 partNumCols,
2007 partColIdx,
2008 partOperators,
2009 ordNumCols,
2010 ordColIdx,
2011 ordOperators,
2012 wc->frameOptions,
2013 wc->startOffset,
2014 wc->endOffset,
2015 subplan);
2016
2017 copy_generic_path_info(&plan->plan, (Path *) best_path);
2018
2019 return plan;
2020 }
2021
2022 /*
2023 * get_column_info_for_window
2024 * Get the partitioning/ordering column numbers and equality operators
2025 * for a WindowAgg node.
2026 *
2027 * This depends on the behavior of planner.c's make_pathkeys_for_window!
2028 *
2029 * We are given the target WindowClause and an array of the input column
2030 * numbers associated with the resulting pathkeys. In the easy case, there
2031 * are the same number of pathkey columns as partitioning + ordering columns
2032 * and we just have to copy some data around. However, it's possible that
2033 * some of the original partitioning + ordering columns were eliminated as
2034 * redundant during the transformation to pathkeys. (This can happen even
2035 * though the parser gets rid of obvious duplicates. A typical scenario is a
2036 * window specification "PARTITION BY x ORDER BY y" coupled with a clause
2037 * "WHERE x = y" that causes the two sort columns to be recognized as
2038 * redundant.) In that unusual case, we have to work a lot harder to
2039 * determine which keys are significant.
2040 *
2041 * The method used here is a bit brute-force: add the sort columns to a list
2042 * one at a time and note when the resulting pathkey list gets longer. But
2043 * it's a sufficiently uncommon case that a faster way doesn't seem worth
2044 * the amount of code refactoring that'd be needed.
2045 */
2046 static void
get_column_info_for_window(PlannerInfo * root,WindowClause * wc,List * tlist,int numSortCols,AttrNumber * sortColIdx,int * partNumCols,AttrNumber ** partColIdx,Oid ** partOperators,int * ordNumCols,AttrNumber ** ordColIdx,Oid ** ordOperators)2047 get_column_info_for_window(PlannerInfo *root, WindowClause *wc, List *tlist,
2048 int numSortCols, AttrNumber *sortColIdx,
2049 int *partNumCols,
2050 AttrNumber **partColIdx,
2051 Oid **partOperators,
2052 int *ordNumCols,
2053 AttrNumber **ordColIdx,
2054 Oid **ordOperators)
2055 {
2056 int numPart = list_length(wc->partitionClause);
2057 int numOrder = list_length(wc->orderClause);
2058
2059 if (numSortCols == numPart + numOrder)
2060 {
2061 /* easy case */
2062 *partNumCols = numPart;
2063 *partColIdx = sortColIdx;
2064 *partOperators = extract_grouping_ops(wc->partitionClause);
2065 *ordNumCols = numOrder;
2066 *ordColIdx = sortColIdx + numPart;
2067 *ordOperators = extract_grouping_ops(wc->orderClause);
2068 }
2069 else
2070 {
2071 List *sortclauses;
2072 List *pathkeys;
2073 int scidx;
2074 ListCell *lc;
2075
2076 /* first, allocate what's certainly enough space for the arrays */
2077 *partNumCols = 0;
2078 *partColIdx = (AttrNumber *) palloc(numPart * sizeof(AttrNumber));
2079 *partOperators = (Oid *) palloc(numPart * sizeof(Oid));
2080 *ordNumCols = 0;
2081 *ordColIdx = (AttrNumber *) palloc(numOrder * sizeof(AttrNumber));
2082 *ordOperators = (Oid *) palloc(numOrder * sizeof(Oid));
2083 sortclauses = NIL;
2084 pathkeys = NIL;
2085 scidx = 0;
2086 foreach(lc, wc->partitionClause)
2087 {
2088 SortGroupClause *sgc = (SortGroupClause *) lfirst(lc);
2089 List *new_pathkeys;
2090
2091 sortclauses = lappend(sortclauses, sgc);
2092 new_pathkeys = make_pathkeys_for_sortclauses(root,
2093 sortclauses,
2094 tlist);
2095 if (list_length(new_pathkeys) > list_length(pathkeys))
2096 {
2097 /* this sort clause is actually significant */
2098 (*partColIdx)[*partNumCols] = sortColIdx[scidx++];
2099 (*partOperators)[*partNumCols] = sgc->eqop;
2100 (*partNumCols)++;
2101 pathkeys = new_pathkeys;
2102 }
2103 }
2104 foreach(lc, wc->orderClause)
2105 {
2106 SortGroupClause *sgc = (SortGroupClause *) lfirst(lc);
2107 List *new_pathkeys;
2108
2109 sortclauses = lappend(sortclauses, sgc);
2110 new_pathkeys = make_pathkeys_for_sortclauses(root,
2111 sortclauses,
2112 tlist);
2113 if (list_length(new_pathkeys) > list_length(pathkeys))
2114 {
2115 /* this sort clause is actually significant */
2116 (*ordColIdx)[*ordNumCols] = sortColIdx[scidx++];
2117 (*ordOperators)[*ordNumCols] = sgc->eqop;
2118 (*ordNumCols)++;
2119 pathkeys = new_pathkeys;
2120 }
2121 }
2122 /* complain if we didn't eat exactly the right number of sort cols */
2123 if (scidx != numSortCols)
2124 elog(ERROR, "failed to deconstruct sort operators into partitioning/ordering operators");
2125 }
2126 }
2127
2128 /*
2129 * create_setop_plan
2130 *
2131 * Create a SetOp plan for 'best_path' and (recursively) plans
2132 * for its subpaths.
2133 */
2134 static SetOp *
create_setop_plan(PlannerInfo * root,SetOpPath * best_path,int flags)2135 create_setop_plan(PlannerInfo *root, SetOpPath *best_path, int flags)
2136 {
2137 SetOp *plan;
2138 Plan *subplan;
2139 long numGroups;
2140
2141 /*
2142 * SetOp doesn't project, so tlist requirements pass through; moreover we
2143 * need grouping columns to be labeled.
2144 */
2145 subplan = create_plan_recurse(root, best_path->subpath,
2146 flags | CP_LABEL_TLIST);
2147
2148 /* Convert numGroups to long int --- but 'ware overflow! */
2149 numGroups = (long) Min(best_path->numGroups, (double) LONG_MAX);
2150
2151 plan = make_setop(best_path->cmd,
2152 best_path->strategy,
2153 subplan,
2154 best_path->distinctList,
2155 best_path->flagColIdx,
2156 best_path->firstFlag,
2157 numGroups);
2158
2159 copy_generic_path_info(&plan->plan, (Path *) best_path);
2160
2161 return plan;
2162 }
2163
2164 /*
2165 * create_recursiveunion_plan
2166 *
2167 * Create a RecursiveUnion plan for 'best_path' and (recursively) plans
2168 * for its subpaths.
2169 */
2170 static RecursiveUnion *
create_recursiveunion_plan(PlannerInfo * root,RecursiveUnionPath * best_path)2171 create_recursiveunion_plan(PlannerInfo *root, RecursiveUnionPath *best_path)
2172 {
2173 RecursiveUnion *plan;
2174 Plan *leftplan;
2175 Plan *rightplan;
2176 List *tlist;
2177 long numGroups;
2178
2179 /* Need both children to produce same tlist, so force it */
2180 leftplan = create_plan_recurse(root, best_path->leftpath, CP_EXACT_TLIST);
2181 rightplan = create_plan_recurse(root, best_path->rightpath, CP_EXACT_TLIST);
2182
2183 tlist = build_path_tlist(root, &best_path->path);
2184
2185 /* Convert numGroups to long int --- but 'ware overflow! */
2186 numGroups = (long) Min(best_path->numGroups, (double) LONG_MAX);
2187
2188 plan = make_recursive_union(tlist,
2189 leftplan,
2190 rightplan,
2191 best_path->wtParam,
2192 best_path->distinctList,
2193 numGroups);
2194
2195 copy_generic_path_info(&plan->plan, (Path *) best_path);
2196
2197 return plan;
2198 }
2199
2200 /*
2201 * create_lockrows_plan
2202 *
2203 * Create a LockRows plan for 'best_path' and (recursively) plans
2204 * for its subpaths.
2205 */
2206 static LockRows *
create_lockrows_plan(PlannerInfo * root,LockRowsPath * best_path,int flags)2207 create_lockrows_plan(PlannerInfo *root, LockRowsPath *best_path,
2208 int flags)
2209 {
2210 LockRows *plan;
2211 Plan *subplan;
2212
2213 /* LockRows doesn't project, so tlist requirements pass through */
2214 subplan = create_plan_recurse(root, best_path->subpath, flags);
2215
2216 plan = make_lockrows(subplan, best_path->rowMarks, best_path->epqParam);
2217
2218 copy_generic_path_info(&plan->plan, (Path *) best_path);
2219
2220 return plan;
2221 }
2222
2223 /*
2224 * create_modifytable_plan
2225 * Create a ModifyTable plan for 'best_path'.
2226 *
2227 * Returns a Plan node.
2228 */
2229 static ModifyTable *
create_modifytable_plan(PlannerInfo * root,ModifyTablePath * best_path)2230 create_modifytable_plan(PlannerInfo *root, ModifyTablePath *best_path)
2231 {
2232 ModifyTable *plan;
2233 List *subplans = NIL;
2234 ListCell *subpaths,
2235 *subroots;
2236
2237 /* Build the plan for each input path */
2238 forboth(subpaths, best_path->subpaths,
2239 subroots, best_path->subroots)
2240 {
2241 Path *subpath = (Path *) lfirst(subpaths);
2242 PlannerInfo *subroot = (PlannerInfo *) lfirst(subroots);
2243 Plan *subplan;
2244
2245 /*
2246 * In an inherited UPDATE/DELETE, reference the per-child modified
2247 * subroot while creating Plans from Paths for the child rel. This is
2248 * a kluge, but otherwise it's too hard to ensure that Plan creation
2249 * functions (particularly in FDWs) don't depend on the contents of
2250 * "root" matching what they saw at Path creation time. The main
2251 * downside is that creation functions for Plans that might appear
2252 * below a ModifyTable cannot expect to modify the contents of "root"
2253 * and have it "stick" for subsequent processing such as setrefs.c.
2254 * That's not great, but it seems better than the alternative.
2255 */
2256 subplan = create_plan_recurse(subroot, subpath, CP_EXACT_TLIST);
2257
2258 /* Transfer resname/resjunk labeling, too, to keep executor happy */
2259 apply_tlist_labeling(subplan->targetlist, subroot->processed_tlist);
2260
2261 subplans = lappend(subplans, subplan);
2262 }
2263
2264 plan = make_modifytable(root,
2265 best_path->operation,
2266 best_path->canSetTag,
2267 best_path->nominalRelation,
2268 best_path->resultRelations,
2269 subplans,
2270 best_path->withCheckOptionLists,
2271 best_path->returningLists,
2272 best_path->rowMarks,
2273 best_path->onconflict,
2274 best_path->epqParam);
2275
2276 copy_generic_path_info(&plan->plan, &best_path->path);
2277
2278 return plan;
2279 }
2280
2281 /*
2282 * create_limit_plan
2283 *
2284 * Create a Limit plan for 'best_path' and (recursively) plans
2285 * for its subpaths.
2286 */
2287 static Limit *
create_limit_plan(PlannerInfo * root,LimitPath * best_path,int flags)2288 create_limit_plan(PlannerInfo *root, LimitPath *best_path, int flags)
2289 {
2290 Limit *plan;
2291 Plan *subplan;
2292
2293 /* Limit doesn't project, so tlist requirements pass through */
2294 subplan = create_plan_recurse(root, best_path->subpath, flags);
2295
2296 plan = make_limit(subplan,
2297 best_path->limitOffset,
2298 best_path->limitCount);
2299
2300 copy_generic_path_info(&plan->plan, (Path *) best_path);
2301
2302 return plan;
2303 }
2304
2305
2306 /*****************************************************************************
2307 *
2308 * BASE-RELATION SCAN METHODS
2309 *
2310 *****************************************************************************/
2311
2312
2313 /*
2314 * create_seqscan_plan
2315 * Returns a seqscan plan for the base relation scanned by 'best_path'
2316 * with restriction clauses 'scan_clauses' and targetlist 'tlist'.
2317 */
2318 static SeqScan *
create_seqscan_plan(PlannerInfo * root,Path * best_path,List * tlist,List * scan_clauses)2319 create_seqscan_plan(PlannerInfo *root, Path *best_path,
2320 List *tlist, List *scan_clauses)
2321 {
2322 SeqScan *scan_plan;
2323 Index scan_relid = best_path->parent->relid;
2324
2325 /* it should be a base rel... */
2326 Assert(scan_relid > 0);
2327 Assert(best_path->parent->rtekind == RTE_RELATION);
2328
2329 /* Sort clauses into best execution order */
2330 scan_clauses = order_qual_clauses(root, scan_clauses);
2331
2332 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
2333 scan_clauses = extract_actual_clauses(scan_clauses, false);
2334
2335 /* Replace any outer-relation variables with nestloop params */
2336 if (best_path->param_info)
2337 {
2338 scan_clauses = (List *)
2339 replace_nestloop_params(root, (Node *) scan_clauses);
2340 }
2341
2342 scan_plan = make_seqscan(tlist,
2343 scan_clauses,
2344 scan_relid);
2345
2346 copy_generic_path_info(&scan_plan->plan, best_path);
2347
2348 return scan_plan;
2349 }
2350
2351 /*
2352 * create_samplescan_plan
2353 * Returns a samplescan plan for the base relation scanned by 'best_path'
2354 * with restriction clauses 'scan_clauses' and targetlist 'tlist'.
2355 */
2356 static SampleScan *
create_samplescan_plan(PlannerInfo * root,Path * best_path,List * tlist,List * scan_clauses)2357 create_samplescan_plan(PlannerInfo *root, Path *best_path,
2358 List *tlist, List *scan_clauses)
2359 {
2360 SampleScan *scan_plan;
2361 Index scan_relid = best_path->parent->relid;
2362 RangeTblEntry *rte;
2363 TableSampleClause *tsc;
2364
2365 /* it should be a base rel with a tablesample clause... */
2366 Assert(scan_relid > 0);
2367 rte = planner_rt_fetch(scan_relid, root);
2368 Assert(rte->rtekind == RTE_RELATION);
2369 tsc = rte->tablesample;
2370 Assert(tsc != NULL);
2371
2372 /* Sort clauses into best execution order */
2373 scan_clauses = order_qual_clauses(root, scan_clauses);
2374
2375 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
2376 scan_clauses = extract_actual_clauses(scan_clauses, false);
2377
2378 /* Replace any outer-relation variables with nestloop params */
2379 if (best_path->param_info)
2380 {
2381 scan_clauses = (List *)
2382 replace_nestloop_params(root, (Node *) scan_clauses);
2383 tsc = (TableSampleClause *)
2384 replace_nestloop_params(root, (Node *) tsc);
2385 }
2386
2387 scan_plan = make_samplescan(tlist,
2388 scan_clauses,
2389 scan_relid,
2390 tsc);
2391
2392 copy_generic_path_info(&scan_plan->scan.plan, best_path);
2393
2394 return scan_plan;
2395 }
2396
2397 /*
2398 * create_indexscan_plan
2399 * Returns an indexscan plan for the base relation scanned by 'best_path'
2400 * with restriction clauses 'scan_clauses' and targetlist 'tlist'.
2401 *
2402 * We use this for both plain IndexScans and IndexOnlyScans, because the
2403 * qual preprocessing work is the same for both. Note that the caller tells
2404 * us which to build --- we don't look at best_path->path.pathtype, because
2405 * create_bitmap_subplan needs to be able to override the prior decision.
2406 */
2407 static Scan *
create_indexscan_plan(PlannerInfo * root,IndexPath * best_path,List * tlist,List * scan_clauses,bool indexonly)2408 create_indexscan_plan(PlannerInfo *root,
2409 IndexPath *best_path,
2410 List *tlist,
2411 List *scan_clauses,
2412 bool indexonly)
2413 {
2414 Scan *scan_plan;
2415 List *indexquals = best_path->indexquals;
2416 List *indexorderbys = best_path->indexorderbys;
2417 Index baserelid = best_path->path.parent->relid;
2418 Oid indexoid = best_path->indexinfo->indexoid;
2419 List *qpqual;
2420 List *stripped_indexquals;
2421 List *fixed_indexquals;
2422 List *fixed_indexorderbys;
2423 List *indexorderbyops = NIL;
2424 ListCell *l;
2425
2426 /* it should be a base rel... */
2427 Assert(baserelid > 0);
2428 Assert(best_path->path.parent->rtekind == RTE_RELATION);
2429
2430 /*
2431 * Build "stripped" indexquals structure (no RestrictInfos) to pass to
2432 * executor as indexqualorig
2433 */
2434 stripped_indexquals = get_actual_clauses(indexquals);
2435
2436 /*
2437 * The executor needs a copy with the indexkey on the left of each clause
2438 * and with index Vars substituted for table ones.
2439 */
2440 fixed_indexquals = fix_indexqual_references(root, best_path);
2441
2442 /*
2443 * Likewise fix up index attr references in the ORDER BY expressions.
2444 */
2445 fixed_indexorderbys = fix_indexorderby_references(root, best_path);
2446
2447 /*
2448 * The qpqual list must contain all restrictions not automatically handled
2449 * by the index, other than pseudoconstant clauses which will be handled
2450 * by a separate gating plan node. All the predicates in the indexquals
2451 * will be checked (either by the index itself, or by nodeIndexscan.c),
2452 * but if there are any "special" operators involved then they must be
2453 * included in qpqual. The upshot is that qpqual must contain
2454 * scan_clauses minus whatever appears in indexquals.
2455 *
2456 * In normal cases simple pointer equality checks will be enough to spot
2457 * duplicate RestrictInfos, so we try that first.
2458 *
2459 * Another common case is that a scan_clauses entry is generated from the
2460 * same EquivalenceClass as some indexqual, and is therefore redundant
2461 * with it, though not equal. (This happens when indxpath.c prefers a
2462 * different derived equality than what generate_join_implied_equalities
2463 * picked for a parameterized scan's ppi_clauses.)
2464 *
2465 * In some situations (particularly with OR'd index conditions) we may
2466 * have scan_clauses that are not equal to, but are logically implied by,
2467 * the index quals; so we also try a predicate_implied_by() check to see
2468 * if we can discard quals that way. (predicate_implied_by assumes its
2469 * first input contains only immutable functions, so we have to check
2470 * that.)
2471 *
2472 * Note: if you change this bit of code you should also look at
2473 * extract_nonindex_conditions() in costsize.c.
2474 */
2475 qpqual = NIL;
2476 foreach(l, scan_clauses)
2477 {
2478 RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
2479
2480 Assert(IsA(rinfo, RestrictInfo));
2481 if (rinfo->pseudoconstant)
2482 continue; /* we may drop pseudoconstants here */
2483 if (list_member_ptr(indexquals, rinfo))
2484 continue; /* simple duplicate */
2485 if (is_redundant_derived_clause(rinfo, indexquals))
2486 continue; /* derived from same EquivalenceClass */
2487 if (!contain_mutable_functions((Node *) rinfo->clause) &&
2488 predicate_implied_by(list_make1(rinfo->clause), indexquals))
2489 continue; /* provably implied by indexquals */
2490 qpqual = lappend(qpqual, rinfo);
2491 }
2492
2493 /* Sort clauses into best execution order */
2494 qpqual = order_qual_clauses(root, qpqual);
2495
2496 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
2497 qpqual = extract_actual_clauses(qpqual, false);
2498
2499 /*
2500 * We have to replace any outer-relation variables with nestloop params in
2501 * the indexqualorig, qpqual, and indexorderbyorig expressions. A bit
2502 * annoying to have to do this separately from the processing in
2503 * fix_indexqual_references --- rethink this when generalizing the inner
2504 * indexscan support. But note we can't really do this earlier because
2505 * it'd break the comparisons to predicates above ... (or would it? Those
2506 * wouldn't have outer refs)
2507 */
2508 if (best_path->path.param_info)
2509 {
2510 stripped_indexquals = (List *)
2511 replace_nestloop_params(root, (Node *) stripped_indexquals);
2512 qpqual = (List *)
2513 replace_nestloop_params(root, (Node *) qpqual);
2514 indexorderbys = (List *)
2515 replace_nestloop_params(root, (Node *) indexorderbys);
2516 }
2517
2518 /*
2519 * If there are ORDER BY expressions, look up the sort operators for their
2520 * result datatypes.
2521 */
2522 if (indexorderbys)
2523 {
2524 ListCell *pathkeyCell,
2525 *exprCell;
2526
2527 /*
2528 * PathKey contains OID of the btree opfamily we're sorting by, but
2529 * that's not quite enough because we need the expression's datatype
2530 * to look up the sort operator in the operator family.
2531 */
2532 Assert(list_length(best_path->path.pathkeys) == list_length(indexorderbys));
2533 forboth(pathkeyCell, best_path->path.pathkeys, exprCell, indexorderbys)
2534 {
2535 PathKey *pathkey = (PathKey *) lfirst(pathkeyCell);
2536 Node *expr = (Node *) lfirst(exprCell);
2537 Oid exprtype = exprType(expr);
2538 Oid sortop;
2539
2540 /* Get sort operator from opfamily */
2541 sortop = get_opfamily_member(pathkey->pk_opfamily,
2542 exprtype,
2543 exprtype,
2544 pathkey->pk_strategy);
2545 if (!OidIsValid(sortop))
2546 elog(ERROR, "failed to find sort operator for ORDER BY expression");
2547 indexorderbyops = lappend_oid(indexorderbyops, sortop);
2548 }
2549 }
2550
2551 /* Finally ready to build the plan node */
2552 if (indexonly)
2553 scan_plan = (Scan *) make_indexonlyscan(tlist,
2554 qpqual,
2555 baserelid,
2556 indexoid,
2557 fixed_indexquals,
2558 fixed_indexorderbys,
2559 best_path->indexinfo->indextlist,
2560 best_path->indexscandir);
2561 else
2562 scan_plan = (Scan *) make_indexscan(tlist,
2563 qpqual,
2564 baserelid,
2565 indexoid,
2566 fixed_indexquals,
2567 stripped_indexquals,
2568 fixed_indexorderbys,
2569 indexorderbys,
2570 indexorderbyops,
2571 best_path->indexscandir);
2572
2573 copy_generic_path_info(&scan_plan->plan, &best_path->path);
2574
2575 return scan_plan;
2576 }
2577
2578 /*
2579 * create_bitmap_scan_plan
2580 * Returns a bitmap scan plan for the base relation scanned by 'best_path'
2581 * with restriction clauses 'scan_clauses' and targetlist 'tlist'.
2582 */
2583 static BitmapHeapScan *
create_bitmap_scan_plan(PlannerInfo * root,BitmapHeapPath * best_path,List * tlist,List * scan_clauses)2584 create_bitmap_scan_plan(PlannerInfo *root,
2585 BitmapHeapPath *best_path,
2586 List *tlist,
2587 List *scan_clauses)
2588 {
2589 Index baserelid = best_path->path.parent->relid;
2590 Plan *bitmapqualplan;
2591 List *bitmapqualorig;
2592 List *indexquals;
2593 List *indexECs;
2594 List *qpqual;
2595 ListCell *l;
2596 BitmapHeapScan *scan_plan;
2597
2598 /* it should be a base rel... */
2599 Assert(baserelid > 0);
2600 Assert(best_path->path.parent->rtekind == RTE_RELATION);
2601
2602 /* Process the bitmapqual tree into a Plan tree and qual lists */
2603 bitmapqualplan = create_bitmap_subplan(root, best_path->bitmapqual,
2604 &bitmapqualorig, &indexquals,
2605 &indexECs);
2606
2607 /*
2608 * The qpqual list must contain all restrictions not automatically handled
2609 * by the index, other than pseudoconstant clauses which will be handled
2610 * by a separate gating plan node. All the predicates in the indexquals
2611 * will be checked (either by the index itself, or by
2612 * nodeBitmapHeapscan.c), but if there are any "special" operators
2613 * involved then they must be added to qpqual. The upshot is that qpqual
2614 * must contain scan_clauses minus whatever appears in indexquals.
2615 *
2616 * This loop is similar to the comparable code in create_indexscan_plan(),
2617 * but with some differences because it has to compare the scan clauses to
2618 * stripped (no RestrictInfos) indexquals. See comments there for more
2619 * info.
2620 *
2621 * In normal cases simple equal() checks will be enough to spot duplicate
2622 * clauses, so we try that first. We next see if the scan clause is
2623 * redundant with any top-level indexqual by virtue of being generated
2624 * from the same EC. After that, try predicate_implied_by().
2625 *
2626 * Unlike create_indexscan_plan(), the predicate_implied_by() test here is
2627 * useful for getting rid of qpquals that are implied by index predicates,
2628 * because the predicate conditions are included in the "indexquals"
2629 * returned by create_bitmap_subplan(). Bitmap scans have to do it that
2630 * way because predicate conditions need to be rechecked if the scan
2631 * becomes lossy, so they have to be included in bitmapqualorig.
2632 */
2633 qpqual = NIL;
2634 foreach(l, scan_clauses)
2635 {
2636 RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
2637 Node *clause = (Node *) rinfo->clause;
2638
2639 Assert(IsA(rinfo, RestrictInfo));
2640 if (rinfo->pseudoconstant)
2641 continue; /* we may drop pseudoconstants here */
2642 if (list_member(indexquals, clause))
2643 continue; /* simple duplicate */
2644 if (rinfo->parent_ec && list_member_ptr(indexECs, rinfo->parent_ec))
2645 continue; /* derived from same EquivalenceClass */
2646 if (!contain_mutable_functions(clause) &&
2647 predicate_implied_by(list_make1(clause), indexquals))
2648 continue; /* provably implied by indexquals */
2649 qpqual = lappend(qpqual, rinfo);
2650 }
2651
2652 /* Sort clauses into best execution order */
2653 qpqual = order_qual_clauses(root, qpqual);
2654
2655 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
2656 qpqual = extract_actual_clauses(qpqual, false);
2657
2658 /*
2659 * When dealing with special operators, we will at this point have
2660 * duplicate clauses in qpqual and bitmapqualorig. We may as well drop
2661 * 'em from bitmapqualorig, since there's no point in making the tests
2662 * twice.
2663 */
2664 bitmapqualorig = list_difference_ptr(bitmapqualorig, qpqual);
2665
2666 /*
2667 * We have to replace any outer-relation variables with nestloop params in
2668 * the qpqual and bitmapqualorig expressions. (This was already done for
2669 * expressions attached to plan nodes in the bitmapqualplan tree.)
2670 */
2671 if (best_path->path.param_info)
2672 {
2673 qpqual = (List *)
2674 replace_nestloop_params(root, (Node *) qpqual);
2675 bitmapqualorig = (List *)
2676 replace_nestloop_params(root, (Node *) bitmapqualorig);
2677 }
2678
2679 /* Finally ready to build the plan node */
2680 scan_plan = make_bitmap_heapscan(tlist,
2681 qpqual,
2682 bitmapqualplan,
2683 bitmapqualorig,
2684 baserelid);
2685
2686 copy_generic_path_info(&scan_plan->scan.plan, &best_path->path);
2687
2688 return scan_plan;
2689 }
2690
2691 /*
2692 * Given a bitmapqual tree, generate the Plan tree that implements it
2693 *
2694 * As byproducts, we also return in *qual and *indexqual the qual lists
2695 * (in implicit-AND form, without RestrictInfos) describing the original index
2696 * conditions and the generated indexqual conditions. (These are the same in
2697 * simple cases, but when special index operators are involved, the former
2698 * list includes the special conditions while the latter includes the actual
2699 * indexable conditions derived from them.) Both lists include partial-index
2700 * predicates, because we have to recheck predicates as well as index
2701 * conditions if the bitmap scan becomes lossy.
2702 *
2703 * In addition, we return a list of EquivalenceClass pointers for all the
2704 * top-level indexquals that were possibly-redundantly derived from ECs.
2705 * This allows removal of scan_clauses that are redundant with such quals.
2706 * (We do not attempt to detect such redundancies for quals that are within
2707 * OR subtrees. This could be done in a less hacky way if we returned the
2708 * indexquals in RestrictInfo form, but that would be slower and still pretty
2709 * messy, since we'd have to build new RestrictInfos in many cases.)
2710 */
2711 static Plan *
create_bitmap_subplan(PlannerInfo * root,Path * bitmapqual,List ** qual,List ** indexqual,List ** indexECs)2712 create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
2713 List **qual, List **indexqual, List **indexECs)
2714 {
2715 Plan *plan;
2716
2717 if (IsA(bitmapqual, BitmapAndPath))
2718 {
2719 BitmapAndPath *apath = (BitmapAndPath *) bitmapqual;
2720 List *subplans = NIL;
2721 List *subquals = NIL;
2722 List *subindexquals = NIL;
2723 List *subindexECs = NIL;
2724 ListCell *l;
2725
2726 /*
2727 * There may well be redundant quals among the subplans, since a
2728 * top-level WHERE qual might have gotten used to form several
2729 * different index quals. We don't try exceedingly hard to eliminate
2730 * redundancies, but we do eliminate obvious duplicates by using
2731 * list_concat_unique.
2732 */
2733 foreach(l, apath->bitmapquals)
2734 {
2735 Plan *subplan;
2736 List *subqual;
2737 List *subindexqual;
2738 List *subindexEC;
2739
2740 subplan = create_bitmap_subplan(root, (Path *) lfirst(l),
2741 &subqual, &subindexqual,
2742 &subindexEC);
2743 subplans = lappend(subplans, subplan);
2744 subquals = list_concat_unique(subquals, subqual);
2745 subindexquals = list_concat_unique(subindexquals, subindexqual);
2746 /* Duplicates in indexECs aren't worth getting rid of */
2747 subindexECs = list_concat(subindexECs, subindexEC);
2748 }
2749 plan = (Plan *) make_bitmap_and(subplans);
2750 plan->startup_cost = apath->path.startup_cost;
2751 plan->total_cost = apath->path.total_cost;
2752 plan->plan_rows =
2753 clamp_row_est(apath->bitmapselectivity * apath->path.parent->tuples);
2754 plan->plan_width = 0; /* meaningless */
2755 plan->parallel_aware = false;
2756 *qual = subquals;
2757 *indexqual = subindexquals;
2758 *indexECs = subindexECs;
2759 }
2760 else if (IsA(bitmapqual, BitmapOrPath))
2761 {
2762 BitmapOrPath *opath = (BitmapOrPath *) bitmapqual;
2763 List *subplans = NIL;
2764 List *subquals = NIL;
2765 List *subindexquals = NIL;
2766 bool const_true_subqual = false;
2767 bool const_true_subindexqual = false;
2768 ListCell *l;
2769
2770 /*
2771 * Here, we only detect qual-free subplans. A qual-free subplan would
2772 * cause us to generate "... OR true ..." which we may as well reduce
2773 * to just "true". We do not try to eliminate redundant subclauses
2774 * because (a) it's not as likely as in the AND case, and (b) we might
2775 * well be working with hundreds or even thousands of OR conditions,
2776 * perhaps from a long IN list. The performance of list_append_unique
2777 * would be unacceptable.
2778 */
2779 foreach(l, opath->bitmapquals)
2780 {
2781 Plan *subplan;
2782 List *subqual;
2783 List *subindexqual;
2784 List *subindexEC;
2785
2786 subplan = create_bitmap_subplan(root, (Path *) lfirst(l),
2787 &subqual, &subindexqual,
2788 &subindexEC);
2789 subplans = lappend(subplans, subplan);
2790 if (subqual == NIL)
2791 const_true_subqual = true;
2792 else if (!const_true_subqual)
2793 subquals = lappend(subquals,
2794 make_ands_explicit(subqual));
2795 if (subindexqual == NIL)
2796 const_true_subindexqual = true;
2797 else if (!const_true_subindexqual)
2798 subindexquals = lappend(subindexquals,
2799 make_ands_explicit(subindexqual));
2800 }
2801
2802 /*
2803 * In the presence of ScalarArrayOpExpr quals, we might have built
2804 * BitmapOrPaths with just one subpath; don't add an OR step.
2805 */
2806 if (list_length(subplans) == 1)
2807 {
2808 plan = (Plan *) linitial(subplans);
2809 }
2810 else
2811 {
2812 plan = (Plan *) make_bitmap_or(subplans);
2813 plan->startup_cost = opath->path.startup_cost;
2814 plan->total_cost = opath->path.total_cost;
2815 plan->plan_rows =
2816 clamp_row_est(opath->bitmapselectivity * opath->path.parent->tuples);
2817 plan->plan_width = 0; /* meaningless */
2818 plan->parallel_aware = false;
2819 }
2820
2821 /*
2822 * If there were constant-TRUE subquals, the OR reduces to constant
2823 * TRUE. Also, avoid generating one-element ORs, which could happen
2824 * due to redundancy elimination or ScalarArrayOpExpr quals.
2825 */
2826 if (const_true_subqual)
2827 *qual = NIL;
2828 else if (list_length(subquals) <= 1)
2829 *qual = subquals;
2830 else
2831 *qual = list_make1(make_orclause(subquals));
2832 if (const_true_subindexqual)
2833 *indexqual = NIL;
2834 else if (list_length(subindexquals) <= 1)
2835 *indexqual = subindexquals;
2836 else
2837 *indexqual = list_make1(make_orclause(subindexquals));
2838 *indexECs = NIL;
2839 }
2840 else if (IsA(bitmapqual, IndexPath))
2841 {
2842 IndexPath *ipath = (IndexPath *) bitmapqual;
2843 IndexScan *iscan;
2844 List *subindexECs;
2845 ListCell *l;
2846
2847 /* Use the regular indexscan plan build machinery... */
2848 iscan = (IndexScan *) create_indexscan_plan(root, ipath,
2849 NIL, NIL, false);
2850 Assert(IsA(iscan, IndexScan));
2851 /* then convert to a bitmap indexscan */
2852 plan = (Plan *) make_bitmap_indexscan(iscan->scan.scanrelid,
2853 iscan->indexid,
2854 iscan->indexqual,
2855 iscan->indexqualorig);
2856 /* and set its cost/width fields appropriately */
2857 plan->startup_cost = 0.0;
2858 plan->total_cost = ipath->indextotalcost;
2859 plan->plan_rows =
2860 clamp_row_est(ipath->indexselectivity * ipath->path.parent->tuples);
2861 plan->plan_width = 0; /* meaningless */
2862 plan->parallel_aware = false;
2863 *qual = get_actual_clauses(ipath->indexclauses);
2864 *indexqual = get_actual_clauses(ipath->indexquals);
2865 foreach(l, ipath->indexinfo->indpred)
2866 {
2867 Expr *pred = (Expr *) lfirst(l);
2868
2869 /*
2870 * We know that the index predicate must have been implied by the
2871 * query condition as a whole, but it may or may not be implied by
2872 * the conditions that got pushed into the bitmapqual. Avoid
2873 * generating redundant conditions.
2874 */
2875 if (!predicate_implied_by(list_make1(pred), ipath->indexclauses))
2876 {
2877 *qual = lappend(*qual, pred);
2878 *indexqual = lappend(*indexqual, pred);
2879 }
2880 }
2881 subindexECs = NIL;
2882 foreach(l, ipath->indexquals)
2883 {
2884 RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
2885
2886 if (rinfo->parent_ec)
2887 subindexECs = lappend(subindexECs, rinfo->parent_ec);
2888 }
2889 *indexECs = subindexECs;
2890 }
2891 else
2892 {
2893 elog(ERROR, "unrecognized node type: %d", nodeTag(bitmapqual));
2894 plan = NULL; /* keep compiler quiet */
2895 }
2896
2897 return plan;
2898 }
2899
2900 /*
2901 * create_tidscan_plan
2902 * Returns a tidscan plan for the base relation scanned by 'best_path'
2903 * with restriction clauses 'scan_clauses' and targetlist 'tlist'.
2904 */
2905 static TidScan *
create_tidscan_plan(PlannerInfo * root,TidPath * best_path,List * tlist,List * scan_clauses)2906 create_tidscan_plan(PlannerInfo *root, TidPath *best_path,
2907 List *tlist, List *scan_clauses)
2908 {
2909 TidScan *scan_plan;
2910 Index scan_relid = best_path->path.parent->relid;
2911 List *tidquals = best_path->tidquals;
2912 List *ortidquals;
2913
2914 /* it should be a base rel... */
2915 Assert(scan_relid > 0);
2916 Assert(best_path->path.parent->rtekind == RTE_RELATION);
2917
2918 /* Sort clauses into best execution order */
2919 scan_clauses = order_qual_clauses(root, scan_clauses);
2920
2921 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
2922 scan_clauses = extract_actual_clauses(scan_clauses, false);
2923
2924 /* Replace any outer-relation variables with nestloop params */
2925 if (best_path->path.param_info)
2926 {
2927 tidquals = (List *)
2928 replace_nestloop_params(root, (Node *) tidquals);
2929 scan_clauses = (List *)
2930 replace_nestloop_params(root, (Node *) scan_clauses);
2931 }
2932
2933 /*
2934 * Remove any clauses that are TID quals. This is a bit tricky since the
2935 * tidquals list has implicit OR semantics.
2936 */
2937 ortidquals = tidquals;
2938 if (list_length(ortidquals) > 1)
2939 ortidquals = list_make1(make_orclause(ortidquals));
2940 scan_clauses = list_difference(scan_clauses, ortidquals);
2941
2942 scan_plan = make_tidscan(tlist,
2943 scan_clauses,
2944 scan_relid,
2945 tidquals);
2946
2947 copy_generic_path_info(&scan_plan->scan.plan, &best_path->path);
2948
2949 return scan_plan;
2950 }
2951
2952 /*
2953 * create_subqueryscan_plan
2954 * Returns a subqueryscan plan for the base relation scanned by 'best_path'
2955 * with restriction clauses 'scan_clauses' and targetlist 'tlist'.
2956 */
2957 static SubqueryScan *
create_subqueryscan_plan(PlannerInfo * root,SubqueryScanPath * best_path,List * tlist,List * scan_clauses)2958 create_subqueryscan_plan(PlannerInfo *root, SubqueryScanPath *best_path,
2959 List *tlist, List *scan_clauses)
2960 {
2961 SubqueryScan *scan_plan;
2962 RelOptInfo *rel = best_path->path.parent;
2963 Index scan_relid = rel->relid;
2964 Plan *subplan;
2965
2966 /* it should be a subquery base rel... */
2967 Assert(scan_relid > 0);
2968 Assert(rel->rtekind == RTE_SUBQUERY);
2969
2970 /*
2971 * Recursively create Plan from Path for subquery. Since we are entering
2972 * a different planner context (subroot), recurse to create_plan not
2973 * create_plan_recurse.
2974 */
2975 subplan = create_plan(rel->subroot, best_path->subpath);
2976
2977 /* Sort clauses into best execution order */
2978 scan_clauses = order_qual_clauses(root, scan_clauses);
2979
2980 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
2981 scan_clauses = extract_actual_clauses(scan_clauses, false);
2982
2983 /* Replace any outer-relation variables with nestloop params */
2984 if (best_path->path.param_info)
2985 {
2986 scan_clauses = (List *)
2987 replace_nestloop_params(root, (Node *) scan_clauses);
2988 process_subquery_nestloop_params(root,
2989 rel->subplan_params);
2990 }
2991
2992 scan_plan = make_subqueryscan(tlist,
2993 scan_clauses,
2994 scan_relid,
2995 subplan);
2996
2997 copy_generic_path_info(&scan_plan->scan.plan, &best_path->path);
2998
2999 return scan_plan;
3000 }
3001
3002 /*
3003 * create_functionscan_plan
3004 * Returns a functionscan plan for the base relation scanned by 'best_path'
3005 * with restriction clauses 'scan_clauses' and targetlist 'tlist'.
3006 */
3007 static FunctionScan *
create_functionscan_plan(PlannerInfo * root,Path * best_path,List * tlist,List * scan_clauses)3008 create_functionscan_plan(PlannerInfo *root, Path *best_path,
3009 List *tlist, List *scan_clauses)
3010 {
3011 FunctionScan *scan_plan;
3012 Index scan_relid = best_path->parent->relid;
3013 RangeTblEntry *rte;
3014 List *functions;
3015
3016 /* it should be a function base rel... */
3017 Assert(scan_relid > 0);
3018 rte = planner_rt_fetch(scan_relid, root);
3019 Assert(rte->rtekind == RTE_FUNCTION);
3020 functions = rte->functions;
3021
3022 /* Sort clauses into best execution order */
3023 scan_clauses = order_qual_clauses(root, scan_clauses);
3024
3025 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3026 scan_clauses = extract_actual_clauses(scan_clauses, false);
3027
3028 /* Replace any outer-relation variables with nestloop params */
3029 if (best_path->param_info)
3030 {
3031 scan_clauses = (List *)
3032 replace_nestloop_params(root, (Node *) scan_clauses);
3033 /* The function expressions could contain nestloop params, too */
3034 functions = (List *) replace_nestloop_params(root, (Node *) functions);
3035 }
3036
3037 scan_plan = make_functionscan(tlist, scan_clauses, scan_relid,
3038 functions, rte->funcordinality);
3039
3040 copy_generic_path_info(&scan_plan->scan.plan, best_path);
3041
3042 return scan_plan;
3043 }
3044
3045 /*
3046 * create_valuesscan_plan
3047 * Returns a valuesscan plan for the base relation scanned by 'best_path'
3048 * with restriction clauses 'scan_clauses' and targetlist 'tlist'.
3049 */
3050 static ValuesScan *
create_valuesscan_plan(PlannerInfo * root,Path * best_path,List * tlist,List * scan_clauses)3051 create_valuesscan_plan(PlannerInfo *root, Path *best_path,
3052 List *tlist, List *scan_clauses)
3053 {
3054 ValuesScan *scan_plan;
3055 Index scan_relid = best_path->parent->relid;
3056 RangeTblEntry *rte;
3057 List *values_lists;
3058
3059 /* it should be a values base rel... */
3060 Assert(scan_relid > 0);
3061 rte = planner_rt_fetch(scan_relid, root);
3062 Assert(rte->rtekind == RTE_VALUES);
3063 values_lists = rte->values_lists;
3064
3065 /* Sort clauses into best execution order */
3066 scan_clauses = order_qual_clauses(root, scan_clauses);
3067
3068 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3069 scan_clauses = extract_actual_clauses(scan_clauses, false);
3070
3071 /* Replace any outer-relation variables with nestloop params */
3072 if (best_path->param_info)
3073 {
3074 scan_clauses = (List *)
3075 replace_nestloop_params(root, (Node *) scan_clauses);
3076 /* The values lists could contain nestloop params, too */
3077 values_lists = (List *)
3078 replace_nestloop_params(root, (Node *) values_lists);
3079 }
3080
3081 scan_plan = make_valuesscan(tlist, scan_clauses, scan_relid,
3082 values_lists);
3083
3084 copy_generic_path_info(&scan_plan->scan.plan, best_path);
3085
3086 return scan_plan;
3087 }
3088
3089 /*
3090 * create_ctescan_plan
3091 * Returns a ctescan plan for the base relation scanned by 'best_path'
3092 * with restriction clauses 'scan_clauses' and targetlist 'tlist'.
3093 */
3094 static CteScan *
create_ctescan_plan(PlannerInfo * root,Path * best_path,List * tlist,List * scan_clauses)3095 create_ctescan_plan(PlannerInfo *root, Path *best_path,
3096 List *tlist, List *scan_clauses)
3097 {
3098 CteScan *scan_plan;
3099 Index scan_relid = best_path->parent->relid;
3100 RangeTblEntry *rte;
3101 SubPlan *ctesplan = NULL;
3102 int plan_id;
3103 int cte_param_id;
3104 PlannerInfo *cteroot;
3105 Index levelsup;
3106 int ndx;
3107 ListCell *lc;
3108
3109 Assert(scan_relid > 0);
3110 rte = planner_rt_fetch(scan_relid, root);
3111 Assert(rte->rtekind == RTE_CTE);
3112 Assert(!rte->self_reference);
3113
3114 /*
3115 * Find the referenced CTE, and locate the SubPlan previously made for it.
3116 */
3117 levelsup = rte->ctelevelsup;
3118 cteroot = root;
3119 while (levelsup-- > 0)
3120 {
3121 cteroot = cteroot->parent_root;
3122 if (!cteroot) /* shouldn't happen */
3123 elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename);
3124 }
3125
3126 /*
3127 * Note: cte_plan_ids can be shorter than cteList, if we are still working
3128 * on planning the CTEs (ie, this is a side-reference from another CTE).
3129 * So we mustn't use forboth here.
3130 */
3131 ndx = 0;
3132 foreach(lc, cteroot->parse->cteList)
3133 {
3134 CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
3135
3136 if (strcmp(cte->ctename, rte->ctename) == 0)
3137 break;
3138 ndx++;
3139 }
3140 if (lc == NULL) /* shouldn't happen */
3141 elog(ERROR, "could not find CTE \"%s\"", rte->ctename);
3142 if (ndx >= list_length(cteroot->cte_plan_ids))
3143 elog(ERROR, "could not find plan for CTE \"%s\"", rte->ctename);
3144 plan_id = list_nth_int(cteroot->cte_plan_ids, ndx);
3145 Assert(plan_id > 0);
3146 foreach(lc, cteroot->init_plans)
3147 {
3148 ctesplan = (SubPlan *) lfirst(lc);
3149 if (ctesplan->plan_id == plan_id)
3150 break;
3151 }
3152 if (lc == NULL) /* shouldn't happen */
3153 elog(ERROR, "could not find plan for CTE \"%s\"", rte->ctename);
3154
3155 /*
3156 * We need the CTE param ID, which is the sole member of the SubPlan's
3157 * setParam list.
3158 */
3159 cte_param_id = linitial_int(ctesplan->setParam);
3160
3161 /* Sort clauses into best execution order */
3162 scan_clauses = order_qual_clauses(root, scan_clauses);
3163
3164 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3165 scan_clauses = extract_actual_clauses(scan_clauses, false);
3166
3167 /* Replace any outer-relation variables with nestloop params */
3168 if (best_path->param_info)
3169 {
3170 scan_clauses = (List *)
3171 replace_nestloop_params(root, (Node *) scan_clauses);
3172 }
3173
3174 scan_plan = make_ctescan(tlist, scan_clauses, scan_relid,
3175 plan_id, cte_param_id);
3176
3177 copy_generic_path_info(&scan_plan->scan.plan, best_path);
3178
3179 return scan_plan;
3180 }
3181
3182 /*
3183 * create_worktablescan_plan
3184 * Returns a worktablescan plan for the base relation scanned by 'best_path'
3185 * with restriction clauses 'scan_clauses' and targetlist 'tlist'.
3186 */
3187 static WorkTableScan *
create_worktablescan_plan(PlannerInfo * root,Path * best_path,List * tlist,List * scan_clauses)3188 create_worktablescan_plan(PlannerInfo *root, Path *best_path,
3189 List *tlist, List *scan_clauses)
3190 {
3191 WorkTableScan *scan_plan;
3192 Index scan_relid = best_path->parent->relid;
3193 RangeTblEntry *rte;
3194 Index levelsup;
3195 PlannerInfo *cteroot;
3196
3197 Assert(scan_relid > 0);
3198 rte = planner_rt_fetch(scan_relid, root);
3199 Assert(rte->rtekind == RTE_CTE);
3200 Assert(rte->self_reference);
3201
3202 /*
3203 * We need to find the worktable param ID, which is in the plan level
3204 * that's processing the recursive UNION, which is one level *below* where
3205 * the CTE comes from.
3206 */
3207 levelsup = rte->ctelevelsup;
3208 if (levelsup == 0) /* shouldn't happen */
3209 elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename);
3210 levelsup--;
3211 cteroot = root;
3212 while (levelsup-- > 0)
3213 {
3214 cteroot = cteroot->parent_root;
3215 if (!cteroot) /* shouldn't happen */
3216 elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename);
3217 }
3218 if (cteroot->wt_param_id < 0) /* shouldn't happen */
3219 elog(ERROR, "could not find param ID for CTE \"%s\"", rte->ctename);
3220
3221 /* Sort clauses into best execution order */
3222 scan_clauses = order_qual_clauses(root, scan_clauses);
3223
3224 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3225 scan_clauses = extract_actual_clauses(scan_clauses, false);
3226
3227 /* Replace any outer-relation variables with nestloop params */
3228 if (best_path->param_info)
3229 {
3230 scan_clauses = (List *)
3231 replace_nestloop_params(root, (Node *) scan_clauses);
3232 }
3233
3234 scan_plan = make_worktablescan(tlist, scan_clauses, scan_relid,
3235 cteroot->wt_param_id);
3236
3237 copy_generic_path_info(&scan_plan->scan.plan, best_path);
3238
3239 return scan_plan;
3240 }
3241
3242 /*
3243 * create_foreignscan_plan
3244 * Returns a foreignscan plan for the relation scanned by 'best_path'
3245 * with restriction clauses 'scan_clauses' and targetlist 'tlist'.
3246 */
3247 static ForeignScan *
create_foreignscan_plan(PlannerInfo * root,ForeignPath * best_path,List * tlist,List * scan_clauses)3248 create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path,
3249 List *tlist, List *scan_clauses)
3250 {
3251 ForeignScan *scan_plan;
3252 RelOptInfo *rel = best_path->path.parent;
3253 Index scan_relid = rel->relid;
3254 Oid rel_oid = InvalidOid;
3255 Plan *outer_plan = NULL;
3256
3257 Assert(rel->fdwroutine != NULL);
3258
3259 /* transform the child path if any */
3260 if (best_path->fdw_outerpath)
3261 outer_plan = create_plan_recurse(root, best_path->fdw_outerpath,
3262 CP_EXACT_TLIST);
3263
3264 /*
3265 * If we're scanning a base relation, fetch its OID. (Irrelevant if
3266 * scanning a join relation.)
3267 */
3268 if (scan_relid > 0)
3269 {
3270 RangeTblEntry *rte;
3271
3272 Assert(rel->rtekind == RTE_RELATION);
3273 rte = planner_rt_fetch(scan_relid, root);
3274 Assert(rte->rtekind == RTE_RELATION);
3275 rel_oid = rte->relid;
3276 }
3277
3278 /*
3279 * Sort clauses into best execution order. We do this first since the FDW
3280 * might have more info than we do and wish to adjust the ordering.
3281 */
3282 scan_clauses = order_qual_clauses(root, scan_clauses);
3283
3284 /*
3285 * Let the FDW perform its processing on the restriction clauses and
3286 * generate the plan node. Note that the FDW might remove restriction
3287 * clauses that it intends to execute remotely, or even add more (if it
3288 * has selected some join clauses for remote use but also wants them
3289 * rechecked locally).
3290 */
3291 scan_plan = rel->fdwroutine->GetForeignPlan(root, rel, rel_oid,
3292 best_path,
3293 tlist, scan_clauses,
3294 outer_plan);
3295
3296 /* Copy cost data from Path to Plan; no need to make FDW do this */
3297 copy_generic_path_info(&scan_plan->scan.plan, &best_path->path);
3298
3299 /* Copy foreign server OID; likewise, no need to make FDW do this */
3300 scan_plan->fs_server = rel->serverid;
3301
3302 /* Likewise, copy the relids that are represented by this foreign scan */
3303 scan_plan->fs_relids = best_path->path.parent->relids;
3304
3305 /*
3306 * If this is a foreign join, and to make it valid to push down we had to
3307 * assume that the current user is the same as some user explicitly named
3308 * in the query, mark the finished plan as depending on the current user.
3309 */
3310 if (rel->useridiscurrent)
3311 root->glob->dependsOnRole = true;
3312
3313 /*
3314 * Replace any outer-relation variables with nestloop params in the qual,
3315 * fdw_exprs and fdw_recheck_quals expressions. We do this last so that
3316 * the FDW doesn't have to be involved. (Note that parts of fdw_exprs or
3317 * fdw_recheck_quals could have come from join clauses, so doing this
3318 * beforehand on the scan_clauses wouldn't work.) We assume
3319 * fdw_scan_tlist contains no such variables.
3320 */
3321 if (best_path->path.param_info)
3322 {
3323 scan_plan->scan.plan.qual = (List *)
3324 replace_nestloop_params(root, (Node *) scan_plan->scan.plan.qual);
3325 scan_plan->fdw_exprs = (List *)
3326 replace_nestloop_params(root, (Node *) scan_plan->fdw_exprs);
3327 scan_plan->fdw_recheck_quals = (List *)
3328 replace_nestloop_params(root,
3329 (Node *) scan_plan->fdw_recheck_quals);
3330 }
3331
3332 /*
3333 * If rel is a base relation, detect whether any system columns are
3334 * requested from the rel. (If rel is a join relation, rel->relid will be
3335 * 0, but there can be no Var with relid 0 in the rel's targetlist or the
3336 * restriction clauses, so we skip this in that case. Note that any such
3337 * columns in base relations that were joined are assumed to be contained
3338 * in fdw_scan_tlist.) This is a bit of a kluge and might go away
3339 * someday, so we intentionally leave it out of the API presented to FDWs.
3340 */
3341 scan_plan->fsSystemCol = false;
3342 if (scan_relid > 0)
3343 {
3344 Bitmapset *attrs_used = NULL;
3345 ListCell *lc;
3346 int i;
3347
3348 /*
3349 * First, examine all the attributes needed for joins or final output.
3350 * Note: we must look at rel's targetlist, not the attr_needed data,
3351 * because attr_needed isn't computed for inheritance child rels.
3352 */
3353 pull_varattnos((Node *) rel->reltarget->exprs, scan_relid, &attrs_used);
3354
3355 /* Add all the attributes used by restriction clauses. */
3356 foreach(lc, rel->baserestrictinfo)
3357 {
3358 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
3359
3360 pull_varattnos((Node *) rinfo->clause, scan_relid, &attrs_used);
3361 }
3362
3363 /* Now, are any system columns requested from rel? */
3364 for (i = FirstLowInvalidHeapAttributeNumber + 1; i < 0; i++)
3365 {
3366 if (bms_is_member(i - FirstLowInvalidHeapAttributeNumber, attrs_used))
3367 {
3368 scan_plan->fsSystemCol = true;
3369 break;
3370 }
3371 }
3372
3373 bms_free(attrs_used);
3374 }
3375
3376 return scan_plan;
3377 }
3378
3379 /*
3380 * create_custom_plan
3381 *
3382 * Transform a CustomPath into a Plan.
3383 */
3384 static CustomScan *
create_customscan_plan(PlannerInfo * root,CustomPath * best_path,List * tlist,List * scan_clauses)3385 create_customscan_plan(PlannerInfo *root, CustomPath *best_path,
3386 List *tlist, List *scan_clauses)
3387 {
3388 CustomScan *cplan;
3389 RelOptInfo *rel = best_path->path.parent;
3390 List *custom_plans = NIL;
3391 ListCell *lc;
3392
3393 /* Recursively transform child paths. */
3394 foreach(lc, best_path->custom_paths)
3395 {
3396 Plan *plan = create_plan_recurse(root, (Path *) lfirst(lc),
3397 CP_EXACT_TLIST);
3398
3399 custom_plans = lappend(custom_plans, plan);
3400 }
3401
3402 /*
3403 * Sort clauses into the best execution order, although custom-scan
3404 * provider can reorder them again.
3405 */
3406 scan_clauses = order_qual_clauses(root, scan_clauses);
3407
3408 /*
3409 * Invoke custom plan provider to create the Plan node represented by the
3410 * CustomPath.
3411 */
3412 cplan = (CustomScan *) best_path->methods->PlanCustomPath(root,
3413 rel,
3414 best_path,
3415 tlist,
3416 scan_clauses,
3417 custom_plans);
3418 Assert(IsA(cplan, CustomScan));
3419
3420 /*
3421 * Copy cost data from Path to Plan; no need to make custom-plan providers
3422 * do this
3423 */
3424 copy_generic_path_info(&cplan->scan.plan, &best_path->path);
3425
3426 /* Likewise, copy the relids that are represented by this custom scan */
3427 cplan->custom_relids = best_path->path.parent->relids;
3428
3429 /*
3430 * Replace any outer-relation variables with nestloop params in the qual
3431 * and custom_exprs expressions. We do this last so that the custom-plan
3432 * provider doesn't have to be involved. (Note that parts of custom_exprs
3433 * could have come from join clauses, so doing this beforehand on the
3434 * scan_clauses wouldn't work.) We assume custom_scan_tlist contains no
3435 * such variables.
3436 */
3437 if (best_path->path.param_info)
3438 {
3439 cplan->scan.plan.qual = (List *)
3440 replace_nestloop_params(root, (Node *) cplan->scan.plan.qual);
3441 cplan->custom_exprs = (List *)
3442 replace_nestloop_params(root, (Node *) cplan->custom_exprs);
3443 }
3444
3445 return cplan;
3446 }
3447
3448
3449 /*****************************************************************************
3450 *
3451 * JOIN METHODS
3452 *
3453 *****************************************************************************/
3454
3455 static NestLoop *
create_nestloop_plan(PlannerInfo * root,NestPath * best_path)3456 create_nestloop_plan(PlannerInfo *root,
3457 NestPath *best_path)
3458 {
3459 NestLoop *join_plan;
3460 Plan *outer_plan;
3461 Plan *inner_plan;
3462 List *tlist = build_path_tlist(root, &best_path->path);
3463 List *joinrestrictclauses = best_path->joinrestrictinfo;
3464 List *joinclauses;
3465 List *otherclauses;
3466 Relids outerrelids;
3467 List *nestParams;
3468 Relids saveOuterRels = root->curOuterRels;
3469
3470 /* NestLoop can project, so no need to be picky about child tlists */
3471 outer_plan = create_plan_recurse(root, best_path->outerjoinpath, 0);
3472
3473 /* For a nestloop, include outer relids in curOuterRels for inner side */
3474 root->curOuterRels = bms_union(root->curOuterRels,
3475 best_path->outerjoinpath->parent->relids);
3476
3477 inner_plan = create_plan_recurse(root, best_path->innerjoinpath, 0);
3478
3479 /* Restore curOuterRels */
3480 bms_free(root->curOuterRels);
3481 root->curOuterRels = saveOuterRels;
3482
3483 /* Sort join qual clauses into best execution order */
3484 joinrestrictclauses = order_qual_clauses(root, joinrestrictclauses);
3485
3486 /* Get the join qual clauses (in plain expression form) */
3487 /* Any pseudoconstant clauses are ignored here */
3488 if (IS_OUTER_JOIN(best_path->jointype))
3489 {
3490 extract_actual_join_clauses(joinrestrictclauses,
3491 best_path->path.parent->relids,
3492 &joinclauses, &otherclauses);
3493 }
3494 else
3495 {
3496 /* We can treat all clauses alike for an inner join */
3497 joinclauses = extract_actual_clauses(joinrestrictclauses, false);
3498 otherclauses = NIL;
3499 }
3500
3501 /* Replace any outer-relation variables with nestloop params */
3502 if (best_path->path.param_info)
3503 {
3504 joinclauses = (List *)
3505 replace_nestloop_params(root, (Node *) joinclauses);
3506 otherclauses = (List *)
3507 replace_nestloop_params(root, (Node *) otherclauses);
3508 }
3509
3510 /*
3511 * Identify any nestloop parameters that should be supplied by this join
3512 * node, and remove them from root->curOuterParams.
3513 */
3514 outerrelids = best_path->outerjoinpath->parent->relids;
3515 nestParams = identify_current_nestloop_params(root, outerrelids);
3516
3517 join_plan = make_nestloop(tlist,
3518 joinclauses,
3519 otherclauses,
3520 nestParams,
3521 outer_plan,
3522 inner_plan,
3523 best_path->jointype);
3524
3525 copy_generic_path_info(&join_plan->join.plan, &best_path->path);
3526
3527 return join_plan;
3528 }
3529
3530 static MergeJoin *
create_mergejoin_plan(PlannerInfo * root,MergePath * best_path)3531 create_mergejoin_plan(PlannerInfo *root,
3532 MergePath *best_path)
3533 {
3534 MergeJoin *join_plan;
3535 Plan *outer_plan;
3536 Plan *inner_plan;
3537 List *tlist = build_path_tlist(root, &best_path->jpath.path);
3538 List *joinclauses;
3539 List *otherclauses;
3540 List *mergeclauses;
3541 List *outerpathkeys;
3542 List *innerpathkeys;
3543 int nClauses;
3544 Oid *mergefamilies;
3545 Oid *mergecollations;
3546 int *mergestrategies;
3547 bool *mergenullsfirst;
3548 PathKey *opathkey;
3549 EquivalenceClass *opeclass;
3550 int i;
3551 ListCell *lc;
3552 ListCell *lop;
3553 ListCell *lip;
3554
3555 /*
3556 * MergeJoin can project, so we don't have to demand exact tlists from the
3557 * inputs. However, if we're intending to sort an input's result, it's
3558 * best to request a small tlist so we aren't sorting more data than
3559 * necessary.
3560 */
3561 outer_plan = create_plan_recurse(root, best_path->jpath.outerjoinpath,
3562 (best_path->outersortkeys != NIL) ? CP_SMALL_TLIST : 0);
3563
3564 inner_plan = create_plan_recurse(root, best_path->jpath.innerjoinpath,
3565 (best_path->innersortkeys != NIL) ? CP_SMALL_TLIST : 0);
3566
3567 /* Sort join qual clauses into best execution order */
3568 /* NB: do NOT reorder the mergeclauses */
3569 joinclauses = order_qual_clauses(root, best_path->jpath.joinrestrictinfo);
3570
3571 /* Get the join qual clauses (in plain expression form) */
3572 /* Any pseudoconstant clauses are ignored here */
3573 if (IS_OUTER_JOIN(best_path->jpath.jointype))
3574 {
3575 extract_actual_join_clauses(joinclauses,
3576 best_path->jpath.path.parent->relids,
3577 &joinclauses, &otherclauses);
3578 }
3579 else
3580 {
3581 /* We can treat all clauses alike for an inner join */
3582 joinclauses = extract_actual_clauses(joinclauses, false);
3583 otherclauses = NIL;
3584 }
3585
3586 /*
3587 * Remove the mergeclauses from the list of join qual clauses, leaving the
3588 * list of quals that must be checked as qpquals.
3589 */
3590 mergeclauses = get_actual_clauses(best_path->path_mergeclauses);
3591 joinclauses = list_difference(joinclauses, mergeclauses);
3592
3593 /*
3594 * Replace any outer-relation variables with nestloop params. There
3595 * should not be any in the mergeclauses.
3596 */
3597 if (best_path->jpath.path.param_info)
3598 {
3599 joinclauses = (List *)
3600 replace_nestloop_params(root, (Node *) joinclauses);
3601 otherclauses = (List *)
3602 replace_nestloop_params(root, (Node *) otherclauses);
3603 }
3604
3605 /*
3606 * Rearrange mergeclauses, if needed, so that the outer variable is always
3607 * on the left; mark the mergeclause restrictinfos with correct
3608 * outer_is_left status.
3609 */
3610 mergeclauses = get_switched_clauses(best_path->path_mergeclauses,
3611 best_path->jpath.outerjoinpath->parent->relids);
3612
3613 /*
3614 * Create explicit sort nodes for the outer and inner paths if necessary.
3615 */
3616 if (best_path->outersortkeys)
3617 {
3618 Sort *sort = make_sort_from_pathkeys(outer_plan,
3619 best_path->outersortkeys);
3620
3621 label_sort_with_costsize(root, sort, -1.0);
3622 outer_plan = (Plan *) sort;
3623 outerpathkeys = best_path->outersortkeys;
3624 }
3625 else
3626 outerpathkeys = best_path->jpath.outerjoinpath->pathkeys;
3627
3628 if (best_path->innersortkeys)
3629 {
3630 Sort *sort = make_sort_from_pathkeys(inner_plan,
3631 best_path->innersortkeys);
3632
3633 label_sort_with_costsize(root, sort, -1.0);
3634 inner_plan = (Plan *) sort;
3635 innerpathkeys = best_path->innersortkeys;
3636 }
3637 else
3638 innerpathkeys = best_path->jpath.innerjoinpath->pathkeys;
3639
3640 /*
3641 * If specified, add a materialize node to shield the inner plan from the
3642 * need to handle mark/restore.
3643 */
3644 if (best_path->materialize_inner)
3645 {
3646 Plan *matplan = (Plan *) make_material(inner_plan);
3647
3648 /*
3649 * We assume the materialize will not spill to disk, and therefore
3650 * charge just cpu_operator_cost per tuple. (Keep this estimate in
3651 * sync with final_cost_mergejoin.)
3652 */
3653 copy_plan_costsize(matplan, inner_plan);
3654 matplan->total_cost += cpu_operator_cost * matplan->plan_rows;
3655
3656 inner_plan = matplan;
3657 }
3658
3659 /*
3660 * Compute the opfamily/collation/strategy/nullsfirst arrays needed by the
3661 * executor. The information is in the pathkeys for the two inputs, but
3662 * we need to be careful about the possibility of mergeclauses sharing a
3663 * pathkey, as well as the possibility that the inner pathkeys are not in
3664 * an order matching the mergeclauses.
3665 */
3666 nClauses = list_length(mergeclauses);
3667 Assert(nClauses == list_length(best_path->path_mergeclauses));
3668 mergefamilies = (Oid *) palloc(nClauses * sizeof(Oid));
3669 mergecollations = (Oid *) palloc(nClauses * sizeof(Oid));
3670 mergestrategies = (int *) palloc(nClauses * sizeof(int));
3671 mergenullsfirst = (bool *) palloc(nClauses * sizeof(bool));
3672
3673 opathkey = NULL;
3674 opeclass = NULL;
3675 lop = list_head(outerpathkeys);
3676 lip = list_head(innerpathkeys);
3677 i = 0;
3678 foreach(lc, best_path->path_mergeclauses)
3679 {
3680 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
3681 EquivalenceClass *oeclass;
3682 EquivalenceClass *ieclass;
3683 PathKey *ipathkey = NULL;
3684 EquivalenceClass *ipeclass = NULL;
3685 bool first_inner_match = false;
3686
3687 /* fetch outer/inner eclass from mergeclause */
3688 Assert(IsA(rinfo, RestrictInfo));
3689 if (rinfo->outer_is_left)
3690 {
3691 oeclass = rinfo->left_ec;
3692 ieclass = rinfo->right_ec;
3693 }
3694 else
3695 {
3696 oeclass = rinfo->right_ec;
3697 ieclass = rinfo->left_ec;
3698 }
3699 Assert(oeclass != NULL);
3700 Assert(ieclass != NULL);
3701
3702 /*
3703 * We must identify the pathkey elements associated with this clause
3704 * by matching the eclasses (which should give a unique match, since
3705 * the pathkey lists should be canonical). In typical cases the merge
3706 * clauses are one-to-one with the pathkeys, but when dealing with
3707 * partially redundant query conditions, things are more complicated.
3708 *
3709 * lop and lip reference the first as-yet-unmatched pathkey elements.
3710 * If they're NULL then all pathkey elements have been matched.
3711 *
3712 * The ordering of the outer pathkeys should match the mergeclauses,
3713 * by construction (see find_mergeclauses_for_outer_pathkeys()). There
3714 * could be more than one mergeclause for the same outer pathkey, but
3715 * no pathkey may be entirely skipped over.
3716 */
3717 if (oeclass != opeclass) /* multiple matches are not interesting */
3718 {
3719 /* doesn't match the current opathkey, so must match the next */
3720 if (lop == NULL)
3721 elog(ERROR, "outer pathkeys do not match mergeclauses");
3722 opathkey = (PathKey *) lfirst(lop);
3723 opeclass = opathkey->pk_eclass;
3724 lop = lnext(lop);
3725 if (oeclass != opeclass)
3726 elog(ERROR, "outer pathkeys do not match mergeclauses");
3727 }
3728
3729 /*
3730 * The inner pathkeys likewise should not have skipped-over keys, but
3731 * it's possible for a mergeclause to reference some earlier inner
3732 * pathkey if we had redundant pathkeys. For example we might have
3733 * mergeclauses like "o.a = i.x AND o.b = i.y AND o.c = i.x". The
3734 * implied inner ordering is then "ORDER BY x, y, x", but the pathkey
3735 * mechanism drops the second sort by x as redundant, and this code
3736 * must cope.
3737 *
3738 * It's also possible for the implied inner-rel ordering to be like
3739 * "ORDER BY x, y, x DESC". We still drop the second instance of x as
3740 * redundant; but this means that the sort ordering of a redundant
3741 * inner pathkey should not be considered significant. So we must
3742 * detect whether this is the first clause matching an inner pathkey.
3743 */
3744 if (lip)
3745 {
3746 ipathkey = (PathKey *) lfirst(lip);
3747 ipeclass = ipathkey->pk_eclass;
3748 if (ieclass == ipeclass)
3749 {
3750 /* successful first match to this inner pathkey */
3751 lip = lnext(lip);
3752 first_inner_match = true;
3753 }
3754 }
3755 if (!first_inner_match)
3756 {
3757 /* redundant clause ... must match something before lip */
3758 ListCell *l2;
3759
3760 foreach(l2, innerpathkeys)
3761 {
3762 if (l2 == lip)
3763 break;
3764 ipathkey = (PathKey *) lfirst(l2);
3765 ipeclass = ipathkey->pk_eclass;
3766 if (ieclass == ipeclass)
3767 break;
3768 }
3769 if (ieclass != ipeclass)
3770 elog(ERROR, "inner pathkeys do not match mergeclauses");
3771 }
3772
3773 /*
3774 * The pathkeys should always match each other as to opfamily and
3775 * collation (which affect equality), but if we're considering a
3776 * redundant inner pathkey, its sort ordering might not match. In
3777 * such cases we may ignore the inner pathkey's sort ordering and use
3778 * the outer's. (In effect, we're lying to the executor about the
3779 * sort direction of this inner column, but it does not matter since
3780 * the run-time row comparisons would only reach this column when
3781 * there's equality for the earlier column containing the same eclass.
3782 * There could be only one value in this column for the range of inner
3783 * rows having a given value in the earlier column, so it does not
3784 * matter which way we imagine this column to be ordered.) But a
3785 * non-redundant inner pathkey had better match outer's ordering too.
3786 */
3787 if (opathkey->pk_opfamily != ipathkey->pk_opfamily ||
3788 opathkey->pk_eclass->ec_collation != ipathkey->pk_eclass->ec_collation)
3789 elog(ERROR, "left and right pathkeys do not match in mergejoin");
3790 if (first_inner_match &&
3791 (opathkey->pk_strategy != ipathkey->pk_strategy ||
3792 opathkey->pk_nulls_first != ipathkey->pk_nulls_first))
3793 elog(ERROR, "left and right pathkeys do not match in mergejoin");
3794
3795 /* OK, save info for executor */
3796 mergefamilies[i] = opathkey->pk_opfamily;
3797 mergecollations[i] = opathkey->pk_eclass->ec_collation;
3798 mergestrategies[i] = opathkey->pk_strategy;
3799 mergenullsfirst[i] = opathkey->pk_nulls_first;
3800 i++;
3801 }
3802
3803 /*
3804 * Note: it is not an error if we have additional pathkey elements (i.e.,
3805 * lop or lip isn't NULL here). The input paths might be better-sorted
3806 * than we need for the current mergejoin.
3807 */
3808
3809 /*
3810 * Now we can build the mergejoin node.
3811 */
3812 join_plan = make_mergejoin(tlist,
3813 joinclauses,
3814 otherclauses,
3815 mergeclauses,
3816 mergefamilies,
3817 mergecollations,
3818 mergestrategies,
3819 mergenullsfirst,
3820 outer_plan,
3821 inner_plan,
3822 best_path->jpath.jointype);
3823
3824 /* Costs of sort and material steps are included in path cost already */
3825 copy_generic_path_info(&join_plan->join.plan, &best_path->jpath.path);
3826
3827 return join_plan;
3828 }
3829
3830 static HashJoin *
create_hashjoin_plan(PlannerInfo * root,HashPath * best_path)3831 create_hashjoin_plan(PlannerInfo *root,
3832 HashPath *best_path)
3833 {
3834 HashJoin *join_plan;
3835 Hash *hash_plan;
3836 Plan *outer_plan;
3837 Plan *inner_plan;
3838 List *tlist = build_path_tlist(root, &best_path->jpath.path);
3839 List *joinclauses;
3840 List *otherclauses;
3841 List *hashclauses;
3842 Oid skewTable = InvalidOid;
3843 AttrNumber skewColumn = InvalidAttrNumber;
3844 bool skewInherit = false;
3845 Oid skewColType = InvalidOid;
3846 int32 skewColTypmod = -1;
3847
3848 /*
3849 * HashJoin can project, so we don't have to demand exact tlists from the
3850 * inputs. However, it's best to request a small tlist from the inner
3851 * side, so that we aren't storing more data than necessary. Likewise, if
3852 * we anticipate batching, request a small tlist from the outer side so
3853 * that we don't put extra data in the outer batch files.
3854 */
3855 outer_plan = create_plan_recurse(root, best_path->jpath.outerjoinpath,
3856 (best_path->num_batches > 1) ? CP_SMALL_TLIST : 0);
3857
3858 inner_plan = create_plan_recurse(root, best_path->jpath.innerjoinpath,
3859 CP_SMALL_TLIST);
3860
3861 /* Sort join qual clauses into best execution order */
3862 joinclauses = order_qual_clauses(root, best_path->jpath.joinrestrictinfo);
3863 /* There's no point in sorting the hash clauses ... */
3864
3865 /* Get the join qual clauses (in plain expression form) */
3866 /* Any pseudoconstant clauses are ignored here */
3867 if (IS_OUTER_JOIN(best_path->jpath.jointype))
3868 {
3869 extract_actual_join_clauses(joinclauses,
3870 best_path->jpath.path.parent->relids,
3871 &joinclauses, &otherclauses);
3872 }
3873 else
3874 {
3875 /* We can treat all clauses alike for an inner join */
3876 joinclauses = extract_actual_clauses(joinclauses, false);
3877 otherclauses = NIL;
3878 }
3879
3880 /*
3881 * Remove the hashclauses from the list of join qual clauses, leaving the
3882 * list of quals that must be checked as qpquals.
3883 */
3884 hashclauses = get_actual_clauses(best_path->path_hashclauses);
3885 joinclauses = list_difference(joinclauses, hashclauses);
3886
3887 /*
3888 * Replace any outer-relation variables with nestloop params. There
3889 * should not be any in the hashclauses.
3890 */
3891 if (best_path->jpath.path.param_info)
3892 {
3893 joinclauses = (List *)
3894 replace_nestloop_params(root, (Node *) joinclauses);
3895 otherclauses = (List *)
3896 replace_nestloop_params(root, (Node *) otherclauses);
3897 }
3898
3899 /*
3900 * Rearrange hashclauses, if needed, so that the outer variable is always
3901 * on the left.
3902 */
3903 hashclauses = get_switched_clauses(best_path->path_hashclauses,
3904 best_path->jpath.outerjoinpath->parent->relids);
3905
3906 /*
3907 * If there is a single join clause and we can identify the outer variable
3908 * as a simple column reference, supply its identity for possible use in
3909 * skew optimization. (Note: in principle we could do skew optimization
3910 * with multiple join clauses, but we'd have to be able to determine the
3911 * most common combinations of outer values, which we don't currently have
3912 * enough stats for.)
3913 */
3914 if (list_length(hashclauses) == 1)
3915 {
3916 OpExpr *clause = (OpExpr *) linitial(hashclauses);
3917 Node *node;
3918
3919 Assert(is_opclause(clause));
3920 node = (Node *) linitial(clause->args);
3921 if (IsA(node, RelabelType))
3922 node = (Node *) ((RelabelType *) node)->arg;
3923 if (IsA(node, Var))
3924 {
3925 Var *var = (Var *) node;
3926 RangeTblEntry *rte;
3927
3928 rte = root->simple_rte_array[var->varno];
3929 if (rte->rtekind == RTE_RELATION)
3930 {
3931 skewTable = rte->relid;
3932 skewColumn = var->varattno;
3933 skewInherit = rte->inh;
3934 skewColType = var->vartype;
3935 skewColTypmod = var->vartypmod;
3936 }
3937 }
3938 }
3939
3940 /*
3941 * Build the hash node and hash join node.
3942 */
3943 hash_plan = make_hash(inner_plan,
3944 skewTable,
3945 skewColumn,
3946 skewInherit,
3947 skewColType,
3948 skewColTypmod);
3949
3950 /*
3951 * Set Hash node's startup & total costs equal to total cost of input
3952 * plan; this only affects EXPLAIN display not decisions.
3953 */
3954 copy_plan_costsize(&hash_plan->plan, inner_plan);
3955 hash_plan->plan.startup_cost = hash_plan->plan.total_cost;
3956
3957 join_plan = make_hashjoin(tlist,
3958 joinclauses,
3959 otherclauses,
3960 hashclauses,
3961 outer_plan,
3962 (Plan *) hash_plan,
3963 best_path->jpath.jointype);
3964
3965 copy_generic_path_info(&join_plan->join.plan, &best_path->jpath.path);
3966
3967 return join_plan;
3968 }
3969
3970
3971 /*****************************************************************************
3972 *
3973 * SUPPORTING ROUTINES
3974 *
3975 *****************************************************************************/
3976
3977 /*
3978 * replace_nestloop_params
3979 * Replace outer-relation Vars and PlaceHolderVars in the given expression
3980 * with nestloop Params
3981 *
3982 * All Vars and PlaceHolderVars belonging to the relation(s) identified by
3983 * root->curOuterRels are replaced by Params, and entries are added to
3984 * root->curOuterParams if not already present.
3985 */
3986 static Node *
replace_nestloop_params(PlannerInfo * root,Node * expr)3987 replace_nestloop_params(PlannerInfo *root, Node *expr)
3988 {
3989 /* No setup needed for tree walk, so away we go */
3990 return replace_nestloop_params_mutator(expr, root);
3991 }
3992
3993 static Node *
replace_nestloop_params_mutator(Node * node,PlannerInfo * root)3994 replace_nestloop_params_mutator(Node *node, PlannerInfo *root)
3995 {
3996 if (node == NULL)
3997 return NULL;
3998 if (IsA(node, Var))
3999 {
4000 Var *var = (Var *) node;
4001
4002 /* Upper-level Vars should be long gone at this point */
4003 Assert(var->varlevelsup == 0);
4004 /* If not to be replaced, we can just return the Var unmodified */
4005 if (!bms_is_member(var->varno, root->curOuterRels))
4006 return node;
4007 /* Replace the Var with a nestloop Param */
4008 return (Node *) replace_nestloop_param_var(root, var);
4009 }
4010 if (IsA(node, PlaceHolderVar))
4011 {
4012 PlaceHolderVar *phv = (PlaceHolderVar *) node;
4013
4014 /* Upper-level PlaceHolderVars should be long gone at this point */
4015 Assert(phv->phlevelsup == 0);
4016
4017 /*
4018 * Check whether we need to replace the PHV. We use bms_overlap as a
4019 * cheap/quick test to see if the PHV might be evaluated in the outer
4020 * rels, and then grab its PlaceHolderInfo to tell for sure.
4021 */
4022 if (!bms_overlap(phv->phrels, root->curOuterRels) ||
4023 !bms_is_subset(find_placeholder_info(root, phv, false)->ph_eval_at,
4024 root->curOuterRels))
4025 {
4026 /*
4027 * We can't replace the whole PHV, but we might still need to
4028 * replace Vars or PHVs within its expression, in case it ends up
4029 * actually getting evaluated here. (It might get evaluated in
4030 * this plan node, or some child node; in the latter case we don't
4031 * really need to process the expression here, but we haven't got
4032 * enough info to tell if that's the case.) Flat-copy the PHV
4033 * node and then recurse on its expression.
4034 *
4035 * Note that after doing this, we might have different
4036 * representations of the contents of the same PHV in different
4037 * parts of the plan tree. This is OK because equal() will just
4038 * match on phid/phlevelsup, so setrefs.c will still recognize an
4039 * upper-level reference to a lower-level copy of the same PHV.
4040 */
4041 PlaceHolderVar *newphv = makeNode(PlaceHolderVar);
4042
4043 memcpy(newphv, phv, sizeof(PlaceHolderVar));
4044 newphv->phexpr = (Expr *)
4045 replace_nestloop_params_mutator((Node *) phv->phexpr,
4046 root);
4047 return (Node *) newphv;
4048 }
4049 /* Replace the PlaceHolderVar with a nestloop Param */
4050 return (Node *) replace_nestloop_param_placeholdervar(root, phv);
4051 }
4052 return expression_tree_mutator(node,
4053 replace_nestloop_params_mutator,
4054 (void *) root);
4055 }
4056
4057 /*
4058 * fix_indexqual_references
4059 * Adjust indexqual clauses to the form the executor's indexqual
4060 * machinery needs.
4061 *
4062 * We have four tasks here:
4063 * * Remove RestrictInfo nodes from the input clauses.
4064 * * Replace any outer-relation Var or PHV nodes with nestloop Params.
4065 * (XXX eventually, that responsibility should go elsewhere?)
4066 * * Index keys must be represented by Var nodes with varattno set to the
4067 * index's attribute number, not the attribute number in the original rel.
4068 * * If the index key is on the right, commute the clause to put it on the
4069 * left.
4070 *
4071 * The result is a modified copy of the path's indexquals list --- the
4072 * original is not changed. Note also that the copy shares no substructure
4073 * with the original; this is needed in case there is a subplan in it (we need
4074 * two separate copies of the subplan tree, or things will go awry).
4075 */
4076 static List *
fix_indexqual_references(PlannerInfo * root,IndexPath * index_path)4077 fix_indexqual_references(PlannerInfo *root, IndexPath *index_path)
4078 {
4079 IndexOptInfo *index = index_path->indexinfo;
4080 List *fixed_indexquals;
4081 ListCell *lcc,
4082 *lci;
4083
4084 fixed_indexquals = NIL;
4085
4086 forboth(lcc, index_path->indexquals, lci, index_path->indexqualcols)
4087 {
4088 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lcc);
4089 int indexcol = lfirst_int(lci);
4090 Node *clause;
4091
4092 Assert(IsA(rinfo, RestrictInfo));
4093
4094 /*
4095 * Replace any outer-relation variables with nestloop params.
4096 *
4097 * This also makes a copy of the clause, so it's safe to modify it
4098 * in-place below.
4099 */
4100 clause = replace_nestloop_params(root, (Node *) rinfo->clause);
4101
4102 if (IsA(clause, OpExpr))
4103 {
4104 OpExpr *op = (OpExpr *) clause;
4105
4106 if (list_length(op->args) != 2)
4107 elog(ERROR, "indexqual clause is not binary opclause");
4108
4109 /*
4110 * Check to see if the indexkey is on the right; if so, commute
4111 * the clause. The indexkey should be the side that refers to
4112 * (only) the base relation.
4113 */
4114 if (!bms_equal(rinfo->left_relids, index->rel->relids))
4115 CommuteOpExpr(op);
4116
4117 /*
4118 * Now replace the indexkey expression with an index Var.
4119 */
4120 linitial(op->args) = fix_indexqual_operand(linitial(op->args),
4121 index,
4122 indexcol);
4123 }
4124 else if (IsA(clause, RowCompareExpr))
4125 {
4126 RowCompareExpr *rc = (RowCompareExpr *) clause;
4127 Expr *newrc;
4128 List *indexcolnos;
4129 bool var_on_left;
4130 ListCell *lca,
4131 *lcai;
4132
4133 /*
4134 * Re-discover which index columns are used in the rowcompare.
4135 */
4136 newrc = adjust_rowcompare_for_index(rc,
4137 index,
4138 indexcol,
4139 &indexcolnos,
4140 &var_on_left);
4141
4142 /*
4143 * Trouble if adjust_rowcompare_for_index thought the
4144 * RowCompareExpr didn't match the index as-is; the clause should
4145 * have gone through that routine already.
4146 */
4147 if (newrc != (Expr *) rc)
4148 elog(ERROR, "inconsistent results from adjust_rowcompare_for_index");
4149
4150 /*
4151 * Check to see if the indexkey is on the right; if so, commute
4152 * the clause.
4153 */
4154 if (!var_on_left)
4155 CommuteRowCompareExpr(rc);
4156
4157 /*
4158 * Now replace the indexkey expressions with index Vars.
4159 */
4160 Assert(list_length(rc->largs) == list_length(indexcolnos));
4161 forboth(lca, rc->largs, lcai, indexcolnos)
4162 {
4163 lfirst(lca) = fix_indexqual_operand(lfirst(lca),
4164 index,
4165 lfirst_int(lcai));
4166 }
4167 }
4168 else if (IsA(clause, ScalarArrayOpExpr))
4169 {
4170 ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;
4171
4172 /* Never need to commute... */
4173
4174 /* Replace the indexkey expression with an index Var. */
4175 linitial(saop->args) = fix_indexqual_operand(linitial(saop->args),
4176 index,
4177 indexcol);
4178 }
4179 else if (IsA(clause, NullTest))
4180 {
4181 NullTest *nt = (NullTest *) clause;
4182
4183 /* Replace the indexkey expression with an index Var. */
4184 nt->arg = (Expr *) fix_indexqual_operand((Node *) nt->arg,
4185 index,
4186 indexcol);
4187 }
4188 else
4189 elog(ERROR, "unsupported indexqual type: %d",
4190 (int) nodeTag(clause));
4191
4192 fixed_indexquals = lappend(fixed_indexquals, clause);
4193 }
4194
4195 return fixed_indexquals;
4196 }
4197
4198 /*
4199 * fix_indexorderby_references
4200 * Adjust indexorderby clauses to the form the executor's index
4201 * machinery needs.
4202 *
4203 * This is a simplified version of fix_indexqual_references. The input does
4204 * not have RestrictInfo nodes, and we assume that indxpath.c already
4205 * commuted the clauses to put the index keys on the left. Also, we don't
4206 * bother to support any cases except simple OpExprs, since nothing else
4207 * is allowed for ordering operators.
4208 */
4209 static List *
fix_indexorderby_references(PlannerInfo * root,IndexPath * index_path)4210 fix_indexorderby_references(PlannerInfo *root, IndexPath *index_path)
4211 {
4212 IndexOptInfo *index = index_path->indexinfo;
4213 List *fixed_indexorderbys;
4214 ListCell *lcc,
4215 *lci;
4216
4217 fixed_indexorderbys = NIL;
4218
4219 forboth(lcc, index_path->indexorderbys, lci, index_path->indexorderbycols)
4220 {
4221 Node *clause = (Node *) lfirst(lcc);
4222 int indexcol = lfirst_int(lci);
4223
4224 /*
4225 * Replace any outer-relation variables with nestloop params.
4226 *
4227 * This also makes a copy of the clause, so it's safe to modify it
4228 * in-place below.
4229 */
4230 clause = replace_nestloop_params(root, clause);
4231
4232 if (IsA(clause, OpExpr))
4233 {
4234 OpExpr *op = (OpExpr *) clause;
4235
4236 if (list_length(op->args) != 2)
4237 elog(ERROR, "indexorderby clause is not binary opclause");
4238
4239 /*
4240 * Now replace the indexkey expression with an index Var.
4241 */
4242 linitial(op->args) = fix_indexqual_operand(linitial(op->args),
4243 index,
4244 indexcol);
4245 }
4246 else
4247 elog(ERROR, "unsupported indexorderby type: %d",
4248 (int) nodeTag(clause));
4249
4250 fixed_indexorderbys = lappend(fixed_indexorderbys, clause);
4251 }
4252
4253 return fixed_indexorderbys;
4254 }
4255
4256 /*
4257 * fix_indexqual_operand
4258 * Convert an indexqual expression to a Var referencing the index column.
4259 *
4260 * We represent index keys by Var nodes having varno == INDEX_VAR and varattno
4261 * equal to the index's attribute number (index column position).
4262 *
4263 * Most of the code here is just for sanity cross-checking that the given
4264 * expression actually matches the index column it's claimed to.
4265 */
4266 static Node *
fix_indexqual_operand(Node * node,IndexOptInfo * index,int indexcol)4267 fix_indexqual_operand(Node *node, IndexOptInfo *index, int indexcol)
4268 {
4269 Var *result;
4270 int pos;
4271 ListCell *indexpr_item;
4272
4273 /*
4274 * Remove any binary-compatible relabeling of the indexkey
4275 */
4276 if (IsA(node, RelabelType))
4277 node = (Node *) ((RelabelType *) node)->arg;
4278
4279 Assert(indexcol >= 0 && indexcol < index->ncolumns);
4280
4281 if (index->indexkeys[indexcol] != 0)
4282 {
4283 /* It's a simple index column */
4284 if (IsA(node, Var) &&
4285 ((Var *) node)->varno == index->rel->relid &&
4286 ((Var *) node)->varattno == index->indexkeys[indexcol])
4287 {
4288 result = (Var *) copyObject(node);
4289 result->varno = INDEX_VAR;
4290 result->varattno = indexcol + 1;
4291 return (Node *) result;
4292 }
4293 else
4294 elog(ERROR, "index key does not match expected index column");
4295 }
4296
4297 /* It's an index expression, so find and cross-check the expression */
4298 indexpr_item = list_head(index->indexprs);
4299 for (pos = 0; pos < index->ncolumns; pos++)
4300 {
4301 if (index->indexkeys[pos] == 0)
4302 {
4303 if (indexpr_item == NULL)
4304 elog(ERROR, "too few entries in indexprs list");
4305 if (pos == indexcol)
4306 {
4307 Node *indexkey;
4308
4309 indexkey = (Node *) lfirst(indexpr_item);
4310 if (indexkey && IsA(indexkey, RelabelType))
4311 indexkey = (Node *) ((RelabelType *) indexkey)->arg;
4312 if (equal(node, indexkey))
4313 {
4314 result = makeVar(INDEX_VAR, indexcol + 1,
4315 exprType(lfirst(indexpr_item)), -1,
4316 exprCollation(lfirst(indexpr_item)),
4317 0);
4318 return (Node *) result;
4319 }
4320 else
4321 elog(ERROR, "index key does not match expected index column");
4322 }
4323 indexpr_item = lnext(indexpr_item);
4324 }
4325 }
4326
4327 /* Ooops... */
4328 elog(ERROR, "index key does not match expected index column");
4329 return NULL; /* keep compiler quiet */
4330 }
4331
4332 /*
4333 * get_switched_clauses
4334 * Given a list of merge or hash joinclauses (as RestrictInfo nodes),
4335 * extract the bare clauses, and rearrange the elements within the
4336 * clauses, if needed, so the outer join variable is on the left and
4337 * the inner is on the right. The original clause data structure is not
4338 * touched; a modified list is returned. We do, however, set the transient
4339 * outer_is_left field in each RestrictInfo to show which side was which.
4340 */
4341 static List *
get_switched_clauses(List * clauses,Relids outerrelids)4342 get_switched_clauses(List *clauses, Relids outerrelids)
4343 {
4344 List *t_list = NIL;
4345 ListCell *l;
4346
4347 foreach(l, clauses)
4348 {
4349 RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(l);
4350 OpExpr *clause = (OpExpr *) restrictinfo->clause;
4351
4352 Assert(is_opclause(clause));
4353 if (bms_is_subset(restrictinfo->right_relids, outerrelids))
4354 {
4355 /*
4356 * Duplicate just enough of the structure to allow commuting the
4357 * clause without changing the original list. Could use
4358 * copyObject, but a complete deep copy is overkill.
4359 */
4360 OpExpr *temp = makeNode(OpExpr);
4361
4362 temp->opno = clause->opno;
4363 temp->opfuncid = InvalidOid;
4364 temp->opresulttype = clause->opresulttype;
4365 temp->opretset = clause->opretset;
4366 temp->opcollid = clause->opcollid;
4367 temp->inputcollid = clause->inputcollid;
4368 temp->args = list_copy(clause->args);
4369 temp->location = clause->location;
4370 /* Commute it --- note this modifies the temp node in-place. */
4371 CommuteOpExpr(temp);
4372 t_list = lappend(t_list, temp);
4373 restrictinfo->outer_is_left = false;
4374 }
4375 else
4376 {
4377 Assert(bms_is_subset(restrictinfo->left_relids, outerrelids));
4378 t_list = lappend(t_list, clause);
4379 restrictinfo->outer_is_left = true;
4380 }
4381 }
4382 return t_list;
4383 }
4384
4385 /*
4386 * order_qual_clauses
4387 * Given a list of qual clauses that will all be evaluated at the same
4388 * plan node, sort the list into the order we want to check the quals
4389 * in at runtime.
4390 *
4391 * Ideally the order should be driven by a combination of execution cost and
4392 * selectivity, but it's not immediately clear how to account for both,
4393 * and given the uncertainty of the estimates the reliability of the decisions
4394 * would be doubtful anyway. So we just order by estimated per-tuple cost,
4395 * being careful not to change the order when (as is often the case) the
4396 * estimates are identical.
4397 *
4398 * Although this will work on either bare clauses or RestrictInfos, it's
4399 * much faster to apply it to RestrictInfos, since it can re-use cost
4400 * information that is cached in RestrictInfos.
4401 *
4402 * Note: some callers pass lists that contain entries that will later be
4403 * removed; this is the easiest way to let this routine see RestrictInfos
4404 * instead of bare clauses. It's OK because we only sort by cost, but
4405 * a cost/selectivity combination would likely do the wrong thing.
4406 */
4407 static List *
order_qual_clauses(PlannerInfo * root,List * clauses)4408 order_qual_clauses(PlannerInfo *root, List *clauses)
4409 {
4410 typedef struct
4411 {
4412 Node *clause;
4413 Cost cost;
4414 } QualItem;
4415 int nitems = list_length(clauses);
4416 QualItem *items;
4417 ListCell *lc;
4418 int i;
4419 List *result;
4420
4421 /* No need to work hard for 0 or 1 clause */
4422 if (nitems <= 1)
4423 return clauses;
4424
4425 /*
4426 * Collect the items and costs into an array. This is to avoid repeated
4427 * cost_qual_eval work if the inputs aren't RestrictInfos.
4428 */
4429 items = (QualItem *) palloc(nitems * sizeof(QualItem));
4430 i = 0;
4431 foreach(lc, clauses)
4432 {
4433 Node *clause = (Node *) lfirst(lc);
4434 QualCost qcost;
4435
4436 cost_qual_eval_node(&qcost, clause, root);
4437 items[i].clause = clause;
4438 items[i].cost = qcost.per_tuple;
4439 i++;
4440 }
4441
4442 /*
4443 * Sort. We don't use qsort() because it's not guaranteed stable for
4444 * equal keys. The expected number of entries is small enough that a
4445 * simple insertion sort should be good enough.
4446 */
4447 for (i = 1; i < nitems; i++)
4448 {
4449 QualItem newitem = items[i];
4450 int j;
4451
4452 /* insert newitem into the already-sorted subarray */
4453 for (j = i; j > 0; j--)
4454 {
4455 if (newitem.cost >= items[j - 1].cost)
4456 break;
4457 items[j] = items[j - 1];
4458 }
4459 items[j] = newitem;
4460 }
4461
4462 /* Convert back to a list */
4463 result = NIL;
4464 for (i = 0; i < nitems; i++)
4465 result = lappend(result, items[i].clause);
4466
4467 return result;
4468 }
4469
4470 /*
4471 * Copy cost and size info from a Path node to the Plan node created from it.
4472 * The executor usually won't use this info, but it's needed by EXPLAIN.
4473 * Also copy the parallel-aware flag, which the executor *will* use.
4474 */
4475 static void
copy_generic_path_info(Plan * dest,Path * src)4476 copy_generic_path_info(Plan *dest, Path *src)
4477 {
4478 dest->startup_cost = src->startup_cost;
4479 dest->total_cost = src->total_cost;
4480 dest->plan_rows = src->rows;
4481 dest->plan_width = src->pathtarget->width;
4482 dest->parallel_aware = src->parallel_aware;
4483 }
4484
4485 /*
4486 * Copy cost and size info from a lower plan node to an inserted node.
4487 * (Most callers alter the info after copying it.)
4488 */
4489 static void
copy_plan_costsize(Plan * dest,Plan * src)4490 copy_plan_costsize(Plan *dest, Plan *src)
4491 {
4492 dest->startup_cost = src->startup_cost;
4493 dest->total_cost = src->total_cost;
4494 dest->plan_rows = src->plan_rows;
4495 dest->plan_width = src->plan_width;
4496 /* Assume the inserted node is not parallel-aware. */
4497 dest->parallel_aware = false;
4498 }
4499
4500 /*
4501 * Some places in this file build Sort nodes that don't have a directly
4502 * corresponding Path node. The cost of the sort is, or should have been,
4503 * included in the cost of the Path node we're working from, but since it's
4504 * not split out, we have to re-figure it using cost_sort(). This is just
4505 * to label the Sort node nicely for EXPLAIN.
4506 *
4507 * limit_tuples is as for cost_sort (in particular, pass -1 if no limit)
4508 */
4509 static void
label_sort_with_costsize(PlannerInfo * root,Sort * plan,double limit_tuples)4510 label_sort_with_costsize(PlannerInfo *root, Sort *plan, double limit_tuples)
4511 {
4512 Plan *lefttree = plan->plan.lefttree;
4513 Path sort_path; /* dummy for result of cost_sort */
4514
4515 cost_sort(&sort_path, root, NIL,
4516 lefttree->total_cost,
4517 lefttree->plan_rows,
4518 lefttree->plan_width,
4519 0.0,
4520 work_mem,
4521 limit_tuples);
4522 plan->plan.startup_cost = sort_path.startup_cost;
4523 plan->plan.total_cost = sort_path.total_cost;
4524 plan->plan.plan_rows = lefttree->plan_rows;
4525 plan->plan.plan_width = lefttree->plan_width;
4526 plan->plan.parallel_aware = false;
4527 }
4528
4529
4530 /*****************************************************************************
4531 *
4532 * PLAN NODE BUILDING ROUTINES
4533 *
4534 * In general, these functions are not passed the original Path and therefore
4535 * leave it to the caller to fill in the cost/width fields from the Path,
4536 * typically by calling copy_generic_path_info(). This convention is
4537 * somewhat historical, but it does support a few places above where we build
4538 * a plan node without having an exactly corresponding Path node. Under no
4539 * circumstances should one of these functions do its own cost calculations,
4540 * as that would be redundant with calculations done while building Paths.
4541 *
4542 *****************************************************************************/
4543
4544 static SeqScan *
make_seqscan(List * qptlist,List * qpqual,Index scanrelid)4545 make_seqscan(List *qptlist,
4546 List *qpqual,
4547 Index scanrelid)
4548 {
4549 SeqScan *node = makeNode(SeqScan);
4550 Plan *plan = &node->plan;
4551
4552 plan->targetlist = qptlist;
4553 plan->qual = qpqual;
4554 plan->lefttree = NULL;
4555 plan->righttree = NULL;
4556 node->scanrelid = scanrelid;
4557
4558 return node;
4559 }
4560
4561 static SampleScan *
make_samplescan(List * qptlist,List * qpqual,Index scanrelid,TableSampleClause * tsc)4562 make_samplescan(List *qptlist,
4563 List *qpqual,
4564 Index scanrelid,
4565 TableSampleClause *tsc)
4566 {
4567 SampleScan *node = makeNode(SampleScan);
4568 Plan *plan = &node->scan.plan;
4569
4570 plan->targetlist = qptlist;
4571 plan->qual = qpqual;
4572 plan->lefttree = NULL;
4573 plan->righttree = NULL;
4574 node->scan.scanrelid = scanrelid;
4575 node->tablesample = tsc;
4576
4577 return node;
4578 }
4579
4580 static IndexScan *
make_indexscan(List * qptlist,List * qpqual,Index scanrelid,Oid indexid,List * indexqual,List * indexqualorig,List * indexorderby,List * indexorderbyorig,List * indexorderbyops,ScanDirection indexscandir)4581 make_indexscan(List *qptlist,
4582 List *qpqual,
4583 Index scanrelid,
4584 Oid indexid,
4585 List *indexqual,
4586 List *indexqualorig,
4587 List *indexorderby,
4588 List *indexorderbyorig,
4589 List *indexorderbyops,
4590 ScanDirection indexscandir)
4591 {
4592 IndexScan *node = makeNode(IndexScan);
4593 Plan *plan = &node->scan.plan;
4594
4595 plan->targetlist = qptlist;
4596 plan->qual = qpqual;
4597 plan->lefttree = NULL;
4598 plan->righttree = NULL;
4599 node->scan.scanrelid = scanrelid;
4600 node->indexid = indexid;
4601 node->indexqual = indexqual;
4602 node->indexqualorig = indexqualorig;
4603 node->indexorderby = indexorderby;
4604 node->indexorderbyorig = indexorderbyorig;
4605 node->indexorderbyops = indexorderbyops;
4606 node->indexorderdir = indexscandir;
4607
4608 return node;
4609 }
4610
4611 static IndexOnlyScan *
make_indexonlyscan(List * qptlist,List * qpqual,Index scanrelid,Oid indexid,List * indexqual,List * indexorderby,List * indextlist,ScanDirection indexscandir)4612 make_indexonlyscan(List *qptlist,
4613 List *qpqual,
4614 Index scanrelid,
4615 Oid indexid,
4616 List *indexqual,
4617 List *indexorderby,
4618 List *indextlist,
4619 ScanDirection indexscandir)
4620 {
4621 IndexOnlyScan *node = makeNode(IndexOnlyScan);
4622 Plan *plan = &node->scan.plan;
4623
4624 plan->targetlist = qptlist;
4625 plan->qual = qpqual;
4626 plan->lefttree = NULL;
4627 plan->righttree = NULL;
4628 node->scan.scanrelid = scanrelid;
4629 node->indexid = indexid;
4630 node->indexqual = indexqual;
4631 node->indexorderby = indexorderby;
4632 node->indextlist = indextlist;
4633 node->indexorderdir = indexscandir;
4634
4635 return node;
4636 }
4637
4638 static BitmapIndexScan *
make_bitmap_indexscan(Index scanrelid,Oid indexid,List * indexqual,List * indexqualorig)4639 make_bitmap_indexscan(Index scanrelid,
4640 Oid indexid,
4641 List *indexqual,
4642 List *indexqualorig)
4643 {
4644 BitmapIndexScan *node = makeNode(BitmapIndexScan);
4645 Plan *plan = &node->scan.plan;
4646
4647 plan->targetlist = NIL; /* not used */
4648 plan->qual = NIL; /* not used */
4649 plan->lefttree = NULL;
4650 plan->righttree = NULL;
4651 node->scan.scanrelid = scanrelid;
4652 node->indexid = indexid;
4653 node->indexqual = indexqual;
4654 node->indexqualorig = indexqualorig;
4655
4656 return node;
4657 }
4658
4659 static BitmapHeapScan *
make_bitmap_heapscan(List * qptlist,List * qpqual,Plan * lefttree,List * bitmapqualorig,Index scanrelid)4660 make_bitmap_heapscan(List *qptlist,
4661 List *qpqual,
4662 Plan *lefttree,
4663 List *bitmapqualorig,
4664 Index scanrelid)
4665 {
4666 BitmapHeapScan *node = makeNode(BitmapHeapScan);
4667 Plan *plan = &node->scan.plan;
4668
4669 plan->targetlist = qptlist;
4670 plan->qual = qpqual;
4671 plan->lefttree = lefttree;
4672 plan->righttree = NULL;
4673 node->scan.scanrelid = scanrelid;
4674 node->bitmapqualorig = bitmapqualorig;
4675
4676 return node;
4677 }
4678
4679 static TidScan *
make_tidscan(List * qptlist,List * qpqual,Index scanrelid,List * tidquals)4680 make_tidscan(List *qptlist,
4681 List *qpqual,
4682 Index scanrelid,
4683 List *tidquals)
4684 {
4685 TidScan *node = makeNode(TidScan);
4686 Plan *plan = &node->scan.plan;
4687
4688 plan->targetlist = qptlist;
4689 plan->qual = qpqual;
4690 plan->lefttree = NULL;
4691 plan->righttree = NULL;
4692 node->scan.scanrelid = scanrelid;
4693 node->tidquals = tidquals;
4694
4695 return node;
4696 }
4697
4698 static SubqueryScan *
make_subqueryscan(List * qptlist,List * qpqual,Index scanrelid,Plan * subplan)4699 make_subqueryscan(List *qptlist,
4700 List *qpqual,
4701 Index scanrelid,
4702 Plan *subplan)
4703 {
4704 SubqueryScan *node = makeNode(SubqueryScan);
4705 Plan *plan = &node->scan.plan;
4706
4707 plan->targetlist = qptlist;
4708 plan->qual = qpqual;
4709 plan->lefttree = NULL;
4710 plan->righttree = NULL;
4711 node->scan.scanrelid = scanrelid;
4712 node->subplan = subplan;
4713
4714 return node;
4715 }
4716
4717 static FunctionScan *
make_functionscan(List * qptlist,List * qpqual,Index scanrelid,List * functions,bool funcordinality)4718 make_functionscan(List *qptlist,
4719 List *qpqual,
4720 Index scanrelid,
4721 List *functions,
4722 bool funcordinality)
4723 {
4724 FunctionScan *node = makeNode(FunctionScan);
4725 Plan *plan = &node->scan.plan;
4726
4727 plan->targetlist = qptlist;
4728 plan->qual = qpqual;
4729 plan->lefttree = NULL;
4730 plan->righttree = NULL;
4731 node->scan.scanrelid = scanrelid;
4732 node->functions = functions;
4733 node->funcordinality = funcordinality;
4734
4735 return node;
4736 }
4737
4738 static ValuesScan *
make_valuesscan(List * qptlist,List * qpqual,Index scanrelid,List * values_lists)4739 make_valuesscan(List *qptlist,
4740 List *qpqual,
4741 Index scanrelid,
4742 List *values_lists)
4743 {
4744 ValuesScan *node = makeNode(ValuesScan);
4745 Plan *plan = &node->scan.plan;
4746
4747 plan->targetlist = qptlist;
4748 plan->qual = qpqual;
4749 plan->lefttree = NULL;
4750 plan->righttree = NULL;
4751 node->scan.scanrelid = scanrelid;
4752 node->values_lists = values_lists;
4753
4754 return node;
4755 }
4756
4757 static CteScan *
make_ctescan(List * qptlist,List * qpqual,Index scanrelid,int ctePlanId,int cteParam)4758 make_ctescan(List *qptlist,
4759 List *qpqual,
4760 Index scanrelid,
4761 int ctePlanId,
4762 int cteParam)
4763 {
4764 CteScan *node = makeNode(CteScan);
4765 Plan *plan = &node->scan.plan;
4766
4767 plan->targetlist = qptlist;
4768 plan->qual = qpqual;
4769 plan->lefttree = NULL;
4770 plan->righttree = NULL;
4771 node->scan.scanrelid = scanrelid;
4772 node->ctePlanId = ctePlanId;
4773 node->cteParam = cteParam;
4774
4775 return node;
4776 }
4777
4778 static WorkTableScan *
make_worktablescan(List * qptlist,List * qpqual,Index scanrelid,int wtParam)4779 make_worktablescan(List *qptlist,
4780 List *qpqual,
4781 Index scanrelid,
4782 int wtParam)
4783 {
4784 WorkTableScan *node = makeNode(WorkTableScan);
4785 Plan *plan = &node->scan.plan;
4786
4787 plan->targetlist = qptlist;
4788 plan->qual = qpqual;
4789 plan->lefttree = NULL;
4790 plan->righttree = NULL;
4791 node->scan.scanrelid = scanrelid;
4792 node->wtParam = wtParam;
4793
4794 return node;
4795 }
4796
4797 ForeignScan *
make_foreignscan(List * qptlist,List * qpqual,Index scanrelid,List * fdw_exprs,List * fdw_private,List * fdw_scan_tlist,List * fdw_recheck_quals,Plan * outer_plan)4798 make_foreignscan(List *qptlist,
4799 List *qpqual,
4800 Index scanrelid,
4801 List *fdw_exprs,
4802 List *fdw_private,
4803 List *fdw_scan_tlist,
4804 List *fdw_recheck_quals,
4805 Plan *outer_plan)
4806 {
4807 ForeignScan *node = makeNode(ForeignScan);
4808 Plan *plan = &node->scan.plan;
4809
4810 /* cost will be filled in by create_foreignscan_plan */
4811 plan->targetlist = qptlist;
4812 plan->qual = qpqual;
4813 plan->lefttree = outer_plan;
4814 plan->righttree = NULL;
4815 node->scan.scanrelid = scanrelid;
4816 node->operation = CMD_SELECT;
4817 /* fs_server will be filled in by create_foreignscan_plan */
4818 node->fs_server = InvalidOid;
4819 node->fdw_exprs = fdw_exprs;
4820 node->fdw_private = fdw_private;
4821 node->fdw_scan_tlist = fdw_scan_tlist;
4822 node->fdw_recheck_quals = fdw_recheck_quals;
4823 /* fs_relids will be filled in by create_foreignscan_plan */
4824 node->fs_relids = NULL;
4825 /* fsSystemCol will be filled in by create_foreignscan_plan */
4826 node->fsSystemCol = false;
4827
4828 return node;
4829 }
4830
4831 static Append *
make_append(List * appendplans,List * tlist)4832 make_append(List *appendplans, List *tlist)
4833 {
4834 Append *node = makeNode(Append);
4835 Plan *plan = &node->plan;
4836
4837 plan->targetlist = tlist;
4838 plan->qual = NIL;
4839 plan->lefttree = NULL;
4840 plan->righttree = NULL;
4841 node->appendplans = appendplans;
4842
4843 return node;
4844 }
4845
4846 static RecursiveUnion *
make_recursive_union(List * tlist,Plan * lefttree,Plan * righttree,int wtParam,List * distinctList,long numGroups)4847 make_recursive_union(List *tlist,
4848 Plan *lefttree,
4849 Plan *righttree,
4850 int wtParam,
4851 List *distinctList,
4852 long numGroups)
4853 {
4854 RecursiveUnion *node = makeNode(RecursiveUnion);
4855 Plan *plan = &node->plan;
4856 int numCols = list_length(distinctList);
4857
4858 plan->targetlist = tlist;
4859 plan->qual = NIL;
4860 plan->lefttree = lefttree;
4861 plan->righttree = righttree;
4862 node->wtParam = wtParam;
4863
4864 /*
4865 * convert SortGroupClause list into arrays of attr indexes and equality
4866 * operators, as wanted by executor
4867 */
4868 node->numCols = numCols;
4869 if (numCols > 0)
4870 {
4871 int keyno = 0;
4872 AttrNumber *dupColIdx;
4873 Oid *dupOperators;
4874 ListCell *slitem;
4875
4876 dupColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
4877 dupOperators = (Oid *) palloc(sizeof(Oid) * numCols);
4878
4879 foreach(slitem, distinctList)
4880 {
4881 SortGroupClause *sortcl = (SortGroupClause *) lfirst(slitem);
4882 TargetEntry *tle = get_sortgroupclause_tle(sortcl,
4883 plan->targetlist);
4884
4885 dupColIdx[keyno] = tle->resno;
4886 dupOperators[keyno] = sortcl->eqop;
4887 Assert(OidIsValid(dupOperators[keyno]));
4888 keyno++;
4889 }
4890 node->dupColIdx = dupColIdx;
4891 node->dupOperators = dupOperators;
4892 }
4893 node->numGroups = numGroups;
4894
4895 return node;
4896 }
4897
4898 static BitmapAnd *
make_bitmap_and(List * bitmapplans)4899 make_bitmap_and(List *bitmapplans)
4900 {
4901 BitmapAnd *node = makeNode(BitmapAnd);
4902 Plan *plan = &node->plan;
4903
4904 plan->targetlist = NIL;
4905 plan->qual = NIL;
4906 plan->lefttree = NULL;
4907 plan->righttree = NULL;
4908 node->bitmapplans = bitmapplans;
4909
4910 return node;
4911 }
4912
4913 static BitmapOr *
make_bitmap_or(List * bitmapplans)4914 make_bitmap_or(List *bitmapplans)
4915 {
4916 BitmapOr *node = makeNode(BitmapOr);
4917 Plan *plan = &node->plan;
4918
4919 plan->targetlist = NIL;
4920 plan->qual = NIL;
4921 plan->lefttree = NULL;
4922 plan->righttree = NULL;
4923 node->bitmapplans = bitmapplans;
4924
4925 return node;
4926 }
4927
4928 static NestLoop *
make_nestloop(List * tlist,List * joinclauses,List * otherclauses,List * nestParams,Plan * lefttree,Plan * righttree,JoinType jointype)4929 make_nestloop(List *tlist,
4930 List *joinclauses,
4931 List *otherclauses,
4932 List *nestParams,
4933 Plan *lefttree,
4934 Plan *righttree,
4935 JoinType jointype)
4936 {
4937 NestLoop *node = makeNode(NestLoop);
4938 Plan *plan = &node->join.plan;
4939
4940 plan->targetlist = tlist;
4941 plan->qual = otherclauses;
4942 plan->lefttree = lefttree;
4943 plan->righttree = righttree;
4944 node->join.jointype = jointype;
4945 node->join.joinqual = joinclauses;
4946 node->nestParams = nestParams;
4947
4948 return node;
4949 }
4950
4951 static HashJoin *
make_hashjoin(List * tlist,List * joinclauses,List * otherclauses,List * hashclauses,Plan * lefttree,Plan * righttree,JoinType jointype)4952 make_hashjoin(List *tlist,
4953 List *joinclauses,
4954 List *otherclauses,
4955 List *hashclauses,
4956 Plan *lefttree,
4957 Plan *righttree,
4958 JoinType jointype)
4959 {
4960 HashJoin *node = makeNode(HashJoin);
4961 Plan *plan = &node->join.plan;
4962
4963 plan->targetlist = tlist;
4964 plan->qual = otherclauses;
4965 plan->lefttree = lefttree;
4966 plan->righttree = righttree;
4967 node->hashclauses = hashclauses;
4968 node->join.jointype = jointype;
4969 node->join.joinqual = joinclauses;
4970
4971 return node;
4972 }
4973
4974 static Hash *
make_hash(Plan * lefttree,Oid skewTable,AttrNumber skewColumn,bool skewInherit,Oid skewColType,int32 skewColTypmod)4975 make_hash(Plan *lefttree,
4976 Oid skewTable,
4977 AttrNumber skewColumn,
4978 bool skewInherit,
4979 Oid skewColType,
4980 int32 skewColTypmod)
4981 {
4982 Hash *node = makeNode(Hash);
4983 Plan *plan = &node->plan;
4984
4985 plan->targetlist = lefttree->targetlist;
4986 plan->qual = NIL;
4987 plan->lefttree = lefttree;
4988 plan->righttree = NULL;
4989
4990 node->skewTable = skewTable;
4991 node->skewColumn = skewColumn;
4992 node->skewInherit = skewInherit;
4993 node->skewColType = skewColType;
4994 node->skewColTypmod = skewColTypmod;
4995
4996 return node;
4997 }
4998
4999 static MergeJoin *
make_mergejoin(List * tlist,List * joinclauses,List * otherclauses,List * mergeclauses,Oid * mergefamilies,Oid * mergecollations,int * mergestrategies,bool * mergenullsfirst,Plan * lefttree,Plan * righttree,JoinType jointype)5000 make_mergejoin(List *tlist,
5001 List *joinclauses,
5002 List *otherclauses,
5003 List *mergeclauses,
5004 Oid *mergefamilies,
5005 Oid *mergecollations,
5006 int *mergestrategies,
5007 bool *mergenullsfirst,
5008 Plan *lefttree,
5009 Plan *righttree,
5010 JoinType jointype)
5011 {
5012 MergeJoin *node = makeNode(MergeJoin);
5013 Plan *plan = &node->join.plan;
5014
5015 plan->targetlist = tlist;
5016 plan->qual = otherclauses;
5017 plan->lefttree = lefttree;
5018 plan->righttree = righttree;
5019 node->mergeclauses = mergeclauses;
5020 node->mergeFamilies = mergefamilies;
5021 node->mergeCollations = mergecollations;
5022 node->mergeStrategies = mergestrategies;
5023 node->mergeNullsFirst = mergenullsfirst;
5024 node->join.jointype = jointype;
5025 node->join.joinqual = joinclauses;
5026
5027 return node;
5028 }
5029
5030 /*
5031 * make_sort --- basic routine to build a Sort plan node
5032 *
5033 * Caller must have built the sortColIdx, sortOperators, collations, and
5034 * nullsFirst arrays already.
5035 */
5036 static Sort *
make_sort(Plan * lefttree,int numCols,AttrNumber * sortColIdx,Oid * sortOperators,Oid * collations,bool * nullsFirst)5037 make_sort(Plan *lefttree, int numCols,
5038 AttrNumber *sortColIdx, Oid *sortOperators,
5039 Oid *collations, bool *nullsFirst)
5040 {
5041 Sort *node = makeNode(Sort);
5042 Plan *plan = &node->plan;
5043
5044 plan->targetlist = lefttree->targetlist;
5045 plan->qual = NIL;
5046 plan->lefttree = lefttree;
5047 plan->righttree = NULL;
5048 node->numCols = numCols;
5049 node->sortColIdx = sortColIdx;
5050 node->sortOperators = sortOperators;
5051 node->collations = collations;
5052 node->nullsFirst = nullsFirst;
5053
5054 return node;
5055 }
5056
5057 /*
5058 * prepare_sort_from_pathkeys
5059 * Prepare to sort according to given pathkeys
5060 *
5061 * This is used to set up for both Sort and MergeAppend nodes. It calculates
5062 * the executor's representation of the sort key information, and adjusts the
5063 * plan targetlist if needed to add resjunk sort columns.
5064 *
5065 * Input parameters:
5066 * 'lefttree' is the plan node which yields input tuples
5067 * 'pathkeys' is the list of pathkeys by which the result is to be sorted
5068 * 'relids' identifies the child relation being sorted, if any
5069 * 'reqColIdx' is NULL or an array of required sort key column numbers
5070 * 'adjust_tlist_in_place' is TRUE if lefttree must be modified in-place
5071 *
5072 * We must convert the pathkey information into arrays of sort key column
5073 * numbers, sort operator OIDs, collation OIDs, and nulls-first flags,
5074 * which is the representation the executor wants. These are returned into
5075 * the output parameters *p_numsortkeys etc.
5076 *
5077 * When looking for matches to an EquivalenceClass's members, we will only
5078 * consider child EC members if they match 'relids'. This protects against
5079 * possible incorrect matches to child expressions that contain no Vars.
5080 *
5081 * If reqColIdx isn't NULL then it contains sort key column numbers that
5082 * we should match. This is used when making child plans for a MergeAppend;
5083 * it's an error if we can't match the columns.
5084 *
5085 * If the pathkeys include expressions that aren't simple Vars, we will
5086 * usually need to add resjunk items to the input plan's targetlist to
5087 * compute these expressions, since the Sort/MergeAppend node itself won't
5088 * do any such calculations. If the input plan type isn't one that can do
5089 * projections, this means adding a Result node just to do the projection.
5090 * However, the caller can pass adjust_tlist_in_place = TRUE to force the
5091 * lefttree tlist to be modified in-place regardless of whether the node type
5092 * can project --- we use this for fixing the tlist of MergeAppend itself.
5093 *
5094 * Returns the node which is to be the input to the Sort (either lefttree,
5095 * or a Result stacked atop lefttree).
5096 */
5097 static Plan *
prepare_sort_from_pathkeys(Plan * lefttree,List * pathkeys,Relids relids,const AttrNumber * reqColIdx,bool adjust_tlist_in_place,int * p_numsortkeys,AttrNumber ** p_sortColIdx,Oid ** p_sortOperators,Oid ** p_collations,bool ** p_nullsFirst)5098 prepare_sort_from_pathkeys(Plan *lefttree, List *pathkeys,
5099 Relids relids,
5100 const AttrNumber *reqColIdx,
5101 bool adjust_tlist_in_place,
5102 int *p_numsortkeys,
5103 AttrNumber **p_sortColIdx,
5104 Oid **p_sortOperators,
5105 Oid **p_collations,
5106 bool **p_nullsFirst)
5107 {
5108 List *tlist = lefttree->targetlist;
5109 ListCell *i;
5110 int numsortkeys;
5111 AttrNumber *sortColIdx;
5112 Oid *sortOperators;
5113 Oid *collations;
5114 bool *nullsFirst;
5115
5116 /*
5117 * We will need at most list_length(pathkeys) sort columns; possibly less
5118 */
5119 numsortkeys = list_length(pathkeys);
5120 sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
5121 sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
5122 collations = (Oid *) palloc(numsortkeys * sizeof(Oid));
5123 nullsFirst = (bool *) palloc(numsortkeys * sizeof(bool));
5124
5125 numsortkeys = 0;
5126
5127 foreach(i, pathkeys)
5128 {
5129 PathKey *pathkey = (PathKey *) lfirst(i);
5130 EquivalenceClass *ec = pathkey->pk_eclass;
5131 EquivalenceMember *em;
5132 TargetEntry *tle = NULL;
5133 Oid pk_datatype = InvalidOid;
5134 Oid sortop;
5135 ListCell *j;
5136
5137 if (ec->ec_has_volatile)
5138 {
5139 /*
5140 * If the pathkey's EquivalenceClass is volatile, then it must
5141 * have come from an ORDER BY clause, and we have to match it to
5142 * that same targetlist entry.
5143 */
5144 if (ec->ec_sortref == 0) /* can't happen */
5145 elog(ERROR, "volatile EquivalenceClass has no sortref");
5146 tle = get_sortgroupref_tle(ec->ec_sortref, tlist);
5147 Assert(tle);
5148 Assert(list_length(ec->ec_members) == 1);
5149 pk_datatype = ((EquivalenceMember *) linitial(ec->ec_members))->em_datatype;
5150 }
5151 else if (reqColIdx != NULL)
5152 {
5153 /*
5154 * If we are given a sort column number to match, only consider
5155 * the single TLE at that position. It's possible that there is
5156 * no such TLE, in which case fall through and generate a resjunk
5157 * targetentry (we assume this must have happened in the parent
5158 * plan as well). If there is a TLE but it doesn't match the
5159 * pathkey's EC, we do the same, which is probably the wrong thing
5160 * but we'll leave it to caller to complain about the mismatch.
5161 */
5162 tle = get_tle_by_resno(tlist, reqColIdx[numsortkeys]);
5163 if (tle)
5164 {
5165 em = find_ec_member_for_tle(ec, tle, relids);
5166 if (em)
5167 {
5168 /* found expr at right place in tlist */
5169 pk_datatype = em->em_datatype;
5170 }
5171 else
5172 tle = NULL;
5173 }
5174 }
5175 else
5176 {
5177 /*
5178 * Otherwise, we can sort by any non-constant expression listed in
5179 * the pathkey's EquivalenceClass. For now, we take the first
5180 * tlist item found in the EC. If there's no match, we'll generate
5181 * a resjunk entry using the first EC member that is an expression
5182 * in the input's vars. (The non-const restriction only matters
5183 * if the EC is below_outer_join; but if it isn't, it won't
5184 * contain consts anyway, else we'd have discarded the pathkey as
5185 * redundant.)
5186 *
5187 * XXX if we have a choice, is there any way of figuring out which
5188 * might be cheapest to execute? (For example, int4lt is likely
5189 * much cheaper to execute than numericlt, but both might appear
5190 * in the same equivalence class...) Not clear that we ever will
5191 * have an interesting choice in practice, so it may not matter.
5192 */
5193 foreach(j, tlist)
5194 {
5195 tle = (TargetEntry *) lfirst(j);
5196 em = find_ec_member_for_tle(ec, tle, relids);
5197 if (em)
5198 {
5199 /* found expr already in tlist */
5200 pk_datatype = em->em_datatype;
5201 break;
5202 }
5203 tle = NULL;
5204 }
5205 }
5206
5207 if (!tle)
5208 {
5209 /*
5210 * No matching tlist item; look for a computable expression. Note
5211 * that we treat Aggrefs as if they were variables; this is
5212 * necessary when attempting to sort the output from an Agg node
5213 * for use in a WindowFunc (since grouping_planner will have
5214 * treated the Aggrefs as variables, too). Likewise, if we find a
5215 * WindowFunc in a sort expression, treat it as a variable.
5216 */
5217 Expr *sortexpr = NULL;
5218
5219 foreach(j, ec->ec_members)
5220 {
5221 EquivalenceMember *em = (EquivalenceMember *) lfirst(j);
5222 List *exprvars;
5223 ListCell *k;
5224
5225 /*
5226 * We shouldn't be trying to sort by an equivalence class that
5227 * contains a constant, so no need to consider such cases any
5228 * further.
5229 */
5230 if (em->em_is_const)
5231 continue;
5232
5233 /*
5234 * Ignore child members unless they match the rel being
5235 * sorted.
5236 */
5237 if (em->em_is_child &&
5238 !bms_equal(em->em_relids, relids))
5239 continue;
5240
5241 sortexpr = em->em_expr;
5242 exprvars = pull_var_clause((Node *) sortexpr,
5243 PVC_INCLUDE_AGGREGATES |
5244 PVC_INCLUDE_WINDOWFUNCS |
5245 PVC_INCLUDE_PLACEHOLDERS);
5246 foreach(k, exprvars)
5247 {
5248 if (!tlist_member_ignore_relabel(lfirst(k), tlist))
5249 break;
5250 }
5251 list_free(exprvars);
5252 if (!k)
5253 {
5254 pk_datatype = em->em_datatype;
5255 break; /* found usable expression */
5256 }
5257 }
5258 if (!j)
5259 elog(ERROR, "could not find pathkey item to sort");
5260
5261 /*
5262 * Do we need to insert a Result node?
5263 */
5264 if (!adjust_tlist_in_place &&
5265 !is_projection_capable_plan(lefttree))
5266 {
5267 /* copy needed so we don't modify input's tlist below */
5268 tlist = copyObject(tlist);
5269 lefttree = inject_projection_plan(lefttree, tlist);
5270 }
5271
5272 /* Don't bother testing is_projection_capable_plan again */
5273 adjust_tlist_in_place = true;
5274
5275 /*
5276 * Add resjunk entry to input's tlist
5277 */
5278 tle = makeTargetEntry(sortexpr,
5279 list_length(tlist) + 1,
5280 NULL,
5281 true);
5282 tlist = lappend(tlist, tle);
5283 lefttree->targetlist = tlist; /* just in case NIL before */
5284 }
5285
5286 /*
5287 * Look up the correct sort operator from the PathKey's slightly
5288 * abstracted representation.
5289 */
5290 sortop = get_opfamily_member(pathkey->pk_opfamily,
5291 pk_datatype,
5292 pk_datatype,
5293 pathkey->pk_strategy);
5294 if (!OidIsValid(sortop)) /* should not happen */
5295 elog(ERROR, "could not find member %d(%u,%u) of opfamily %u",
5296 pathkey->pk_strategy, pk_datatype, pk_datatype,
5297 pathkey->pk_opfamily);
5298
5299 /* Add the column to the sort arrays */
5300 sortColIdx[numsortkeys] = tle->resno;
5301 sortOperators[numsortkeys] = sortop;
5302 collations[numsortkeys] = ec->ec_collation;
5303 nullsFirst[numsortkeys] = pathkey->pk_nulls_first;
5304 numsortkeys++;
5305 }
5306
5307 /* Return results */
5308 *p_numsortkeys = numsortkeys;
5309 *p_sortColIdx = sortColIdx;
5310 *p_sortOperators = sortOperators;
5311 *p_collations = collations;
5312 *p_nullsFirst = nullsFirst;
5313
5314 return lefttree;
5315 }
5316
5317 /*
5318 * find_ec_member_for_tle
5319 * Locate an EquivalenceClass member matching the given TLE, if any
5320 *
5321 * Child EC members are ignored unless they match 'relids'.
5322 */
5323 static EquivalenceMember *
find_ec_member_for_tle(EquivalenceClass * ec,TargetEntry * tle,Relids relids)5324 find_ec_member_for_tle(EquivalenceClass *ec,
5325 TargetEntry *tle,
5326 Relids relids)
5327 {
5328 Expr *tlexpr;
5329 ListCell *lc;
5330
5331 /* We ignore binary-compatible relabeling on both ends */
5332 tlexpr = tle->expr;
5333 while (tlexpr && IsA(tlexpr, RelabelType))
5334 tlexpr = ((RelabelType *) tlexpr)->arg;
5335
5336 foreach(lc, ec->ec_members)
5337 {
5338 EquivalenceMember *em = (EquivalenceMember *) lfirst(lc);
5339 Expr *emexpr;
5340
5341 /*
5342 * We shouldn't be trying to sort by an equivalence class that
5343 * contains a constant, so no need to consider such cases any further.
5344 */
5345 if (em->em_is_const)
5346 continue;
5347
5348 /*
5349 * Ignore child members unless they match the rel being sorted.
5350 */
5351 if (em->em_is_child &&
5352 !bms_equal(em->em_relids, relids))
5353 continue;
5354
5355 /* Match if same expression (after stripping relabel) */
5356 emexpr = em->em_expr;
5357 while (emexpr && IsA(emexpr, RelabelType))
5358 emexpr = ((RelabelType *) emexpr)->arg;
5359
5360 if (equal(emexpr, tlexpr))
5361 return em;
5362 }
5363
5364 return NULL;
5365 }
5366
5367 /*
5368 * make_sort_from_pathkeys
5369 * Create sort plan to sort according to given pathkeys
5370 *
5371 * 'lefttree' is the node which yields input tuples
5372 * 'pathkeys' is the list of pathkeys by which the result is to be sorted
5373 */
5374 static Sort *
make_sort_from_pathkeys(Plan * lefttree,List * pathkeys)5375 make_sort_from_pathkeys(Plan *lefttree, List *pathkeys)
5376 {
5377 int numsortkeys;
5378 AttrNumber *sortColIdx;
5379 Oid *sortOperators;
5380 Oid *collations;
5381 bool *nullsFirst;
5382
5383 /* Compute sort column info, and adjust lefttree as needed */
5384 lefttree = prepare_sort_from_pathkeys(lefttree, pathkeys,
5385 NULL,
5386 NULL,
5387 false,
5388 &numsortkeys,
5389 &sortColIdx,
5390 &sortOperators,
5391 &collations,
5392 &nullsFirst);
5393
5394 /* Now build the Sort node */
5395 return make_sort(lefttree, numsortkeys,
5396 sortColIdx, sortOperators,
5397 collations, nullsFirst);
5398 }
5399
5400 /*
5401 * make_sort_from_sortclauses
5402 * Create sort plan to sort according to given sortclauses
5403 *
5404 * 'sortcls' is a list of SortGroupClauses
5405 * 'lefttree' is the node which yields input tuples
5406 */
5407 Sort *
make_sort_from_sortclauses(List * sortcls,Plan * lefttree)5408 make_sort_from_sortclauses(List *sortcls, Plan *lefttree)
5409 {
5410 List *sub_tlist = lefttree->targetlist;
5411 ListCell *l;
5412 int numsortkeys;
5413 AttrNumber *sortColIdx;
5414 Oid *sortOperators;
5415 Oid *collations;
5416 bool *nullsFirst;
5417
5418 /* Convert list-ish representation to arrays wanted by executor */
5419 numsortkeys = list_length(sortcls);
5420 sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
5421 sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
5422 collations = (Oid *) palloc(numsortkeys * sizeof(Oid));
5423 nullsFirst = (bool *) palloc(numsortkeys * sizeof(bool));
5424
5425 numsortkeys = 0;
5426 foreach(l, sortcls)
5427 {
5428 SortGroupClause *sortcl = (SortGroupClause *) lfirst(l);
5429 TargetEntry *tle = get_sortgroupclause_tle(sortcl, sub_tlist);
5430
5431 sortColIdx[numsortkeys] = tle->resno;
5432 sortOperators[numsortkeys] = sortcl->sortop;
5433 collations[numsortkeys] = exprCollation((Node *) tle->expr);
5434 nullsFirst[numsortkeys] = sortcl->nulls_first;
5435 numsortkeys++;
5436 }
5437
5438 return make_sort(lefttree, numsortkeys,
5439 sortColIdx, sortOperators,
5440 collations, nullsFirst);
5441 }
5442
5443 /*
5444 * make_sort_from_groupcols
5445 * Create sort plan to sort based on grouping columns
5446 *
5447 * 'groupcls' is the list of SortGroupClauses
5448 * 'grpColIdx' gives the column numbers to use
5449 *
5450 * This might look like it could be merged with make_sort_from_sortclauses,
5451 * but presently we *must* use the grpColIdx[] array to locate sort columns,
5452 * because the child plan's tlist is not marked with ressortgroupref info
5453 * appropriate to the grouping node. So, only the sort ordering info
5454 * is used from the SortGroupClause entries.
5455 */
5456 static Sort *
make_sort_from_groupcols(List * groupcls,AttrNumber * grpColIdx,Plan * lefttree)5457 make_sort_from_groupcols(List *groupcls,
5458 AttrNumber *grpColIdx,
5459 Plan *lefttree)
5460 {
5461 List *sub_tlist = lefttree->targetlist;
5462 ListCell *l;
5463 int numsortkeys;
5464 AttrNumber *sortColIdx;
5465 Oid *sortOperators;
5466 Oid *collations;
5467 bool *nullsFirst;
5468
5469 /* Convert list-ish representation to arrays wanted by executor */
5470 numsortkeys = list_length(groupcls);
5471 sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
5472 sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
5473 collations = (Oid *) palloc(numsortkeys * sizeof(Oid));
5474 nullsFirst = (bool *) palloc(numsortkeys * sizeof(bool));
5475
5476 numsortkeys = 0;
5477 foreach(l, groupcls)
5478 {
5479 SortGroupClause *grpcl = (SortGroupClause *) lfirst(l);
5480 TargetEntry *tle = get_tle_by_resno(sub_tlist, grpColIdx[numsortkeys]);
5481
5482 if (!tle)
5483 elog(ERROR, "could not retrieve tle for sort-from-groupcols");
5484
5485 sortColIdx[numsortkeys] = tle->resno;
5486 sortOperators[numsortkeys] = grpcl->sortop;
5487 collations[numsortkeys] = exprCollation((Node *) tle->expr);
5488 nullsFirst[numsortkeys] = grpcl->nulls_first;
5489 numsortkeys++;
5490 }
5491
5492 return make_sort(lefttree, numsortkeys,
5493 sortColIdx, sortOperators,
5494 collations, nullsFirst);
5495 }
5496
5497 static Material *
make_material(Plan * lefttree)5498 make_material(Plan *lefttree)
5499 {
5500 Material *node = makeNode(Material);
5501 Plan *plan = &node->plan;
5502
5503 plan->targetlist = lefttree->targetlist;
5504 plan->qual = NIL;
5505 plan->lefttree = lefttree;
5506 plan->righttree = NULL;
5507
5508 return node;
5509 }
5510
5511 /*
5512 * materialize_finished_plan: stick a Material node atop a completed plan
5513 *
5514 * There are a couple of places where we want to attach a Material node
5515 * after completion of create_plan(), without any MaterialPath path.
5516 * Those places should probably be refactored someday to do this on the
5517 * Path representation, but it's not worth the trouble yet.
5518 */
5519 Plan *
materialize_finished_plan(Plan * subplan)5520 materialize_finished_plan(Plan *subplan)
5521 {
5522 Plan *matplan;
5523 Path matpath; /* dummy for result of cost_material */
5524
5525 matplan = (Plan *) make_material(subplan);
5526
5527 /*
5528 * XXX horrid kluge: if there are any initPlans attached to the subplan,
5529 * move them up to the Material node, which is now effectively the top
5530 * plan node in its query level. This prevents failure in
5531 * SS_finalize_plan(), which see for comments. We don't bother adjusting
5532 * the subplan's cost estimate for this.
5533 */
5534 matplan->initPlan = subplan->initPlan;
5535 subplan->initPlan = NIL;
5536
5537 /* Set cost data */
5538 cost_material(&matpath,
5539 subplan->startup_cost,
5540 subplan->total_cost,
5541 subplan->plan_rows,
5542 subplan->plan_width);
5543 matplan->startup_cost = matpath.startup_cost;
5544 matplan->total_cost = matpath.total_cost;
5545 matplan->plan_rows = subplan->plan_rows;
5546 matplan->plan_width = subplan->plan_width;
5547 matplan->parallel_aware = false;
5548
5549 return matplan;
5550 }
5551
5552 Agg *
make_agg(List * tlist,List * qual,AggStrategy aggstrategy,AggSplit aggsplit,int numGroupCols,AttrNumber * grpColIdx,Oid * grpOperators,List * groupingSets,List * chain,double dNumGroups,Plan * lefttree)5553 make_agg(List *tlist, List *qual,
5554 AggStrategy aggstrategy, AggSplit aggsplit,
5555 int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators,
5556 List *groupingSets, List *chain,
5557 double dNumGroups, Plan *lefttree)
5558 {
5559 Agg *node = makeNode(Agg);
5560 Plan *plan = &node->plan;
5561 long numGroups;
5562
5563 /* Reduce to long, but 'ware overflow! */
5564 numGroups = (long) Min(dNumGroups, (double) LONG_MAX);
5565
5566 node->aggstrategy = aggstrategy;
5567 node->aggsplit = aggsplit;
5568 node->numCols = numGroupCols;
5569 node->grpColIdx = grpColIdx;
5570 node->grpOperators = grpOperators;
5571 node->numGroups = numGroups;
5572 node->aggParams = NULL; /* SS_finalize_plan() will fill this */
5573 node->groupingSets = groupingSets;
5574 node->chain = chain;
5575
5576 plan->qual = qual;
5577 plan->targetlist = tlist;
5578 plan->lefttree = lefttree;
5579 plan->righttree = NULL;
5580
5581 return node;
5582 }
5583
5584 static WindowAgg *
make_windowagg(List * tlist,Index winref,int partNumCols,AttrNumber * partColIdx,Oid * partOperators,int ordNumCols,AttrNumber * ordColIdx,Oid * ordOperators,int frameOptions,Node * startOffset,Node * endOffset,Plan * lefttree)5585 make_windowagg(List *tlist, Index winref,
5586 int partNumCols, AttrNumber *partColIdx, Oid *partOperators,
5587 int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators,
5588 int frameOptions, Node *startOffset, Node *endOffset,
5589 Plan *lefttree)
5590 {
5591 WindowAgg *node = makeNode(WindowAgg);
5592 Plan *plan = &node->plan;
5593
5594 node->winref = winref;
5595 node->partNumCols = partNumCols;
5596 node->partColIdx = partColIdx;
5597 node->partOperators = partOperators;
5598 node->ordNumCols = ordNumCols;
5599 node->ordColIdx = ordColIdx;
5600 node->ordOperators = ordOperators;
5601 node->frameOptions = frameOptions;
5602 node->startOffset = startOffset;
5603 node->endOffset = endOffset;
5604
5605 plan->targetlist = tlist;
5606 plan->lefttree = lefttree;
5607 plan->righttree = NULL;
5608 /* WindowAgg nodes never have a qual clause */
5609 plan->qual = NIL;
5610
5611 return node;
5612 }
5613
5614 static Group *
make_group(List * tlist,List * qual,int numGroupCols,AttrNumber * grpColIdx,Oid * grpOperators,Plan * lefttree)5615 make_group(List *tlist,
5616 List *qual,
5617 int numGroupCols,
5618 AttrNumber *grpColIdx,
5619 Oid *grpOperators,
5620 Plan *lefttree)
5621 {
5622 Group *node = makeNode(Group);
5623 Plan *plan = &node->plan;
5624
5625 node->numCols = numGroupCols;
5626 node->grpColIdx = grpColIdx;
5627 node->grpOperators = grpOperators;
5628
5629 plan->qual = qual;
5630 plan->targetlist = tlist;
5631 plan->lefttree = lefttree;
5632 plan->righttree = NULL;
5633
5634 return node;
5635 }
5636
5637 /*
5638 * distinctList is a list of SortGroupClauses, identifying the targetlist items
5639 * that should be considered by the Unique filter. The input path must
5640 * already be sorted accordingly.
5641 */
5642 static Unique *
make_unique_from_sortclauses(Plan * lefttree,List * distinctList)5643 make_unique_from_sortclauses(Plan *lefttree, List *distinctList)
5644 {
5645 Unique *node = makeNode(Unique);
5646 Plan *plan = &node->plan;
5647 int numCols = list_length(distinctList);
5648 int keyno = 0;
5649 AttrNumber *uniqColIdx;
5650 Oid *uniqOperators;
5651 ListCell *slitem;
5652
5653 plan->targetlist = lefttree->targetlist;
5654 plan->qual = NIL;
5655 plan->lefttree = lefttree;
5656 plan->righttree = NULL;
5657
5658 /*
5659 * convert SortGroupClause list into arrays of attr indexes and equality
5660 * operators, as wanted by executor
5661 */
5662 Assert(numCols > 0);
5663 uniqColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
5664 uniqOperators = (Oid *) palloc(sizeof(Oid) * numCols);
5665
5666 foreach(slitem, distinctList)
5667 {
5668 SortGroupClause *sortcl = (SortGroupClause *) lfirst(slitem);
5669 TargetEntry *tle = get_sortgroupclause_tle(sortcl, plan->targetlist);
5670
5671 uniqColIdx[keyno] = tle->resno;
5672 uniqOperators[keyno] = sortcl->eqop;
5673 Assert(OidIsValid(uniqOperators[keyno]));
5674 keyno++;
5675 }
5676
5677 node->numCols = numCols;
5678 node->uniqColIdx = uniqColIdx;
5679 node->uniqOperators = uniqOperators;
5680
5681 return node;
5682 }
5683
5684 /*
5685 * as above, but use pathkeys to identify the sort columns and semantics
5686 */
5687 static Unique *
make_unique_from_pathkeys(Plan * lefttree,List * pathkeys,int numCols)5688 make_unique_from_pathkeys(Plan *lefttree, List *pathkeys, int numCols)
5689 {
5690 Unique *node = makeNode(Unique);
5691 Plan *plan = &node->plan;
5692 int keyno = 0;
5693 AttrNumber *uniqColIdx;
5694 Oid *uniqOperators;
5695 ListCell *lc;
5696
5697 plan->targetlist = lefttree->targetlist;
5698 plan->qual = NIL;
5699 plan->lefttree = lefttree;
5700 plan->righttree = NULL;
5701
5702 /*
5703 * Convert pathkeys list into arrays of attr indexes and equality
5704 * operators, as wanted by executor. This has a lot in common with
5705 * prepare_sort_from_pathkeys ... maybe unify sometime?
5706 */
5707 Assert(numCols >= 0 && numCols <= list_length(pathkeys));
5708 uniqColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
5709 uniqOperators = (Oid *) palloc(sizeof(Oid) * numCols);
5710
5711 foreach(lc, pathkeys)
5712 {
5713 PathKey *pathkey = (PathKey *) lfirst(lc);
5714 EquivalenceClass *ec = pathkey->pk_eclass;
5715 EquivalenceMember *em;
5716 TargetEntry *tle = NULL;
5717 Oid pk_datatype = InvalidOid;
5718 Oid eqop;
5719 ListCell *j;
5720
5721 /* Ignore pathkeys beyond the specified number of columns */
5722 if (keyno >= numCols)
5723 break;
5724
5725 if (ec->ec_has_volatile)
5726 {
5727 /*
5728 * If the pathkey's EquivalenceClass is volatile, then it must
5729 * have come from an ORDER BY clause, and we have to match it to
5730 * that same targetlist entry.
5731 */
5732 if (ec->ec_sortref == 0) /* can't happen */
5733 elog(ERROR, "volatile EquivalenceClass has no sortref");
5734 tle = get_sortgroupref_tle(ec->ec_sortref, plan->targetlist);
5735 Assert(tle);
5736 Assert(list_length(ec->ec_members) == 1);
5737 pk_datatype = ((EquivalenceMember *) linitial(ec->ec_members))->em_datatype;
5738 }
5739 else
5740 {
5741 /*
5742 * Otherwise, we can use any non-constant expression listed in the
5743 * pathkey's EquivalenceClass. For now, we take the first tlist
5744 * item found in the EC.
5745 */
5746 foreach(j, plan->targetlist)
5747 {
5748 tle = (TargetEntry *) lfirst(j);
5749 em = find_ec_member_for_tle(ec, tle, NULL);
5750 if (em)
5751 {
5752 /* found expr already in tlist */
5753 pk_datatype = em->em_datatype;
5754 break;
5755 }
5756 tle = NULL;
5757 }
5758 }
5759
5760 if (!tle)
5761 elog(ERROR, "could not find pathkey item to sort");
5762
5763 /*
5764 * Look up the correct equality operator from the PathKey's slightly
5765 * abstracted representation.
5766 */
5767 eqop = get_opfamily_member(pathkey->pk_opfamily,
5768 pk_datatype,
5769 pk_datatype,
5770 BTEqualStrategyNumber);
5771 if (!OidIsValid(eqop)) /* should not happen */
5772 elog(ERROR, "could not find member %d(%u,%u) of opfamily %u",
5773 BTEqualStrategyNumber, pk_datatype, pk_datatype,
5774 pathkey->pk_opfamily);
5775
5776 uniqColIdx[keyno] = tle->resno;
5777 uniqOperators[keyno] = eqop;
5778
5779 keyno++;
5780 }
5781
5782 node->numCols = numCols;
5783 node->uniqColIdx = uniqColIdx;
5784 node->uniqOperators = uniqOperators;
5785
5786 return node;
5787 }
5788
5789 static Gather *
make_gather(List * qptlist,List * qpqual,int nworkers,bool single_copy,Plan * subplan)5790 make_gather(List *qptlist,
5791 List *qpqual,
5792 int nworkers,
5793 bool single_copy,
5794 Plan *subplan)
5795 {
5796 Gather *node = makeNode(Gather);
5797 Plan *plan = &node->plan;
5798
5799 plan->targetlist = qptlist;
5800 plan->qual = qpqual;
5801 plan->lefttree = subplan;
5802 plan->righttree = NULL;
5803 node->num_workers = nworkers;
5804 node->single_copy = single_copy;
5805 node->invisible = false;
5806
5807 return node;
5808 }
5809
5810 /*
5811 * distinctList is a list of SortGroupClauses, identifying the targetlist
5812 * items that should be considered by the SetOp filter. The input path must
5813 * already be sorted accordingly.
5814 */
5815 static SetOp *
make_setop(SetOpCmd cmd,SetOpStrategy strategy,Plan * lefttree,List * distinctList,AttrNumber flagColIdx,int firstFlag,long numGroups)5816 make_setop(SetOpCmd cmd, SetOpStrategy strategy, Plan *lefttree,
5817 List *distinctList, AttrNumber flagColIdx, int firstFlag,
5818 long numGroups)
5819 {
5820 SetOp *node = makeNode(SetOp);
5821 Plan *plan = &node->plan;
5822 int numCols = list_length(distinctList);
5823 int keyno = 0;
5824 AttrNumber *dupColIdx;
5825 Oid *dupOperators;
5826 ListCell *slitem;
5827
5828 plan->targetlist = lefttree->targetlist;
5829 plan->qual = NIL;
5830 plan->lefttree = lefttree;
5831 plan->righttree = NULL;
5832
5833 /*
5834 * convert SortGroupClause list into arrays of attr indexes and equality
5835 * operators, as wanted by executor
5836 */
5837 Assert(numCols > 0);
5838 dupColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
5839 dupOperators = (Oid *) palloc(sizeof(Oid) * numCols);
5840
5841 foreach(slitem, distinctList)
5842 {
5843 SortGroupClause *sortcl = (SortGroupClause *) lfirst(slitem);
5844 TargetEntry *tle = get_sortgroupclause_tle(sortcl, plan->targetlist);
5845
5846 dupColIdx[keyno] = tle->resno;
5847 dupOperators[keyno] = sortcl->eqop;
5848 Assert(OidIsValid(dupOperators[keyno]));
5849 keyno++;
5850 }
5851
5852 node->cmd = cmd;
5853 node->strategy = strategy;
5854 node->numCols = numCols;
5855 node->dupColIdx = dupColIdx;
5856 node->dupOperators = dupOperators;
5857 node->flagColIdx = flagColIdx;
5858 node->firstFlag = firstFlag;
5859 node->numGroups = numGroups;
5860
5861 return node;
5862 }
5863
5864 /*
5865 * make_lockrows
5866 * Build a LockRows plan node
5867 */
5868 static LockRows *
make_lockrows(Plan * lefttree,List * rowMarks,int epqParam)5869 make_lockrows(Plan *lefttree, List *rowMarks, int epqParam)
5870 {
5871 LockRows *node = makeNode(LockRows);
5872 Plan *plan = &node->plan;
5873
5874 plan->targetlist = lefttree->targetlist;
5875 plan->qual = NIL;
5876 plan->lefttree = lefttree;
5877 plan->righttree = NULL;
5878
5879 node->rowMarks = rowMarks;
5880 node->epqParam = epqParam;
5881
5882 return node;
5883 }
5884
5885 /*
5886 * make_limit
5887 * Build a Limit plan node
5888 */
5889 Limit *
make_limit(Plan * lefttree,Node * limitOffset,Node * limitCount)5890 make_limit(Plan *lefttree, Node *limitOffset, Node *limitCount)
5891 {
5892 Limit *node = makeNode(Limit);
5893 Plan *plan = &node->plan;
5894
5895 plan->targetlist = lefttree->targetlist;
5896 plan->qual = NIL;
5897 plan->lefttree = lefttree;
5898 plan->righttree = NULL;
5899
5900 node->limitOffset = limitOffset;
5901 node->limitCount = limitCount;
5902
5903 return node;
5904 }
5905
5906 /*
5907 * make_result
5908 * Build a Result plan node
5909 */
5910 static Result *
make_result(List * tlist,Node * resconstantqual,Plan * subplan)5911 make_result(List *tlist,
5912 Node *resconstantqual,
5913 Plan *subplan)
5914 {
5915 Result *node = makeNode(Result);
5916 Plan *plan = &node->plan;
5917
5918 plan->targetlist = tlist;
5919 plan->qual = NIL;
5920 plan->lefttree = subplan;
5921 plan->righttree = NULL;
5922 node->resconstantqual = resconstantqual;
5923
5924 return node;
5925 }
5926
5927 /*
5928 * make_modifytable
5929 * Build a ModifyTable plan node
5930 */
5931 static ModifyTable *
make_modifytable(PlannerInfo * root,CmdType operation,bool canSetTag,Index nominalRelation,List * resultRelations,List * subplans,List * withCheckOptionLists,List * returningLists,List * rowMarks,OnConflictExpr * onconflict,int epqParam)5932 make_modifytable(PlannerInfo *root,
5933 CmdType operation, bool canSetTag,
5934 Index nominalRelation,
5935 List *resultRelations, List *subplans,
5936 List *withCheckOptionLists, List *returningLists,
5937 List *rowMarks, OnConflictExpr *onconflict, int epqParam)
5938 {
5939 ModifyTable *node = makeNode(ModifyTable);
5940 List *fdw_private_list;
5941 Bitmapset *direct_modify_plans;
5942 ListCell *lc;
5943 int i;
5944
5945 Assert(list_length(resultRelations) == list_length(subplans));
5946 Assert(withCheckOptionLists == NIL ||
5947 list_length(resultRelations) == list_length(withCheckOptionLists));
5948 Assert(returningLists == NIL ||
5949 list_length(resultRelations) == list_length(returningLists));
5950
5951 node->plan.lefttree = NULL;
5952 node->plan.righttree = NULL;
5953 node->plan.qual = NIL;
5954 /* setrefs.c will fill in the targetlist, if needed */
5955 node->plan.targetlist = NIL;
5956
5957 node->operation = operation;
5958 node->canSetTag = canSetTag;
5959 node->nominalRelation = nominalRelation;
5960 node->resultRelations = resultRelations;
5961 node->resultRelIndex = -1; /* will be set correctly in setrefs.c */
5962 node->plans = subplans;
5963 if (!onconflict)
5964 {
5965 node->onConflictAction = ONCONFLICT_NONE;
5966 node->onConflictSet = NIL;
5967 node->onConflictWhere = NULL;
5968 node->arbiterIndexes = NIL;
5969 node->exclRelRTI = 0;
5970 node->exclRelTlist = NIL;
5971 }
5972 else
5973 {
5974 node->onConflictAction = onconflict->action;
5975 node->onConflictSet = onconflict->onConflictSet;
5976 node->onConflictWhere = onconflict->onConflictWhere;
5977
5978 /*
5979 * If a set of unique index inference elements was provided (an
5980 * INSERT...ON CONFLICT "inference specification"), then infer
5981 * appropriate unique indexes (or throw an error if none are
5982 * available).
5983 */
5984 node->arbiterIndexes = infer_arbiter_indexes(root);
5985
5986 node->exclRelRTI = onconflict->exclRelIndex;
5987 node->exclRelTlist = onconflict->exclRelTlist;
5988 }
5989 node->withCheckOptionLists = withCheckOptionLists;
5990 node->returningLists = returningLists;
5991 node->rowMarks = rowMarks;
5992 node->epqParam = epqParam;
5993
5994 /*
5995 * For each result relation that is a foreign table, allow the FDW to
5996 * construct private plan data, and accumulate it all into a list.
5997 */
5998 fdw_private_list = NIL;
5999 direct_modify_plans = NULL;
6000 i = 0;
6001 foreach(lc, resultRelations)
6002 {
6003 Index rti = lfirst_int(lc);
6004 FdwRoutine *fdwroutine;
6005 List *fdw_private;
6006 bool direct_modify;
6007
6008 /*
6009 * If possible, we want to get the FdwRoutine from our RelOptInfo for
6010 * the table. But sometimes we don't have a RelOptInfo and must get
6011 * it the hard way. (In INSERT, the target relation is not scanned,
6012 * so it's not a baserel; and there are also corner cases for
6013 * updatable views where the target rel isn't a baserel.)
6014 */
6015 if (rti < root->simple_rel_array_size &&
6016 root->simple_rel_array[rti] != NULL)
6017 {
6018 RelOptInfo *resultRel = root->simple_rel_array[rti];
6019
6020 fdwroutine = resultRel->fdwroutine;
6021 }
6022 else
6023 {
6024 RangeTblEntry *rte = planner_rt_fetch(rti, root);
6025
6026 Assert(rte->rtekind == RTE_RELATION);
6027 if (rte->relkind == RELKIND_FOREIGN_TABLE)
6028 fdwroutine = GetFdwRoutineByRelId(rte->relid);
6029 else
6030 fdwroutine = NULL;
6031 }
6032
6033 /*
6034 * Try to modify the foreign table directly if (1) the FDW provides
6035 * callback functions needed for that, (2) there are no row-level
6036 * triggers on the foreign table, and (3) there are no WITH CHECK
6037 * OPTIONs from parent views.
6038 */
6039 direct_modify = false;
6040 if (fdwroutine != NULL &&
6041 fdwroutine->PlanDirectModify != NULL &&
6042 fdwroutine->BeginDirectModify != NULL &&
6043 fdwroutine->IterateDirectModify != NULL &&
6044 fdwroutine->EndDirectModify != NULL &&
6045 withCheckOptionLists == NIL &&
6046 !has_row_triggers(root, rti, operation))
6047 direct_modify = fdwroutine->PlanDirectModify(root, node, rti, i);
6048 if (direct_modify)
6049 direct_modify_plans = bms_add_member(direct_modify_plans, i);
6050
6051 if (!direct_modify &&
6052 fdwroutine != NULL &&
6053 fdwroutine->PlanForeignModify != NULL)
6054 fdw_private = fdwroutine->PlanForeignModify(root, node, rti, i);
6055 else
6056 fdw_private = NIL;
6057 fdw_private_list = lappend(fdw_private_list, fdw_private);
6058 i++;
6059 }
6060 node->fdwPrivLists = fdw_private_list;
6061 node->fdwDirectModifyPlans = direct_modify_plans;
6062
6063 return node;
6064 }
6065
6066 /*
6067 * is_projection_capable_path
6068 * Check whether a given Path node is able to do projection.
6069 */
6070 bool
is_projection_capable_path(Path * path)6071 is_projection_capable_path(Path *path)
6072 {
6073 /* Most plan types can project, so just list the ones that can't */
6074 switch (path->pathtype)
6075 {
6076 case T_Hash:
6077 case T_Material:
6078 case T_Sort:
6079 case T_Unique:
6080 case T_SetOp:
6081 case T_LockRows:
6082 case T_Limit:
6083 case T_ModifyTable:
6084 case T_MergeAppend:
6085 case T_RecursiveUnion:
6086 return false;
6087 case T_Append:
6088
6089 /*
6090 * Append can't project, but if it's being used to represent a
6091 * dummy path, claim that it can project. This prevents us from
6092 * converting a rel from dummy to non-dummy status by applying a
6093 * projection to its dummy path.
6094 */
6095 return IS_DUMMY_PATH(path);
6096 default:
6097 break;
6098 }
6099 return true;
6100 }
6101
6102 /*
6103 * is_projection_capable_plan
6104 * Check whether a given Plan node is able to do projection.
6105 */
6106 bool
is_projection_capable_plan(Plan * plan)6107 is_projection_capable_plan(Plan *plan)
6108 {
6109 /* Most plan types can project, so just list the ones that can't */
6110 switch (nodeTag(plan))
6111 {
6112 case T_Hash:
6113 case T_Material:
6114 case T_Sort:
6115 case T_Unique:
6116 case T_SetOp:
6117 case T_LockRows:
6118 case T_Limit:
6119 case T_ModifyTable:
6120 case T_Append:
6121 case T_MergeAppend:
6122 case T_RecursiveUnion:
6123 return false;
6124 default:
6125 break;
6126 }
6127 return true;
6128 }
6129