1 /*-------------------------------------------------------------------------
4 * Routines to create the desired plan for processing a query.
5 * Planning is complete, we just need to convert the selected
8 * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
9 * Portions Copyright (c) 1994, Regents of the University of California
13 * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.148 2003/07/14 22:35:54 tgl Exp $
15 *-------------------------------------------------------------------------
21 #include "nodes/makefuncs.h"
22 #include "nodes/nodeFuncs.h"
23 #include "optimizer/clauses.h"
24 #include "optimizer/cost.h"
25 #include "optimizer/paths.h"
26 #include "optimizer/plancat.h"
27 #include "optimizer/planmain.h"
28 #include "optimizer/restrictinfo.h"
29 #include "optimizer/tlist.h"
30 #include "optimizer/var.h"
31 #include "parser/parse_clause.h"
32 #include "parser/parse_expr.h"
33 #include "utils/lsyscache.h"
34 #include "utils/syscache.h"
37 static Scan *create_scan_plan(Query *root, Path *best_path);
38 static List *build_relation_tlist(RelOptInfo *rel);
39 static bool use_physical_tlist(RelOptInfo *rel);
40 static void disuse_physical_tlist(Plan *plan, Path *path);
41 static Join *create_join_plan(Query *root, JoinPath *best_path);
42 static Append *create_append_plan(Query *root, AppendPath *best_path);
43 static Result *create_result_plan(Query *root, ResultPath *best_path);
44 static Material *create_material_plan(Query *root, MaterialPath *best_path);
45 static Plan *create_unique_plan(Query *root, UniquePath *best_path);
46 static SeqScan *create_seqscan_plan(Path *best_path, List *tlist,
48 static IndexScan *create_indexscan_plan(Query *root, IndexPath *best_path,
49 List *tlist, List *scan_clauses);
50 static TidScan *create_tidscan_plan(TidPath *best_path, List *tlist,
52 static SubqueryScan *create_subqueryscan_plan(Path *best_path,
53 List *tlist, List *scan_clauses);
54 static FunctionScan *create_functionscan_plan(Path *best_path,
55 List *tlist, List *scan_clauses);
56 static NestLoop *create_nestloop_plan(Query *root, NestPath *best_path,
57 Plan *outer_plan, Plan *inner_plan);
58 static MergeJoin *create_mergejoin_plan(Query *root, MergePath *best_path,
59 Plan *outer_plan, Plan *inner_plan);
60 static HashJoin *create_hashjoin_plan(Query *root, HashPath *best_path,
61 Plan *outer_plan, Plan *inner_plan);
62 static void fix_indxqual_references(List *indexquals, IndexPath *index_path,
63 List **fixed_indexquals,
64 List **recheck_indexquals);
65 static void fix_indxqual_sublist(List *indexqual,
66 Relids baserelids, int baserelid,
68 List **fixed_quals, List **recheck_quals);
69 static Node *fix_indxqual_operand(Node *node, int baserelid,
72 static List *get_switched_clauses(List *clauses, Relids outerrelids);
73 static List *order_qual_clauses(Query *root, List *clauses);
74 static void copy_path_costsize(Plan *dest, Path *src);
75 static void copy_plan_costsize(Plan *dest, Plan *src);
76 static SeqScan *make_seqscan(List *qptlist, List *qpqual, Index scanrelid);
77 static IndexScan *make_indexscan(List *qptlist, List *qpqual, Index scanrelid,
78 List *indxid, List *indxqual,
80 ScanDirection indexscandir);
81 static TidScan *make_tidscan(List *qptlist, List *qpqual, Index scanrelid,
83 static FunctionScan *make_functionscan(List *qptlist, List *qpqual,
85 static NestLoop *make_nestloop(List *tlist,
86 List *joinclauses, List *otherclauses,
87 Plan *lefttree, Plan *righttree,
89 static HashJoin *make_hashjoin(List *tlist,
90 List *joinclauses, List *otherclauses,
92 Plan *lefttree, Plan *righttree,
94 static Hash *make_hash(List *tlist, List *hashkeys, Plan *lefttree);
95 static MergeJoin *make_mergejoin(List *tlist,
96 List *joinclauses, List *otherclauses,
98 Plan *lefttree, Plan *righttree,
100 static Sort *make_sort(Query *root, List *tlist, Plan *lefttree, int numCols,
101 AttrNumber *sortColIdx, Oid *sortOperators);
102 static Sort *make_sort_from_pathkeys(Query *root, Plan *lefttree,
103 Relids relids, List *pathkeys);
108 * Creates the access plan for a query by tracing backwards through the
109 * desired chain of pathnodes, starting at the node 'best_path'. For
110 * every pathnode found:
111 * (1) Create a corresponding plan node containing appropriate id,
112 * target list, and qualification information.
113 * (2) Modify qual clauses of join nodes so that subplan attributes are
114 * referenced using relative values.
115 * (3) Target lists are not modified, but will be in setrefs.c.
117 * best_path is the best access path
119 * Returns a Plan tree.
122 create_plan(Query *root, Path *best_path)
126 switch (best_path->pathtype)
133 plan = (Plan *) create_scan_plan(root, best_path);
138 plan = (Plan *) create_join_plan(root,
139 (JoinPath *) best_path);
142 plan = (Plan *) create_append_plan(root,
143 (AppendPath *) best_path);
146 plan = (Plan *) create_result_plan(root,
147 (ResultPath *) best_path);
150 plan = (Plan *) create_material_plan(root,
151 (MaterialPath *) best_path);
154 plan = (Plan *) create_unique_plan(root,
155 (UniquePath *) best_path);
158 elog(ERROR, "create_plan: unknown pathtype %d",
159 best_path->pathtype);
160 plan = NULL; /* keep compiler quiet */
164 #ifdef NOT_USED /* fix xfunc */
165 /* sort clauses by cost/(1-selectivity) -- JMH 2/26/92 */
166 if (XfuncMode != XFUNC_OFF)
168 set_qpqual((Plan) plan,
169 lisp_qsort(get_qpqual((Plan) plan),
170 xfunc_clause_compare));
171 if (XfuncMode != XFUNC_NOR)
172 /* sort the disjuncts within each clause by cost -- JMH 3/4/92 */
173 xfunc_disjunct_sort(plan->qpqual);
182 * Create a scan plan for the parent relation of 'best_path'.
184 * Returns a Plan node.
187 create_scan_plan(Query *root, Path *best_path)
189 RelOptInfo *rel = best_path->parent;
195 * For table scans, rather than using the relation targetlist (which is
196 * only those Vars actually needed by the query), we prefer to generate a
197 * tlist containing all Vars in order. This will allow the executor to
198 * optimize away projection of the table tuples, if possible. (Note that
199 * planner.c may replace the tlist we generate here, forcing projection to
202 if (use_physical_tlist(rel))
204 tlist = build_physical_tlist(root, rel);
205 /* if fail because of dropped cols, use regular method */
207 tlist = build_relation_tlist(rel);
210 tlist = build_relation_tlist(rel);
213 * Extract the relevant restriction clauses from the parent relation;
214 * the executor must apply all these restrictions during the scan.
216 scan_clauses = get_actual_clauses(rel->baserestrictinfo);
218 /* Sort clauses into best execution order */
219 scan_clauses = order_qual_clauses(root, scan_clauses);
221 switch (best_path->pathtype)
224 plan = (Scan *) create_seqscan_plan(best_path,
230 plan = (Scan *) create_indexscan_plan(root,
231 (IndexPath *) best_path,
237 plan = (Scan *) create_tidscan_plan((TidPath *) best_path,
243 plan = (Scan *) create_subqueryscan_plan(best_path,
249 plan = (Scan *) create_functionscan_plan(best_path,
255 elog(ERROR, "create_scan_plan: unknown node type: %d",
256 best_path->pathtype);
257 plan = NULL; /* keep compiler quiet */
265 * Build a target list (ie, a list of TargetEntry) for a relation.
268 build_relation_tlist(RelOptInfo *rel)
274 FastListInit(&tlist);
275 foreach(v, FastListValue(&rel->reltargetlist))
277 /* Do we really need to copy here? Not sure */
278 Var *var = (Var *) copyObject(lfirst(v));
280 FastAppend(&tlist, create_tl_element(var, resdomno));
283 return FastListValue(&tlist);
288 * Decide whether to use a tlist matching relation structure,
289 * rather than only those Vars actually referenced.
292 use_physical_tlist(RelOptInfo *rel)
297 * Currently, can't do this for subquery or function scans. (This
298 * is mainly because we don't have an equivalent of build_physical_tlist
299 * for them; worth adding?)
301 if (rel->rtekind != RTE_RELATION)
304 * Can't do it with inheritance cases either (mainly because Append
307 if (rel->reloptkind != RELOPT_BASEREL)
310 * Can't do it if any system columns are requested, either. (This could
311 * possibly be fixed but would take some fragile assumptions in setrefs.c,
314 for (i = rel->min_attr; i <= 0; i++)
316 if (!bms_is_empty(rel->attr_needed[i - rel->min_attr]))
323 * disuse_physical_tlist
324 * Switch a plan node back to emitting only Vars actually referenced.
326 * If the plan node immediately above a scan would prefer to get only
327 * needed Vars and not a physical tlist, it must call this routine to
328 * undo the decision made by use_physical_tlist(). Currently, Hash, Sort,
329 * and Material nodes want this, so they don't have to store useless columns.
332 disuse_physical_tlist(Plan *plan, Path *path)
334 /* Only need to undo it for path types handled by create_scan_plan() */
335 switch (path->pathtype)
342 plan->targetlist = build_relation_tlist(path->parent);
351 * Create a join plan for 'best_path' and (recursively) plans for its
352 * inner and outer paths.
354 * Returns a Plan node.
357 create_join_plan(Query *root, JoinPath *best_path)
363 outer_plan = create_plan(root, best_path->outerjoinpath);
364 inner_plan = create_plan(root, best_path->innerjoinpath);
366 switch (best_path->path.pathtype)
369 plan = (Join *) create_mergejoin_plan(root,
370 (MergePath *) best_path,
375 plan = (Join *) create_hashjoin_plan(root,
376 (HashPath *) best_path,
381 plan = (Join *) create_nestloop_plan(root,
382 (NestPath *) best_path,
387 elog(ERROR, "unsupported node type %d",
388 best_path->path.pathtype);
389 plan = NULL; /* keep compiler quiet */
396 * * Expensive function pullups may have pulled local predicates *
397 * into this path node. Put them in the qpqual of the plan node. *
400 if (get_loc_restrictinfo(best_path) != NIL)
401 set_qpqual((Plan) plan,
402 nconc(get_qpqual((Plan) plan),
403 get_actual_clauses(get_loc_restrictinfo(best_path))));
411 * Create an Append plan for 'best_path' and (recursively) plans
414 * Returns a Plan node.
417 create_append_plan(Query *root, AppendPath *best_path)
420 List *tlist = build_relation_tlist(best_path->path.parent);
421 List *subplans = NIL;
424 foreach(subpaths, best_path->subpaths)
426 Path *subpath = (Path *) lfirst(subpaths);
428 subplans = lappend(subplans, create_plan(root, subpath));
431 plan = make_append(subplans, false, tlist);
438 * Create a Result plan for 'best_path' and (recursively) plans
441 * Returns a Plan node.
444 create_result_plan(Query *root, ResultPath *best_path)
451 if (best_path->path.parent)
452 tlist = build_relation_tlist(best_path->path.parent);
454 tlist = NIL; /* will be filled in later */
456 if (best_path->subpath)
457 subplan = create_plan(root, best_path->subpath);
461 constclauses = order_qual_clauses(root, best_path->constantqual);
463 plan = make_result(tlist, (Node *) constclauses, subplan);
469 * create_material_plan
470 * Create a Material plan for 'best_path' and (recursively) plans
473 * Returns a Plan node.
476 create_material_plan(Query *root, MaterialPath *best_path)
481 subplan = create_plan(root, best_path->subpath);
483 /* We don't want any excess columns in the materialized tuples */
484 disuse_physical_tlist(subplan, best_path->subpath);
486 plan = make_material(subplan->targetlist, subplan);
488 copy_path_costsize(&plan->plan, (Path *) best_path);
495 * Create a Unique plan for 'best_path' and (recursively) plans
498 * Returns a Plan node.
501 create_unique_plan(Query *root, UniquePath *best_path)
505 List *sub_targetlist;
509 subplan = create_plan(root, best_path->subpath);
512 * If the subplan came from an IN subselect (currently always the case),
513 * we need to instantiate the correct output targetlist for the subselect,
514 * rather than using the flattened tlist.
516 sub_targetlist = NIL;
517 foreach(l, root->in_info_list)
519 InClauseInfo *ininfo = (InClauseInfo *) lfirst(l);
521 if (bms_equal(ininfo->righthand, best_path->path.parent->relids))
523 sub_targetlist = ininfo->sub_targetlist;
531 * Transform list of plain Vars into targetlist
533 List *newtlist = NIL;
536 foreach(l, sub_targetlist)
538 Node *tlexpr = lfirst(l);
541 tle = makeTargetEntry(makeResdom(resno,
547 newtlist = lappend(newtlist, tle);
551 * If the top plan node can't do projections, we need to add a
552 * Result node to help it along.
554 * Currently, the only non-projection-capable plan type
555 * we can see here is Append.
557 if (IsA(subplan, Append))
558 subplan = (Plan *) make_result(newtlist, NULL, subplan);
560 subplan->targetlist = newtlist;
563 my_tlist = copyObject(subplan->targetlist);
565 if (best_path->use_hash)
567 int numGroupCols = length(my_tlist);
569 AttrNumber *groupColIdx;
572 numGroups = (long) Min(best_path->rows, (double) LONG_MAX);
574 groupColIdx = (AttrNumber *) palloc(numGroupCols * sizeof(AttrNumber));
575 for (i = 0; i < numGroupCols; i++)
576 groupColIdx[i] = i+1;
578 plan = (Plan *) make_agg(root,
592 sortList = addAllTargetsToSortList(NULL, NIL, my_tlist, false);
593 plan = (Plan *) make_sort_from_sortclauses(root, my_tlist,
595 plan = (Plan *) make_unique(my_tlist, plan, sortList);
598 plan->plan_rows = best_path->rows;
604 /*****************************************************************************
606 * BASE-RELATION SCAN METHODS
608 *****************************************************************************/
612 * create_seqscan_plan
613 * Returns a seqscan plan for the base relation scanned by 'best_path'
614 * with restriction clauses 'scan_clauses' and targetlist 'tlist'.
617 create_seqscan_plan(Path *best_path, List *tlist, List *scan_clauses)
620 Index scan_relid = best_path->parent->relid;
622 /* it should be a base rel... */
623 Assert(scan_relid > 0);
624 Assert(best_path->parent->rtekind == RTE_RELATION);
626 scan_plan = make_seqscan(tlist,
630 copy_path_costsize(&scan_plan->plan, best_path);
636 * create_indexscan_plan
637 * Returns a indexscan plan for the base relation scanned by 'best_path'
638 * with restriction clauses 'scan_clauses' and targetlist 'tlist'.
640 * The indexqual of the path contains a sublist of implicitly-ANDed qual
641 * conditions for each scan of the index(es); if there is more than one
642 * scan then the retrieved tuple sets are ORed together. The indexqual
643 * and indexinfo lists must have the same length, ie, the number of scans
644 * that will occur. Note it is possible for a qual condition sublist
645 * to be empty --- then no index restrictions will be applied during that
649 create_indexscan_plan(Query *root,
650 IndexPath *best_path,
654 List *indxqual = best_path->indexqual;
655 Index baserelid = best_path->path.parent->relid;
657 Expr *indxqual_or_expr = NULL;
658 List *fixed_indxqual;
659 List *recheck_indxqual;
662 IndexScan *scan_plan;
664 /* it should be a base rel... */
665 Assert(baserelid > 0);
666 Assert(best_path->path.parent->rtekind == RTE_RELATION);
669 * Build list of index OIDs.
671 FastListInit(&indexids);
672 foreach(ixinfo, best_path->indexinfo)
674 IndexOptInfo *index = (IndexOptInfo *) lfirst(ixinfo);
676 FastAppendo(&indexids, index->indexoid);
680 * The qpqual list must contain all restrictions not automatically
681 * handled by the index. Normally the predicates in the indxqual are
682 * checked fully by the index, but if the index is "lossy" for a
683 * particular operator (as signaled by the amopreqcheck flag in
684 * pg_amop), then we need to double-check that predicate in qpqual,
685 * because the index may return more tuples than match the predicate.
687 * Since the indexquals were generated from the restriction clauses given
688 * by scan_clauses, there will normally be some duplications between
689 * the lists. We get rid of the duplicates, then add back if lossy.
691 if (length(indxqual) > 1)
694 * Build an expression representation of the indexqual, expanding
695 * the implicit OR and AND semantics of the first- and
696 * second-level lists.
701 FastListInit(&orclauses);
702 foreach(orclause, indxqual)
704 FastAppend(&orclauses, make_ands_explicit(lfirst(orclause)));
706 indxqual_or_expr = make_orclause(FastListValue(&orclauses));
708 qpqual = set_difference(scan_clauses, makeList1(indxqual_or_expr));
710 else if (indxqual != NIL)
713 * Here, we can simply treat the first sublist as an independent
714 * set of qual expressions, since there is no top-level OR
717 qpqual = set_difference(scan_clauses, lfirst(indxqual));
720 qpqual = scan_clauses;
723 * The executor needs a copy with the indexkey on the left of each
724 * clause and with index attr numbers substituted for table ones. This
725 * pass also looks for "lossy" operators.
727 fix_indxqual_references(indxqual, best_path,
728 &fixed_indxqual, &recheck_indxqual);
731 * If there were any "lossy" operators, need to add back the
732 * appropriate qual clauses to the qpqual. When there is just one
733 * indexscan being performed (ie, we have simple AND semantics), we
734 * can just add the lossy clauses themselves to qpqual. If we have
735 * OR-of-ANDs, we'd better add the entire original indexqual to make
736 * sure that the semantics are correct.
738 if (recheck_indxqual != NIL)
740 if (indxqual_or_expr)
742 /* Better do a deep copy of the original scanclauses */
743 qpqual = lappend(qpqual, copyObject(indxqual_or_expr));
747 /* Subroutine already copied quals, so just append to list */
748 Assert(length(recheck_indxqual) == 1);
749 qpqual = nconc(qpqual, (List *) lfirst(recheck_indxqual));
753 /* Finally ready to build the plan node */
754 scan_plan = make_indexscan(tlist,
757 FastListValue(&indexids),
760 best_path->indexscandir);
762 copy_path_costsize(&scan_plan->scan.plan, &best_path->path);
763 /* use the indexscan-specific rows estimate, not the parent rel's */
764 scan_plan->scan.plan.plan_rows = best_path->rows;
770 * create_tidscan_plan
771 * Returns a tidscan plan for the base relation scanned by 'best_path'
772 * with restriction clauses 'scan_clauses' and targetlist 'tlist'.
775 create_tidscan_plan(TidPath *best_path, List *tlist, List *scan_clauses)
778 Index scan_relid = best_path->path.parent->relid;
780 /* it should be a base rel... */
781 Assert(scan_relid > 0);
782 Assert(best_path->path.parent->rtekind == RTE_RELATION);
784 scan_plan = make_tidscan(tlist,
789 copy_path_costsize(&scan_plan->scan.plan, &best_path->path);
795 * create_subqueryscan_plan
796 * Returns a subqueryscan plan for the base relation scanned by 'best_path'
797 * with restriction clauses 'scan_clauses' and targetlist 'tlist'.
799 static SubqueryScan *
800 create_subqueryscan_plan(Path *best_path, List *tlist, List *scan_clauses)
802 SubqueryScan *scan_plan;
803 Index scan_relid = best_path->parent->relid;
805 /* it should be a subquery base rel... */
806 Assert(scan_relid > 0);
807 Assert(best_path->parent->rtekind == RTE_SUBQUERY);
809 scan_plan = make_subqueryscan(tlist,
812 best_path->parent->subplan);
814 copy_path_costsize(&scan_plan->scan.plan, best_path);
820 * create_functionscan_plan
821 * Returns a functionscan plan for the base relation scanned by 'best_path'
822 * with restriction clauses 'scan_clauses' and targetlist 'tlist'.
824 static FunctionScan *
825 create_functionscan_plan(Path *best_path, List *tlist, List *scan_clauses)
827 FunctionScan *scan_plan;
828 Index scan_relid = best_path->parent->relid;
830 /* it should be a function base rel... */
831 Assert(scan_relid > 0);
832 Assert(best_path->parent->rtekind == RTE_FUNCTION);
834 scan_plan = make_functionscan(tlist, scan_clauses, scan_relid);
836 copy_path_costsize(&scan_plan->scan.plan, best_path);
841 /*****************************************************************************
845 *****************************************************************************/
848 create_nestloop_plan(Query *root,
853 List *tlist = build_relation_tlist(best_path->path.parent);
854 List *joinrestrictclauses = best_path->joinrestrictinfo;
859 if (IsA(best_path->innerjoinpath, IndexPath))
862 * An index is being used to reduce the number of tuples scanned
863 * in the inner relation. If there are join clauses being used
864 * with the index, we may remove those join clauses from the list of
865 * clauses that have to be checked as qpquals at the join node ---
866 * but only if there's just one indexscan in the inner path
867 * (otherwise, several different sets of clauses are being ORed
870 * We can also remove any join clauses that are redundant with those
871 * being used in the index scan; prior redundancy checks will not
872 * have caught this case because the join clauses would never have
873 * been put in the same joininfo list.
875 * This would be a waste of time if the indexpath was an ordinary
876 * indexpath and not a special innerjoin path. We will skip it in
877 * that case since indexjoinclauses is NIL in an ordinary indexpath.
879 IndexPath *innerpath = (IndexPath *) best_path->innerjoinpath;
880 List *indexjoinclauses = innerpath->indexjoinclauses;
882 if (length(indexjoinclauses) == 1) /* single indexscan? */
884 joinrestrictclauses =
885 select_nonredundant_join_clauses(root,
887 lfirst(indexjoinclauses),
888 best_path->jointype);
892 /* Get the join qual clauses (in plain expression form) */
893 if (IS_OUTER_JOIN(best_path->jointype))
895 get_actual_join_clauses(joinrestrictclauses,
896 &joinclauses, &otherclauses);
900 /* We can treat all clauses alike for an inner join */
901 joinclauses = get_actual_clauses(joinrestrictclauses);
905 join_plan = make_nestloop(tlist,
910 best_path->jointype);
912 copy_path_costsize(&join_plan->join.plan, &best_path->path);
918 create_mergejoin_plan(Query *root,
919 MergePath *best_path,
923 List *tlist = build_relation_tlist(best_path->jpath.path.parent);
927 MergeJoin *join_plan;
929 /* Get the join qual clauses (in plain expression form) */
930 if (IS_OUTER_JOIN(best_path->jpath.jointype))
932 get_actual_join_clauses(best_path->jpath.joinrestrictinfo,
933 &joinclauses, &otherclauses);
937 /* We can treat all clauses alike for an inner join */
938 joinclauses = get_actual_clauses(best_path->jpath.joinrestrictinfo);
943 * Remove the mergeclauses from the list of join qual clauses, leaving
944 * the list of quals that must be checked as qpquals.
946 mergeclauses = get_actual_clauses(best_path->path_mergeclauses);
947 joinclauses = set_difference(joinclauses, mergeclauses);
950 * Rearrange mergeclauses, if needed, so that the outer variable
951 * is always on the left.
953 mergeclauses = get_switched_clauses(best_path->path_mergeclauses,
954 best_path->jpath.outerjoinpath->parent->relids);
957 * Create explicit sort nodes for the outer and inner join paths if
958 * necessary. The sort cost was already accounted for in the path.
959 * Make sure there are no excess columns in the inputs if sorting.
961 if (best_path->outersortkeys)
963 disuse_physical_tlist(outer_plan, best_path->jpath.outerjoinpath);
964 outer_plan = (Plan *)
965 make_sort_from_pathkeys(root,
967 best_path->jpath.outerjoinpath->parent->relids,
968 best_path->outersortkeys);
971 if (best_path->innersortkeys)
973 disuse_physical_tlist(inner_plan, best_path->jpath.innerjoinpath);
974 inner_plan = (Plan *)
975 make_sort_from_pathkeys(root,
977 best_path->jpath.innerjoinpath->parent->relids,
978 best_path->innersortkeys);
982 * Now we can build the mergejoin node.
984 join_plan = make_mergejoin(tlist,
990 best_path->jpath.jointype);
992 copy_path_costsize(&join_plan->join.plan, &best_path->jpath.path);
998 create_hashjoin_plan(Query *root,
1003 List *tlist = build_relation_tlist(best_path->jpath.path.parent);
1007 HashJoin *join_plan;
1009 List *innerhashkeys;
1012 /* Get the join qual clauses (in plain expression form) */
1013 if (IS_OUTER_JOIN(best_path->jpath.jointype))
1015 get_actual_join_clauses(best_path->jpath.joinrestrictinfo,
1016 &joinclauses, &otherclauses);
1020 /* We can treat all clauses alike for an inner join */
1021 joinclauses = get_actual_clauses(best_path->jpath.joinrestrictinfo);
1026 * Remove the hashclauses from the list of join qual clauses, leaving
1027 * the list of quals that must be checked as qpquals.
1029 hashclauses = get_actual_clauses(best_path->path_hashclauses);
1030 joinclauses = set_difference(joinclauses, hashclauses);
1033 * Rearrange hashclauses, if needed, so that the outer variable
1034 * is always on the left.
1036 hashclauses = get_switched_clauses(best_path->path_hashclauses,
1037 best_path->jpath.outerjoinpath->parent->relids);
1040 * Extract the inner hash keys (right-hand operands of the hashclauses)
1041 * to put in the Hash node.
1043 innerhashkeys = NIL;
1044 foreach(hcl, hashclauses)
1046 innerhashkeys = lappend(innerhashkeys, get_rightop(lfirst(hcl)));
1049 /* We don't want any excess columns in the hashed tuples */
1050 disuse_physical_tlist(inner_plan, best_path->jpath.innerjoinpath);
1053 * Build the hash node and hash join node.
1055 hash_plan = make_hash(inner_plan->targetlist,
1058 join_plan = make_hashjoin(tlist,
1064 best_path->jpath.jointype);
1066 copy_path_costsize(&join_plan->join.plan, &best_path->jpath.path);
1072 /*****************************************************************************
1074 * SUPPORTING ROUTINES
1076 *****************************************************************************/
1079 * fix_indxqual_references
1080 * Adjust indexqual clauses to the form the executor's indexqual
1081 * machinery needs, and check for recheckable (lossy) index conditions.
1083 * We have three tasks here:
1084 * * Index keys must be represented by Var nodes with varattno set to the
1085 * index's attribute number, not the attribute number in the original rel.
1086 * * If the index key is on the right, commute the clause to put it on the
1087 * left. (Someday the executor might not need this, but for now it does.)
1088 * * If the indexable operator is marked 'amopreqcheck' in pg_amop, then
1089 * the index is "lossy" for this operator: it may return more tuples than
1090 * actually satisfy the operator condition. For each such operator, we
1091 * must add (the original form of) the indexqual clause to the "qpquals"
1092 * of the indexscan node, where the operator will be re-evaluated to
1095 * This code used to be entirely bogus for multi-index scans. Now it keeps
1096 * track of which index applies to each subgroup of index qual clauses...
1098 * Both the input list and the output lists have the form of lists of sublists
1099 * of qual clauses --- the top-level list has one entry for each indexscan
1100 * to be performed. The semantics are OR-of-ANDs.
1102 * fixed_indexquals receives a modified copy of the indexqual list --- the
1103 * original is not changed. Note also that the copy shares no substructure
1104 * with the original; this is needed in case there is a subplan in it (we need
1105 * two separate copies of the subplan tree, or things will go awry).
1107 * recheck_indexquals similarly receives a full copy of whichever clauses
1111 fix_indxqual_references(List *indexquals, IndexPath *index_path,
1112 List **fixed_indexquals, List **recheck_indexquals)
1114 FastList fixed_quals;
1115 FastList recheck_quals;
1116 Relids baserelids = index_path->path.parent->relids;
1117 int baserelid = index_path->path.parent->relid;
1118 List *ixinfo = index_path->indexinfo;
1121 FastListInit(&fixed_quals);
1122 FastListInit(&recheck_quals);
1123 foreach(i, indexquals)
1125 List *indexqual = lfirst(i);
1126 IndexOptInfo *index = (IndexOptInfo *) lfirst(ixinfo);
1130 fix_indxqual_sublist(indexqual, baserelids, baserelid, index,
1131 &fixed_qual, &recheck_qual);
1132 FastAppend(&fixed_quals, fixed_qual);
1133 if (recheck_qual != NIL)
1134 FastAppend(&recheck_quals, recheck_qual);
1136 ixinfo = lnext(ixinfo);
1139 *fixed_indexquals = FastListValue(&fixed_quals);
1140 *recheck_indexquals = FastListValue(&recheck_quals);
1144 * Fix the sublist of indexquals to be used in a particular scan.
1146 * For each qual clause, commute if needed to put the indexkey operand on the
1147 * left, and then fix its varattno. (We do not need to change the other side
1148 * of the clause.) Also change the operator if necessary, and check for
1149 * lossy index behavior.
1151 * Returns two lists: the list of fixed indexquals, and the list (usually
1152 * empty) of original clauses that must be rechecked as qpquals because
1153 * the index is lossy for this operator type.
1156 fix_indxqual_sublist(List *indexqual,
1157 Relids baserelids, int baserelid,
1158 IndexOptInfo *index,
1159 List **fixed_quals, List **recheck_quals)
1161 FastList fixed_qual;
1162 FastList recheck_qual;
1165 FastListInit(&fixed_qual);
1166 FastListInit(&recheck_qual);
1167 foreach(i, indexqual)
1169 OpExpr *clause = (OpExpr *) lfirst(i);
1174 if (!IsA(clause, OpExpr) || length(clause->args) != 2)
1175 elog(ERROR, "fix_indxqual_sublist: indexqual clause is not binary opclause");
1178 * Make a copy that will become the fixed clause.
1180 * We used to try to do a shallow copy here, but that fails if there
1181 * is a subplan in the arguments of the opclause. So just do a
1184 newclause = (OpExpr *) copyObject((Node *) clause);
1187 * Check to see if the indexkey is on the right; if so, commute
1188 * the clause. The indexkey should be the side that refers to
1189 * (only) the base relation.
1191 leftvarnos = pull_varnos((Node *) lfirst(newclause->args));
1192 if (!bms_equal(leftvarnos, baserelids))
1193 CommuteClause(newclause);
1194 bms_free(leftvarnos);
1197 * Now, determine which index attribute this is, change the
1198 * indexkey operand as needed, and get the index opclass.
1200 lfirst(newclause->args) = fix_indxqual_operand(lfirst(newclause->args),
1205 FastAppend(&fixed_qual, newclause);
1208 * Finally, check to see if index is lossy for this operator. If
1209 * so, add (a copy of) original form of clause to recheck list.
1211 if (op_requires_recheck(newclause->opno, opclass))
1212 FastAppend(&recheck_qual, copyObject((Node *) clause));
1215 *fixed_quals = FastListValue(&fixed_qual);
1216 *recheck_quals = FastListValue(&recheck_qual);
1220 fix_indxqual_operand(Node *node, int baserelid, IndexOptInfo *index,
1224 * We represent index keys by Var nodes having the varno of the base
1225 * table but varattno equal to the index's attribute number (index
1226 * column position). This is a bit hokey ... would be cleaner to use
1227 * a special-purpose node type that could not be mistaken for a
1228 * regular Var. But it will do for now.
1235 * Remove any binary-compatible relabeling of the indexkey
1237 if (IsA(node, RelabelType))
1238 node = (Node *) ((RelabelType *) node)->arg;
1240 if (IsA(node, Var) &&
1241 ((Var *) node)->varno == baserelid)
1243 /* Try to match against simple index columns */
1244 int varatt = ((Var *) node)->varattno;
1248 for (pos = 0; pos < index->ncolumns; pos++)
1250 if (index->indexkeys[pos] == varatt)
1252 result = (Var *) copyObject(node);
1253 result->varattno = pos + 1;
1254 /* return the correct opclass, too */
1255 *opclass = index->classlist[pos];
1256 return (Node *) result;
1262 /* Try to match against index expressions */
1263 indexprs = index->indexprs;
1264 for (pos = 0; pos < index->ncolumns; pos++)
1266 if (index->indexkeys[pos] == 0)
1270 if (indexprs == NIL)
1271 elog(ERROR, "too few entries in indexprs list");
1272 indexkey = (Node *) lfirst(indexprs);
1273 if (indexkey && IsA(indexkey, RelabelType))
1274 indexkey = (Node *) ((RelabelType *) indexkey)->arg;
1275 if (equal(node, indexkey))
1278 result = makeVar(baserelid, pos + 1,
1279 exprType(lfirst(indexprs)), -1,
1281 /* return the correct opclass, too */
1282 *opclass = index->classlist[pos];
1283 return (Node *) result;
1285 indexprs = lnext(indexprs);
1290 elog(ERROR, "fix_indxqual_operand: node is not index attribute");
1291 return NULL; /* keep compiler quiet */
1295 * get_switched_clauses
1296 * Given a list of merge or hash joinclauses (as RestrictInfo nodes),
1297 * extract the bare clauses, and rearrange the elements within the
1298 * clauses, if needed, so the outer join variable is on the left and
1299 * the inner is on the right. The original data structure is not touched;
1300 * a modified list is returned.
1303 get_switched_clauses(List *clauses, Relids outerrelids)
1310 RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(i);
1311 OpExpr *clause = (OpExpr *) restrictinfo->clause;
1313 Assert(is_opclause(clause));
1314 if (bms_is_subset(restrictinfo->right_relids, outerrelids))
1317 * Duplicate just enough of the structure to allow commuting
1318 * the clause without changing the original list. Could use
1319 * copyObject, but a complete deep copy is overkill.
1321 OpExpr *temp = makeNode(OpExpr);
1323 temp->opno = clause->opno;
1324 temp->opfuncid = InvalidOid;
1325 temp->opresulttype = clause->opresulttype;
1326 temp->opretset = clause->opretset;
1327 temp->args = listCopy(clause->args);
1328 /* Commute it --- note this modifies the temp node in-place. */
1329 CommuteClause(temp);
1330 t_list = lappend(t_list, temp);
1333 t_list = lappend(t_list, clause);
1339 * order_qual_clauses
1340 * Given a list of qual clauses that will all be evaluated at the same
1341 * plan node, sort the list into the order we want to check the quals
1344 * Ideally the order should be driven by a combination of execution cost and
1345 * selectivity, but unfortunately we have so little information about
1346 * execution cost of operators that it's really hard to do anything smart.
1347 * For now, we just move any quals that contain SubPlan references (but not
1348 * InitPlan references) to the end of the list.
1351 order_qual_clauses(Query *root, List *clauses)
1353 FastList nosubplans;
1354 FastList withsubplans;
1357 /* No need to work hard if the query is subselect-free */
1358 if (!root->hasSubLinks)
1361 FastListInit(&nosubplans);
1362 FastListInit(&withsubplans);
1365 Node *clause = lfirst(l);
1367 if (contain_subplans(clause))
1368 FastAppend(&withsubplans, clause);
1370 FastAppend(&nosubplans, clause);
1373 FastConcFast(&nosubplans, &withsubplans);
1374 return FastListValue(&nosubplans);
1378 * Copy cost and size info from a Path node to the Plan node created from it.
1379 * The executor won't use this info, but it's needed by EXPLAIN.
1382 copy_path_costsize(Plan *dest, Path *src)
1386 dest->startup_cost = src->startup_cost;
1387 dest->total_cost = src->total_cost;
1388 dest->plan_rows = src->parent->rows;
1389 dest->plan_width = src->parent->width;
1393 dest->startup_cost = 0;
1394 dest->total_cost = 0;
1395 dest->plan_rows = 0;
1396 dest->plan_width = 0;
1401 * Copy cost and size info from a lower plan node to an inserted node.
1402 * This is not critical, since the decisions have already been made,
1403 * but it helps produce more reasonable-looking EXPLAIN output.
1404 * (Some callers alter the info after copying it.)
1407 copy_plan_costsize(Plan *dest, Plan *src)
1411 dest->startup_cost = src->startup_cost;
1412 dest->total_cost = src->total_cost;
1413 dest->plan_rows = src->plan_rows;
1414 dest->plan_width = src->plan_width;
1418 dest->startup_cost = 0;
1419 dest->total_cost = 0;
1420 dest->plan_rows = 0;
1421 dest->plan_width = 0;
1426 /*****************************************************************************
1428 * PLAN NODE BUILDING ROUTINES
1430 * Some of these are exported because they are called to build plan nodes
1431 * in contexts where we're not deriving the plan node from a path node.
1433 *****************************************************************************/
1436 make_seqscan(List *qptlist,
1440 SeqScan *node = makeNode(SeqScan);
1441 Plan *plan = &node->plan;
1443 /* cost should be inserted by caller */
1444 plan->targetlist = qptlist;
1445 plan->qual = qpqual;
1446 plan->lefttree = NULL;
1447 plan->righttree = NULL;
1448 node->scanrelid = scanrelid;
1454 make_indexscan(List *qptlist,
1460 ScanDirection indexscandir)
1462 IndexScan *node = makeNode(IndexScan);
1463 Plan *plan = &node->scan.plan;
1465 /* cost should be inserted by caller */
1466 plan->targetlist = qptlist;
1467 plan->qual = qpqual;
1468 plan->lefttree = NULL;
1469 plan->righttree = NULL;
1470 node->scan.scanrelid = scanrelid;
1471 node->indxid = indxid;
1472 node->indxqual = indxqual;
1473 node->indxqualorig = indxqualorig;
1474 node->indxorderdir = indexscandir;
1480 make_tidscan(List *qptlist,
1485 TidScan *node = makeNode(TidScan);
1486 Plan *plan = &node->scan.plan;
1488 /* cost should be inserted by caller */
1489 plan->targetlist = qptlist;
1490 plan->qual = qpqual;
1491 plan->lefttree = NULL;
1492 plan->righttree = NULL;
1493 node->scan.scanrelid = scanrelid;
1494 node->tideval = tideval;
1500 make_subqueryscan(List *qptlist,
1505 SubqueryScan *node = makeNode(SubqueryScan);
1506 Plan *plan = &node->scan.plan;
1509 * Cost is figured here for the convenience of prepunion.c. Note this
1510 * is only correct for the case where qpqual is empty; otherwise caller
1511 * should overwrite cost with a better estimate.
1513 copy_plan_costsize(plan, subplan);
1514 plan->total_cost += cpu_tuple_cost * subplan->plan_rows;
1516 plan->targetlist = qptlist;
1517 plan->qual = qpqual;
1518 plan->lefttree = NULL;
1519 plan->righttree = NULL;
1520 node->scan.scanrelid = scanrelid;
1521 node->subplan = subplan;
1526 static FunctionScan *
1527 make_functionscan(List *qptlist,
1531 FunctionScan *node = makeNode(FunctionScan);
1532 Plan *plan = &node->scan.plan;
1534 /* cost should be inserted by caller */
1535 plan->targetlist = qptlist;
1536 plan->qual = qpqual;
1537 plan->lefttree = NULL;
1538 plan->righttree = NULL;
1539 node->scan.scanrelid = scanrelid;
1545 make_append(List *appendplans, bool isTarget, List *tlist)
1547 Append *node = makeNode(Append);
1548 Plan *plan = &node->plan;
1552 * Compute cost as sum of subplan costs. We charge nothing extra for
1553 * the Append itself, which perhaps is too optimistic, but since it
1554 * doesn't do any selection or projection, it is a pretty cheap node.
1556 plan->startup_cost = 0;
1557 plan->total_cost = 0;
1558 plan->plan_rows = 0;
1559 plan->plan_width = 0;
1560 foreach(subnode, appendplans)
1562 Plan *subplan = (Plan *) lfirst(subnode);
1564 if (subnode == appendplans) /* first node? */
1565 plan->startup_cost = subplan->startup_cost;
1566 plan->total_cost += subplan->total_cost;
1567 plan->plan_rows += subplan->plan_rows;
1568 if (plan->plan_width < subplan->plan_width)
1569 plan->plan_width = subplan->plan_width;
1572 plan->targetlist = tlist;
1574 plan->lefttree = NULL;
1575 plan->righttree = NULL;
1576 node->appendplans = appendplans;
1577 node->isTarget = isTarget;
1583 make_nestloop(List *tlist,
1590 NestLoop *node = makeNode(NestLoop);
1591 Plan *plan = &node->join.plan;
1593 /* cost should be inserted by caller */
1594 plan->targetlist = tlist;
1595 plan->qual = otherclauses;
1596 plan->lefttree = lefttree;
1597 plan->righttree = righttree;
1598 node->join.jointype = jointype;
1599 node->join.joinqual = joinclauses;
1605 make_hashjoin(List *tlist,
1613 HashJoin *node = makeNode(HashJoin);
1614 Plan *plan = &node->join.plan;
1616 /* cost should be inserted by caller */
1617 plan->targetlist = tlist;
1618 plan->qual = otherclauses;
1619 plan->lefttree = lefttree;
1620 plan->righttree = righttree;
1621 node->hashclauses = hashclauses;
1622 node->join.jointype = jointype;
1623 node->join.joinqual = joinclauses;
1629 make_hash(List *tlist, List *hashkeys, Plan *lefttree)
1631 Hash *node = makeNode(Hash);
1632 Plan *plan = &node->plan;
1634 copy_plan_costsize(plan, lefttree);
1637 * For plausibility, make startup & total costs equal total cost of
1638 * input plan; this only affects EXPLAIN display not decisions.
1640 plan->startup_cost = plan->total_cost;
1641 plan->targetlist = tlist;
1643 plan->lefttree = lefttree;
1644 plan->righttree = NULL;
1645 node->hashkeys = hashkeys;
1651 make_mergejoin(List *tlist,
1659 MergeJoin *node = makeNode(MergeJoin);
1660 Plan *plan = &node->join.plan;
1662 /* cost should be inserted by caller */
1663 plan->targetlist = tlist;
1664 plan->qual = otherclauses;
1665 plan->lefttree = lefttree;
1666 plan->righttree = righttree;
1667 node->mergeclauses = mergeclauses;
1668 node->join.jointype = jointype;
1669 node->join.joinqual = joinclauses;
1675 * make_sort --- basic routine to build a Sort plan node
1677 * Caller must have built the sortColIdx and sortOperators arrays already.
1680 make_sort(Query *root, List *tlist, Plan *lefttree, int numCols,
1681 AttrNumber *sortColIdx, Oid *sortOperators)
1683 Sort *node = makeNode(Sort);
1684 Plan *plan = &node->plan;
1685 Path sort_path; /* dummy for result of cost_sort */
1687 copy_plan_costsize(plan, lefttree); /* only care about copying size */
1688 cost_sort(&sort_path, root, NIL,
1689 lefttree->total_cost,
1690 lefttree->plan_rows,
1691 lefttree->plan_width);
1692 plan->startup_cost = sort_path.startup_cost;
1693 plan->total_cost = sort_path.total_cost;
1694 plan->targetlist = tlist;
1696 plan->lefttree = lefttree;
1697 plan->righttree = NULL;
1698 node->numCols = numCols;
1699 node->sortColIdx = sortColIdx;
1700 node->sortOperators = sortOperators;
1706 * add_sort_column --- utility subroutine for building sort info arrays
1708 * We need this routine because the same column might be selected more than
1709 * once as a sort key column; if so, the extra mentions are redundant.
1711 * Caller is assumed to have allocated the arrays large enough for the
1712 * max possible number of columns. Return value is the new column count.
1715 add_sort_column(AttrNumber colIdx, Oid sortOp,
1716 int numCols, AttrNumber *sortColIdx, Oid *sortOperators)
1720 for (i = 0; i < numCols; i++)
1722 if (sortColIdx[i] == colIdx)
1724 /* Already sorting by this col, so extra sort key is useless */
1729 /* Add the column */
1730 sortColIdx[numCols] = colIdx;
1731 sortOperators[numCols] = sortOp;
1736 * make_sort_from_pathkeys
1737 * Create sort plan to sort according to given pathkeys
1739 * 'lefttree' is the node which yields input tuples
1740 * 'relids' is the set of relids represented by the input node
1741 * 'pathkeys' is the list of pathkeys by which the result is to be sorted
1743 * We must convert the pathkey information into arrays of sort key column
1744 * numbers and sort operator OIDs.
1746 * If the pathkeys include expressions that aren't simple Vars, we will
1747 * usually need to add resjunk items to the input plan's targetlist to
1748 * compute these expressions (since the Sort node itself won't do it).
1749 * If the input plan type isn't one that can do projections, this means
1750 * adding a Result node just to do the projection.
1753 make_sort_from_pathkeys(Query *root, Plan *lefttree,
1754 Relids relids, List *pathkeys)
1756 List *tlist = lefttree->targetlist;
1760 AttrNumber *sortColIdx;
1763 /* We will need at most length(pathkeys) sort columns; possibly less */
1764 numsortkeys = length(pathkeys);
1765 sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
1766 sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
1770 foreach(i, pathkeys)
1772 List *keysublist = (List *) lfirst(i);
1773 PathKeyItem *pathkey = NULL;
1774 Resdom *resdom = NULL;
1778 * We can sort by any one of the sort key items listed in this
1779 * sublist. For now, we take the first one that corresponds to an
1780 * available Var in the tlist. If there isn't any, use the
1781 * first one that is an expression in the input's vars.
1783 * XXX if we have a choice, is there any way of figuring out which
1784 * might be cheapest to execute? (For example, int4lt is likely
1785 * much cheaper to execute than numericlt, but both might appear
1786 * in the same pathkey sublist...) Not clear that we ever will
1787 * have a choice in practice, so it may not matter.
1789 foreach(j, keysublist)
1791 pathkey = lfirst(j);
1792 Assert(IsA(pathkey, PathKeyItem));
1793 resdom = tlist_member(pathkey->key, tlist);
1799 /* No matching Var; look for an expression */
1800 foreach(j, keysublist)
1802 pathkey = lfirst(j);
1803 if (bms_is_subset(pull_varnos(pathkey->key), relids))
1807 elog(ERROR, "make_sort_from_pathkeys: cannot find pathkey item to sort");
1809 * Do we need to insert a Result node?
1811 * Currently, the only non-projection-capable plan type
1812 * we can see here is Append.
1814 if (IsA(lefttree, Append))
1816 tlist = copyObject(tlist);
1817 lefttree = (Plan *) make_result(tlist, NULL, lefttree);
1820 * Add resjunk entry to input's tlist
1822 resdom = makeResdom(length(tlist) + 1,
1823 exprType(pathkey->key),
1824 exprTypmod(pathkey->key),
1827 tlist = lappend(tlist,
1828 makeTargetEntry(resdom,
1829 (Expr *) pathkey->key));
1830 lefttree->targetlist = tlist; /* just in case NIL before */
1833 * The column might already be selected as a sort key, if the
1834 * pathkeys contain duplicate entries. (This can happen in
1835 * scenarios where multiple mergejoinable clauses mention the same
1836 * var, for example.) So enter it only once in the sort arrays.
1838 numsortkeys = add_sort_column(resdom->resno, pathkey->sortop,
1839 numsortkeys, sortColIdx, sortOperators);
1842 Assert(numsortkeys > 0);
1844 /* Give Sort node its own copy of the tlist (still necessary?) */
1845 sort_tlist = copyObject(tlist);
1847 return make_sort(root, sort_tlist, lefttree, numsortkeys,
1848 sortColIdx, sortOperators);
1852 * make_sort_from_sortclauses
1853 * Create sort plan to sort according to given sortclauses
1855 * 'tlist' is the targetlist
1856 * 'lefttree' is the node which yields input tuples
1857 * 'sortcls' is a list of SortClauses
1860 make_sort_from_sortclauses(Query *root, List *tlist,
1861 Plan *lefttree, List *sortcls)
1866 AttrNumber *sortColIdx;
1869 /* We will need at most length(sortcls) sort columns; possibly less */
1870 numsortkeys = length(sortcls);
1871 sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
1872 sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
1878 SortClause *sortcl = (SortClause *) lfirst(i);
1879 TargetEntry *tle = get_sortgroupclause_tle(sortcl, tlist);
1880 Resdom *resdom = tle->resdom;
1883 * Check for the possibility of duplicate order-by clauses --- the
1884 * parser should have removed 'em, but no point in sorting redundantly.
1886 numsortkeys = add_sort_column(resdom->resno, sortcl->sortop,
1887 numsortkeys, sortColIdx, sortOperators);
1890 Assert(numsortkeys > 0);
1892 /* Give Sort node its own copy of the tlist (still necessary?) */
1893 sort_tlist = copyObject(tlist);
1895 return make_sort(root, sort_tlist, lefttree, numsortkeys,
1896 sortColIdx, sortOperators);
1900 * make_sort_from_groupcols
1901 * Create sort plan to sort based on grouping columns
1903 * 'groupcls' is the list of GroupClauses
1904 * 'grpColIdx' gives the column numbers to use
1906 * This might look like it could be merged with make_sort_from_sortclauses,
1907 * but presently we *must* use the grpColIdx[] array to locate sort columns,
1908 * because the child plan's tlist is not marked with ressortgroupref info
1909 * appropriate to the grouping node. So, only the sortop is used from the
1910 * GroupClause entries.
1913 make_sort_from_groupcols(Query *root,
1915 AttrNumber *grpColIdx,
1918 List *sub_tlist = lefttree->targetlist;
1923 AttrNumber *sortColIdx;
1926 /* We will need at most length(groupcls) sort columns; possibly less */
1927 numsortkeys = length(groupcls);
1928 sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
1929 sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
1933 foreach(i, groupcls)
1935 GroupClause *grpcl = (GroupClause *) lfirst(i);
1936 TargetEntry *tle = nth(grpColIdx[grpno] - 1, sub_tlist);
1937 Resdom *resdom = tle->resdom;
1940 * Check for the possibility of duplicate group-by clauses --- the
1941 * parser should have removed 'em, but no point in sorting redundantly.
1943 numsortkeys = add_sort_column(resdom->resno, grpcl->sortop,
1944 numsortkeys, sortColIdx, sortOperators);
1948 Assert(numsortkeys > 0);
1950 /* Give Sort node its own copy of the tlist (still necessary?) */
1951 sort_tlist = copyObject(sub_tlist);
1953 return make_sort(root, sort_tlist, lefttree, numsortkeys,
1954 sortColIdx, sortOperators);
1958 make_material(List *tlist, Plan *lefttree)
1960 Material *node = makeNode(Material);
1961 Plan *plan = &node->plan;
1963 /* cost should be inserted by caller */
1964 plan->targetlist = tlist;
1966 plan->lefttree = lefttree;
1967 plan->righttree = NULL;
1973 * materialize_finished_plan: stick a Material node atop a completed plan
1975 * There are a couple of places where we want to attach a Material node
1976 * after completion of subquery_planner(). This currently requires hackery.
1977 * Since subquery_planner has already run SS_finalize_plan on the subplan
1978 * tree, we have to kluge up parameter lists for the Material node.
1979 * Possibly this could be fixed by postponing SS_finalize_plan processing
1980 * until setrefs.c is run?
1983 materialize_finished_plan(Plan *subplan)
1986 Path matpath; /* dummy for result of cost_material */
1988 matplan = (Plan *) make_material(subplan->targetlist, subplan);
1991 cost_material(&matpath,
1992 subplan->total_cost,
1994 subplan->plan_width);
1995 matplan->startup_cost = matpath.startup_cost;
1996 matplan->total_cost = matpath.total_cost;
1997 matplan->plan_rows = subplan->plan_rows;
1998 matplan->plan_width = subplan->plan_width;
2000 /* parameter kluge --- see comments above */
2001 matplan->extParam = bms_copy(subplan->extParam);
2002 matplan->allParam = bms_copy(subplan->allParam);
2008 make_agg(Query *root, List *tlist, List *qual,
2009 AggStrategy aggstrategy,
2010 int numGroupCols, AttrNumber *grpColIdx,
2011 long numGroups, int numAggs,
2014 Agg *node = makeNode(Agg);
2015 Plan *plan = &node->plan;
2016 Path agg_path; /* dummy for result of cost_agg */
2019 node->aggstrategy = aggstrategy;
2020 node->numCols = numGroupCols;
2021 node->grpColIdx = grpColIdx;
2022 node->numGroups = numGroups;
2024 copy_plan_costsize(plan, lefttree); /* only care about copying size */
2025 cost_agg(&agg_path, root,
2026 aggstrategy, numAggs,
2027 numGroupCols, numGroups,
2028 lefttree->startup_cost,
2029 lefttree->total_cost,
2030 lefttree->plan_rows);
2031 plan->startup_cost = agg_path.startup_cost;
2032 plan->total_cost = agg_path.total_cost;
2035 * We will produce a single output tuple if not grouping,
2036 * and a tuple per group otherwise.
2038 if (aggstrategy == AGG_PLAIN)
2039 plan->plan_rows = 1;
2041 plan->plan_rows = numGroups;
2044 * We also need to account for the cost of evaluation of the qual
2045 * (ie, the HAVING clause) and the tlist. Note that cost_qual_eval
2046 * doesn't charge anything for Aggref nodes; this is okay since
2047 * they are really comparable to Vars.
2049 * See notes in grouping_planner about why this routine and make_group
2050 * are the only ones in this file that worry about tlist eval cost.
2054 cost_qual_eval(&qual_cost, qual);
2055 plan->startup_cost += qual_cost.startup;
2056 plan->total_cost += qual_cost.startup;
2057 plan->total_cost += qual_cost.per_tuple * plan->plan_rows;
2059 cost_qual_eval(&qual_cost, tlist);
2060 plan->startup_cost += qual_cost.startup;
2061 plan->total_cost += qual_cost.startup;
2062 plan->total_cost += qual_cost.per_tuple * plan->plan_rows;
2065 plan->targetlist = tlist;
2066 plan->lefttree = lefttree;
2067 plan->righttree = (Plan *) NULL;
2073 make_group(Query *root,
2076 AttrNumber *grpColIdx,
2080 Group *node = makeNode(Group);
2081 Plan *plan = &node->plan;
2082 Path group_path; /* dummy for result of cost_group */
2085 node->numCols = numGroupCols;
2086 node->grpColIdx = grpColIdx;
2088 copy_plan_costsize(plan, lefttree); /* only care about copying size */
2089 cost_group(&group_path, root,
2090 numGroupCols, numGroups,
2091 lefttree->startup_cost,
2092 lefttree->total_cost,
2093 lefttree->plan_rows);
2094 plan->startup_cost = group_path.startup_cost;
2095 plan->total_cost = group_path.total_cost;
2097 /* One output tuple per estimated result group */
2098 plan->plan_rows = numGroups;
2101 * We also need to account for the cost of evaluation of the tlist.
2103 * XXX this double-counts the cost of evaluation of any expressions
2104 * used for grouping, since in reality those will have been evaluated
2105 * at a lower plan level and will only be copied by the Group node.
2108 * See notes in grouping_planner about why this routine and make_agg
2109 * are the only ones in this file that worry about tlist eval cost.
2111 cost_qual_eval(&qual_cost, tlist);
2112 plan->startup_cost += qual_cost.startup;
2113 plan->total_cost += qual_cost.startup;
2114 plan->total_cost += qual_cost.per_tuple * plan->plan_rows;
2117 plan->targetlist = tlist;
2118 plan->lefttree = lefttree;
2119 plan->righttree = (Plan *) NULL;
2125 * distinctList is a list of SortClauses, identifying the targetlist items
2126 * that should be considered by the Unique filter.
2129 make_unique(List *tlist, Plan *lefttree, List *distinctList)
2131 Unique *node = makeNode(Unique);
2132 Plan *plan = &node->plan;
2133 int numCols = length(distinctList);
2135 AttrNumber *uniqColIdx;
2138 copy_plan_costsize(plan, lefttree);
2141 * Charge one cpu_operator_cost per comparison per input tuple. We
2142 * assume all columns get compared at most of the tuples. (XXX probably
2143 * this is an overestimate.)
2145 plan->total_cost += cpu_operator_cost * plan->plan_rows * numCols;
2148 * plan->plan_rows is left as a copy of the input subplan's plan_rows;
2149 * ie, we assume the filter removes nothing. The caller must alter this
2150 * if he has a better idea.
2153 plan->targetlist = tlist;
2155 plan->lefttree = lefttree;
2156 plan->righttree = NULL;
2159 * convert SortClause list into array of attr indexes, as wanted by
2162 Assert(numCols > 0);
2163 uniqColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
2165 foreach(slitem, distinctList)
2167 SortClause *sortcl = (SortClause *) lfirst(slitem);
2168 TargetEntry *tle = get_sortgroupclause_tle(sortcl, tlist);
2170 uniqColIdx[keyno++] = tle->resdom->resno;
2173 node->numCols = numCols;
2174 node->uniqColIdx = uniqColIdx;
2180 * distinctList is a list of SortClauses, identifying the targetlist items
2181 * that should be considered by the SetOp filter.
2185 make_setop(SetOpCmd cmd, List *tlist, Plan *lefttree,
2186 List *distinctList, AttrNumber flagColIdx)
2188 SetOp *node = makeNode(SetOp);
2189 Plan *plan = &node->plan;
2190 int numCols = length(distinctList);
2192 AttrNumber *dupColIdx;
2195 copy_plan_costsize(plan, lefttree);
2198 * Charge one cpu_operator_cost per comparison per input tuple. We
2199 * assume all columns get compared at most of the tuples.
2201 plan->total_cost += cpu_operator_cost * plan->plan_rows * numCols;
2204 * We make the unsupported assumption that there will be 10% as many
2205 * tuples out as in. Any way to do better?
2207 plan->plan_rows *= 0.1;
2208 if (plan->plan_rows < 1)
2209 plan->plan_rows = 1;
2211 plan->targetlist = tlist;
2213 plan->lefttree = lefttree;
2214 plan->righttree = NULL;
2217 * convert SortClause list into array of attr indexes, as wanted by
2220 Assert(numCols > 0);
2221 dupColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
2223 foreach(slitem, distinctList)
2225 SortClause *sortcl = (SortClause *) lfirst(slitem);
2226 TargetEntry *tle = get_sortgroupclause_tle(sortcl, tlist);
2228 dupColIdx[keyno++] = tle->resdom->resno;
2232 node->numCols = numCols;
2233 node->dupColIdx = dupColIdx;
2234 node->flagColIdx = flagColIdx;
2240 make_limit(List *tlist, Plan *lefttree,
2241 Node *limitOffset, Node *limitCount)
2243 Limit *node = makeNode(Limit);
2244 Plan *plan = &node->plan;
2246 copy_plan_costsize(plan, lefttree);
2249 * If offset/count are constants, adjust the output rows count and
2250 * costs accordingly. This is only a cosmetic issue if we are at top
2251 * level, but if we are building a subquery then it's important to
2252 * report correct info to the outer planner.
2254 if (limitOffset && IsA(limitOffset, Const))
2256 Const *limito = (Const *) limitOffset;
2257 int32 offset = DatumGetInt32(limito->constvalue);
2259 if (!limito->constisnull && offset > 0)
2261 if (offset > plan->plan_rows)
2262 offset = (int32) plan->plan_rows;
2263 if (plan->plan_rows > 0)
2264 plan->startup_cost +=
2265 (plan->total_cost - plan->startup_cost)
2266 * ((double) offset) / plan->plan_rows;
2267 plan->plan_rows -= offset;
2268 if (plan->plan_rows < 1)
2269 plan->plan_rows = 1;
2272 if (limitCount && IsA(limitCount, Const))
2274 Const *limitc = (Const *) limitCount;
2275 int32 count = DatumGetInt32(limitc->constvalue);
2277 if (!limitc->constisnull && count >= 0)
2279 if (count > plan->plan_rows)
2280 count = (int32) plan->plan_rows;
2281 if (plan->plan_rows > 0)
2282 plan->total_cost = plan->startup_cost +
2283 (plan->total_cost - plan->startup_cost)
2284 * ((double) count) / plan->plan_rows;
2285 plan->plan_rows = count;
2286 if (plan->plan_rows < 1)
2287 plan->plan_rows = 1;
2291 plan->targetlist = tlist;
2293 plan->lefttree = lefttree;
2294 plan->righttree = NULL;
2296 node->limitOffset = limitOffset;
2297 node->limitCount = limitCount;
2303 make_result(List *tlist,
2304 Node *resconstantqual,
2307 Result *node = makeNode(Result);
2308 Plan *plan = &node->plan;
2311 copy_plan_costsize(plan, subplan);
2314 plan->startup_cost = 0;
2315 plan->total_cost = cpu_tuple_cost;
2316 plan->plan_rows = 1; /* wrong if we have a set-valued function? */
2317 plan->plan_width = 0; /* XXX try to be smarter? */
2320 if (resconstantqual)
2324 cost_qual_eval(&qual_cost, (List *) resconstantqual);
2325 /* resconstantqual is evaluated once at startup */
2326 plan->startup_cost += qual_cost.startup + qual_cost.per_tuple;
2327 plan->total_cost += qual_cost.startup + qual_cost.per_tuple;
2330 plan->targetlist = tlist;
2332 plan->lefttree = subplan;
2333 plan->righttree = NULL;
2334 node->resconstantqual = resconstantqual;