mirror of
https://github.com/postgres/postgres.git
synced 2025-08-27 07:42:10 +03:00
pgindent run over code.
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: geqo_eval.c,v 1.37 1999/05/17 00:25:34 tgl Exp $
|
||||
* $Id: geqo_eval.c,v 1.38 1999/05/25 16:09:15 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -56,7 +56,7 @@ static MemoryContext geqo_eval_context;
|
||||
|
||||
/*
|
||||
* geqo_eval_startup:
|
||||
* Must be called during geqo_main startup (before geqo_eval may be called)
|
||||
* Must be called during geqo_main startup (before geqo_eval may be called)
|
||||
*
|
||||
* The main thing we need to do here is prepare a private memory context for
|
||||
* allocation of temp storage used while constructing a path in geqo_eval().
|
||||
@@ -70,9 +70,10 @@ void
|
||||
geqo_eval_startup(void)
|
||||
{
|
||||
#define GEQO_PORTAL_NAME "<geqo workspace>"
|
||||
Portal geqo_portal = GetPortalByName(GEQO_PORTAL_NAME);
|
||||
Portal geqo_portal = GetPortalByName(GEQO_PORTAL_NAME);
|
||||
|
||||
if (!PortalIsValid(geqo_portal)) {
|
||||
if (!PortalIsValid(geqo_portal))
|
||||
{
|
||||
/* First time through (within current transaction, that is) */
|
||||
geqo_portal = CreatePortal(GEQO_PORTAL_NAME);
|
||||
Assert(PortalIsValid(geqo_portal));
|
||||
@@ -89,15 +90,18 @@ geqo_eval_startup(void)
|
||||
Cost
|
||||
geqo_eval(Query *root, Gene *tour, int num_gene)
|
||||
{
|
||||
MemoryContext oldcxt;
|
||||
RelOptInfo *joinrel;
|
||||
Cost fitness;
|
||||
List *savelist;
|
||||
MemoryContext oldcxt;
|
||||
RelOptInfo *joinrel;
|
||||
Cost fitness;
|
||||
List *savelist;
|
||||
|
||||
/* preserve root->join_rel_list, which gimme_tree changes */
|
||||
savelist = root->join_rel_list;
|
||||
|
||||
/* create a temporary allocation context for the path construction work */
|
||||
/*
|
||||
* create a temporary allocation context for the path construction
|
||||
* work
|
||||
*/
|
||||
oldcxt = MemoryContextSwitchTo(geqo_eval_context);
|
||||
StartPortalAllocMode(DefaultAllocMode, 0);
|
||||
|
||||
@@ -118,7 +122,7 @@ geqo_eval(Query *root, Gene *tour, int num_gene)
|
||||
}
|
||||
|
||||
/*
|
||||
* gimme_tree
|
||||
* gimme_tree
|
||||
* this program presumes that only LEFT-SIDED TREES are considered!
|
||||
*
|
||||
* 'old_rel' is the preceding join
|
||||
@@ -126,7 +130,7 @@ geqo_eval(Query *root, Gene *tour, int num_gene)
|
||||
* Returns a new join relation incorporating all joins in a left-sided tree.
|
||||
*/
|
||||
RelOptInfo *
|
||||
gimme_tree(Query *root, Gene *tour, int rel_count, int num_gene, RelOptInfo *old_rel)
|
||||
gimme_tree(Query *root, Gene *tour, int rel_count, int num_gene, RelOptInfo * old_rel)
|
||||
{
|
||||
RelOptInfo *inner_rel; /* current relation */
|
||||
int base_rel_index;
|
||||
@@ -139,7 +143,7 @@ gimme_tree(Query *root, Gene *tour, int rel_count, int num_gene, RelOptInfo *old
|
||||
/* tour[0] = 3; tour[1] = 1; tour[2] = 2 */
|
||||
base_rel_index = (int) tour[rel_count];
|
||||
|
||||
inner_rel = (RelOptInfo *) nth(base_rel_index-1, root->base_rel_list);
|
||||
inner_rel = (RelOptInfo *) nth(base_rel_index - 1, root->base_rel_list);
|
||||
|
||||
if (rel_count == 0)
|
||||
{ /* processing first join with
|
||||
@@ -151,15 +155,17 @@ gimme_tree(Query *root, Gene *tour, int rel_count, int num_gene, RelOptInfo *old
|
||||
{ /* tree main part */
|
||||
if (!(new_rels = make_rels_by_clause_joins(root, old_rel,
|
||||
old_rel->joininfo,
|
||||
inner_rel->relids)))
|
||||
inner_rel->relids)))
|
||||
{
|
||||
new_rels = make_rels_by_clauseless_joins(old_rel,
|
||||
lcons(inner_rel,NIL));
|
||||
/* we don't do bushy plans in geqo, do we? bjm 02/18/1999
|
||||
new_rels = append(new_rels,
|
||||
make_rels_by_clauseless_joins(old_rel,
|
||||
lcons(old_rel,NIL));
|
||||
*/
|
||||
lcons(inner_rel, NIL));
|
||||
|
||||
/*
|
||||
* we don't do bushy plans in geqo, do we? bjm 02/18/1999
|
||||
* new_rels = append(new_rels,
|
||||
* make_rels_by_clauseless_joins(old_rel,
|
||||
* lcons(old_rel,NIL));
|
||||
*/
|
||||
}
|
||||
|
||||
/* process new_rel->pathlist */
|
||||
@@ -202,5 +208,5 @@ gimme_tree(Query *root, Gene *tour, int rel_count, int num_gene, RelOptInfo *old
|
||||
}
|
||||
}
|
||||
|
||||
return old_rel; /* tree finished ... */
|
||||
return old_rel; /* tree finished ... */
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: geqo_main.c,v 1.15 1999/05/17 00:25:33 tgl Exp $
|
||||
* $Id: geqo_main.c,v 1.16 1999/05/25 16:09:16 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -77,24 +77,28 @@ geqo(Query *root)
|
||||
status_interval;
|
||||
Gene *best_tour;
|
||||
RelOptInfo *best_rel;
|
||||
|
||||
#if defined(ERX)
|
||||
Edge *edge_table; /* list of edges */
|
||||
int edge_failures = 0;
|
||||
float difference;
|
||||
|
||||
#endif
|
||||
#if defined(CX) || defined(PX) || defined(OX1) || defined(OX2)
|
||||
City *city_table; /* list of cities */
|
||||
|
||||
#endif
|
||||
#if defined(CX)
|
||||
int cycle_diffs = 0;
|
||||
int mutations = 0;
|
||||
|
||||
#endif
|
||||
|
||||
/* set tour size */
|
||||
number_of_rels = length(root->base_rel_list);
|
||||
|
||||
/* set GA parameters */
|
||||
geqo_params(number_of_rels); /* read "$PGDATA/pg_geqo" file */
|
||||
geqo_params(number_of_rels);/* read "$PGDATA/pg_geqo" file */
|
||||
pool_size = PoolSize;
|
||||
number_generations = Generations;
|
||||
status_interval = 10;
|
||||
|
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: geqo_misc.c,v 1.17 1999/02/13 23:16:09 momjian Exp $
|
||||
* $Id: geqo_misc.c,v 1.18 1999/05/25 16:09:17 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -261,7 +261,7 @@ geqo_print_path(Query *root, Path *path, int indent)
|
||||
}
|
||||
|
||||
void
|
||||
geqo_print_rel(Query *root, RelOptInfo *rel)
|
||||
geqo_print_rel(Query *root, RelOptInfo * rel)
|
||||
{
|
||||
List *l;
|
||||
|
||||
|
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: geqo_pool.c,v 1.11 1999/02/13 23:16:12 momjian Exp $
|
||||
* $Id: geqo_pool.c,v 1.12 1999/05/25 16:09:18 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -109,7 +109,7 @@ random_init_pool(Query *root, Pool *pool, int strt, int stp)
|
||||
* "geqo_recombination.c"
|
||||
* */
|
||||
|
||||
pool->data[i].worth = geqo_eval(root, chromo[i].string, pool->string_length); /* "from geqo_eval.c" */
|
||||
pool->data[i].worth = geqo_eval(root, chromo[i].string, pool->string_length); /* "from geqo_eval.c" */
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/geqo/Attic/minspantree.c,v 1.10 1999/02/13 23:16:13 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/geqo/Attic/minspantree.c,v 1.11 1999/05/25 16:09:19 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -41,7 +41,7 @@
|
||||
*/
|
||||
|
||||
void
|
||||
minspantree(Query *root, List *join_rels, RelOptInfo *garel)
|
||||
minspantree(Query *root, List *join_rels, RelOptInfo * garel)
|
||||
{
|
||||
int number_of_rels = length(root->base_rel_list);
|
||||
int number_of_joins = length(join_rels);
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/_deadcode/Attic/predmig.c,v 1.1 1999/02/18 19:58:53 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/_deadcode/Attic/predmig.c,v 1.2 1999/05/25 16:09:30 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -257,7 +257,7 @@ xfunc_llel_chains(Stream root, Stream bottom)
|
||||
*/
|
||||
Assert(xfunc_num_relids(pathstream) > xfunc_num_relids(tmpstream));
|
||||
progress = xfunc_prdmig_pullup(origstream, tmpstream,
|
||||
(JoinPath) get_pathptr(pathstream));
|
||||
(JoinPath) get_pathptr(pathstream));
|
||||
}
|
||||
if (get_downstream(tmpstream))
|
||||
pathstream = (Stream) xfunc_get_downjoin((Stream) get_downstream(tmpstream));
|
||||
@@ -269,7 +269,7 @@ xfunc_llel_chains(Stream root, Stream bottom)
|
||||
}
|
||||
|
||||
/*
|
||||
** xfunc_complete_stream
|
||||
** xfunc_complete_stream
|
||||
** Given a stream composed of join nodes only, make a copy containing the
|
||||
** join nodes along with the associated restriction nodes.
|
||||
*/
|
||||
@@ -313,7 +313,7 @@ xfunc_complete_stream(Stream stream)
|
||||
static bool
|
||||
xfunc_prdmig_pullup(Stream origstream, Stream pullme, JoinPath joinpath)
|
||||
{
|
||||
RestrictInfo restrictinfo = get_cinfo(pullme);
|
||||
RestrictInfo restrictinfo = get_cinfo(pullme);
|
||||
bool progress = false;
|
||||
Stream upjoin,
|
||||
orignode,
|
||||
@@ -347,10 +347,10 @@ xfunc_prdmig_pullup(Stream origstream, Stream pullme, JoinPath joinpath)
|
||||
else
|
||||
whichchild = INNER;
|
||||
restrictinfo = xfunc_pullup((Path) get_pathptr((Stream) get_downstream(upjoin)),
|
||||
(JoinPath) get_pathptr(upjoin),
|
||||
restrictinfo,
|
||||
whichchild,
|
||||
get_clausetype(orignode));
|
||||
(JoinPath) get_pathptr(upjoin),
|
||||
restrictinfo,
|
||||
whichchild,
|
||||
get_clausetype(orignode));
|
||||
set_pathptr(pullme, get_pathptr(upjoin));
|
||||
/* pullme has been moved into locrestrictinfo */
|
||||
set_clausetype(pullme, XFUNC_LOCPRD);
|
||||
@@ -390,7 +390,7 @@ xfunc_prdmig_pullup(Stream origstream, Stream pullme, JoinPath joinpath)
|
||||
}
|
||||
|
||||
/*
|
||||
** xfunc_form_groups
|
||||
** xfunc_form_groups
|
||||
** A group is a pair of stream nodes a,b such that a is constrained to
|
||||
** precede b (for instance if a and b are both joins), but rank(a) > rank(b).
|
||||
** In such a situation, Monma and Sidney prove that no clauses should end
|
||||
@@ -487,10 +487,10 @@ xfunc_form_groups(Query *queryInfo, Stream root, Stream bottom)
|
||||
}
|
||||
|
||||
|
||||
/* ------------------- UTILITY FUNCTIONS ------------------------- */
|
||||
/* ------------------- UTILITY FUNCTIONS ------------------------- */
|
||||
|
||||
/*
|
||||
** xfunc_free_stream
|
||||
** xfunc_free_stream
|
||||
** walk down a stream and pfree it
|
||||
*/
|
||||
static void
|
||||
@@ -525,7 +525,7 @@ xfunc_add_clauses(Stream current)
|
||||
foreach(temp, get_loc_restrictinfo((Path) get_pathptr(current)))
|
||||
{
|
||||
topnode = xfunc_streaminsert((RestrictInfo) lfirst(temp), topnode,
|
||||
XFUNC_LOCPRD);
|
||||
XFUNC_LOCPRD);
|
||||
}
|
||||
|
||||
/* and add in the join clauses */
|
||||
@@ -536,7 +536,7 @@ xfunc_add_clauses(Stream current)
|
||||
{
|
||||
if (!equal(get_clause((RestrictInfo) lfirst(temp)), primjoin))
|
||||
topnode = xfunc_streaminsert((RestrictInfo) lfirst(temp), topnode,
|
||||
XFUNC_JOINPRD);
|
||||
XFUNC_JOINPRD);
|
||||
}
|
||||
}
|
||||
return topnode;
|
||||
@@ -623,7 +623,7 @@ xfunc_num_relids(Stream node)
|
||||
}
|
||||
|
||||
/*
|
||||
** xfunc_get_downjoin
|
||||
** xfunc_get_downjoin
|
||||
** Given a stream node, find the next lowest node which points to a
|
||||
** join predicate or a scan node.
|
||||
*/
|
||||
@@ -642,7 +642,7 @@ xfunc_get_downjoin(Stream node)
|
||||
}
|
||||
|
||||
/*
|
||||
** xfunc_get_upjoin
|
||||
** xfunc_get_upjoin
|
||||
** same as above, but upwards.
|
||||
*/
|
||||
static StreamPtr
|
||||
@@ -660,7 +660,7 @@ xfunc_get_upjoin(Stream node)
|
||||
}
|
||||
|
||||
/*
|
||||
** xfunc_stream_qsort
|
||||
** xfunc_stream_qsort
|
||||
** Given a stream, sort by group rank the elements in the stream from the
|
||||
** node "bottom" up. DESTRUCTIVELY MODIFIES STREAM! Returns new root.
|
||||
*/
|
||||
|
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/_deadcode/Attic/xfunc.c,v 1.2 1999/05/10 00:45:14 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/_deadcode/Attic/xfunc.c,v 1.3 1999/05/25 16:09:31 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -49,7 +49,7 @@ static int xfunc_card_unreferenced(Query *queryInfo,
|
||||
*/
|
||||
|
||||
/*
|
||||
** xfunc_trypullup
|
||||
** xfunc_trypullup
|
||||
** Preliminary pullup of predicates, to allow for maximal pruning.
|
||||
** Given a relation, check each of its paths and see if you can
|
||||
** pullup clauses from its inner and outer.
|
||||
@@ -59,7 +59,7 @@ void
|
||||
xfunc_trypullup(RelOptInfo rel)
|
||||
{
|
||||
LispValue y; /* list ptr */
|
||||
RestrictInfo maxcinfo; /* The RestrictInfo to pull up, as
|
||||
RestrictInfo maxcinfo; /* The RestrictInfo to pull up, as
|
||||
* calculated by xfunc_shouldpull() */
|
||||
JoinPath curpath; /* current path in list */
|
||||
int progress; /* has progress been made this time
|
||||
@@ -81,7 +81,7 @@ xfunc_trypullup(RelOptInfo rel)
|
||||
{
|
||||
/* No, the following should NOT be '==' !! */
|
||||
if (clausetype = xfunc_shouldpull((Path) get_innerjoinpath(curpath),
|
||||
curpath, INNER, &maxcinfo))
|
||||
curpath, INNER, &maxcinfo))
|
||||
{
|
||||
|
||||
xfunc_pullup((Path) get_innerjoinpath(curpath),
|
||||
@@ -96,7 +96,7 @@ xfunc_trypullup(RelOptInfo rel)
|
||||
|
||||
/* No, the following should NOT be '==' !! */
|
||||
if (clausetype = xfunc_shouldpull((Path) get_outerjoinpath(curpath),
|
||||
curpath, OUTER, &maxcinfo))
|
||||
curpath, OUTER, &maxcinfo))
|
||||
{
|
||||
|
||||
xfunc_pullup((Path) get_outerjoinpath(curpath),
|
||||
@@ -127,7 +127,7 @@ xfunc_trypullup(RelOptInfo rel)
|
||||
}
|
||||
|
||||
/*
|
||||
** xfunc_shouldpull
|
||||
** xfunc_shouldpull
|
||||
** find clause with highest rank, and decide whether to pull it up
|
||||
** from child to parent. Currently we only pullup secondary join clauses
|
||||
** that are in the pathrestrictinfo. Secondary hash and sort clauses are
|
||||
@@ -144,12 +144,12 @@ xfunc_shouldpull(Query *queryInfo,
|
||||
Path childpath,
|
||||
JoinPath parentpath,
|
||||
int whichchild,
|
||||
RestrictInfo *maxcinfopt) /* Out: pointer to clause
|
||||
RestrictInfo * maxcinfopt) /* Out: pointer to clause
|
||||
* to pullup */
|
||||
{
|
||||
LispValue clauselist,
|
||||
tmplist; /* lists of clauses */
|
||||
RestrictInfo maxcinfo; /* clause to pullup */
|
||||
RestrictInfo maxcinfo; /* clause to pullup */
|
||||
LispValue primjoinclause /* primary join clause */
|
||||
= xfunc_primary_join(parentpath);
|
||||
Cost tmprank,
|
||||
@@ -225,7 +225,7 @@ xfunc_shouldpull(Query *queryInfo,
|
||||
|| (!is_join(childpath)
|
||||
&& (whichchild == INNER)
|
||||
&& IsA(parentpath, NestPath)
|
||||
&&!IsA(parentpath, HashPath)
|
||||
&& !IsA(parentpath, HashPath)
|
||||
&&!IsA(parentpath, MergePath)))))
|
||||
{
|
||||
|
||||
@@ -250,7 +250,7 @@ xfunc_shouldpull(Query *queryInfo,
|
||||
|
||||
|
||||
/*
|
||||
** xfunc_pullup
|
||||
** xfunc_pullup
|
||||
** move clause from child pathnode to parent pathnode. This operation
|
||||
** makes the child pathnode produce a larger relation than it used to.
|
||||
** This means that we must construct a new RelOptInfo just for the childpath,
|
||||
@@ -264,7 +264,7 @@ RestrictInfo
|
||||
xfunc_pullup(Query *queryInfo,
|
||||
Path childpath,
|
||||
JoinPath parentpath,
|
||||
RestrictInfo cinfo, /* clause to pull up */
|
||||
RestrictInfo cinfo,/* clause to pull up */
|
||||
int whichchild, /* whether child is INNER or OUTER of join */
|
||||
int clausetype) /* whether clause to pull is join or local */
|
||||
{
|
||||
@@ -272,22 +272,22 @@ xfunc_pullup(Query *queryInfo,
|
||||
RelOptInfo newrel;
|
||||
Cost pulled_selec;
|
||||
Cost cost;
|
||||
RestrictInfo newinfo;
|
||||
RestrictInfo newinfo;
|
||||
|
||||
/* remove clause from childpath */
|
||||
newkid = (Path) copyObject((Node) childpath);
|
||||
if (clausetype == XFUNC_LOCPRD)
|
||||
{
|
||||
set_locrestrictinfo(newkid,
|
||||
xfunc_LispRemove((LispValue) cinfo,
|
||||
(List) get_loc_restrictinfo(newkid)));
|
||||
xfunc_LispRemove((LispValue) cinfo,
|
||||
(List) get_loc_restrictinfo(newkid)));
|
||||
}
|
||||
else
|
||||
{
|
||||
set_pathrestrictinfo
|
||||
((JoinPath) newkid,
|
||||
xfunc_LispRemove((LispValue) cinfo,
|
||||
(List) get_pathrestrictinfo((JoinPath) newkid)));
|
||||
(List) get_pathrestrictinfo((JoinPath) newkid)));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -328,8 +328,8 @@ xfunc_pullup(Query *queryInfo,
|
||||
|
||||
/* add clause to parentpath, and fix up its cost. */
|
||||
set_locrestrictinfo(parentpath,
|
||||
lispCons((LispValue) newinfo,
|
||||
(LispValue) get_loc_restrictinfo(parentpath)));
|
||||
lispCons((LispValue) newinfo,
|
||||
(LispValue) get_loc_restrictinfo(parentpath)));
|
||||
/* put new childpath into the path tree */
|
||||
if (whichchild == INNER)
|
||||
set_innerjoinpath(parentpath, (pathPtr) newkid);
|
||||
@@ -386,7 +386,7 @@ LispValue clause;
|
||||
}
|
||||
|
||||
/*
|
||||
** xfunc_join_expense
|
||||
** xfunc_join_expense
|
||||
** Find global expense of a join clause
|
||||
*/
|
||||
Cost
|
||||
@@ -457,7 +457,7 @@ xfunc_local_expense(LispValue clause)
|
||||
}
|
||||
|
||||
/*
|
||||
** xfunc_func_expense
|
||||
** xfunc_func_expense
|
||||
** given a Func or Oper and its args, find its expense.
|
||||
** Note: in Stonebraker's SIGMOD '91 paper, he uses a more complicated metric
|
||||
** than the one here. We can ignore the expected number of tuples for
|
||||
@@ -581,7 +581,7 @@ xfunc_func_expense(LispValue node, LispValue args)
|
||||
}
|
||||
|
||||
/*
|
||||
** xfunc_width
|
||||
** xfunc_width
|
||||
** recursively find the width of a expression
|
||||
*/
|
||||
|
||||
@@ -694,7 +694,7 @@ xfunc_width(LispValue clause)
|
||||
*/
|
||||
Assert(length(get_func_tlist(func)) == 1); /* sanity */
|
||||
retval = xfunc_width((LispValue)
|
||||
get_expr(lfirst(get_func_tlist(func))));
|
||||
get_expr(lfirst(get_func_tlist(func))));
|
||||
goto exit;
|
||||
}
|
||||
else
|
||||
@@ -771,8 +771,8 @@ xfunc_card_product(Query *queryInfo, Relids relids)
|
||||
{
|
||||
if (!xfunc_expense(queryInfo, get_clause((RestrictInfo) lfirst(cinfonode))))
|
||||
tuples *= compute_clause_selec(queryInfo,
|
||||
get_clause((RestrictInfo) lfirst(cinfonode)),
|
||||
LispNil);
|
||||
get_clause((RestrictInfo) lfirst(cinfonode)),
|
||||
LispNil);
|
||||
}
|
||||
|
||||
if (retval == 0)
|
||||
@@ -857,7 +857,7 @@ LispValue
|
||||
xfunc_primary_join(JoinPath pathnode)
|
||||
{
|
||||
LispValue joinclauselist = get_pathrestrictinfo(pathnode);
|
||||
RestrictInfo mincinfo;
|
||||
RestrictInfo mincinfo;
|
||||
LispValue tmplist;
|
||||
LispValue minclause = LispNil;
|
||||
Cost minrank,
|
||||
@@ -931,7 +931,7 @@ xfunc_get_path_cost(Query *queryInfo, Path pathnode)
|
||||
*/
|
||||
if (XfuncMode != XFUNC_OFF)
|
||||
set_locrestrictinfo(pathnode, lisp_qsort(get_loc_restrictinfo(pathnode),
|
||||
xfunc_cinfo_compare));
|
||||
xfunc_cinfo_compare));
|
||||
for (tmplist = get_loc_restrictinfo(pathnode), selec = 1.0;
|
||||
tmplist != LispNil;
|
||||
tmplist = lnext(tmplist))
|
||||
@@ -939,7 +939,7 @@ xfunc_get_path_cost(Query *queryInfo, Path pathnode)
|
||||
cost += (Cost) (xfunc_local_expense(get_clause((RestrictInfo) lfirst(tmplist)))
|
||||
* (Cost) get_tuples(get_parent(pathnode)) * selec);
|
||||
selec *= compute_clause_selec(queryInfo,
|
||||
get_clause((RestrictInfo) lfirst(tmplist)),
|
||||
get_clause((RestrictInfo) lfirst(tmplist)),
|
||||
LispNil);
|
||||
}
|
||||
|
||||
@@ -951,8 +951,8 @@ xfunc_get_path_cost(Query *queryInfo, Path pathnode)
|
||||
{
|
||||
if (XfuncMode != XFUNC_OFF)
|
||||
set_pathrestrictinfo((JoinPath) pathnode, lisp_qsort
|
||||
(get_pathrestrictinfo((JoinPath) pathnode),
|
||||
xfunc_cinfo_compare));
|
||||
(get_pathrestrictinfo((JoinPath) pathnode),
|
||||
xfunc_cinfo_compare));
|
||||
for (tmplist = get_pathrestrictinfo((JoinPath) pathnode), selec = 1.0;
|
||||
tmplist != LispNil;
|
||||
tmplist = lnext(tmplist))
|
||||
@@ -960,7 +960,7 @@ xfunc_get_path_cost(Query *queryInfo, Path pathnode)
|
||||
cost += (Cost) (xfunc_local_expense(get_clause((RestrictInfo) lfirst(tmplist)))
|
||||
* (Cost) get_tuples(get_parent(pathnode)) * selec);
|
||||
selec *= compute_clause_selec(queryInfo,
|
||||
get_clause((RestrictInfo) lfirst(tmplist)),
|
||||
get_clause((RestrictInfo) lfirst(tmplist)),
|
||||
LispNil);
|
||||
}
|
||||
}
|
||||
@@ -1071,7 +1071,7 @@ xfunc_total_path_cost(JoinPath pathnode)
|
||||
|
||||
|
||||
/*
|
||||
** xfunc_expense_per_tuple
|
||||
** xfunc_expense_per_tuple
|
||||
** return the expense of the join *per-tuple* of the input relation.
|
||||
** The cost model here is that a join costs
|
||||
** k*card(outer)*card(inner) + l*card(outer) + m*card(inner) + n
|
||||
@@ -1124,7 +1124,7 @@ xfunc_expense_per_tuple(JoinPath joinnode, int whichchild)
|
||||
}
|
||||
|
||||
/*
|
||||
** xfunc_fixvars
|
||||
** xfunc_fixvars
|
||||
** After pulling up a clause, we must walk its expression tree, fixing Var
|
||||
** nodes to point to the correct varno (either INNER or OUTER, depending
|
||||
** on which child the clause was pulled from), and the right varattno in the
|
||||
@@ -1189,8 +1189,8 @@ xfunc_fixvars(LispValue clause, /* clause being pulled up */
|
||||
int
|
||||
xfunc_cinfo_compare(void *arg1, void *arg2)
|
||||
{
|
||||
RestrictInfo info1 = *(RestrictInfo *) arg1;
|
||||
RestrictInfo info2 = *(RestrictInfo *) arg2;
|
||||
RestrictInfo info1 = *(RestrictInfo *) arg1;
|
||||
RestrictInfo info2 = *(RestrictInfo *) arg2;
|
||||
|
||||
LispValue clause1 = (LispValue) get_clause(info1),
|
||||
clause2 = (LispValue) get_clause(info2);
|
||||
@@ -1223,7 +1223,7 @@ xfunc_clause_compare(void *arg1, void *arg2)
|
||||
}
|
||||
|
||||
/*
|
||||
** xfunc_disjunct_sort
|
||||
** xfunc_disjunct_sort
|
||||
** given a list of clauses, for each clause sort the disjuncts by cost
|
||||
** (this assumes the predicates have been converted to Conjunctive NF)
|
||||
** Modifies the clause list!
|
||||
@@ -1287,7 +1287,7 @@ xfunc_disjunct_compare(Query *queryInfo, void *arg1, void *arg2)
|
||||
|
||||
/* ------------------------ UTILITY FUNCTIONS ------------------------------- */
|
||||
/*
|
||||
** xfunc_func_width
|
||||
** xfunc_func_width
|
||||
** Given a function OID and operands, find the width of the return value.
|
||||
*/
|
||||
int
|
||||
@@ -1349,7 +1349,7 @@ exit:
|
||||
}
|
||||
|
||||
/*
|
||||
** xfunc_tuple_width
|
||||
** xfunc_tuple_width
|
||||
** Return the sum of the lengths of all the attributes of a given relation
|
||||
*/
|
||||
int
|
||||
@@ -1371,7 +1371,7 @@ xfunc_tuple_width(Relation rd)
|
||||
}
|
||||
|
||||
/*
|
||||
** xfunc_num_join_clauses
|
||||
** xfunc_num_join_clauses
|
||||
** Find the number of join clauses associated with this join path
|
||||
*/
|
||||
int
|
||||
@@ -1388,7 +1388,7 @@ xfunc_num_join_clauses(JoinPath path)
|
||||
}
|
||||
|
||||
/*
|
||||
** xfunc_LispRemove
|
||||
** xfunc_LispRemove
|
||||
** Just like LispRemove, but it whines if the item to be removed ain't there
|
||||
*/
|
||||
LispValue
|
||||
@@ -1419,11 +1419,11 @@ do { \
|
||||
} while(0)
|
||||
|
||||
/*
|
||||
** xfunc_copyrel
|
||||
** xfunc_copyrel
|
||||
** Just like _copyRel, but doesn't copy the paths
|
||||
*/
|
||||
bool
|
||||
xfunc_copyrel(RelOptInfo from, RelOptInfo *to)
|
||||
xfunc_copyrel(RelOptInfo from, RelOptInfo * to)
|
||||
{
|
||||
RelOptInfo newnode;
|
||||
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.44 1999/02/22 05:26:18 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.45 1999/05/25 16:09:22 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -45,10 +45,10 @@ int32 _use_geqo_rels_ = GEQO_RELS;
|
||||
|
||||
static void set_base_rel_pathlist(Query *root, List *rels);
|
||||
static RelOptInfo *make_one_rel_by_joins(Query *root, List *rels,
|
||||
int levels_needed);
|
||||
int levels_needed);
|
||||
|
||||
#ifdef OPTIMIZER_DEBUG
|
||||
static void debug_print_rel(Query *root, RelOptInfo *rel);
|
||||
static void debug_print_rel(Query *root, RelOptInfo * rel);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -76,6 +76,7 @@ make_one_rel(Query *root, List *rels)
|
||||
|
||||
if (levels_needed <= 1)
|
||||
{
|
||||
|
||||
/*
|
||||
* Unsorted single relation, no more processing is required.
|
||||
*/
|
||||
@@ -83,6 +84,7 @@ make_one_rel(Query *root, List *rels)
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/*
|
||||
* This means that joins or sorts are required. set selectivities
|
||||
* of clauses that have not been set by an index.
|
||||
@@ -117,17 +119,17 @@ set_base_rel_pathlist(Query *root, List *rels)
|
||||
sequential_scan_list = lcons(create_seqscan_path(rel), NIL);
|
||||
|
||||
rel_index_scan_list = create_index_paths(root,
|
||||
rel,
|
||||
find_relation_indices(root, rel),
|
||||
rel->restrictinfo,
|
||||
rel->joininfo);
|
||||
rel,
|
||||
find_relation_indices(root, rel),
|
||||
rel->restrictinfo,
|
||||
rel->joininfo);
|
||||
|
||||
or_index_scan_list = create_or_index_paths(root, rel, rel->restrictinfo);
|
||||
|
||||
rel->pathlist = add_pathlist(rel,
|
||||
sequential_scan_list,
|
||||
nconc(rel_index_scan_list,
|
||||
or_index_scan_list));
|
||||
or_index_scan_list));
|
||||
|
||||
set_cheapest(rel, rel->pathlist);
|
||||
|
||||
@@ -171,13 +173,14 @@ make_one_rel_by_joins(Query *root, List *rels, int levels_needed)
|
||||
*******************************************/
|
||||
if ((_use_geqo_) && length(root->base_rel_list) >= _use_geqo_rels_)
|
||||
return geqo(root);
|
||||
|
||||
|
||||
/*******************************************
|
||||
* rest will be deprecated in case of GEQO *
|
||||
*******************************************/
|
||||
|
||||
while (--levels_needed)
|
||||
{
|
||||
|
||||
/*
|
||||
* Determine all possible pairs of relations to be joined at this
|
||||
* level. Determine paths for joining these relation pairs and
|
||||
@@ -193,6 +196,7 @@ make_one_rel_by_joins(Query *root, List *rels, int levels_needed)
|
||||
root->join_rel_list = rels = joined_rels;
|
||||
|
||||
#ifdef NOT_USED
|
||||
|
||||
/*
|
||||
* * for each expensive predicate in each path in each distinct
|
||||
* rel, * consider doing pullup -- JMH
|
||||
@@ -351,7 +355,7 @@ print_path(Query *root, Path *path, int indent)
|
||||
}
|
||||
|
||||
static void
|
||||
debug_print_rel(Query *root, RelOptInfo *rel)
|
||||
debug_print_rel(Query *root, RelOptInfo * rel)
|
||||
{
|
||||
List *l;
|
||||
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/clausesel.c,v 1.19 1999/05/16 19:45:37 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/clausesel.c,v 1.20 1999/05/25 16:09:22 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -132,7 +132,7 @@ set_rest_selec(Query *root, List *restrictinfo_list)
|
||||
if (cost_clause <= 0 || valid_or_clause(clausenode))
|
||||
{
|
||||
clausenode->selectivity = compute_clause_selec(root,
|
||||
(Node *) clausenode->clause,
|
||||
(Node *) clausenode->clause,
|
||||
lcons(makeFloat(cost_clause), NIL));
|
||||
}
|
||||
}
|
||||
@@ -256,7 +256,7 @@ compute_selec(Query *root, List *clauses, List *or_selectivities)
|
||||
else if (not_clause((Node *) clause))
|
||||
{
|
||||
/* negate this baby */
|
||||
return 1 - compute_selec(root, ((Expr *)clause)->args, or_selectivities);
|
||||
return 1 - compute_selec(root, ((Expr *) clause)->args, or_selectivities);
|
||||
}
|
||||
else if (is_subplan((Node *) clause))
|
||||
{
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.36 1999/05/01 19:47:41 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.37 1999/05/25 16:09:23 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -37,7 +37,7 @@
|
||||
extern int NBuffers;
|
||||
|
||||
static int compute_attribute_width(TargetEntry *tlistentry);
|
||||
static double relation_byte_size (int tuples, int width);
|
||||
static double relation_byte_size(int tuples, int width);
|
||||
static double base_log(double x, double b);
|
||||
static int compute_targetlist_width(List *targetlist);
|
||||
|
||||
@@ -134,9 +134,10 @@ cost_index(Oid indexid,
|
||||
if (!_enable_indexscan_ && !is_injoin)
|
||||
temp += _disable_cost_;
|
||||
|
||||
/* We want to be sure we estimate the cost of an index scan
|
||||
* as more than the cost of a sequential scan (when selec == 1.0),
|
||||
* even if we don't have good stats. So, disbelieve zero index size.
|
||||
/*
|
||||
* We want to be sure we estimate the cost of an index scan as more
|
||||
* than the cost of a sequential scan (when selec == 1.0), even if we
|
||||
* don't have good stats. So, disbelieve zero index size.
|
||||
*/
|
||||
if (expected_indexpages <= 0)
|
||||
expected_indexpages = 1;
|
||||
@@ -146,11 +147,11 @@ cost_index(Oid indexid,
|
||||
/* expected index relation pages */
|
||||
temp += expected_indexpages;
|
||||
|
||||
/* expected base relation pages
|
||||
* XXX this isn't really right, since we will access the table
|
||||
* nonsequentially and might have to fetch the same page
|
||||
* more than once. This calculation assumes the buffer cache
|
||||
* will prevent that from happening...
|
||||
/*
|
||||
* expected base relation pages XXX this isn't really right, since we
|
||||
* will access the table nonsequentially and might have to fetch the
|
||||
* same page more than once. This calculation assumes the buffer
|
||||
* cache will prevent that from happening...
|
||||
*/
|
||||
temp += ceil(((double) selec) * ((double) relpages));
|
||||
|
||||
@@ -192,8 +193,10 @@ cost_sort(List *pathkeys, int tuples, int width)
|
||||
if (!_enable_sort_)
|
||||
temp += _disable_cost_;
|
||||
|
||||
/* We want to be sure the cost of a sort is never estimated as zero,
|
||||
* even if passed-in tuple count is zero. Besides, mustn't do log(0)...
|
||||
/*
|
||||
* We want to be sure the cost of a sort is never estimated as zero,
|
||||
* even if passed-in tuple count is zero. Besides, mustn't do
|
||||
* log(0)...
|
||||
*/
|
||||
if (tuples <= 0)
|
||||
tuples = 1;
|
||||
@@ -344,10 +347,11 @@ cost_hashjoin(Cost outercost,
|
||||
if (!_enable_hashjoin_)
|
||||
temp += _disable_cost_;
|
||||
|
||||
/* Bias against putting larger relation on inside.
|
||||
/*
|
||||
* Bias against putting larger relation on inside.
|
||||
*
|
||||
* Code used to use "outerpages < innerpages" but that has
|
||||
* poor resolution when both relations are small.
|
||||
* Code used to use "outerpages < innerpages" but that has poor
|
||||
* resolution when both relations are small.
|
||||
*/
|
||||
if (relation_byte_size(outersize, outerwidth) <
|
||||
relation_byte_size(innersize, innerwidth))
|
||||
@@ -362,7 +366,8 @@ cost_hashjoin(Cost outercost,
|
||||
/* cost of main-memory hashtable */
|
||||
temp += (innerpages < NBuffers) ? innerpages : NBuffers;
|
||||
|
||||
/* if inner relation is too big then we will need to "batch" the join,
|
||||
/*
|
||||
* if inner relation is too big then we will need to "batch" the join,
|
||||
* which implies writing and reading most of the tuples to disk an
|
||||
* extra time.
|
||||
*/
|
||||
@@ -385,7 +390,7 @@ cost_hashjoin(Cost outercost,
|
||||
* Returns the size.
|
||||
*/
|
||||
int
|
||||
compute_rel_size(RelOptInfo *rel)
|
||||
compute_rel_size(RelOptInfo * rel)
|
||||
{
|
||||
Cost temp;
|
||||
int temp1;
|
||||
@@ -408,7 +413,7 @@ compute_rel_size(RelOptInfo *rel)
|
||||
* Returns the width of the tuple as a fixnum.
|
||||
*/
|
||||
int
|
||||
compute_rel_width(RelOptInfo *rel)
|
||||
compute_rel_width(RelOptInfo * rel)
|
||||
{
|
||||
return compute_targetlist_width(get_actual_tlist(rel->targetlist));
|
||||
}
|
||||
@@ -470,11 +475,11 @@ compute_joinrel_size(JoinPath *joinpath)
|
||||
temp *= ((Path *) joinpath->innerjoinpath)->parent->size;
|
||||
|
||||
temp = temp * product_selec(joinpath->pathinfo);
|
||||
if (temp >= (MAXINT-1)/2)
|
||||
if (temp >= (MAXINT - 1) / 2)
|
||||
{
|
||||
/* if we exceed (MAXINT-1)/2, we switch to log scale */
|
||||
/* +1 prevents log(0) */
|
||||
temp1 = ceil(log(temp + 1 - (MAXINT-1)/2) + (MAXINT-1)/2);
|
||||
temp1 = ceil(log(temp + 1 - (MAXINT - 1) / 2) + (MAXINT - 1) / 2);
|
||||
}
|
||||
else
|
||||
temp1 = ceil((double) temp);
|
||||
@@ -485,13 +490,13 @@ compute_joinrel_size(JoinPath *joinpath)
|
||||
|
||||
/*
|
||||
* relation_byte_size
|
||||
* Estimate the storage space in bytes for a given number of tuples
|
||||
* of a given width (size in bytes).
|
||||
* To avoid overflow with big relations, result is a double.
|
||||
* Estimate the storage space in bytes for a given number of tuples
|
||||
* of a given width (size in bytes).
|
||||
* To avoid overflow with big relations, result is a double.
|
||||
*/
|
||||
|
||||
static double
|
||||
relation_byte_size (int tuples, int width)
|
||||
relation_byte_size(int tuples, int width)
|
||||
{
|
||||
return ((double) tuples) * ((double) (width + sizeof(HeapTupleData)));
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/hashutils.c,v 1.15 1999/04/03 00:18:27 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/hashutils.c,v 1.16 1999/05/25 16:09:23 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -30,7 +30,7 @@ static HashInfo *match_hashop_hashinfo(Oid hashop, List *hashinfo_list);
|
||||
*
|
||||
* 'restrictinfo_list' is the list of restrictinfo nodes
|
||||
* 'inner_relids' is the list of relids in the inner join relation
|
||||
* (used to determine whether a join var is inner or outer)
|
||||
* (used to determine whether a join var is inner or outer)
|
||||
*
|
||||
* Returns the new list of hashinfo nodes.
|
||||
*
|
||||
@@ -84,7 +84,7 @@ group_clauses_by_hashop(List *restrictinfo_list,
|
||||
}
|
||||
|
||||
xhashinfo->jmethod.clauses = lcons(clause,
|
||||
xhashinfo->jmethod.clauses);
|
||||
xhashinfo->jmethod.clauses);
|
||||
xhashinfo->jmethod.jmkeys = lcons(joinkey,
|
||||
xhashinfo->jmethod.jmkeys);
|
||||
}
|
||||
@@ -105,7 +105,7 @@ static HashInfo *
|
||||
match_hashop_hashinfo(Oid hashop, List *hashinfo_list)
|
||||
{
|
||||
Oid key = 0;
|
||||
HashInfo *xhashinfo = (HashInfo *) NULL;
|
||||
HashInfo *xhashinfo = (HashInfo *) NULL;
|
||||
List *i = NIL;
|
||||
|
||||
foreach(i, hashinfo_list)
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.54 1999/03/18 19:59:53 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.55 1999/05/25 16:09:24 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -45,32 +45,32 @@
|
||||
#include "utils/lsyscache.h"
|
||||
|
||||
|
||||
static void match_index_orclauses(RelOptInfo *rel, RelOptInfo *index, int indexkey,
|
||||
static void match_index_orclauses(RelOptInfo * rel, RelOptInfo * index, int indexkey,
|
||||
int xclass, List *restrictinfo_list);
|
||||
static bool match_index_to_operand(int indexkey, Expr *operand,
|
||||
RelOptInfo *rel, RelOptInfo *index);
|
||||
static List *match_index_orclause(RelOptInfo *rel, RelOptInfo *index, int indexkey,
|
||||
RelOptInfo * rel, RelOptInfo * index);
|
||||
static List *match_index_orclause(RelOptInfo * rel, RelOptInfo * index, int indexkey,
|
||||
int xclass, List *or_clauses, List *other_matching_indices);
|
||||
static List *group_clauses_by_indexkey(RelOptInfo *rel, RelOptInfo *index,
|
||||
int *indexkeys, Oid *classes, List *restrictinfo_list);
|
||||
static List *group_clauses_by_ikey_for_joins(RelOptInfo *rel, RelOptInfo *index,
|
||||
static List *group_clauses_by_indexkey(RelOptInfo * rel, RelOptInfo * index,
|
||||
int *indexkeys, Oid *classes, List *restrictinfo_list);
|
||||
static List *group_clauses_by_ikey_for_joins(RelOptInfo * rel, RelOptInfo * index,
|
||||
int *indexkeys, Oid *classes, List *join_cinfo_list, List *restr_cinfo_list);
|
||||
static RestrictInfo *match_clause_to_indexkey(RelOptInfo *rel, RelOptInfo *index, int indexkey,
|
||||
int xclass, RestrictInfo *restrictInfo, bool join);
|
||||
static RestrictInfo *match_clause_to_indexkey(RelOptInfo * rel, RelOptInfo * index, int indexkey,
|
||||
int xclass, RestrictInfo * restrictInfo, bool join);
|
||||
static bool pred_test(List *predicate_list, List *restrictinfo_list,
|
||||
List *joininfo_list);
|
||||
static bool one_pred_test(Expr *predicate, List *restrictinfo_list);
|
||||
static bool one_pred_clause_expr_test(Expr *predicate, Node *clause);
|
||||
static bool one_pred_clause_test(Expr *predicate, Node *clause);
|
||||
static bool clause_pred_clause_test(Expr *predicate, Node *clause);
|
||||
static List *indexable_joinclauses(RelOptInfo *rel, RelOptInfo *index,
|
||||
static List *indexable_joinclauses(RelOptInfo * rel, RelOptInfo * index,
|
||||
List *joininfo_list, List *restrictinfo_list);
|
||||
static List *index_innerjoin(Query *root, RelOptInfo *rel,
|
||||
List *clausegroup_list, RelOptInfo *index);
|
||||
static List *create_index_path_group(Query *root, RelOptInfo *rel, RelOptInfo *index,
|
||||
List *clausegroup_list, bool join);
|
||||
static List *index_innerjoin(Query *root, RelOptInfo * rel,
|
||||
List *clausegroup_list, RelOptInfo * index);
|
||||
static List *create_index_path_group(Query *root, RelOptInfo * rel, RelOptInfo * index,
|
||||
List *clausegroup_list, bool join);
|
||||
static List *add_index_paths(List *indexpaths, List *new_indexpaths);
|
||||
static bool function_index_operand(Expr *funcOpnd, RelOptInfo *rel, RelOptInfo *index);
|
||||
static bool function_index_operand(Expr *funcOpnd, RelOptInfo * rel, RelOptInfo * index);
|
||||
|
||||
|
||||
/* find_index_paths()
|
||||
@@ -100,10 +100,10 @@ static bool function_index_operand(Expr *funcOpnd, RelOptInfo *rel, RelOptInfo *
|
||||
*/
|
||||
List *
|
||||
create_index_paths(Query *root,
|
||||
RelOptInfo *rel,
|
||||
List *indices,
|
||||
List *restrictinfo_list,
|
||||
List *joininfo_list)
|
||||
RelOptInfo * rel,
|
||||
List *indices,
|
||||
List *restrictinfo_list,
|
||||
List *joininfo_list)
|
||||
{
|
||||
List *scanclausegroups = NIL;
|
||||
List *scanpaths = NIL;
|
||||
@@ -127,11 +127,11 @@ create_index_paths(Query *root,
|
||||
|
||||
/*
|
||||
* 1. Try matching the index against subclauses of an 'or' clause.
|
||||
* The fields of the restrictinfo nodes are marked with lists of the
|
||||
* matching indices. No path are actually created. We currently
|
||||
* only look to match the first key. We don't find multi-key
|
||||
* index cases where an AND matches the first key, and the OR
|
||||
* matches the second key.
|
||||
* The fields of the restrictinfo nodes are marked with lists of
|
||||
* the matching indices. No path are actually created. We
|
||||
* currently only look to match the first key. We don't find
|
||||
* multi-key index cases where an AND matches the first key, and
|
||||
* the OR matches the second key.
|
||||
*/
|
||||
match_index_orclauses(rel,
|
||||
index,
|
||||
@@ -144,7 +144,7 @@ create_index_paths(Query *root,
|
||||
* restriction clauses, then create pathnodes corresponding to
|
||||
* each group of usable clauses.
|
||||
*/
|
||||
scanclausegroups = group_clauses_by_indexkey(rel,
|
||||
scanclausegroups = group_clauses_by_indexkey(rel,
|
||||
index,
|
||||
index->indexkeys,
|
||||
index->classlist,
|
||||
@@ -153,10 +153,10 @@ create_index_paths(Query *root,
|
||||
scanpaths = NIL;
|
||||
if (scanclausegroups != NIL)
|
||||
scanpaths = create_index_path_group(root,
|
||||
rel,
|
||||
index,
|
||||
scanclausegroups,
|
||||
false);
|
||||
rel,
|
||||
index,
|
||||
scanclausegroups,
|
||||
false);
|
||||
|
||||
/*
|
||||
* 3. If this index can be used with any join clause, then create
|
||||
@@ -171,12 +171,12 @@ create_index_paths(Query *root,
|
||||
if (joinclausegroups != NIL)
|
||||
{
|
||||
joinpaths = create_index_path_group(root, rel,
|
||||
index,
|
||||
joinclausegroups,
|
||||
true);
|
||||
index,
|
||||
joinclausegroups,
|
||||
true);
|
||||
rel->innerjoin = nconc(rel->innerjoin,
|
||||
index_innerjoin(root, rel,
|
||||
joinclausegroups, index));
|
||||
joinclausegroups, index));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -217,8 +217,8 @@ create_index_paths(Query *root,
|
||||
*
|
||||
*/
|
||||
static void
|
||||
match_index_orclauses(RelOptInfo *rel,
|
||||
RelOptInfo *index,
|
||||
match_index_orclauses(RelOptInfo * rel,
|
||||
RelOptInfo * index,
|
||||
int indexkey,
|
||||
int xclass,
|
||||
List *restrictinfo_list)
|
||||
@@ -238,9 +238,9 @@ match_index_orclauses(RelOptInfo *rel,
|
||||
* 'index' to the existing list where appropriate.
|
||||
*/
|
||||
restrictinfo->indexids = match_index_orclause(rel, index, indexkey,
|
||||
xclass,
|
||||
restrictinfo->clause->args,
|
||||
restrictinfo->indexids);
|
||||
xclass,
|
||||
restrictinfo->clause->args,
|
||||
restrictinfo->indexids);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -253,8 +253,8 @@ match_index_orclauses(RelOptInfo *rel,
|
||||
static bool
|
||||
match_index_to_operand(int indexkey,
|
||||
Expr *operand,
|
||||
RelOptInfo *rel,
|
||||
RelOptInfo *index)
|
||||
RelOptInfo * rel,
|
||||
RelOptInfo * index)
|
||||
{
|
||||
bool result;
|
||||
|
||||
@@ -296,8 +296,8 @@ match_index_to_operand(int indexkey,
|
||||
* match the third, g,h match the fourth, etc.
|
||||
*/
|
||||
static List *
|
||||
match_index_orclause(RelOptInfo *rel,
|
||||
RelOptInfo *index,
|
||||
match_index_orclause(RelOptInfo * rel,
|
||||
RelOptInfo * index,
|
||||
int indexkey,
|
||||
int xclass,
|
||||
List *or_clauses,
|
||||
@@ -325,8 +325,9 @@ match_index_orclause(RelOptInfo *rel,
|
||||
|
||||
if (is_opclause(clause))
|
||||
{
|
||||
Expr *left = (Expr *) get_leftop((Expr *) clause);
|
||||
Expr *right = (Expr *) get_rightop((Expr *) clause);
|
||||
Expr *left = (Expr *) get_leftop((Expr *) clause);
|
||||
Expr *right = (Expr *) get_rightop((Expr *) clause);
|
||||
|
||||
if (left && right &&
|
||||
op_class(((Oper *) ((Expr *) clause)->oper)->opno,
|
||||
xclass, index->relam) &&
|
||||
@@ -335,7 +336,7 @@ match_index_orclause(RelOptInfo *rel,
|
||||
(IsA(left, Const) &&
|
||||
match_index_to_operand(indexkey, right, rel, index))))
|
||||
lfirst(matching_indices) = lcons(index,
|
||||
lfirst(matching_indices));
|
||||
lfirst(matching_indices));
|
||||
}
|
||||
|
||||
matching_indices = lnext(matching_indices);
|
||||
@@ -386,8 +387,8 @@ match_index_orclause(RelOptInfo *rel,
|
||||
*
|
||||
*/
|
||||
static List *
|
||||
group_clauses_by_indexkey(RelOptInfo *rel,
|
||||
RelOptInfo *index,
|
||||
group_clauses_by_indexkey(RelOptInfo * rel,
|
||||
RelOptInfo * index,
|
||||
int *indexkeys,
|
||||
Oid *classes,
|
||||
List *restrictinfo_list)
|
||||
@@ -448,8 +449,8 @@ group_clauses_by_indexkey(RelOptInfo *rel,
|
||||
*
|
||||
*/
|
||||
static List *
|
||||
group_clauses_by_ikey_for_joins(RelOptInfo *rel,
|
||||
RelOptInfo *index,
|
||||
group_clauses_by_ikey_for_joins(RelOptInfo * rel,
|
||||
RelOptInfo * index,
|
||||
int *indexkeys,
|
||||
Oid *classes,
|
||||
List *join_cinfo_list,
|
||||
@@ -570,11 +571,11 @@ group_clauses_by_ikey_for_joins(RelOptInfo *rel,
|
||||
*
|
||||
*/
|
||||
static RestrictInfo *
|
||||
match_clause_to_indexkey(RelOptInfo *rel,
|
||||
RelOptInfo *index,
|
||||
match_clause_to_indexkey(RelOptInfo * rel,
|
||||
RelOptInfo * index,
|
||||
int indexkey,
|
||||
int xclass,
|
||||
RestrictInfo *restrictInfo,
|
||||
RestrictInfo * restrictInfo,
|
||||
bool join)
|
||||
{
|
||||
Expr *clause = restrictInfo->clause;
|
||||
@@ -597,6 +598,7 @@ match_clause_to_indexkey(RelOptInfo *rel,
|
||||
*/
|
||||
if (!join)
|
||||
{
|
||||
|
||||
/*
|
||||
* Check for standard s-argable clause
|
||||
*/
|
||||
@@ -647,10 +649,10 @@ match_clause_to_indexkey(RelOptInfo *rel,
|
||||
restrict_op = oprid(newop);
|
||||
|
||||
isIndexable = (op_class(restrict_op, xclass, index->relam) &&
|
||||
IndexScanableOperand(leftop,
|
||||
indexkey,
|
||||
rel,
|
||||
index));
|
||||
IndexScanableOperand(leftop,
|
||||
indexkey,
|
||||
rel,
|
||||
index));
|
||||
|
||||
if (isIndexable)
|
||||
((Oper *) ((Expr *) clause)->oper)->opno = restrict_op;
|
||||
@@ -1181,7 +1183,7 @@ clause_pred_clause_test(Expr *predicate, Node *clause)
|
||||
*
|
||||
*/
|
||||
static List *
|
||||
indexable_joinclauses(RelOptInfo *rel, RelOptInfo *index,
|
||||
indexable_joinclauses(RelOptInfo * rel, RelOptInfo * index,
|
||||
List *joininfo_list, List *restrictinfo_list)
|
||||
{
|
||||
JoinInfo *joininfo = (JoinInfo *) NULL;
|
||||
@@ -1196,11 +1198,11 @@ indexable_joinclauses(RelOptInfo *rel, RelOptInfo *index,
|
||||
if (joininfo->jinfo_restrictinfo == NIL)
|
||||
continue;
|
||||
clausegroups = group_clauses_by_ikey_for_joins(rel,
|
||||
index,
|
||||
index->indexkeys,
|
||||
index->classlist,
|
||||
index,
|
||||
index->indexkeys,
|
||||
index->classlist,
|
||||
joininfo->jinfo_restrictinfo,
|
||||
restrictinfo_list);
|
||||
restrictinfo_list);
|
||||
|
||||
if (clausegroups != NIL)
|
||||
{
|
||||
@@ -1253,8 +1255,8 @@ extract_restrict_clauses(List *clausegroup)
|
||||
*
|
||||
*/
|
||||
static List *
|
||||
index_innerjoin(Query *root, RelOptInfo *rel, List *clausegroup_list,
|
||||
RelOptInfo *index)
|
||||
index_innerjoin(Query *root, RelOptInfo * rel, List *clausegroup_list,
|
||||
RelOptInfo * index)
|
||||
{
|
||||
List *clausegroup = NIL;
|
||||
List *cg_list = NIL;
|
||||
@@ -1289,9 +1291,9 @@ index_innerjoin(Query *root, RelOptInfo *rel, List *clausegroup_list,
|
||||
pathnode->path.pathtype = T_IndexScan;
|
||||
pathnode->path.parent = rel;
|
||||
pathnode->path.pathorder = makeNode(PathOrder);
|
||||
pathnode->path.pathorder->ordtype = SORTOP_ORDER;
|
||||
pathnode->path.pathorder->ord.sortop = index->ordering;
|
||||
pathnode->path.pathkeys = NIL;
|
||||
pathnode->path.pathorder->ordtype = SORTOP_ORDER;
|
||||
pathnode->path.pathorder->ord.sortop = index->ordering;
|
||||
pathnode->path.pathkeys = NIL;
|
||||
|
||||
pathnode->indexid = index->relids;
|
||||
pathnode->indexkeys = index->indexkeys;
|
||||
@@ -1300,27 +1302,25 @@ index_innerjoin(Query *root, RelOptInfo *rel, List *clausegroup_list,
|
||||
pathnode->path.joinid = ((RestrictInfo *) lfirst(clausegroup))->restrictinfojoinid;
|
||||
|
||||
pathnode->path.path_cost = cost_index((Oid) lfirsti(index->relids),
|
||||
(int) temp_pages,
|
||||
temp_selec,
|
||||
rel->pages,
|
||||
rel->tuples,
|
||||
index->pages,
|
||||
index->tuples,
|
||||
true);
|
||||
(int) temp_pages,
|
||||
temp_selec,
|
||||
rel->pages,
|
||||
rel->tuples,
|
||||
index->pages,
|
||||
index->tuples,
|
||||
true);
|
||||
|
||||
/*
|
||||
* copy restrictinfo list into path for expensive function
|
||||
* processing -- JMH, 7/7/92
|
||||
*/
|
||||
pathnode->path.loc_restrictinfo = set_difference(copyObject((Node *) rel->restrictinfo),
|
||||
clausegroup);
|
||||
clausegroup);
|
||||
|
||||
#ifdef NOT_USED /* fix xfunc */
|
||||
#ifdef NOT_USED /* fix xfunc */
|
||||
/* add in cost for expensive functions! -- JMH, 7/7/92 */
|
||||
if (XfuncMode != XFUNC_OFF)
|
||||
{
|
||||
((Path *) pathnode)->path_cost += xfunc_get_path_cost((Path *) pathnode);
|
||||
}
|
||||
#endif
|
||||
cg_list = lappend(cg_list, pathnode);
|
||||
}
|
||||
@@ -1343,10 +1343,10 @@ index_innerjoin(Query *root, RelOptInfo *rel, List *clausegroup_list,
|
||||
*/
|
||||
static List *
|
||||
create_index_path_group(Query *root,
|
||||
RelOptInfo *rel,
|
||||
RelOptInfo *index,
|
||||
List *clausegroup_list,
|
||||
bool join)
|
||||
RelOptInfo * rel,
|
||||
RelOptInfo * index,
|
||||
List *clausegroup_list,
|
||||
bool join)
|
||||
{
|
||||
List *clausegroup = NIL;
|
||||
List *ip_list = NIL;
|
||||
@@ -1366,7 +1366,7 @@ create_index_path_group(Query *root,
|
||||
restrictinfo = (RestrictInfo *) lfirst(j);
|
||||
if (!(is_joinable((Node *) restrictinfo->clause) &&
|
||||
equal_path_merge_ordering(index->ordering,
|
||||
restrictinfo->mergejoinorder)))
|
||||
restrictinfo->mergejoinorder)))
|
||||
temp = false;
|
||||
}
|
||||
|
||||
@@ -1386,7 +1386,7 @@ add_index_paths(List *indexpaths, List *new_indexpaths)
|
||||
}
|
||||
|
||||
static bool
|
||||
function_index_operand(Expr *funcOpnd, RelOptInfo *rel, RelOptInfo *index)
|
||||
function_index_operand(Expr *funcOpnd, RelOptInfo * rel, RelOptInfo * index)
|
||||
{
|
||||
Oid heapRelid = (Oid) lfirsti(rel->relids);
|
||||
Func *function;
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinpath.c,v 1.36 1999/05/18 21:36:10 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinpath.c,v 1.37 1999/05/25 16:09:25 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -30,14 +30,14 @@
|
||||
* _enable_mergejoin} */
|
||||
|
||||
static Path *best_innerjoin(List *join_paths, List *outer_relid);
|
||||
static List *sort_inner_and_outer(RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel,
|
||||
static List *sort_inner_and_outer(RelOptInfo * joinrel, RelOptInfo * outerrel, RelOptInfo * innerrel,
|
||||
List *mergeinfo_list);
|
||||
static List *match_unsorted_outer(RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel,
|
||||
static List *match_unsorted_outer(RelOptInfo * joinrel, RelOptInfo * outerrel, RelOptInfo * innerrel,
|
||||
List *outerpath_list, Path *cheapest_inner, Path *best_innerjoin,
|
||||
List *mergeinfo_list);
|
||||
static List *match_unsorted_inner(RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel,
|
||||
static List *match_unsorted_inner(RelOptInfo * joinrel, RelOptInfo * outerrel, RelOptInfo * innerrel,
|
||||
List *innerpath_list, List *mergeinfo_list);
|
||||
static List *hash_inner_and_outer(RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel,
|
||||
static List *hash_inner_and_outer(RelOptInfo * joinrel, RelOptInfo * outerrel, RelOptInfo * innerrel,
|
||||
List *hashinfo_list);
|
||||
|
||||
/*
|
||||
@@ -119,13 +119,13 @@ update_rels_pathlist_for_joins(Query *root, List *joinrels)
|
||||
* mergejoins where the outer path is already ordered.
|
||||
*/
|
||||
pathlist = add_pathlist(joinrel, pathlist,
|
||||
match_unsorted_outer(joinrel,
|
||||
outerrel,
|
||||
innerrel,
|
||||
outerrel->pathlist,
|
||||
innerrel->cheapestpath,
|
||||
bestinnerjoin,
|
||||
mergeinfo_list));
|
||||
match_unsorted_outer(joinrel,
|
||||
outerrel,
|
||||
innerrel,
|
||||
outerrel->pathlist,
|
||||
innerrel->cheapestpath,
|
||||
bestinnerjoin,
|
||||
mergeinfo_list));
|
||||
|
||||
/*
|
||||
* 3. Consider paths where the inner relation need not be
|
||||
@@ -134,18 +134,18 @@ update_rels_pathlist_for_joins(Query *root, List *joinrels)
|
||||
* (match_unsorted_outer).
|
||||
*/
|
||||
pathlist = add_pathlist(joinrel, pathlist,
|
||||
match_unsorted_inner(joinrel, outerrel,
|
||||
innerrel,
|
||||
innerrel->pathlist,
|
||||
mergeinfo_list));
|
||||
match_unsorted_inner(joinrel, outerrel,
|
||||
innerrel,
|
||||
innerrel->pathlist,
|
||||
mergeinfo_list));
|
||||
|
||||
/*
|
||||
* 4. Consider paths where both outer and inner relations must be
|
||||
* hashed before being joined.
|
||||
*/
|
||||
pathlist = add_pathlist(joinrel, pathlist,
|
||||
hash_inner_and_outer(joinrel, outerrel,
|
||||
innerrel, hashinfo_list));
|
||||
hash_inner_and_outer(joinrel, outerrel,
|
||||
innerrel, hashinfo_list));
|
||||
|
||||
joinrel->pathlist = pathlist;
|
||||
}
|
||||
@@ -194,9 +194,9 @@ best_innerjoin(List *join_paths, Relids outer_relids)
|
||||
* Returns a list of mergejoin paths.
|
||||
*/
|
||||
static List *
|
||||
sort_inner_and_outer(RelOptInfo *joinrel,
|
||||
RelOptInfo *outerrel,
|
||||
RelOptInfo *innerrel,
|
||||
sort_inner_and_outer(RelOptInfo * joinrel,
|
||||
RelOptInfo * outerrel,
|
||||
RelOptInfo * innerrel,
|
||||
List *mergeinfo_list)
|
||||
{
|
||||
List *ms_list = NIL;
|
||||
@@ -212,28 +212,28 @@ sort_inner_and_outer(RelOptInfo *joinrel,
|
||||
xmergeinfo = (MergeInfo *) lfirst(i);
|
||||
|
||||
outerkeys = make_pathkeys_from_joinkeys(xmergeinfo->jmethod.jmkeys,
|
||||
outerrel->targetlist,
|
||||
OUTER);
|
||||
outerrel->targetlist,
|
||||
OUTER);
|
||||
|
||||
innerkeys = make_pathkeys_from_joinkeys(xmergeinfo->jmethod.jmkeys,
|
||||
innerrel->targetlist,
|
||||
INNER);
|
||||
innerrel->targetlist,
|
||||
INNER);
|
||||
|
||||
merge_pathkeys = new_join_pathkeys(outerkeys, joinrel->targetlist,
|
||||
xmergeinfo->jmethod.clauses);
|
||||
xmergeinfo->jmethod.clauses);
|
||||
|
||||
temp_node = create_mergejoin_path(joinrel,
|
||||
outerrel->size,
|
||||
innerrel->size,
|
||||
outerrel->width,
|
||||
innerrel->width,
|
||||
(Path *) outerrel->cheapestpath,
|
||||
(Path *) innerrel->cheapestpath,
|
||||
merge_pathkeys,
|
||||
xmergeinfo->m_ordering,
|
||||
xmergeinfo->jmethod.clauses,
|
||||
outerkeys,
|
||||
innerkeys);
|
||||
outerrel->size,
|
||||
innerrel->size,
|
||||
outerrel->width,
|
||||
innerrel->width,
|
||||
(Path *) outerrel->cheapestpath,
|
||||
(Path *) innerrel->cheapestpath,
|
||||
merge_pathkeys,
|
||||
xmergeinfo->m_ordering,
|
||||
xmergeinfo->jmethod.clauses,
|
||||
outerkeys,
|
||||
innerkeys);
|
||||
|
||||
ms_list = lappend(ms_list, temp_node);
|
||||
}
|
||||
@@ -268,9 +268,9 @@ sort_inner_and_outer(RelOptInfo *joinrel,
|
||||
* Returns a list of possible join path nodes.
|
||||
*/
|
||||
static List *
|
||||
match_unsorted_outer(RelOptInfo *joinrel,
|
||||
RelOptInfo *outerrel,
|
||||
RelOptInfo *innerrel,
|
||||
match_unsorted_outer(RelOptInfo * joinrel,
|
||||
RelOptInfo * outerrel,
|
||||
RelOptInfo * innerrel,
|
||||
List *outerpath_list,
|
||||
Path *cheapest_inner,
|
||||
Path *best_innerjoin,
|
||||
@@ -298,7 +298,7 @@ match_unsorted_outer(RelOptInfo *joinrel,
|
||||
|
||||
if (outerpath_ordering)
|
||||
xmergeinfo = match_order_mergeinfo(outerpath_ordering,
|
||||
mergeinfo_list);
|
||||
mergeinfo_list);
|
||||
|
||||
if (xmergeinfo)
|
||||
clauses = xmergeinfo->jmethod.clauses;
|
||||
@@ -308,13 +308,13 @@ match_unsorted_outer(RelOptInfo *joinrel,
|
||||
List *jmkeys = xmergeinfo->jmethod.jmkeys;
|
||||
|
||||
order_joinkeys_by_pathkeys(outerpath->pathkeys,
|
||||
jmkeys,
|
||||
clauses,
|
||||
OUTER,
|
||||
&matchedJoinKeys,
|
||||
&matchedJoinClauses);
|
||||
merge_pathkeys = new_join_pathkeys(outerpath->pathkeys,
|
||||
joinrel->targetlist, clauses);
|
||||
jmkeys,
|
||||
clauses,
|
||||
OUTER,
|
||||
&matchedJoinKeys,
|
||||
&matchedJoinClauses);
|
||||
merge_pathkeys = new_join_pathkeys(outerpath->pathkeys,
|
||||
joinrel->targetlist, clauses);
|
||||
}
|
||||
else
|
||||
merge_pathkeys = outerpath->pathkeys;
|
||||
@@ -338,21 +338,21 @@ match_unsorted_outer(RelOptInfo *joinrel,
|
||||
List *varkeys = NIL;
|
||||
Path *mergeinnerpath = get_cheapest_path_for_joinkeys(
|
||||
matchedJoinKeys,
|
||||
outerpath_ordering,
|
||||
innerrel->pathlist,
|
||||
INNER);
|
||||
outerpath_ordering,
|
||||
innerrel->pathlist,
|
||||
INNER);
|
||||
|
||||
/* Should we use the mergeinner, or sort the cheapest inner? */
|
||||
path_is_cheaper_than_sort = (bool) (mergeinnerpath &&
|
||||
(mergeinnerpath->path_cost <
|
||||
(cheapest_inner->path_cost +
|
||||
cost_sort(matchedJoinKeys, innerrel->size,
|
||||
innerrel->width))));
|
||||
(mergeinnerpath->path_cost <
|
||||
(cheapest_inner->path_cost +
|
||||
cost_sort(matchedJoinKeys, innerrel->size,
|
||||
innerrel->width))));
|
||||
if (!path_is_cheaper_than_sort)
|
||||
{
|
||||
varkeys = make_pathkeys_from_joinkeys(matchedJoinKeys,
|
||||
innerrel->targetlist,
|
||||
INNER);
|
||||
innerrel->targetlist,
|
||||
INNER);
|
||||
}
|
||||
|
||||
|
||||
@@ -368,18 +368,18 @@ match_unsorted_outer(RelOptInfo *joinrel,
|
||||
mergeinnerpath = cheapest_inner;
|
||||
|
||||
temp_node = lcons(create_mergejoin_path(joinrel,
|
||||
outerrel->size,
|
||||
innerrel->size,
|
||||
outerrel->width,
|
||||
innerrel->width,
|
||||
outerpath,
|
||||
mergeinnerpath,
|
||||
merge_pathkeys,
|
||||
xmergeinfo->m_ordering,
|
||||
matchedJoinClauses,
|
||||
NIL,
|
||||
varkeys),
|
||||
paths);
|
||||
outerrel->size,
|
||||
innerrel->size,
|
||||
outerrel->width,
|
||||
innerrel->width,
|
||||
outerpath,
|
||||
mergeinnerpath,
|
||||
merge_pathkeys,
|
||||
xmergeinfo->m_ordering,
|
||||
matchedJoinClauses,
|
||||
NIL,
|
||||
varkeys),
|
||||
paths);
|
||||
}
|
||||
else
|
||||
temp_node = paths;
|
||||
@@ -389,7 +389,7 @@ match_unsorted_outer(RelOptInfo *joinrel,
|
||||
}
|
||||
|
||||
/*
|
||||
* match_unsorted_inner
|
||||
* match_unsorted_inner
|
||||
* Find the cheapest ordered join path for a given(ordered, unsorted)
|
||||
* inner join path.
|
||||
*
|
||||
@@ -411,9 +411,9 @@ match_unsorted_outer(RelOptInfo *joinrel,
|
||||
* Returns a list of possible merge paths.
|
||||
*/
|
||||
static List *
|
||||
match_unsorted_inner(RelOptInfo *joinrel,
|
||||
RelOptInfo *outerrel,
|
||||
RelOptInfo *innerrel,
|
||||
match_unsorted_inner(RelOptInfo * joinrel,
|
||||
RelOptInfo * outerrel,
|
||||
RelOptInfo * innerrel,
|
||||
List *innerpath_list,
|
||||
List *mergeinfo_list)
|
||||
{
|
||||
@@ -441,11 +441,11 @@ match_unsorted_inner(RelOptInfo *joinrel,
|
||||
List *jmkeys = xmergeinfo->jmethod.jmkeys;
|
||||
|
||||
order_joinkeys_by_pathkeys(innerpath->pathkeys,
|
||||
jmkeys,
|
||||
clauses,
|
||||
INNER,
|
||||
&matchedJoinKeys,
|
||||
&matchedJoinClauses);
|
||||
jmkeys,
|
||||
clauses,
|
||||
INNER,
|
||||
&matchedJoinKeys,
|
||||
&matchedJoinClauses);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -459,29 +459,29 @@ match_unsorted_inner(RelOptInfo *joinrel,
|
||||
temp1 = outerrel->cheapestpath->path_cost +
|
||||
cost_sort(matchedJoinKeys, outerrel->size, outerrel->width);
|
||||
|
||||
if (innerpath->outerjoincost <= 0 /* unset? */
|
||||
if (innerpath->outerjoincost <= 0 /* unset? */
|
||||
|| innerpath->outerjoincost > temp1)
|
||||
{
|
||||
List *outerkeys = make_pathkeys_from_joinkeys(matchedJoinKeys,
|
||||
outerrel->targetlist,
|
||||
OUTER);
|
||||
outerrel->targetlist,
|
||||
OUTER);
|
||||
List *merge_pathkeys = new_join_pathkeys(outerkeys,
|
||||
joinrel->targetlist,
|
||||
clauses);
|
||||
joinrel->targetlist,
|
||||
clauses);
|
||||
|
||||
mp_list = lappend(mp_list,
|
||||
create_mergejoin_path(joinrel,
|
||||
outerrel->size,
|
||||
innerrel->size,
|
||||
outerrel->width,
|
||||
innerrel->width,
|
||||
outerrel->size,
|
||||
innerrel->size,
|
||||
outerrel->width,
|
||||
innerrel->width,
|
||||
(Path *) outerrel->cheapestpath,
|
||||
innerpath,
|
||||
merge_pathkeys,
|
||||
xmergeinfo->m_ordering,
|
||||
matchedJoinClauses,
|
||||
outerkeys,
|
||||
NIL));
|
||||
innerpath,
|
||||
merge_pathkeys,
|
||||
xmergeinfo->m_ordering,
|
||||
matchedJoinClauses,
|
||||
outerkeys,
|
||||
NIL));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -503,9 +503,9 @@ match_unsorted_inner(RelOptInfo *joinrel,
|
||||
* Returns a list of hashjoin paths.
|
||||
*/
|
||||
static List *
|
||||
hash_inner_and_outer(RelOptInfo *joinrel,
|
||||
RelOptInfo *outerrel,
|
||||
RelOptInfo *innerrel,
|
||||
hash_inner_and_outer(RelOptInfo * joinrel,
|
||||
RelOptInfo * outerrel,
|
||||
RelOptInfo * innerrel,
|
||||
List *hashinfo_list)
|
||||
{
|
||||
List *hjoin_list = NIL;
|
||||
@@ -520,20 +520,22 @@ hash_inner_and_outer(RelOptInfo *joinrel,
|
||||
HashPath *temp_node;
|
||||
|
||||
outerkeys = make_pathkeys_from_joinkeys(
|
||||
((JoinMethod *) xhashinfo)->jmkeys,
|
||||
outerrel->targetlist,
|
||||
OUTER);
|
||||
((JoinMethod *) xhashinfo)->jmkeys,
|
||||
outerrel->targetlist,
|
||||
OUTER);
|
||||
innerkeys = make_pathkeys_from_joinkeys(
|
||||
((JoinMethod *) xhashinfo)->jmkeys,
|
||||
innerrel->targetlist,
|
||||
INNER);
|
||||
/* We cannot assume that the output of the hashjoin appears in any
|
||||
((JoinMethod *) xhashinfo)->jmkeys,
|
||||
innerrel->targetlist,
|
||||
INNER);
|
||||
|
||||
/*
|
||||
* We cannot assume that the output of the hashjoin appears in any
|
||||
* particular order, so it should have NIL pathkeys.
|
||||
*/
|
||||
#ifdef NOT_USED
|
||||
hash_pathkeys = new_join_pathkeys(outerkeys,
|
||||
joinrel->targetlist,
|
||||
((JoinMethod *) xhashinfo)->clauses);
|
||||
joinrel->targetlist,
|
||||
((JoinMethod *) xhashinfo)->clauses);
|
||||
#else
|
||||
hash_pathkeys = NIL;
|
||||
#endif
|
||||
@@ -547,7 +549,7 @@ hash_inner_and_outer(RelOptInfo *joinrel,
|
||||
(Path *) innerrel->cheapestpath,
|
||||
hash_pathkeys,
|
||||
xhashinfo->hashop,
|
||||
((JoinMethod *) xhashinfo)->clauses,
|
||||
((JoinMethod *) xhashinfo)->clauses,
|
||||
outerkeys,
|
||||
innerkeys);
|
||||
hjoin_list = lappend(hjoin_list, temp_node);
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinrels.c,v 1.32 1999/02/22 06:08:48 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinrels.c,v 1.33 1999/05/25 16:09:26 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -26,8 +26,8 @@
|
||||
static List *new_joininfo_list(List *joininfo_list, Relids join_relids);
|
||||
static bool nonoverlap_sets(List *s1, List *s2);
|
||||
static bool is_subset(List *s1, List *s2);
|
||||
static void set_joinrel_size(RelOptInfo *joinrel, RelOptInfo *outer_rel,
|
||||
RelOptInfo *inner_rel, JoinInfo *jinfo);
|
||||
static void set_joinrel_size(RelOptInfo * joinrel, RelOptInfo * outer_rel,
|
||||
RelOptInfo * inner_rel, JoinInfo * jinfo);
|
||||
|
||||
/*
|
||||
* make_rels_by_joins
|
||||
@@ -52,18 +52,19 @@ make_rels_by_joins(Query *root, List *old_rels)
|
||||
RelOptInfo *old_rel = (RelOptInfo *) lfirst(r);
|
||||
|
||||
if (!(joined_rels = make_rels_by_clause_joins(root, old_rel,
|
||||
old_rel->joininfo,
|
||||
NIL)))
|
||||
old_rel->joininfo,
|
||||
NIL)))
|
||||
{
|
||||
|
||||
/*
|
||||
* Oops, we have a relation that is not joined to any other
|
||||
* relation. Cartesian product time.
|
||||
*/
|
||||
joined_rels = make_rels_by_clauseless_joins(old_rel,
|
||||
root->base_rel_list);
|
||||
root->base_rel_list);
|
||||
joined_rels = nconc(joined_rels,
|
||||
make_rels_by_clauseless_joins(old_rel,
|
||||
old_rels));
|
||||
old_rels));
|
||||
}
|
||||
|
||||
join_list = nconc(join_list, joined_rels);
|
||||
@@ -88,14 +89,14 @@ make_rels_by_joins(Query *root, List *old_rels)
|
||||
* Returns a list of new join relations.
|
||||
*/
|
||||
List *
|
||||
make_rels_by_clause_joins(Query *root, RelOptInfo *old_rel,
|
||||
List *joininfo_list, Relids only_relids)
|
||||
make_rels_by_clause_joins(Query *root, RelOptInfo * old_rel,
|
||||
List *joininfo_list, Relids only_relids)
|
||||
{
|
||||
List *join_list = NIL;
|
||||
List *i = NIL;
|
||||
|
||||
foreach(i, joininfo_list)
|
||||
{
|
||||
{
|
||||
JoinInfo *joininfo = (JoinInfo *) lfirst(i);
|
||||
RelOptInfo *joined_rel;
|
||||
Relids unjoined_relids = joininfo->unjoined_relids;
|
||||
@@ -104,29 +105,29 @@ make_rels_by_clause_joins(Query *root, RelOptInfo *old_rel,
|
||||
{
|
||||
if (length(unjoined_relids) == 1 &&
|
||||
(only_relids == NIL ||
|
||||
/* geqo only wants certain relids to make new rels */
|
||||
/* geqo only wants certain relids to make new rels */
|
||||
intMember(lfirsti(unjoined_relids), only_relids)))
|
||||
{
|
||||
joined_rel = make_join_rel(old_rel,
|
||||
get_base_rel(root,
|
||||
lfirsti(unjoined_relids)),
|
||||
joininfo);
|
||||
get_base_rel(root,
|
||||
lfirsti(unjoined_relids)),
|
||||
joininfo);
|
||||
join_list = lappend(join_list, joined_rel);
|
||||
|
||||
/* Right-sided plan */
|
||||
if (length(old_rel->relids) > 1)
|
||||
{
|
||||
joined_rel = make_join_rel(
|
||||
get_base_rel(root, lfirsti(unjoined_relids)),
|
||||
old_rel,
|
||||
joininfo);
|
||||
get_base_rel(root, lfirsti(unjoined_relids)),
|
||||
old_rel,
|
||||
joininfo);
|
||||
join_list = lappend(join_list, joined_rel);
|
||||
}
|
||||
}
|
||||
|
||||
if (only_relids == NIL) /* no bushy from geqo */
|
||||
if (only_relids == NIL) /* no bushy from geqo */
|
||||
{
|
||||
List *r;
|
||||
List *r;
|
||||
|
||||
foreach(r, root->join_rel_list)
|
||||
{
|
||||
@@ -134,11 +135,11 @@ make_rels_by_clause_joins(Query *root, RelOptInfo *old_rel,
|
||||
|
||||
Assert(length(join_rel->relids) > 1);
|
||||
if (is_subset(unjoined_relids, join_rel->relids) &&
|
||||
nonoverlap_sets(old_rel->relids, join_rel->relids))
|
||||
nonoverlap_sets(old_rel->relids, join_rel->relids))
|
||||
{
|
||||
joined_rel = make_join_rel(old_rel,
|
||||
join_rel,
|
||||
joininfo);
|
||||
join_rel,
|
||||
joininfo);
|
||||
join_list = lappend(join_list, joined_rel);
|
||||
}
|
||||
}
|
||||
@@ -158,7 +159,7 @@ make_rels_by_clause_joins(Query *root, RelOptInfo *old_rel,
|
||||
* Returns a list of new join relations.
|
||||
*/
|
||||
List *
|
||||
make_rels_by_clauseless_joins(RelOptInfo *old_rel, List *inner_rels)
|
||||
make_rels_by_clauseless_joins(RelOptInfo * old_rel, List *inner_rels)
|
||||
{
|
||||
RelOptInfo *inner_rel;
|
||||
List *t_list = NIL;
|
||||
@@ -191,7 +192,7 @@ make_rels_by_clauseless_joins(RelOptInfo *old_rel, List *inner_rels)
|
||||
* Returns the new join relation node.
|
||||
*/
|
||||
RelOptInfo *
|
||||
make_join_rel(RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinInfo *joininfo)
|
||||
make_join_rel(RelOptInfo * outer_rel, RelOptInfo * inner_rel, JoinInfo * joininfo)
|
||||
{
|
||||
RelOptInfo *joinrel = makeNode(RelOptInfo);
|
||||
List *joinrel_joininfo_list = NIL;
|
||||
@@ -203,7 +204,7 @@ make_join_rel(RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinInfo *joininfo)
|
||||
* of the outer and inner join relations and then merging the results
|
||||
* together.
|
||||
*/
|
||||
new_outer_tlist = new_join_tlist(outer_rel->targetlist, 1);
|
||||
new_outer_tlist = new_join_tlist(outer_rel->targetlist, 1);
|
||||
new_inner_tlist = new_join_tlist(inner_rel->targetlist,
|
||||
length(new_outer_tlist) + 1);
|
||||
|
||||
@@ -224,8 +225,8 @@ make_join_rel(RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinInfo *joininfo)
|
||||
joinrel->innerjoin = NIL;
|
||||
|
||||
/*
|
||||
* This function uses a trick to pass inner/outer rels as
|
||||
* different lists, and then flattens it out later. bjm
|
||||
* This function uses a trick to pass inner/outer rels as different
|
||||
* lists, and then flattens it out later. bjm
|
||||
*/
|
||||
joinrel->relids = lcons(outer_rel->relids, lcons(inner_rel->relids, NIL));
|
||||
|
||||
@@ -236,10 +237,10 @@ make_join_rel(RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinInfo *joininfo)
|
||||
joinrel->restrictinfo = joininfo->jinfo_restrictinfo;
|
||||
|
||||
joinrel_joininfo_list = new_joininfo_list(
|
||||
nconc(copyObject(outer_rel->joininfo),
|
||||
copyObject(inner_rel->joininfo)),
|
||||
nconc(listCopy(outer_rel->relids),
|
||||
listCopy(inner_rel->relids)));
|
||||
nconc(copyObject(outer_rel->joininfo),
|
||||
copyObject(inner_rel->joininfo)),
|
||||
nconc(listCopy(outer_rel->relids),
|
||||
listCopy(inner_rel->relids)));
|
||||
|
||||
joinrel->joininfo = joinrel_joininfo_list;
|
||||
|
||||
@@ -278,12 +279,16 @@ new_join_tlist(List *tlist,
|
||||
foreach(i, tlist)
|
||||
{
|
||||
xtl = lfirst(i);
|
||||
/* XXX surely this is wrong? join_list is never changed? tgl 2/99 */
|
||||
|
||||
/*
|
||||
* XXX surely this is wrong? join_list is never changed? tgl
|
||||
* 2/99
|
||||
*/
|
||||
in_final_tlist = (join_list == NIL);
|
||||
if (in_final_tlist)
|
||||
{
|
||||
resdomno += 1;
|
||||
t_list = lappend(t_list,create_tl_element(get_expr(xtl), resdomno));
|
||||
t_list = lappend(t_list, create_tl_element(get_expr(xtl), resdomno));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,8 +340,8 @@ new_joininfo_list(List *joininfo_list, Relids join_relids)
|
||||
if (other_joininfo)
|
||||
{
|
||||
other_joininfo->jinfo_restrictinfo = (List *)
|
||||
LispUnion(joininfo->jinfo_restrictinfo,
|
||||
other_joininfo->jinfo_restrictinfo);
|
||||
LispUnion(joininfo->jinfo_restrictinfo,
|
||||
other_joininfo->jinfo_restrictinfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -393,7 +398,7 @@ get_cheapest_complete_rel(List *join_rel_list)
|
||||
}
|
||||
if (final)
|
||||
if (final_rel == NULL ||
|
||||
path_is_cheaper(rel->cheapestpath, final_rel->cheapestpath))
|
||||
path_is_cheaper(rel->cheapestpath, final_rel->cheapestpath))
|
||||
final_rel = rel;
|
||||
}
|
||||
|
||||
@@ -431,7 +436,7 @@ is_subset(List *s1, List *s2)
|
||||
}
|
||||
|
||||
static void
|
||||
set_joinrel_size(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinInfo *jinfo)
|
||||
set_joinrel_size(RelOptInfo * joinrel, RelOptInfo * outer_rel, RelOptInfo * inner_rel, JoinInfo * jinfo)
|
||||
{
|
||||
int ntuples;
|
||||
float selec;
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/mergeutils.c,v 1.21 1999/04/03 00:18:28 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/mergeutils.c,v 1.22 1999/05/25 16:09:27 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -37,7 +37,7 @@
|
||||
*
|
||||
* 'restrictinfo_list' is the list of restrictinfo nodes
|
||||
* 'inner_relids' is the list of relids in the inner join relation
|
||||
* (used to determine whether a join var is inner or outer)
|
||||
* (used to determine whether a join var is inner or outer)
|
||||
*
|
||||
* Returns the new list of mergeinfo nodes.
|
||||
*
|
||||
@@ -56,6 +56,7 @@ group_clauses_by_order(List *restrictinfo_list,
|
||||
|
||||
if (merge_ordering)
|
||||
{
|
||||
|
||||
/*
|
||||
* Create a new mergeinfo node and add it to 'mergeinfo_list'
|
||||
* if one does not yet exist for this merge ordering.
|
||||
@@ -63,8 +64,8 @@ group_clauses_by_order(List *restrictinfo_list,
|
||||
Expr *clause = restrictinfo->clause;
|
||||
Var *leftop = get_leftop(clause);
|
||||
Var *rightop = get_rightop(clause);
|
||||
PathOrder *pathorder;
|
||||
MergeInfo *xmergeinfo;
|
||||
PathOrder *pathorder;
|
||||
MergeInfo *xmergeinfo;
|
||||
JoinKey *jmkeys;
|
||||
|
||||
pathorder = makeNode(PathOrder);
|
||||
@@ -91,9 +92,9 @@ group_clauses_by_order(List *restrictinfo_list,
|
||||
}
|
||||
|
||||
xmergeinfo->jmethod.clauses = lcons(clause,
|
||||
xmergeinfo->jmethod.clauses);
|
||||
xmergeinfo->jmethod.clauses);
|
||||
xmergeinfo->jmethod.jmkeys = lcons(jmkeys,
|
||||
xmergeinfo->jmethod.jmkeys);
|
||||
xmergeinfo->jmethod.jmkeys);
|
||||
}
|
||||
}
|
||||
return mergeinfo_list;
|
||||
@@ -108,7 +109,7 @@ group_clauses_by_order(List *restrictinfo_list,
|
||||
* Returns the node if it exists.
|
||||
*
|
||||
*/
|
||||
MergeInfo *
|
||||
MergeInfo *
|
||||
match_order_mergeinfo(PathOrder *ordering, List *mergeinfo_list)
|
||||
{
|
||||
MergeOrder *xmergeorder;
|
||||
@@ -116,12 +117,12 @@ match_order_mergeinfo(PathOrder *ordering, List *mergeinfo_list)
|
||||
|
||||
foreach(xmergeinfo, mergeinfo_list)
|
||||
{
|
||||
MergeInfo *mergeinfo = (MergeInfo *) lfirst(xmergeinfo);
|
||||
MergeInfo *mergeinfo = (MergeInfo *) lfirst(xmergeinfo);
|
||||
|
||||
xmergeorder = mergeinfo->m_ordering;
|
||||
|
||||
if ((ordering->ordtype == MERGE_ORDER &&
|
||||
equal_merge_ordering(ordering->ord.merge, xmergeorder)) ||
|
||||
equal_merge_ordering(ordering->ord.merge, xmergeorder)) ||
|
||||
(ordering->ordtype == SORTOP_ORDER &&
|
||||
equal_path_merge_ordering(ordering->ord.sortop, xmergeorder)))
|
||||
{
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/orindxpath.c,v 1.23 1999/03/08 14:01:55 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/orindxpath.c,v 1.24 1999/05/25 16:09:27 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -31,10 +31,9 @@
|
||||
#include "parser/parsetree.h"
|
||||
|
||||
|
||||
static void
|
||||
best_or_subclause_indices(Query *root, RelOptInfo *rel, List *subclauses,
|
||||
List *indices, List **indexids, Cost *cost, Cost *selec);
|
||||
static void best_or_subclause_index(Query *root, RelOptInfo *rel, Expr *subclause,
|
||||
static void best_or_subclause_indices(Query *root, RelOptInfo * rel, List *subclauses,
|
||||
List *indices, List **indexids, Cost *cost, Cost *selec);
|
||||
static void best_or_subclause_index(Query *root, RelOptInfo * rel, Expr *subclause,
|
||||
List *indices, int *indexid, Cost *cost, Cost *selec);
|
||||
|
||||
|
||||
@@ -50,7 +49,7 @@ static void best_or_subclause_index(Query *root, RelOptInfo *rel, Expr *subclaus
|
||||
*/
|
||||
List *
|
||||
create_or_index_paths(Query *root,
|
||||
RelOptInfo *rel, List *clauses)
|
||||
RelOptInfo * rel, List *clauses)
|
||||
{
|
||||
List *t_list = NIL;
|
||||
List *clist;
|
||||
@@ -88,7 +87,7 @@ create_or_index_paths(Query *root,
|
||||
IndexPath *pathnode = makeNode(IndexPath);
|
||||
List *indexids = NIL;
|
||||
Cost cost;
|
||||
Cost selec;
|
||||
Cost selec;
|
||||
|
||||
best_or_subclause_indices(root,
|
||||
rel,
|
||||
@@ -101,14 +100,15 @@ create_or_index_paths(Query *root,
|
||||
pathnode->path.pathtype = T_IndexScan;
|
||||
pathnode->path.parent = rel;
|
||||
pathnode->path.pathorder = makeNode(PathOrder);
|
||||
pathnode->path.pathorder->ordtype = SORTOP_ORDER;
|
||||
/*
|
||||
* This is an IndexScan, but it does index lookups based
|
||||
* on the order of the fields specified in the WHERE clause,
|
||||
* not in any order, so the sortop is NULL.
|
||||
pathnode->path.pathorder->ordtype = SORTOP_ORDER;
|
||||
|
||||
/*
|
||||
* This is an IndexScan, but it does index lookups based
|
||||
* on the order of the fields specified in the WHERE
|
||||
* clause, not in any order, so the sortop is NULL.
|
||||
*/
|
||||
pathnode->path.pathorder->ord.sortop = NULL;
|
||||
pathnode->path.pathkeys = NIL;
|
||||
pathnode->path.pathorder->ord.sortop = NULL;
|
||||
pathnode->path.pathkeys = NIL;
|
||||
|
||||
pathnode->indexqual = lcons(clausenode, NIL);
|
||||
pathnode->indexid = indexids;
|
||||
@@ -119,14 +119,12 @@ create_or_index_paths(Query *root,
|
||||
* processing -- JMH, 7/7/92
|
||||
*/
|
||||
pathnode->path.loc_restrictinfo = set_difference(copyObject((Node *) rel->restrictinfo),
|
||||
lcons(clausenode, NIL));
|
||||
lcons(clausenode, NIL));
|
||||
|
||||
#ifdef NOT_USED /* fix xfunc */
|
||||
#ifdef NOT_USED /* fix xfunc */
|
||||
/* add in cost for expensive functions! -- JMH, 7/7/92 */
|
||||
if (XfuncMode != XFUNC_OFF)
|
||||
{
|
||||
((Path *) pathnode)->path_cost += xfunc_get_path_cost((Path) pathnode);
|
||||
}
|
||||
#endif
|
||||
clausenode->selectivity = (Cost) selec;
|
||||
t_list = lappend(t_list, pathnode);
|
||||
@@ -158,18 +156,18 @@ create_or_index_paths(Query *root,
|
||||
*/
|
||||
static void
|
||||
best_or_subclause_indices(Query *root,
|
||||
RelOptInfo *rel,
|
||||
RelOptInfo * rel,
|
||||
List *subclauses,
|
||||
List *indices,
|
||||
List **indexids, /* return value */
|
||||
Cost *cost, /* return value */
|
||||
Cost *selec) /* return value */
|
||||
Cost *cost, /* return value */
|
||||
Cost *selec) /* return value */
|
||||
{
|
||||
List *slist;
|
||||
List *slist;
|
||||
|
||||
*selec = (Cost) 0.0;
|
||||
*cost = (Cost) 0.0;
|
||||
|
||||
|
||||
foreach(slist, subclauses)
|
||||
{
|
||||
int best_indexid;
|
||||
@@ -207,7 +205,7 @@ best_or_subclause_indices(Query *root,
|
||||
*/
|
||||
static void
|
||||
best_or_subclause_index(Query *root,
|
||||
RelOptInfo *rel,
|
||||
RelOptInfo * rel,
|
||||
Expr *subclause,
|
||||
List *indices,
|
||||
int *retIndexid, /* return value */
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.9 1999/05/17 00:26:33 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.10 1999/05/25 16:09:28 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -26,9 +26,9 @@
|
||||
#include "optimizer/ordering.h"
|
||||
|
||||
static int match_pathkey_joinkeys(List *pathkey, List *joinkeys,
|
||||
int outer_or_inner);
|
||||
int outer_or_inner);
|
||||
static List *new_join_pathkey(List *pathkeys, List *join_rel_tlist,
|
||||
List *joinclauses);
|
||||
List *joinclauses);
|
||||
|
||||
|
||||
/*--------------------
|
||||
@@ -41,7 +41,7 @@ static List *new_join_pathkey(List *pathkeys, List *join_rel_tlist,
|
||||
* of generating the relation and the resulting ordering of the tuples.
|
||||
* Sequential scan Paths have NIL pathkeys, indicating no known ordering.
|
||||
* Index scans have Path.pathkeys that represent the chosen index.
|
||||
* A single-key index pathkeys would be { {tab1_indexkey1} }. For a
|
||||
* A single-key index pathkeys would be { {tab1_indexkey1} }. For a
|
||||
* multi-key index pathkeys would be { {tab1_indexkey1}, {tab1_indexkey2} },
|
||||
* indicating major sort by indexkey1 and minor sort by indexkey2.
|
||||
*
|
||||
@@ -70,12 +70,12 @@ static List *new_join_pathkey(List *pathkeys, List *join_rel_tlist,
|
||||
* executor might have to split the join into multiple batches.
|
||||
*
|
||||
* NestJoin does not perform sorting, and allows non-equijoins, so it does
|
||||
* not allow useful pathkeys. (But couldn't we use the outer path's order?)
|
||||
* not allow useful pathkeys. (But couldn't we use the outer path's order?)
|
||||
*
|
||||
* -- bjm
|
||||
*--------------------
|
||||
*/
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* KEY COMPARISONS
|
||||
****************************************************************************/
|
||||
@@ -111,11 +111,11 @@ static List *new_join_pathkey(List *pathkeys, List *join_rel_tlist,
|
||||
*/
|
||||
bool
|
||||
order_joinkeys_by_pathkeys(List *pathkeys,
|
||||
List *joinkeys,
|
||||
List *joinclauses,
|
||||
int outer_or_inner,
|
||||
List **matchedJoinKeysPtr,
|
||||
List **matchedJoinClausesPtr)
|
||||
List *joinkeys,
|
||||
List *joinclauses,
|
||||
int outer_or_inner,
|
||||
List **matchedJoinKeysPtr,
|
||||
List **matchedJoinClausesPtr)
|
||||
{
|
||||
List *matched_joinkeys = NIL;
|
||||
List *matched_joinclauses = NIL;
|
||||
@@ -123,9 +123,10 @@ order_joinkeys_by_pathkeys(List *pathkeys,
|
||||
List *i = NIL;
|
||||
int matched_joinkey_index = -1;
|
||||
int matched_keys = 0;
|
||||
|
||||
/*
|
||||
* Reorder the joinkeys by picking out one that matches each pathkey,
|
||||
* and create a new joinkey/joinclause list in pathkey order
|
||||
* Reorder the joinkeys by picking out one that matches each pathkey,
|
||||
* and create a new joinkey/joinclause list in pathkey order
|
||||
*/
|
||||
foreach(i, pathkeys)
|
||||
{
|
||||
@@ -138,34 +139,36 @@ order_joinkeys_by_pathkeys(List *pathkeys,
|
||||
matched_keys++;
|
||||
if (matchedJoinKeysPtr)
|
||||
{
|
||||
JoinKey *joinkey = nth(matched_joinkey_index, joinkeys);
|
||||
JoinKey *joinkey = nth(matched_joinkey_index, joinkeys);
|
||||
|
||||
matched_joinkeys = lappend(matched_joinkeys, joinkey);
|
||||
}
|
||||
|
||||
|
||||
if (matchedJoinClausesPtr)
|
||||
{
|
||||
Expr *joinclause = nth(matched_joinkey_index,
|
||||
joinclauses);
|
||||
|
||||
Assert(joinclauses);
|
||||
matched_joinclauses = lappend(matched_joinclauses, joinclause);
|
||||
}
|
||||
}
|
||||
else
|
||||
/* A pathkey could not be matched. */
|
||||
/* A pathkey could not be matched. */
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Did we fail to match all the joinkeys?
|
||||
* Extra pathkeys are no problem.
|
||||
* Did we fail to match all the joinkeys? Extra pathkeys are no
|
||||
* problem.
|
||||
*/
|
||||
if (matched_keys != length(joinkeys))
|
||||
{
|
||||
if (matchedJoinKeysPtr)
|
||||
*matchedJoinKeysPtr = NIL;
|
||||
if (matchedJoinClausesPtr)
|
||||
*matchedJoinClausesPtr = NIL;
|
||||
return false;
|
||||
if (matchedJoinKeysPtr)
|
||||
*matchedJoinKeysPtr = NIL;
|
||||
if (matchedJoinClausesPtr)
|
||||
*matchedJoinClausesPtr = NIL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (matchedJoinKeysPtr)
|
||||
@@ -190,7 +193,8 @@ match_pathkey_joinkeys(List *pathkey,
|
||||
{
|
||||
Var *key;
|
||||
int pos;
|
||||
List *i, *x;
|
||||
List *i,
|
||||
*x;
|
||||
JoinKey *jk;
|
||||
|
||||
foreach(i, pathkey)
|
||||
@@ -232,9 +236,9 @@ match_pathkey_joinkeys(List *pathkey,
|
||||
*/
|
||||
Path *
|
||||
get_cheapest_path_for_joinkeys(List *joinkeys,
|
||||
PathOrder *ordering,
|
||||
List *paths,
|
||||
int outer_or_inner)
|
||||
PathOrder *ordering,
|
||||
List *paths,
|
||||
int outer_or_inner)
|
||||
{
|
||||
Path *matched_path = NULL;
|
||||
List *i;
|
||||
@@ -243,7 +247,7 @@ get_cheapest_path_for_joinkeys(List *joinkeys,
|
||||
{
|
||||
Path *path = (Path *) lfirst(i);
|
||||
int better_sort;
|
||||
|
||||
|
||||
if (order_joinkeys_by_pathkeys(path->pathkeys, joinkeys, NIL,
|
||||
outer_or_inner, NULL, NULL) &&
|
||||
pathorder_match(ordering, path->pathorder, &better_sort) &&
|
||||
@@ -274,8 +278,8 @@ get_cheapest_path_for_joinkeys(List *joinkeys,
|
||||
*/
|
||||
List *
|
||||
make_pathkeys_from_joinkeys(List *joinkeys,
|
||||
List *tlist,
|
||||
int outer_or_inner)
|
||||
List *tlist,
|
||||
int outer_or_inner)
|
||||
{
|
||||
List *pathkeys = NIL;
|
||||
List *jk;
|
||||
@@ -284,7 +288,8 @@ make_pathkeys_from_joinkeys(List *joinkeys,
|
||||
{
|
||||
JoinKey *jkey = (JoinKey *) lfirst(jk);
|
||||
Var *key;
|
||||
List *p, *p2;
|
||||
List *p,
|
||||
*p2;
|
||||
bool found = false;
|
||||
|
||||
key = (Var *) extract_join_key(jkey, outer_or_inner);
|
||||
@@ -292,17 +297,19 @@ make_pathkeys_from_joinkeys(List *joinkeys,
|
||||
/* check to see if it is in the target list */
|
||||
if (matching_tlist_var(key, tlist))
|
||||
{
|
||||
|
||||
/*
|
||||
* Include it in the pathkeys list if we haven't already done so
|
||||
* Include it in the pathkeys list if we haven't already done
|
||||
* so
|
||||
*/
|
||||
foreach(p, pathkeys)
|
||||
{
|
||||
List *pathkey = lfirst(p);
|
||||
|
||||
|
||||
foreach(p2, pathkey)
|
||||
{
|
||||
Var *pkey = lfirst(p2);
|
||||
|
||||
|
||||
if (equal(key, pkey))
|
||||
{
|
||||
found = true;
|
||||
@@ -371,7 +378,7 @@ new_join_pathkeys(List *outer_pathkeys,
|
||||
*
|
||||
* Note that each returned pathkey is the var node found in
|
||||
* 'join_rel_tlist' rather than the joinclause var node.
|
||||
* (Is this important?) Also, we return a fully copied list
|
||||
* (Is this important?) Also, we return a fully copied list
|
||||
* that does not share any subnodes with existing data structures.
|
||||
* (Is that important, either?)
|
||||
*
|
||||
@@ -393,7 +400,7 @@ new_join_pathkey(List *pathkey,
|
||||
Expr *tlist_key;
|
||||
|
||||
Assert(key);
|
||||
|
||||
|
||||
tlist_key = matching_tlist_var(key, join_rel_tlist);
|
||||
if (tlist_key && !member(tlist_key, new_pathkey))
|
||||
new_pathkey = lcons(copyObject(tlist_key), new_pathkey);
|
||||
@@ -404,8 +411,8 @@ new_join_pathkey(List *pathkey,
|
||||
Expr *tlist_other_var;
|
||||
|
||||
tlist_other_var = matching_tlist_var(
|
||||
other_join_clause_var(key, joinclause),
|
||||
join_rel_tlist);
|
||||
other_join_clause_var(key, joinclause),
|
||||
join_rel_tlist);
|
||||
if (tlist_other_var && !member(tlist_other_var, new_pathkey))
|
||||
new_pathkey = lcons(copyObject(tlist_other_var), new_pathkey);
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/prune.c,v 1.37 1999/02/18 00:49:21 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/prune.c,v 1.38 1999/05/25 16:09:28 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "utils/elog.h"
|
||||
|
||||
|
||||
static List *merge_rel_with_same_relids(RelOptInfo *rel, Relids unjoined_relids);
|
||||
static List *merge_rel_with_same_relids(RelOptInfo * rel, Relids unjoined_relids);
|
||||
|
||||
/*
|
||||
* merge_rels_with_same_relids
|
||||
@@ -59,7 +59,7 @@ merge_rels_with_same_relids(List *rel_list)
|
||||
*
|
||||
*/
|
||||
static List *
|
||||
merge_rel_with_same_relids(RelOptInfo *rel, Relids unjoined_relids)
|
||||
merge_rel_with_same_relids(RelOptInfo * rel, Relids unjoined_relids)
|
||||
{
|
||||
List *i = NIL;
|
||||
List *result = NIL;
|
||||
@@ -69,9 +69,10 @@ merge_rel_with_same_relids(RelOptInfo *rel, Relids unjoined_relids)
|
||||
RelOptInfo *unjoined_rel = (RelOptInfo *) lfirst(i);
|
||||
|
||||
if (same(rel->relids, unjoined_rel->relids))
|
||||
|
||||
/*
|
||||
* This are on the same relations,
|
||||
* so get the best of their pathlists.
|
||||
* This are on the same relations, so get the best of their
|
||||
* pathlists.
|
||||
*/
|
||||
rel->pathlist = add_pathlist(rel,
|
||||
rel->pathlist,
|
||||
@@ -92,7 +93,7 @@ rels_set_cheapest(List *rel_list)
|
||||
{
|
||||
List *x = NIL;
|
||||
RelOptInfo *rel = (RelOptInfo *) NULL;
|
||||
JoinPath *cheapest;
|
||||
JoinPath *cheapest;
|
||||
|
||||
foreach(x, rel_list)
|
||||
{
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.55 1999/05/18 21:34:29 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.56 1999/05/25 16:09:34 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -42,18 +42,18 @@
|
||||
|
||||
|
||||
#define NONAME_SORT 1
|
||||
#define NONAME_MATERIAL 2
|
||||
#define NONAME_MATERIAL 2
|
||||
|
||||
static List *switch_outer(List *clauses);
|
||||
static Oid *generate_merge_input_sortorder(List *pathkeys,
|
||||
MergeOrder *mergeorder);
|
||||
MergeOrder *mergeorder);
|
||||
static Scan *create_scan_node(Path *best_path, List *tlist);
|
||||
static Join *create_join_node(JoinPath *best_path, List *tlist);
|
||||
static SeqScan *create_seqscan_node(Path *best_path, List *tlist,
|
||||
List *scan_clauses);
|
||||
static IndexScan *create_indexscan_node(IndexPath *best_path, List *tlist,
|
||||
List *scan_clauses);
|
||||
static NestLoop *create_nestloop_node(NestPath *best_path, List *tlist,
|
||||
static NestLoop *create_nestloop_node(NestPath * best_path, List *tlist,
|
||||
List *clauses, Plan *outer_node, List *outer_tlist,
|
||||
Plan *inner_node, List *inner_tlist);
|
||||
static MergeJoin *create_mergejoin_node(MergePath *best_path, List *tlist,
|
||||
@@ -64,7 +64,7 @@ static HashJoin *create_hashjoin_node(HashPath *best_path, List *tlist,
|
||||
Plan *inner_node, List *inner_tlist);
|
||||
static Node *fix_indxqual_references(Node *clause, Path *index_path);
|
||||
static Noname *make_noname(List *tlist, List *pathkeys, Oid *operators,
|
||||
Plan *plan_node, int nonametype);
|
||||
Plan *plan_node, int nonametype);
|
||||
static IndexScan *make_indexscan(List *qptlist, List *qpqual, Index scanrelid,
|
||||
List *indxid, List *indxqual, List *indxqualorig);
|
||||
static NestLoop *make_nestloop(List *qptlist, List *qpqual, Plan *lefttree,
|
||||
@@ -133,7 +133,7 @@ create_plan(Path *best_path)
|
||||
pages = 1;
|
||||
plan_node->plan_tupperpage = tuples / pages;
|
||||
|
||||
#ifdef NOT_USED /* fix xfunc */
|
||||
#ifdef NOT_USED /* fix xfunc */
|
||||
/* sort clauses by cost/(1-selectivity) -- JMH 2/26/92 */
|
||||
if (XfuncMode != XFUNC_OFF)
|
||||
{
|
||||
@@ -197,7 +197,7 @@ create_scan_node(Path *best_path, List *tlist)
|
||||
}
|
||||
|
||||
/*
|
||||
* create_join_node
|
||||
* create_join_node
|
||||
* Create a join path for 'best_path' and(recursively) paths for its
|
||||
* inner and outer paths.
|
||||
*
|
||||
@@ -263,7 +263,7 @@ create_join_node(JoinPath *best_path, List *tlist)
|
||||
|
||||
/*
|
||||
* * Expensive function pullups may have pulled local predicates *
|
||||
* into this path node. Put them in the qpqual of the plan node. *
|
||||
* into this path node. Put them in the qpqual of the plan node. *
|
||||
* JMH, 6/15/92
|
||||
*/
|
||||
if (get_loc_restrictinfo(best_path) != NIL)
|
||||
@@ -400,11 +400,11 @@ create_indexscan_node(IndexPath *best_path,
|
||||
fixed_indxqual = (List *) fix_indxqual_references((Node *) indxqual, (Path *) best_path);
|
||||
|
||||
scan_node = make_indexscan(tlist,
|
||||
qpqual,
|
||||
lfirsti(best_path->path.parent->relids),
|
||||
best_path->indexid,
|
||||
fixed_indxqual,
|
||||
indxqual);
|
||||
qpqual,
|
||||
lfirsti(best_path->path.parent->relids),
|
||||
best_path->indexid,
|
||||
fixed_indxqual,
|
||||
indxqual);
|
||||
|
||||
scan_node->scan.plan.cost = best_path->path.path_cost;
|
||||
|
||||
@@ -418,7 +418,7 @@ create_indexscan_node(IndexPath *best_path,
|
||||
*****************************************************************************/
|
||||
|
||||
static NestLoop *
|
||||
create_nestloop_node(NestPath *best_path,
|
||||
create_nestloop_node(NestPath * best_path,
|
||||
List *tlist,
|
||||
List *clauses,
|
||||
Plan *outer_node,
|
||||
@@ -471,7 +471,7 @@ create_nestloop_node(NestPath *best_path,
|
||||
|
||||
clauses = set_difference(clauses, inner_indxqual); /* XXX */
|
||||
new_inner_qual = index_outerjoin_references(inner_indxqual,
|
||||
outer_node->targetlist,
|
||||
outer_node->targetlist,
|
||||
((Scan *) inner_node)->scanrelid);
|
||||
((IndexScan *) inner_node)->indxqual = lcons(new_inner_qual, NIL);
|
||||
}
|
||||
@@ -479,10 +479,10 @@ create_nestloop_node(NestPath *best_path,
|
||||
else if (IsA_Join(inner_node))
|
||||
{
|
||||
inner_node = (Plan *) make_noname(inner_tlist,
|
||||
NIL,
|
||||
NULL,
|
||||
inner_node,
|
||||
NONAME_MATERIAL);
|
||||
NIL,
|
||||
NULL,
|
||||
inner_node,
|
||||
NONAME_MATERIAL);
|
||||
}
|
||||
|
||||
join_node = make_nestloop(tlist,
|
||||
@@ -535,8 +535,9 @@ create_mergejoin_node(MergePath *best_path,
|
||||
if (best_path->outersortkeys)
|
||||
{
|
||||
Oid *outer_order = generate_merge_input_sortorder(
|
||||
best_path->outersortkeys,
|
||||
best_path->jpath.path.pathorder->ord.merge);
|
||||
best_path->outersortkeys,
|
||||
best_path->jpath.path.pathorder->ord.merge);
|
||||
|
||||
outer_node = (Plan *) make_noname(outer_tlist,
|
||||
best_path->outersortkeys,
|
||||
outer_order,
|
||||
@@ -547,8 +548,9 @@ create_mergejoin_node(MergePath *best_path,
|
||||
if (best_path->innersortkeys)
|
||||
{
|
||||
Oid *inner_order = generate_merge_input_sortorder(
|
||||
best_path->innersortkeys,
|
||||
best_path->jpath.path.pathorder->ord.merge);
|
||||
best_path->innersortkeys,
|
||||
best_path->jpath.path.pathorder->ord.merge);
|
||||
|
||||
inner_node = (Plan *) make_noname(inner_tlist,
|
||||
best_path->innersortkeys,
|
||||
inner_order,
|
||||
@@ -595,17 +597,17 @@ create_hashjoin_node(HashPath *best_path,
|
||||
* and set those clauses to contain references to lower attributes.
|
||||
*/
|
||||
qpqual = join_references(set_difference(clauses,
|
||||
best_path->path_hashclauses),
|
||||
outer_tlist,
|
||||
inner_tlist);
|
||||
best_path->path_hashclauses),
|
||||
outer_tlist,
|
||||
inner_tlist);
|
||||
|
||||
/*
|
||||
* Now set the references in the hashclauses and rearrange them so
|
||||
* that the outer variable is always on the left.
|
||||
*/
|
||||
hashclauses = switch_outer(join_references(best_path->path_hashclauses,
|
||||
outer_tlist,
|
||||
inner_tlist));
|
||||
outer_tlist,
|
||||
inner_tlist));
|
||||
|
||||
innerhashkey = get_rightop(lfirst(hashclauses));
|
||||
|
||||
@@ -671,20 +673,22 @@ fix_indxqual_references(Node *clause, Path *index_path)
|
||||
is_funcclause((Node *) get_leftop((Expr *) clause)) &&
|
||||
((Func *) ((Expr *) get_leftop((Expr *) clause))->oper)->funcisindex)
|
||||
{
|
||||
/* This looks pretty seriously wrong to me, but I'm not sure what it's
|
||||
* supposed to be doing ... tgl 5/99
|
||||
|
||||
/*
|
||||
* This looks pretty seriously wrong to me, but I'm not sure what
|
||||
* it's supposed to be doing ... tgl 5/99
|
||||
*/
|
||||
Var *newvar = makeVar((Index) lfirsti(index_path->parent->relids),
|
||||
1, /* func indices have one key */
|
||||
((Func *) ((Expr *) clause)->oper)->functype,
|
||||
-1,
|
||||
0,
|
||||
(Index) lfirsti(index_path->parent->relids),
|
||||
0);
|
||||
1, /* func indices have one key */
|
||||
((Func *) ((Expr *) clause)->oper)->functype,
|
||||
-1,
|
||||
0,
|
||||
(Index) lfirsti(index_path->parent->relids),
|
||||
0);
|
||||
|
||||
return ((Node *) make_opclause((Oper *) ((Expr *) clause)->oper,
|
||||
newvar,
|
||||
get_rightop((Expr *) clause)));
|
||||
newvar,
|
||||
get_rightop((Expr *) clause)));
|
||||
|
||||
}
|
||||
else if (IsA(clause, Expr))
|
||||
@@ -696,6 +700,7 @@ fix_indxqual_references(Node *clause, Path *index_path)
|
||||
foreach(i, expr->args)
|
||||
{
|
||||
Node *subclause = lfirst(i);
|
||||
|
||||
new_subclauses = lappend(new_subclauses,
|
||||
fix_indxqual_references(subclause,
|
||||
index_path));
|
||||
@@ -711,6 +716,7 @@ fix_indxqual_references(Node *clause, Path *index_path)
|
||||
foreach(i, (List *) clause)
|
||||
{
|
||||
Node *subclause = lfirst(i);
|
||||
|
||||
new_subclauses = lappend(new_subclauses,
|
||||
fix_indxqual_references(subclause,
|
||||
index_path));
|
||||
@@ -768,15 +774,17 @@ switch_outer(List *clauses)
|
||||
foreach(i, clauses)
|
||||
{
|
||||
clause = lfirst(i);
|
||||
Assert(is_opclause((Node*) clause));
|
||||
Assert(is_opclause((Node *) clause));
|
||||
op = (Node *) get_rightop(clause);
|
||||
Assert(op != (Node*) NULL);
|
||||
Assert(op != (Node *) NULL);
|
||||
if (IsA(op, ArrayRef))
|
||||
op = ((ArrayRef *) op)->refexpr;
|
||||
Assert(IsA(op, Var));
|
||||
if (var_is_outer((Var *) op))
|
||||
{
|
||||
/* Duplicate just enough of the structure to allow commuting
|
||||
|
||||
/*
|
||||
* Duplicate just enough of the structure to allow commuting
|
||||
* the clause without changing the original list. Could use
|
||||
* copyObject, but a complete deep copy is overkill.
|
||||
*/
|
||||
@@ -812,13 +820,14 @@ static Oid *
|
||||
generate_merge_input_sortorder(List *pathkeys, MergeOrder *mergeorder)
|
||||
{
|
||||
int listlength = length(pathkeys);
|
||||
Oid *result = (Oid*) palloc(sizeof(Oid) * (listlength+1));
|
||||
Oid *result = (Oid *) palloc(sizeof(Oid) * (listlength + 1));
|
||||
Oid *nextsortop = result;
|
||||
List *p;
|
||||
|
||||
foreach(p, pathkeys)
|
||||
{
|
||||
Var *pkey = (Var*) lfirst((List*) lfirst(p));
|
||||
Var *pkey = (Var *) lfirst((List *) lfirst(p));
|
||||
|
||||
Assert(IsA(pkey, Var));
|
||||
if (pkey->vartype == mergeorder->left_type)
|
||||
*nextsortop++ = mergeorder->left_operator;
|
||||
@@ -826,7 +835,7 @@ generate_merge_input_sortorder(List *pathkeys, MergeOrder *mergeorder)
|
||||
*nextsortop++ = mergeorder->right_operator;
|
||||
else
|
||||
elog(ERROR,
|
||||
"generate_merge_input_sortorder: can't handle data type %d",
|
||||
"generate_merge_input_sortorder: can't handle data type %d",
|
||||
pkey->vartype);
|
||||
}
|
||||
*nextsortop++ = InvalidOid;
|
||||
@@ -859,12 +868,13 @@ set_noname_tlist_operators(List *tlist, List *pathkeys, Oid *operators)
|
||||
resdom = tlist_member((Var *) pathkey, tlist);
|
||||
if (resdom)
|
||||
{
|
||||
|
||||
/*
|
||||
* Order the resdom pathkey and replace the operator OID for each
|
||||
* key with the regproc OID.
|
||||
* Order the resdom pathkey and replace the operator OID for
|
||||
* each key with the regproc OID.
|
||||
*/
|
||||
resdom->reskey = keyno;
|
||||
resdom->reskeyop = get_opcode(operators[keyno-1]);
|
||||
resdom->reskeyop = get_opcode(operators[keyno - 1]);
|
||||
}
|
||||
keyno += 1;
|
||||
}
|
||||
@@ -878,7 +888,7 @@ set_noname_tlist_operators(List *tlist, List *pathkeys, Oid *operators)
|
||||
*/
|
||||
|
||||
static void
|
||||
copy_costsize (Plan *dest, Plan *src)
|
||||
copy_costsize(Plan *dest, Plan *src)
|
||||
{
|
||||
if (src)
|
||||
{
|
||||
@@ -915,10 +925,10 @@ copy_costsize (Plan *dest, Plan *src)
|
||||
*/
|
||||
static Noname *
|
||||
make_noname(List *tlist,
|
||||
List *pathkeys,
|
||||
Oid *operators,
|
||||
Plan *plan_node,
|
||||
int nonametype)
|
||||
List *pathkeys,
|
||||
Oid *operators,
|
||||
Plan *plan_node,
|
||||
int nonametype)
|
||||
{
|
||||
List *noname_tlist;
|
||||
Noname *retval = NULL;
|
||||
@@ -931,22 +941,22 @@ make_noname(List *tlist,
|
||||
{
|
||||
case NONAME_SORT:
|
||||
retval = (Noname *) make_seqscan(tlist,
|
||||
NIL,
|
||||
_NONAME_RELATION_ID_,
|
||||
(Plan *) make_sort(noname_tlist,
|
||||
_NONAME_RELATION_ID_,
|
||||
plan_node,
|
||||
length(pathkeys)));
|
||||
NIL,
|
||||
_NONAME_RELATION_ID_,
|
||||
(Plan *) make_sort(noname_tlist,
|
||||
_NONAME_RELATION_ID_,
|
||||
plan_node,
|
||||
length(pathkeys)));
|
||||
break;
|
||||
|
||||
case NONAME_MATERIAL:
|
||||
retval = (Noname *) make_seqscan(tlist,
|
||||
NIL,
|
||||
_NONAME_RELATION_ID_,
|
||||
(Plan *) make_material(noname_tlist,
|
||||
_NONAME_RELATION_ID_,
|
||||
plan_node,
|
||||
length(pathkeys)));
|
||||
NIL,
|
||||
_NONAME_RELATION_ID_,
|
||||
(Plan *) make_material(noname_tlist,
|
||||
_NONAME_RELATION_ID_,
|
||||
plan_node,
|
||||
length(pathkeys)));
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1014,8 +1024,9 @@ make_nestloop(List *qptlist,
|
||||
NestLoop *node = makeNode(NestLoop);
|
||||
Plan *plan = &node->join;
|
||||
|
||||
/* this cost estimate is entirely bogus...
|
||||
* hopefully it will be overwritten by caller.
|
||||
/*
|
||||
* this cost estimate is entirely bogus... hopefully it will be
|
||||
* overwritten by caller.
|
||||
*/
|
||||
plan->cost = (lefttree ? lefttree->cost : 0) +
|
||||
(righttree ? righttree->cost : 0);
|
||||
@@ -1039,8 +1050,9 @@ make_hashjoin(List *tlist,
|
||||
HashJoin *node = makeNode(HashJoin);
|
||||
Plan *plan = &node->join;
|
||||
|
||||
/* this cost estimate is entirely bogus...
|
||||
* hopefully it will be overwritten by caller.
|
||||
/*
|
||||
* this cost estimate is entirely bogus... hopefully it will be
|
||||
* overwritten by caller.
|
||||
*/
|
||||
plan->cost = (lefttree ? lefttree->cost : 0) +
|
||||
(righttree ? righttree->cost : 0);
|
||||
@@ -1082,8 +1094,9 @@ make_mergejoin(List *tlist,
|
||||
MergeJoin *node = makeNode(MergeJoin);
|
||||
Plan *plan = &node->join;
|
||||
|
||||
/* this cost estimate is entirely bogus...
|
||||
* hopefully it will be overwritten by caller.
|
||||
/*
|
||||
* this cost estimate is entirely bogus... hopefully it will be
|
||||
* overwritten by caller.
|
||||
*/
|
||||
plan->cost = (lefttree ? lefttree->cost : 0) +
|
||||
(righttree ? righttree->cost : 0);
|
||||
@@ -1142,7 +1155,7 @@ make_agg(List *tlist, Plan *lefttree)
|
||||
{
|
||||
Agg *node = makeNode(Agg);
|
||||
|
||||
copy_costsize(& node->plan, lefttree);
|
||||
copy_costsize(&node->plan, lefttree);
|
||||
node->plan.state = (EState *) NULL;
|
||||
node->plan.qual = NULL;
|
||||
node->plan.targetlist = tlist;
|
||||
@@ -1162,7 +1175,7 @@ make_group(List *tlist,
|
||||
{
|
||||
Group *node = makeNode(Group);
|
||||
|
||||
copy_costsize(& node->plan, (Plan *) lefttree);
|
||||
copy_costsize(&node->plan, (Plan *) lefttree);
|
||||
node->plan.state = (EState *) NULL;
|
||||
node->plan.qual = NULL;
|
||||
node->plan.targetlist = tlist;
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.29 1999/02/22 05:26:21 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.30 1999/05/25 16:09:36 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -40,7 +40,7 @@
|
||||
extern int Quiet;
|
||||
|
||||
static void add_restrict_and_join_to_rel(Query *root, List *clause);
|
||||
static void add_join_info_to_rels(Query *root, RestrictInfo *restrictinfo,
|
||||
static void add_join_info_to_rels(Query *root, RestrictInfo * restrictinfo,
|
||||
Relids join_relids);
|
||||
static void add_vars_to_targetlist(Query *root, List *vars, Relids join_relids);
|
||||
|
||||
@@ -183,6 +183,7 @@ add_restrict_and_join_to_rel(Query *root, List *clause)
|
||||
|
||||
if (length(relids) == 1)
|
||||
{
|
||||
|
||||
/*
|
||||
* There is only one relation participating in 'clause', so
|
||||
* 'clause' must be a restriction clause.
|
||||
@@ -207,11 +208,13 @@ add_restrict_and_join_to_rel(Query *root, List *clause)
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/*
|
||||
* 'clause' is a join clause, since there is more than one atom in
|
||||
* the relid list.
|
||||
*/
|
||||
if (is_funcclause((Node *) clause))
|
||||
|
||||
/*
|
||||
* XXX If we have a func clause set selectivity to 1/3, really
|
||||
* need a true selectivity function.
|
||||
@@ -237,8 +240,8 @@ add_restrict_and_join_to_rel(Query *root, List *clause)
|
||||
*
|
||||
*/
|
||||
static void
|
||||
add_join_info_to_rels(Query *root, RestrictInfo *restrictinfo,
|
||||
Relids join_relids)
|
||||
add_join_info_to_rels(Query *root, RestrictInfo * restrictinfo,
|
||||
Relids join_relids)
|
||||
{
|
||||
List *join_relid;
|
||||
|
||||
@@ -247,7 +250,7 @@ add_join_info_to_rels(Query *root, RestrictInfo *restrictinfo,
|
||||
{
|
||||
JoinInfo *joininfo;
|
||||
Relids unjoined_relids = NIL;
|
||||
List *rel;
|
||||
List *rel;
|
||||
|
||||
/* Get the relids not equal to the current relid */
|
||||
foreach(rel, join_relids)
|
||||
@@ -259,7 +262,7 @@ add_join_info_to_rels(Query *root, RestrictInfo *restrictinfo,
|
||||
joininfo = find_joininfo_node(get_base_rel(root, lfirsti(join_relid)),
|
||||
unjoined_relids);
|
||||
joininfo->jinfo_restrictinfo = lcons(copyObject((void *) restrictinfo),
|
||||
joininfo->jinfo_restrictinfo);
|
||||
joininfo->jinfo_restrictinfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -375,7 +378,7 @@ mergejoinop(Expr *clause)
|
||||
rightOp;
|
||||
bool sortable;
|
||||
|
||||
if (!is_opclause((Node*) clause))
|
||||
if (!is_opclause((Node *) clause))
|
||||
return NULL;
|
||||
|
||||
left = get_leftop(clause);
|
||||
@@ -384,7 +387,7 @@ mergejoinop(Expr *clause)
|
||||
/* caution: is_opclause accepts more than I do, so check it */
|
||||
if (!right)
|
||||
return NULL; /* unary opclauses need not apply */
|
||||
if (!IsA(left, Var) || !IsA(right, Var))
|
||||
if (!IsA(left, Var) ||!IsA(right, Var))
|
||||
return NULL;
|
||||
|
||||
opno = ((Oper *) clause->oper)->opno;
|
||||
@@ -422,7 +425,7 @@ hashjoinop(Expr *clause)
|
||||
Var *left,
|
||||
*right;
|
||||
|
||||
if (!is_opclause((Node*) clause))
|
||||
if (!is_opclause((Node *) clause))
|
||||
return InvalidOid;
|
||||
|
||||
left = get_leftop(clause);
|
||||
@@ -431,7 +434,7 @@ hashjoinop(Expr *clause)
|
||||
/* caution: is_opclause accepts more than I do, so check it */
|
||||
if (!right)
|
||||
return InvalidOid; /* unary opclauses need not apply */
|
||||
if (!IsA(left, Var) || !IsA(right, Var))
|
||||
if (!IsA(left, Var) ||!IsA(right, Var))
|
||||
return InvalidOid;
|
||||
|
||||
return op_hashjoinable(((Oper *) clause->oper)->opno,
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.35 1999/05/03 00:38:43 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.36 1999/05/25 16:09:36 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -154,7 +154,7 @@ query_planner(Query *root,
|
||||
else
|
||||
return (Plan *) scan;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
return (Plan *) NULL;
|
||||
}
|
||||
@@ -195,9 +195,9 @@ query_planner(Query *root,
|
||||
* tree. -- Wei
|
||||
*
|
||||
* Note: formerly there was a test here to skip the flatten call if we
|
||||
* expected union_planner to insert a Group or Agg node above our result.
|
||||
* However, now union_planner tells us exactly what it wants returned,
|
||||
* and we just do it. Much cleaner.
|
||||
* expected union_planner to insert a Group or Agg node above our
|
||||
* result. However, now union_planner tells us exactly what it wants
|
||||
* returned, and we just do it. Much cleaner.
|
||||
*/
|
||||
else
|
||||
{
|
||||
@@ -207,6 +207,7 @@ query_planner(Query *root,
|
||||
}
|
||||
|
||||
#ifdef NOT_USED
|
||||
|
||||
/*
|
||||
* Destructively modify the query plan's targetlist to add fjoin lists
|
||||
* to flatten functions that return sets of base types
|
||||
@@ -251,7 +252,7 @@ subplanner(Query *root,
|
||||
|
||||
final_rel = make_one_rel(root, root->base_rel_list);
|
||||
|
||||
#ifdef NOT_USED /* fix xfunc */
|
||||
#ifdef NOT_USED /* fix xfunc */
|
||||
|
||||
/*
|
||||
* Perform Predicate Migration on each path, to optimize and correctly
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.53 1999/05/17 17:03:15 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.54 1999/05/25 16:09:37 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -56,10 +56,10 @@
|
||||
#include "parser/parse_oper.h"
|
||||
|
||||
static List *make_subplanTargetList(Query *parse, List *tlist,
|
||||
AttrNumber **groupColIdx);
|
||||
AttrNumber **groupColIdx);
|
||||
static Plan *make_groupplan(List *group_tlist, bool tuplePerGroup,
|
||||
List *groupClause, AttrNumber *grpColIdx,
|
||||
Plan *subplan);
|
||||
List *groupClause, AttrNumber *grpColIdx,
|
||||
Plan *subplan);
|
||||
static bool need_sortplan(List *sortcls, Plan *plan);
|
||||
static Plan *make_sortplan(List *tlist, List *sortcls, Plan *plannode);
|
||||
|
||||
@@ -113,12 +113,12 @@ union_planner(Query *parse)
|
||||
|
||||
if (parse->unionClause)
|
||||
{
|
||||
result_plan = (Plan *) plan_union_queries(parse);
|
||||
/* XXX do we need to do this? bjm 12/19/97 */
|
||||
tlist = preprocess_targetlist(tlist,
|
||||
parse->commandType,
|
||||
parse->resultRelation,
|
||||
parse->rtable);
|
||||
result_plan = (Plan *) plan_union_queries(parse);
|
||||
/* XXX do we need to do this? bjm 12/19/97 */
|
||||
tlist = preprocess_targetlist(tlist,
|
||||
parse->commandType,
|
||||
parse->resultRelation,
|
||||
parse->rtable);
|
||||
}
|
||||
else if ((rt_index = first_inherit_rt_entry(rangetable)) != -1)
|
||||
{
|
||||
@@ -127,78 +127,80 @@ union_planner(Query *parse)
|
||||
result_plan = (Plan *) plan_inherit_queries(parse, rt_index);
|
||||
/* XXX do we need to do this? bjm 12/19/97 */
|
||||
tlist = preprocess_targetlist(tlist,
|
||||
parse->commandType,
|
||||
parse->resultRelation,
|
||||
parse->rtable);
|
||||
parse->commandType,
|
||||
parse->resultRelation,
|
||||
parse->rtable);
|
||||
}
|
||||
else
|
||||
{
|
||||
List **vpm = NULL;
|
||||
List *sub_tlist;
|
||||
List **vpm = NULL;
|
||||
List *sub_tlist;
|
||||
|
||||
/* Preprocess targetlist in case we are inside an INSERT/UPDATE. */
|
||||
tlist = preprocess_targetlist(tlist,
|
||||
parse->commandType,
|
||||
parse->resultRelation,
|
||||
parse->rtable);
|
||||
/* Preprocess targetlist in case we are inside an INSERT/UPDATE. */
|
||||
tlist = preprocess_targetlist(tlist,
|
||||
parse->commandType,
|
||||
parse->resultRelation,
|
||||
parse->rtable);
|
||||
|
||||
/* Add row-mark targets for UPDATE
|
||||
* (should this be done in preprocess_targetlist?)
|
||||
*/
|
||||
if (parse->rowMark != NULL)
|
||||
{
|
||||
List *l;
|
||||
|
||||
foreach (l, parse->rowMark)
|
||||
/*
|
||||
* Add row-mark targets for UPDATE (should this be done in
|
||||
* preprocess_targetlist?)
|
||||
*/
|
||||
if (parse->rowMark != NULL)
|
||||
{
|
||||
RowMark *rowmark = (RowMark*) lfirst(l);
|
||||
TargetEntry *ctid;
|
||||
Resdom *resdom;
|
||||
Var *var;
|
||||
char *resname;
|
||||
List *l;
|
||||
|
||||
if (!(rowmark->info & ROW_MARK_FOR_UPDATE))
|
||||
continue;
|
||||
foreach(l, parse->rowMark)
|
||||
{
|
||||
RowMark *rowmark = (RowMark *) lfirst(l);
|
||||
TargetEntry *ctid;
|
||||
Resdom *resdom;
|
||||
Var *var;
|
||||
char *resname;
|
||||
|
||||
resname = (char*) palloc(32);
|
||||
sprintf(resname, "ctid%u", rowmark->rti);
|
||||
resdom = makeResdom(length(tlist) + 1,
|
||||
TIDOID,
|
||||
-1,
|
||||
resname,
|
||||
0,
|
||||
0,
|
||||
true);
|
||||
if (!(rowmark->info & ROW_MARK_FOR_UPDATE))
|
||||
continue;
|
||||
|
||||
var = makeVar(rowmark->rti, -1, TIDOID,
|
||||
-1, 0, rowmark->rti, -1);
|
||||
resname = (char *) palloc(32);
|
||||
sprintf(resname, "ctid%u", rowmark->rti);
|
||||
resdom = makeResdom(length(tlist) + 1,
|
||||
TIDOID,
|
||||
-1,
|
||||
resname,
|
||||
0,
|
||||
0,
|
||||
true);
|
||||
|
||||
ctid = makeTargetEntry(resdom, (Node *) var);
|
||||
tlist = lappend(tlist, ctid);
|
||||
var = makeVar(rowmark->rti, -1, TIDOID,
|
||||
-1, 0, rowmark->rti, -1);
|
||||
|
||||
ctid = makeTargetEntry(resdom, (Node *) var);
|
||||
tlist = lappend(tlist, ctid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate appropriate target list for subplan; may be different
|
||||
* from tlist if grouping or aggregation is needed.
|
||||
*/
|
||||
sub_tlist = make_subplanTargetList(parse, tlist, &groupColIdx);
|
||||
/*
|
||||
* Generate appropriate target list for subplan; may be different
|
||||
* from tlist if grouping or aggregation is needed.
|
||||
*/
|
||||
sub_tlist = make_subplanTargetList(parse, tlist, &groupColIdx);
|
||||
|
||||
/* Generate the (sub) plan */
|
||||
if (parse->rtable != NULL)
|
||||
{
|
||||
vpm = (List **) palloc(length(parse->rtable) * sizeof(List *));
|
||||
memset(vpm, 0, length(parse->rtable) * sizeof(List *));
|
||||
}
|
||||
PlannerVarParam = lcons(vpm, PlannerVarParam);
|
||||
result_plan = query_planner(parse,
|
||||
parse->commandType,
|
||||
sub_tlist,
|
||||
(List *) parse->qual);
|
||||
PlannerVarParam = lnext(PlannerVarParam);
|
||||
if (vpm != NULL)
|
||||
pfree(vpm);
|
||||
/* Generate the (sub) plan */
|
||||
if (parse->rtable != NULL)
|
||||
{
|
||||
vpm = (List **) palloc(length(parse->rtable) * sizeof(List *));
|
||||
memset(vpm, 0, length(parse->rtable) * sizeof(List *));
|
||||
}
|
||||
PlannerVarParam = lcons(vpm, PlannerVarParam);
|
||||
result_plan = query_planner(parse,
|
||||
parse->commandType,
|
||||
sub_tlist,
|
||||
(List *) parse->qual);
|
||||
PlannerVarParam = lnext(PlannerVarParam);
|
||||
if (vpm != NULL)
|
||||
pfree(vpm);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* If we have a GROUP BY clause, insert a group node (with the
|
||||
* appropriate sort node.)
|
||||
@@ -216,7 +218,8 @@ union_planner(Query *parse)
|
||||
*/
|
||||
tuplePerGroup = parse->hasAggs;
|
||||
|
||||
/* If there are aggregates then the Group node should just return
|
||||
/*
|
||||
* If there are aggregates then the Group node should just return
|
||||
* the same (simplified) tlist as the subplan, which we indicate
|
||||
* to make_groupplan by passing NIL. If there are no aggregates
|
||||
* then the Group node had better compute the final tlist.
|
||||
@@ -235,7 +238,7 @@ union_planner(Query *parse)
|
||||
*/
|
||||
if (parse->havingQual)
|
||||
{
|
||||
List **vpm = NULL;
|
||||
List **vpm = NULL;
|
||||
|
||||
if (parse->rtable != NULL)
|
||||
{
|
||||
@@ -249,15 +252,20 @@ union_planner(Query *parse)
|
||||
|
||||
if (parse->hasSubLinks)
|
||||
{
|
||||
/* There is a subselect in the havingQual, so we have to process it
|
||||
* using the same function as for a subselect in 'where'
|
||||
|
||||
/*
|
||||
* There is a subselect in the havingQual, so we have to
|
||||
* process it using the same function as for a subselect in
|
||||
* 'where'
|
||||
*/
|
||||
parse->havingQual =
|
||||
(Node *) SS_process_sublinks(parse->havingQual);
|
||||
/* Check for ungrouped variables passed to subplans.
|
||||
* (Probably this should be done by the parser, but right now
|
||||
* the parser is not smart enough to tell which level the vars
|
||||
* belong to?)
|
||||
|
||||
/*
|
||||
* Check for ungrouped variables passed to subplans. (Probably
|
||||
* this should be done by the parser, but right now the parser
|
||||
* is not smart enough to tell which level the vars belong
|
||||
* to?)
|
||||
*/
|
||||
check_having_for_ungrouped_vars(parse->havingQual,
|
||||
parse->groupClause,
|
||||
@@ -269,7 +277,7 @@ union_planner(Query *parse)
|
||||
|
||||
PlannerVarParam = lnext(PlannerVarParam);
|
||||
if (vpm != NULL)
|
||||
pfree(vpm);
|
||||
pfree(vpm);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -283,22 +291,22 @@ union_planner(Query *parse)
|
||||
result_plan->qual = (List *) parse->havingQual;
|
||||
|
||||
/*
|
||||
* Update vars to refer to subplan result tuples,
|
||||
* find Aggrefs, make sure there is an Aggref in every HAVING clause.
|
||||
* Update vars to refer to subplan result tuples, find Aggrefs,
|
||||
* make sure there is an Aggref in every HAVING clause.
|
||||
*/
|
||||
if (! set_agg_tlist_references((Agg *) result_plan))
|
||||
if (!set_agg_tlist_references((Agg *) result_plan))
|
||||
elog(ERROR, "SELECT/HAVING requires aggregates to be valid");
|
||||
|
||||
/*
|
||||
* Check that we actually found some aggregates, else executor
|
||||
* will die unpleasantly. (The rewrite module currently has bugs
|
||||
* that allow hasAggs to be incorrectly set 'true' sometimes.
|
||||
* It's not easy to recover here, since we've already made decisions
|
||||
* that allow hasAggs to be incorrectly set 'true' sometimes. It's
|
||||
* not easy to recover here, since we've already made decisions
|
||||
* assuming there will be an Agg node.)
|
||||
*/
|
||||
if (((Agg *) result_plan)->aggs == NIL)
|
||||
elog(ERROR, "union_planner: query is marked hasAggs, but I don't see any");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* For now, before we hand back the plan, check to see if there is a
|
||||
@@ -363,7 +371,7 @@ union_planner(Query *parse)
|
||||
* SELECT a+1, ... GROUP BY a+1
|
||||
* Note, however, that other varnodes in the parent's targetlist (and
|
||||
* havingQual, if any) will still need to be updated to refer to outputs
|
||||
* of the subplan. This routine is quite large enough already, so we do
|
||||
* of the subplan. This routine is quite large enough already, so we do
|
||||
* that later.
|
||||
*---------------
|
||||
*/
|
||||
@@ -384,13 +392,15 @@ make_subplanTargetList(Query *parse,
|
||||
|
||||
*groupColIdx = NULL;
|
||||
|
||||
/* If we're not grouping or aggregating, nothing to do here;
|
||||
/*
|
||||
* If we're not grouping or aggregating, nothing to do here;
|
||||
* query_planner should receive the unmodified target list.
|
||||
*/
|
||||
if (!parse->hasAggs && !parse->groupClause && !parse->havingQual)
|
||||
return tlist;
|
||||
|
||||
/* If grouping, make a working copy of groupClause list (which we use
|
||||
/*
|
||||
* If grouping, make a working copy of groupClause list (which we use
|
||||
* just to verify that we found all the groupClause items in tlist).
|
||||
* Also allocate space to remember where the group columns are in the
|
||||
* subplan tlist.
|
||||
@@ -403,14 +413,14 @@ make_subplanTargetList(Query *parse,
|
||||
*groupColIdx = grpColIdx;
|
||||
}
|
||||
|
||||
sub_tlist = new_unsorted_tlist(tlist); /* make a modifiable copy */
|
||||
sub_tlist = new_unsorted_tlist(tlist); /* make a modifiable copy */
|
||||
|
||||
/*
|
||||
* Step 1: build grpColIdx by finding targetlist items that match
|
||||
* GroupBy entries. If there are aggregates, remove non-GroupBy items
|
||||
* from sub_tlist, and reset its resnos accordingly. When we leave an
|
||||
* expression in the subplan tlist, modify the parent tlist to copy the
|
||||
* value from the subplan output rather than re-evaluating it.
|
||||
* expression in the subplan tlist, modify the parent tlist to copy
|
||||
* the value from the subplan output rather than re-evaluating it.
|
||||
*/
|
||||
prnt_tlist = tlist; /* scans parent tlist in sync with sl */
|
||||
foreach(sl, sub_tlist)
|
||||
@@ -434,23 +444,28 @@ make_subplanTargetList(Query *parse,
|
||||
resdom->reskey = keyno;
|
||||
resdom->reskeyop = get_opcode(grpcl->grpOpoid);
|
||||
grpColIdx[keyno - 1] = next_resno;
|
||||
/* Remove groupclause from our list of unmatched groupclauses.
|
||||
* NB: this depends on having used a shallow listCopy() above.
|
||||
|
||||
/*
|
||||
* Remove groupclause from our list of unmatched
|
||||
* groupclauses. NB: this depends on having used a shallow
|
||||
* listCopy() above.
|
||||
*/
|
||||
glc = lremove((void*) grpcl, glc);
|
||||
glc = lremove((void *) grpcl, glc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (! foundGroupClause)
|
||||
if (!foundGroupClause)
|
||||
{
|
||||
|
||||
/*
|
||||
* Non-GroupBy entry: remove it from subplan if there are
|
||||
* aggregates in query - it will be evaluated by Aggregate plan.
|
||||
* But do not remove simple-Var entries; we'd just have to add
|
||||
* them back anyway, and we risk confusing INSERT/UPDATE.
|
||||
* aggregates in query - it will be evaluated by Aggregate
|
||||
* plan. But do not remove simple-Var entries; we'd just have
|
||||
* to add them back anyway, and we risk confusing
|
||||
* INSERT/UPDATE.
|
||||
*/
|
||||
if (parse->hasAggs && ! IsA(te->expr, Var))
|
||||
if (parse->hasAggs && !IsA(te->expr, Var))
|
||||
keepInSubPlan = false;
|
||||
}
|
||||
|
||||
@@ -458,15 +473,16 @@ make_subplanTargetList(Query *parse,
|
||||
{
|
||||
/* Assign new sequential resnos to subplan tlist items */
|
||||
resdom->resno = next_resno++;
|
||||
if (! IsA(parentte->expr, Var))
|
||||
if (!IsA(parentte->expr, Var))
|
||||
{
|
||||
/* Since the item is being computed in the subplan,
|
||||
* we can just make a Var node to reference it in the
|
||||
* outer plan, rather than recomputing it there.
|
||||
* Note we use varnoold = -1 as a flag to let
|
||||
* replace_vars_with_subplan_refs know it needn't change
|
||||
* this Var node.
|
||||
* If it's only a Var anyway, we leave it alone for now;
|
||||
|
||||
/*
|
||||
* Since the item is being computed in the subplan, we can
|
||||
* just make a Var node to reference it in the outer plan,
|
||||
* rather than recomputing it there. Note we use varnoold
|
||||
* = -1 as a flag to let replace_vars_with_subplan_refs
|
||||
* know it needn't change this Var node. If it's only a
|
||||
* Var anyway, we leave it alone for now;
|
||||
* replace_vars_with_subplan_refs will fix it later.
|
||||
*/
|
||||
parentte->expr = (Node *) makeVar(1, resdom->resno,
|
||||
@@ -477,9 +493,11 @@ make_subplanTargetList(Query *parse,
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Remove this tlist item from the subplan, but remember the
|
||||
* vars it needs. The outer tlist item probably needs changes,
|
||||
* but that will happen later.
|
||||
|
||||
/*
|
||||
* Remove this tlist item from the subplan, but remember the
|
||||
* vars it needs. The outer tlist item probably needs
|
||||
* changes, but that will happen later.
|
||||
*/
|
||||
sub_tlist = lremove(te, sub_tlist);
|
||||
extravars = nconc(extravars, pull_var_clause(te->expr));
|
||||
@@ -493,8 +511,8 @@ make_subplanTargetList(Query *parse,
|
||||
elog(ERROR, "make_subplanTargetList: GROUP BY attribute not found in target list");
|
||||
|
||||
/*
|
||||
* Add subplan targets for any variables needed by removed tlist entries
|
||||
* that aren't otherwise mentioned in the subplan target list.
|
||||
* Add subplan targets for any variables needed by removed tlist
|
||||
* entries that aren't otherwise mentioned in the subplan target list.
|
||||
* We'll also need targets for any variables seen only in HAVING.
|
||||
*/
|
||||
extravars = nconc(extravars, pull_var_clause(parse->havingQual));
|
||||
@@ -505,9 +523,11 @@ make_subplanTargetList(Query *parse,
|
||||
|
||||
if (tlist_member(v, sub_tlist) == NULL)
|
||||
{
|
||||
/* Make sure sub_tlist element is a fresh object not shared with
|
||||
* any other structure; not sure if anything will break if it is
|
||||
* shared, but better to be safe...
|
||||
|
||||
/*
|
||||
* Make sure sub_tlist element is a fresh object not shared
|
||||
* with any other structure; not sure if anything will break
|
||||
* if it is shared, but better to be safe...
|
||||
*/
|
||||
sub_tlist = lappend(sub_tlist,
|
||||
create_tl_element((Var *) copyObject(v),
|
||||
@@ -535,9 +555,9 @@ make_groupplan(List *group_tlist,
|
||||
/*
|
||||
* Make the targetlist for the Sort node; it always just references
|
||||
* each of the corresponding target items of the subplan. We need to
|
||||
* ensure that simple Vars in the subplan's target list are recognizable
|
||||
* by replace_vars_with_subplan_refs when it's applied to the Sort/Group
|
||||
* target list, so copy up their varnoold/varoattno.
|
||||
* ensure that simple Vars in the subplan's target list are
|
||||
* recognizable by replace_vars_with_subplan_refs when it's applied to
|
||||
* the Sort/Group target list, so copy up their varnoold/varoattno.
|
||||
*/
|
||||
sort_tlist = NIL;
|
||||
foreach(sl, subplan->targetlist)
|
||||
@@ -548,7 +568,8 @@ make_groupplan(List *group_tlist,
|
||||
|
||||
if (IsA(te->expr, Var))
|
||||
{
|
||||
Var *subvar = (Var *) te->expr;
|
||||
Var *subvar = (Var *) te->expr;
|
||||
|
||||
newvar = makeVar(1, resdom->resno,
|
||||
resdom->restype, resdom->restypmod,
|
||||
0, subvar->varnoold, subvar->varoattno);
|
||||
@@ -561,8 +582,8 @@ make_groupplan(List *group_tlist,
|
||||
}
|
||||
|
||||
sort_tlist = lappend(sort_tlist,
|
||||
makeTargetEntry((Resdom *) copyObject(resdom),
|
||||
(Node *) newvar));
|
||||
makeTargetEntry((Resdom *) copyObject(resdom),
|
||||
(Node *) newvar));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -575,20 +596,19 @@ make_groupplan(List *group_tlist,
|
||||
sortplan->plan.cost = subplan->cost; /* XXX assume no cost */
|
||||
|
||||
/*
|
||||
* If the caller gave us a target list, use it after fixing the variables.
|
||||
* If not, we need the same sort of "repeater" tlist as for the Sort node.
|
||||
* If the caller gave us a target list, use it after fixing the
|
||||
* variables. If not, we need the same sort of "repeater" tlist as for
|
||||
* the Sort node.
|
||||
*/
|
||||
if (group_tlist)
|
||||
{
|
||||
group_tlist = copyObject(group_tlist); /* necessary?? */
|
||||
group_tlist = copyObject(group_tlist); /* necessary?? */
|
||||
replace_tlist_with_subplan_refs(group_tlist,
|
||||
(Index) 0,
|
||||
subplan->targetlist);
|
||||
}
|
||||
else
|
||||
{
|
||||
group_tlist = copyObject(sort_tlist);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make the Group node
|
||||
@@ -686,7 +706,7 @@ pg_checkretval(Oid rettype, List *queryTreeList)
|
||||
int i;
|
||||
|
||||
/* find the final query */
|
||||
parse = (Query *) nth(length(queryTreeList)-1, queryTreeList);
|
||||
parse = (Query *) nth(length(queryTreeList) - 1, queryTreeList);
|
||||
|
||||
/*
|
||||
* test 1: if the last query is a utility invocation, then there had
|
||||
@@ -787,7 +807,7 @@ pg_checkretval(Oid rettype, List *queryTreeList)
|
||||
tlist = lnext(tlist);
|
||||
tletype = exprType(thenode);
|
||||
|
||||
#ifdef NOT_USED /* fix me */
|
||||
#ifdef NOT_USED /* fix me */
|
||||
/* this is tedious */
|
||||
if (IsA(thenode, Var))
|
||||
tletype = (Oid) ((Var *) thenode)->vartype;
|
||||
@@ -830,11 +850,12 @@ pg_checkretval(Oid rettype, List *queryTreeList)
|
||||
static TargetEntry *
|
||||
get_matching_tle(Plan *plan, Resdom *resdom)
|
||||
{
|
||||
List *i;
|
||||
TargetEntry *tle;
|
||||
List *i;
|
||||
TargetEntry *tle;
|
||||
|
||||
foreach (i, plan->targetlist) {
|
||||
tle = (TargetEntry *)lfirst(i);
|
||||
foreach(i, plan->targetlist)
|
||||
{
|
||||
tle = (TargetEntry *) lfirst(i);
|
||||
if (tle->resdom->resno == resdom->resno)
|
||||
return tle;
|
||||
}
|
||||
@@ -853,50 +874,45 @@ static bool
|
||||
need_sortplan(List *sortcls, Plan *plan)
|
||||
{
|
||||
Relation indexRel;
|
||||
IndexScan *indexScan;
|
||||
Oid indexId;
|
||||
List *i;
|
||||
IndexScan *indexScan;
|
||||
Oid indexId;
|
||||
List *i;
|
||||
HeapTuple htup;
|
||||
Form_pg_index index_tup;
|
||||
int key_no = 0;
|
||||
Form_pg_index index_tup;
|
||||
int key_no = 0;
|
||||
|
||||
/* ----------
|
||||
* Must be an IndexScan
|
||||
* ----------
|
||||
*/
|
||||
if (nodeTag(plan) != T_IndexScan) {
|
||||
if (nodeTag(plan) != T_IndexScan)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
indexScan = (IndexScan *)plan;
|
||||
indexScan = (IndexScan *) plan;
|
||||
|
||||
/* ----------
|
||||
* Should not have left- or righttree
|
||||
* ----------
|
||||
*/
|
||||
if (plan->lefttree != NULL) {
|
||||
if (plan->lefttree != NULL)
|
||||
return TRUE;
|
||||
}
|
||||
if (plan->righttree != NULL) {
|
||||
if (plan->righttree != NULL)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* ----------
|
||||
* Must be a single index scan
|
||||
* ----------
|
||||
*/
|
||||
if (length(indexScan->indxid) != 1) {
|
||||
if (length(indexScan->indxid) != 1)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* ----------
|
||||
* Indices can only have up to 8 attributes. So an ORDER BY using
|
||||
* more that 8 attributes could never be satisfied by an index.
|
||||
* ----------
|
||||
*/
|
||||
if (length(sortcls) > 8) {
|
||||
if (length(sortcls) > 8)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* ----------
|
||||
* The choosen Index must be a btree
|
||||
@@ -905,7 +921,8 @@ need_sortplan(List *sortcls, Plan *plan)
|
||||
indexId = lfirsti(indexScan->indxid);
|
||||
|
||||
indexRel = index_open(indexId);
|
||||
if (strcmp(nameout(&(indexRel->rd_am->amname)), "btree") != 0) {
|
||||
if (strcmp(nameout(&(indexRel->rd_am->amname)), "btree") != 0)
|
||||
{
|
||||
heap_close(indexRel);
|
||||
return TRUE;
|
||||
}
|
||||
@@ -916,34 +933,36 @@ need_sortplan(List *sortcls, Plan *plan)
|
||||
* ----------
|
||||
*/
|
||||
htup = SearchSysCacheTuple(INDEXRELID,
|
||||
ObjectIdGetDatum(indexId), 0, 0, 0);
|
||||
if (!HeapTupleIsValid(htup)) {
|
||||
ObjectIdGetDatum(indexId), 0, 0, 0);
|
||||
if (!HeapTupleIsValid(htup))
|
||||
elog(ERROR, "cache lookup for index %u failed", indexId);
|
||||
}
|
||||
index_tup = (Form_pg_index) GETSTRUCT(htup);
|
||||
|
||||
/* ----------
|
||||
* Check if all the sort clauses match the attributes in the index
|
||||
* ----------
|
||||
*/
|
||||
foreach (i, sortcls) {
|
||||
SortClause *sortcl;
|
||||
Resdom *resdom;
|
||||
TargetEntry *tle;
|
||||
Var *var;
|
||||
foreach(i, sortcls)
|
||||
{
|
||||
SortClause *sortcl;
|
||||
Resdom *resdom;
|
||||
TargetEntry *tle;
|
||||
Var *var;
|
||||
|
||||
sortcl = (SortClause *) lfirst(i);
|
||||
|
||||
resdom = sortcl->resdom;
|
||||
tle = get_matching_tle(plan, resdom);
|
||||
if (tle == NULL) {
|
||||
if (tle == NULL)
|
||||
{
|
||||
/* ----------
|
||||
* Could this happen?
|
||||
* ----------
|
||||
*/
|
||||
return TRUE;
|
||||
}
|
||||
if (nodeTag(tle->expr) != T_Var) {
|
||||
if (nodeTag(tle->expr) != T_Var)
|
||||
{
|
||||
/* ----------
|
||||
* The target list expression isn't a var, so it
|
||||
* cannot be the indexed attribute
|
||||
@@ -951,9 +970,10 @@ need_sortplan(List *sortcls, Plan *plan)
|
||||
*/
|
||||
return TRUE;
|
||||
}
|
||||
var = (Var *)(tle->expr);
|
||||
var = (Var *) (tle->expr);
|
||||
|
||||
if (var->varno != indexScan->scan.scanrelid) {
|
||||
if (var->varno != indexScan->scan.scanrelid)
|
||||
{
|
||||
/* ----------
|
||||
* This Var isn't from the scan relation. So it isn't
|
||||
* that of the index
|
||||
@@ -962,7 +982,8 @@ need_sortplan(List *sortcls, Plan *plan)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (var->varattno != index_tup->indkey[key_no]) {
|
||||
if (var->varattno != index_tup->indkey[key_no])
|
||||
{
|
||||
/* ----------
|
||||
* It isn't the indexed attribute.
|
||||
* ----------
|
||||
@@ -970,7 +991,8 @@ need_sortplan(List *sortcls, Plan *plan)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (oprid(oper("<", resdom->restype, resdom->restype, FALSE)) != sortcl->opoid) {
|
||||
if (oprid(oper("<", resdom->restype, resdom->restype, FALSE)) != sortcl->opoid)
|
||||
{
|
||||
/* ----------
|
||||
* Sort order isn't in ascending order.
|
||||
* ----------
|
||||
@@ -987,4 +1009,3 @@ need_sortplan(List *sortcls, Plan *plan)
|
||||
*/
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.46 1999/05/12 15:01:39 wieck Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.47 1999/05/25 16:09:39 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -35,13 +35,13 @@
|
||||
|
||||
static void set_join_tlist_references(Join *join);
|
||||
static void set_nonamescan_tlist_references(SeqScan *nonamescan);
|
||||
static void set_noname_tlist_references(Noname *noname);
|
||||
static void set_noname_tlist_references(Noname * noname);
|
||||
static Node *replace_clause_joinvar_refs(Node *clause,
|
||||
List *outer_tlist,
|
||||
List *inner_tlist);
|
||||
List *outer_tlist,
|
||||
List *inner_tlist);
|
||||
static Var *replace_joinvar_refs(Var *var,
|
||||
List *outer_tlist,
|
||||
List *inner_tlist);
|
||||
List *outer_tlist,
|
||||
List *inner_tlist);
|
||||
static List *tlist_noname_references(Oid nonameid, List *tlist);
|
||||
static bool OperandIsInner(Node *opnd, int inner_relid);
|
||||
static List *pull_agg_clause(Node *clause);
|
||||
@@ -114,11 +114,12 @@ set_join_tlist_references(Join *join)
|
||||
foreach(entry, qptlist)
|
||||
{
|
||||
TargetEntry *xtl = (TargetEntry *) lfirst(entry);
|
||||
Node *joinvar = replace_clause_joinvar_refs(xtl->expr,
|
||||
outer_tlist,
|
||||
inner_tlist);
|
||||
Node *joinvar = replace_clause_joinvar_refs(xtl->expr,
|
||||
outer_tlist,
|
||||
inner_tlist);
|
||||
|
||||
new_join_targetlist = lappend(new_join_targetlist,
|
||||
makeTargetEntry(xtl->resdom, joinvar));
|
||||
makeTargetEntry(xtl->resdom, joinvar));
|
||||
}
|
||||
|
||||
((Plan *) join)->targetlist = new_join_targetlist;
|
||||
@@ -144,7 +145,7 @@ set_nonamescan_tlist_references(SeqScan *nonamescan)
|
||||
Noname *noname = (Noname *) ((Plan *) nonamescan)->lefttree;
|
||||
|
||||
((Plan *) nonamescan)->targetlist = tlist_noname_references(noname->nonameid,
|
||||
((Plan *) nonamescan)->targetlist);
|
||||
((Plan *) nonamescan)->targetlist);
|
||||
set_noname_tlist_references(noname);
|
||||
}
|
||||
|
||||
@@ -160,7 +161,7 @@ set_nonamescan_tlist_references(SeqScan *nonamescan)
|
||||
*
|
||||
*/
|
||||
static void
|
||||
set_noname_tlist_references(Noname *noname)
|
||||
set_noname_tlist_references(Noname * noname)
|
||||
{
|
||||
Plan *source = ((Plan *) noname)->lefttree;
|
||||
|
||||
@@ -168,7 +169,7 @@ set_noname_tlist_references(Noname *noname)
|
||||
{
|
||||
set_tlist_references(source);
|
||||
((Plan *) noname)->targetlist = copy_vars(((Plan *) noname)->targetlist,
|
||||
(source)->targetlist);
|
||||
(source)->targetlist);
|
||||
}
|
||||
else
|
||||
elog(ERROR, "calling set_noname_tlist_references with empty lefttree");
|
||||
@@ -235,9 +236,9 @@ index_outerjoin_references(List *inner_indxqual,
|
||||
if (OperandIsInner((Node *) get_rightop(clause), inner_relid))
|
||||
{
|
||||
Var *joinvar = (Var *)
|
||||
replace_clause_joinvar_refs((Node *) get_leftop(clause),
|
||||
outer_tlist,
|
||||
NIL);
|
||||
replace_clause_joinvar_refs((Node *) get_leftop(clause),
|
||||
outer_tlist,
|
||||
NIL);
|
||||
|
||||
temp = make_opclause(replace_opid((Oper *) ((Expr *) clause)->oper),
|
||||
joinvar,
|
||||
@@ -248,9 +249,9 @@ index_outerjoin_references(List *inner_indxqual,
|
||||
{
|
||||
/* inner scan on left */
|
||||
Var *joinvar = (Var *)
|
||||
replace_clause_joinvar_refs((Node *) get_rightop(clause),
|
||||
outer_tlist,
|
||||
NIL);
|
||||
replace_clause_joinvar_refs((Node *) get_rightop(clause),
|
||||
outer_tlist,
|
||||
NIL);
|
||||
|
||||
temp = make_opclause(replace_opid((Oper *) ((Expr *) clause)->oper),
|
||||
get_leftop(clause),
|
||||
@@ -290,8 +291,9 @@ replace_clause_joinvar_refs(Node *clause,
|
||||
return NULL;
|
||||
if (IsA(clause, Var))
|
||||
{
|
||||
Var *temp = replace_joinvar_refs((Var *) clause,
|
||||
outer_tlist, inner_tlist);
|
||||
Var *temp = replace_joinvar_refs((Var *) clause,
|
||||
outer_tlist, inner_tlist);
|
||||
|
||||
if (temp != NULL)
|
||||
return (Node *) temp;
|
||||
else
|
||||
@@ -344,32 +346,32 @@ replace_clause_joinvar_refs(Node *clause,
|
||||
else if (is_funcclause(clause))
|
||||
{
|
||||
return (Node *) make_funcclause(
|
||||
(Func *) ((Expr *) clause)->oper,
|
||||
(List *) replace_clause_joinvar_refs(
|
||||
(Node *) ((Expr *) clause)->args,
|
||||
outer_tlist,
|
||||
inner_tlist));
|
||||
(Func *) ((Expr *) clause)->oper,
|
||||
(List *) replace_clause_joinvar_refs(
|
||||
(Node *) ((Expr *) clause)->args,
|
||||
outer_tlist,
|
||||
inner_tlist));
|
||||
}
|
||||
else if (not_clause(clause))
|
||||
{
|
||||
return (Node *) make_notclause((Expr *)
|
||||
replace_clause_joinvar_refs(
|
||||
(Node *) get_notclausearg((Expr *) clause),
|
||||
outer_tlist,
|
||||
inner_tlist));
|
||||
replace_clause_joinvar_refs(
|
||||
(Node *) get_notclausearg((Expr *) clause),
|
||||
outer_tlist,
|
||||
inner_tlist));
|
||||
}
|
||||
else if (is_opclause(clause))
|
||||
{
|
||||
return (Node *) make_opclause(
|
||||
replace_opid((Oper *) ((Expr *) clause)->oper),
|
||||
(Var *) replace_clause_joinvar_refs(
|
||||
(Node *) get_leftop((Expr *) clause),
|
||||
outer_tlist,
|
||||
inner_tlist),
|
||||
(Var *) replace_clause_joinvar_refs(
|
||||
(Node *) get_rightop((Expr *) clause),
|
||||
outer_tlist,
|
||||
inner_tlist));
|
||||
replace_opid((Oper *) ((Expr *) clause)->oper),
|
||||
(Var *) replace_clause_joinvar_refs(
|
||||
(Node *) get_leftop((Expr *) clause),
|
||||
outer_tlist,
|
||||
inner_tlist),
|
||||
(Var *) replace_clause_joinvar_refs(
|
||||
(Node *) get_rightop((Expr *) clause),
|
||||
outer_tlist,
|
||||
inner_tlist));
|
||||
}
|
||||
else if (IsA(clause, List))
|
||||
{
|
||||
@@ -379,25 +381,26 @@ replace_clause_joinvar_refs(Node *clause,
|
||||
foreach(subclause, (List *) clause)
|
||||
{
|
||||
t_list = lappend(t_list,
|
||||
replace_clause_joinvar_refs(lfirst(subclause),
|
||||
outer_tlist,
|
||||
inner_tlist));
|
||||
replace_clause_joinvar_refs(lfirst(subclause),
|
||||
outer_tlist,
|
||||
inner_tlist));
|
||||
}
|
||||
return (Node *) t_list;
|
||||
}
|
||||
else if (is_subplan(clause))
|
||||
{
|
||||
/* This is a tad wasteful of space, but it works... */
|
||||
Expr *newclause = (Expr *) copyObject(clause);
|
||||
Expr *newclause = (Expr *) copyObject(clause);
|
||||
|
||||
newclause->args = (List *)
|
||||
replace_clause_joinvar_refs((Node *) newclause->args,
|
||||
outer_tlist,
|
||||
inner_tlist);
|
||||
((SubPlan *) newclause->oper)->sublink->oper = (List *)
|
||||
replace_clause_joinvar_refs(
|
||||
(Node *) ((SubPlan *) newclause->oper)->sublink->oper,
|
||||
outer_tlist,
|
||||
inner_tlist);
|
||||
(Node *) ((SubPlan *) newclause->oper)->sublink->oper,
|
||||
outer_tlist,
|
||||
inner_tlist);
|
||||
return (Node *) newclause;
|
||||
}
|
||||
else if (IsA(clause, CaseExpr))
|
||||
@@ -406,7 +409,8 @@ replace_clause_joinvar_refs(Node *clause,
|
||||
CaseExpr *newnode = makeNode(CaseExpr);
|
||||
|
||||
newnode->casetype = oldnode->casetype;
|
||||
newnode->arg = oldnode->arg; /* XXX should always be null anyway ... */
|
||||
newnode->arg = oldnode->arg; /* XXX should always be null
|
||||
* anyway ... */
|
||||
newnode->args = (List *)
|
||||
replace_clause_joinvar_refs((Node *) oldnode->args,
|
||||
outer_tlist,
|
||||
@@ -494,7 +498,7 @@ replace_joinvar_refs(Var *var, List *outer_tlist, List *inner_tlist)
|
||||
*/
|
||||
static List *
|
||||
tlist_noname_references(Oid nonameid,
|
||||
List *tlist)
|
||||
List *tlist)
|
||||
{
|
||||
List *t_list = NIL;
|
||||
TargetEntry *noname = (TargetEntry *) NULL;
|
||||
@@ -512,13 +516,13 @@ tlist_noname_references(Oid nonameid,
|
||||
oattno = 0;
|
||||
|
||||
noname = makeTargetEntry(xtl->resdom,
|
||||
(Node *) makeVar(nonameid,
|
||||
xtl->resdom->resno,
|
||||
xtl->resdom->restype,
|
||||
xtl->resdom->restypmod,
|
||||
0,
|
||||
nonameid,
|
||||
oattno));
|
||||
(Node *) makeVar(nonameid,
|
||||
xtl->resdom->resno,
|
||||
xtl->resdom->restype,
|
||||
xtl->resdom->restypmod,
|
||||
0,
|
||||
nonameid,
|
||||
oattno));
|
||||
|
||||
t_list = lappend(t_list, noname);
|
||||
}
|
||||
@@ -573,11 +577,12 @@ replace_tlist_with_subplan_refs(List *tlist,
|
||||
Index subvarno,
|
||||
List *subplanTargetList)
|
||||
{
|
||||
List *t;
|
||||
List *t;
|
||||
|
||||
foreach(t, tlist)
|
||||
{
|
||||
TargetEntry *entry = (TargetEntry *) lfirst(t);
|
||||
|
||||
replace_vars_with_subplan_refs((Node *) get_expr(entry),
|
||||
subvarno, subplanTargetList);
|
||||
}
|
||||
@@ -609,19 +614,20 @@ replace_vars_with_subplan_refs(Node *clause,
|
||||
return;
|
||||
if (IsA(clause, Var))
|
||||
{
|
||||
|
||||
/*
|
||||
* Ha! A Var node!
|
||||
*
|
||||
* It could be that this varnode has been created by make_groupplan
|
||||
* and is already set up to reference the subplan target list.
|
||||
* We recognize that case by varno = 1, varnoold = -1,
|
||||
* varattno = varoattno, and varlevelsup = 0. (Probably ought to
|
||||
* have an explicit flag, but this should do for now.)
|
||||
* and is already set up to reference the subplan target list. We
|
||||
* recognize that case by varno = 1, varnoold = -1, varattno =
|
||||
* varoattno, and varlevelsup = 0. (Probably ought to have an
|
||||
* explicit flag, but this should do for now.)
|
||||
*/
|
||||
Var *var = (Var *) clause;
|
||||
Var *var = (Var *) clause;
|
||||
TargetEntry *subplanVar;
|
||||
|
||||
if (var->varno == (Index) 1 &&
|
||||
if (var->varno == (Index) 1 &&
|
||||
var->varnoold == ((Index) -1) &&
|
||||
var->varattno == var->varoattno &&
|
||||
var->varlevelsup == 0)
|
||||
@@ -629,7 +635,7 @@ replace_vars_with_subplan_refs(Node *clause,
|
||||
|
||||
/* Otherwise it had better be in the subplan list. */
|
||||
subplanVar = match_varid(var, subplanTargetList);
|
||||
if (! subplanVar)
|
||||
if (!subplanVar)
|
||||
elog(ERROR, "replace_vars_with_subplan_refs: variable not in target list");
|
||||
|
||||
/*
|
||||
@@ -656,10 +662,11 @@ replace_vars_with_subplan_refs(Node *clause,
|
||||
}
|
||||
else if (IsA(clause, Expr))
|
||||
{
|
||||
|
||||
/*
|
||||
* Recursively scan the arguments of an expression.
|
||||
* NOTE: this must come after is_subplan() case since
|
||||
* subplan is a kind of Expr node.
|
||||
* Recursively scan the arguments of an expression. NOTE: this
|
||||
* must come after is_subplan() case since subplan is a kind of
|
||||
* Expr node.
|
||||
*/
|
||||
foreach(t, ((Expr *) clause)->args)
|
||||
replace_vars_with_subplan_refs(lfirst(t),
|
||||
@@ -671,6 +678,7 @@ replace_vars_with_subplan_refs(Node *clause,
|
||||
else if (IsA(clause, ArrayRef))
|
||||
{
|
||||
ArrayRef *aref = (ArrayRef *) clause;
|
||||
|
||||
foreach(t, aref->refupperindexpr)
|
||||
replace_vars_with_subplan_refs(lfirst(t),
|
||||
subvarno, subplanTargetList);
|
||||
@@ -687,6 +695,7 @@ replace_vars_with_subplan_refs(Node *clause,
|
||||
foreach(t, ((CaseExpr *) clause)->args)
|
||||
{
|
||||
CaseWhen *when = (CaseWhen *) lfirst(t);
|
||||
|
||||
replace_vars_with_subplan_refs(when->expr,
|
||||
subvarno, subplanTargetList);
|
||||
replace_vars_with_subplan_refs(when->result,
|
||||
@@ -767,15 +776,16 @@ set_agg_tlist_references(Agg *aggNode)
|
||||
all_quals_ok = true;
|
||||
foreach(ql, aggNode->plan.qual)
|
||||
{
|
||||
Node *qual = lfirst(ql);
|
||||
List *qualaggs;
|
||||
Node *qual = lfirst(ql);
|
||||
List *qualaggs;
|
||||
|
||||
replace_vars_with_subplan_refs(qual,
|
||||
(Index) 0,
|
||||
subplanTargetList);
|
||||
qualaggs = pull_agg_clause(qual);
|
||||
if (qualaggs == NIL)
|
||||
all_quals_ok = false; /* this qual clause has no agg functions! */
|
||||
all_quals_ok = false; /* this qual clause has no agg
|
||||
* functions! */
|
||||
else
|
||||
aggNode->aggs = nconc(qualaggs, aggNode->aggs);
|
||||
}
|
||||
@@ -800,7 +810,7 @@ pull_agg_clause(Node *clause)
|
||||
return pull_agg_clause(((Iter *) clause)->iterexpr);
|
||||
else if (is_subplan(clause))
|
||||
{
|
||||
SubLink *sublink = ((SubPlan *) ((Expr *) clause)->oper)->sublink;
|
||||
SubLink *sublink = ((SubPlan *) ((Expr *) clause)->oper)->sublink;
|
||||
|
||||
/*
|
||||
* Only the lefthand side of the sublink should be checked for
|
||||
@@ -814,10 +824,11 @@ pull_agg_clause(Node *clause)
|
||||
}
|
||||
else if (IsA(clause, Expr))
|
||||
{
|
||||
|
||||
/*
|
||||
* Recursively scan the arguments of an expression.
|
||||
* NOTE: this must come after is_subplan() case since
|
||||
* subplan is a kind of Expr node.
|
||||
* Recursively scan the arguments of an expression. NOTE: this
|
||||
* must come after is_subplan() case since subplan is a kind of
|
||||
* Expr node.
|
||||
*/
|
||||
foreach(t, ((Expr *) clause)->args)
|
||||
agg_list = nconc(pull_agg_clause(lfirst(t)), agg_list);
|
||||
@@ -830,6 +841,7 @@ pull_agg_clause(Node *clause)
|
||||
else if (IsA(clause, ArrayRef))
|
||||
{
|
||||
ArrayRef *aref = (ArrayRef *) clause;
|
||||
|
||||
foreach(t, aref->refupperindexpr)
|
||||
agg_list = nconc(pull_agg_clause(lfirst(t)), agg_list);
|
||||
foreach(t, aref->reflowerindexpr)
|
||||
@@ -842,6 +854,7 @@ pull_agg_clause(Node *clause)
|
||||
foreach(t, ((CaseExpr *) clause)->args)
|
||||
{
|
||||
CaseWhen *when = (CaseWhen *) lfirst(t);
|
||||
|
||||
agg_list = nconc(agg_list, pull_agg_clause(when->expr));
|
||||
agg_list = nconc(agg_list, pull_agg_clause(when->result));
|
||||
}
|
||||
@@ -951,7 +964,7 @@ del_agg_clause(Node *clause)
|
||||
* GROUP BY clauses and checks for subplans in the havingQual that are being
|
||||
* passed ungrouped variables as parameters. In other contexts, ungrouped
|
||||
* vars in the havingQual will be detected by the parser (see parse_agg.c,
|
||||
* exprIsAggOrGroupCol()). But that routine currently does not check subplans,
|
||||
* exprIsAggOrGroupCol()). But that routine currently does not check subplans,
|
||||
* because the necessary info is not computed until the planner runs.
|
||||
* This ought to be cleaned up someday.
|
||||
*
|
||||
@@ -962,7 +975,7 @@ del_agg_clause(Node *clause)
|
||||
|
||||
void
|
||||
check_having_for_ungrouped_vars(Node *clause, List *groupClause,
|
||||
List *targetList)
|
||||
List *targetList)
|
||||
{
|
||||
List *t;
|
||||
|
||||
@@ -971,8 +984,10 @@ check_having_for_ungrouped_vars(Node *clause, List *groupClause,
|
||||
|
||||
if (IsA(clause, Var))
|
||||
{
|
||||
/* Ignore vars elsewhere in the having clause, since the
|
||||
* parser already checked 'em.
|
||||
|
||||
/*
|
||||
* Ignore vars elsewhere in the having clause, since the parser
|
||||
* already checked 'em.
|
||||
*/
|
||||
}
|
||||
else if (single_node(clause))
|
||||
@@ -986,20 +1001,21 @@ check_having_for_ungrouped_vars(Node *clause, List *groupClause,
|
||||
}
|
||||
else if (is_subplan(clause))
|
||||
{
|
||||
|
||||
/*
|
||||
* The args list of the subplan node represents attributes from outside
|
||||
* passed into the sublink.
|
||||
* The args list of the subplan node represents attributes from
|
||||
* outside passed into the sublink.
|
||||
*/
|
||||
foreach(t, ((Expr *) clause)->args)
|
||||
{
|
||||
bool contained_in_group_clause = false;
|
||||
bool contained_in_group_clause = false;
|
||||
List *gl;
|
||||
|
||||
foreach(gl, groupClause)
|
||||
{
|
||||
if (var_equal(lfirst(t),
|
||||
get_groupclause_expr((GroupClause *)
|
||||
lfirst(gl), targetList)))
|
||||
get_groupclause_expr((GroupClause *)
|
||||
lfirst(gl), targetList)))
|
||||
{
|
||||
contained_in_group_clause = true;
|
||||
break;
|
||||
@@ -1012,23 +1028,25 @@ check_having_for_ungrouped_vars(Node *clause, List *groupClause,
|
||||
}
|
||||
else if (IsA(clause, Expr))
|
||||
{
|
||||
|
||||
/*
|
||||
* Recursively scan the arguments of an expression.
|
||||
* NOTE: this must come after is_subplan() case since
|
||||
* subplan is a kind of Expr node.
|
||||
* Recursively scan the arguments of an expression. NOTE: this
|
||||
* must come after is_subplan() case since subplan is a kind of
|
||||
* Expr node.
|
||||
*/
|
||||
foreach(t, ((Expr *) clause)->args)
|
||||
check_having_for_ungrouped_vars(lfirst(t), groupClause,
|
||||
targetList);
|
||||
targetList);
|
||||
}
|
||||
else if (IsA(clause, List))
|
||||
{
|
||||
|
||||
/*
|
||||
* Recursively scan AND subclauses (see NOTE above).
|
||||
*/
|
||||
foreach(t, ((List *) clause))
|
||||
check_having_for_ungrouped_vars(lfirst(t), groupClause,
|
||||
targetList);
|
||||
targetList);
|
||||
}
|
||||
else if (IsA(clause, Aggref))
|
||||
{
|
||||
@@ -1045,24 +1063,25 @@ check_having_for_ungrouped_vars(Node *clause, List *groupClause,
|
||||
*/
|
||||
foreach(t, aref->refupperindexpr)
|
||||
check_having_for_ungrouped_vars(lfirst(t), groupClause,
|
||||
targetList);
|
||||
targetList);
|
||||
foreach(t, aref->reflowerindexpr)
|
||||
check_having_for_ungrouped_vars(lfirst(t), groupClause,
|
||||
targetList);
|
||||
targetList);
|
||||
check_having_for_ungrouped_vars(aref->refexpr, groupClause,
|
||||
targetList);
|
||||
targetList);
|
||||
check_having_for_ungrouped_vars(aref->refassgnexpr, groupClause,
|
||||
targetList);
|
||||
targetList);
|
||||
}
|
||||
else if (case_clause(clause))
|
||||
{
|
||||
foreach(t, ((CaseExpr *) clause)->args)
|
||||
{
|
||||
CaseWhen *when = (CaseWhen *) lfirst(t);
|
||||
|
||||
check_having_for_ungrouped_vars(when->expr, groupClause,
|
||||
targetList);
|
||||
targetList);
|
||||
check_having_for_ungrouped_vars(when->result, groupClause,
|
||||
targetList);
|
||||
targetList);
|
||||
}
|
||||
check_having_for_ungrouped_vars(((CaseExpr *) clause)->defresult,
|
||||
groupClause, targetList);
|
||||
|
@@ -338,9 +338,7 @@ SS_replace_correlation_vars(Node *expr)
|
||||
}
|
||||
}
|
||||
else if (IsA(expr, Iter))
|
||||
{
|
||||
((Iter *) expr)->iterexpr = SS_replace_correlation_vars(((Iter *) expr)->iterexpr);
|
||||
}
|
||||
else if (single_node(expr))
|
||||
return expr;
|
||||
else if (or_clause(expr) || and_clause(expr) || is_opclause(expr) ||
|
||||
@@ -398,9 +396,7 @@ SS_process_sublinks(Node *expr)
|
||||
((Expr *) expr)->args = (List *)
|
||||
SS_process_sublinks((Node *) ((Expr *) expr)->args);
|
||||
else if (IsA(expr, SubLink))/* got it! */
|
||||
{
|
||||
expr = _make_subplan((SubLink *) expr);
|
||||
}
|
||||
|
||||
return expr;
|
||||
}
|
||||
@@ -529,13 +525,13 @@ SS_pull_subplan(Node *expr)
|
||||
return SS_pull_subplan(((Aggref *) expr)->target);
|
||||
else if (IsA(expr, ArrayRef))
|
||||
{
|
||||
result = SS_pull_subplan((Node *)((ArrayRef *) expr)->refupperindexpr);
|
||||
result = SS_pull_subplan((Node *) ((ArrayRef *) expr)->refupperindexpr);
|
||||
result = nconc(result,
|
||||
SS_pull_subplan((Node*) ((ArrayRef *) expr)->reflowerindexpr));
|
||||
SS_pull_subplan((Node *) ((ArrayRef *) expr)->reflowerindexpr));
|
||||
result = nconc(result,
|
||||
SS_pull_subplan(((ArrayRef *) expr)->refexpr));
|
||||
result = nconc(result,
|
||||
SS_pull_subplan(((ArrayRef *) expr)->refassgnexpr));
|
||||
SS_pull_subplan(((ArrayRef *) expr)->refassgnexpr));
|
||||
}
|
||||
else if (IsA(expr, TargetEntry))
|
||||
return SS_pull_subplan(((TargetEntry *) expr)->expr);
|
||||
|
@@ -15,89 +15,90 @@
|
||||
|
||||
/*
|
||||
* Node_Copy
|
||||
* a macro to simplify calling of copyObject on the specified field
|
||||
* a macro to simplify calling of copyObject on the specified field
|
||||
*/
|
||||
#define Node_Copy(from, newnode, field) newnode->field = copyObject(from->field)
|
||||
|
||||
bool _use_keyset_query_optimizer = FALSE;
|
||||
bool _use_keyset_query_optimizer = FALSE;
|
||||
|
||||
static int inspectOpNode(Expr *expr);
|
||||
static int inspectAndNode(Expr *expr);
|
||||
static int inspectOrNode(Expr *expr);
|
||||
static int TotalExpr;
|
||||
static int inspectOpNode(Expr *expr);
|
||||
static int inspectAndNode(Expr *expr);
|
||||
static int inspectOrNode(Expr *expr);
|
||||
static int TotalExpr;
|
||||
|
||||
/**********************************************************************
|
||||
* This routine transforms query trees with the following form:
|
||||
* SELECT a,b, ... FROM one_table WHERE
|
||||
* (v1 = const1 AND v2 = const2 [ vn = constn ]) OR
|
||||
* (v1 = const3 AND v2 = const4 [ vn = constn ]) OR
|
||||
* (v1 = const5 AND v2 = const6 [ vn = constn ]) OR
|
||||
* ...
|
||||
* [(v1 = constn AND v2 = constn [ vn = constn ])]
|
||||
* This routine transforms query trees with the following form:
|
||||
* SELECT a,b, ... FROM one_table WHERE
|
||||
* (v1 = const1 AND v2 = const2 [ vn = constn ]) OR
|
||||
* (v1 = const3 AND v2 = const4 [ vn = constn ]) OR
|
||||
* (v1 = const5 AND v2 = const6 [ vn = constn ]) OR
|
||||
* ...
|
||||
* [(v1 = constn AND v2 = constn [ vn = constn ])]
|
||||
*
|
||||
* into
|
||||
* into
|
||||
*
|
||||
* SELECT a,b, ... FROM one_table WHERE
|
||||
* (v1 = const1 AND v2 = const2 [ vn = constn ]) UNION
|
||||
* SELECT a,b, ... FROM one_table WHERE
|
||||
* (v1 = const3 AND v2 = const4 [ vn = constn ]) UNION
|
||||
* SELECT a,b, ... FROM one_table WHERE
|
||||
* (v1 = const5 AND v2 = const6 [ vn = constn ]) UNION
|
||||
* ...
|
||||
* SELECT a,b, ... FROM one_table WHERE
|
||||
* [(v1 = constn AND v2 = constn [ vn = constn ])]
|
||||
* SELECT a,b, ... FROM one_table WHERE
|
||||
* (v1 = const1 AND v2 = const2 [ vn = constn ]) UNION
|
||||
* SELECT a,b, ... FROM one_table WHERE
|
||||
* (v1 = const3 AND v2 = const4 [ vn = constn ]) UNION
|
||||
* SELECT a,b, ... FROM one_table WHERE
|
||||
* (v1 = const5 AND v2 = const6 [ vn = constn ]) UNION
|
||||
* ...
|
||||
* SELECT a,b, ... FROM one_table WHERE
|
||||
* [(v1 = constn AND v2 = constn [ vn = constn ])]
|
||||
*
|
||||
*
|
||||
* To qualify for transformation the query must not be a sub select,
|
||||
* a HAVING, or a GROUP BY. It must be a single table and have KSQO
|
||||
* set to 'on'.
|
||||
* To qualify for transformation the query must not be a sub select,
|
||||
* a HAVING, or a GROUP BY. It must be a single table and have KSQO
|
||||
* set to 'on'.
|
||||
*
|
||||
* The primary use of this transformation is to avoid the exponrntial
|
||||
* memory consumption of cnfify() and to make use of index access
|
||||
* methods.
|
||||
* The primary use of this transformation is to avoid the exponrntial
|
||||
* memory consumption of cnfify() and to make use of index access
|
||||
* methods.
|
||||
*
|
||||
* daveh@insightdist.com 1998-08-31
|
||||
* daveh@insightdist.com 1998-08-31
|
||||
*
|
||||
* May want to also prune out duplicate terms.
|
||||
* May want to also prune out duplicate terms.
|
||||
**********************************************************************/
|
||||
void
|
||||
transformKeySetQuery(Query *origNode)
|
||||
{
|
||||
/* Qualify as a key set query candidate */
|
||||
if (_use_keyset_query_optimizer == FALSE ||
|
||||
origNode->groupClause ||
|
||||
origNode->havingQual ||
|
||||
origNode->hasAggs ||
|
||||
origNode->utilityStmt ||
|
||||
origNode->unionClause ||
|
||||
origNode->unionall ||
|
||||
origNode->hasSubLinks ||
|
||||
origNode->commandType != CMD_SELECT)
|
||||
/* Qualify as a key set query candidate */
|
||||
if (_use_keyset_query_optimizer == FALSE ||
|
||||
origNode->groupClause ||
|
||||
origNode->havingQual ||
|
||||
origNode->hasAggs ||
|
||||
origNode->utilityStmt ||
|
||||
origNode->unionClause ||
|
||||
origNode->unionall ||
|
||||
origNode->hasSubLinks ||
|
||||
origNode->commandType != CMD_SELECT)
|
||||
return;
|
||||
|
||||
/* Qualify single table query */
|
||||
/* Qualify single table query */
|
||||
if (length(origNode->rtable) != 1)
|
||||
return;
|
||||
|
||||
/* Sorry about the global, not worth passing around */
|
||||
/* 9 expressions seems like a good number. More than 9 */
|
||||
/* and it starts to slow down quite a bit */
|
||||
TotalExpr = 0;
|
||||
/*************************/
|
||||
/* Qualify where clause */
|
||||
/*************************/
|
||||
if ( ! inspectOrNode((Expr*)origNode->qual) || TotalExpr < 9)
|
||||
return;
|
||||
|
||||
/* Copy essential elements into a union node */
|
||||
while (((Expr*)origNode->qual)->opType == OR_EXPR) {
|
||||
/* Sorry about the global, not worth passing around */
|
||||
/* 9 expressions seems like a good number. More than 9 */
|
||||
/* and it starts to slow down quite a bit */
|
||||
TotalExpr = 0;
|
||||
/*************************/
|
||||
/* Qualify where clause */
|
||||
/*************************/
|
||||
if (!inspectOrNode((Expr *) origNode->qual) || TotalExpr < 9)
|
||||
return;
|
||||
|
||||
/* Copy essential elements into a union node */
|
||||
while (((Expr *) origNode->qual)->opType == OR_EXPR)
|
||||
{
|
||||
Query *unionNode = makeNode(Query);
|
||||
|
||||
/* Pull up Expr = */
|
||||
unionNode->qual = lsecond(((Expr*)origNode->qual)->args);
|
||||
/* Pull up Expr = */
|
||||
unionNode->qual = lsecond(((Expr *) origNode->qual)->args);
|
||||
|
||||
/* Pull up balance of tree */
|
||||
origNode->qual = lfirst(((Expr*)origNode->qual)->args);
|
||||
/* Pull up balance of tree */
|
||||
origNode->qual = lfirst(((Expr *) origNode->qual)->args);
|
||||
|
||||
unionNode->commandType = origNode->commandType;
|
||||
unionNode->resultRelation = origNode->resultRelation;
|
||||
@@ -121,37 +122,38 @@ transformKeySetQuery(Query *origNode)
|
||||
|
||||
static int
|
||||
/**********************************************************************
|
||||
* Checks for 1 or more OR terms w/ 1 or more AND terms.
|
||||
* AND terms must be equal in size.
|
||||
* Returns the number of each AND term.
|
||||
* Checks for 1 or more OR terms w/ 1 or more AND terms.
|
||||
* AND terms must be equal in size.
|
||||
* Returns the number of each AND term.
|
||||
**********************************************************************/
|
||||
inspectOrNode(Expr *expr)
|
||||
{
|
||||
int rc;
|
||||
Expr *firstExpr, *secondExpr;
|
||||
int rc;
|
||||
Expr *firstExpr,
|
||||
*secondExpr;
|
||||
|
||||
if ( ! (expr && nodeTag(expr) == T_Expr && expr->opType == OR_EXPR))
|
||||
if (!(expr && nodeTag(expr) == T_Expr && expr->opType == OR_EXPR))
|
||||
return 0;
|
||||
|
||||
firstExpr = lfirst(expr->args);
|
||||
secondExpr = lsecond(expr->args);
|
||||
if (nodeTag(firstExpr) != T_Expr || nodeTag(secondExpr) != T_Expr)
|
||||
if (nodeTag(firstExpr) != T_Expr || nodeTag(secondExpr) != T_Expr)
|
||||
return 0;
|
||||
|
||||
if (firstExpr->opType == OR_EXPR && secondExpr->opType == AND_EXPR)
|
||||
{
|
||||
if ((rc = inspectOrNode(firstExpr)) == 0)
|
||||
if ((rc = inspectOrNode(firstExpr)) == 0)
|
||||
return 0;
|
||||
|
||||
return (rc == inspectAndNode(secondExpr)) ? rc : 0;
|
||||
return (rc == inspectAndNode(secondExpr)) ? rc : 0;
|
||||
}
|
||||
else if (firstExpr->opType == AND_EXPR && secondExpr->opType == AND_EXPR)
|
||||
{
|
||||
if ((rc = inspectAndNode(firstExpr)) == 0)
|
||||
if ((rc = inspectAndNode(firstExpr)) == 0)
|
||||
return 0;
|
||||
|
||||
return (rc == inspectAndNode(secondExpr)) ? rc : 0;
|
||||
|
||||
|
||||
return (rc == inspectAndNode(secondExpr)) ? rc : 0;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -160,34 +162,33 @@ inspectOrNode(Expr *expr)
|
||||
|
||||
static int
|
||||
/**********************************************************************
|
||||
* Check for one or more AND terms. Each sub-term must be a T_Const
|
||||
* T_Var expression.
|
||||
* Returns the number of AND terms.
|
||||
* Check for one or more AND terms. Each sub-term must be a T_Const
|
||||
* T_Var expression.
|
||||
* Returns the number of AND terms.
|
||||
**********************************************************************/
|
||||
inspectAndNode(Expr *expr)
|
||||
{
|
||||
int rc;
|
||||
Expr *firstExpr, *secondExpr;
|
||||
int rc;
|
||||
Expr *firstExpr,
|
||||
*secondExpr;
|
||||
|
||||
if ( ! (expr && nodeTag(expr) == T_Expr && expr->opType == AND_EXPR))
|
||||
if (!(expr && nodeTag(expr) == T_Expr && expr->opType == AND_EXPR))
|
||||
return 0;
|
||||
|
||||
firstExpr = lfirst(expr->args);
|
||||
secondExpr = lsecond(expr->args);
|
||||
if (nodeTag(firstExpr) != T_Expr || nodeTag(secondExpr) != T_Expr)
|
||||
if (nodeTag(firstExpr) != T_Expr || nodeTag(secondExpr) != T_Expr)
|
||||
return 0;
|
||||
|
||||
if (firstExpr->opType == AND_EXPR &&
|
||||
secondExpr->opType == OP_EXPR && inspectOpNode(secondExpr))
|
||||
secondExpr->opType == OP_EXPR && inspectOpNode(secondExpr))
|
||||
{
|
||||
rc = inspectAndNode(firstExpr);
|
||||
return ((rc) ? (rc + 1) : 0); /* Add up the AND nodes */
|
||||
rc = inspectAndNode(firstExpr);
|
||||
return ((rc) ? (rc + 1) : 0); /* Add up the AND nodes */
|
||||
}
|
||||
else if (firstExpr->opType == OP_EXPR && inspectOpNode(firstExpr) &&
|
||||
secondExpr->opType == OP_EXPR && inspectOpNode(secondExpr))
|
||||
{
|
||||
else if (firstExpr->opType == OP_EXPR && inspectOpNode(firstExpr) &&
|
||||
secondExpr->opType == OP_EXPR && inspectOpNode(secondExpr))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -195,12 +196,13 @@ inspectAndNode(Expr *expr)
|
||||
|
||||
static int
|
||||
/******************************************************************
|
||||
* Return TRUE if T_Var = T_Const, else FALSE
|
||||
* Actually it does not test for =. Need to do this!
|
||||
* Return TRUE if T_Var = T_Const, else FALSE
|
||||
* Actually it does not test for =. Need to do this!
|
||||
******************************************************************/
|
||||
inspectOpNode(Expr *expr)
|
||||
{
|
||||
Expr *firstExpr, *secondExpr;
|
||||
Expr *firstExpr,
|
||||
*secondExpr;
|
||||
|
||||
if (nodeTag(expr) != T_Expr || expr->opType != OP_EXPR)
|
||||
return FALSE;
|
||||
@@ -209,5 +211,5 @@ inspectOpNode(Expr *expr)
|
||||
|
||||
firstExpr = lfirst(expr->args);
|
||||
secondExpr = lsecond(expr->args);
|
||||
return (firstExpr && secondExpr && nodeTag(firstExpr) == T_Var && nodeTag(secondExpr) == T_Const);
|
||||
return (firstExpr && secondExpr && nodeTag(firstExpr) == T_Var && nodeTag(secondExpr) == T_Const);
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepqual.c,v 1.14 1999/02/15 01:06:59 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepqual.c,v 1.15 1999/05/25 16:09:45 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -106,8 +106,9 @@ find_nots(Expr *qual)
|
||||
|
||||
if (is_opclause((Node *) qual))
|
||||
{
|
||||
Expr *left = (Expr *) get_leftop(qual);
|
||||
Expr *right = (Expr *) get_rightop(qual);
|
||||
Expr *left = (Expr *) get_leftop(qual);
|
||||
Expr *right = (Expr *) get_rightop(qual);
|
||||
|
||||
if (right)
|
||||
return make_clause(qual->opType, qual->oper,
|
||||
lcons(find_nots(left),
|
||||
@@ -162,8 +163,9 @@ normalize(Expr *qual)
|
||||
|
||||
if (is_opclause((Node *) qual))
|
||||
{
|
||||
Expr *left = (Expr *) get_leftop(qual);
|
||||
Expr *right = (Expr *) get_rightop(qual);
|
||||
Expr *left = (Expr *) get_leftop(qual);
|
||||
Expr *right = (Expr *) get_rightop(qual);
|
||||
|
||||
if (right)
|
||||
return make_clause(qual->opType, qual->oper,
|
||||
lcons(normalize(left),
|
||||
@@ -229,8 +231,9 @@ qual_cleanup(Expr *qual)
|
||||
|
||||
if (is_opclause((Node *) qual))
|
||||
{
|
||||
Expr *left = (Expr *) get_leftop(qual);
|
||||
Expr *right = (Expr *) get_rightop(qual);
|
||||
Expr *left = (Expr *) get_leftop(qual);
|
||||
Expr *right = (Expr *) get_rightop(qual);
|
||||
|
||||
if (right)
|
||||
return (List *) make_clause(qual->opType, qual->oper,
|
||||
lcons(qual_cleanup(left),
|
||||
@@ -295,8 +298,9 @@ pull_args(Expr *qual)
|
||||
|
||||
if (is_opclause((Node *) qual))
|
||||
{
|
||||
Expr *left = (Expr *) get_leftop(qual);
|
||||
Expr *right = (Expr *) get_rightop(qual);
|
||||
Expr *left = (Expr *) get_leftop(qual);
|
||||
Expr *right = (Expr *) get_rightop(qual);
|
||||
|
||||
if (right)
|
||||
return make_clause(qual->opType, qual->oper,
|
||||
lcons(pull_args(left),
|
||||
@@ -485,7 +489,7 @@ or_normalize(List *orlist)
|
||||
{
|
||||
return (or_normalize(lcons(distribute_args(lfirst(new_orlist),
|
||||
((Expr *) distributable)->args),
|
||||
lnext(new_orlist))));
|
||||
lnext(new_orlist))));
|
||||
}
|
||||
else
|
||||
return orlist;
|
||||
@@ -537,8 +541,9 @@ remove_ands(Expr *qual)
|
||||
return NIL;
|
||||
if (is_opclause((Node *) qual))
|
||||
{
|
||||
Expr *left = (Expr *) get_leftop(qual);
|
||||
Expr *right = (Expr *) get_rightop(qual);
|
||||
Expr *left = (Expr *) get_leftop(qual);
|
||||
Expr *right = (Expr *) get_rightop(qual);
|
||||
|
||||
if (right)
|
||||
return (List *) make_clause(qual->opType, qual->oper,
|
||||
lcons(remove_ands(left),
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.20 1999/05/17 17:03:18 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.21 1999/05/25 16:09:46 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -211,8 +211,8 @@ replace_matching_resname(List *new_tlist, List *old_tlist)
|
||||
* locks.
|
||||
*
|
||||
* So, copy all these entries to the end of the target list and set their
|
||||
* 'resjunk' value to true to show that these are special attributes and
|
||||
* have to be treated specially by the executor!
|
||||
* 'resjunk' value to true to show that these are special attributes
|
||||
* and have to be treated specially by the executor!
|
||||
*/
|
||||
foreach(temp, old_tlist)
|
||||
{
|
||||
@@ -231,28 +231,27 @@ replace_matching_resname(List *new_tlist, List *old_tlist)
|
||||
}
|
||||
|
||||
/*
|
||||
* Also it is possible that the parser or rewriter added
|
||||
* some junk attributes to hold GROUP BY expressions which
|
||||
* are not part of the result attributes.
|
||||
* We can simply identify them by looking at the resgroupref
|
||||
* in the TLE's resdom, which is a unique number telling which
|
||||
* TLE belongs to which GroupClause.
|
||||
* Also it is possible that the parser or rewriter added some junk
|
||||
* attributes to hold GROUP BY expressions which are not part of
|
||||
* the result attributes. We can simply identify them by looking
|
||||
* at the resgroupref in the TLE's resdom, which is a unique
|
||||
* number telling which TLE belongs to which GroupClause.
|
||||
*/
|
||||
if (old_tle->resdom->resgroupref > 0)
|
||||
{
|
||||
bool already_there = FALSE;
|
||||
TargetEntry *new_tle;
|
||||
Resdom *newresno;
|
||||
bool already_there = FALSE;
|
||||
TargetEntry *new_tle;
|
||||
Resdom *newresno;
|
||||
|
||||
/*
|
||||
* Check if the tle is already in the new list
|
||||
*/
|
||||
foreach(i, t_list)
|
||||
{
|
||||
new_tle = (TargetEntry *)lfirst(i);
|
||||
new_tle = (TargetEntry *) lfirst(i);
|
||||
|
||||
if (new_tle->resdom->resgroupref ==
|
||||
old_tle->resdom->resgroupref)
|
||||
if (new_tle->resdom->resgroupref ==
|
||||
old_tle->resdom->resgroupref)
|
||||
{
|
||||
already_there = TRUE;
|
||||
break;
|
||||
@@ -349,8 +348,8 @@ new_relation_targetlist(Oid relid, Index rt_index, NodeTag node_type)
|
||||
TargetEntry *temp_list = NULL;
|
||||
|
||||
temp_var = makeVar(rt_index, attno, atttype,
|
||||
get_atttypmod(relid, attno),
|
||||
0, rt_index, attno);
|
||||
get_atttypmod(relid, attno),
|
||||
0, rt_index, attno);
|
||||
|
||||
temp_list = makeTargetEntry(makeResdom(attno,
|
||||
atttype,
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.30 1999/02/18 00:49:32 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.31 1999/05/25 16:09:47 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -223,8 +223,8 @@ plan_inherit_queries(Query *parse, Index rt_index)
|
||||
List *union_relids = NIL;
|
||||
|
||||
union_relids = find_all_inheritors(lconsi(rt_entry->relid,
|
||||
NIL),
|
||||
NIL);
|
||||
NIL),
|
||||
NIL);
|
||||
|
||||
/*
|
||||
* Remove the flag for this relation, since we're about to handle it
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.33 1999/05/10 00:45:24 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.34 1999/05/25 16:09:50 momjian Exp $
|
||||
*
|
||||
* HISTORY
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
@@ -84,7 +84,7 @@ bool
|
||||
is_opclause(Node *clause)
|
||||
{
|
||||
return (clause != NULL &&
|
||||
nodeTag(clause) == T_Expr && ((Expr *) clause)->opType == OP_EXPR);
|
||||
nodeTag(clause) == T_Expr && ((Expr *) clause)->opType == OP_EXPR);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -163,7 +163,7 @@ bool
|
||||
is_funcclause(Node *clause)
|
||||
{
|
||||
return (clause != NULL &&
|
||||
nodeTag(clause) == T_Expr && ((Expr *) clause)->opType == FUNC_EXPR);
|
||||
nodeTag(clause) == T_Expr && ((Expr *) clause)->opType == FUNC_EXPR);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -320,7 +320,7 @@ bool
|
||||
case_clause(Node *clause)
|
||||
{
|
||||
return (clause != NULL &&
|
||||
nodeTag(clause) == T_CaseExpr);
|
||||
nodeTag(clause) == T_CaseExpr);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
@@ -369,7 +369,7 @@ pull_constant_clauses(List *quals, List **constantQual)
|
||||
*
|
||||
*/
|
||||
void
|
||||
clause_get_relids_vars(Node *clause, Relids *relids, List **vars)
|
||||
clause_get_relids_vars(Node *clause, Relids * relids, List **vars)
|
||||
{
|
||||
List *clvars = pull_var_clause(clause);
|
||||
List *var_list = NIL;
|
||||
@@ -515,9 +515,9 @@ qual_clause_p(Node *clause)
|
||||
return false; /* unary opclauses need not apply */
|
||||
|
||||
/* How about Param-s ? - vadim 02/03/98 */
|
||||
if (IsA(leftop, Var) && IsA(rightop, Const))
|
||||
if (IsA(leftop, Var) &&IsA(rightop, Const))
|
||||
return true;
|
||||
if (IsA(rightop, Var) && IsA(leftop, Const))
|
||||
if (IsA(rightop, Var) &&IsA(leftop, Const))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@@ -646,14 +646,14 @@ get_relattval(Node *clause,
|
||||
if (!right)
|
||||
goto default_results;
|
||||
|
||||
if (IsA(left, Var) && IsA(right, Const))
|
||||
if (IsA(left, Var) &&IsA(right, Const))
|
||||
{
|
||||
*relid = left->varno;
|
||||
*attno = left->varattno;
|
||||
*constval = ((Const *) right)->constvalue;
|
||||
*flag = (_SELEC_CONSTANT_RIGHT_ | _SELEC_IS_CONSTANT_);
|
||||
}
|
||||
else if (IsA(left, Var) && IsA(right, Param))
|
||||
else if (IsA(left, Var) &&IsA(right, Param))
|
||||
{
|
||||
*relid = left->varno;
|
||||
*attno = left->varattno;
|
||||
@@ -669,7 +669,7 @@ get_relattval(Node *clause,
|
||||
*constval = ((Const *) right)->constvalue;
|
||||
*flag = (_SELEC_CONSTANT_RIGHT_ | _SELEC_IS_CONSTANT_);
|
||||
}
|
||||
else if (IsA(right, Var) && IsA(left, Const))
|
||||
else if (IsA(right, Var) &&IsA(left, Const))
|
||||
{
|
||||
*relid = right->varno;
|
||||
*attno = right->varattno;
|
||||
@@ -723,16 +723,16 @@ get_rels_atts(Node *clause,
|
||||
{
|
||||
if (is_opclause(clause))
|
||||
{
|
||||
Var *left = get_leftop((Expr *) clause);
|
||||
Var *right = get_rightop((Expr *) clause);
|
||||
Var *left = get_leftop((Expr *) clause);
|
||||
Var *right = get_rightop((Expr *) clause);
|
||||
|
||||
if (left && right)
|
||||
{
|
||||
bool var_left = IsA(left, Var);
|
||||
bool var_right = IsA(right, Var);
|
||||
bool varexpr_left = (bool) ((IsA(left, Func) || IsA(left, Oper)) &&
|
||||
contain_var_clause((Node *) left));
|
||||
bool varexpr_right = (bool) ((IsA(right, Func) || IsA(right, Oper)) &&
|
||||
bool var_left = IsA(left, Var);
|
||||
bool var_right = IsA(right, Var);
|
||||
bool varexpr_left = (bool) ((IsA(left, Func) ||IsA(left, Oper)) &&
|
||||
contain_var_clause((Node *) left));
|
||||
bool varexpr_right = (bool) ((IsA(right, Func) ||IsA(right, Oper)) &&
|
||||
contain_var_clause((Node *) right));
|
||||
|
||||
if (var_left && var_right)
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/Attic/indexnode.c,v 1.14 1999/02/13 23:16:43 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/Attic/indexnode.c,v 1.15 1999/05/25 16:09:53 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -33,7 +33,7 @@ static List *find_secondary_index(Query *root, Oid relid);
|
||||
*
|
||||
*/
|
||||
List *
|
||||
find_relation_indices(Query *root, RelOptInfo *rel)
|
||||
find_relation_indices(Query *root, RelOptInfo * rel)
|
||||
{
|
||||
if (rel->indexed)
|
||||
return find_secondary_index(root, lfirsti(rel->relids));
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/joininfo.c,v 1.19 1999/02/22 05:26:26 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/joininfo.c,v 1.20 1999/05/25 16:09:54 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -38,11 +38,11 @@
|
||||
JoinInfo *
|
||||
joininfo_member(List *join_relids, List *joininfo_list)
|
||||
{
|
||||
List *i;
|
||||
List *i;
|
||||
|
||||
foreach(i, joininfo_list)
|
||||
{
|
||||
JoinInfo *joininfo = (JoinInfo *)lfirst(i);
|
||||
JoinInfo *joininfo = (JoinInfo *) lfirst(i);
|
||||
|
||||
if (same(join_relids, joininfo->unjoined_relids))
|
||||
return joininfo;
|
||||
@@ -62,7 +62,7 @@ joininfo_member(List *join_relids, List *joininfo_list)
|
||||
*
|
||||
*/
|
||||
JoinInfo *
|
||||
find_joininfo_node(RelOptInfo *this_rel, Relids join_relids)
|
||||
find_joininfo_node(RelOptInfo * this_rel, Relids join_relids)
|
||||
{
|
||||
JoinInfo *joininfo = joininfo_member(join_relids,
|
||||
this_rel->joininfo);
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/Attic/keys.c,v 1.19 1999/02/20 18:01:02 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/Attic/keys.c,v 1.20 1999/05/25 16:09:56 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -54,7 +54,7 @@ static bool equal_indexkey_var(int index_key, Var *var);
|
||||
*
|
||||
*/
|
||||
bool
|
||||
match_indexkey_operand(int indexkey, Var *operand, RelOptInfo *rel)
|
||||
match_indexkey_operand(int indexkey, Var *operand, RelOptInfo * rel)
|
||||
{
|
||||
if (IsA(operand, Var) &&
|
||||
(lfirsti(rel->relids) == operand->varno) &&
|
||||
@@ -112,7 +112,7 @@ extract_join_key(JoinKey *jk, int outer_or_inner)
|
||||
*
|
||||
* See the top of optimizer/path/pathkeys.c for a description of pathkeys.
|
||||
* Each pathkey is ordered by its join order, so they not pre-ordered to
|
||||
* match. We must search them ourselves.
|
||||
* match. We must search them ourselves.
|
||||
*
|
||||
* This gets called a lot, so it is optimized.
|
||||
*/
|
||||
@@ -128,31 +128,33 @@ pathkeys_match(List *keys1, List *keys2, int *better_key)
|
||||
key1 != NIL && key2 != NIL;
|
||||
key1 = lnext(key1), key2 = lnext(key2))
|
||||
{
|
||||
List *i;
|
||||
List *i;
|
||||
|
||||
if (key1_subsetof_key2)
|
||||
foreach(i, lfirst(key1))
|
||||
{
|
||||
Var *subkey = lfirst(i);
|
||||
|
||||
if (!member(subkey, lfirst(key2)))
|
||||
{
|
||||
Var *subkey = lfirst(i);
|
||||
if (!member(subkey, lfirst(key2)))
|
||||
{
|
||||
key1_subsetof_key2 = false;
|
||||
break;
|
||||
}
|
||||
key1_subsetof_key2 = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (key2_subsetof_key1)
|
||||
foreach(i, lfirst(key2))
|
||||
{
|
||||
Var *subkey = lfirst(i);
|
||||
|
||||
if (!member(subkey, lfirst(key1)))
|
||||
{
|
||||
Var *subkey = lfirst(i);
|
||||
if (!member(subkey, lfirst(key1)))
|
||||
{
|
||||
key2_subsetof_key1 = false;
|
||||
break;
|
||||
}
|
||||
key2_subsetof_key1 = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!key1_subsetof_key2 && !key2_subsetof_key1)
|
||||
break; /* no need to continue comparisons. */
|
||||
break; /* no need to continue comparisons. */
|
||||
}
|
||||
|
||||
if (!key1_subsetof_key2 && !key2_subsetof_key1)
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/Attic/ordering.c,v 1.15 1999/02/13 23:16:46 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/Attic/ordering.c,v 1.16 1999/05/25 16:09:57 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -19,7 +19,7 @@
|
||||
#include "optimizer/ordering.h"
|
||||
|
||||
static bool sortops_order_match(Oid *ordering1, Oid *ordering2,
|
||||
int *better_sort);
|
||||
int *better_sort);
|
||||
|
||||
/*
|
||||
* equal_path_ordering
|
||||
@@ -31,12 +31,12 @@ pathorder_match(PathOrder *path_ordering1,
|
||||
PathOrder *path_ordering2,
|
||||
int *better_sort)
|
||||
{
|
||||
|
||||
|
||||
*better_sort = 0;
|
||||
|
||||
if (path_ordering1 == path_ordering2)
|
||||
return true;
|
||||
|
||||
|
||||
if (!path_ordering2)
|
||||
{
|
||||
*better_sort = 1;
|
||||
@@ -51,15 +51,13 @@ pathorder_match(PathOrder *path_ordering1,
|
||||
|
||||
if (path_ordering1->ordtype == MERGE_ORDER &&
|
||||
path_ordering2->ordtype == MERGE_ORDER)
|
||||
{
|
||||
return equal(path_ordering1->ord.merge, path_ordering2->ord.merge);
|
||||
}
|
||||
else if (path_ordering1->ordtype == SORTOP_ORDER &&
|
||||
path_ordering2->ordtype == SORTOP_ORDER)
|
||||
{
|
||||
return sortops_order_match(path_ordering1->ord.sortop,
|
||||
path_ordering2->ord.sortop,
|
||||
better_sort);
|
||||
path_ordering2->ord.sortop,
|
||||
better_sort);
|
||||
}
|
||||
else if (path_ordering1->ordtype == MERGE_ORDER &&
|
||||
path_ordering2->ordtype == SORTOP_ORDER)
|
||||
@@ -112,7 +110,7 @@ equal_path_merge_ordering(Oid *path_ordering,
|
||||
*/
|
||||
bool
|
||||
equal_merge_ordering(MergeOrder *merge_ordering1,
|
||||
MergeOrder *merge_ordering2)
|
||||
MergeOrder *merge_ordering2)
|
||||
{
|
||||
return equal(merge_ordering1, merge_ordering2);
|
||||
}
|
||||
@@ -133,7 +131,7 @@ sortops_order_match(Oid *ordering1, Oid *ordering2, int *better_sort)
|
||||
int i = 0;
|
||||
|
||||
*better_sort = 0;
|
||||
|
||||
|
||||
if (ordering1 == ordering2)
|
||||
return true;
|
||||
|
||||
@@ -142,13 +140,13 @@ sortops_order_match(Oid *ordering1, Oid *ordering2, int *better_sort)
|
||||
*better_sort = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (!ordering1)
|
||||
{
|
||||
*better_sort = 2;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
while (ordering1[i] != 0 && ordering2[i] != 0)
|
||||
{
|
||||
if (ordering1[i] != ordering2[i])
|
||||
@@ -167,6 +165,6 @@ sortops_order_match(Oid *ordering1, Oid *ordering2, int *better_sort)
|
||||
*better_sort = 2;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return ordering1[i] == 0 && ordering2[i] == 0;
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.40 1999/02/21 03:48:54 scrappy Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.41 1999/05/25 16:09:58 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -62,7 +62,7 @@ path_is_cheaper(Path *path1, Path *path2)
|
||||
*
|
||||
*/
|
||||
Path *
|
||||
set_cheapest(RelOptInfo *parent_rel, List *pathlist)
|
||||
set_cheapest(RelOptInfo * parent_rel, List *pathlist)
|
||||
{
|
||||
List *p;
|
||||
Path *cheapest_so_far;
|
||||
@@ -99,14 +99,14 @@ set_cheapest(RelOptInfo *parent_rel, List *pathlist)
|
||||
*
|
||||
*/
|
||||
List *
|
||||
add_pathlist(RelOptInfo *parent_rel, List *unique_paths, List *new_paths)
|
||||
add_pathlist(RelOptInfo * parent_rel, List *unique_paths, List *new_paths)
|
||||
{
|
||||
List *p1;
|
||||
|
||||
foreach(p1, new_paths)
|
||||
{
|
||||
Path *new_path = (Path *) lfirst(p1);
|
||||
Path *old_path;
|
||||
Path *old_path;
|
||||
bool is_new;
|
||||
|
||||
/* Is this new path already in unique_paths? */
|
||||
@@ -174,7 +174,7 @@ better_path(Path *new_path, List *unique_paths, bool *is_new)
|
||||
|
||||
#ifdef OPTDUP_DEBUG
|
||||
if (!pathkeys_match(new_path->pathkeys, path->pathkeys, &better_key) ||
|
||||
better_key != 0)
|
||||
better_key != 0)
|
||||
{
|
||||
printf("betterkey = %d\n", better_key);
|
||||
printf("newpath\n");
|
||||
@@ -182,13 +182,15 @@ better_path(Path *new_path, List *unique_paths, bool *is_new)
|
||||
printf("oldpath\n");
|
||||
pprint(path->pathkeys);
|
||||
if (path->pathkeys && new_path->pathkeys &&
|
||||
length(lfirst(path->pathkeys)) >= 2/* &&
|
||||
length(lfirst(path->pathkeys)) <
|
||||
length(lfirst(new_path->pathkeys))*/)
|
||||
sleep(0); /* set breakpoint here */
|
||||
length(lfirst(path->pathkeys)) >= 2 /* &&
|
||||
* length(lfirst(path->pa
|
||||
* thkeys)) <
|
||||
* length(lfirst(new_path
|
||||
->pathkeys)) */ )
|
||||
sleep(0); /* set breakpoint here */
|
||||
}
|
||||
if (!pathorder_match(new_path->pathorder, path->pathorder,
|
||||
&better_sort) ||
|
||||
&better_sort) ||
|
||||
better_sort != 0)
|
||||
{
|
||||
printf("neword\n");
|
||||
@@ -199,25 +201,26 @@ better_path(Path *new_path, List *unique_paths, bool *is_new)
|
||||
#endif
|
||||
|
||||
if (pathkeys_match(new_path->pathkeys, path->pathkeys,
|
||||
&better_key) &&
|
||||
&better_key) &&
|
||||
pathorder_match(new_path->pathorder, path->pathorder,
|
||||
&better_sort))
|
||||
&better_sort))
|
||||
{
|
||||
|
||||
/*
|
||||
* Replace pathkeys that match exactly, {{1,2}}, {{1,2}}
|
||||
* Replace pathkeys {{1,2}} with {{1,2,3}}} if the latter is not
|
||||
* more expensive and replace unordered path with ordered
|
||||
* path if it is not more expensive. Favor sorted keys
|
||||
* over unsorted keys in the same way.
|
||||
* Replace pathkeys {{1,2}} with {{1,2,3}}} if the latter is
|
||||
* not more expensive and replace unordered path with ordered
|
||||
* path if it is not more expensive. Favor sorted keys over
|
||||
* unsorted keys in the same way.
|
||||
*/
|
||||
/* same keys, and new is cheaper, use it */
|
||||
if ((better_key == 0 && better_sort == 0 &&
|
||||
/* same keys, and new is cheaper, use it */
|
||||
if ((better_key == 0 && better_sort == 0 &&
|
||||
new_path->path_cost < path->path_cost) ||
|
||||
|
||||
/* new is better, and cheaper, use it */
|
||||
/* new is better, and cheaper, use it */
|
||||
(((better_key == 1 && better_sort != 2) ||
|
||||
(better_key != 2 && better_sort == 1)) &&
|
||||
new_path->path_cost <= path->path_cost))
|
||||
new_path->path_cost <= path->path_cost))
|
||||
{
|
||||
#ifdef OPTDUP_DEBUG
|
||||
printf("replace with new %p old %p better key %d better sort %d\n", &new_path, &path, better_key, better_sort);
|
||||
@@ -230,14 +233,14 @@ better_path(Path *new_path, List *unique_paths, bool *is_new)
|
||||
return path;
|
||||
}
|
||||
|
||||
/* same keys, new is more expensive, stop */
|
||||
/* same keys, new is more expensive, stop */
|
||||
if ((better_key == 0 && better_sort == 0 &&
|
||||
new_path->path_cost >= path->path_cost) ||
|
||||
|
||||
/* old is better, and less expensive, stop */
|
||||
/* old is better, and less expensive, stop */
|
||||
(((better_key == 2 && better_sort != 1) ||
|
||||
(better_key != 1 && better_sort == 2)) &&
|
||||
new_path->path_cost >= path->path_cost))
|
||||
new_path->path_cost >= path->path_cost))
|
||||
{
|
||||
#ifdef OPTDUP_DEBUG
|
||||
printf("skip new %p old %p better key %d better sort %d\n", &new_path, &path, better_key, better_sort);
|
||||
@@ -253,11 +256,11 @@ better_path(Path *new_path, List *unique_paths, bool *is_new)
|
||||
}
|
||||
|
||||
#ifdef OPTDUP_DEBUG
|
||||
printf("add new %p old %p better key %d better sort %d\n", &new_path, &path, better_key, better_sort);
|
||||
printf("new\n");
|
||||
pprint(new_path);
|
||||
printf("add new %p old %p better key %d better sort %d\n", &new_path, &path, better_key, better_sort);
|
||||
printf("new\n");
|
||||
pprint(new_path);
|
||||
#endif
|
||||
|
||||
|
||||
*is_new = true;
|
||||
return NULL;
|
||||
}
|
||||
@@ -275,7 +278,7 @@ better_path(Path *new_path, List *unique_paths, bool *is_new)
|
||||
*
|
||||
*/
|
||||
Path *
|
||||
create_seqscan_path(RelOptInfo *rel)
|
||||
create_seqscan_path(RelOptInfo * rel)
|
||||
{
|
||||
int relid = 0;
|
||||
|
||||
@@ -290,7 +293,7 @@ create_seqscan_path(RelOptInfo *rel)
|
||||
pathnode->pathkeys = NIL;
|
||||
|
||||
/*
|
||||
* copy restrictinfo list into path for expensive function processing
|
||||
* copy restrictinfo list into path for expensive function processing
|
||||
* JMH, 7/7/92
|
||||
*/
|
||||
pathnode->loc_restrictinfo = (List *) copyObject((Node *) rel->restrictinfo);
|
||||
@@ -303,9 +306,7 @@ create_seqscan_path(RelOptInfo *rel)
|
||||
/* add in expensive functions cost! -- JMH, 7/7/92 */
|
||||
#ifdef NOT_USED
|
||||
if (XfuncMode != XFUNC_OFF)
|
||||
{
|
||||
pathnode->path_cost += xfunc_get_path_cost(pathnode);
|
||||
}
|
||||
#endif
|
||||
return pathnode;
|
||||
}
|
||||
@@ -325,8 +326,8 @@ create_seqscan_path(RelOptInfo *rel)
|
||||
*/
|
||||
IndexPath *
|
||||
create_index_path(Query *root,
|
||||
RelOptInfo *rel,
|
||||
RelOptInfo *index,
|
||||
RelOptInfo * rel,
|
||||
RelOptInfo * index,
|
||||
List *restriction_clauses,
|
||||
bool is_join_scan)
|
||||
{
|
||||
@@ -343,11 +344,11 @@ create_index_path(Query *root,
|
||||
pathnode->indexqual = NIL;
|
||||
|
||||
/*
|
||||
* copy restrictinfo list into path for expensive function processing
|
||||
* copy restrictinfo list into path for expensive function processing
|
||||
* JMH, 7/7/92
|
||||
*/
|
||||
pathnode->path.loc_restrictinfo = set_difference((List *) copyObject((Node *) rel->restrictinfo),
|
||||
(List *) restriction_clauses);
|
||||
(List *) restriction_clauses);
|
||||
|
||||
/*
|
||||
* The index must have an ordering for the path to have (ordering)
|
||||
@@ -356,7 +357,7 @@ create_index_path(Query *root,
|
||||
if (pathnode->path.pathorder->ord.sortop)
|
||||
{
|
||||
pathnode->path.pathkeys = collect_index_pathkeys(index->indexkeys,
|
||||
rel->targetlist);
|
||||
rel->targetlist);
|
||||
|
||||
/*
|
||||
* Check that the keys haven't 'disappeared', since they may no
|
||||
@@ -381,19 +382,19 @@ create_index_path(Query *root,
|
||||
/* is the statement above really true? what about IndexScan as the
|
||||
inner of a join? */
|
||||
pathnode->path.path_cost = cost_index(lfirsti(index->relids),
|
||||
index->pages,
|
||||
1.0,
|
||||
rel->pages,
|
||||
rel->tuples,
|
||||
index->pages,
|
||||
index->tuples,
|
||||
false);
|
||||
index->pages,
|
||||
1.0,
|
||||
rel->pages,
|
||||
rel->tuples,
|
||||
index->pages,
|
||||
index->tuples,
|
||||
false);
|
||||
#ifdef NOT_USED
|
||||
/* add in expensive functions cost! -- JMH, 7/7/92 */
|
||||
if (XfuncMode != XFUNC_OFF)
|
||||
{
|
||||
pathnode->path_cost = (pathnode->path_cost +
|
||||
xfunc_get_path_cost((Path *) pathnode));
|
||||
xfunc_get_path_cost((Path *) pathnode));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -427,24 +428,22 @@ create_index_path(Query *root,
|
||||
&npages,
|
||||
&selec);
|
||||
/* each clause gets an equal selectivity */
|
||||
clausesel = pow(selec, 1.0 / (double) length(restriction_clauses));
|
||||
clausesel = pow(selec, 1.0 / (double) length(restriction_clauses));
|
||||
|
||||
pathnode->indexqual = restriction_clauses;
|
||||
pathnode->path.path_cost = cost_index(lfirsti(index->relids),
|
||||
(int) npages,
|
||||
selec,
|
||||
rel->pages,
|
||||
rel->tuples,
|
||||
index->pages,
|
||||
index->tuples,
|
||||
false);
|
||||
(int) npages,
|
||||
selec,
|
||||
rel->pages,
|
||||
rel->tuples,
|
||||
index->pages,
|
||||
index->tuples,
|
||||
false);
|
||||
|
||||
#ifdef NOT_USED
|
||||
/* add in expensive functions cost! -- JMH, 7/7/92 */
|
||||
if (XfuncMode != XFUNC_OFF)
|
||||
{
|
||||
pathnode->path_cost += xfunc_get_path_cost((Path *) pathnode);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -474,8 +473,8 @@ create_index_path(Query *root,
|
||||
*
|
||||
*/
|
||||
NestPath *
|
||||
create_nestloop_path(RelOptInfo *joinrel,
|
||||
RelOptInfo *outer_rel,
|
||||
create_nestloop_path(RelOptInfo * joinrel,
|
||||
RelOptInfo * outer_rel,
|
||||
Path *outer_path,
|
||||
Path *inner_path,
|
||||
List *pathkeys)
|
||||
@@ -492,7 +491,7 @@ create_nestloop_path(RelOptInfo *joinrel,
|
||||
pathnode->path.outerjoincost = (Cost) 0.0;
|
||||
pathnode->path.loc_restrictinfo = NIL;
|
||||
pathnode->path.pathorder = makeNode(PathOrder);
|
||||
|
||||
|
||||
if (pathkeys)
|
||||
{
|
||||
pathnode->path.pathorder->ordtype = outer_path->pathorder->ordtype;
|
||||
@@ -508,12 +507,12 @@ create_nestloop_path(RelOptInfo *joinrel,
|
||||
}
|
||||
|
||||
pathnode->path.path_cost = cost_nestloop(outer_path->path_cost,
|
||||
inner_path->path_cost,
|
||||
outer_rel->size,
|
||||
inner_path->parent->size,
|
||||
page_size(outer_rel->size,
|
||||
outer_rel->width),
|
||||
IsA(inner_path, IndexPath));
|
||||
inner_path->path_cost,
|
||||
outer_rel->size,
|
||||
inner_path->parent->size,
|
||||
page_size(outer_rel->size,
|
||||
outer_rel->width),
|
||||
IsA(inner_path, IndexPath));
|
||||
/* add in expensive function costs -- JMH 7/7/92 */
|
||||
#ifdef NOT_USED
|
||||
if (XfuncMode != XFUNC_OFF)
|
||||
@@ -542,7 +541,7 @@ create_nestloop_path(RelOptInfo *joinrel,
|
||||
*
|
||||
*/
|
||||
MergePath *
|
||||
create_mergejoin_path(RelOptInfo *joinrel,
|
||||
create_mergejoin_path(RelOptInfo * joinrel,
|
||||
int outersize,
|
||||
int innersize,
|
||||
int outerwidth,
|
||||
@@ -571,19 +570,17 @@ create_mergejoin_path(RelOptInfo *joinrel,
|
||||
pathnode->outersortkeys = outersortkeys;
|
||||
pathnode->innersortkeys = innersortkeys;
|
||||
pathnode->jpath.path.path_cost = cost_mergejoin(outer_path->path_cost,
|
||||
inner_path->path_cost,
|
||||
outersortkeys,
|
||||
innersortkeys,
|
||||
outersize,
|
||||
innersize,
|
||||
outerwidth,
|
||||
innerwidth);
|
||||
inner_path->path_cost,
|
||||
outersortkeys,
|
||||
innersortkeys,
|
||||
outersize,
|
||||
innersize,
|
||||
outerwidth,
|
||||
innerwidth);
|
||||
/* add in expensive function costs -- JMH 7/7/92 */
|
||||
#ifdef NOT_USED
|
||||
if (XfuncMode != XFUNC_OFF)
|
||||
{
|
||||
pathnode->path_cost += xfunc_get_path_cost((Path *) pathnode);
|
||||
}
|
||||
#endif
|
||||
return pathnode;
|
||||
}
|
||||
@@ -607,7 +604,7 @@ create_mergejoin_path(RelOptInfo *joinrel,
|
||||
*
|
||||
*/
|
||||
HashPath *
|
||||
create_hashjoin_path(RelOptInfo *joinrel,
|
||||
create_hashjoin_path(RelOptInfo * joinrel,
|
||||
int outersize,
|
||||
int innersize,
|
||||
int outerwidth,
|
||||
@@ -639,17 +636,15 @@ create_hashjoin_path(RelOptInfo *joinrel,
|
||||
pathnode->outerhashkeys = outerkeys;
|
||||
pathnode->innerhashkeys = innerkeys;
|
||||
pathnode->jpath.path.path_cost = cost_hashjoin(outer_path->path_cost,
|
||||
inner_path->path_cost,
|
||||
outerkeys,
|
||||
innerkeys,
|
||||
outersize, innersize,
|
||||
outerwidth, innerwidth);
|
||||
inner_path->path_cost,
|
||||
outerkeys,
|
||||
innerkeys,
|
||||
outersize, innersize,
|
||||
outerwidth, innerwidth);
|
||||
/* add in expensive function costs -- JMH 7/7/92 */
|
||||
#ifdef NOT_USED
|
||||
if (XfuncMode != XFUNC_OFF)
|
||||
{
|
||||
pathnode->path_cost += xfunc_get_path_cost((Path *) pathnode);
|
||||
}
|
||||
#endif
|
||||
return pathnode;
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.29 1999/05/10 00:45:25 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.30 1999/05/25 16:09:59 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -461,6 +461,7 @@ VersionGetParents(Oid verrelid)
|
||||
heap_close(relation);
|
||||
return list;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -545,6 +546,7 @@ IndexSelectivity(Oid indexrelid,
|
||||
select = 1.0;
|
||||
for (n = 0; n < nIndexKeys; ++n)
|
||||
{
|
||||
|
||||
/*
|
||||
* Find the AM class for this key.
|
||||
*
|
||||
@@ -579,7 +581,7 @@ IndexSelectivity(Oid indexrelid,
|
||||
|
||||
amopTuple = SearchSysCacheTuple(AMOPOPID,
|
||||
ObjectIdGetDatum(indclass),
|
||||
ObjectIdGetDatum(operatorObjectIds[n]),
|
||||
ObjectIdGetDatum(operatorObjectIds[n]),
|
||||
ObjectIdGetDatum(relam),
|
||||
0);
|
||||
if (!HeapTupleIsValid(amopTuple))
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/relnode.c,v 1.15 1999/02/18 00:49:38 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/relnode.c,v 1.16 1999/05/25 16:10:01 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -30,7 +30,7 @@
|
||||
RelOptInfo *
|
||||
get_base_rel(Query *root, int relid)
|
||||
{
|
||||
Relids relids;
|
||||
Relids relids;
|
||||
RelOptInfo *rel;
|
||||
|
||||
relids = lconsi(relid, NIL);
|
||||
@@ -63,6 +63,7 @@ get_base_rel(Query *root, int relid)
|
||||
*/
|
||||
if (relid < 0)
|
||||
{
|
||||
|
||||
/*
|
||||
* If the relation is a materialized relation, assume
|
||||
* constants for sizes.
|
||||
@@ -75,6 +76,7 @@ get_base_rel(Query *root, int relid)
|
||||
bool hasindex;
|
||||
int pages,
|
||||
tuples;
|
||||
|
||||
/*
|
||||
* Otherwise, retrieve relation characteristics from the
|
||||
* system catalogs.
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.2 1999/02/13 23:16:49 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.3 1999/05/25 16:10:02 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -27,7 +27,7 @@
|
||||
*
|
||||
*/
|
||||
bool
|
||||
valid_or_clause(RestrictInfo *restrictinfo)
|
||||
valid_or_clause(RestrictInfo * restrictinfo)
|
||||
{
|
||||
if (restrictinfo != NULL &&
|
||||
!single_node((Node *) restrictinfo->clause) &&
|
||||
@@ -117,7 +117,7 @@ get_relattvals(List *restrictinfo_list,
|
||||
}
|
||||
|
||||
/*
|
||||
* get_joinvars
|
||||
* get_joinvars
|
||||
* Given a list of join restrictinfo nodes to be used with the index
|
||||
* of an inner join relation, return three lists consisting of:
|
||||
* the attributes corresponding to the inner join relation
|
||||
@@ -184,7 +184,7 @@ get_opnos(List *restrictinfo_list)
|
||||
{
|
||||
temp = (RestrictInfo *) lfirst(i);
|
||||
result = lappendi(result,
|
||||
(((Oper *) temp->clause->oper)->opno));
|
||||
(((Oper *) temp->clause->oper)->opno));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.31 1999/05/17 17:03:23 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.32 1999/05/25 16:10:03 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -93,7 +93,7 @@ matching_tlist_var(Var *var, List *targetlist)
|
||||
* CREATES: new var_node iff no matching var_node exists in targetlist
|
||||
*/
|
||||
void
|
||||
add_var_to_tlist(RelOptInfo *rel, Var *var)
|
||||
add_var_to_tlist(RelOptInfo * rel, Var *var)
|
||||
{
|
||||
Expr *oldvar;
|
||||
|
||||
@@ -114,8 +114,8 @@ add_var_to_tlist(RelOptInfo *rel, Var *var)
|
||||
var->varoattno);
|
||||
|
||||
rel->targetlist = lappend(tlist,
|
||||
create_tl_element(newvar,
|
||||
length(tlist) + 1));
|
||||
create_tl_element(newvar,
|
||||
length(tlist) + 1));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -203,6 +203,7 @@ tlist_member(Var *var, List *tlist)
|
||||
foreach(i, tlist)
|
||||
{
|
||||
TargetEntry *tle = (TargetEntry *) lfirst(i);
|
||||
|
||||
if (var_equal(var, get_expr(tle)))
|
||||
return tle->resdom;
|
||||
}
|
||||
@@ -222,6 +223,7 @@ tlist_resdom(List *tlist, Resdom *resnode)
|
||||
{
|
||||
TargetEntry *tle = (TargetEntry *) lfirst(i);
|
||||
Resdom *resdom = tle->resdom;
|
||||
|
||||
/* Since resnos are supposed to be unique */
|
||||
if (resnode->resno == resdom->resno)
|
||||
return resdom;
|
||||
@@ -362,7 +364,7 @@ flatten_tlist(List *tlist)
|
||||
TargetEntry *temp_entry = (TargetEntry *) lfirst(temp);
|
||||
|
||||
tlist_vars = nconc(tlist_vars,
|
||||
pull_var_clause((Node *) get_expr(temp_entry)));
|
||||
pull_var_clause((Node *) get_expr(temp_entry)));
|
||||
}
|
||||
|
||||
foreach(temp, tlist_vars)
|
||||
@@ -411,8 +413,8 @@ flatten_tlist_vars(List *full_tlist, List *flat_tlist)
|
||||
TargetEntry *tle = lfirst(x);
|
||||
|
||||
result = lappend(result, makeTargetEntry(tle->resdom,
|
||||
flatten_tlistentry((Node *) get_expr(tle),
|
||||
flat_tlist)));
|
||||
flatten_tlistentry((Node *) get_expr(tle),
|
||||
flat_tlist)));
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -456,10 +458,11 @@ flatten_tlistentry(Node *tlistentry, List *flat_tlist)
|
||||
}
|
||||
else if (IsA(tlistentry, Expr))
|
||||
{
|
||||
|
||||
/*
|
||||
* Recursively scan the arguments of an expression.
|
||||
* NOTE: this must come after is_subplan() case since
|
||||
* subplan is a kind of Expr node.
|
||||
* Recursively scan the arguments of an expression. NOTE: this
|
||||
* must come after is_subplan() case since subplan is a kind of
|
||||
* Expr node.
|
||||
*/
|
||||
foreach(temp, ((Expr *) tlistentry)->args)
|
||||
lfirst(temp) = flatten_tlistentry(lfirst(temp), flat_tlist);
|
||||
@@ -467,8 +470,10 @@ flatten_tlistentry(Node *tlistentry, List *flat_tlist)
|
||||
}
|
||||
else if (IsA(tlistentry, Aggref))
|
||||
{
|
||||
/* XXX shouldn't this be recursing into the agg's target?
|
||||
* Seems to work though, so will leave it alone ... tgl 5/99
|
||||
|
||||
/*
|
||||
* XXX shouldn't this be recursing into the agg's target? Seems to
|
||||
* work though, so will leave it alone ... tgl 5/99
|
||||
*/
|
||||
return tlistentry;
|
||||
}
|
||||
@@ -481,7 +486,7 @@ flatten_tlistentry(Node *tlistentry, List *flat_tlist)
|
||||
foreach(temp, aref->reflowerindexpr)
|
||||
lfirst(temp) = flatten_tlistentry(lfirst(temp), flat_tlist);
|
||||
aref->refexpr = flatten_tlistentry(aref->refexpr, flat_tlist);
|
||||
aref->refassgnexpr = flatten_tlistentry(aref->refassgnexpr,flat_tlist);
|
||||
aref->refassgnexpr = flatten_tlistentry(aref->refassgnexpr, flat_tlist);
|
||||
|
||||
return tlistentry;
|
||||
}
|
||||
@@ -491,7 +496,8 @@ flatten_tlistentry(Node *tlistentry, List *flat_tlist)
|
||||
|
||||
foreach(temp, cexpr->args)
|
||||
{
|
||||
CaseWhen *cwhen = (CaseWhen *) lfirst(temp);
|
||||
CaseWhen *cwhen = (CaseWhen *) lfirst(temp);
|
||||
|
||||
cwhen->expr = flatten_tlistentry(cwhen->expr, flat_tlist);
|
||||
cwhen->result = flatten_tlistentry(cwhen->result, flat_tlist);
|
||||
}
|
||||
@@ -521,18 +527,18 @@ get_expr(TargetEntry *tle)
|
||||
Var *
|
||||
get_groupclause_expr(GroupClause *groupClause, List *targetList)
|
||||
{
|
||||
List *l;
|
||||
TargetEntry *tle;
|
||||
List *l;
|
||||
TargetEntry *tle;
|
||||
|
||||
foreach(l, targetList)
|
||||
{
|
||||
tle = (TargetEntry *)lfirst(l);
|
||||
tle = (TargetEntry *) lfirst(l);
|
||||
if (tle->resdom->resgroupref == groupClause->tleGroupref)
|
||||
return get_expr(tle);
|
||||
}
|
||||
|
||||
elog(ERROR,
|
||||
"get_groupclause_expr: GROUP BY expression not found in targetlist");
|
||||
elog(ERROR,
|
||||
"get_groupclause_expr: GROUP BY expression not found in targetlist");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.18 1999/05/03 00:38:44 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.19 1999/05/25 16:10:05 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -102,10 +102,11 @@ contain_var_clause(Node *clause)
|
||||
}
|
||||
else if (IsA(clause, Expr))
|
||||
{
|
||||
|
||||
/*
|
||||
* Recursively scan the arguments of an expression.
|
||||
* NOTE: this must come after is_subplan() case since
|
||||
* subplan is a kind of Expr node.
|
||||
* Recursively scan the arguments of an expression. NOTE: this
|
||||
* must come after is_subplan() case since subplan is a kind of
|
||||
* Expr node.
|
||||
*/
|
||||
foreach(temp, ((Expr *) clause)->args)
|
||||
{
|
||||
@@ -139,6 +140,7 @@ contain_var_clause(Node *clause)
|
||||
foreach(temp, ((CaseExpr *) clause)->args)
|
||||
{
|
||||
CaseWhen *when = (CaseWhen *) lfirst(temp);
|
||||
|
||||
if (contain_var_clause(when->expr))
|
||||
return TRUE;
|
||||
if (contain_var_clause(when->result))
|
||||
@@ -188,10 +190,11 @@ pull_var_clause(Node *clause)
|
||||
}
|
||||
else if (IsA(clause, Expr))
|
||||
{
|
||||
|
||||
/*
|
||||
* Recursively scan the arguments of an expression.
|
||||
* NOTE: this must come after is_subplan() case since
|
||||
* subplan is a kind of Expr node.
|
||||
* Recursively scan the arguments of an expression. NOTE: this
|
||||
* must come after is_subplan() case since subplan is a kind of
|
||||
* Expr node.
|
||||
*/
|
||||
foreach(temp, ((Expr *) clause)->args)
|
||||
retval = nconc(retval, pull_var_clause(lfirst(temp)));
|
||||
@@ -214,6 +217,7 @@ pull_var_clause(Node *clause)
|
||||
foreach(temp, ((CaseExpr *) clause)->args)
|
||||
{
|
||||
CaseWhen *when = (CaseWhen *) lfirst(temp);
|
||||
|
||||
retval = nconc(retval, pull_var_clause(when->expr));
|
||||
retval = nconc(retval, pull_var_clause(when->result));
|
||||
}
|
||||
|
Reference in New Issue
Block a user