summaryrefslogtreecommitdiff
path: root/src/backend/optimizer/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/util')
-rw-r--r--src/backend/optimizer/util/Makefile4
-rw-r--r--src/backend/optimizer/util/clauses.c100
-rw-r--r--src/backend/optimizer/util/indexnode.c34
-rw-r--r--src/backend/optimizer/util/pathnode.c29
-rw-r--r--src/backend/optimizer/util/plancat.c19
-rw-r--r--src/backend/optimizer/util/relnode.c31
-rw-r--r--src/backend/optimizer/util/restrictinfo.c10
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);
}
}