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.42 2000/01/22 23:50:16 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);
33 static void set_restrictinfo_joininfo(RestrictInfo *restrictinfo);
34 static void check_mergejoinable(RestrictInfo *restrictinfo);
35 static void check_hashjoinable(RestrictInfo *restrictinfo);
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, false);
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_rels_to_query
83 * If we have a range variable in the FROM clause that does not appear
84 * in the target list nor qualifications, we must add it to the base
85 * relation list so that it will be joined. For instance, "select f.x
86 * from foo f, foo f2" is a join of f and f2. Note that if we have
87 * "select foo.x from foo f", it also gets turned into a join (between
88 * foo as foo and foo as f).
90 * To avoid putting useless entries into the per-relation targetlists,
91 * this should only be called after all the variables in the targetlist
92 * and quals have been processed by the routines above.
95 add_missing_rels_to_query(Query *root)
100 foreach(l, root->rtable)
102 RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
106 RelOptInfo *rel = get_base_rel(root, varno);
108 /* If the rel isn't otherwise referenced, give it a dummy
109 * targetlist consisting of its own OID.
111 if (rel->targetlist == NIL)
113 Var *var = makeVar(varno, ObjectIdAttributeNumber,
115 add_var_to_tlist(rel, var);
122 /*****************************************************************************
126 *****************************************************************************/
131 * add_restrict_and_join_to_rels
132 * Fill RestrictInfo and JoinInfo lists of relation entries for all
133 * relations appearing within clauses. Creates new relation entries if
134 * necessary, adding them to *query_relation_list*.
136 * 'clauses': the list of clauses in the cnfify'd query qualification.
139 add_restrict_and_join_to_rels(Query *root, List *clauses)
143 foreach(clause, clauses)
144 add_restrict_and_join_to_rel(root, (Node*) lfirst(clause));
148 * add_restrict_and_join_to_rel
149 * Add clause information to either the 'RestrictInfo' or 'JoinInfo' field
150 * (depending on whether the clause is a join) of each base relation
151 * mentioned in the clause. A RestrictInfo node is created and added to
152 * the appropriate list for each rel.
155 add_restrict_and_join_to_rel(Query *root, Node *clause)
157 RestrictInfo *restrictinfo = makeNode(RestrictInfo);
161 restrictinfo->clause = (Expr *) clause;
162 restrictinfo->subclauseindices = NIL;
163 restrictinfo->mergejoinoperator = InvalidOid;
164 restrictinfo->left_sortop = InvalidOid;
165 restrictinfo->right_sortop = InvalidOid;
166 restrictinfo->hashjoinoperator = InvalidOid;
169 * Retrieve all relids and vars contained within the clause.
171 clause_get_relids_vars(clause, &relids, &vars);
173 if (length(relids) == 1)
176 * There is only one relation participating in 'clause', so
177 * 'clause' must be a restriction clause for that relation.
179 RelOptInfo *rel = get_base_rel(root, lfirsti(relids));
181 rel->restrictinfo = lcons(restrictinfo, rel->restrictinfo);
186 * 'clause' is a join clause, since there is more than one atom in
187 * the relid list. Set additional RestrictInfo fields for joining.
189 set_restrictinfo_joininfo(restrictinfo);
191 * Add clause to the join lists of all the relevant
192 * relations. (If, perchance, 'clause' contains NO vars, then
193 * nothing will happen...)
195 add_join_info_to_rels(root, restrictinfo, relids);
197 * Add vars used in the join clause to targetlists of member relations,
198 * so that they will be emitted by the plan nodes that scan those
199 * relations (else they won't be available at the join node!).
201 add_vars_to_targetlist(root, vars);
206 * add_join_info_to_rels
207 * For every relation participating in a join clause, add 'restrictinfo' to
208 * the appropriate joininfo list (creating a new list and adding it to the
209 * appropriate rel node if necessary).
211 * 'restrictinfo' describes the join clause
212 * 'join_relids' is the list of relations participating in the join clause
215 add_join_info_to_rels(Query *root, RestrictInfo *restrictinfo,
220 /* For every relid, find the joininfo, and add the proper join entries */
221 foreach(join_relid, join_relids)
223 int cur_relid = lfirsti(join_relid);
224 Relids unjoined_relids = NIL;
228 /* Get the relids not equal to the current relid */
229 foreach(otherrel, join_relids)
231 if (lfirsti(otherrel) != cur_relid)
232 unjoined_relids = lappendi(unjoined_relids, lfirsti(otherrel));
236 * Find or make the joininfo node for this combination of rels,
237 * and add the restrictinfo node to it.
239 joininfo = find_joininfo_node(get_base_rel(root, cur_relid),
241 joininfo->jinfo_restrictinfo = lcons(restrictinfo,
242 joininfo->jinfo_restrictinfo);
246 /*****************************************************************************
250 *****************************************************************************/
253 * set_restrictinfo_joininfo
254 * Examine a RestrictInfo that has been determined to be a join clause,
255 * and set the merge and hash info fields if it can be merge/hash joined.
258 set_restrictinfo_joininfo(RestrictInfo *restrictinfo)
260 if (enable_mergejoin)
261 check_mergejoinable(restrictinfo);
263 check_hashjoinable(restrictinfo);
267 * check_mergejoinable
268 * If the restrictinfo's clause is mergejoinable, set the mergejoin
269 * info fields in the restrictinfo.
271 * Currently, we support mergejoin for binary opclauses where
272 * both operands are simple Vars and the operator is a mergejoinable
273 * operator. (Note: since we are only examining clauses that were
274 * classified as joins, it is certain that the two Vars belong to
275 * different relations... if we accepted more general clause structures
276 * we might need to check that the two sides refer to different rels...)
279 check_mergejoinable(RestrictInfo *restrictinfo)
281 Expr *clause = restrictinfo->clause;
288 if (! is_opclause((Node *) clause))
291 left = get_leftop(clause);
292 right = get_rightop(clause);
294 /* caution: is_opclause accepts more than I do, so check it */
296 return; /* unary opclauses need not apply */
297 if (!IsA(left, Var) || !IsA(right, Var))
300 opno = ((Oper *) clause->oper)->opno;
302 if (op_mergejoinable(opno,
308 restrictinfo->mergejoinoperator = opno;
309 restrictinfo->left_sortop = leftOp;
310 restrictinfo->right_sortop = rightOp;
316 * If the restrictinfo's clause is hashjoinable, set the hashjoin
317 * info fields in the restrictinfo.
319 * Currently, we support hashjoin for binary opclauses where
320 * both operands are simple Vars and the operator is a hashjoinable
321 * operator. (Note: since we are only examining clauses that were
322 * classified as joins, it is certain that the two Vars belong to
323 * different relations... if we accepted more general clause structures
324 * we might need to check that the two sides refer to different rels...)
327 check_hashjoinable(RestrictInfo *restrictinfo)
329 Expr *clause = restrictinfo->clause;
334 if (! is_opclause((Node *) clause))
337 left = get_leftop(clause);
338 right = get_rightop(clause);
340 /* caution: is_opclause accepts more than I do, so check it */
342 return; /* unary opclauses need not apply */
343 if (!IsA(left, Var) || !IsA(right, Var))
346 opno = ((Oper *) clause->oper)->opno;
348 if (op_hashjoinable(opno,
352 restrictinfo->hashjoinoperator = opno;