1 /*-------------------------------------------------------------------------
4 * Target list, qualification, joininfo initialization routines
6 * Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.36 1999/08/10 03:00:14 tgl Exp $
12 *-------------------------------------------------------------------------
14 #include <sys/types.h>
17 #include "catalog/pg_type.h"
18 #include "nodes/makefuncs.h"
19 #include "optimizer/clauses.h"
20 #include "optimizer/cost.h"
21 #include "optimizer/joininfo.h"
22 #include "optimizer/pathnode.h"
23 #include "optimizer/planmain.h"
24 #include "optimizer/tlist.h"
25 #include "optimizer/var.h"
26 #include "utils/lsyscache.h"
29 static void add_restrict_and_join_to_rel(Query *root, Node *clause);
30 static void add_join_info_to_rels(Query *root, RestrictInfo *restrictinfo,
32 static void add_vars_to_targetlist(Query *root, List *vars);
34 static MergeOrder *mergejoinop(Expr *clause);
35 static Oid hashjoinop(Expr *clause);
38 /*****************************************************************************
42 *****************************************************************************/
46 * Creates rel nodes for every relation mentioned in the target list
47 * 'tlist' (if a node hasn't already been created) and adds them to
48 * *query_relation_list*. Creates targetlist entries for each member of
49 * 'tlist' and adds them to the tlist field of the appropriate rel node.
52 make_var_only_tlist(Query *root, List *tlist)
54 List *tlist_vars = pull_var_clause((Node *) tlist);
56 add_vars_to_targetlist(root, tlist_vars);
61 * add_vars_to_targetlist
62 * For each variable appearing in the list, add it to the relation's
63 * targetlist if not already present. Rel nodes will also be created
64 * if not already present.
67 add_vars_to_targetlist(Query *root, List *vars)
73 Var *var = (Var *) lfirst(temp);
74 RelOptInfo *rel = get_base_rel(root, var->varno);
76 add_var_to_tlist(rel, var);
81 * add_missing_vars_to_tlist
82 * If we have range variable(s) in the FROM clause that does not appear
83 * in the target list nor qualifications, we add it to the base relation
84 * list. For instance, "select f.x from foo f, foo f2" is a join of f and
85 * f2. Note that if we have "select foo.x from foo f", it also gets turned
89 add_missing_vars_to_tlist(Query *root, List *tlist)
94 foreach(l, root->rtable)
96 RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
99 relids = lconsi(varno, NIL);
100 if (rte->inFromCl && !rel_member(relids, root->base_rel_list))
105 /* add it to base_rel_list */
106 rel = get_base_rel(root, varno);
107 /* give it a dummy tlist entry for its OID */
108 var = makeVar(varno, ObjectIdAttributeNumber,
109 OIDOID, -1, 0, varno, ObjectIdAttributeNumber);
110 add_var_to_tlist(rel, var);
117 /*****************************************************************************
121 *****************************************************************************/
126 * add_restrict_and_join_to_rels-
127 * Initializes RestrictInfo and JoinInfo fields of relation entries for all
128 * relations appearing within clauses. Creates new relation entries if
129 * necessary, adding them to *query_relation_list*.
131 * 'clauses': the list of clauses in the cnfify'd query qualification.
134 add_restrict_and_join_to_rels(Query *root, List *clauses)
138 foreach(clause, clauses)
139 add_restrict_and_join_to_rel(root, (Node*) lfirst(clause));
143 * add_restrict_and_join_to_rel-
144 * Add clause information to either the 'RestrictInfo' or 'JoinInfo' field
145 * of a relation entry (depending on whether or not the clause is a join)
146 * by creating a new RestrictInfo node and setting appropriate fields
150 add_restrict_and_join_to_rel(Query *root, Node *clause)
152 RestrictInfo *restrictinfo = makeNode(RestrictInfo);
156 restrictinfo->clause = (Expr *) clause;
157 restrictinfo->indexids = NIL;
158 restrictinfo->mergejoinorder = (MergeOrder *) NULL;
159 restrictinfo->hashjoinoperator = (Oid) 0;
162 * The selectivity of the clause must be computed regardless of
163 * whether it's a restriction or a join clause
165 restrictinfo->selectivity = compute_clause_selec(root, clause);
168 * Retrieve all relids and vars contained within the clause.
170 clause_get_relids_vars(clause, &relids, &vars);
172 if (length(relids) == 1)
175 * There is only one relation participating in 'clause', so
176 * 'clause' must be a restriction clause for that relation.
178 RelOptInfo *rel = get_base_rel(root, lfirsti(relids));
180 rel->restrictinfo = lcons(restrictinfo, rel->restrictinfo);
185 * 'clause' is a join clause, since there is more than one atom in
186 * the relid list. Add it to the join lists of all the relevant
187 * relations. (If, perchance, 'clause' contains NO vars, then
188 * nothing will happen...)
190 add_join_info_to_rels(root, restrictinfo, relids);
191 /* we are going to be doing a join, so add vars to targetlists */
192 add_vars_to_targetlist(root, vars);
197 * add_join_info_to_rels
198 * For every relation participating in a join clause, add 'restrictinfo' to
199 * the appropriate joininfo node (creating a new one and adding it to the
200 * appropriate rel node if necessary).
202 * 'restrictinfo' describes the join clause
203 * 'join_relids' is the list of relations participating in the join clause
206 add_join_info_to_rels(Query *root, RestrictInfo *restrictinfo,
211 /* For every relid, find the joininfo, and add the proper join entries */
212 foreach(join_relid, join_relids)
215 Relids unjoined_relids = NIL;
218 /* Get the relids not equal to the current relid */
219 foreach(rel, join_relids)
221 if (lfirsti(rel) != lfirsti(join_relid))
222 unjoined_relids = lappendi(unjoined_relids, lfirsti(rel));
226 * Find or make the joininfo node for this combination of rels
228 joininfo = find_joininfo_node(get_base_rel(root, lfirsti(join_relid)),
232 * And add the restrictinfo node to it. NOTE that each joininfo
233 * gets its own copy of the restrictinfo node! (Is this really
234 * necessary? Possibly ... later parts of the optimizer destructively
235 * modify restrict/join clauses...)
237 joininfo->jinfo_restrictinfo = lcons(copyObject((void *) restrictinfo),
238 joininfo->jinfo_restrictinfo);
242 /*****************************************************************************
246 *****************************************************************************/
249 * set_joininfo_mergeable_hashable
250 * Set the MergeJoinable or HashJoinable field for every joininfo node
251 * (within a rel node) and the mergejoinorder or hashjoinop field for
252 * each restrictinfo node (within a joininfo node) for all relations in a
258 set_joininfo_mergeable_hashable(List *rel_list)
264 RelOptInfo *rel = (RelOptInfo *) lfirst(x);
267 foreach(y, rel->joininfo)
269 JoinInfo *joininfo = (JoinInfo *) lfirst(y);
272 foreach(z, joininfo->jinfo_restrictinfo)
274 RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(z);
275 Expr *clause = restrictinfo->clause;
277 if (is_joinable((Node *) clause))
279 if (_enable_mergejoin_)
281 MergeOrder *sortop = mergejoinop(clause);
284 restrictinfo->mergejoinorder = sortop;
285 joininfo->mergejoinable = true;
289 if (_enable_hashjoin_)
291 Oid hashop = hashjoinop(clause);
294 restrictinfo->hashjoinoperator = hashop;
295 joininfo->hashjoinable = true;
306 * Returns a MergeOrder node for 'clause' iff 'clause' is mergejoinable,
307 * i.e., both operands are single vars and the operator is
308 * a mergejoinable operator.
311 mergejoinop(Expr *clause)
320 if (!is_opclause((Node *) clause))
323 left = get_leftop(clause);
324 right = get_rightop(clause);
326 /* caution: is_opclause accepts more than I do, so check it */
328 return NULL; /* unary opclauses need not apply */
329 if (!IsA(left, Var) || !IsA(right, Var))
332 opno = ((Oper *) clause->oper)->opno;
334 sortable = op_mergejoinable(opno,
342 MergeOrder *morder = makeNode(MergeOrder);
344 morder->join_operator = opno;
345 morder->left_operator = leftOp;
346 morder->right_operator = rightOp;
347 morder->left_type = left->vartype;
348 morder->right_type = right->vartype;
357 * Returns the hashjoin operator iff 'clause' is hashjoinable,
358 * i.e., both operands are single vars and the operator is
359 * a hashjoinable operator.
362 hashjoinop(Expr *clause)
367 if (!is_opclause((Node *) clause))
370 left = get_leftop(clause);
371 right = get_rightop(clause);
373 /* caution: is_opclause accepts more than I do, so check it */
375 return InvalidOid; /* unary opclauses need not apply */
376 if (!IsA(left, Var) || !IsA(right, Var))
379 return op_hashjoinable(((Oper *) clause->oper)->opno,