diff options
Diffstat (limited to 'src/backend/optimizer/util')
-rw-r--r-- | src/backend/optimizer/util/Makefile | 4 | ||||
-rw-r--r-- | src/backend/optimizer/util/clauses.c | 100 | ||||
-rw-r--r-- | src/backend/optimizer/util/indexnode.c | 34 | ||||
-rw-r--r-- | src/backend/optimizer/util/pathnode.c | 29 | ||||
-rw-r--r-- | src/backend/optimizer/util/plancat.c | 19 | ||||
-rw-r--r-- | src/backend/optimizer/util/relnode.c | 31 | ||||
-rw-r--r-- | src/backend/optimizer/util/restrictinfo.c | 10 |
7 files changed, 123 insertions, 104 deletions
diff --git a/src/backend/optimizer/util/Makefile b/src/backend/optimizer/util/Makefile index c616010337..471cfdf6b9 100644 --- a/src/backend/optimizer/util/Makefile +++ b/src/backend/optimizer/util/Makefile @@ -4,7 +4,7 @@ # Makefile for optimizer/util # # IDENTIFICATION -# $Header: /cvsroot/pgsql/src/backend/optimizer/util/Makefile,v 1.13 2000/08/31 16:10:14 petere Exp $ +# $Header: /cvsroot/pgsql/src/backend/optimizer/util/Makefile,v 1.14 2000/09/29 18:21:23 tgl Exp $ # #------------------------------------------------------------------------- @@ -12,7 +12,7 @@ subdir = src/backend/optimizer/util top_builddir = ../../../.. include $(top_builddir)/src/Makefile.global -OBJS = restrictinfo.o clauses.o indexnode.o plancat.o \ +OBJS = restrictinfo.o clauses.o plancat.o \ joininfo.o pathnode.o relnode.o tlist.o var.o all: SUBSYS.o diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 9f371ff739..06c67daebf 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.75 2000/09/25 18:14:55 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.76 2000/09/29 18:21:23 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -119,9 +119,9 @@ make_opclause(Oper *op, Var *leftop, Var *rightop) expr->opType = OP_EXPR; expr->oper = (Node *) op; if (rightop) - expr->args = lcons(leftop, lcons(rightop, NIL)); + expr->args = makeList2(leftop, rightop); else - expr->args = lcons(leftop, NIL); + expr->args = makeList1(leftop); return expr; } @@ -264,7 +264,7 @@ make_notclause(Expr *notclause) expr->typeOid = BOOLOID; expr->opType = NOT_EXPR; expr->oper = NULL; - expr->args = lcons(notclause, NIL); + expr->args = makeList1(notclause); return expr; } @@ -303,7 +303,6 @@ and_clause(Node *clause) * make_andclause * * Create an 'and' clause given its arguments in a list. - * */ Expr * make_andclause(List *andclauses) @@ -318,6 +317,23 @@ make_andclause(List *andclauses) } /* + * make_and_qual + * + * Variant of make_andclause for ANDing two qual conditions together. + * Qual conditions have the property that a NULL nodetree is interpreted + * as 'true'. + */ +Node * +make_and_qual(Node *qual1, Node *qual2) +{ + if (qual1 == NULL) + return qual2; + if (qual2 == NULL) + return qual1; + return (Node *) make_andclause(makeList2(qual1, qual2)); +} + +/* * Sometimes (such as in the result of canonicalize_qual or the input of * ExecQual), we use lists of expression nodes with implicit AND semantics. * @@ -356,7 +372,7 @@ make_ands_implicit(Expr *clause) DatumGetBool(((Const *) clause)->constvalue)) return NIL; /* constant TRUE input -> NIL list */ else - return lcons(clause, NIL); + return makeList1(clause); } @@ -676,49 +692,32 @@ is_pseudo_constant_clause(Node *clause) return false; } -/*---------- +/* * pull_constant_clauses * Scan through a list of qualifications and separate "constant" quals * from those that are not. * - * The input qual list is divided into three parts: - * * The function's return value is a list of all those quals that contain - * variable(s) of the current query level. (These quals will become - * restrict and join quals.) - * * *noncachableQual receives a list of quals that have no Vars, yet - * cannot be treated as constants because they contain noncachable - * function calls. (Example: WHERE random() < 0.5) - * * *constantQual receives a list of the remaining quals, which can be - * treated as constants for any one scan of the current query level. - * (They are really only pseudo-constant, since they may contain - * Params or outer-level Vars.) - *---------- + * Returns a list of the pseudo-constant clauses in constantQual and the + * remaining quals as the return value. */ List * -pull_constant_clauses(List *quals, - List **noncachableQual, - List **constantQual) +pull_constant_clauses(List *quals, List **constantQual) { - List *q; - List *normqual = NIL; - List *noncachequal = NIL; List *constqual = NIL; + List *restqual = NIL; + List *q; foreach(q, quals) { - Node *qual = (Node *) lfirst(q); + Node *qual = (Node *) lfirst(q); - if (contain_var_clause(qual)) - normqual = lappend(normqual, qual); - else if (contain_noncachable_functions(qual)) - noncachequal = lappend(noncachequal, qual); - else + if (is_pseudo_constant_clause(qual)) constqual = lappend(constqual, qual); + else + restqual = lappend(restqual, qual); } - - *noncachableQual = noncachequal; *constantQual = constqual; - return normqual; + return restqual; } @@ -1636,9 +1635,9 @@ simplify_op_or_func(Expr *expr, List *args) * will have List structure at the top level, and it handles TargetEntry nodes * so that a scan of a target list can be handled without additional code. * (But only the "expr" part of a TargetEntry is examined, unless the walker - * chooses to process TargetEntry nodes specially.) Also, RangeTblRef and - * JoinExpr nodes are handled, so that qual expressions in a jointree can be - * processed without additional code. + * chooses to process TargetEntry nodes specially.) Also, RangeTblRef, + * FromExpr, and JoinExpr nodes are handled, so that qual expressions in a + * jointree can be processed without additional code. * * expression_tree_walker will handle SubLink and SubPlan nodes by recursing * normally into the "lefthand" arguments (which belong to the outer plan). @@ -1801,6 +1800,16 @@ expression_tree_walker(Node *node, break; case T_TargetEntry: return walker(((TargetEntry *) node)->expr, context); + case T_FromExpr: + { + FromExpr *from = (FromExpr *) node; + + if (walker(from->fromlist, context)) + return true; + if (walker(from->quals, context)) + return true; + } + break; case T_JoinExpr: { JoinExpr *join = (JoinExpr *) node; @@ -1844,14 +1853,12 @@ query_tree_walker(Query *query, if (walker((Node *) query->targetList, context)) return true; - if (walker(query->qual, context)) + if (walker((Node *) query->jointree, context)) return true; if (walker(query->havingQual, context)) return true; - if (walker((Node *) query->jointree, context)) - return true; /* - * XXX for subselect-in-FROM, may need to examine rtable as well + * XXX for subselect-in-FROM, may need to examine rtable as well? */ return false; } @@ -2126,6 +2133,17 @@ expression_tree_mutator(Node *node, return (Node *) newnode; } break; + case T_FromExpr: + { + FromExpr *from = (FromExpr *) node; + FromExpr *newnode; + + FLATCOPY(newnode, from, FromExpr); + MUTATE(newnode->fromlist, from->fromlist, List *); + MUTATE(newnode->quals, from->quals, Node *); + return (Node *) newnode; + } + break; case T_JoinExpr: { JoinExpr *join = (JoinExpr *) node; diff --git a/src/backend/optimizer/util/indexnode.c b/src/backend/optimizer/util/indexnode.c deleted file mode 100644 index e8d97aae7c..0000000000 --- a/src/backend/optimizer/util/indexnode.c +++ /dev/null @@ -1,34 +0,0 @@ -/*------------------------------------------------------------------------- - * - * indexnode.c - * Routines to find all indices on a relation - * - * Portions Copyright (c) 1996-2000, PostgreSQL, Inc - * Portions Copyright (c) 1994, Regents of the University of California - * - * - * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/Attic/indexnode.c,v 1.22 2000/01/26 05:56:40 momjian Exp $ - * - *------------------------------------------------------------------------- - */ -#include "postgres.h" - -#include "optimizer/pathnode.h" -#include "optimizer/plancat.h" - - -/* - * find_relation_indices - * Returns a list of index nodes containing appropriate information for - * each (secondary) index defined on a relation. - * - */ -List * -find_relation_indices(Query *root, RelOptInfo *rel) -{ - if (rel->indexed) - return find_secondary_indexes(root, lfirsti(rel->relids)); - else - return NIL; -} diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index fc73bb2b66..737b4db2d3 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.65 2000/09/12 21:06:58 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.66 2000/09/29 18:21:23 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -16,6 +16,7 @@ #include "postgres.h" +#include "nodes/plannodes.h" #include "optimizer/cost.h" #include "optimizer/pathnode.h" #include "optimizer/paths.h" @@ -272,7 +273,6 @@ add_path(RelOptInfo *parent_rel, Path *new_path) * create_seqscan_path * Creates a path corresponding to a sequential scan, returning the * pathnode. - * */ Path * create_seqscan_path(RelOptInfo *rel) @@ -343,8 +343,8 @@ create_index_path(Query *root, * We are making a pathnode for a single-scan indexscan; therefore, * both indexid and indexqual should be single-element lists. */ - pathnode->indexid = lconsi(index->indexoid, NIL); - pathnode->indexqual = lcons(indexquals, NIL); + pathnode->indexid = makeListi1(index->indexoid); + pathnode->indexqual = makeList1(indexquals); pathnode->indexscandir = indexscandir; @@ -391,6 +391,27 @@ create_tidscan_path(RelOptInfo *rel, List *tideval) } /* + * create_subqueryscan_path + * Creates a path corresponding to a sequential scan of a subquery, + * returning the pathnode. + */ +Path * +create_subqueryscan_path(RelOptInfo *rel) +{ + Path *pathnode = makeNode(Path); + + pathnode->pathtype = T_SubqueryScan; + pathnode->parent = rel; + pathnode->pathkeys = NIL; /* for now, assume unordered result */ + + /* just copy the subplan's cost estimates */ + pathnode->startup_cost = rel->subplan->startup_cost; + pathnode->total_cost = rel->subplan->total_cost; + + return pathnode; +} + +/* * create_nestloop_path * Creates a pathnode corresponding to a nestloop join between two * relations. diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 750a463122..0d32e82ed9 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.60 2000/07/27 23:16:04 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.61 2000/09/29 18:21:23 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -25,7 +25,6 @@ #include "catalog/pg_inherits.h" #include "catalog/pg_index.h" #include "optimizer/plancat.h" -#include "parser/parsetree.h" #include "utils/builtins.h" #include "utils/fmgroids.h" #include "utils/relcache.h" @@ -37,16 +36,15 @@ /* * relation_info - * Retrieves catalog information for a given relation. - * Given the rangetable index of the relation, return the following info: + * Given the Oid of the relation, return the following info: * whether the relation has secondary indices * number of pages * number of tuples */ void -relation_info(Query *root, Index relid, +relation_info(Oid relationObjectId, bool *hasindex, long *pages, double *tuples) { - Oid relationObjectId = getrelid(relid, root->rtable); HeapTuple relationTuple; Form_pg_class relation; @@ -69,19 +67,18 @@ relation_info(Query *root, Index relid, /* * find_secondary_indexes * Creates a list of IndexOptInfo nodes containing information for each - * secondary index defined on the given relation. + * secondary index defined on the specified relation. * - * 'relid' is the RT index of the relation for which indices are being located + * 'relationObjectId' is the OID of the relation for which indices are wanted * * Returns a list of new IndexOptInfo nodes. */ List * -find_secondary_indexes(Query *root, Index relid) +find_secondary_indexes(Oid relationObjectId) { List *indexinfos = NIL; List *indexoidlist, *indexoidscan; - Oid indrelid = getrelid(relid, root->rtable); Relation relation; /* @@ -89,12 +86,12 @@ find_secondary_indexes(Query *root, Index relid) * a cached list of OID indexes for each relation. So, get that list * and then use the syscache to obtain pg_index entries. */ - relation = heap_open(indrelid, AccessShareLock); + relation = heap_open(relationObjectId, AccessShareLock); indexoidlist = RelationGetIndexList(relation); foreach(indexoidscan, indexoidlist) { - Oid indexoid = lfirsti(indexoidscan); + Oid indexoid = lfirsti(indexoidscan); HeapTuple indexTuple; Form_pg_index index; IndexOptInfo *info; diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c index 87e87597d1..86258b0f64 100644 --- a/src/backend/optimizer/util/relnode.c +++ b/src/backend/optimizer/util/relnode.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/relnode.c,v 1.28 2000/09/12 21:06:58 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/relnode.c,v 1.29 2000/09/29 18:21:23 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,6 +19,7 @@ #include "optimizer/pathnode.h" #include "optimizer/plancat.h" #include "optimizer/tlist.h" +#include "parser/parsetree.h" static List *new_join_tlist(List *tlist, int first_resdomno); @@ -44,6 +45,7 @@ get_base_rel(Query *root, int relid) { List *baserels; RelOptInfo *rel; + Oid relationObjectId; foreach(baserels, root->base_rel_list) { @@ -59,7 +61,7 @@ get_base_rel(Query *root, int relid) /* No existing RelOptInfo for this base rel, so make a new one */ rel = makeNode(RelOptInfo); - rel->relids = lconsi(relid, NIL); + rel->relids = makeListi1(relid); rel->rows = 0; rel->width = 0; rel->targetlist = NIL; @@ -67,18 +69,31 @@ get_base_rel(Query *root, int relid) rel->cheapest_startup_path = NULL; rel->cheapest_total_path = NULL; rel->pruneable = true; + rel->issubquery = false; rel->indexed = false; rel->pages = 0; rel->tuples = 0; + rel->subplan = NULL; rel->baserestrictinfo = NIL; rel->baserestrictcost = 0; rel->outerjoinset = NIL; rel->joininfo = NIL; rel->innerjoin = NIL; - /* Retrieve relation statistics from the system catalogs. */ - relation_info(root, relid, - &rel->indexed, &rel->pages, &rel->tuples); + /* Check rtable to see if it's a plain relation or a subquery */ + relationObjectId = getrelid(relid, root->rtable); + + if (relationObjectId != InvalidOid) + { + /* Plain relation --- retrieve statistics from the system catalogs */ + relation_info(relationObjectId, + &rel->indexed, &rel->pages, &rel->tuples); + } + else + { + /* subquery --- mark it as such for later processing */ + rel->issubquery = true; + } root->base_rel_list = lcons(rel, root->base_rel_list); @@ -174,9 +189,11 @@ get_join_rel(Query *root, joinrel->cheapest_startup_path = NULL; joinrel->cheapest_total_path = NULL; joinrel->pruneable = true; + joinrel->issubquery = false; joinrel->indexed = false; joinrel->pages = 0; joinrel->tuples = 0; + joinrel->subplan = NULL; joinrel->baserestrictinfo = NIL; joinrel->baserestrictcost = 0; joinrel->outerjoinset = NIL; @@ -310,7 +327,7 @@ build_joinrel_restrictlist(RelOptInfo *joinrel, * We must eliminate duplicates, since we will see the same clauses * arriving from both input relations... */ - return LispUnion(subbuild_joinrel_restrictlist(joinrel, + return set_union(subbuild_joinrel_restrictlist(joinrel, outer_rel->joininfo), subbuild_joinrel_restrictlist(joinrel, inner_rel->joininfo)); @@ -396,7 +413,7 @@ subbuild_joinrel_joinlist(RelOptInfo *joinrel, new_joininfo = find_joininfo_node(joinrel, new_unjoined_relids); new_joininfo->jinfo_restrictinfo = - LispUnion(new_joininfo->jinfo_restrictinfo, + set_union(new_joininfo->jinfo_restrictinfo, joininfo->jinfo_restrictinfo); } } diff --git a/src/backend/optimizer/util/restrictinfo.c b/src/backend/optimizer/util/restrictinfo.c index adbfd884c3..318c789c4a 100644 --- a/src/backend/optimizer/util/restrictinfo.c +++ b/src/backend/optimizer/util/restrictinfo.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.11 2000/09/12 21:06:58 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.12 2000/09/29 18:21:23 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -59,7 +59,7 @@ get_actual_clauses(List *restrictinfo_list) * get_actual_join_clauses * * Extract clauses from 'restrictinfo_list', separating those that - * came from JOIN/ON conditions from those that didn't. + * syntactically match the join level from those that were pushed down. */ void get_actual_join_clauses(List *restrictinfo_list, @@ -74,9 +74,9 @@ get_actual_join_clauses(List *restrictinfo_list, { RestrictInfo *clause = (RestrictInfo *) lfirst(temp); - if (clause->isjoinqual) - *joinquals = lappend(*joinquals, clause->clause); - else + if (clause->ispusheddown) *otherquals = lappend(*otherquals, clause->clause); + else + *joinquals = lappend(*joinquals, clause->clause); } } |