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