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