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.96 2000/09/12 21:06:53 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 NestLoop *create_nestloop_node(NestPath *best_path, List *tlist,
45 List *joinclauses, List *otherclauses,
46 Plan *outer_node, List *outer_tlist,
47 Plan *inner_node, List *inner_tlist);
48 static MergeJoin *create_mergejoin_node(MergePath *best_path, List *tlist,
49 List *joinclauses, List *otherclauses,
50 Plan *outer_node, List *outer_tlist,
51 Plan *inner_node, List *inner_tlist);
52 static HashJoin *create_hashjoin_node(HashPath *best_path, List *tlist,
53 List *joinclauses, List *otherclauses,
54 Plan *outer_node, List *outer_tlist,
55 Plan *inner_node, List *inner_tlist);
56 static List *fix_indxqual_references(List *indexquals, IndexPath *index_path);
57 static List *fix_indxqual_sublist(List *indexqual, int baserelid, Oid relam,
59 static Node *fix_indxqual_operand(Node *node, int baserelid,
62 static SeqScan *make_seqscan(List *qptlist, List *qpqual, Index scanrelid);
63 static IndexScan *make_indexscan(List *qptlist, List *qpqual, Index scanrelid,
64 List *indxid, List *indxqual,
66 ScanDirection indexscandir);
67 static TidScan *make_tidscan(List *qptlist, List *qpqual, Index scanrelid,
69 static NestLoop *make_nestloop(List *tlist,
70 List *joinclauses, List *otherclauses,
71 Plan *lefttree, Plan *righttree,
73 static HashJoin *make_hashjoin(List *tlist,
74 List *joinclauses, List *otherclauses,
76 Plan *lefttree, Plan *righttree,
78 static Hash *make_hash(List *tlist, Node *hashkey, Plan *lefttree);
79 static MergeJoin *make_mergejoin(List *tlist,
80 List *joinclauses, List *otherclauses,
82 Plan *lefttree, Plan *righttree,
84 static void copy_path_costsize(Plan *dest, Path *src);
85 static void copy_plan_costsize(Plan *dest, Plan *src);
89 * Creates the access plan for a query by tracing backwards through the
90 * desired chain of pathnodes, starting at the node 'best_path'. For
91 * every pathnode found:
92 * (1) Create a corresponding plan node containing appropriate id,
93 * target list, and qualification information.
94 * (2) Modify qual clauses of join nodes so that subplan attributes are
95 * referenced using relative values.
96 * (3) Target lists are not modified, but will be in setrefs.c.
98 * best_path is the best access path
100 * Returns the access plan.
103 create_plan(Query *root, Path *best_path)
105 List *tlist = best_path->parent->targetlist;
106 Plan *plan_node = (Plan *) NULL;
108 switch (best_path->pathtype)
113 plan_node = (Plan *) create_scan_node(root, best_path, tlist);
118 plan_node = (Plan *) create_join_node(root,
119 (JoinPath *) best_path,
123 elog(ERROR, "create_plan: unknown pathtype %d",
124 best_path->pathtype);
128 #ifdef NOT_USED /* fix xfunc */
129 /* sort clauses by cost/(1-selectivity) -- JMH 2/26/92 */
130 if (XfuncMode != XFUNC_OFF)
132 set_qpqual((Plan) plan_node,
133 lisp_qsort(get_qpqual((Plan) plan_node),
134 xfunc_clause_compare));
135 if (XfuncMode != XFUNC_NOR)
136 /* sort the disjuncts within each clause by cost -- JMH 3/4/92 */
137 xfunc_disjunct_sort(plan_node->qpqual);
146 * Create a scan path for the parent relation of 'best_path'.
148 * tlist is the targetlist for the base relation scanned by 'best_path'
150 * Returns the scan node.
153 create_scan_node(Query *root, Path *best_path, List *tlist)
159 * Extract the relevant restriction clauses from the parent relation;
160 * the executor must apply all these restrictions during the scan.
162 scan_clauses = get_actual_clauses(best_path->parent->baserestrictinfo);
164 switch (best_path->pathtype)
167 node = (Scan *) create_seqscan_node(best_path, tlist, scan_clauses);
171 node = (Scan *) create_indexscan_node(root,
172 (IndexPath *) best_path,
178 node = (Scan *) create_tidscan_node((TidPath *) best_path,
184 elog(ERROR, "create_scan_node: unknown node type: %d",
185 best_path->pathtype);
194 * Create a join path for 'best_path' and(recursively) paths for its
195 * inner and outer paths.
197 * 'tlist' is the targetlist for the join relation corresponding to
200 * Returns the join node.
203 create_join_node(Query *root, JoinPath *best_path, List *tlist)
213 outer_node = create_plan(root, best_path->outerjoinpath);
214 outer_tlist = outer_node->targetlist;
216 inner_node = create_plan(root, best_path->innerjoinpath);
217 inner_tlist = inner_node->targetlist;
219 if (IS_OUTER_JOIN(best_path->jointype))
221 get_actual_join_clauses(best_path->joinrestrictinfo,
222 &joinclauses, &otherclauses);
226 /* We can treat all clauses alike for an inner join */
227 joinclauses = get_actual_clauses(best_path->joinrestrictinfo);
231 switch (best_path->path.pathtype)
234 retval = (Join *) create_mergejoin_node((MergePath *) best_path,
244 retval = (Join *) create_hashjoin_node((HashPath *) best_path,
254 retval = (Join *) create_nestloop_node((NestPath *) best_path,
264 elog(ERROR, "create_join_node: unknown node type: %d",
265 best_path->path.pathtype);
271 * * Expensive function pullups may have pulled local predicates *
272 * into this path node. Put them in the qpqual of the plan node. *
275 if (get_loc_restrictinfo(best_path) != NIL)
276 set_qpqual((Plan) retval,
277 nconc(get_qpqual((Plan) retval),
278 get_actual_clauses(get_loc_restrictinfo(best_path))));
284 /*****************************************************************************
286 * BASE-RELATION SCAN METHODS
288 *****************************************************************************/
292 * create_seqscan_node
293 * Returns a seqscan node for the base relation scanned by 'best_path'
294 * with restriction clauses 'scan_clauses' and targetlist 'tlist'.
297 create_seqscan_node(Path *best_path, List *tlist, List *scan_clauses)
302 /* there should be exactly one base rel involved... */
303 Assert(length(best_path->parent->relids) == 1);
305 scan_relid = (Index) lfirsti(best_path->parent->relids);
307 scan_node = make_seqscan(tlist,
311 copy_path_costsize(&scan_node->plan, best_path);
317 * create_indexscan_node
318 * Returns a indexscan node for the base relation scanned by 'best_path'
319 * with restriction clauses 'scan_clauses' and targetlist 'tlist'.
321 * The indexqual of the path contains a sublist of implicitly-ANDed qual
322 * conditions for each scan of the index(es); if there is more than one
323 * scan then the retrieved tuple sets are ORed together. The indexqual
324 * and indexid lists must have the same length, ie, the number of scans
325 * that will occur. Note it is possible for a qual condition sublist
326 * to be empty --- then no index restrictions will be applied during that
330 create_indexscan_node(Query *root,
331 IndexPath *best_path,
335 List *indxqual = best_path->indexqual;
338 List *fixed_indxqual;
340 IndexScan *scan_node;
343 /* there should be exactly one base rel involved... */
344 Assert(length(best_path->path.parent->relids) == 1);
345 baserelid = lfirsti(best_path->path.parent->relids);
347 /* check to see if any of the indices are lossy */
348 foreach(ixid, best_path->indexid)
350 HeapTuple indexTuple;
353 indexTuple = SearchSysCacheTuple(INDEXRELID,
354 ObjectIdGetDatum(lfirsti(ixid)),
356 if (!HeapTupleIsValid(indexTuple))
357 elog(ERROR, "create_plan: index %u not found", lfirsti(ixid));
358 index = (Form_pg_index) GETSTRUCT(indexTuple);
359 if (index->indislossy)
367 * The qpqual list must contain all restrictions not automatically
368 * handled by the index. Note that for non-lossy indices, the
369 * predicates in the indxqual are checked fully by the index, while
370 * for lossy indices the indxqual predicates need to be double-checked
371 * after the index fetches the best-guess tuples.
373 * Since the indexquals were generated from the restriction clauses given
374 * by scan_clauses, there will normally be some duplications between
375 * the lists. We get rid of the duplicates, then add back if lossy.
377 if (length(indxqual) > 1)
381 * Build an expression representation of the indexqual, expanding
382 * the implicit OR and AND semantics of the first- and
383 * second-level lists.
385 List *orclauses = NIL;
389 foreach(orclause, indxqual)
390 orclauses = lappend(orclauses,
391 make_ands_explicit(lfirst(orclause)));
392 indxqual_expr = make_orclause(orclauses);
394 qpqual = set_difference(scan_clauses,
395 lcons(indxqual_expr, NIL));
398 qpqual = lappend(qpqual, copyObject(indxqual_expr));
400 else if (indxqual != NIL)
404 * Here, we can simply treat the first sublist as an independent
405 * set of qual expressions, since there is no top-level OR
408 List *indxqual_list = lfirst(indxqual);
410 qpqual = set_difference(scan_clauses, indxqual_list);
413 qpqual = nconc(qpqual, (List *) copyObject(indxqual_list));
416 qpqual = scan_clauses;
419 * The executor needs a copy with the indexkey on the left of each
420 * clause and with index attr numbers substituted for table ones.
422 fixed_indxqual = fix_indxqual_references(indxqual, best_path);
424 scan_node = make_indexscan(tlist,
430 best_path->indexscandir);
432 copy_path_costsize(&scan_node->scan.plan, &best_path->path);
433 /* use the indexscan-specific rows estimate, not the parent rel's */
434 scan_node->scan.plan.plan_rows = best_path->rows;
440 * create_tidscan_node
441 * Returns a tidscan node for the base relation scanned by 'best_path'
442 * with restriction clauses 'scan_clauses' and targetlist 'tlist'.
445 create_tidscan_node(TidPath *best_path, List *tlist, List *scan_clauses)
450 /* there should be exactly one base rel involved... */
451 Assert(length(best_path->path.parent->relids) == 1);
453 scan_relid = (Index) lfirsti(best_path->path.parent->relids);
455 scan_node = make_tidscan(tlist,
460 if (best_path->unjoined_relids)
461 scan_node->needRescan = true;
463 copy_path_costsize(&scan_node->scan.plan, &best_path->path);
468 /*****************************************************************************
472 * A general note about join_references() processing in these routines:
473 * once we have changed a Var node to refer to a subplan output rather than
474 * the original relation, it is no longer equal() to an unmodified Var node
475 * for the same var. So, we cannot easily compare reference-adjusted qual
476 * clauses to clauses that have not been adjusted. Fortunately, that
477 * doesn't seem to be necessary; all the decisions are made before we do
478 * the reference adjustments.
480 * A cleaner solution would be to not call join_references() here at all,
481 * but leave it for setrefs.c to do at the end of plan tree construction.
482 * But that would make switch_outer() much more complicated, and some care
483 * would be needed to get setrefs.c to do the right thing with nestloop
484 * inner indexscan quals. So, we do subplan reference adjustment here for
485 * quals of join nodes (and *only* for quals of join nodes).
487 *****************************************************************************/
490 create_nestloop_node(NestPath *best_path,
501 if (IsA(inner_node, IndexScan))
505 * An index is being used to reduce the number of tuples scanned
506 * in the inner relation. If there are join clauses being used
507 * with the index, we must update their outer-rel var nodes to
508 * refer to the outer side of the join.
510 * We can also remove those join clauses from the list of clauses
511 * that have to be checked as qpquals at the join node, but only
512 * if there's just one indexscan in the inner path (otherwise,
513 * several different sets of clauses are being ORed together).
515 * Note: if the index is lossy, the same clauses may also be getting
516 * checked as qpquals in the indexscan. We can still remove them
517 * from the nestloop's qpquals, but we gotta update the outer-rel
518 * vars in the indexscan's qpquals too.
520 * Note: we can safely do set_difference() against my clauses and
521 * join_references() because the innerscan is a primitive plan,
522 * and therefore has not itself done join_references renumbering
523 * of the vars in its quals.
525 IndexScan *innerscan = (IndexScan *) inner_node;
526 List *indxqualorig = innerscan->indxqualorig;
528 /* No work needed if indxqual refers only to its own relation... */
529 if (NumRelids((Node *) indxqualorig) > 1)
531 Index innerrel = innerscan->scan.scanrelid;
534 * Remove redundant tests from my clauses, if possible. Note
535 * we must compare against indxqualorig not the "fixed"
536 * indxqual (which has index attnos instead of relation
537 * attnos, and may have been commuted as well).
539 if (length(indxqualorig) == 1) /* single indexscan? */
540 joinclauses = set_difference(joinclauses,
541 lfirst(indxqualorig));
543 /* only refs to outer vars get changed in the inner indexqual */
544 innerscan->indxqualorig = join_references(indxqualorig,
548 innerscan->indxqual = join_references(innerscan->indxqual,
552 /* fix the inner qpqual too, if it has join clauses */
553 if (NumRelids((Node *) inner_node->qual) > 1)
554 inner_node->qual = join_references(inner_node->qual,
560 else if (IsA(inner_node, TidScan))
562 TidScan *innerscan = (TidScan *) inner_node;
564 innerscan->tideval = join_references(innerscan->tideval,
567 innerscan->scan.scanrelid);
569 else if (IsA_Join(inner_node))
573 * Materialize the inner join for speed reasons.
575 * XXX It is probably *not* always fastest to materialize an inner
576 * join --- how can we estimate whether this is a good thing to
579 inner_node = (Plan *) make_material(inner_tlist,
584 * Set quals to contain INNER/OUTER var references.
586 joinclauses = join_references(joinclauses,
590 otherclauses = join_references(otherclauses,
595 join_node = make_nestloop(tlist,
600 best_path->jointype);
602 copy_path_costsize(&join_node->join.plan, &best_path->path);
608 create_mergejoin_node(MergePath *best_path,
618 MergeJoin *join_node;
620 mergeclauses = get_actual_clauses(best_path->path_mergeclauses);
623 * Remove the mergeclauses from the list of join qual clauses, leaving
624 * the list of quals that must be checked as qpquals. Set those
625 * clauses to contain INNER/OUTER var references.
627 joinclauses = join_references(set_difference(joinclauses, mergeclauses),
633 * Fix the additional qpquals too.
635 otherclauses = join_references(otherclauses,
641 * Now set the references in the mergeclauses and rearrange them so
642 * that the outer variable is always on the left.
644 mergeclauses = switch_outer(join_references(mergeclauses,
650 * Create explicit sort nodes for the outer and inner join paths if
651 * necessary. The sort cost was already accounted for in the path.
653 if (best_path->outersortkeys)
654 outer_node = (Plan *)
655 make_sort_from_pathkeys(outer_tlist,
657 best_path->outersortkeys);
659 if (best_path->innersortkeys)
660 inner_node = (Plan *)
661 make_sort_from_pathkeys(inner_tlist,
663 best_path->innersortkeys);
666 * The executor requires the inner side of a mergejoin to support "mark"
667 * and "restore" operations. Not all plan types do, so we must be careful
668 * not to generate an invalid plan. If necessary, an invalid inner plan
669 * can be handled by inserting a Materialize node.
671 * Since the inner side must be ordered, and only Sorts and IndexScans can
672 * create order to begin with, you might think there's no problem --- but
673 * you'd be wrong. Nestloop and merge joins can *preserve* the order of
674 * their inputs, so they can be selected as the input of a mergejoin,
675 * and that won't work in the present executor.
677 * Doing this here is a bit of a kluge since the cost of the Materialize
678 * wasn't taken into account in our earlier decisions. But Materialize
679 * is hard to estimate a cost for, and the above consideration shows that
680 * this is a rare case anyway, so this seems an acceptable way to proceed.
682 * This check must agree with ExecMarkPos/ExecRestrPos in
683 * executor/execAmi.c!
685 switch (nodeTag(inner_node))
691 /* OK, these inner plans support mark/restore */
695 /* Ooops, need to materialize the inner plan */
696 inner_node = (Plan *) make_material(inner_tlist,
702 * Now we can build the mergejoin node.
704 join_node = make_mergejoin(tlist,
710 best_path->jpath.jointype);
712 copy_path_costsize(&join_node->join.plan, &best_path->jpath.path);
718 create_hashjoin_node(HashPath *best_path,
733 * NOTE: there will always be exactly one hashclause in the list
734 * best_path->path_hashclauses (cf. hash_inner_and_outer()). We
735 * represent it as a list anyway, for convenience with routines that
736 * want to work on lists of clauses.
738 hashclauses = get_actual_clauses(best_path->path_hashclauses);
741 * Remove the hashclauses from the list of join qual clauses, leaving
742 * the list of quals that must be checked as qpquals. Set those
743 * clauses to contain INNER/OUTER var references.
745 joinclauses = join_references(set_difference(joinclauses, hashclauses),
751 * Fix the additional qpquals too.
753 otherclauses = join_references(otherclauses,
759 * Now set the references in the hashclauses and rearrange them so
760 * that the outer variable is always on the left.
762 hashclauses = switch_outer(join_references(hashclauses,
767 /* Now the righthand op of the sole hashclause is the inner hash key. */
768 innerhashkey = (Node *) get_rightop(lfirst(hashclauses));
771 * Build the hash node and hash join node.
773 hash_node = make_hash(inner_tlist, innerhashkey, inner_node);
774 join_node = make_hashjoin(tlist,
780 best_path->jpath.jointype);
782 copy_path_costsize(&join_node->join.plan, &best_path->jpath.path);
788 /*****************************************************************************
790 * SUPPORTING ROUTINES
792 *****************************************************************************/
795 * fix_indxqual_references
796 * Adjust indexqual clauses to the form the executor's indexqual
799 * We have three tasks here:
800 * * Index keys must be represented by Var nodes with varattno set to the
801 * index's attribute number, not the attribute number in the original rel.
802 * * indxpath.c may have selected an index that is binary-compatible with
803 * the actual expression operator, but not exactly the same datatype.
804 * We must replace the expression's operator with the binary-compatible
805 * equivalent operator that the index will recognize.
806 * * If the index key is on the right, commute the clause to put it on the
807 * left. (Someday the executor might not need this, but for now it does.)
809 * This code used to be entirely bogus for multi-index scans. Now it keeps
810 * track of which index applies to each subgroup of index qual clauses...
812 * Returns a modified copy of the indexqual list --- the original is not
813 * changed. Note also that the copy shares no substructure with the
814 * original; this is needed in case there is a subplan in it (we need
815 * two separate copies of the subplan tree, or things will go awry).
819 fix_indxqual_references(List *indexquals, IndexPath *index_path)
821 List *fixed_quals = NIL;
822 int baserelid = lfirsti(index_path->path.parent->relids);
823 List *indexids = index_path->indexid;
826 foreach(i, indexquals)
828 List *indexqual = lfirst(i);
829 Oid indexid = lfirsti(indexids);
830 HeapTuple indexTuple;
834 /* Get the relam from the index's pg_class entry */
835 indexTuple = SearchSysCacheTuple(RELOID,
836 ObjectIdGetDatum(indexid),
838 if (!HeapTupleIsValid(indexTuple))
839 elog(ERROR, "fix_indxqual_references: index %u not found in pg_class",
841 relam = ((Form_pg_class) GETSTRUCT(indexTuple))->relam;
843 /* Need the index's pg_index entry for other stuff */
844 indexTuple = SearchSysCacheTuple(INDEXRELID,
845 ObjectIdGetDatum(indexid),
847 if (!HeapTupleIsValid(indexTuple))
848 elog(ERROR, "fix_indxqual_references: index %u not found in pg_index",
850 index = (Form_pg_index) GETSTRUCT(indexTuple);
852 fixed_quals = lappend(fixed_quals,
853 fix_indxqual_sublist(indexqual,
858 indexids = lnext(indexids);
864 * Fix the sublist of indexquals to be used in a particular scan.
866 * For each qual clause, commute if needed to put the indexkey operand on the
867 * left, and then fix its varattno. (We do not need to change the other side
868 * of the clause.) Also change the operator if necessary.
871 fix_indxqual_sublist(List *indexqual, int baserelid, Oid relam,
874 List *fixed_qual = NIL;
877 foreach(i, indexqual)
879 Expr *clause = (Expr *) lfirst(i);
888 if (!is_opclause((Node *) clause) ||
889 length(clause->args) != 2)
890 elog(ERROR, "fix_indxqual_sublist: indexqual clause is not binary opclause");
893 * Which side is the indexkey on?
895 * get_relattval sets flag&SEL_RIGHT if the indexkey is on the LEFT.
897 get_relattval((Node *) clause, baserelid,
898 &relid, &attno, &constval, &flag);
901 * Make a copy that will become the fixed clause.
903 * We used to try to do a shallow copy here, but that fails if there
904 * is a subplan in the arguments of the opclause. So just do a
907 newclause = (Expr *) copyObject((Node *) clause);
909 /* If the indexkey is on the right, commute the clause. */
910 if ((flag & SEL_RIGHT) == 0)
911 CommuteClause(newclause);
914 * Now, determine which index attribute this is, change the
915 * indexkey operand as needed, and get the index opclass.
917 lfirst(newclause->args) = fix_indxqual_operand(lfirst(newclause->args),
923 * Substitute the appropriate operator if the expression operator
924 * is merely binary-compatible with the index. This shouldn't
925 * fail, since indxpath.c found it before...
927 newopno = indexable_operator(newclause, opclass, relam, true);
928 if (newopno == InvalidOid)
929 elog(ERROR, "fix_indxqual_sublist: failed to find substitute op");
930 ((Oper *) newclause->oper)->opno = newopno;
932 fixed_qual = lappend(fixed_qual, newclause);
938 fix_indxqual_operand(Node *node, int baserelid, Form_pg_index index,
942 * Remove any binary-compatible relabeling of the indexkey
944 if (IsA(node, RelabelType))
945 node = ((RelabelType *) node)->arg;
948 * We represent index keys by Var nodes having the varno of the base
949 * table but varattno equal to the index's attribute number (index
950 * column position). This is a bit hokey ... would be cleaner to use
951 * a special-purpose node type that could not be mistaken for a regular
952 * Var. But it will do for now.
956 /* If it's a var, find which index key position it occupies */
957 if (((Var *) node)->varno == baserelid)
959 int varatt = ((Var *) node)->varattno;
962 for (pos = 0; pos < INDEX_MAX_KEYS; pos++)
964 if (index->indkey[pos] == varatt)
966 Node *newnode = copyObject(node);
968 ((Var *) newnode)->varattno = pos + 1;
969 /* return the correct opclass, too */
970 *opclass = index->indclass[pos];
977 * Oops, this Var isn't the indexkey!
979 elog(ERROR, "fix_indxqual_operand: var is not index attribute");
983 * Else, it must be a func expression matching a functional index.
984 * Since we currently only support single-column functional indexes,
985 * the returned varattno must be 1.
988 Assert(is_funcclause(node)); /* not a very thorough check, but easy */
990 /* indclass[0] is the only class of a functional index */
991 *opclass = index->indclass[0];
993 return (Node *) makeVar(baserelid, 1, exprType(node), -1, 0);
998 * Given a list of merge or hash joinclauses, rearrange the elements within
999 * the clauses so the outer join variable is on the left and the inner is
1000 * on the right. The original list is not touched; a modified list
1004 switch_outer(List *clauses)
1011 Expr *clause = (Expr *) lfirst(i);
1014 Assert(is_opclause((Node *) clause));
1015 op = get_rightop(clause);
1016 Assert(op && IsA(op, Var));
1017 if (var_is_outer(op))
1021 * Duplicate just enough of the structure to allow commuting
1022 * the clause without changing the original list. Could use
1023 * copyObject, but a complete deep copy is overkill.
1027 temp = make_clause(clause->opType, clause->oper,
1028 listCopy(clause->args));
1029 /* Commute it --- note this modifies the temp node in-place. */
1030 CommuteClause(temp);
1031 t_list = lappend(t_list, temp);
1034 t_list = lappend(t_list, clause);
1040 * Copy cost and size info from a Path node to the Plan node created from it.
1041 * The executor won't use this info, but it's needed by EXPLAIN.
1044 copy_path_costsize(Plan *dest, Path *src)
1048 dest->startup_cost = src->startup_cost;
1049 dest->total_cost = src->total_cost;
1050 dest->plan_rows = src->parent->rows;
1051 dest->plan_width = src->parent->width;
1055 dest->startup_cost = 0;
1056 dest->total_cost = 0;
1057 dest->plan_rows = 0;
1058 dest->plan_width = 0;
1063 * Copy cost and size info from a lower plan node to an inserted node.
1064 * This is not critical, since the decisions have already been made,
1065 * but it helps produce more reasonable-looking EXPLAIN output.
1066 * (Some callers alter the info after copying it.)
1069 copy_plan_costsize(Plan *dest, Plan *src)
1073 dest->startup_cost = src->startup_cost;
1074 dest->total_cost = src->total_cost;
1075 dest->plan_rows = src->plan_rows;
1076 dest->plan_width = src->plan_width;
1080 dest->startup_cost = 0;
1081 dest->total_cost = 0;
1082 dest->plan_rows = 0;
1083 dest->plan_width = 0;
1088 /*****************************************************************************
1091 *****************************************************************************/
1094 make_seqscan(List *qptlist,
1098 SeqScan *node = makeNode(SeqScan);
1099 Plan *plan = &node->plan;
1101 /* cost should be inserted by caller */
1102 plan->state = (EState *) NULL;
1103 plan->targetlist = qptlist;
1104 plan->qual = qpqual;
1105 plan->lefttree = NULL;
1106 plan->righttree = NULL;
1107 node->scanrelid = scanrelid;
1108 node->scanstate = (CommonScanState *) NULL;
1114 make_indexscan(List *qptlist,
1120 ScanDirection indexscandir)
1122 IndexScan *node = makeNode(IndexScan);
1123 Plan *plan = &node->scan.plan;
1125 /* cost should be inserted by caller */
1126 plan->state = (EState *) NULL;
1127 plan->targetlist = qptlist;
1128 plan->qual = qpqual;
1129 plan->lefttree = NULL;
1130 plan->righttree = NULL;
1131 node->scan.scanrelid = scanrelid;
1132 node->indxid = indxid;
1133 node->indxqual = indxqual;
1134 node->indxqualorig = indxqualorig;
1135 node->indxorderdir = indexscandir;
1136 node->scan.scanstate = (CommonScanState *) NULL;
1142 make_tidscan(List *qptlist,
1147 TidScan *node = makeNode(TidScan);
1148 Plan *plan = &node->scan.plan;
1150 /* cost should be inserted by caller */
1151 plan->state = (EState *) NULL;
1152 plan->targetlist = qptlist;
1153 plan->qual = qpqual;
1154 plan->lefttree = NULL;
1155 plan->righttree = NULL;
1156 node->scan.scanrelid = scanrelid;
1157 node->tideval = copyObject(tideval); /* XXX do we really need a
1159 node->needRescan = false;
1160 node->scan.scanstate = (CommonScanState *) NULL;
1167 make_nestloop(List *tlist,
1174 NestLoop *node = makeNode(NestLoop);
1175 Plan *plan = &node->join.plan;
1177 /* cost should be inserted by caller */
1178 plan->state = (EState *) NULL;
1179 plan->targetlist = tlist;
1180 plan->qual = otherclauses;
1181 plan->lefttree = lefttree;
1182 plan->righttree = righttree;
1183 node->join.jointype = jointype;
1184 node->join.joinqual = joinclauses;
1190 make_hashjoin(List *tlist,
1198 HashJoin *node = makeNode(HashJoin);
1199 Plan *plan = &node->join.plan;
1201 /* cost should be inserted by caller */
1202 plan->state = (EState *) NULL;
1203 plan->targetlist = tlist;
1204 plan->qual = otherclauses;
1205 plan->lefttree = lefttree;
1206 plan->righttree = righttree;
1207 node->hashclauses = hashclauses;
1208 node->join.jointype = jointype;
1209 node->join.joinqual = joinclauses;
1215 make_hash(List *tlist, Node *hashkey, Plan *lefttree)
1217 Hash *node = makeNode(Hash);
1218 Plan *plan = &node->plan;
1220 copy_plan_costsize(plan, lefttree);
1223 * For plausibility, make startup & total costs equal total cost of
1224 * input plan; this only affects EXPLAIN display not decisions.
1226 plan->startup_cost = plan->total_cost;
1227 plan->state = (EState *) NULL;
1228 plan->targetlist = tlist;
1230 plan->lefttree = lefttree;
1231 plan->righttree = NULL;
1232 node->hashkey = hashkey;
1238 make_mergejoin(List *tlist,
1246 MergeJoin *node = makeNode(MergeJoin);
1247 Plan *plan = &node->join.plan;
1249 /* cost should be inserted by caller */
1250 plan->state = (EState *) NULL;
1251 plan->targetlist = tlist;
1252 plan->qual = otherclauses;
1253 plan->lefttree = lefttree;
1254 plan->righttree = righttree;
1255 node->mergeclauses = mergeclauses;
1256 node->join.jointype = jointype;
1257 node->join.joinqual = joinclauses;
1263 * To use make_sort directly, you must already have marked the tlist
1264 * with reskey and reskeyop information. The keys had better be
1265 * non-redundant, too (ie, there had better be tlist items marked with
1266 * each key number from 1 to keycount), or the executor will get confused!
1269 make_sort(List *tlist, Plan *lefttree, int keycount)
1271 Sort *node = makeNode(Sort);
1272 Plan *plan = &node->plan;
1273 Path sort_path; /* dummy for result of cost_sort */
1275 copy_plan_costsize(plan, lefttree); /* only care about copying size */
1276 cost_sort(&sort_path, NIL, lefttree->plan_rows, lefttree->plan_width);
1277 plan->startup_cost = sort_path.startup_cost + lefttree->total_cost;
1278 plan->total_cost = sort_path.total_cost + lefttree->total_cost;
1279 plan->state = (EState *) NULL;
1280 plan->targetlist = tlist;
1282 plan->lefttree = lefttree;
1283 plan->righttree = NULL;
1284 node->keycount = keycount;
1290 * make_sort_from_pathkeys
1291 * Create sort plan to sort according to given pathkeys
1293 * 'tlist' is the target list of the input plan
1294 * 'lefttree' is the node which yields input tuples
1295 * 'pathkeys' is the list of pathkeys by which the result is to be sorted
1297 * We must convert the pathkey information into reskey and reskeyop fields
1298 * of resdom nodes in the sort plan's target list.
1301 make_sort_from_pathkeys(List *tlist, Plan *lefttree, List *pathkeys)
1305 int numsortkeys = 0;
1307 /* Create a new target list for the sort, with sort keys set. */
1308 sort_tlist = new_unsorted_tlist(tlist);
1310 foreach(i, pathkeys)
1312 List *keysublist = (List *) lfirst(i);
1313 PathKeyItem *pathkey = NULL;
1314 Resdom *resdom = NULL;
1318 * We can sort by any one of the sort key items listed in this
1319 * sublist. For now, we take the first one that corresponds to an
1320 * available Var in the sort_tlist.
1322 * XXX if we have a choice, is there any way of figuring out which
1323 * might be cheapest to execute? (For example, int4lt is likely
1324 * much cheaper to execute than numericlt, but both might appear
1325 * in the same pathkey sublist...) Not clear that we ever will
1326 * have a choice in practice, so it may not matter.
1328 foreach(j, keysublist)
1330 pathkey = lfirst(j);
1331 Assert(IsA(pathkey, PathKeyItem));
1332 resdom = tlist_member(pathkey->key, sort_tlist);
1337 elog(ERROR, "make_sort_from_pathkeys: cannot find tlist item to sort");
1340 * The resdom might be already marked as a sort key, if the
1341 * pathkeys contain duplicate entries. (This can happen in
1342 * scenarios where multiple mergejoinable clauses mention the same
1343 * var, for example.) In that case the current pathkey is
1344 * essentially a no-op, because only one value can be seen within
1345 * any subgroup where it would be consulted. We can ignore it.
1347 if (resdom->reskey == 0)
1349 /* OK, mark it as a sort key and set the sort operator regproc */
1350 resdom->reskey = ++numsortkeys;
1351 resdom->reskeyop = get_opcode(pathkey->sortop);
1355 Assert(numsortkeys > 0);
1357 return make_sort(sort_tlist, lefttree, numsortkeys);
1361 make_material(List *tlist, Plan *lefttree)
1363 Material *node = makeNode(Material);
1364 Plan *plan = &node->plan;
1366 copy_plan_costsize(plan, lefttree);
1369 * For plausibility, make startup & total costs equal total cost of
1370 * input plan; this only affects EXPLAIN display not decisions.
1372 * XXX shouldn't we charge some additional cost for materialization?
1374 plan->startup_cost = plan->total_cost;
1375 plan->state = (EState *) NULL;
1376 plan->targetlist = tlist;
1378 plan->lefttree = lefttree;
1379 plan->righttree = NULL;
1385 make_agg(List *tlist, List *qual, Plan *lefttree)
1387 Agg *node = makeNode(Agg);
1388 Plan *plan = &node->plan;
1390 copy_plan_costsize(plan, lefttree);
1393 * Charge one cpu_operator_cost per aggregate function per input
1396 plan->total_cost += cpu_operator_cost * plan->plan_rows *
1397 (length(pull_agg_clause((Node *) tlist)) +
1398 length(pull_agg_clause((Node *) qual)));
1401 * We will produce a single output tuple if the input is not a Group,
1402 * and a tuple per group otherwise. For now, estimate the number of
1403 * groups as 10% of the number of tuples --- bogus, but how to do
1404 * better? (Note we assume the input Group node is in "tuplePerGroup"
1405 * mode, so it didn't reduce its row count already.)
1407 if (IsA(lefttree, Group))
1408 plan->plan_rows *= 0.1;
1411 plan->plan_rows = 1;
1412 plan->startup_cost = plan->total_cost;
1415 plan->state = (EState *) NULL;
1417 plan->targetlist = tlist;
1418 plan->lefttree = lefttree;
1419 plan->righttree = (Plan *) NULL;
1425 make_group(List *tlist,
1428 AttrNumber *grpColIdx,
1431 Group *node = makeNode(Group);
1432 Plan *plan = &node->plan;
1434 copy_plan_costsize(plan, lefttree);
1437 * Charge one cpu_operator_cost per comparison per input tuple. We
1438 * assume all columns get compared at most of the tuples.
1440 plan->total_cost += cpu_operator_cost * plan->plan_rows * ngrp;
1443 * If tuplePerGroup (which is named exactly backwards) is true, we
1444 * will return all the input tuples, so the input node's row count is
1445 * OK. Otherwise, we'll return only one tuple from each group. For
1446 * now, estimate the number of groups as 10% of the number of tuples
1447 * --- bogus, but how to do better?
1450 plan->plan_rows *= 0.1;
1452 plan->state = (EState *) NULL;
1454 plan->targetlist = tlist;
1455 plan->lefttree = lefttree;
1456 plan->righttree = (Plan *) NULL;
1457 node->tuplePerGroup = tuplePerGroup;
1458 node->numCols = ngrp;
1459 node->grpColIdx = grpColIdx;
1465 * distinctList is a list of SortClauses, identifying the targetlist items
1466 * that should be considered by the Unique filter.
1470 make_unique(List *tlist, Plan *lefttree, List *distinctList)
1472 Unique *node = makeNode(Unique);
1473 Plan *plan = &node->plan;
1474 int numCols = length(distinctList);
1476 AttrNumber *uniqColIdx;
1479 copy_plan_costsize(plan, lefttree);
1482 * Charge one cpu_operator_cost per comparison per input tuple. We
1483 * assume all columns get compared at most of the tuples.
1485 plan->total_cost += cpu_operator_cost * plan->plan_rows * numCols;
1488 * As for Group, we make the unsupported assumption that there will be
1489 * 10% as many tuples out as in.
1491 plan->plan_rows *= 0.1;
1493 plan->state = (EState *) NULL;
1494 plan->targetlist = tlist;
1496 plan->lefttree = lefttree;
1497 plan->righttree = NULL;
1500 * convert SortClause list into array of attr indexes, as wanted by
1503 Assert(numCols > 0);
1504 uniqColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
1506 foreach(slitem, distinctList)
1508 SortClause *sortcl = (SortClause *) lfirst(slitem);
1509 TargetEntry *tle = get_sortgroupclause_tle(sortcl, tlist);
1511 uniqColIdx[keyno++] = tle->resdom->resno;
1514 node->numCols = numCols;
1515 node->uniqColIdx = uniqColIdx;
1521 make_result(List *tlist,
1522 Node *resconstantqual,
1525 Result *node = makeNode(Result);
1526 Plan *plan = &node->plan;
1529 tlist = generate_fjoin(tlist);
1531 copy_plan_costsize(plan, subplan);
1532 plan->state = (EState *) NULL;
1533 plan->targetlist = tlist;
1535 plan->lefttree = subplan;
1536 plan->righttree = NULL;
1537 node->resconstantqual = resconstantqual;
1538 node->resstate = NULL;
1545 generate_fjoin(List *tlist)
1548 List newTlist = NIL;
1549 List fjoinList = NIL;
1553 * Break the target list into elements with Iter nodes, and those
1556 foreach(tlistP, tlist)
1560 tlistElem = lfirst(tlistP);
1561 if (IsA(lsecond(tlistElem), Iter))
1564 fjoinList = lappend(fjoinList, tlistElem);
1567 newTlist = lappend(newTlist, tlistElem);
1571 * if we have an Iter node then we need to flatten.
1578 DatumPtr results = (DatumPtr) palloc(nIters * sizeof(Datum));
1579 BoolPtr alwaysDone = (BoolPtr) palloc(nIters * sizeof(bool));
1581 inner = lfirst(fjoinList);
1582 fjoinList = lnext(fjoinList);
1583 fjoinNode = (Fjoin) MakeFjoin(false,
1588 tempList = lcons(fjoinNode, fjoinList);
1589 newTlist = lappend(newTlist, tempList);
1592 return tlist; /* do nothing for now - ay 10/94 */