1 /*-------------------------------------------------------------------------
4 * Relation-node lookup/construction routines
6 * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $Header: /cvsroot/pgsql/src/backend/optimizer/util/relnode.c,v 1.35 2001/10/25 05:49:34 momjian Exp $
13 *-------------------------------------------------------------------------
17 #include "optimizer/cost.h"
18 #include "optimizer/joininfo.h"
19 #include "optimizer/pathnode.h"
20 #include "optimizer/paths.h"
21 #include "optimizer/plancat.h"
22 #include "optimizer/tlist.h"
23 #include "parser/parsetree.h"
26 static RelOptInfo *make_base_rel(Query *root, int relid);
27 static List *new_join_tlist(List *tlist, int first_resdomno);
28 static List *build_joinrel_restrictlist(Query *root,
30 RelOptInfo *outer_rel,
31 RelOptInfo *inner_rel);
32 static void build_joinrel_joinlist(RelOptInfo *joinrel,
33 RelOptInfo *outer_rel,
34 RelOptInfo *inner_rel);
35 static List *subbuild_joinrel_restrictlist(RelOptInfo *joinrel,
37 static void subbuild_joinrel_joinlist(RelOptInfo *joinrel,
43 * Returns relation entry corresponding to 'relid', creating a new one
44 * if necessary. This is for base relations.
47 build_base_rel(Query *root, int relid)
53 foreach(rels, root->base_rel_list)
55 rel = (RelOptInfo *) lfirst(rels);
57 /* length(rel->relids) == 1 for all members of base_rel_list */
58 if (lfirsti(rel->relids) == relid)
62 /* It should not exist as an "other" rel */
63 foreach(rels, root->other_rel_list)
65 rel = (RelOptInfo *) lfirst(rels);
67 if (lfirsti(rel->relids) == relid)
68 elog(ERROR, "build_base_rel: rel already exists as 'other' rel");
71 /* No existing RelOptInfo for this base rel, so make a new one */
72 rel = make_base_rel(root, relid);
74 /* and add it to the list */
75 root->base_rel_list = lcons(rel, root->base_rel_list);
82 * Returns relation entry corresponding to 'relid', creating a new one
83 * if necessary. This is for 'other' relations, which are just like
84 * base relations except that they live in a different list.
87 build_other_rel(Query *root, int relid)
93 foreach(rels, root->other_rel_list)
95 rel = (RelOptInfo *) lfirst(rels);
97 /* length(rel->relids) == 1 for all members of other_rel_list */
98 if (lfirsti(rel->relids) == relid)
102 /* It should not exist as a base rel */
103 foreach(rels, root->base_rel_list)
105 rel = (RelOptInfo *) lfirst(rels);
107 if (lfirsti(rel->relids) == relid)
108 elog(ERROR, "build_other_rel: rel already exists as base rel");
111 /* No existing RelOptInfo for this other rel, so make a new one */
112 rel = make_base_rel(root, relid);
114 /* and add it to the list */
115 root->other_rel_list = lcons(rel, root->other_rel_list);
122 * Construct a base-relation RelOptInfo for the specified rangetable index.
124 * Common code for build_base_rel and build_other_rel.
127 make_base_rel(Query *root, int relid)
129 RelOptInfo *rel = makeNode(RelOptInfo);
130 Oid relationObjectId;
132 rel->relids = makeListi1(relid);
135 rel->targetlist = NIL;
137 rel->cheapest_startup_path = NULL;
138 rel->cheapest_total_path = NULL;
139 rel->pruneable = true;
140 rel->issubquery = false;
141 rel->indexlist = NIL;
145 rel->baserestrictinfo = NIL;
146 rel->baserestrictcost = 0;
147 rel->outerjoinset = NIL;
149 rel->innerjoin = NIL;
151 /* Check rtable to see if it's a plain relation or a subquery */
152 relationObjectId = getrelid(relid, root->rtable);
154 if (relationObjectId != InvalidOid)
156 /* Plain relation --- retrieve statistics from the system catalogs */
159 get_relation_info(relationObjectId,
160 &indexed, &rel->pages, &rel->tuples);
162 rel->indexlist = find_secondary_indexes(relationObjectId);
166 /* subquery --- mark it as such for later processing */
167 rel->issubquery = true;
175 * Find a base or other relation entry, which must already exist
176 * (since we'd have no idea which list to add it to).
179 find_base_rel(Query *root, int relid)
184 foreach(rels, root->base_rel_list)
186 rel = (RelOptInfo *) lfirst(rels);
188 /* length(rel->relids) == 1 for all members of base_rel_list */
189 if (lfirsti(rel->relids) == relid)
193 foreach(rels, root->other_rel_list)
195 rel = (RelOptInfo *) lfirst(rels);
197 if (lfirsti(rel->relids) == relid)
201 elog(ERROR, "find_base_rel: no relation entry for relid %d", relid);
203 return NULL; /* keep compiler quiet */
208 * Returns relation entry corresponding to 'relids' (a list of RT indexes),
209 * or NULL if none exists. This is for join relations.
211 * Note: there is probably no good reason for this to be called from
212 * anywhere except build_join_rel, but keep it as a separate routine
216 find_join_rel(Query *root, Relids relids)
220 foreach(joinrels, root->join_rel_list)
222 RelOptInfo *rel = (RelOptInfo *) lfirst(joinrels);
224 if (sameseti(rel->relids, relids))
233 * Returns relation entry corresponding to the union of two given rels,
234 * creating a new relation entry if none already exists.
236 * 'outer_rel' and 'inner_rel' are relation nodes for the relations to be
238 * 'jointype': type of join (inner/outer)
239 * 'restrictlist_ptr': result variable. If not NULL, *restrictlist_ptr
240 * receives the list of RestrictInfo nodes that apply to this
241 * particular pair of joinable relations.
243 * restrictlist_ptr makes the routine's API a little grotty, but it saves
244 * duplicated calculation of the restrictlist...
247 build_join_rel(Query *root,
248 RelOptInfo *outer_rel,
249 RelOptInfo *inner_rel,
251 List **restrictlist_ptr)
256 List *new_outer_tlist;
257 List *new_inner_tlist;
259 /* We should never try to join two overlapping sets of rels. */
260 Assert(nonoverlap_setsi(outer_rel->relids, inner_rel->relids));
263 * See if we already have a joinrel for this set of base rels.
265 * nconc(listCopy(x), y) is an idiom for making a new list without
266 * changing either input list.
268 joinrelids = nconc(listCopy(outer_rel->relids), inner_rel->relids);
269 joinrel = find_join_rel(root, joinrelids);
274 * Yes, so we only need to figure the restrictlist for this
275 * particular pair of component relations.
277 if (restrictlist_ptr)
278 *restrictlist_ptr = build_joinrel_restrictlist(root,
288 joinrel = makeNode(RelOptInfo);
289 joinrel->relids = joinrelids;
292 joinrel->targetlist = NIL;
293 joinrel->pathlist = NIL;
294 joinrel->cheapest_startup_path = NULL;
295 joinrel->cheapest_total_path = NULL;
296 joinrel->pruneable = true;
297 joinrel->issubquery = false;
298 joinrel->indexlist = NIL;
301 joinrel->subplan = NULL;
302 joinrel->baserestrictinfo = NIL;
303 joinrel->baserestrictcost = 0;
304 joinrel->outerjoinset = NIL;
305 joinrel->joininfo = NIL;
306 joinrel->innerjoin = NIL;
309 * Create a new tlist by removing irrelevant elements from both tlists
310 * of the outer and inner join relations and then merging the results
313 * NOTE: the tlist order for a join rel will depend on which pair of
314 * outer and inner rels we first try to build it from. But the
315 * contents should be the same regardless.
317 * XXX someday: consider pruning vars from the join's targetlist if they
318 * are needed only to evaluate restriction clauses of this join, and
319 * will never be accessed at higher levels of the plantree.
321 new_outer_tlist = new_join_tlist(outer_rel->targetlist, 1);
322 new_inner_tlist = new_join_tlist(inner_rel->targetlist,
323 length(new_outer_tlist) + 1);
324 joinrel->targetlist = nconc(new_outer_tlist, new_inner_tlist);
327 * Construct restrict and join clause lists for the new joinrel. (The
328 * caller might or might not need the restrictlist, but I need it
329 * anyway for set_joinrel_size_estimates().)
331 restrictlist = build_joinrel_restrictlist(root,
335 if (restrictlist_ptr)
336 *restrictlist_ptr = restrictlist;
337 build_joinrel_joinlist(joinrel, outer_rel, inner_rel);
340 * Set estimates of the joinrel's size.
342 set_joinrel_size_estimates(root, joinrel, outer_rel, inner_rel,
343 jointype, restrictlist);
346 * Add the joinrel to the query's joinrel list.
348 root->join_rel_list = lcons(joinrel, root->join_rel_list);
355 * Builds a join relation's target list by keeping those elements that
356 * will be in the final target list and any other elements that are still
357 * needed for future joins. For a target list entry to still be needed
358 * for future joins, its 'joinlist' field must not be empty after removal
359 * of all relids in 'other_relids'.
361 * XXX the above comment refers to code that is long dead and gone;
362 * we don't keep track of joinlists for individual targetlist entries
363 * anymore. For now, all vars present in either input tlist will be
364 * emitted in the join's tlist.
366 * 'tlist' is the target list of one of the join relations
367 * 'first_resdomno' is the resdom number to use for the first created
370 * Returns the new target list.
373 new_join_tlist(List *tlist,
376 int resdomno = first_resdomno - 1;
382 TargetEntry *xtl = lfirst(i);
385 t_list = lappend(t_list,
386 create_tl_element(get_expr(xtl), resdomno));
393 * build_joinrel_restrictlist
394 * build_joinrel_joinlist
395 * These routines build lists of restriction and join clauses for a
396 * join relation from the joininfo lists of the relations it joins.
398 * These routines are separate because the restriction list must be
399 * built afresh for each pair of input sub-relations we consider, whereas
400 * the join lists need only be computed once for any join RelOptInfo.
401 * The join lists are fully determined by the set of rels making up the
402 * joinrel, so we should get the same results (up to ordering) from any
403 * candidate pair of sub-relations. But the restriction list is whatever
404 * is not handled in the sub-relations, so it depends on which
405 * sub-relations are considered.
407 * If a join clause from an input relation refers to base rels still not
408 * present in the joinrel, then it is still a join clause for the joinrel;
409 * we put it into an appropriate JoinInfo list for the joinrel. Otherwise,
410 * the clause is now a restrict clause for the joined relation, and we
411 * return it to the caller of build_joinrel_restrictlist() to be stored in
412 * join paths made from this pair of sub-relations. (It will not need to
413 * be considered further up the join tree.)
415 * When building a restriction list, we eliminate redundant clauses.
416 * We don't try to do that for join clause lists, since the join clauses
417 * aren't really doing anything, just waiting to become part of higher
418 * levels' restriction lists.
420 * 'joinrel' is a join relation node
421 * 'outer_rel' and 'inner_rel' are a pair of relations that can be joined
424 * build_joinrel_restrictlist() returns a list of relevant restrictinfos,
425 * whereas build_joinrel_joinlist() stores its results in the joinrel's
426 * joininfo lists. One or the other must accept each given clause!
428 * NB: Formerly, we made deep(!) copies of each input RestrictInfo to pass
429 * up to the join relation. I believe this is no longer necessary, because
430 * RestrictInfo nodes are no longer context-dependent. Instead, just include
431 * the original nodes in the lists made for the join relation.
434 build_joinrel_restrictlist(Query *root,
436 RelOptInfo *outer_rel,
437 RelOptInfo *inner_rel)
444 * Collect all the clauses that syntactically belong at this level.
446 rlist = nconc(subbuild_joinrel_restrictlist(joinrel,
447 outer_rel->joininfo),
448 subbuild_joinrel_restrictlist(joinrel,
449 inner_rel->joininfo));
452 * Eliminate duplicate and redundant clauses.
454 * We must eliminate duplicates, since we will see many of the same
455 * clauses arriving from both input relations. Also, if a clause is a
456 * mergejoinable clause, it's possible that it is redundant with
457 * previous clauses (see optimizer/README for discussion). We detect
458 * that case and omit the redundant clause from the result list.
460 * We can detect redundant mergejoinable clauses very cheaply by using
461 * their left and right pathkeys, which uniquely identify the sets of
462 * equijoined variables in question. All the members of a pathkey set
463 * that are in the left relation have already been forced to be equal;
464 * likewise for those in the right relation. So, we need to have only
465 * one clause that checks equality between any set member on the left
466 * and any member on the right; by transitivity, all the rest are then
471 RestrictInfo *rinfo = (RestrictInfo *) lfirst(item);
473 /* eliminate duplicates */
474 if (member(rinfo, result))
477 /* check for redundant merge clauses */
478 if (rinfo->mergejoinoperator != InvalidOid)
480 bool redundant = false;
483 cache_mergeclause_pathkeys(root, rinfo);
485 foreach(olditem, result)
487 RestrictInfo *oldrinfo = (RestrictInfo *) lfirst(olditem);
489 if (oldrinfo->mergejoinoperator != InvalidOid &&
490 rinfo->left_pathkey == oldrinfo->left_pathkey &&
491 rinfo->right_pathkey == oldrinfo->right_pathkey)
502 /* otherwise, add it to result list */
503 result = lappend(result, rinfo);
512 build_joinrel_joinlist(RelOptInfo *joinrel,
513 RelOptInfo *outer_rel,
514 RelOptInfo *inner_rel)
516 subbuild_joinrel_joinlist(joinrel, outer_rel->joininfo);
517 subbuild_joinrel_joinlist(joinrel, inner_rel->joininfo);
521 subbuild_joinrel_restrictlist(RelOptInfo *joinrel,
524 List *restrictlist = NIL;
527 foreach(xjoininfo, joininfo_list)
529 JoinInfo *joininfo = (JoinInfo *) lfirst(xjoininfo);
531 if (is_subseti(joininfo->unjoined_relids, joinrel->relids))
534 * Clauses in this JoinInfo list become restriction clauses
535 * for the joinrel, since they refer to no outside rels.
537 * We must copy the list to avoid disturbing the input relation,
538 * but we can use a shallow copy.
540 restrictlist = nconc(restrictlist,
541 listCopy(joininfo->jinfo_restrictinfo));
546 * These clauses are still join clauses at this level, so we
547 * ignore them in this routine.
556 subbuild_joinrel_joinlist(RelOptInfo *joinrel,
561 foreach(xjoininfo, joininfo_list)
563 JoinInfo *joininfo = (JoinInfo *) lfirst(xjoininfo);
564 Relids new_unjoined_relids;
566 new_unjoined_relids = set_differencei(joininfo->unjoined_relids,
568 if (new_unjoined_relids == NIL)
571 * Clauses in this JoinInfo list become restriction clauses
572 * for the joinrel, since they refer to no outside rels. So we
573 * can ignore them in this routine.
579 * These clauses are still join clauses at this level, so find
580 * or make the appropriate JoinInfo item for the joinrel, and
581 * add the clauses to it (eliminating duplicates).
583 JoinInfo *new_joininfo;
585 new_joininfo = find_joininfo_node(joinrel, new_unjoined_relids);
586 new_joininfo->jinfo_restrictinfo =
587 set_union(new_joininfo->jinfo_restrictinfo,
588 joininfo->jinfo_restrictinfo);