PostgreSQL Source Code git master
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
4525 /*
4526 * We can assert that the outer path is not already ordered
4527 * appropriately for the mergejoin; otherwise, outersortkeys would
4528 * have been set to NIL.
4529 */
4531 outer_path->pathkeys));
4532
4533 /*
4534 * We choose to use incremental sort if it is enabled and there are
4535 * presorted keys; otherwise we use full sort.
4536 */
4537 if (enable_incremental_sort && best_path->outer_presorted_keys > 0)
4538 {
4539 sort_plan = (Plan *)
4541 best_path->outersortkeys,
4542 outer_relids,
4543 best_path->outer_presorted_keys);
4544
4546 (IncrementalSort *) sort_plan,
4547 best_path->outersortkeys,
4548 -1.0);
4549 }
4550 else
4551 {
4552 sort_plan = (Plan *)
4553 make_sort_from_pathkeys(outer_plan,
4554 best_path->outersortkeys,
4555 outer_relids);
4556
4557 label_sort_with_costsize(root, (Sort *) sort_plan, -1.0);
4558 }
4559
4560 outer_plan = sort_plan;
4561 outerpathkeys = best_path->outersortkeys;
4562 }
4563 else
4564 outerpathkeys = best_path->jpath.outerjoinpath->pathkeys;
4565
4566 if (best_path->innersortkeys)
4567 {
4568 /*
4569 * We do not consider incremental sort for inner path, because
4570 * incremental sort does not support mark/restore.
4571 */
4572
4573 Relids inner_relids = inner_path->parent->relids;
4574 Sort *sort;
4575
4576 /*
4577 * We can assert that the inner path is not already ordered
4578 * appropriately for the mergejoin; otherwise, innersortkeys would
4579 * have been set to NIL.
4580 */
4582 inner_path->pathkeys));
4583
4584 sort = make_sort_from_pathkeys(inner_plan,
4585 best_path->innersortkeys,
4586 inner_relids);
4587
4589 inner_plan = (Plan *) sort;
4590 innerpathkeys = best_path->innersortkeys;
4591 }
4592 else
4593 innerpathkeys = best_path->jpath.innerjoinpath->pathkeys;
4594
4595 /*
4596 * If specified, add a materialize node to shield the inner plan from the
4597 * need to handle mark/restore.
4598 */
4599 if (best_path->materialize_inner)
4600 {
4601 Plan *matplan = (Plan *) make_material(inner_plan);
4602
4603 /*
4604 * We assume the materialize will not spill to disk, and therefore
4605 * charge just cpu_operator_cost per tuple. (Keep this estimate in
4606 * sync with final_cost_mergejoin.)
4607 */
4608 copy_plan_costsize(matplan, inner_plan);
4609 matplan->total_cost += cpu_operator_cost * matplan->plan_rows;
4610
4611 inner_plan = matplan;
4612 }
4613
4614 /*
4615 * Compute the opfamily/collation/strategy/nullsfirst arrays needed by the
4616 * executor. The information is in the pathkeys for the two inputs, but
4617 * we need to be careful about the possibility of mergeclauses sharing a
4618 * pathkey, as well as the possibility that the inner pathkeys are not in
4619 * an order matching the mergeclauses.
4620 */
4621 nClauses = list_length(mergeclauses);
4622 Assert(nClauses == list_length(best_path->path_mergeclauses));
4623 mergefamilies = (Oid *) palloc(nClauses * sizeof(Oid));
4624 mergecollations = (Oid *) palloc(nClauses * sizeof(Oid));
4625 mergereversals = (bool *) palloc(nClauses * sizeof(bool));
4626 mergenullsfirst = (bool *) palloc(nClauses * sizeof(bool));
4627
4628 opathkey = NULL;
4629 opeclass = NULL;
4630 lop = list_head(outerpathkeys);
4631 lip = list_head(innerpathkeys);
4632 i = 0;
4633 foreach(lc, best_path->path_mergeclauses)
4634 {
4636 EquivalenceClass *oeclass;
4637 EquivalenceClass *ieclass;
4638 PathKey *ipathkey = NULL;
4639 EquivalenceClass *ipeclass = NULL;
4640 bool first_inner_match = false;
4641
4642 /* fetch outer/inner eclass from mergeclause */
4643 if (rinfo->outer_is_left)
4644 {
4645 oeclass = rinfo->left_ec;
4646 ieclass = rinfo->right_ec;
4647 }
4648 else
4649 {
4650 oeclass = rinfo->right_ec;
4651 ieclass = rinfo->left_ec;
4652 }
4653 Assert(oeclass != NULL);
4654 Assert(ieclass != NULL);
4655
4656 /*
4657 * We must identify the pathkey elements associated with this clause
4658 * by matching the eclasses (which should give a unique match, since
4659 * the pathkey lists should be canonical). In typical cases the merge
4660 * clauses are one-to-one with the pathkeys, but when dealing with
4661 * partially redundant query conditions, things are more complicated.
4662 *
4663 * lop and lip reference the first as-yet-unmatched pathkey elements.
4664 * If they're NULL then all pathkey elements have been matched.
4665 *
4666 * The ordering of the outer pathkeys should match the mergeclauses,
4667 * by construction (see find_mergeclauses_for_outer_pathkeys()). There
4668 * could be more than one mergeclause for the same outer pathkey, but
4669 * no pathkey may be entirely skipped over.
4670 */
4671 if (oeclass != opeclass) /* multiple matches are not interesting */
4672 {
4673 /* doesn't match the current opathkey, so must match the next */
4674 if (lop == NULL)
4675 elog(ERROR, "outer pathkeys do not match mergeclauses");
4676 opathkey = (PathKey *) lfirst(lop);
4677 opeclass = opathkey->pk_eclass;
4678 lop = lnext(outerpathkeys, lop);
4679 if (oeclass != opeclass)
4680 elog(ERROR, "outer pathkeys do not match mergeclauses");
4681 }
4682
4683 /*
4684 * The inner pathkeys likewise should not have skipped-over keys, but
4685 * it's possible for a mergeclause to reference some earlier inner
4686 * pathkey if we had redundant pathkeys. For example we might have
4687 * mergeclauses like "o.a = i.x AND o.b = i.y AND o.c = i.x". The
4688 * implied inner ordering is then "ORDER BY x, y, x", but the pathkey
4689 * mechanism drops the second sort by x as redundant, and this code
4690 * must cope.
4691 *
4692 * It's also possible for the implied inner-rel ordering to be like
4693 * "ORDER BY x, y, x DESC". We still drop the second instance of x as
4694 * redundant; but this means that the sort ordering of a redundant
4695 * inner pathkey should not be considered significant. So we must
4696 * detect whether this is the first clause matching an inner pathkey.
4697 */
4698 if (lip)
4699 {
4700 ipathkey = (PathKey *) lfirst(lip);
4701 ipeclass = ipathkey->pk_eclass;
4702 if (ieclass == ipeclass)
4703 {
4704 /* successful first match to this inner pathkey */
4705 lip = lnext(innerpathkeys, lip);
4706 first_inner_match = true;
4707 }
4708 }
4709 if (!first_inner_match)
4710 {
4711 /* redundant clause ... must match something before lip */
4712 ListCell *l2;
4713
4714 foreach(l2, innerpathkeys)
4715 {
4716 if (l2 == lip)
4717 break;
4718 ipathkey = (PathKey *) lfirst(l2);
4719 ipeclass = ipathkey->pk_eclass;
4720 if (ieclass == ipeclass)
4721 break;
4722 }
4723 if (ieclass != ipeclass)
4724 elog(ERROR, "inner pathkeys do not match mergeclauses");
4725 }
4726
4727 /*
4728 * The pathkeys should always match each other as to opfamily and
4729 * collation (which affect equality), but if we're considering a
4730 * redundant inner pathkey, its sort ordering might not match. In
4731 * such cases we may ignore the inner pathkey's sort ordering and use
4732 * the outer's. (In effect, we're lying to the executor about the
4733 * sort direction of this inner column, but it does not matter since
4734 * the run-time row comparisons would only reach this column when
4735 * there's equality for the earlier column containing the same eclass.
4736 * There could be only one value in this column for the range of inner
4737 * rows having a given value in the earlier column, so it does not
4738 * matter which way we imagine this column to be ordered.) But a
4739 * non-redundant inner pathkey had better match outer's ordering too.
4740 */
4741 if (opathkey->pk_opfamily != ipathkey->pk_opfamily ||
4742 opathkey->pk_eclass->ec_collation != ipathkey->pk_eclass->ec_collation)
4743 elog(ERROR, "left and right pathkeys do not match in mergejoin");
4744 if (first_inner_match &&
4745 (opathkey->pk_cmptype != ipathkey->pk_cmptype ||
4746 opathkey->pk_nulls_first != ipathkey->pk_nulls_first))
4747 elog(ERROR, "left and right pathkeys do not match in mergejoin");
4748
4749 /* OK, save info for executor */
4750 mergefamilies[i] = opathkey->pk_opfamily;
4751 mergecollations[i] = opathkey->pk_eclass->ec_collation;
4752 mergereversals[i] = (opathkey->pk_cmptype == COMPARE_GT ? true : false);
4753 mergenullsfirst[i] = opathkey->pk_nulls_first;
4754 i++;
4755 }
4756
4757 /*
4758 * Note: it is not an error if we have additional pathkey elements (i.e.,
4759 * lop or lip isn't NULL here). The input paths might be better-sorted
4760 * than we need for the current mergejoin.
4761 */
4762
4763 /*
4764 * Now we can build the mergejoin node.
4765 */
4766 join_plan = make_mergejoin(tlist,
4767 joinclauses,
4768 otherclauses,
4769 mergeclauses,
4770 mergefamilies,
4771 mergecollations,
4772 mergereversals,
4773 mergenullsfirst,
4774 outer_plan,
4775 inner_plan,
4776 best_path->jpath.jointype,
4777 best_path->jpath.inner_unique,
4778 best_path->skip_mark_restore);
4779
4780 /* Costs of sort and material steps are included in path cost already */
4781 copy_generic_path_info(&join_plan->join.plan, &best_path->jpath.path);
4782
4783 return join_plan;
4784}
4785
4786static HashJoin *
4788 HashPath *best_path)
4789{
4790 HashJoin *join_plan;
4791 Hash *hash_plan;
4792 Plan *outer_plan;
4793 Plan *inner_plan;
4794 List *tlist = build_path_tlist(root, &best_path->jpath.path);
4795 List *joinclauses;
4796 List *otherclauses;
4797 List *hashclauses;
4798 List *hashoperators = NIL;
4799 List *hashcollations = NIL;
4800 List *inner_hashkeys = NIL;
4801 List *outer_hashkeys = NIL;
4802 Oid skewTable = InvalidOid;
4803 AttrNumber skewColumn = InvalidAttrNumber;
4804 bool skewInherit = false;
4805 ListCell *lc;
4806
4807 /*
4808 * HashJoin can project, so we don't have to demand exact tlists from the
4809 * inputs. However, it's best to request a small tlist from the inner
4810 * side, so that we aren't storing more data than necessary. Likewise, if
4811 * we anticipate batching, request a small tlist from the outer side so
4812 * that we don't put extra data in the outer batch files.
4813 */
4814 outer_plan = create_plan_recurse(root, best_path->jpath.outerjoinpath,
4815 (best_path->num_batches > 1) ? CP_SMALL_TLIST : 0);
4816
4817 inner_plan = create_plan_recurse(root, best_path->jpath.innerjoinpath,
4819
4820 /* Sort join qual clauses into best execution order */
4821 joinclauses = order_qual_clauses(root, best_path->jpath.joinrestrictinfo);
4822 /* There's no point in sorting the hash clauses ... */
4823
4824 /* Get the join qual clauses (in plain expression form) */
4825 /* Any pseudoconstant clauses are ignored here */
4826 if (IS_OUTER_JOIN(best_path->jpath.jointype))
4827 {
4828 extract_actual_join_clauses(joinclauses,
4829 best_path->jpath.path.parent->relids,
4830 &joinclauses, &otherclauses);
4831 }
4832 else
4833 {
4834 /* We can treat all clauses alike for an inner join */
4835 joinclauses = extract_actual_clauses(joinclauses, false);
4836 otherclauses = NIL;
4837 }
4838
4839 /*
4840 * Remove the hashclauses from the list of join qual clauses, leaving the
4841 * list of quals that must be checked as qpquals.
4842 */
4843 hashclauses = get_actual_clauses(best_path->path_hashclauses);
4844 joinclauses = list_difference(joinclauses, hashclauses);
4845
4846 /*
4847 * Replace any outer-relation variables with nestloop params. There
4848 * should not be any in the hashclauses.
4849 */
4850 if (best_path->jpath.path.param_info)
4851 {
4852 joinclauses = (List *)
4853 replace_nestloop_params(root, (Node *) joinclauses);
4854 otherclauses = (List *)
4855 replace_nestloop_params(root, (Node *) otherclauses);
4856 }
4857
4858 /*
4859 * Rearrange hashclauses, if needed, so that the outer variable is always
4860 * on the left.
4861 */
4862 hashclauses = get_switched_clauses(best_path->path_hashclauses,
4863 best_path->jpath.outerjoinpath->parent->relids);
4864
4865 /*
4866 * If there is a single join clause and we can identify the outer variable
4867 * as a simple column reference, supply its identity for possible use in
4868 * skew optimization. (Note: in principle we could do skew optimization
4869 * with multiple join clauses, but we'd have to be able to determine the
4870 * most common combinations of outer values, which we don't currently have
4871 * enough stats for.)
4872 */
4873 if (list_length(hashclauses) == 1)
4874 {
4875 OpExpr *clause = (OpExpr *) linitial(hashclauses);
4876 Node *node;
4877
4878 Assert(is_opclause(clause));
4879 node = (Node *) linitial(clause->args);
4880 if (IsA(node, RelabelType))
4881 node = (Node *) ((RelabelType *) node)->arg;
4882 if (IsA(node, Var))
4883 {
4884 Var *var = (Var *) node;
4885 RangeTblEntry *rte;
4886
4887 rte = root->simple_rte_array[var->varno];
4888 if (rte->rtekind == RTE_RELATION)
4889 {
4890 skewTable = rte->relid;
4891 skewColumn = var->varattno;
4892 skewInherit = rte->inh;
4893 }
4894 }
4895 }
4896
4897 /*
4898 * Collect hash related information. The hashed expressions are
4899 * deconstructed into outer/inner expressions, so they can be computed
4900 * separately (inner expressions are used to build the hashtable via Hash,
4901 * outer expressions to perform lookups of tuples from HashJoin's outer
4902 * plan in the hashtable). Also collect operator information necessary to
4903 * build the hashtable.
4904 */
4905 foreach(lc, hashclauses)
4906 {
4907 OpExpr *hclause = lfirst_node(OpExpr, lc);
4908
4909 hashoperators = lappend_oid(hashoperators, hclause->opno);
4910 hashcollations = lappend_oid(hashcollations, hclause->inputcollid);
4911 outer_hashkeys = lappend(outer_hashkeys, linitial(hclause->args));
4912 inner_hashkeys = lappend(inner_hashkeys, lsecond(hclause->args));
4913 }
4914
4915 /*
4916 * Build the hash node and hash join node.
4917 */
4918 hash_plan = make_hash(inner_plan,
4919 inner_hashkeys,
4920 skewTable,
4921 skewColumn,
4922 skewInherit);
4923
4924 /*
4925 * Set Hash node's startup & total costs equal to total cost of input
4926 * plan; this only affects EXPLAIN display not decisions.
4927 */
4928 copy_plan_costsize(&hash_plan->plan, inner_plan);
4929 hash_plan->plan.startup_cost = hash_plan->plan.total_cost;
4930
4931 /*
4932 * If parallel-aware, the executor will also need an estimate of the total
4933 * number of rows expected from all participants so that it can size the
4934 * shared hash table.
4935 */
4936 if (best_path->jpath.path.parallel_aware)
4937 {
4938 hash_plan->plan.parallel_aware = true;
4939 hash_plan->rows_total = best_path->inner_rows_total;
4940 }
4941
4942 join_plan = make_hashjoin(tlist,
4943 joinclauses,
4944 otherclauses,
4945 hashclauses,
4946 hashoperators,
4947 hashcollations,
4948 outer_hashkeys,
4949 outer_plan,
4950 (Plan *) hash_plan,
4951 best_path->jpath.jointype,
4952 best_path->jpath.inner_unique);
4953
4954 copy_generic_path_info(&join_plan->join.plan, &best_path->jpath.path);
4955
4956 return join_plan;
4957}
4958
4959
4960/*****************************************************************************
4961 *
4962 * SUPPORTING ROUTINES
4963 *
4964 *****************************************************************************/
4965
4966/*
4967 * replace_nestloop_params
4968 * Replace outer-relation Vars and PlaceHolderVars in the given expression
4969 * with nestloop Params
4970 *
4971 * All Vars and PlaceHolderVars belonging to the relation(s) identified by
4972 * root->curOuterRels are replaced by Params, and entries are added to
4973 * root->curOuterParams if not already present.
4974 */
4975static Node *
4977{
4978 /* No setup needed for tree walk, so away we go */
4980}
4981
4982static Node *
4984{
4985 if (node == NULL)
4986 return NULL;
4987 if (IsA(node, Var))
4988 {
4989 Var *var = (Var *) node;
4990
4991 /* Upper-level Vars should be long gone at this point */
4992 Assert(var->varlevelsup == 0);
4993 /* If not to be replaced, we can just return the Var unmodified */
4994 if (IS_SPECIAL_VARNO(var->varno) ||
4995 !bms_is_member(var->varno, root->curOuterRels))
4996 return node;
4997 /* Replace the Var with a nestloop Param */
4998 return (Node *) replace_nestloop_param_var(root, var);
4999 }
5000 if (IsA(node, PlaceHolderVar))
5001 {
5002 PlaceHolderVar *phv = (PlaceHolderVar *) node;
5003
5004 /* Upper-level PlaceHolderVars should be long gone at this point */
5005 Assert(phv->phlevelsup == 0);
5006
5007 /* Check whether we need to replace the PHV */
5008 if (!bms_is_subset(find_placeholder_info(root, phv)->ph_eval_at,
5009 root->curOuterRels))
5010 {
5011 /*
5012 * We can't replace the whole PHV, but we might still need to
5013 * replace Vars or PHVs within its expression, in case it ends up
5014 * actually getting evaluated here. (It might get evaluated in
5015 * this plan node, or some child node; in the latter case we don't
5016 * really need to process the expression here, but we haven't got
5017 * enough info to tell if that's the case.) Flat-copy the PHV
5018 * node and then recurse on its expression.
5019 *
5020 * Note that after doing this, we might have different
5021 * representations of the contents of the same PHV in different
5022 * parts of the plan tree. This is OK because equal() will just
5023 * match on phid/phlevelsup, so setrefs.c will still recognize an
5024 * upper-level reference to a lower-level copy of the same PHV.
5025 */
5027
5028 memcpy(newphv, phv, sizeof(PlaceHolderVar));
5029 newphv->phexpr = (Expr *)
5030 replace_nestloop_params_mutator((Node *) phv->phexpr,
5031 root);
5032 return (Node *) newphv;
5033 }
5034 /* Replace the PlaceHolderVar with a nestloop Param */
5036 }
5038}
5039
5040/*
5041 * fix_indexqual_references
5042 * Adjust indexqual clauses to the form the executor's indexqual
5043 * machinery needs.
5044 *
5045 * We have three tasks here:
5046 * * Select the actual qual clauses out of the input IndexClause list,
5047 * and remove RestrictInfo nodes from the qual clauses.
5048 * * Replace any outer-relation Var or PHV nodes with nestloop Params.
5049 * (XXX eventually, that responsibility should go elsewhere?)
5050 * * Index keys must be represented by Var nodes with varattno set to the
5051 * index's attribute number, not the attribute number in the original rel.
5052 *
5053 * *stripped_indexquals_p receives a list of the actual qual clauses.
5054 *
5055 * *fixed_indexquals_p receives a list of the adjusted quals. This is a copy
5056 * that shares no substructure with the original; this is needed in case there
5057 * are subplans in it (we need two separate copies of the subplan tree, or
5058 * things will go awry).
5059 */
5060static void
5062 List **stripped_indexquals_p, List **fixed_indexquals_p)
5063{
5064 IndexOptInfo *index = index_path->indexinfo;
5065 List *stripped_indexquals;
5066 List *fixed_indexquals;
5067 ListCell *lc;
5068
5069 stripped_indexquals = fixed_indexquals = NIL;
5070
5071 foreach(lc, index_path->indexclauses)
5072 {
5073 IndexClause *iclause = lfirst_node(IndexClause, lc);
5074 int indexcol = iclause->indexcol;
5075 ListCell *lc2;
5076
5077 foreach(lc2, iclause->indexquals)
5078 {
5079 RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc2);
5080 Node *clause = (Node *) rinfo->clause;
5081
5082 stripped_indexquals = lappend(stripped_indexquals, clause);
5083 clause = fix_indexqual_clause(root, index, indexcol,
5084 clause, iclause->indexcols);
5085 fixed_indexquals = lappend(fixed_indexquals, clause);
5086 }
5087 }
5088
5089 *stripped_indexquals_p = stripped_indexquals;
5090 *fixed_indexquals_p = fixed_indexquals;
5091}
5092
5093/*
5094 * fix_indexorderby_references
5095 * Adjust indexorderby clauses to the form the executor's index
5096 * machinery needs.
5097 *
5098 * This is a simplified version of fix_indexqual_references. The input is
5099 * bare clauses and a separate indexcol list, instead of IndexClauses.
5100 */
5101static List *
5103{
5104 IndexOptInfo *index = index_path->indexinfo;
5105 List *fixed_indexorderbys;
5106 ListCell *lcc,
5107 *lci;
5108
5109 fixed_indexorderbys = NIL;
5110
5111 forboth(lcc, index_path->indexorderbys, lci, index_path->indexorderbycols)
5112 {
5113 Node *clause = (Node *) lfirst(lcc);
5114 int indexcol = lfirst_int(lci);
5115
5116 clause = fix_indexqual_clause(root, index, indexcol, clause, NIL);
5117 fixed_indexorderbys = lappend(fixed_indexorderbys, clause);
5118 }
5119
5120 return fixed_indexorderbys;
5121}
5122
5123/*
5124 * fix_indexqual_clause
5125 * Convert a single indexqual clause to the form needed by the executor.
5126 *
5127 * We replace nestloop params here, and replace the index key variables
5128 * or expressions by index Var nodes.
5129 */
5130static Node *
5132 Node *clause, List *indexcolnos)
5133{
5134 /*
5135 * Replace any outer-relation variables with nestloop params.
5136 *
5137 * This also makes a copy of the clause, so it's safe to modify it
5138 * in-place below.
5139 */
5140 clause = replace_nestloop_params(root, clause);
5141
5142 if (IsA(clause, OpExpr))
5143 {
5144 OpExpr *op = (OpExpr *) clause;
5145
5146 /* Replace the indexkey expression with an index Var. */
5148 index,
5149 indexcol);
5150 }
5151 else if (IsA(clause, RowCompareExpr))
5152 {
5153 RowCompareExpr *rc = (RowCompareExpr *) clause;
5154 ListCell *lca,
5155 *lcai;
5156
5157 /* Replace the indexkey expressions with index Vars. */
5158 Assert(list_length(rc->largs) == list_length(indexcolnos));
5159 forboth(lca, rc->largs, lcai, indexcolnos)
5160 {
5162 index,
5163 lfirst_int(lcai));
5164 }
5165 }
5166 else if (IsA(clause, ScalarArrayOpExpr))
5167 {
5168 ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;
5169
5170 /* Replace the indexkey expression with an index Var. */
5172 index,
5173 indexcol);
5174 }
5175 else if (IsA(clause, NullTest))
5176 {
5177 NullTest *nt = (NullTest *) clause;
5178
5179 /* Replace the indexkey expression with an index Var. */
5180 nt->arg = (Expr *) fix_indexqual_operand((Node *) nt->arg,
5181 index,
5182 indexcol);
5183 }
5184 else
5185 elog(ERROR, "unsupported indexqual type: %d",
5186 (int) nodeTag(clause));
5187
5188 return clause;
5189}
5190
5191/*
5192 * fix_indexqual_operand
5193 * Convert an indexqual expression to a Var referencing the index column.
5194 *
5195 * We represent index keys by Var nodes having varno == INDEX_VAR and varattno
5196 * equal to the index's attribute number (index column position).
5197 *
5198 * Most of the code here is just for sanity cross-checking that the given
5199 * expression actually matches the index column it's claimed to.
5200 */
5201static Node *
5203{
5204 Var *result;
5205 int pos;
5206 ListCell *indexpr_item;
5207
5208 /*
5209 * Remove any binary-compatible relabeling of the indexkey
5210 */
5211 if (IsA(node, RelabelType))
5212 node = (Node *) ((RelabelType *) node)->arg;
5213
5214 Assert(indexcol >= 0 && indexcol < index->ncolumns);
5215
5216 if (index->indexkeys[indexcol] != 0)
5217 {
5218 /* It's a simple index column */
5219 if (IsA(node, Var) &&
5220 ((Var *) node)->varno == index->rel->relid &&
5221 ((Var *) node)->varattno == index->indexkeys[indexcol])
5222 {
5223 result = (Var *) copyObject(node);
5224 result->varno = INDEX_VAR;
5225 result->varattno = indexcol + 1;
5226 return (Node *) result;
5227 }
5228 else
5229 elog(ERROR, "index key does not match expected index column");
5230 }
5231
5232 /* It's an index expression, so find and cross-check the expression */
5233 indexpr_item = list_head(index->indexprs);
5234 for (pos = 0; pos < index->ncolumns; pos++)
5235 {
5236 if (index->indexkeys[pos] == 0)
5237 {
5238 if (indexpr_item == NULL)
5239 elog(ERROR, "too few entries in indexprs list");
5240 if (pos == indexcol)
5241 {
5242 Node *indexkey;
5243
5244 indexkey = (Node *) lfirst(indexpr_item);
5245 if (indexkey && IsA(indexkey, RelabelType))
5246 indexkey = (Node *) ((RelabelType *) indexkey)->arg;
5247 if (equal(node, indexkey))
5248 {
5249 result = makeVar(INDEX_VAR, indexcol + 1,
5250 exprType(lfirst(indexpr_item)), -1,
5251 exprCollation(lfirst(indexpr_item)),
5252 0);
5253 return (Node *) result;
5254 }
5255 else
5256 elog(ERROR, "index key does not match expected index column");
5257 }
5258 indexpr_item = lnext(index->indexprs, indexpr_item);
5259 }
5260 }
5261
5262 /* Oops... */
5263 elog(ERROR, "index key does not match expected index column");
5264 return NULL; /* keep compiler quiet */
5265}
5266
5267/*
5268 * get_switched_clauses
5269 * Given a list of merge or hash joinclauses (as RestrictInfo nodes),
5270 * extract the bare clauses, and rearrange the elements within the
5271 * clauses, if needed, so the outer join variable is on the left and
5272 * the inner is on the right. The original clause data structure is not
5273 * touched; a modified list is returned. We do, however, set the transient
5274 * outer_is_left field in each RestrictInfo to show which side was which.
5275 */
5276static List *
5277get_switched_clauses(List *clauses, Relids outerrelids)
5278{
5279 List *t_list = NIL;
5280 ListCell *l;
5281
5282 foreach(l, clauses)
5283 {
5284 RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(l);
5285 OpExpr *clause = (OpExpr *) restrictinfo->clause;
5286
5287 Assert(is_opclause(clause));
5288 if (bms_is_subset(restrictinfo->right_relids, outerrelids))
5289 {
5290 /*
5291 * Duplicate just enough of the structure to allow commuting the
5292 * clause without changing the original list. Could use
5293 * copyObject, but a complete deep copy is overkill.
5294 */
5295 OpExpr *temp = makeNode(OpExpr);
5296
5297 temp->opno = clause->opno;
5298 temp->opfuncid = InvalidOid;
5299 temp->opresulttype = clause->opresulttype;
5300 temp->opretset = clause->opretset;
5301 temp->opcollid = clause->opcollid;
5302 temp->inputcollid = clause->inputcollid;
5303 temp->args = list_copy(clause->args);
5304 temp->location = clause->location;
5305 /* Commute it --- note this modifies the temp node in-place. */
5306 CommuteOpExpr(temp);
5307 t_list = lappend(t_list, temp);
5308 restrictinfo->outer_is_left = false;
5309 }
5310 else
5311 {
5312 Assert(bms_is_subset(restrictinfo->left_relids, outerrelids));
5313 t_list = lappend(t_list, clause);
5314 restrictinfo->outer_is_left = true;
5315 }
5316 }
5317 return t_list;
5318}
5319
5320/*
5321 * order_qual_clauses
5322 * Given a list of qual clauses that will all be evaluated at the same
5323 * plan node, sort the list into the order we want to check the quals
5324 * in at runtime.
5325 *
5326 * When security barrier quals are used in the query, we may have quals with
5327 * different security levels in the list. Quals of lower security_level
5328 * must go before quals of higher security_level, except that we can grant
5329 * exceptions to move up quals that are leakproof. When security level
5330 * doesn't force the decision, we prefer to order clauses by estimated
5331 * execution cost, cheapest first.
5332 *
5333 * Ideally the order should be driven by a combination of execution cost and
5334 * selectivity, but it's not immediately clear how to account for both,
5335 * and given the uncertainty of the estimates the reliability of the decisions
5336 * would be doubtful anyway. So we just order by security level then
5337 * estimated per-tuple cost, being careful not to change the order when
5338 * (as is often the case) the estimates are identical.
5339 *
5340 * Although this will work on either bare clauses or RestrictInfos, it's
5341 * much faster to apply it to RestrictInfos, since it can re-use cost
5342 * information that is cached in RestrictInfos. XXX in the bare-clause
5343 * case, we are also not able to apply security considerations. That is
5344 * all right for the moment, because the bare-clause case doesn't occur
5345 * anywhere that barrier quals could be present, but it would be better to
5346 * get rid of it.
5347 *
5348 * Note: some callers pass lists that contain entries that will later be
5349 * removed; this is the easiest way to let this routine see RestrictInfos
5350 * instead of bare clauses. This is another reason why trying to consider
5351 * selectivity in the ordering would likely do the wrong thing.
5352 */
5353static List *
5355{
5356 typedef struct
5357 {
5358 Node *clause;
5359 Cost cost;
5360 Index security_level;
5361 } QualItem;
5362 int nitems = list_length(clauses);
5363 QualItem *items;
5364 ListCell *lc;
5365 int i;
5366 List *result;
5367
5368 /* No need to work hard for 0 or 1 clause */
5369 if (nitems <= 1)
5370 return clauses;
5371
5372 /*
5373 * Collect the items and costs into an array. This is to avoid repeated
5374 * cost_qual_eval work if the inputs aren't RestrictInfos.
5375 */
5376 items = (QualItem *) palloc(nitems * sizeof(QualItem));
5377 i = 0;
5378 foreach(lc, clauses)
5379 {
5380 Node *clause = (Node *) lfirst(lc);
5381 QualCost qcost;
5382
5383 cost_qual_eval_node(&qcost, clause, root);
5384 items[i].clause = clause;
5385 items[i].cost = qcost.per_tuple;
5386 if (IsA(clause, RestrictInfo))
5387 {
5388 RestrictInfo *rinfo = (RestrictInfo *) clause;
5389
5390 /*
5391 * If a clause is leakproof, it doesn't have to be constrained by
5392 * its nominal security level. If it's also reasonably cheap
5393 * (here defined as 10X cpu_operator_cost), pretend it has
5394 * security_level 0, which will allow it to go in front of
5395 * more-expensive quals of lower security levels. Of course, that
5396 * will also force it to go in front of cheaper quals of its own
5397 * security level, which is not so great, but we can alleviate
5398 * that risk by applying the cost limit cutoff.
5399 */
5400 if (rinfo->leakproof && items[i].cost < 10 * cpu_operator_cost)
5401 items[i].security_level = 0;
5402 else
5403 items[i].security_level = rinfo->security_level;
5404 }
5405 else
5406 items[i].security_level = 0;
5407 i++;
5408 }
5409
5410 /*
5411 * Sort. We don't use qsort() because it's not guaranteed stable for
5412 * equal keys. The expected number of entries is small enough that a
5413 * simple insertion sort should be good enough.
5414 */
5415 for (i = 1; i < nitems; i++)
5416 {
5417 QualItem newitem = items[i];
5418 int j;
5419
5420 /* insert newitem into the already-sorted subarray */
5421 for (j = i; j > 0; j--)
5422 {
5423 QualItem *olditem = &items[j - 1];
5424
5425 if (newitem.security_level > olditem->security_level ||
5426 (newitem.security_level == olditem->security_level &&
5427 newitem.cost >= olditem->cost))
5428 break;
5429 items[j] = *olditem;
5430 }
5431 items[j] = newitem;
5432 }
5433
5434 /* Convert back to a list */
5435 result = NIL;
5436 for (i = 0; i < nitems; i++)
5437 result = lappend(result, items[i].clause);
5438
5439 return result;
5440}
5441
5442/*
5443 * Copy cost and size info from a Path node to the Plan node created from it.
5444 * The executor usually won't use this info, but it's needed by EXPLAIN.
5445 * Also copy the parallel-related flags, which the executor *will* use.
5446 */
5447static void
5449{
5450 dest->disabled_nodes = src->disabled_nodes;
5451 dest->startup_cost = src->startup_cost;
5452 dest->total_cost = src->total_cost;
5453 dest->plan_rows = src->rows;
5454 dest->plan_width = src->pathtarget->width;
5455 dest->parallel_aware = src->parallel_aware;
5456 dest->parallel_safe = src->parallel_safe;
5457}
5458
5459/*
5460 * Copy cost and size info from a lower plan node to an inserted node.
5461 * (Most callers alter the info after copying it.)
5462 */
5463static void
5465{
5466 dest->disabled_nodes = src->disabled_nodes;
5467 dest->startup_cost = src->startup_cost;
5468 dest->total_cost = src->total_cost;
5469 dest->plan_rows = src->plan_rows;
5470 dest->plan_width = src->plan_width;
5471 /* Assume the inserted node is not parallel-aware. */
5472 dest->parallel_aware = false;
5473 /* Assume the inserted node is parallel-safe, if child plan is. */
5474 dest->parallel_safe = src->parallel_safe;
5475}
5476
5477/*
5478 * Some places in this file build Sort nodes that don't have a directly
5479 * corresponding Path node. The cost of the sort is, or should have been,
5480 * included in the cost of the Path node we're working from, but since it's
5481 * not split out, we have to re-figure it using cost_sort(). This is just
5482 * to label the Sort node nicely for EXPLAIN.
5483 *
5484 * limit_tuples is as for cost_sort (in particular, pass -1 if no limit)
5485 */
5486static void
5488{
5489 Plan *lefttree = plan->plan.lefttree;
5490 Path sort_path; /* dummy for result of cost_sort */
5491
5492 Assert(IsA(plan, Sort));
5493
5494 cost_sort(&sort_path, root, NIL,
5495 plan->plan.disabled_nodes,
5496 lefttree->total_cost,
5497 lefttree->plan_rows,
5498 lefttree->plan_width,
5499 0.0,
5500 work_mem,
5501 limit_tuples);
5502 plan->plan.startup_cost = sort_path.startup_cost;
5503 plan->plan.total_cost = sort_path.total_cost;
5504 plan->plan.plan_rows = lefttree->plan_rows;
5505 plan->plan.plan_width = lefttree->plan_width;
5506 plan->plan.parallel_aware = false;
5507 plan->plan.parallel_safe = lefttree->parallel_safe;
5508}
5509
5510/*
5511 * Same as label_sort_with_costsize, but labels the IncrementalSort node
5512 * instead.
5513 */
5514static void
5516 List *pathkeys, double limit_tuples)
5517{
5518 Plan *lefttree = plan->sort.plan.lefttree;
5519 Path sort_path; /* dummy for result of cost_incremental_sort */
5520
5522
5523 cost_incremental_sort(&sort_path, root, pathkeys,
5524 plan->nPresortedCols,
5525 plan->sort.plan.disabled_nodes,
5526 lefttree->startup_cost,
5527 lefttree->total_cost,
5528 lefttree->plan_rows,
5529 lefttree->plan_width,
5530 0.0,
5531 work_mem,
5532 limit_tuples);
5533 plan->sort.plan.startup_cost = sort_path.startup_cost;
5534 plan->sort.plan.total_cost = sort_path.total_cost;
5535 plan->sort.plan.plan_rows = lefttree->plan_rows;
5536 plan->sort.plan.plan_width = lefttree->plan_width;
5537 plan->sort.plan.parallel_aware = false;
5538 plan->sort.plan.parallel_safe = lefttree->parallel_safe;
5539}
5540
5541/*
5542 * bitmap_subplan_mark_shared
5543 * Set isshared flag in bitmap subplan so that it will be created in
5544 * shared memory.
5545 */
5546static void
5548{
5549 if (IsA(plan, BitmapAnd))
5551 else if (IsA(plan, BitmapOr))
5552 {
5553 ((BitmapOr *) plan)->isshared = true;
5554 bitmap_subplan_mark_shared(linitial(((BitmapOr *) plan)->bitmapplans));
5555 }
5556 else if (IsA(plan, BitmapIndexScan))
5557 ((BitmapIndexScan *) plan)->isshared = true;
5558 else
5559 elog(ERROR, "unrecognized node type: %d", nodeTag(plan));
5560}
5561
5562/*****************************************************************************
5563 *
5564 * PLAN NODE BUILDING ROUTINES
5565 *
5566 * In general, these functions are not passed the original Path and therefore
5567 * leave it to the caller to fill in the cost/width fields from the Path,
5568 * typically by calling copy_generic_path_info(). This convention is
5569 * somewhat historical, but it does support a few places above where we build
5570 * a plan node without having an exactly corresponding Path node. Under no
5571 * circumstances should one of these functions do its own cost calculations,
5572 * as that would be redundant with calculations done while building Paths.
5573 *
5574 *****************************************************************************/
5575
5576static SeqScan *
5578 List *qpqual,
5579 Index scanrelid)
5580{
5581 SeqScan *node = makeNode(SeqScan);
5582 Plan *plan = &node->scan.plan;
5583
5584 plan->targetlist = qptlist;
5585 plan->qual = qpqual;
5586 plan->lefttree = NULL;
5587 plan->righttree = NULL;
5588 node->scan.scanrelid = scanrelid;
5589
5590 return node;
5591}
5592
5593static SampleScan *
5595 List *qpqual,
5596 Index scanrelid,
5597 TableSampleClause *tsc)
5598{
5600 Plan *plan = &node->scan.plan;
5601
5602 plan->targetlist = qptlist;
5603 plan->qual = qpqual;
5604 plan->lefttree = NULL;
5605 plan->righttree = NULL;
5606 node->scan.scanrelid = scanrelid;
5607 node->tablesample = tsc;
5608
5609 return node;
5610}
5611
5612static IndexScan *
5614 List *qpqual,
5615 Index scanrelid,
5616 Oid indexid,
5617 List *indexqual,
5618 List *indexqualorig,
5619 List *indexorderby,
5620 List *indexorderbyorig,
5621 List *indexorderbyops,
5622 ScanDirection indexscandir)
5623{
5624 IndexScan *node = makeNode(IndexScan);
5625 Plan *plan = &node->scan.plan;
5626
5627 plan->targetlist = qptlist;
5628 plan->qual = qpqual;
5629 plan->lefttree = NULL;
5630 plan->righttree = NULL;
5631 node->scan.scanrelid = scanrelid;
5632 node->indexid = indexid;
5633 node->indexqual = indexqual;
5634 node->indexqualorig = indexqualorig;
5635 node->indexorderby = indexorderby;
5636 node->indexorderbyorig = indexorderbyorig;
5637 node->indexorderbyops = indexorderbyops;
5638 node->indexorderdir = indexscandir;
5639
5640 return node;
5641}
5642
5643static IndexOnlyScan *
5645 List *qpqual,
5646 Index scanrelid,
5647 Oid indexid,
5648 List *indexqual,
5649 List *recheckqual,
5650 List *indexorderby,
5651 List *indextlist,
5652 ScanDirection indexscandir)
5653{
5655 Plan *plan = &node->scan.plan;
5656
5657 plan->targetlist = qptlist;
5658 plan->qual = qpqual;
5659 plan->lefttree = NULL;
5660 plan->righttree = NULL;
5661 node->scan.scanrelid = scanrelid;
5662 node->indexid = indexid;
5663 node->indexqual = indexqual;
5664 node->recheckqual = recheckqual;
5665 node->indexorderby = indexorderby;
5666 node->indextlist = indextlist;
5667 node->indexorderdir = indexscandir;
5668
5669 return node;
5670}
5671
5672static BitmapIndexScan *
5674 Oid indexid,
5675 List *indexqual,
5676 List *indexqualorig)
5677{
5679 Plan *plan = &node->scan.plan;
5680
5681 plan->targetlist = NIL; /* not used */
5682 plan->qual = NIL; /* not used */
5683 plan->lefttree = NULL;
5684 plan->righttree = NULL;
5685 node->scan.scanrelid = scanrelid;
5686 node->indexid = indexid;
5687 node->indexqual = indexqual;
5688 node->indexqualorig = indexqualorig;
5689
5690 return node;
5691}
5692
5693static BitmapHeapScan *
5695 List *qpqual,
5696 Plan *lefttree,
5697 List *bitmapqualorig,
5698 Index scanrelid)
5699{
5701 Plan *plan = &node->scan.plan;
5702
5703 plan->targetlist = qptlist;
5704 plan->qual = qpqual;
5705 plan->lefttree = lefttree;
5706 plan->righttree = NULL;
5707 node->scan.scanrelid = scanrelid;
5708 node->bitmapqualorig = bitmapqualorig;
5709
5710 return node;
5711}
5712
5713static TidScan *
5715 List *qpqual,
5716 Index scanrelid,
5717 List *tidquals)
5718{
5719 TidScan *node = makeNode(TidScan);
5720 Plan *plan = &node->scan.plan;
5721
5722 plan->targetlist = qptlist;
5723 plan->qual = qpqual;
5724 plan->lefttree = NULL;
5725 plan->righttree = NULL;
5726 node->scan.scanrelid = scanrelid;
5727 node->tidquals = tidquals;
5728
5729 return node;
5730}
5731
5732static TidRangeScan *
5734 List *qpqual,
5735 Index scanrelid,
5736 List *tidrangequals)
5737{
5739 Plan *plan = &node->scan.plan;
5740
5741 plan->targetlist = qptlist;
5742 plan->qual = qpqual;
5743 plan->lefttree = NULL;
5744 plan->righttree = NULL;
5745 node->scan.scanrelid = scanrelid;
5746 node->tidrangequals = tidrangequals;
5747
5748 return node;
5749}
5750
5751static SubqueryScan *
5753 List *qpqual,
5754 Index scanrelid,
5755 Plan *subplan)
5756{
5758 Plan *plan = &node->scan.plan;
5759
5760 plan->targetlist = qptlist;
5761 plan->qual = qpqual;
5762 plan->lefttree = NULL;
5763 plan->righttree = NULL;
5764 node->scan.scanrelid = scanrelid;
5765 node->subplan = subplan;
5767
5768 return node;
5769}
5770
5771static FunctionScan *
5773 List *qpqual,
5774 Index scanrelid,
5775 List *functions,
5776 bool funcordinality)
5777{
5779 Plan *plan = &node->scan.plan;
5780
5781 plan->targetlist = qptlist;
5782 plan->qual = qpqual;
5783 plan->lefttree = NULL;
5784 plan->righttree = NULL;
5785 node->scan.scanrelid = scanrelid;
5786 node->functions = functions;
5787 node->funcordinality = funcordinality;
5788
5789 return node;
5790}
5791
5792static TableFuncScan *
5794 List *qpqual,
5795 Index scanrelid,
5796 TableFunc *tablefunc)
5797{
5799 Plan *plan = &node->scan.plan;
5800
5801 plan->targetlist = qptlist;
5802 plan->qual = qpqual;
5803 plan->lefttree = NULL;
5804 plan->righttree = NULL;
5805 node->scan.scanrelid = scanrelid;
5806 node->tablefunc = tablefunc;
5807
5808 return node;
5809}
5810
5811static ValuesScan *
5813 List *qpqual,
5814 Index scanrelid,
5815 List *values_lists)
5816{
5818 Plan *plan = &node->scan.plan;
5819
5820 plan->targetlist = qptlist;
5821 plan->qual = qpqual;
5822 plan->lefttree = NULL;
5823 plan->righttree = NULL;
5824 node->scan.scanrelid = scanrelid;
5825 node->values_lists = values_lists;
5826
5827 return node;
5828}
5829
5830static CteScan *
5832 List *qpqual,
5833 Index scanrelid,
5834 int ctePlanId,
5835 int cteParam)
5836{
5837 CteScan *node = makeNode(CteScan);
5838 Plan *plan = &node->scan.plan;
5839
5840 plan->targetlist = qptlist;
5841 plan->qual = qpqual;
5842 plan->lefttree = NULL;
5843 plan->righttree = NULL;
5844 node->scan.scanrelid = scanrelid;
5845 node->ctePlanId = ctePlanId;
5846 node->cteParam = cteParam;
5847
5848 return node;
5849}
5850
5851static NamedTuplestoreScan *
5853 List *qpqual,
5854 Index scanrelid,
5855 char *enrname)
5856{
5858 Plan *plan = &node->scan.plan;
5859
5860 /* cost should be inserted by caller */
5861 plan->targetlist = qptlist;
5862 plan->qual = qpqual;
5863 plan->lefttree = NULL;
5864 plan->righttree = NULL;
5865 node->scan.scanrelid = scanrelid;
5866 node->enrname = enrname;
5867
5868 return node;
5869}
5870
5871static WorkTableScan *
5873 List *qpqual,
5874 Index scanrelid,
5875 int wtParam)
5876{
5878 Plan *plan = &node->scan.plan;
5879
5880 plan->targetlist = qptlist;
5881 plan->qual = qpqual;
5882 plan->lefttree = NULL;
5883 plan->righttree = NULL;
5884 node->scan.scanrelid = scanrelid;
5885 node->wtParam = wtParam;
5886
5887 return node;
5888}
5889
5892 List *qpqual,
5893 Index scanrelid,
5894 List *fdw_exprs,
5895 List *fdw_private,
5896 List *fdw_scan_tlist,
5897 List *fdw_recheck_quals,
5898 Plan *outer_plan)
5899{
5901 Plan *plan = &node->scan.plan;
5902
5903 /* cost will be filled in by create_foreignscan_plan */
5904 plan->targetlist = qptlist;
5905 plan->qual = qpqual;
5906 plan->lefttree = outer_plan;
5907 plan->righttree = NULL;
5908 node->scan.scanrelid = scanrelid;
5909
5910 /* these may be overridden by the FDW's PlanDirectModify callback. */
5911 node->operation = CMD_SELECT;
5912 node->resultRelation = 0;
5913
5914 /* checkAsUser, fs_server will be filled in by create_foreignscan_plan */
5915 node->checkAsUser = InvalidOid;
5916 node->fs_server = InvalidOid;
5917 node->fdw_exprs = fdw_exprs;
5918 node->fdw_private = fdw_private;
5919 node->fdw_scan_tlist = fdw_scan_tlist;
5920 node->fdw_recheck_quals = fdw_recheck_quals;
5921 /* fs_relids, fs_base_relids will be filled by create_foreignscan_plan */
5922 node->fs_relids = NULL;
5923 node->fs_base_relids = NULL;
5924 /* fsSystemCol will be filled in by create_foreignscan_plan */
5925 node->fsSystemCol = false;
5926
5927 return node;
5928}
5929
5930static RecursiveUnion *
5932 Plan *lefttree,
5933 Plan *righttree,
5934 int wtParam,
5935 List *distinctList,
5936 long numGroups)
5937{
5939 Plan *plan = &node->plan;
5940 int numCols = list_length(distinctList);
5941
5942 plan->targetlist = tlist;
5943 plan->qual = NIL;
5944 plan->lefttree = lefttree;
5945 plan->righttree = righttree;
5946 node->wtParam = wtParam;
5947
5948 /*
5949 * convert SortGroupClause list into arrays of attr indexes and equality
5950 * operators, as wanted by executor
5951 */
5952 node->numCols = numCols;
5953 if (numCols > 0)
5954 {
5955 int keyno = 0;
5956 AttrNumber *dupColIdx;
5957 Oid *dupOperators;
5958 Oid *dupCollations;
5959 ListCell *slitem;
5960
5961 dupColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
5962 dupOperators = (Oid *) palloc(sizeof(Oid) * numCols);
5963 dupCollations = (Oid *) palloc(sizeof(Oid) * numCols);
5964
5965 foreach(slitem, distinctList)
5966 {
5967 SortGroupClause *sortcl = (SortGroupClause *) lfirst(slitem);
5969 plan->targetlist);
5970
5971 dupColIdx[keyno] = tle->resno;
5972 dupOperators[keyno] = sortcl->eqop;
5973 dupCollations[keyno] = exprCollation((Node *) tle->expr);
5974 Assert(OidIsValid(dupOperators[keyno]));
5975 keyno++;
5976 }
5977 node->dupColIdx = dupColIdx;
5978 node->dupOperators = dupOperators;
5979 node->dupCollations = dupCollations;
5980 }
5981 node->numGroups = numGroups;
5982
5983 return node;
5984}
5985
5986static BitmapAnd *
5988{
5989 BitmapAnd *node = makeNode(BitmapAnd);
5990 Plan *plan = &node->plan;
5991
5992 plan->targetlist = NIL;
5993 plan->qual = NIL;
5994 plan->lefttree = NULL;
5995 plan->righttree = NULL;
5996 node->bitmapplans = bitmapplans;
5997
5998 return node;
5999}
6000
6001static BitmapOr *
6003{
6004 BitmapOr *node = makeNode(BitmapOr);
6005 Plan *plan = &node->plan;
6006
6007 plan->targetlist = NIL;
6008 plan->qual = NIL;
6009 plan->lefttree = NULL;
6010 plan->righttree = NULL;
6011 node->bitmapplans = bitmapplans;
6012
6013 return node;
6014}
6015
6016static NestLoop *
6018 List *joinclauses,
6019 List *otherclauses,
6020 List *nestParams,
6021 Plan *lefttree,
6022 Plan *righttree,
6023 JoinType jointype,
6024 bool inner_unique)
6025{
6026 NestLoop *node = makeNode(NestLoop);
6027 Plan *plan = &node->join.plan;
6028
6029 plan->targetlist = tlist;
6030 plan->qual = otherclauses;
6031 plan->lefttree = lefttree;
6032 plan->righttree = righttree;
6033 node->join.jointype = jointype;
6034 node->join.inner_unique = inner_unique;
6035 node->join.joinqual = joinclauses;
6036 node->nestParams = nestParams;
6037
6038 return node;
6039}
6040
6041static HashJoin *
6043 List *joinclauses,
6044 List *otherclauses,
6045 List *hashclauses,
6046 List *hashoperators,
6047 List *hashcollations,
6048 List *hashkeys,
6049 Plan *lefttree,
6050 Plan *righttree,
6051 JoinType jointype,
6052 bool inner_unique)
6053{
6054 HashJoin *node = makeNode(HashJoin);
6055 Plan *plan = &node->join.plan;
6056
6057 plan->targetlist = tlist;
6058 plan->qual = otherclauses;
6059 plan->lefttree = lefttree;
6060 plan->righttree = righttree;
6061 node->hashclauses = hashclauses;
6062 node->hashoperators = hashoperators;
6063 node->hashcollations = hashcollations;
6064 node->hashkeys = hashkeys;
6065 node->join.jointype = jointype;
6066 node->join.inner_unique = inner_unique;
6067 node->join.joinqual = joinclauses;
6068
6069 return node;
6070}
6071
6072static Hash *
6073make_hash(Plan *lefttree,
6074 List *hashkeys,
6075 Oid skewTable,
6076 AttrNumber skewColumn,
6077 bool skewInherit)
6078{
6079 Hash *node = makeNode(Hash);
6080 Plan *plan = &node->plan;
6081
6082 plan->targetlist = lefttree->targetlist;
6083 plan->qual = NIL;
6084 plan->lefttree = lefttree;
6085 plan->righttree = NULL;
6086
6087 node->hashkeys = hashkeys;
6088 node->skewTable = skewTable;
6089 node->skewColumn = skewColumn;
6090 node->skewInherit = skewInherit;
6091
6092 return node;
6093}
6094
6095static MergeJoin *
6097 List *joinclauses,
6098 List *otherclauses,
6099 List *mergeclauses,
6100 Oid *mergefamilies,
6101 Oid *mergecollations,
6102 bool *mergereversals,
6103 bool *mergenullsfirst,
6104 Plan *lefttree,
6105 Plan *righttree,
6106 JoinType jointype,
6107 bool inner_unique,
6108 bool skip_mark_restore)
6109{
6110 MergeJoin *node = makeNode(MergeJoin);
6111 Plan *plan = &node->join.plan;
6112
6113 plan->targetlist = tlist;
6114 plan->qual = otherclauses;
6115 plan->lefttree = lefttree;
6116 plan->righttree = righttree;
6117 node->skip_mark_restore = skip_mark_restore;
6118 node->mergeclauses = mergeclauses;
6119 node->mergeFamilies = mergefamilies;
6120 node->mergeCollations = mergecollations;
6121 node->mergeReversals = mergereversals;
6122 node->mergeNullsFirst = mergenullsfirst;
6123 node->join.jointype = jointype;
6124 node->join.inner_unique = inner_unique;
6125 node->join.joinqual = joinclauses;
6126
6127 return node;
6128}
6129
6130/*
6131 * make_sort --- basic routine to build a Sort plan node
6132 *
6133 * Caller must have built the sortColIdx, sortOperators, collations, and
6134 * nullsFirst arrays already.
6135 */
6136static Sort *
6137make_sort(Plan *lefttree, int numCols,
6138 AttrNumber *sortColIdx, Oid *sortOperators,
6139 Oid *collations, bool *nullsFirst)
6140{
6141 Sort *node;
6142 Plan *plan;
6143
6144 node = makeNode(Sort);
6145
6146 plan = &node->plan;
6147 plan->targetlist = lefttree->targetlist;
6148 plan->disabled_nodes = lefttree->disabled_nodes + (enable_sort == false);
6149 plan->qual = NIL;
6150 plan->lefttree = lefttree;
6151 plan->righttree = NULL;
6152 node->numCols = numCols;
6153 node->sortColIdx = sortColIdx;
6154 node->sortOperators = sortOperators;
6155 node->collations = collations;
6156 node->nullsFirst = nullsFirst;
6157
6158 return node;
6159}
6160
6161/*
6162 * make_incrementalsort --- basic routine to build an IncrementalSort plan node
6163 *
6164 * Caller must have built the sortColIdx, sortOperators, collations, and
6165 * nullsFirst arrays already.
6166 */
6167static IncrementalSort *
6168make_incrementalsort(Plan *lefttree, int numCols, int nPresortedCols,
6169 AttrNumber *sortColIdx, Oid *sortOperators,
6170 Oid *collations, bool *nullsFirst)
6171{
6172 IncrementalSort *node;
6173 Plan *plan;
6174
6175 node = makeNode(IncrementalSort);
6176
6177 plan = &node->sort.plan;
6178 plan->targetlist = lefttree->targetlist;
6179 plan->qual = NIL;
6180 plan->lefttree = lefttree;
6181 plan->righttree = NULL;
6182 node->nPresortedCols = nPresortedCols;
6183 node->sort.numCols = numCols;
6184 node->sort.sortColIdx = sortColIdx;
6185 node->sort.sortOperators = sortOperators;
6186 node->sort.collations = collations;
6187 node->sort.nullsFirst = nullsFirst;
6188
6189 return node;
6190}
6191
6192/*
6193 * prepare_sort_from_pathkeys
6194 * Prepare to sort according to given pathkeys
6195 *
6196 * This is used to set up for Sort, MergeAppend, and Gather Merge nodes. It
6197 * calculates the executor's representation of the sort key information, and
6198 * adjusts the plan targetlist if needed to add resjunk sort columns.
6199 *
6200 * Input parameters:
6201 * 'lefttree' is the plan node which yields input tuples
6202 * 'pathkeys' is the list of pathkeys by which the result is to be sorted
6203 * 'relids' identifies the child relation being sorted, if any
6204 * 'reqColIdx' is NULL or an array of required sort key column numbers
6205 * 'adjust_tlist_in_place' is true if lefttree must be modified in-place
6206 *
6207 * We must convert the pathkey information into arrays of sort key column
6208 * numbers, sort operator OIDs, collation OIDs, and nulls-first flags,
6209 * which is the representation the executor wants. These are returned into
6210 * the output parameters *p_numsortkeys etc.
6211 *
6212 * When looking for matches to an EquivalenceClass's members, we will only
6213 * consider child EC members if they belong to given 'relids'. This protects
6214 * against possible incorrect matches to child expressions that contain no
6215 * Vars.
6216 *
6217 * If reqColIdx isn't NULL then it contains sort key column numbers that
6218 * we should match. This is used when making child plans for a MergeAppend;
6219 * it's an error if we can't match the columns.
6220 *
6221 * If the pathkeys include expressions that aren't simple Vars, we will
6222 * usually need to add resjunk items to the input plan's targetlist to
6223 * compute these expressions, since a Sort or MergeAppend node itself won't
6224 * do any such calculations. If the input plan type isn't one that can do
6225 * projections, this means adding a Result node just to do the projection.
6226 * However, the caller can pass adjust_tlist_in_place = true to force the
6227 * lefttree tlist to be modified in-place regardless of whether the node type
6228 * can project --- we use this for fixing the tlist of MergeAppend itself.
6229 *
6230 * Returns the node which is to be the input to the Sort (either lefttree,
6231 * or a Result stacked atop lefttree).
6232 */
6233static Plan *
6235 Relids relids,
6236 const AttrNumber *reqColIdx,
6237 bool adjust_tlist_in_place,
6238 int *p_numsortkeys,
6239 AttrNumber **p_sortColIdx,
6240 Oid **p_sortOperators,
6241 Oid **p_collations,
6242 bool **p_nullsFirst)
6243{
6244 List *tlist = lefttree->targetlist;
6245 ListCell *i;
6246 int numsortkeys;
6247 AttrNumber *sortColIdx;
6248 Oid *sortOperators;
6249 Oid *collations;
6250 bool *nullsFirst;
6251
6252 /*
6253 * We will need at most list_length(pathkeys) sort columns; possibly less
6254 */
6255 numsortkeys = list_length(pathkeys);
6256 sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
6257 sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
6258 collations = (Oid *) palloc(numsortkeys * sizeof(Oid));
6259 nullsFirst = (bool *) palloc(numsortkeys * sizeof(bool));
6260
6261 numsortkeys = 0;
6262
6263 foreach(i, pathkeys)
6264 {
6265 PathKey *pathkey = (PathKey *) lfirst(i);
6266 EquivalenceClass *ec = pathkey->pk_eclass;
6268 TargetEntry *tle = NULL;
6269 Oid pk_datatype = InvalidOid;
6270 Oid sortop;
6271 ListCell *j;
6272
6273 if (ec->ec_has_volatile)
6274 {
6275 /*
6276 * If the pathkey's EquivalenceClass is volatile, then it must
6277 * have come from an ORDER BY clause, and we have to match it to
6278 * that same targetlist entry.
6279 */
6280 if (ec->ec_sortref == 0) /* can't happen */
6281 elog(ERROR, "volatile EquivalenceClass has no sortref");
6282 tle = get_sortgroupref_tle(ec->ec_sortref, tlist);
6283 Assert(tle);
6284 Assert(list_length(ec->ec_members) == 1);
6285 pk_datatype = ((EquivalenceMember *) linitial(ec->ec_members))->em_datatype;
6286 }
6287 else if (reqColIdx != NULL)
6288 {
6289 /*
6290 * If we are given a sort column number to match, only consider
6291 * the single TLE at that position. It's possible that there is
6292 * no such TLE, in which case fall through and generate a resjunk
6293 * targetentry (we assume this must have happened in the parent
6294 * plan as well). If there is a TLE but it doesn't match the
6295 * pathkey's EC, we do the same, which is probably the wrong thing
6296 * but we'll leave it to caller to complain about the mismatch.
6297 */
6298 tle = get_tle_by_resno(tlist, reqColIdx[numsortkeys]);
6299 if (tle)
6300 {
6301 em = find_ec_member_matching_expr(ec, tle->expr, relids);
6302 if (em)
6303 {
6304 /* found expr at right place in tlist */
6305 pk_datatype = em->em_datatype;
6306 }
6307 else
6308 tle = NULL;
6309 }
6310 }
6311 else
6312 {
6313 /*
6314 * Otherwise, we can sort by any non-constant expression listed in
6315 * the pathkey's EquivalenceClass. For now, we take the first
6316 * tlist item found in the EC. If there's no match, we'll generate
6317 * a resjunk entry using the first EC member that is an expression
6318 * in the input's vars.
6319 *
6320 * XXX if we have a choice, is there any way of figuring out which
6321 * might be cheapest to execute? (For example, int4lt is likely
6322 * much cheaper to execute than numericlt, but both might appear
6323 * in the same equivalence class...) Not clear that we ever will
6324 * have an interesting choice in practice, so it may not matter.
6325 */
6326 foreach(j, tlist)
6327 {
6328 tle = (TargetEntry *) lfirst(j);
6329 em = find_ec_member_matching_expr(ec, tle->expr, relids);
6330 if (em)
6331 {
6332 /* found expr already in tlist */
6333 pk_datatype = em->em_datatype;
6334 break;
6335 }
6336 tle = NULL;
6337 }
6338 }
6339
6340 if (!tle)
6341 {
6342 /*
6343 * No matching tlist item; look for a computable expression.
6344 */
6345 em = find_computable_ec_member(NULL, ec, tlist, relids, false);
6346 if (!em)
6347 elog(ERROR, "could not find pathkey item to sort");
6348 pk_datatype = em->em_datatype;
6349
6350 /*
6351 * Do we need to insert a Result node?
6352 */
6353 if (!adjust_tlist_in_place &&
6354 !is_projection_capable_plan(lefttree))
6355 {
6356 /* copy needed so we don't modify input's tlist below */
6357 tlist = copyObject(tlist);
6358 lefttree = inject_projection_plan(lefttree, tlist,
6359 lefttree->parallel_safe);
6360 }
6361
6362 /* Don't bother testing is_projection_capable_plan again */
6363 adjust_tlist_in_place = true;
6364
6365 /*
6366 * Add resjunk entry to input's tlist
6367 */
6369 list_length(tlist) + 1,
6370 NULL,
6371 true);
6372 tlist = lappend(tlist, tle);
6373 lefttree->targetlist = tlist; /* just in case NIL before */
6374 }
6375
6376 /*
6377 * Look up the correct sort operator from the PathKey's slightly
6378 * abstracted representation.
6379 */
6381 pk_datatype,
6382 pk_datatype,
6383 pathkey->pk_cmptype);
6384 if (!OidIsValid(sortop)) /* should not happen */
6385 elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
6386 pathkey->pk_cmptype, pk_datatype, pk_datatype,
6387 pathkey->pk_opfamily);
6388
6389 /* Add the column to the sort arrays */
6390 sortColIdx[numsortkeys] = tle->resno;
6391 sortOperators[numsortkeys] = sortop;
6392 collations[numsortkeys] = ec->ec_collation;
6393 nullsFirst[numsortkeys] = pathkey->pk_nulls_first;
6394 numsortkeys++;
6395 }
6396
6397 /* Return results */
6398 *p_numsortkeys = numsortkeys;
6399 *p_sortColIdx = sortColIdx;
6400 *p_sortOperators = sortOperators;
6401 *p_collations = collations;
6402 *p_nullsFirst = nullsFirst;
6403
6404 return lefttree;
6405}
6406
6407/*
6408 * make_sort_from_pathkeys
6409 * Create sort plan to sort according to given pathkeys
6410 *
6411 * 'lefttree' is the node which yields input tuples
6412 * 'pathkeys' is the list of pathkeys by which the result is to be sorted
6413 * 'relids' is the set of relations required by prepare_sort_from_pathkeys()
6414 */
6415static Sort *
6416make_sort_from_pathkeys(Plan *lefttree, List *pathkeys, Relids relids)
6417{
6418 int numsortkeys;
6419 AttrNumber *sortColIdx;
6420 Oid *sortOperators;
6421 Oid *collations;
6422 bool *nullsFirst;
6423
6424 /* Compute sort column info, and adjust lefttree as needed */
6425 lefttree = prepare_sort_from_pathkeys(lefttree, pathkeys,
6426 relids,
6427 NULL,
6428 false,
6429 &numsortkeys,
6430 &sortColIdx,
6431 &sortOperators,
6432 &collations,
6433 &nullsFirst);
6434
6435 /* Now build the Sort node */
6436 return make_sort(lefttree, numsortkeys,
6437 sortColIdx, sortOperators,
6438 collations, nullsFirst);
6439}
6440
6441/*
6442 * make_incrementalsort_from_pathkeys
6443 * Create sort plan to sort according to given pathkeys
6444 *
6445 * 'lefttree' is the node which yields input tuples
6446 * 'pathkeys' is the list of pathkeys by which the result is to be sorted
6447 * 'relids' is the set of relations required by prepare_sort_from_pathkeys()
6448 * 'nPresortedCols' is the number of presorted columns in input tuples
6449 */
6450static IncrementalSort *
6452 Relids relids, int nPresortedCols)
6453{
6454 int numsortkeys;
6455 AttrNumber *sortColIdx;
6456 Oid *sortOperators;
6457 Oid *collations;
6458 bool *nullsFirst;
6459
6460 /* Compute sort column info, and adjust lefttree as needed */
6461 lefttree = prepare_sort_from_pathkeys(lefttree, pathkeys,
6462 relids,
6463 NULL,
6464 false,
6465 &numsortkeys,
6466 &sortColIdx,
6467 &sortOperators,
6468 &collations,
6469 &nullsFirst);
6470
6471 /* Now build the Sort node */
6472 return make_incrementalsort(lefttree, numsortkeys, nPresortedCols,
6473 sortColIdx, sortOperators,
6474 collations, nullsFirst);
6475}
6476
6477/*
6478 * make_sort_from_sortclauses
6479 * Create sort plan to sort according to given sortclauses
6480 *
6481 * 'sortcls' is a list of SortGroupClauses
6482 * 'lefttree' is the node which yields input tuples
6483 */
6484Sort *
6486{
6487 List *sub_tlist = lefttree->targetlist;
6488 ListCell *l;
6489 int numsortkeys;
6490 AttrNumber *sortColIdx;
6491 Oid *sortOperators;
6492 Oid *collations;
6493 bool *nullsFirst;
6494
6495 /* Convert list-ish representation to arrays wanted by executor */
6496 numsortkeys = list_length(sortcls);
6497 sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
6498 sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
6499 collations = (Oid *) palloc(numsortkeys * sizeof(Oid));
6500 nullsFirst = (bool *) palloc(numsortkeys * sizeof(bool));
6501
6502 numsortkeys = 0;
6503 foreach(l, sortcls)
6504 {
6505 SortGroupClause *sortcl = (SortGroupClause *) lfirst(l);
6506 TargetEntry *tle = get_sortgroupclause_tle(sortcl, sub_tlist);
6507
6508 sortColIdx[numsortkeys] = tle->resno;
6509 sortOperators[numsortkeys] = sortcl->sortop;
6510 collations[numsortkeys] = exprCollation((Node *) tle->expr);
6511 nullsFirst[numsortkeys] = sortcl->nulls_first;
6512 numsortkeys++;
6513 }
6514
6515 return make_sort(lefttree, numsortkeys,
6516 sortColIdx, sortOperators,
6517 collations, nullsFirst);
6518}
6519
6520/*
6521 * make_sort_from_groupcols
6522 * Create sort plan to sort based on grouping columns
6523 *
6524 * 'groupcls' is the list of SortGroupClauses
6525 * 'grpColIdx' gives the column numbers to use
6526 *
6527 * This might look like it could be merged with make_sort_from_sortclauses,
6528 * but presently we *must* use the grpColIdx[] array to locate sort columns,
6529 * because the child plan's tlist is not marked with ressortgroupref info
6530 * appropriate to the grouping node. So, only the sort ordering info
6531 * is used from the SortGroupClause entries.
6532 */
6533static Sort *
6535 AttrNumber *grpColIdx,
6536 Plan *lefttree)
6537{
6538 List *sub_tlist = lefttree->targetlist;
6539 ListCell *l;
6540 int numsortkeys;
6541 AttrNumber *sortColIdx;
6542 Oid *sortOperators;
6543 Oid *collations;
6544 bool *nullsFirst;
6545
6546 /* Convert list-ish representation to arrays wanted by executor */
6547 numsortkeys = list_length(groupcls);
6548 sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
6549 sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
6550 collations = (Oid *) palloc(numsortkeys * sizeof(Oid));
6551 nullsFirst = (bool *) palloc(numsortkeys * sizeof(bool));
6552
6553 numsortkeys = 0;
6554 foreach(l, groupcls)
6555 {
6556 SortGroupClause *grpcl = (SortGroupClause *) lfirst(l);
6557 TargetEntry *tle = get_tle_by_resno(sub_tlist, grpColIdx[numsortkeys]);
6558
6559 if (!tle)
6560 elog(ERROR, "could not retrieve tle for sort-from-groupcols");
6561
6562 sortColIdx[numsortkeys] = tle->resno;
6563 sortOperators[numsortkeys] = grpcl->sortop;
6564 collations[numsortkeys] = exprCollation((Node *) tle->expr);
6565 nullsFirst[numsortkeys] = grpcl->nulls_first;
6566 numsortkeys++;
6567 }
6568
6569 return make_sort(lefttree, numsortkeys,
6570 sortColIdx, sortOperators,
6571 collations, nullsFirst);
6572}
6573
6574static Material *
6576{
6577 Material *node = makeNode(Material);
6578 Plan *plan = &node->plan;
6579
6580 plan->targetlist = lefttree->targetlist;
6581 plan->qual = NIL;
6582 plan->lefttree = lefttree;
6583 plan->righttree = NULL;
6584
6585 return node;
6586}
6587
6588/*
6589 * materialize_finished_plan: stick a Material node atop a completed plan
6590 *
6591 * There are a couple of places where we want to attach a Material node
6592 * after completion of create_plan(), without any MaterialPath path.
6593 * Those places should probably be refactored someday to do this on the
6594 * Path representation, but it's not worth the trouble yet.
6595 */
6596Plan *
6598{
6599 Plan *matplan;
6600 Path matpath; /* dummy for result of cost_material */
6601 Cost initplan_cost;
6602 bool unsafe_initplans;
6603
6604 matplan = (Plan *) make_material(subplan);
6605
6606 /*
6607 * XXX horrid kluge: if there are any initPlans attached to the subplan,
6608 * move them up to the Material node, which is now effectively the top
6609 * plan node in its query level. This prevents failure in
6610 * SS_finalize_plan(), which see for comments.
6611 */
6612 matplan->initPlan = subplan->initPlan;
6613 subplan->initPlan = NIL;
6614
6615 /* Move the initplans' cost delta, as well */
6617 &initplan_cost, &unsafe_initplans);
6618 subplan->startup_cost -= initplan_cost;
6619 subplan->total_cost -= initplan_cost;
6620
6621 /* Set cost data */
6622 cost_material(&matpath,
6623 subplan->disabled_nodes,
6624 subplan->startup_cost,
6625 subplan->total_cost,
6626 subplan->plan_rows,
6627 subplan->plan_width);
6628 matplan->disabled_nodes = subplan->disabled_nodes;
6629 matplan->startup_cost = matpath.startup_cost + initplan_cost;
6630 matplan->total_cost = matpath.total_cost + initplan_cost;
6631 matplan->plan_rows = subplan->plan_rows;
6632 matplan->plan_width = subplan->plan_width;
6633 matplan->parallel_aware = false;
6634 matplan->parallel_safe = subplan->parallel_safe;
6635
6636 return matplan;
6637}
6638
6639static Memoize *
6640make_memoize(Plan *lefttree, Oid *hashoperators, Oid *collations,
6641 List *param_exprs, bool singlerow, bool binary_mode,
6642 uint32 est_entries, Bitmapset *keyparamids)
6643{
6644 Memoize *node = makeNode(Memoize);
6645 Plan *plan = &node->plan;
6646
6647 plan->targetlist = lefttree->targetlist;
6648 plan->qual = NIL;
6649 plan->lefttree = lefttree;
6650 plan->righttree = NULL;
6651
6652 node->numKeys = list_length(param_exprs);
6653 node->hashOperators = hashoperators;
6654 node->collations = collations;
6655 node->param_exprs = param_exprs;
6656 node->singlerow = singlerow;
6657 node->binary_mode = binary_mode;
6658 node->est_entries = est_entries;
6659 node->keyparamids = keyparamids;
6660
6661 return node;
6662}
6663
6664Agg *
6665make_agg(List *tlist, List *qual,
6666 AggStrategy aggstrategy, AggSplit aggsplit,
6667 int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations,
6668 List *groupingSets, List *chain, double dNumGroups,
6669 Size transitionSpace, Plan *lefttree)
6670{
6671 Agg *node = makeNode(Agg);
6672 Plan *plan = &node->plan;
6673 long numGroups;
6674
6675 /* Reduce to long, but 'ware overflow! */
6676 numGroups = clamp_cardinality_to_long(dNumGroups);
6677
6678 node->aggstrategy = aggstrategy;
6679 node->aggsplit = aggsplit;
6680 node->numCols = numGroupCols;
6681 node->grpColIdx = grpColIdx;
6682 node->grpOperators = grpOperators;
6683 node->grpCollations = grpCollations;
6684 node->numGroups = numGroups;
6685 node->transitionSpace = transitionSpace;
6686 node->aggParams = NULL; /* SS_finalize_plan() will fill this */
6687 node->groupingSets = groupingSets;
6688 node->chain = chain;
6689
6690 plan->qual = qual;
6691 plan->targetlist = tlist;
6692 plan->lefttree = lefttree;
6693 plan->righttree = NULL;
6694
6695 return node;
6696}
6697
6698static WindowAgg *
6700 int partNumCols, AttrNumber *partColIdx, Oid *partOperators, Oid *partCollations,
6701 int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations,
6702 List *runCondition, List *qual, bool topWindow, Plan *lefttree)
6703{
6704 WindowAgg *node = makeNode(WindowAgg);
6705 Plan *plan = &node->plan;
6706
6707 node->winname = wc->name;
6708 node->winref = wc->winref;
6709 node->partNumCols = partNumCols;
6710 node->partColIdx = partColIdx;
6711 node->partOperators = partOperators;
6712 node->partCollations = partCollations;
6713 node->ordNumCols = ordNumCols;
6714 node->ordColIdx = ordColIdx;
6715 node->ordOperators = ordOperators;
6716 node->ordCollations = ordCollations;
6717 node->frameOptions = wc->frameOptions;
6718 node->startOffset = wc->startOffset;
6719 node->endOffset = wc->endOffset;
6720 node->runCondition = runCondition;
6721 /* a duplicate of the above for EXPLAIN */
6722 node->runConditionOrig = runCondition;
6723 node->startInRangeFunc = wc->startInRangeFunc;
6724 node->endInRangeFunc = wc->endInRangeFunc;
6725 node->inRangeColl = wc->inRangeColl;
6726 node->inRangeAsc = wc->inRangeAsc;
6727 node->inRangeNullsFirst = wc->inRangeNullsFirst;
6728 node->topWindow = topWindow;
6729
6730 plan->targetlist = tlist;
6731 plan->lefttree = lefttree;
6732 plan->righttree = NULL;
6733 plan->qual = qual;
6734
6735 return node;
6736}
6737
6738static Group *
6740 List *qual,
6741 int numGroupCols,
6742 AttrNumber *grpColIdx,
6743 Oid *grpOperators,
6744 Oid *grpCollations,
6745 Plan *lefttree)
6746{
6747 Group *node = makeNode(Group);
6748 Plan *plan = &node->plan;
6749
6750 node->numCols = numGroupCols;
6751 node->grpColIdx = grpColIdx;
6752 node->grpOperators = grpOperators;
6753 node->grpCollations = grpCollations;
6754
6755 plan->qual = qual;
6756 plan->targetlist = tlist;
6757 plan->lefttree = lefttree;
6758 plan->righttree = NULL;
6759
6760 return node;
6761}
6762
6763/*
6764 * distinctList is a list of SortGroupClauses, identifying the targetlist items
6765 * that should be considered by the Unique filter. The input path must
6766 * already be sorted accordingly.
6767 */
6768static Unique *
6769make_unique_from_sortclauses(Plan *lefttree, List *distinctList)
6770{
6771 Unique *node = makeNode(Unique);
6772 Plan *plan = &node->plan;
6773 int numCols = list_length(distinctList);
6774 int keyno = 0;
6775 AttrNumber *uniqColIdx;
6776 Oid *uniqOperators;
6777 Oid *uniqCollations;
6778 ListCell *slitem;
6779
6780 plan->targetlist = lefttree->targetlist;
6781 plan->qual = NIL;
6782 plan->lefttree = lefttree;
6783 plan->righttree = NULL;
6784
6785 /*
6786 * convert SortGroupClause list into arrays of attr indexes and equality
6787 * operators, as wanted by executor
6788 */
6789 Assert(numCols > 0);
6790 uniqColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
6791 uniqOperators = (Oid *) palloc(sizeof(Oid) * numCols);
6792 uniqCollations = (Oid *) palloc(sizeof(Oid) * numCols);
6793
6794 foreach(slitem, distinctList)
6795 {
6796 SortGroupClause *sortcl = (SortGroupClause *) lfirst(slitem);
6797 TargetEntry *tle = get_sortgroupclause_tle(sortcl, plan->targetlist);
6798
6799 uniqColIdx[keyno] = tle->resno;
6800 uniqOperators[keyno] = sortcl->eqop;
6801 uniqCollations[keyno] = exprCollation((Node *) tle->expr);
6802 Assert(OidIsValid(uniqOperators[keyno]));
6803 keyno++;
6804 }
6805
6806 node->numCols = numCols;
6807 node->uniqColIdx = uniqColIdx;
6808 node->uniqOperators = uniqOperators;
6809 node->uniqCollations = uniqCollations;
6810
6811 return node;
6812}
6813
6814/*
6815 * as above, but use pathkeys to identify the sort columns and semantics
6816 */
6817static Unique *
6818make_unique_from_pathkeys(Plan *lefttree, List *pathkeys, int numCols)
6819{
6820 Unique *node = makeNode(Unique);
6821 Plan *plan = &node->plan;
6822 int keyno = 0;
6823 AttrNumber *uniqColIdx;
6824 Oid *uniqOperators;
6825 Oid *uniqCollations;
6826 ListCell *lc;
6827
6828 plan->targetlist = lefttree->targetlist;
6829 plan->qual = NIL;
6830 plan->lefttree = lefttree;
6831 plan->righttree = NULL;
6832
6833 /*
6834 * Convert pathkeys list into arrays of attr indexes and equality
6835 * operators, as wanted by executor. This has a lot in common with
6836 * prepare_sort_from_pathkeys ... maybe unify sometime?
6837 */
6838 Assert(numCols >= 0 && numCols <= list_length(pathkeys));
6839 uniqColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
6840 uniqOperators = (Oid *) palloc(sizeof(Oid) * numCols);
6841 uniqCollations = (Oid *) palloc(sizeof(Oid) * numCols);
6842
6843 foreach(lc, pathkeys)
6844 {
6845 PathKey *pathkey = (PathKey *) lfirst(lc);
6846 EquivalenceClass *ec = pathkey->pk_eclass;
6848 TargetEntry *tle = NULL;
6849 Oid pk_datatype = InvalidOid;
6850 Oid eqop;
6851 ListCell *j;
6852
6853 /* Ignore pathkeys beyond the specified number of columns */
6854 if (keyno >= numCols)
6855 break;
6856
6857 if (ec->ec_has_volatile)
6858 {
6859 /*
6860 * If the pathkey's EquivalenceClass is volatile, then it must
6861 * have come from an ORDER BY clause, and we have to match it to
6862 * that same targetlist entry.
6863 */
6864 if (ec->ec_sortref == 0) /* can't happen */
6865 elog(ERROR, "volatile EquivalenceClass has no sortref");
6866 tle = get_sortgroupref_tle(ec->ec_sortref, plan->targetlist);
6867 Assert(tle);
6868 Assert(list_length(ec->ec_members) == 1);
6869 pk_datatype = ((EquivalenceMember *) linitial(ec->ec_members))->em_datatype;
6870 }
6871 else
6872 {
6873 /*
6874 * Otherwise, we can use any non-constant expression listed in the
6875 * pathkey's EquivalenceClass. For now, we take the first tlist
6876 * item found in the EC.
6877 */
6878 foreach(j, plan->targetlist)
6879 {
6880 tle = (TargetEntry *) lfirst(j);
6881 em = find_ec_member_matching_expr(ec, tle->expr, NULL);
6882 if (em)
6883 {
6884 /* found expr already in tlist */
6885 pk_datatype = em->em_datatype;
6886 break;
6887 }
6888 tle = NULL;
6889 }
6890 }
6891
6892 if (!tle)
6893 elog(ERROR, "could not find pathkey item to sort");
6894
6895 /*
6896 * Look up the correct equality operator from the PathKey's slightly
6897 * abstracted representation.
6898 */
6900 pk_datatype,
6901 pk_datatype,
6902 COMPARE_EQ);
6903 if (!OidIsValid(eqop)) /* should not happen */
6904 elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
6905 COMPARE_EQ, pk_datatype, pk_datatype,
6906 pathkey->pk_opfamily);
6907
6908 uniqColIdx[keyno] = tle->resno;
6909 uniqOperators[keyno] = eqop;
6910 uniqCollations[keyno] = ec->ec_collation;
6911
6912 keyno++;
6913 }
6914
6915 node->numCols = numCols;
6916 node->uniqColIdx = uniqColIdx;
6917 node->uniqOperators = uniqOperators;
6918 node->uniqCollations = uniqCollations;
6919
6920 return node;
6921}
6922
6923static Gather *
6925 List *qpqual,
6926 int nworkers,
6927 int rescan_param,
6928 bool single_copy,
6929 Plan *subplan)
6930{
6931 Gather *node = makeNode(Gather);
6932 Plan *plan = &node->plan;
6933
6934 plan->targetlist = qptlist;
6935 plan->qual = qpqual;
6936 plan->lefttree = subplan;
6937 plan->righttree = NULL;
6938 node->num_workers = nworkers;
6939 node->rescan_param = rescan_param;
6940 node->single_copy = single_copy;
6941 node->invisible = false;
6942 node->initParam = NULL;
6943
6944 return node;
6945}
6946
6947/*
6948 * groupList is a list of SortGroupClauses, identifying the targetlist
6949 * items that should be considered by the SetOp filter. The input plans must
6950 * already be sorted accordingly, if we're doing SETOP_SORTED mode.
6951 */
6952static SetOp *
6954 List *tlist, Plan *lefttree, Plan *righttree,
6955 List *groupList, long numGroups)
6956{
6957 SetOp *node = makeNode(SetOp);
6958 Plan *plan = &node->plan;
6959 int numCols = list_length(groupList);
6960 int keyno = 0;
6961 AttrNumber *cmpColIdx;
6962 Oid *cmpOperators;
6963 Oid *cmpCollations;
6964 bool *cmpNullsFirst;
6965 ListCell *slitem;
6966
6967 plan->targetlist = tlist;
6968 plan->qual = NIL;
6969 plan->lefttree = lefttree;
6970 plan->righttree = righttree;
6971
6972 /*
6973 * convert SortGroupClause list into arrays of attr indexes and comparison
6974 * operators, as wanted by executor
6975 */
6976 cmpColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
6977 cmpOperators = (Oid *) palloc(sizeof(Oid) * numCols);
6978 cmpCollations = (Oid *) palloc(sizeof(Oid) * numCols);
6979 cmpNullsFirst = (bool *) palloc(sizeof(bool) * numCols);
6980
6981 foreach(slitem, groupList)
6982 {
6983 SortGroupClause *sortcl = (SortGroupClause *) lfirst(slitem);
6984 TargetEntry *tle = get_sortgroupclause_tle(sortcl, plan->targetlist);
6985
6986 cmpColIdx[keyno] = tle->resno;
6987 if (strategy == SETOP_HASHED)
6988 cmpOperators[keyno] = sortcl->eqop;
6989 else
6990 cmpOperators[keyno] = sortcl->sortop;
6991 Assert(OidIsValid(cmpOperators[keyno]));
6992 cmpCollations[keyno] = exprCollation((Node *) tle->expr);
6993 cmpNullsFirst[keyno] = sortcl->nulls_first;
6994 keyno++;
6995 }
6996
6997 node->cmd = cmd;
6998 node->strategy = strategy;
6999 node->numCols = numCols;
7000 node->cmpColIdx = cmpColIdx;
7001 node->cmpOperators = cmpOperators;
7002 node->cmpCollations = cmpCollations;
7003 node->cmpNullsFirst = cmpNullsFirst;
7004 node->numGroups = numGroups;
7005
7006 return node;
7007}
7008
7009/*
7010 * make_lockrows
7011 * Build a LockRows plan node
7012 */
7013static LockRows *
7014make_lockrows(Plan *lefttree, List *rowMarks, int epqParam)
7015{
7016 LockRows *node = makeNode(LockRows);
7017 Plan *plan = &node->plan;
7018
7019 plan->targetlist = lefttree->targetlist;
7020 plan->qual = NIL;
7021 plan->lefttree = lefttree;
7022 plan->righttree = NULL;
7023
7024 node->rowMarks = rowMarks;
7025 node->epqParam = epqParam;
7026
7027 return node;
7028}
7029
7030/*
7031 * make_limit
7032 * Build a Limit plan node
7033 */
7034Limit *
7035make_limit(Plan *lefttree, Node *limitOffset, Node *limitCount,
7036 LimitOption limitOption, int uniqNumCols, AttrNumber *uniqColIdx,
7037 Oid *uniqOperators, Oid *uniqCollations)
7038{
7039 Limit *node = makeNode(Limit);
7040 Plan *plan = &node->plan;
7041
7042 plan->targetlist = lefttree->targetlist;
7043 plan->qual = NIL;
7044 plan->lefttree = lefttree;
7045 plan->righttree = NULL;
7046
7047 node->limitOffset = limitOffset;
7048 node->limitCount = limitCount;
7049 node->limitOption = limitOption;
7050 node->uniqNumCols = uniqNumCols;
7051 node->uniqColIdx = uniqColIdx;
7052 node->uniqOperators = uniqOperators;
7053 node->uniqCollations = uniqCollations;
7054
7055 return node;
7056}
7057
7058/*
7059 * make_result
7060 * Build a Result plan node
7061 */
7062static Result *
7064 Node *resconstantqual,
7065 Plan *subplan)
7066{
7067 Result *node = makeNode(Result);
7068 Plan *plan = &node->plan;
7069
7070 plan->targetlist = tlist;
7071 plan->qual = NIL;
7072 plan->lefttree = subplan;
7073 plan->righttree = NULL;
7074 node->resconstantqual = resconstantqual;
7075
7076 return node;
7077}
7078
7079/*
7080 * make_project_set
7081 * Build a ProjectSet plan node
7082 */
7083static ProjectSet *
7085 Plan *subplan)
7086{
7088 Plan *plan = &node->plan;
7089
7090 plan->targetlist = tlist;
7091 plan->qual = NIL;
7092 plan->lefttree = subplan;
7093 plan->righttree = NULL;
7094
7095 return node;
7096}
7097
7098/*
7099 * make_modifytable
7100 * Build a ModifyTable plan node
7101 */
7102static ModifyTable *
7104 CmdType operation, bool canSetTag,
7105 Index nominalRelation, Index rootRelation,
7106 bool partColsUpdated,
7107 List *resultRelations,
7108 List *updateColnosLists,
7109 List *withCheckOptionLists, List *returningLists,
7110 List *rowMarks, OnConflictExpr *onconflict,
7111 List *mergeActionLists, List *mergeJoinConditions,
7112 int epqParam)
7113{
7115 bool returning_old_or_new = false;
7116 bool returning_old_or_new_valid = false;
7117 List *fdw_private_list;
7118 Bitmapset *direct_modify_plans;
7119 ListCell *lc;
7120 int i;
7121
7122 Assert(operation == CMD_MERGE ||
7123 (operation == CMD_UPDATE ?
7124 list_length(resultRelations) == list_length(updateColnosLists) :
7125 updateColnosLists == NIL));
7126 Assert(withCheckOptionLists == NIL ||
7127 list_length(resultRelations) == list_length(withCheckOptionLists));
7128 Assert(returningLists == NIL ||
7129 list_length(resultRelations) == list_length(returningLists));
7130
7131 node->plan.lefttree = subplan;
7132 node->plan.righttree = NULL;
7133 node->plan.qual = NIL;
7134 /* setrefs.c will fill in the targetlist, if needed */
7135 node->plan.targetlist = NIL;
7136
7137 node->operation = operation;
7138 node->canSetTag = canSetTag;
7139 node->nominalRelation = nominalRelation;
7140 node->rootRelation = rootRelation;
7141 node->partColsUpdated = partColsUpdated;
7142 node->resultRelations = resultRelations;
7143 if (!onconflict)
7144 {
7146 node->onConflictSet = NIL;
7147 node->onConflictCols = NIL;
7148 node->onConflictWhere = NULL;
7149 node->arbiterIndexes = NIL;
7150 node->exclRelRTI = 0;
7151 node->exclRelTlist = NIL;
7152 }
7153 else
7154 {
7155 node->onConflictAction = onconflict->action;
7156
7157 /*
7158 * Here we convert the ON CONFLICT UPDATE tlist, if any, to the
7159 * executor's convention of having consecutive resno's. The actual
7160 * target column numbers are saved in node->onConflictCols. (This
7161 * could be done earlier, but there seems no need to.)
7162 */
7163 node->onConflictSet = onconflict->onConflictSet;
7164 node->onConflictCols =
7166 node->onConflictWhere = onconflict->onConflictWhere;
7167
7168 /*
7169 * If a set of unique index inference elements was provided (an
7170 * INSERT...ON CONFLICT "inference specification"), then infer
7171 * appropriate unique indexes (or throw an error if none are
7172 * available).
7173 */
7175
7176 node->exclRelRTI = onconflict->exclRelIndex;
7177 node->exclRelTlist = onconflict->exclRelTlist;
7178 }
7179 node->updateColnosLists = updateColnosLists;
7180 node->withCheckOptionLists = withCheckOptionLists;
7181 node->returningOldAlias = root->parse->returningOldAlias;
7182 node->returningNewAlias = root->parse->returningNewAlias;
7183 node->returningLists = returningLists;
7184 node->rowMarks = rowMarks;
7185 node->mergeActionLists = mergeActionLists;
7186 node->mergeJoinConditions = mergeJoinConditions;
7187 node->epqParam = epqParam;
7188
7189 /*
7190 * For each result relation that is a foreign table, allow the FDW to
7191 * construct private plan data, and accumulate it all into a list.
7192 */
7193 fdw_private_list = NIL;
7194 direct_modify_plans = NULL;
7195 i = 0;
7196 foreach(lc, resultRelations)
7197 {
7198 Index rti = lfirst_int(lc);
7199 FdwRoutine *fdwroutine;
7200 List *fdw_private;
7201 bool direct_modify;
7202
7203 /*
7204 * If possible, we want to get the FdwRoutine from our RelOptInfo for
7205 * the table. But sometimes we don't have a RelOptInfo and must get
7206 * it the hard way. (In INSERT, the target relation is not scanned,
7207 * so it's not a baserel; and there are also corner cases for
7208 * updatable views where the target rel isn't a baserel.)
7209 */
7210 if (rti < root->simple_rel_array_size &&
7211 root->simple_rel_array[rti] != NULL)
7212 {
7213 RelOptInfo *resultRel = root->simple_rel_array[rti];
7214
7215 fdwroutine = resultRel->fdwroutine;
7216 }
7217 else
7218 {
7219 RangeTblEntry *rte = planner_rt_fetch(rti, root);
7220
7221 if (rte->rtekind == RTE_RELATION &&
7222 rte->relkind == RELKIND_FOREIGN_TABLE)
7223 {
7224 /* Check if the access to foreign tables is restricted */
7226 {
7227 /* there must not be built-in foreign tables */
7228 Assert(rte->relid >= FirstNormalObjectId);
7229 ereport(ERROR,
7230 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
7231 errmsg("access to non-system foreign table is restricted")));
7232 }
7233
7234 fdwroutine = GetFdwRoutineByRelId(rte->relid);
7235 }
7236 else
7237 fdwroutine = NULL;
7238 }
7239
7240 /*
7241 * MERGE is not currently supported for foreign tables. We already
7242 * checked that when the table mentioned in the query is foreign; but
7243 * we can still get here if a partitioned table has a foreign table as
7244 * partition. Disallow that now, to avoid an uglier error message
7245 * later.
7246 */
7247 if (operation == CMD_MERGE && fdwroutine != NULL)
7248 {
7249 RangeTblEntry *rte = planner_rt_fetch(rti, root);
7250
7251 ereport(ERROR,
7252 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
7253 errmsg("cannot execute MERGE on relation \"%s\"",
7254 get_rel_name(rte->relid)),
7255 errdetail_relkind_not_supported(rte->relkind));
7256 }
7257
7258 /*
7259 * Try to modify the foreign table directly if (1) the FDW provides
7260 * callback functions needed for that and (2) there are no local
7261 * structures that need to be run for each modified row: row-level
7262 * triggers on the foreign table, stored generated columns, WITH CHECK
7263 * OPTIONs from parent views, or Vars returning OLD/NEW in the
7264 * RETURNING list.
7265 */
7266 direct_modify = false;
7267 if (fdwroutine != NULL &&
7268 fdwroutine->PlanDirectModify != NULL &&
7269 fdwroutine->BeginDirectModify != NULL &&
7270 fdwroutine->IterateDirectModify != NULL &&
7271 fdwroutine->EndDirectModify != NULL &&
7272 withCheckOptionLists == NIL &&
7273 !has_row_triggers(root, rti, operation) &&
7275 {
7276 /* returning_old_or_new is the same for all result relations */
7277 if (!returning_old_or_new_valid)
7278 {
7279 returning_old_or_new =
7281 root->parse->returningList);
7282 returning_old_or_new_valid = true;
7283 }
7284 if (!returning_old_or_new)
7285 direct_modify = fdwroutine->PlanDirectModify(root, node, rti, i);
7286 }
7287 if (direct_modify)
7288 direct_modify_plans = bms_add_member(direct_modify_plans, i);
7289
7290 if (!direct_modify &&
7291 fdwroutine != NULL &&
7292 fdwroutine->PlanForeignModify != NULL)
7293 fdw_private = fdwroutine->PlanForeignModify(root, node, rti, i);
7294 else
7295 fdw_private = NIL;
7296 fdw_private_list = lappend(fdw_private_list, fdw_private);
7297 i++;
7298 }
7299 node->fdwPrivLists = fdw_private_list;
7300 node->fdwDirectModifyPlans = direct_modify_plans;
7301
7302 return node;
7303}
7304
7305/*
7306 * is_projection_capable_path
7307 * Check whether a given Path node is able to do projection.
7308 */
7309bool
7311{
7312 /* Most plan types can project, so just list the ones that can't */
7313 switch (path->pathtype)
7314 {
7315 case T_Hash:
7316 case T_Material:
7317 case T_Memoize:
7318 case T_Sort:
7319 case T_IncrementalSort:
7320 case T_Unique:
7321 case T_SetOp:
7322 case T_LockRows:
7323 case T_Limit:
7324 case T_ModifyTable:
7325 case T_MergeAppend:
7326 case T_RecursiveUnion:
7327 return false;
7328 case T_CustomScan:
7330 return true;
7331 return false;
7332 case T_Append:
7333
7334 /*
7335 * Append can't project, but if an AppendPath is being used to
7336 * represent a dummy path, what will actually be generated is a
7337 * Result which can project.
7338 */
7339 return IS_DUMMY_APPEND(path);
7340 case T_ProjectSet:
7341
7342 /*
7343 * Although ProjectSet certainly projects, say "no" because we
7344 * don't want the planner to randomly replace its tlist with
7345 * something else; the SRFs have to stay at top level. This might
7346 * get relaxed later.
7347 */
7348 return false;
7349 default:
7350 break;
7351 }
7352 return true;
7353}
7354
7355/*
7356 * is_projection_capable_plan
7357 * Check whether a given Plan node is able to do projection.
7358 */
7359bool
7361{
7362 /* Most plan types can project, so just list the ones that can't */
7363 switch (nodeTag(plan))
7364 {
7365 case T_Hash:
7366 case T_Material:
7367 case T_Memoize:
7368 case T_Sort:
7369 case T_Unique:
7370 case T_SetOp:
7371 case T_LockRows:
7372 case T_Limit:
7373 case T_ModifyTable:
7374 case T_Append:
7375 case T_MergeAppend:
7376 case T_RecursiveUnion:
7377 return false;
7378 case T_CustomScan:
7380 return true;
7381 return false;
7382 case T_ProjectSet:
7383
7384 /*
7385 * Although ProjectSet certainly projects, say "no" because we
7386 * don't want the planner to randomly replace its tlist with
7387 * something else; the SRFs have to stay at top level. This might
7388 * get relaxed later.
7389 */
7390 return false;
7391 default:
7392 break;
7393 }
7394 return true;
7395}
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:4768
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:6769
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:5872
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:5354
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:6096
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:6953
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:5448
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:6699
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:6640
Sort * make_sort_from_sortclauses(List *sortcls, Plan *lefttree)
Definition: createplan.c:6485
static BitmapOr * make_bitmap_or(List *bitmapplans)
Definition: createplan.c:6002
static HashJoin * create_hashjoin_plan(PlannerInfo *root, HashPath *best_path)
Definition: createplan.c:4787
static SeqScan * make_seqscan(List *qptlist, List *qpqual, Index scanrelid)
Definition: createplan.c:5577
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:5202
static void fix_indexqual_references(PlannerInfo *root, IndexPath *index_path, List **stripped_indexquals_p, List **fixed_indexquals_p)
Definition: createplan.c:5061
static List * fix_indexorderby_references(PlannerInfo *root, IndexPath *index_path)
Definition: createplan.c:5102
static Result * make_result(List *tlist, Node *resconstantqual, Plan *subplan)
Definition: createplan.c:7063
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:5547
static TidScan * make_tidscan(List *qptlist, List *qpqual, Index scanrelid, List *tidquals)
Definition: createplan.c:5714
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:5487
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:6168
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:7310
static CteScan * make_ctescan(List *qptlist, List *qpqual, Index scanrelid, int ctePlanId, int cteParam)
Definition: createplan.c:5831
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:5733
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:5131
static Unique * make_unique_from_pathkeys(Plan *lefttree, List *pathkeys, int numCols)
Definition: createplan.c:6818
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:5694
static Node * replace_nestloop_params_mutator(Node *node, PlannerInfo *root)
Definition: createplan.c:4983
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:7360
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:7084
static Sort * make_sort_from_pathkeys(Plan *lefttree, List *pathkeys, Relids relids)
Definition: createplan.c:6416
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:6042
static Gather * make_gather(List *qptlist, List *qpqual, int nworkers, int rescan_param, bool single_copy, Plan *subplan)
Definition: createplan.c:6924
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:6137
Limit * make_limit(Plan *lefttree, Node *limitOffset, Node *limitCount, LimitOption limitOption, int uniqNumCols, AttrNumber *uniqColIdx, Oid *uniqOperators, Oid *uniqCollations)
Definition: createplan.c:7035
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:5515
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:5891
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:6739
static LockRows * make_lockrows(Plan *lefttree, List *rowMarks, int epqParam)
Definition: createplan.c:7014
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:5931
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:5644
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:5613
static FunctionScan * make_functionscan(List *qptlist, List *qpqual, Index scanrelid, List *functions, bool funcordinality)
Definition: createplan.c:5772
static TableFuncScan * make_tablefuncscan(List *qptlist, List *qpqual, Index scanrelid, TableFunc *tablefunc)
Definition: createplan.c:5793
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:6665
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:5277
static void copy_plan_costsize(Plan *dest, Plan *src)
Definition: createplan.c:5464
static ValuesScan * make_valuesscan(List *qptlist, List *qpqual, Index scanrelid, List *values_lists)
Definition: createplan.c:5812
Plan * materialize_finished_plan(Plan *subplan)
Definition: createplan.c:6597
static SampleScan * make_samplescan(List *qptlist, List *qpqual, Index scanrelid, TableSampleClause *tsc)
Definition: createplan.c:5594
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:5852
static bool mark_async_capable_plan(Plan *plan, Path *path)
Definition: createplan.c:1140
static Material * make_material(Plan *lefttree)
Definition: createplan.c:6575
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:6017
static BitmapIndexScan * make_bitmap_indexscan(Index scanrelid, Oid indexid, List *indexqual, List *indexqualorig)
Definition: createplan.c:5673
static SubqueryScan * make_subqueryscan(List *qptlist, List *qpqual, Index scanrelid, Plan *subplan)
Definition: createplan.c:5752
static Hash * make_hash(Plan *lefttree, List *hashkeys, Oid skewTable, AttrNumber skewColumn, bool skewInherit)
Definition: createplan.c:6073
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:4976
#define CP_LABEL_TLIST
Definition: createplan.c:72
static BitmapAnd * make_bitmap_and(List *bitmapplans)
Definition: createplan.c:5987
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:6534
#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:7103
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:6234
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:6451
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:225
#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:420
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:1975
void * palloc(Size size)
Definition: mcxt.c:1945
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_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:4272
#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:348
#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:2399
Cardinality numGroups
Definition: pathnodes.h:2402
AggSplit aggsplit
Definition: pathnodes.h:2401
List * groupClause
Definition: pathnodes.h:2404
uint64 transitionSpace
Definition: pathnodes.h:2403
AggStrategy aggstrategy
Definition: pathnodes.h:2400
Path path
Definition: pathnodes.h:2398
List * qual
Definition: pathnodes.h:2405
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:2373
List * groupClause
Definition: pathnodes.h:2372
Path * subpath
Definition: pathnodes.h:2371
Path path
Definition: pathnodes.h:2370
int numCols
Definition: plannodes.h:1114
Plan plan
Definition: plannodes.h:1111
uint64 transitionSpace
Definition: pathnodes.h:2445
AggStrategy aggstrategy
Definition: pathnodes.h:2442
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:2297
Cardinality inner_rows_total
Definition: pathnodes.h:2299
int num_batches
Definition: pathnodes.h:2298
JoinPath jpath
Definition: pathnodes.h:2296
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:2545
LimitOption limitOption
Definition: pathnodes.h:2548
Node * limitOffset
Definition: pathnodes.h:2546
Node * limitCount
Definition: pathnodes.h:2547
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:2505
List * rowMarks
Definition: pathnodes.h:2506
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:2277
bool skip_mark_restore
Definition: pathnodes.h:2281
List * innersortkeys
Definition: pathnodes.h:2278
JoinPath jpath
Definition: pathnodes.h:2275
bool materialize_inner
Definition: pathnodes.h:2282
int outer_presorted_keys
Definition: pathnodes.h:2279
List * path_mergeclauses
Definition: pathnodes.h:2276
Param * param
Definition: pathnodes.h:3277
List * quals
Definition: pathnodes.h:2455
List * mmaggregates
Definition: pathnodes.h:2454
bool partColsUpdated
Definition: pathnodes.h:2525
List * returningLists
Definition: pathnodes.h:2529
List * resultRelations
Definition: pathnodes.h:2526
List * withCheckOptionLists
Definition: pathnodes.h:2528
List * mergeJoinConditions
Definition: pathnodes.h:2535
List * updateColnosLists
Definition: pathnodes.h:2527
OnConflictExpr * onconflict
Definition: pathnodes.h:2531
CmdType operation
Definition: pathnodes.h:2521
Index rootRelation
Definition: pathnodes.h:2524
Index nominalRelation
Definition: pathnodes.h:2523
List * mergeActionLists
Definition: pathnodes.h:2533
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:3238
Relids ph_eval_at
Definition: pathnodes.h:3232
Index phlevelsup
Definition: pathnodes.h:2941
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:2331
Plan plan
Definition: plannodes.h:269
Path * subpath
Definition: pathnodes.h:2319
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:2496
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:2730
Expr * clause
Definition: pathnodes.h:2708
Node * resconstantqual
Definition: plannodes.h:258
Plan plan
Definition: plannodes.h:257
Cardinality numGroups
Definition: pathnodes.h:2429
List * groupClause
Definition: pathnodes.h:2426
List * gsets
Definition: pathnodes.h:2427
bool is_hashed
Definition: pathnodes.h:2431
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:2479
Cardinality numGroups
Definition: pathnodes.h:2483
Path * leftpath
Definition: pathnodes.h:2478
SetOpCmd cmd
Definition: pathnodes.h:2480
Path path
Definition: pathnodes.h:2477
SetOpStrategy strategy
Definition: pathnodes.h:2481
List * groupList
Definition: pathnodes.h:2482
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:2344
Path * subpath
Definition: pathnodes.h:2345
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:2467
Path * subpath
Definition: pathnodes.h:2464
WindowClause * winclause
Definition: pathnodes.h:2465
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