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-2000, PostgreSQL, Inc
9 * Portions Copyright (c) 1994, Regents of the University of California
13 * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.99 2000/10/26 21:36:09 tgl Exp $
15 *-------------------------------------------------------------------------
17 #include <sys/types.h>
21 #include "catalog/pg_index.h"
22 #include "nodes/makefuncs.h"
23 #include "nodes/nodeFuncs.h"
24 #include "optimizer/clauses.h"
25 #include "optimizer/cost.h"
26 #include "optimizer/paths.h"
27 #include "optimizer/planmain.h"
28 #include "optimizer/restrictinfo.h"
29 #include "optimizer/tlist.h"
30 #include "parser/parse_expr.h"
31 #include "utils/lsyscache.h"
32 #include "utils/syscache.h"
35 static List *switch_outer(List *clauses);
36 static Scan *create_scan_node(Query *root, Path *best_path, List *tlist);
37 static Join *create_join_node(Query *root, JoinPath *best_path, List *tlist);
38 static SeqScan *create_seqscan_node(Path *best_path, List *tlist,
40 static IndexScan *create_indexscan_node(Query *root, IndexPath *best_path,
41 List *tlist, List *scan_clauses);
42 static TidScan *create_tidscan_node(TidPath *best_path, List *tlist,
44 static SubqueryScan *create_subqueryscan_node(Path *best_path,
45 List *tlist, List *scan_clauses);
46 static NestLoop *create_nestloop_node(NestPath *best_path, List *tlist,
47 List *joinclauses, List *otherclauses,
48 Plan *outer_node, List *outer_tlist,
49 Plan *inner_node, List *inner_tlist);
50 static MergeJoin *create_mergejoin_node(MergePath *best_path, List *tlist,
51 List *joinclauses, List *otherclauses,
52 Plan *outer_node, List *outer_tlist,
53 Plan *inner_node, List *inner_tlist);
54 static HashJoin *create_hashjoin_node(HashPath *best_path, List *tlist,
55 List *joinclauses, List *otherclauses,
56 Plan *outer_node, List *outer_tlist,
57 Plan *inner_node, List *inner_tlist);
58 static List *fix_indxqual_references(List *indexquals, IndexPath *index_path);
59 static List *fix_indxqual_sublist(List *indexqual, int baserelid, Oid relam,
61 static Node *fix_indxqual_operand(Node *node, int baserelid,
64 static SeqScan *make_seqscan(List *qptlist, List *qpqual, Index scanrelid);
65 static IndexScan *make_indexscan(List *qptlist, List *qpqual, Index scanrelid,
66 List *indxid, List *indxqual,
68 ScanDirection indexscandir);
69 static TidScan *make_tidscan(List *qptlist, List *qpqual, Index scanrelid,
71 static NestLoop *make_nestloop(List *tlist,
72 List *joinclauses, List *otherclauses,
73 Plan *lefttree, Plan *righttree,
75 static HashJoin *make_hashjoin(List *tlist,
76 List *joinclauses, List *otherclauses,
78 Plan *lefttree, Plan *righttree,
80 static Hash *make_hash(List *tlist, Node *hashkey, Plan *lefttree);
81 static MergeJoin *make_mergejoin(List *tlist,
82 List *joinclauses, List *otherclauses,
84 Plan *lefttree, Plan *righttree,
86 static void copy_path_costsize(Plan *dest, Path *src);
90 * Creates the access plan for a query by tracing backwards through the
91 * desired chain of pathnodes, starting at the node 'best_path'. For
92 * every pathnode found:
93 * (1) Create a corresponding plan node containing appropriate id,
94 * target list, and qualification information.
95 * (2) Modify qual clauses of join nodes so that subplan attributes are
96 * referenced using relative values.
97 * (3) Target lists are not modified, but will be in setrefs.c.
99 * best_path is the best access path
101 * Returns the access plan.
104 create_plan(Query *root, Path *best_path)
106 List *tlist = best_path->parent->targetlist;
107 Plan *plan_node = (Plan *) NULL;
109 switch (best_path->pathtype)
115 plan_node = (Plan *) create_scan_node(root, best_path, tlist);
120 plan_node = (Plan *) create_join_node(root,
121 (JoinPath *) best_path,
125 elog(ERROR, "create_plan: unknown pathtype %d",
126 best_path->pathtype);
130 #ifdef NOT_USED /* fix xfunc */
131 /* sort clauses by cost/(1-selectivity) -- JMH 2/26/92 */
132 if (XfuncMode != XFUNC_OFF)
134 set_qpqual((Plan) plan_node,
135 lisp_qsort(get_qpqual((Plan) plan_node),
136 xfunc_clause_compare));
137 if (XfuncMode != XFUNC_NOR)
138 /* sort the disjuncts within each clause by cost -- JMH 3/4/92 */
139 xfunc_disjunct_sort(plan_node->qpqual);
148 * Create a scan path for the parent relation of 'best_path'.
150 * tlist is the targetlist for the base relation scanned by 'best_path'
152 * Returns the scan node.
155 create_scan_node(Query *root, Path *best_path, List *tlist)
161 * Extract the relevant restriction clauses from the parent relation;
162 * the executor must apply all these restrictions during the scan.
164 scan_clauses = get_actual_clauses(best_path->parent->baserestrictinfo);
166 switch (best_path->pathtype)
169 node = (Scan *) create_seqscan_node(best_path,
175 node = (Scan *) create_indexscan_node(root,
176 (IndexPath *) best_path,
182 node = (Scan *) create_tidscan_node((TidPath *) best_path,
188 node = (Scan *) create_subqueryscan_node(best_path,
194 elog(ERROR, "create_scan_node: unknown node type: %d",
195 best_path->pathtype);
204 * Create a join path for 'best_path' and(recursively) paths for its
205 * inner and outer paths.
207 * 'tlist' is the targetlist for the join relation corresponding to
210 * Returns the join node.
213 create_join_node(Query *root, JoinPath *best_path, List *tlist)
223 outer_node = create_plan(root, best_path->outerjoinpath);
224 outer_tlist = outer_node->targetlist;
226 inner_node = create_plan(root, best_path->innerjoinpath);
227 inner_tlist = inner_node->targetlist;
229 if (IS_OUTER_JOIN(best_path->jointype))
231 get_actual_join_clauses(best_path->joinrestrictinfo,
232 &joinclauses, &otherclauses);
236 /* We can treat all clauses alike for an inner join */
237 joinclauses = get_actual_clauses(best_path->joinrestrictinfo);
241 switch (best_path->path.pathtype)
244 retval = (Join *) create_mergejoin_node((MergePath *) best_path,
254 retval = (Join *) create_hashjoin_node((HashPath *) best_path,
264 retval = (Join *) create_nestloop_node((NestPath *) best_path,
274 elog(ERROR, "create_join_node: unknown node type: %d",
275 best_path->path.pathtype);
281 * * Expensive function pullups may have pulled local predicates *
282 * into this path node. Put them in the qpqual of the plan node. *
285 if (get_loc_restrictinfo(best_path) != NIL)
286 set_qpqual((Plan) retval,
287 nconc(get_qpqual((Plan) retval),
288 get_actual_clauses(get_loc_restrictinfo(best_path))));
294 /*****************************************************************************
296 * BASE-RELATION SCAN METHODS
298 *****************************************************************************/
302 * create_seqscan_node
303 * Returns a seqscan node for the base relation scanned by 'best_path'
304 * with restriction clauses 'scan_clauses' and targetlist 'tlist'.
307 create_seqscan_node(Path *best_path, List *tlist, List *scan_clauses)
312 /* there should be exactly one base rel involved... */
313 Assert(length(best_path->parent->relids) == 1);
314 Assert(! best_path->parent->issubquery);
316 scan_relid = (Index) lfirsti(best_path->parent->relids);
318 scan_node = make_seqscan(tlist,
322 copy_path_costsize(&scan_node->plan, best_path);
328 * create_indexscan_node
329 * Returns a indexscan node for the base relation scanned by 'best_path'
330 * with restriction clauses 'scan_clauses' and targetlist 'tlist'.
332 * The indexqual of the path contains a sublist of implicitly-ANDed qual
333 * conditions for each scan of the index(es); if there is more than one
334 * scan then the retrieved tuple sets are ORed together. The indexqual
335 * and indexid lists must have the same length, ie, the number of scans
336 * that will occur. Note it is possible for a qual condition sublist
337 * to be empty --- then no index restrictions will be applied during that
341 create_indexscan_node(Query *root,
342 IndexPath *best_path,
346 List *indxqual = best_path->indexqual;
349 List *fixed_indxqual;
351 IndexScan *scan_node;
354 /* there should be exactly one base rel involved... */
355 Assert(length(best_path->path.parent->relids) == 1);
356 Assert(! best_path->path.parent->issubquery);
358 baserelid = lfirsti(best_path->path.parent->relids);
360 /* check to see if any of the indices are lossy */
361 foreach(ixid, best_path->indexid)
363 HeapTuple indexTuple;
366 indexTuple = SearchSysCacheTuple(INDEXRELID,
367 ObjectIdGetDatum(lfirsti(ixid)),
369 if (!HeapTupleIsValid(indexTuple))
370 elog(ERROR, "create_plan: index %u not found", lfirsti(ixid));
371 index = (Form_pg_index) GETSTRUCT(indexTuple);
372 if (index->indislossy)
380 * The qpqual list must contain all restrictions not automatically
381 * handled by the index. Note that for non-lossy indices, the
382 * predicates in the indxqual are checked fully by the index, while
383 * for lossy indices the indxqual predicates need to be double-checked
384 * after the index fetches the best-guess tuples.
386 * Since the indexquals were generated from the restriction clauses given
387 * by scan_clauses, there will normally be some duplications between
388 * the lists. We get rid of the duplicates, then add back if lossy.
390 if (length(indxqual) > 1)
394 * Build an expression representation of the indexqual, expanding
395 * the implicit OR and AND semantics of the first- and
396 * second-level lists.
398 List *orclauses = NIL;
402 foreach(orclause, indxqual)
403 orclauses = lappend(orclauses,
404 make_ands_explicit(lfirst(orclause)));
405 indxqual_expr = make_orclause(orclauses);
407 qpqual = set_difference(scan_clauses, makeList1(indxqual_expr));
410 qpqual = lappend(qpqual, copyObject(indxqual_expr));
412 else if (indxqual != NIL)
416 * Here, we can simply treat the first sublist as an independent
417 * set of qual expressions, since there is no top-level OR
420 List *indxqual_list = lfirst(indxqual);
422 qpqual = set_difference(scan_clauses, indxqual_list);
425 qpqual = nconc(qpqual, (List *) copyObject(indxqual_list));
428 qpqual = scan_clauses;
431 * The executor needs a copy with the indexkey on the left of each
432 * clause and with index attr numbers substituted for table ones.
434 fixed_indxqual = fix_indxqual_references(indxqual, best_path);
436 scan_node = make_indexscan(tlist,
442 best_path->indexscandir);
444 copy_path_costsize(&scan_node->scan.plan, &best_path->path);
445 /* use the indexscan-specific rows estimate, not the parent rel's */
446 scan_node->scan.plan.plan_rows = best_path->rows;
452 * create_tidscan_node
453 * Returns a tidscan node for the base relation scanned by 'best_path'
454 * with restriction clauses 'scan_clauses' and targetlist 'tlist'.
457 create_tidscan_node(TidPath *best_path, List *tlist, List *scan_clauses)
462 /* there should be exactly one base rel involved... */
463 Assert(length(best_path->path.parent->relids) == 1);
464 Assert(! best_path->path.parent->issubquery);
466 scan_relid = (Index) lfirsti(best_path->path.parent->relids);
468 scan_node = make_tidscan(tlist,
473 if (best_path->unjoined_relids)
474 scan_node->needRescan = true;
476 copy_path_costsize(&scan_node->scan.plan, &best_path->path);
482 * create_subqueryscan_node
483 * Returns a subqueryscan node for the base relation scanned by 'best_path'
484 * with restriction clauses 'scan_clauses' and targetlist 'tlist'.
486 static SubqueryScan *
487 create_subqueryscan_node(Path *best_path, List *tlist, List *scan_clauses)
489 SubqueryScan *scan_node;
492 /* there should be exactly one base rel involved... */
493 Assert(length(best_path->parent->relids) == 1);
494 /* and it must be a subquery */
495 Assert(best_path->parent->issubquery);
497 scan_relid = (Index) lfirsti(best_path->parent->relids);
499 scan_node = make_subqueryscan(tlist,
502 best_path->parent->subplan);
504 copy_path_costsize(&scan_node->scan.plan, best_path);
509 /*****************************************************************************
513 * A general note about join_references() processing in these routines:
514 * once we have changed a Var node to refer to a subplan output rather than
515 * the original relation, it is no longer equal() to an unmodified Var node
516 * for the same var. So, we cannot easily compare reference-adjusted qual
517 * clauses to clauses that have not been adjusted. Fortunately, that
518 * doesn't seem to be necessary; all the decisions are made before we do
519 * the reference adjustments.
521 * A cleaner solution would be to not call join_references() here at all,
522 * but leave it for setrefs.c to do at the end of plan tree construction.
523 * But that would make switch_outer() much more complicated, and some care
524 * would be needed to get setrefs.c to do the right thing with nestloop
525 * inner indexscan quals. So, we do subplan reference adjustment here for
526 * quals of join nodes (and *only* for quals of join nodes).
528 *****************************************************************************/
531 create_nestloop_node(NestPath *best_path,
542 if (IsA(inner_node, IndexScan))
546 * An index is being used to reduce the number of tuples scanned
547 * in the inner relation. If there are join clauses being used
548 * with the index, we must update their outer-rel var nodes to
549 * refer to the outer side of the join.
551 * We can also remove those join clauses from the list of clauses
552 * that have to be checked as qpquals at the join node, but only
553 * if there's just one indexscan in the inner path (otherwise,
554 * several different sets of clauses are being ORed together).
556 * Note: if the index is lossy, the same clauses may also be getting
557 * checked as qpquals in the indexscan. We can still remove them
558 * from the nestloop's qpquals, but we gotta update the outer-rel
559 * vars in the indexscan's qpquals too.
561 * Note: we can safely do set_difference() against my clauses and
562 * join_references() because the innerscan is a primitive plan,
563 * and therefore has not itself done join_references renumbering
564 * of the vars in its quals.
566 IndexScan *innerscan = (IndexScan *) inner_node;
567 List *indxqualorig = innerscan->indxqualorig;
569 /* No work needed if indxqual refers only to its own relation... */
570 if (NumRelids((Node *) indxqualorig) > 1)
572 Index innerrel = innerscan->scan.scanrelid;
575 * Remove redundant tests from my clauses, if possible. Note
576 * we must compare against indxqualorig not the "fixed"
577 * indxqual (which has index attnos instead of relation
578 * attnos, and may have been commuted as well).
580 if (length(indxqualorig) == 1) /* single indexscan? */
581 joinclauses = set_difference(joinclauses,
582 lfirst(indxqualorig));
584 /* only refs to outer vars get changed in the inner indexqual */
585 innerscan->indxqualorig = join_references(indxqualorig,
589 innerscan->indxqual = join_references(innerscan->indxqual,
593 /* fix the inner qpqual too, if it has join clauses */
594 if (NumRelids((Node *) inner_node->qual) > 1)
595 inner_node->qual = join_references(inner_node->qual,
601 else if (IsA(inner_node, TidScan))
603 TidScan *innerscan = (TidScan *) inner_node;
605 innerscan->tideval = join_references(innerscan->tideval,
608 innerscan->scan.scanrelid);
610 else if (IsA_Join(inner_node))
614 * Materialize the inner join for speed reasons.
616 * XXX It is probably *not* always fastest to materialize an inner
617 * join --- how can we estimate whether this is a good thing to
620 inner_node = (Plan *) make_material(inner_tlist,
625 * Set quals to contain INNER/OUTER var references.
627 joinclauses = join_references(joinclauses,
631 otherclauses = join_references(otherclauses,
636 join_node = make_nestloop(tlist,
641 best_path->jointype);
643 copy_path_costsize(&join_node->join.plan, &best_path->path);
649 create_mergejoin_node(MergePath *best_path,
659 MergeJoin *join_node;
661 mergeclauses = get_actual_clauses(best_path->path_mergeclauses);
664 * Remove the mergeclauses from the list of join qual clauses, leaving
665 * the list of quals that must be checked as qpquals. Set those
666 * clauses to contain INNER/OUTER var references.
668 joinclauses = join_references(set_difference(joinclauses, mergeclauses),
674 * Fix the additional qpquals too.
676 otherclauses = join_references(otherclauses,
682 * Now set the references in the mergeclauses and rearrange them so
683 * that the outer variable is always on the left.
685 mergeclauses = switch_outer(join_references(mergeclauses,
691 * Create explicit sort nodes for the outer and inner join paths if
692 * necessary. The sort cost was already accounted for in the path.
694 if (best_path->outersortkeys)
695 outer_node = (Plan *)
696 make_sort_from_pathkeys(outer_tlist,
698 best_path->outersortkeys);
700 if (best_path->innersortkeys)
701 inner_node = (Plan *)
702 make_sort_from_pathkeys(inner_tlist,
704 best_path->innersortkeys);
707 * The executor requires the inner side of a mergejoin to support "mark"
708 * and "restore" operations. Not all plan types do, so we must be careful
709 * not to generate an invalid plan. If necessary, an invalid inner plan
710 * can be handled by inserting a Materialize node.
712 * Since the inner side must be ordered, and only Sorts and IndexScans can
713 * create order to begin with, you might think there's no problem --- but
714 * you'd be wrong. Nestloop and merge joins can *preserve* the order of
715 * their inputs, so they can be selected as the input of a mergejoin,
716 * and that won't work in the present executor.
718 * Doing this here is a bit of a kluge since the cost of the Materialize
719 * wasn't taken into account in our earlier decisions. But Materialize
720 * is hard to estimate a cost for, and the above consideration shows that
721 * this is a rare case anyway, so this seems an acceptable way to proceed.
723 * This check must agree with ExecMarkPos/ExecRestrPos in
724 * executor/execAmi.c!
726 switch (nodeTag(inner_node))
732 /* OK, these inner plans support mark/restore */
736 /* Ooops, need to materialize the inner plan */
737 inner_node = (Plan *) make_material(inner_tlist,
743 * Now we can build the mergejoin node.
745 join_node = make_mergejoin(tlist,
751 best_path->jpath.jointype);
753 copy_path_costsize(&join_node->join.plan, &best_path->jpath.path);
759 create_hashjoin_node(HashPath *best_path,
774 * NOTE: there will always be exactly one hashclause in the list
775 * best_path->path_hashclauses (cf. hash_inner_and_outer()). We
776 * represent it as a list anyway, for convenience with routines that
777 * want to work on lists of clauses.
779 hashclauses = get_actual_clauses(best_path->path_hashclauses);
782 * Remove the hashclauses from the list of join qual clauses, leaving
783 * the list of quals that must be checked as qpquals. Set those
784 * clauses to contain INNER/OUTER var references.
786 joinclauses = join_references(set_difference(joinclauses, hashclauses),
792 * Fix the additional qpquals too.
794 otherclauses = join_references(otherclauses,
800 * Now set the references in the hashclauses and rearrange them so
801 * that the outer variable is always on the left.
803 hashclauses = switch_outer(join_references(hashclauses,
808 /* Now the righthand op of the sole hashclause is the inner hash key. */
809 innerhashkey = (Node *) get_rightop(lfirst(hashclauses));
812 * Build the hash node and hash join node.
814 hash_node = make_hash(inner_tlist, innerhashkey, inner_node);
815 join_node = make_hashjoin(tlist,
821 best_path->jpath.jointype);
823 copy_path_costsize(&join_node->join.plan, &best_path->jpath.path);
829 /*****************************************************************************
831 * SUPPORTING ROUTINES
833 *****************************************************************************/
836 * fix_indxqual_references
837 * Adjust indexqual clauses to the form the executor's indexqual
840 * We have three tasks here:
841 * * Index keys must be represented by Var nodes with varattno set to the
842 * index's attribute number, not the attribute number in the original rel.
843 * * indxpath.c may have selected an index that is binary-compatible with
844 * the actual expression operator, but not exactly the same datatype.
845 * We must replace the expression's operator with the binary-compatible
846 * equivalent operator that the index will recognize.
847 * * If the index key is on the right, commute the clause to put it on the
848 * left. (Someday the executor might not need this, but for now it does.)
850 * This code used to be entirely bogus for multi-index scans. Now it keeps
851 * track of which index applies to each subgroup of index qual clauses...
853 * Returns a modified copy of the indexqual list --- the original is not
854 * changed. Note also that the copy shares no substructure with the
855 * original; this is needed in case there is a subplan in it (we need
856 * two separate copies of the subplan tree, or things will go awry).
860 fix_indxqual_references(List *indexquals, IndexPath *index_path)
862 List *fixed_quals = NIL;
863 int baserelid = lfirsti(index_path->path.parent->relids);
864 List *indexids = index_path->indexid;
867 foreach(i, indexquals)
869 List *indexqual = lfirst(i);
870 Oid indexid = lfirsti(indexids);
871 HeapTuple indexTuple;
875 /* Get the relam from the index's pg_class entry */
876 indexTuple = SearchSysCacheTuple(RELOID,
877 ObjectIdGetDatum(indexid),
879 if (!HeapTupleIsValid(indexTuple))
880 elog(ERROR, "fix_indxqual_references: index %u not found in pg_class",
882 relam = ((Form_pg_class) GETSTRUCT(indexTuple))->relam;
884 /* Need the index's pg_index entry for other stuff */
885 indexTuple = SearchSysCacheTuple(INDEXRELID,
886 ObjectIdGetDatum(indexid),
888 if (!HeapTupleIsValid(indexTuple))
889 elog(ERROR, "fix_indxqual_references: index %u not found in pg_index",
891 index = (Form_pg_index) GETSTRUCT(indexTuple);
893 fixed_quals = lappend(fixed_quals,
894 fix_indxqual_sublist(indexqual,
899 indexids = lnext(indexids);
905 * Fix the sublist of indexquals to be used in a particular scan.
907 * For each qual clause, commute if needed to put the indexkey operand on the
908 * left, and then fix its varattno. (We do not need to change the other side
909 * of the clause.) Also change the operator if necessary.
912 fix_indxqual_sublist(List *indexqual, int baserelid, Oid relam,
915 List *fixed_qual = NIL;
918 foreach(i, indexqual)
920 Expr *clause = (Expr *) lfirst(i);
929 if (!is_opclause((Node *) clause) ||
930 length(clause->args) != 2)
931 elog(ERROR, "fix_indxqual_sublist: indexqual clause is not binary opclause");
934 * Which side is the indexkey on?
936 * get_relattval sets flag&SEL_RIGHT if the indexkey is on the LEFT.
938 get_relattval((Node *) clause, baserelid,
939 &relid, &attno, &constval, &flag);
942 * Make a copy that will become the fixed clause.
944 * We used to try to do a shallow copy here, but that fails if there
945 * is a subplan in the arguments of the opclause. So just do a
948 newclause = (Expr *) copyObject((Node *) clause);
950 /* If the indexkey is on the right, commute the clause. */
951 if ((flag & SEL_RIGHT) == 0)
952 CommuteClause(newclause);
955 * Now, determine which index attribute this is, change the
956 * indexkey operand as needed, and get the index opclass.
958 lfirst(newclause->args) = fix_indxqual_operand(lfirst(newclause->args),
964 * Substitute the appropriate operator if the expression operator
965 * is merely binary-compatible with the index. This shouldn't
966 * fail, since indxpath.c found it before...
968 newopno = indexable_operator(newclause, opclass, relam, true);
969 if (newopno == InvalidOid)
970 elog(ERROR, "fix_indxqual_sublist: failed to find substitute op");
971 ((Oper *) newclause->oper)->opno = newopno;
973 fixed_qual = lappend(fixed_qual, newclause);
979 fix_indxqual_operand(Node *node, int baserelid, Form_pg_index index,
983 * Remove any binary-compatible relabeling of the indexkey
985 if (IsA(node, RelabelType))
986 node = ((RelabelType *) node)->arg;
989 * We represent index keys by Var nodes having the varno of the base
990 * table but varattno equal to the index's attribute number (index
991 * column position). This is a bit hokey ... would be cleaner to use
992 * a special-purpose node type that could not be mistaken for a regular
993 * Var. But it will do for now.
997 /* If it's a var, find which index key position it occupies */
998 if (((Var *) node)->varno == baserelid)
1000 int varatt = ((Var *) node)->varattno;
1003 for (pos = 0; pos < INDEX_MAX_KEYS; pos++)
1005 if (index->indkey[pos] == varatt)
1007 Node *newnode = copyObject(node);
1009 ((Var *) newnode)->varattno = pos + 1;
1010 /* return the correct opclass, too */
1011 *opclass = index->indclass[pos];
1018 * Oops, this Var isn't the indexkey!
1020 elog(ERROR, "fix_indxqual_operand: var is not index attribute");
1024 * Else, it must be a func expression matching a functional index.
1025 * Since we currently only support single-column functional indexes,
1026 * the returned varattno must be 1.
1029 Assert(is_funcclause(node)); /* not a very thorough check, but easy */
1031 /* indclass[0] is the only class of a functional index */
1032 *opclass = index->indclass[0];
1034 return (Node *) makeVar(baserelid, 1, exprType(node), -1, 0);
1039 * Given a list of merge or hash joinclauses, rearrange the elements within
1040 * the clauses so the outer join variable is on the left and the inner is
1041 * on the right. The original list is not touched; a modified list
1045 switch_outer(List *clauses)
1052 Expr *clause = (Expr *) lfirst(i);
1055 Assert(is_opclause((Node *) clause));
1056 op = get_rightop(clause);
1057 Assert(op && IsA(op, Var));
1058 if (var_is_outer(op))
1062 * Duplicate just enough of the structure to allow commuting
1063 * the clause without changing the original list. Could use
1064 * copyObject, but a complete deep copy is overkill.
1068 temp = make_clause(clause->opType, clause->oper,
1069 listCopy(clause->args));
1070 /* Commute it --- note this modifies the temp node in-place. */
1071 CommuteClause(temp);
1072 t_list = lappend(t_list, temp);
1075 t_list = lappend(t_list, clause);
1081 * Copy cost and size info from a Path node to the Plan node created from it.
1082 * The executor won't use this info, but it's needed by EXPLAIN.
1085 copy_path_costsize(Plan *dest, Path *src)
1089 dest->startup_cost = src->startup_cost;
1090 dest->total_cost = src->total_cost;
1091 dest->plan_rows = src->parent->rows;
1092 dest->plan_width = src->parent->width;
1096 dest->startup_cost = 0;
1097 dest->total_cost = 0;
1098 dest->plan_rows = 0;
1099 dest->plan_width = 0;
1104 * Copy cost and size info from a lower plan node to an inserted node.
1105 * This is not critical, since the decisions have already been made,
1106 * but it helps produce more reasonable-looking EXPLAIN output.
1107 * (Some callers alter the info after copying it.)
1110 copy_plan_costsize(Plan *dest, Plan *src)
1114 dest->startup_cost = src->startup_cost;
1115 dest->total_cost = src->total_cost;
1116 dest->plan_rows = src->plan_rows;
1117 dest->plan_width = src->plan_width;
1121 dest->startup_cost = 0;
1122 dest->total_cost = 0;
1123 dest->plan_rows = 0;
1124 dest->plan_width = 0;
1129 /*****************************************************************************
1132 *****************************************************************************/
1135 make_seqscan(List *qptlist,
1139 SeqScan *node = makeNode(SeqScan);
1140 Plan *plan = &node->plan;
1142 /* cost should be inserted by caller */
1143 plan->state = (EState *) NULL;
1144 plan->targetlist = qptlist;
1145 plan->qual = qpqual;
1146 plan->lefttree = NULL;
1147 plan->righttree = NULL;
1148 node->scanrelid = scanrelid;
1149 node->scanstate = (CommonScanState *) NULL;
1155 make_indexscan(List *qptlist,
1161 ScanDirection indexscandir)
1163 IndexScan *node = makeNode(IndexScan);
1164 Plan *plan = &node->scan.plan;
1166 /* cost should be inserted by caller */
1167 plan->state = (EState *) NULL;
1168 plan->targetlist = qptlist;
1169 plan->qual = qpqual;
1170 plan->lefttree = NULL;
1171 plan->righttree = NULL;
1172 node->scan.scanrelid = scanrelid;
1173 node->indxid = indxid;
1174 node->indxqual = indxqual;
1175 node->indxqualorig = indxqualorig;
1176 node->indxorderdir = indexscandir;
1177 node->scan.scanstate = (CommonScanState *) NULL;
1183 make_tidscan(List *qptlist,
1188 TidScan *node = makeNode(TidScan);
1189 Plan *plan = &node->scan.plan;
1191 /* cost should be inserted by caller */
1192 plan->state = (EState *) NULL;
1193 plan->targetlist = qptlist;
1194 plan->qual = qpqual;
1195 plan->lefttree = NULL;
1196 plan->righttree = NULL;
1197 node->scan.scanrelid = scanrelid;
1198 node->tideval = copyObject(tideval); /* XXX do we really need a
1200 node->needRescan = false;
1201 node->scan.scanstate = (CommonScanState *) NULL;
1207 make_subqueryscan(List *qptlist,
1212 SubqueryScan *node = makeNode(SubqueryScan);
1213 Plan *plan = &node->scan.plan;
1215 /* cost should be inserted by caller */
1216 plan->state = (EState *) NULL;
1217 plan->targetlist = qptlist;
1218 plan->qual = qpqual;
1219 plan->lefttree = NULL;
1220 plan->righttree = NULL;
1221 node->scan.scanrelid = scanrelid;
1222 node->subplan = subplan;
1223 node->scan.scanstate = (CommonScanState *) NULL;
1230 make_nestloop(List *tlist,
1237 NestLoop *node = makeNode(NestLoop);
1238 Plan *plan = &node->join.plan;
1240 /* cost should be inserted by caller */
1241 plan->state = (EState *) NULL;
1242 plan->targetlist = tlist;
1243 plan->qual = otherclauses;
1244 plan->lefttree = lefttree;
1245 plan->righttree = righttree;
1246 node->join.jointype = jointype;
1247 node->join.joinqual = joinclauses;
1253 make_hashjoin(List *tlist,
1261 HashJoin *node = makeNode(HashJoin);
1262 Plan *plan = &node->join.plan;
1264 /* cost should be inserted by caller */
1265 plan->state = (EState *) NULL;
1266 plan->targetlist = tlist;
1267 plan->qual = otherclauses;
1268 plan->lefttree = lefttree;
1269 plan->righttree = righttree;
1270 node->hashclauses = hashclauses;
1271 node->join.jointype = jointype;
1272 node->join.joinqual = joinclauses;
1278 make_hash(List *tlist, Node *hashkey, Plan *lefttree)
1280 Hash *node = makeNode(Hash);
1281 Plan *plan = &node->plan;
1283 copy_plan_costsize(plan, lefttree);
1286 * For plausibility, make startup & total costs equal total cost of
1287 * input plan; this only affects EXPLAIN display not decisions.
1289 plan->startup_cost = plan->total_cost;
1290 plan->state = (EState *) NULL;
1291 plan->targetlist = tlist;
1293 plan->lefttree = lefttree;
1294 plan->righttree = NULL;
1295 node->hashkey = hashkey;
1301 make_mergejoin(List *tlist,
1309 MergeJoin *node = makeNode(MergeJoin);
1310 Plan *plan = &node->join.plan;
1312 /* cost should be inserted by caller */
1313 plan->state = (EState *) NULL;
1314 plan->targetlist = tlist;
1315 plan->qual = otherclauses;
1316 plan->lefttree = lefttree;
1317 plan->righttree = righttree;
1318 node->mergeclauses = mergeclauses;
1319 node->join.jointype = jointype;
1320 node->join.joinqual = joinclauses;
1326 * To use make_sort directly, you must already have marked the tlist
1327 * with reskey and reskeyop information. The keys had better be
1328 * non-redundant, too (ie, there had better be tlist items marked with
1329 * each key number from 1 to keycount), or the executor will get confused!
1332 make_sort(List *tlist, Plan *lefttree, int keycount)
1334 Sort *node = makeNode(Sort);
1335 Plan *plan = &node->plan;
1336 Path sort_path; /* dummy for result of cost_sort */
1338 copy_plan_costsize(plan, lefttree); /* only care about copying size */
1339 cost_sort(&sort_path, NIL, lefttree->plan_rows, lefttree->plan_width);
1340 plan->startup_cost = sort_path.startup_cost + lefttree->total_cost;
1341 plan->total_cost = sort_path.total_cost + lefttree->total_cost;
1342 plan->state = (EState *) NULL;
1343 plan->targetlist = tlist;
1345 plan->lefttree = lefttree;
1346 plan->righttree = NULL;
1347 node->keycount = keycount;
1353 * make_sort_from_pathkeys
1354 * Create sort plan to sort according to given pathkeys
1356 * 'tlist' is the target list of the input plan
1357 * 'lefttree' is the node which yields input tuples
1358 * 'pathkeys' is the list of pathkeys by which the result is to be sorted
1360 * We must convert the pathkey information into reskey and reskeyop fields
1361 * of resdom nodes in the sort plan's target list.
1364 make_sort_from_pathkeys(List *tlist, Plan *lefttree, List *pathkeys)
1368 int numsortkeys = 0;
1370 /* Create a new target list for the sort, with sort keys set. */
1371 sort_tlist = new_unsorted_tlist(tlist);
1373 foreach(i, pathkeys)
1375 List *keysublist = (List *) lfirst(i);
1376 PathKeyItem *pathkey = NULL;
1377 Resdom *resdom = NULL;
1381 * We can sort by any one of the sort key items listed in this
1382 * sublist. For now, we take the first one that corresponds to an
1383 * available Var in the sort_tlist.
1385 * XXX if we have a choice, is there any way of figuring out which
1386 * might be cheapest to execute? (For example, int4lt is likely
1387 * much cheaper to execute than numericlt, but both might appear
1388 * in the same pathkey sublist...) Not clear that we ever will
1389 * have a choice in practice, so it may not matter.
1391 foreach(j, keysublist)
1393 pathkey = lfirst(j);
1394 Assert(IsA(pathkey, PathKeyItem));
1395 resdom = tlist_member(pathkey->key, sort_tlist);
1400 elog(ERROR, "make_sort_from_pathkeys: cannot find tlist item to sort");
1403 * The resdom might be already marked as a sort key, if the
1404 * pathkeys contain duplicate entries. (This can happen in
1405 * scenarios where multiple mergejoinable clauses mention the same
1406 * var, for example.) In that case the current pathkey is
1407 * essentially a no-op, because only one value can be seen within
1408 * any subgroup where it would be consulted. We can ignore it.
1410 if (resdom->reskey == 0)
1412 /* OK, mark it as a sort key and set the sort operator regproc */
1413 resdom->reskey = ++numsortkeys;
1414 resdom->reskeyop = get_opcode(pathkey->sortop);
1418 Assert(numsortkeys > 0);
1420 return make_sort(sort_tlist, lefttree, numsortkeys);
1424 make_material(List *tlist, Plan *lefttree)
1426 Material *node = makeNode(Material);
1427 Plan *plan = &node->plan;
1429 copy_plan_costsize(plan, lefttree);
1432 * For plausibility, make startup & total costs equal total cost of
1433 * input plan; this only affects EXPLAIN display not decisions.
1435 * XXX shouldn't we charge some additional cost for materialization?
1437 plan->startup_cost = plan->total_cost;
1438 plan->state = (EState *) NULL;
1439 plan->targetlist = tlist;
1441 plan->lefttree = lefttree;
1442 plan->righttree = NULL;
1448 make_agg(List *tlist, List *qual, Plan *lefttree)
1450 Agg *node = makeNode(Agg);
1451 Plan *plan = &node->plan;
1453 copy_plan_costsize(plan, lefttree);
1456 * Charge one cpu_operator_cost per aggregate function per input
1459 plan->total_cost += cpu_operator_cost * plan->plan_rows *
1460 (length(pull_agg_clause((Node *) tlist)) +
1461 length(pull_agg_clause((Node *) qual)));
1464 * We will produce a single output tuple if the input is not a Group,
1465 * and a tuple per group otherwise. For now, estimate the number of
1466 * groups as 10% of the number of tuples --- bogus, but how to do
1467 * better? (Note we assume the input Group node is in "tuplePerGroup"
1468 * mode, so it didn't reduce its row count already.)
1470 if (IsA(lefttree, Group))
1472 plan->plan_rows *= 0.1;
1473 if (plan->plan_rows < 1)
1474 plan->plan_rows = 1;
1478 plan->plan_rows = 1;
1479 plan->startup_cost = plan->total_cost;
1482 plan->state = (EState *) NULL;
1484 plan->targetlist = tlist;
1485 plan->lefttree = lefttree;
1486 plan->righttree = (Plan *) NULL;
1492 make_group(List *tlist,
1495 AttrNumber *grpColIdx,
1498 Group *node = makeNode(Group);
1499 Plan *plan = &node->plan;
1501 copy_plan_costsize(plan, lefttree);
1504 * Charge one cpu_operator_cost per comparison per input tuple. We
1505 * assume all columns get compared at most of the tuples.
1507 plan->total_cost += cpu_operator_cost * plan->plan_rows * ngrp;
1510 * If tuplePerGroup (which is named exactly backwards) is true, we
1511 * will return all the input tuples, so the input node's row count is
1512 * OK. Otherwise, we'll return only one tuple from each group. For
1513 * now, estimate the number of groups as 10% of the number of tuples
1514 * --- bogus, but how to do better?
1518 plan->plan_rows *= 0.1;
1519 if (plan->plan_rows < 1)
1520 plan->plan_rows = 1;
1523 plan->state = (EState *) NULL;
1525 plan->targetlist = tlist;
1526 plan->lefttree = lefttree;
1527 plan->righttree = (Plan *) NULL;
1528 node->tuplePerGroup = tuplePerGroup;
1529 node->numCols = ngrp;
1530 node->grpColIdx = grpColIdx;
1536 * distinctList is a list of SortClauses, identifying the targetlist items
1537 * that should be considered by the Unique filter.
1541 make_unique(List *tlist, Plan *lefttree, List *distinctList)
1543 Unique *node = makeNode(Unique);
1544 Plan *plan = &node->plan;
1545 int numCols = length(distinctList);
1547 AttrNumber *uniqColIdx;
1550 copy_plan_costsize(plan, lefttree);
1553 * Charge one cpu_operator_cost per comparison per input tuple. We
1554 * assume all columns get compared at most of the tuples.
1556 plan->total_cost += cpu_operator_cost * plan->plan_rows * numCols;
1559 * As for Group, we make the unsupported assumption that there will be
1560 * 10% as many tuples out as in.
1562 plan->plan_rows *= 0.1;
1563 if (plan->plan_rows < 1)
1564 plan->plan_rows = 1;
1566 plan->state = (EState *) NULL;
1567 plan->targetlist = tlist;
1569 plan->lefttree = lefttree;
1570 plan->righttree = NULL;
1573 * convert SortClause list into array of attr indexes, as wanted by
1576 Assert(numCols > 0);
1577 uniqColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
1579 foreach(slitem, distinctList)
1581 SortClause *sortcl = (SortClause *) lfirst(slitem);
1582 TargetEntry *tle = get_sortgroupclause_tle(sortcl, tlist);
1584 uniqColIdx[keyno++] = tle->resdom->resno;
1587 node->numCols = numCols;
1588 node->uniqColIdx = uniqColIdx;
1594 * distinctList is a list of SortClauses, identifying the targetlist items
1595 * that should be considered by the SetOp filter.
1599 make_setop(SetOpCmd cmd, List *tlist, Plan *lefttree,
1600 List *distinctList, AttrNumber flagColIdx)
1602 SetOp *node = makeNode(SetOp);
1603 Plan *plan = &node->plan;
1604 int numCols = length(distinctList);
1606 AttrNumber *dupColIdx;
1609 copy_plan_costsize(plan, lefttree);
1612 * Charge one cpu_operator_cost per comparison per input tuple. We
1613 * assume all columns get compared at most of the tuples.
1615 plan->total_cost += cpu_operator_cost * plan->plan_rows * numCols;
1618 * As for Group, we make the unsupported assumption that there will be
1619 * 10% as many tuples out as in.
1621 plan->plan_rows *= 0.1;
1622 if (plan->plan_rows < 1)
1623 plan->plan_rows = 1;
1625 plan->state = (EState *) NULL;
1626 plan->targetlist = tlist;
1628 plan->lefttree = lefttree;
1629 plan->righttree = NULL;
1632 * convert SortClause list into array of attr indexes, as wanted by
1635 Assert(numCols > 0);
1636 dupColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
1638 foreach(slitem, distinctList)
1640 SortClause *sortcl = (SortClause *) lfirst(slitem);
1641 TargetEntry *tle = get_sortgroupclause_tle(sortcl, tlist);
1643 dupColIdx[keyno++] = tle->resdom->resno;
1647 node->numCols = numCols;
1648 node->dupColIdx = dupColIdx;
1649 node->flagColIdx = flagColIdx;
1655 make_limit(List *tlist, Plan *lefttree,
1656 Node *limitOffset, Node *limitCount)
1658 Limit *node = makeNode(Limit);
1659 Plan *plan = &node->plan;
1661 copy_plan_costsize(plan, lefttree);
1663 plan->state = (EState *) NULL;
1664 plan->targetlist = tlist;
1666 plan->lefttree = lefttree;
1667 plan->righttree = NULL;
1669 node->limitOffset = limitOffset;
1670 node->limitCount = limitCount;
1676 make_result(List *tlist,
1677 Node *resconstantqual,
1680 Result *node = makeNode(Result);
1681 Plan *plan = &node->plan;
1684 tlist = generate_fjoin(tlist);
1686 copy_plan_costsize(plan, subplan);
1687 plan->state = (EState *) NULL;
1688 plan->targetlist = tlist;
1690 plan->lefttree = subplan;
1691 plan->righttree = NULL;
1692 node->resconstantqual = resconstantqual;
1693 node->resstate = NULL;
1700 generate_fjoin(List *tlist)
1703 List newTlist = NIL;
1704 List fjoinList = NIL;
1708 * Break the target list into elements with Iter nodes, and those
1711 foreach(tlistP, tlist)
1715 tlistElem = lfirst(tlistP);
1716 if (IsA(lsecond(tlistElem), Iter))
1719 fjoinList = lappend(fjoinList, tlistElem);
1722 newTlist = lappend(newTlist, tlistElem);
1726 * if we have an Iter node then we need to flatten.
1733 DatumPtr results = (DatumPtr) palloc(nIters * sizeof(Datum));
1734 BoolPtr alwaysDone = (BoolPtr) palloc(nIters * sizeof(bool));
1736 inner = lfirst(fjoinList);
1737 fjoinList = lnext(fjoinList);
1738 fjoinNode = (Fjoin) MakeFjoin(false,
1743 tempList = lcons(fjoinNode, fjoinList);
1744 newTlist = lappend(newTlist, tempList);
1747 return tlist; /* do nothing for now - ay 10/94 */