Plug some more memory leaks in the planner. It still leaks like a sieve,
but this is as good as it'll get for this release...
This commit is contained in:
parent
bc8a39beef
commit
3cbcb78a3d
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinpath.c,v 1.52 2000/02/15 20:49:17 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinpath.c,v 1.53 2000/02/18 23:47:19 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -171,9 +171,13 @@ sort_inner_and_outer(Query *root,
|
|||||||
List *merge_pathkeys;
|
List *merge_pathkeys;
|
||||||
|
|
||||||
/* Make a mergeclause list with this guy first. */
|
/* Make a mergeclause list with this guy first. */
|
||||||
curclause_list = lcons(restrictinfo,
|
if (i != mergeclause_list)
|
||||||
lremove(restrictinfo,
|
curclause_list = lcons(restrictinfo,
|
||||||
listCopy(mergeclause_list)));
|
lremove(restrictinfo,
|
||||||
|
listCopy(mergeclause_list)));
|
||||||
|
else
|
||||||
|
curclause_list = mergeclause_list; /* no work at first one... */
|
||||||
|
|
||||||
/* Build sort pathkeys for both sides.
|
/* Build sort pathkeys for both sides.
|
||||||
*
|
*
|
||||||
* Note: it's possible that the cheapest paths will already be
|
* Note: it's possible that the cheapest paths will already be
|
||||||
@ -203,7 +207,7 @@ sort_inner_and_outer(Query *root,
|
|||||||
innerrel->cheapest_total_path,
|
innerrel->cheapest_total_path,
|
||||||
restrictlist,
|
restrictlist,
|
||||||
merge_pathkeys,
|
merge_pathkeys,
|
||||||
get_actual_clauses(curclause_list),
|
curclause_list,
|
||||||
outerkeys,
|
outerkeys,
|
||||||
innerkeys));
|
innerkeys));
|
||||||
}
|
}
|
||||||
@ -265,6 +269,7 @@ match_unsorted_outer(Query *root,
|
|||||||
List *trialsortkeys;
|
List *trialsortkeys;
|
||||||
Path *cheapest_startup_inner;
|
Path *cheapest_startup_inner;
|
||||||
Path *cheapest_total_inner;
|
Path *cheapest_total_inner;
|
||||||
|
int num_mergeclauses;
|
||||||
int clausecnt;
|
int clausecnt;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -325,7 +330,7 @@ match_unsorted_outer(Query *root,
|
|||||||
innerrel->cheapest_total_path,
|
innerrel->cheapest_total_path,
|
||||||
restrictlist,
|
restrictlist,
|
||||||
merge_pathkeys,
|
merge_pathkeys,
|
||||||
get_actual_clauses(mergeclauses),
|
mergeclauses,
|
||||||
NIL,
|
NIL,
|
||||||
innersortkeys));
|
innersortkeys));
|
||||||
|
|
||||||
@ -337,10 +342,12 @@ match_unsorted_outer(Query *root,
|
|||||||
trialsortkeys = listCopy(innersortkeys); /* modifiable copy */
|
trialsortkeys = listCopy(innersortkeys); /* modifiable copy */
|
||||||
cheapest_startup_inner = NULL;
|
cheapest_startup_inner = NULL;
|
||||||
cheapest_total_inner = NULL;
|
cheapest_total_inner = NULL;
|
||||||
|
num_mergeclauses = length(mergeclauses);
|
||||||
|
|
||||||
for (clausecnt = length(mergeclauses); clausecnt > 0; clausecnt--)
|
for (clausecnt = num_mergeclauses; clausecnt > 0; clausecnt--)
|
||||||
{
|
{
|
||||||
Path *innerpath;
|
Path *innerpath;
|
||||||
|
List *newclauses = NIL;
|
||||||
|
|
||||||
/* Look for an inner path ordered well enough to merge with
|
/* Look for an inner path ordered well enough to merge with
|
||||||
* the first 'clausecnt' mergeclauses. NB: trialsortkeys list
|
* the first 'clausecnt' mergeclauses. NB: trialsortkeys list
|
||||||
@ -356,10 +363,11 @@ match_unsorted_outer(Query *root,
|
|||||||
TOTAL_COST) < 0))
|
TOTAL_COST) < 0))
|
||||||
{
|
{
|
||||||
/* Found a cheap (or even-cheaper) sorted path */
|
/* Found a cheap (or even-cheaper) sorted path */
|
||||||
List *newclauses;
|
if (clausecnt < num_mergeclauses)
|
||||||
|
newclauses = ltruncate(clausecnt,
|
||||||
newclauses = ltruncate(clausecnt,
|
listCopy(mergeclauses));
|
||||||
get_actual_clauses(mergeclauses));
|
else
|
||||||
|
newclauses = mergeclauses;
|
||||||
add_path(joinrel, (Path *)
|
add_path(joinrel, (Path *)
|
||||||
create_mergejoin_path(joinrel,
|
create_mergejoin_path(joinrel,
|
||||||
outerpath,
|
outerpath,
|
||||||
@ -383,10 +391,17 @@ match_unsorted_outer(Query *root,
|
|||||||
/* Found a cheap (or even-cheaper) sorted path */
|
/* Found a cheap (or even-cheaper) sorted path */
|
||||||
if (innerpath != cheapest_total_inner)
|
if (innerpath != cheapest_total_inner)
|
||||||
{
|
{
|
||||||
List *newclauses;
|
/* Avoid rebuilding clause list if we already made one;
|
||||||
|
* saves memory in big join trees...
|
||||||
newclauses = ltruncate(clausecnt,
|
*/
|
||||||
get_actual_clauses(mergeclauses));
|
if (newclauses == NIL)
|
||||||
|
{
|
||||||
|
if (clausecnt < num_mergeclauses)
|
||||||
|
newclauses = ltruncate(clausecnt,
|
||||||
|
listCopy(mergeclauses));
|
||||||
|
else
|
||||||
|
newclauses = mergeclauses;
|
||||||
|
}
|
||||||
add_path(joinrel, (Path *)
|
add_path(joinrel, (Path *)
|
||||||
create_mergejoin_path(joinrel,
|
create_mergejoin_path(joinrel,
|
||||||
outerpath,
|
outerpath,
|
||||||
@ -461,7 +476,7 @@ match_unsorted_inner(Query *root,
|
|||||||
innerpath,
|
innerpath,
|
||||||
restrictlist,
|
restrictlist,
|
||||||
merge_pathkeys,
|
merge_pathkeys,
|
||||||
get_actual_clauses(mergeclauses),
|
mergeclauses,
|
||||||
outersortkeys,
|
outersortkeys,
|
||||||
NIL));
|
NIL));
|
||||||
/*
|
/*
|
||||||
@ -487,7 +502,7 @@ match_unsorted_inner(Query *root,
|
|||||||
innerpath,
|
innerpath,
|
||||||
restrictlist,
|
restrictlist,
|
||||||
merge_pathkeys,
|
merge_pathkeys,
|
||||||
get_actual_clauses(mergeclauses),
|
mergeclauses,
|
||||||
NIL,
|
NIL,
|
||||||
NIL));
|
NIL));
|
||||||
|
|
||||||
@ -505,7 +520,7 @@ match_unsorted_inner(Query *root,
|
|||||||
innerpath,
|
innerpath,
|
||||||
restrictlist,
|
restrictlist,
|
||||||
merge_pathkeys,
|
merge_pathkeys,
|
||||||
get_actual_clauses(mergeclauses),
|
mergeclauses,
|
||||||
NIL,
|
NIL,
|
||||||
NIL));
|
NIL));
|
||||||
}
|
}
|
||||||
@ -552,6 +567,7 @@ hash_inner_and_outer(Query *root,
|
|||||||
Var *left,
|
Var *left,
|
||||||
*right,
|
*right,
|
||||||
*inner;
|
*inner;
|
||||||
|
List *hashclauses;
|
||||||
Selectivity innerdisbursion;
|
Selectivity innerdisbursion;
|
||||||
|
|
||||||
if (restrictinfo->hashjoinoperator == InvalidOid)
|
if (restrictinfo->hashjoinoperator == InvalidOid)
|
||||||
@ -572,6 +588,9 @@ hash_inner_and_outer(Query *root,
|
|||||||
else
|
else
|
||||||
continue; /* no good for these input relations */
|
continue; /* no good for these input relations */
|
||||||
|
|
||||||
|
/* always a one-element list of hash clauses */
|
||||||
|
hashclauses = lcons(restrictinfo, NIL);
|
||||||
|
|
||||||
/* estimate disbursion of inner var for costing purposes */
|
/* estimate disbursion of inner var for costing purposes */
|
||||||
innerdisbursion = estimate_disbursion(root, inner);
|
innerdisbursion = estimate_disbursion(root, inner);
|
||||||
|
|
||||||
@ -585,7 +604,7 @@ hash_inner_and_outer(Query *root,
|
|||||||
outerrel->cheapest_total_path,
|
outerrel->cheapest_total_path,
|
||||||
innerrel->cheapest_total_path,
|
innerrel->cheapest_total_path,
|
||||||
restrictlist,
|
restrictlist,
|
||||||
lcons(clause, NIL),
|
hashclauses,
|
||||||
innerdisbursion));
|
innerdisbursion));
|
||||||
if (outerrel->cheapest_startup_path != outerrel->cheapest_total_path)
|
if (outerrel->cheapest_startup_path != outerrel->cheapest_total_path)
|
||||||
add_path(joinrel, (Path *)
|
add_path(joinrel, (Path *)
|
||||||
@ -593,7 +612,7 @@ hash_inner_and_outer(Query *root,
|
|||||||
outerrel->cheapest_startup_path,
|
outerrel->cheapest_startup_path,
|
||||||
innerrel->cheapest_total_path,
|
innerrel->cheapest_total_path,
|
||||||
restrictlist,
|
restrictlist,
|
||||||
lcons(clause, NIL),
|
hashclauses,
|
||||||
innerdisbursion));
|
innerdisbursion));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.19 2000/02/15 20:49:17 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.20 2000/02/18 23:47:19 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -778,6 +778,7 @@ make_pathkeys_for_mergeclauses(Query *root,
|
|||||||
Node *key;
|
Node *key;
|
||||||
Oid sortop;
|
Oid sortop;
|
||||||
PathKeyItem *item;
|
PathKeyItem *item;
|
||||||
|
List *pathkey;
|
||||||
|
|
||||||
Assert(restrictinfo->mergejoinoperator != InvalidOid);
|
Assert(restrictinfo->mergejoinoperator != InvalidOid);
|
||||||
|
|
||||||
@ -791,10 +792,21 @@ make_pathkeys_for_mergeclauses(Query *root,
|
|||||||
key = (Node *) get_leftop(restrictinfo->clause);
|
key = (Node *) get_leftop(restrictinfo->clause);
|
||||||
sortop = restrictinfo->left_sortop;
|
sortop = restrictinfo->left_sortop;
|
||||||
/*
|
/*
|
||||||
* Add a pathkey sublist for this sort item
|
* Find pathkey sublist for this sort item. We expect to find
|
||||||
|
* the canonical set including the mergeclause's left and right
|
||||||
|
* sides; if we get back just the one item, something is rotten.
|
||||||
*/
|
*/
|
||||||
item = makePathKeyItem(key, sortop);
|
item = makePathKeyItem(key, sortop);
|
||||||
pathkeys = lappend(pathkeys, make_canonical_pathkey(root, item));
|
pathkey = make_canonical_pathkey(root, item);
|
||||||
|
Assert(length(pathkey) > 1);
|
||||||
|
/*
|
||||||
|
* Since the item we just made is not in the returned canonical set,
|
||||||
|
* we can free it --- this saves a useful amount of storage in a
|
||||||
|
* big join tree.
|
||||||
|
*/
|
||||||
|
pfree(item);
|
||||||
|
|
||||||
|
pathkeys = lappend(pathkeys, pathkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
return pathkeys;
|
return pathkeys;
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.85 2000/02/15 20:49:18 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.86 2000/02/18 23:47:21 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -626,13 +626,14 @@ create_mergejoin_node(MergePath *best_path,
|
|||||||
*mergeclauses;
|
*mergeclauses;
|
||||||
MergeJoin *join_node;
|
MergeJoin *join_node;
|
||||||
|
|
||||||
|
mergeclauses = get_actual_clauses(best_path->path_mergeclauses);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove the mergeclauses from the list of join qual clauses,
|
* Remove the mergeclauses from the list of join qual clauses,
|
||||||
* leaving the list of quals that must be checked as qpquals.
|
* leaving the list of quals that must be checked as qpquals.
|
||||||
* Set those clauses to contain INNER/OUTER var references.
|
* Set those clauses to contain INNER/OUTER var references.
|
||||||
*/
|
*/
|
||||||
qpqual = join_references(set_difference(clauses,
|
qpqual = join_references(set_difference(clauses, mergeclauses),
|
||||||
best_path->path_mergeclauses),
|
|
||||||
outer_tlist,
|
outer_tlist,
|
||||||
inner_tlist,
|
inner_tlist,
|
||||||
(Index) 0);
|
(Index) 0);
|
||||||
@ -641,7 +642,7 @@ create_mergejoin_node(MergePath *best_path,
|
|||||||
* Now set the references in the mergeclauses and rearrange them so
|
* Now set the references in the mergeclauses and rearrange them so
|
||||||
* that the outer variable is always on the left.
|
* that the outer variable is always on the left.
|
||||||
*/
|
*/
|
||||||
mergeclauses = switch_outer(join_references(best_path->path_mergeclauses,
|
mergeclauses = switch_outer(join_references(mergeclauses,
|
||||||
outer_tlist,
|
outer_tlist,
|
||||||
inner_tlist,
|
inner_tlist,
|
||||||
(Index) 0));
|
(Index) 0));
|
||||||
@ -692,14 +693,14 @@ create_hashjoin_node(HashPath *best_path,
|
|||||||
* We represent it as a list anyway, for convenience with routines
|
* We represent it as a list anyway, for convenience with routines
|
||||||
* that want to work on lists of clauses.
|
* that want to work on lists of clauses.
|
||||||
*/
|
*/
|
||||||
|
hashclauses = get_actual_clauses(best_path->path_hashclauses);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove the hashclauses from the list of join qual clauses,
|
* Remove the hashclauses from the list of join qual clauses,
|
||||||
* leaving the list of quals that must be checked as qpquals.
|
* leaving the list of quals that must be checked as qpquals.
|
||||||
* Set those clauses to contain INNER/OUTER var references.
|
* Set those clauses to contain INNER/OUTER var references.
|
||||||
*/
|
*/
|
||||||
qpqual = join_references(set_difference(clauses,
|
qpqual = join_references(set_difference(clauses, hashclauses),
|
||||||
best_path->path_hashclauses),
|
|
||||||
outer_tlist,
|
outer_tlist,
|
||||||
inner_tlist,
|
inner_tlist,
|
||||||
(Index) 0);
|
(Index) 0);
|
||||||
@ -708,7 +709,7 @@ create_hashjoin_node(HashPath *best_path,
|
|||||||
* Now set the references in the hashclauses and rearrange them so
|
* Now set the references in the hashclauses and rearrange them so
|
||||||
* that the outer variable is always on the left.
|
* that the outer variable is always on the left.
|
||||||
*/
|
*/
|
||||||
hashclauses = switch_outer(join_references(best_path->path_hashclauses,
|
hashclauses = switch_outer(join_references(hashclauses,
|
||||||
outer_tlist,
|
outer_tlist,
|
||||||
inner_tlist,
|
inner_tlist,
|
||||||
(Index) 0));
|
(Index) 0));
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.60 2000/02/15 20:49:20 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.61 2000/02/18 23:47:30 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -416,7 +416,8 @@ create_nestloop_path(RelOptInfo *joinrel,
|
|||||||
* 'inner_path' is the inner path
|
* 'inner_path' is the inner path
|
||||||
* 'restrict_clauses' are the RestrictInfo nodes to apply at the join
|
* 'restrict_clauses' are the RestrictInfo nodes to apply at the join
|
||||||
* 'pathkeys' are the path keys of the new join path
|
* 'pathkeys' are the path keys of the new join path
|
||||||
* 'mergeclauses' are the applicable join/restriction clauses
|
* 'mergeclauses' are the RestrictInfo nodes to use as merge clauses
|
||||||
|
* (this should be a subset of the restrict_clauses list)
|
||||||
* 'outersortkeys' are the sort varkeys for the outer relation
|
* 'outersortkeys' are the sort varkeys for the outer relation
|
||||||
* 'innersortkeys' are the sort varkeys for the inner relation
|
* 'innersortkeys' are the sort varkeys for the inner relation
|
||||||
*
|
*
|
||||||
@ -473,6 +474,7 @@ create_mergejoin_path(RelOptInfo *joinrel,
|
|||||||
* 'inner_path' is the cheapest inner path
|
* 'inner_path' is the cheapest inner path
|
||||||
* 'restrict_clauses' are the RestrictInfo nodes to apply at the join
|
* 'restrict_clauses' are the RestrictInfo nodes to apply at the join
|
||||||
* 'hashclauses' is a list of the hash join clause (always a 1-element list)
|
* 'hashclauses' is a list of the hash join clause (always a 1-element list)
|
||||||
|
* (this should be a subset of the restrict_clauses list)
|
||||||
* 'innerdisbursion' is an estimate of the disbursion of the inner hash key
|
* 'innerdisbursion' is an estimate of the disbursion of the inner hash key
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/relnode.c,v 1.24 2000/02/15 20:49:21 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/relnode.c,v 1.25 2000/02/18 23:47:31 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -345,11 +345,8 @@ subbuild_joinrel_restrictlist(RelOptInfo *joinrel,
|
|||||||
foreach(xjoininfo, joininfo_list)
|
foreach(xjoininfo, joininfo_list)
|
||||||
{
|
{
|
||||||
JoinInfo *joininfo = (JoinInfo *) lfirst(xjoininfo);
|
JoinInfo *joininfo = (JoinInfo *) lfirst(xjoininfo);
|
||||||
Relids new_unjoined_relids;
|
|
||||||
|
|
||||||
new_unjoined_relids = set_differencei(joininfo->unjoined_relids,
|
if (is_subseti(joininfo->unjoined_relids, joinrel->relids))
|
||||||
joinrel->relids);
|
|
||||||
if (new_unjoined_relids == NIL)
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Clauses in this JoinInfo list become restriction clauses
|
* Clauses in this JoinInfo list become restriction clauses
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: relation.h,v 1.44 2000/02/15 20:49:25 tgl Exp $
|
* $Id: relation.h,v 1.45 2000/02/18 23:47:17 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -237,6 +237,8 @@ typedef struct Path
|
|||||||
* are usable as indexquals (as determined by indxpath.c) may appear here.
|
* are usable as indexquals (as determined by indxpath.c) may appear here.
|
||||||
* NOTE that the semantics of the top-level list in 'indexqual' is OR
|
* NOTE that the semantics of the top-level list in 'indexqual' is OR
|
||||||
* combination, while the sublists are implicitly AND combinations!
|
* combination, while the sublists are implicitly AND combinations!
|
||||||
|
* Also note that indexquals lists do not contain RestrictInfo nodes,
|
||||||
|
* just bare clause expressions.
|
||||||
*
|
*
|
||||||
* 'indexscandir' is one of:
|
* 'indexscandir' is one of:
|
||||||
* ForwardScanDirection: forward scan of an ordered index
|
* ForwardScanDirection: forward scan of an ordered index
|
||||||
@ -293,32 +295,39 @@ typedef JoinPath NestPath;
|
|||||||
/*
|
/*
|
||||||
* A mergejoin path has these fields.
|
* A mergejoin path has these fields.
|
||||||
*
|
*
|
||||||
|
* path_mergeclauses lists the clauses (in the form of RestrictInfos)
|
||||||
|
* that will be used in the merge. (Before 7.0, this was a list of
|
||||||
|
* bare clause expressions, but we can save on list memory by leaving
|
||||||
|
* it in the form of a RestrictInfo list.)
|
||||||
|
*
|
||||||
* Note that the mergeclauses are a subset of the parent relation's
|
* Note that the mergeclauses are a subset of the parent relation's
|
||||||
* restriction-clause list. Any join clauses that are not mergejoinable
|
* restriction-clause list. Any join clauses that are not mergejoinable
|
||||||
* appear only in the parent's restrict list, and must be checked by a
|
* appear only in the parent's restrict list, and must be checked by a
|
||||||
* qpqual at execution time.
|
* qpqual at execution time.
|
||||||
|
*
|
||||||
|
* outersortkeys (resp. innersortkeys) is NIL if the outer path
|
||||||
|
* (resp. inner path) is already ordered appropriately for the
|
||||||
|
* mergejoin. If it is not NIL then it is a PathKeys list describing
|
||||||
|
* the ordering that must be created by an explicit sort step.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct MergePath
|
typedef struct MergePath
|
||||||
{
|
{
|
||||||
JoinPath jpath;
|
JoinPath jpath;
|
||||||
List *path_mergeclauses; /* join clauses used for merge */
|
List *path_mergeclauses; /* join clauses to be used for merge */
|
||||||
/*
|
List *outersortkeys; /* keys for explicit sort, if any */
|
||||||
* outersortkeys (resp. innersortkeys) is NIL if the outer path
|
List *innersortkeys; /* keys for explicit sort, if any */
|
||||||
* (resp. inner path) is already ordered appropriately for the
|
|
||||||
* mergejoin. If it is not NIL then it is a PathKeys list describing
|
|
||||||
* the ordering that must be created by an explicit sort step.
|
|
||||||
*/
|
|
||||||
List *outersortkeys;
|
|
||||||
List *innersortkeys;
|
|
||||||
} MergePath;
|
} MergePath;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A hashjoin path has these fields.
|
* A hashjoin path has these fields.
|
||||||
*
|
*
|
||||||
* The remarks above for mergeclauses apply for hashclauses as well.
|
* The remarks above for mergeclauses apply for hashclauses as well.
|
||||||
* However, hashjoin does not care what order its inputs appear in,
|
* (But note that path_hashclauses will always be a one-element list,
|
||||||
* so we have no need for sortkeys.
|
* since we only hash on one hashable clause.)
|
||||||
|
*
|
||||||
|
* Hashjoin does not care what order its inputs appear in, so we have
|
||||||
|
* no need for sortkeys.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct HashPath
|
typedef struct HashPath
|
||||||
|
Loading…
x
Reference in New Issue
Block a user