Skip to content

Commit 3cbcb78

Browse files
committed
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...
1 parent bc8a39b commit 3cbcb78

File tree

6 files changed

+89
-49
lines changed

6 files changed

+89
-49
lines changed

src/backend/optimizer/path/joinpath.c

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinpath.c,v 1.52 2000/02/15 20:49:17 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinpath.c,v 1.53 2000/02/18 23:47:19 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -171,9 +171,13 @@ sort_inner_and_outer(Query *root,
171171
List *merge_pathkeys;
172172

173173
/* Make a mergeclause list with this guy first. */
174-
curclause_list = lcons(restrictinfo,
175-
lremove(restrictinfo,
176-
listCopy(mergeclause_list)));
174+
if (i != mergeclause_list)
175+
curclause_list = lcons(restrictinfo,
176+
lremove(restrictinfo,
177+
listCopy(mergeclause_list)));
178+
else
179+
curclause_list = mergeclause_list; /* no work at first one... */
180+
177181
/* Build sort pathkeys for both sides.
178182
*
179183
* Note: it's possible that the cheapest paths will already be
@@ -203,7 +207,7 @@ sort_inner_and_outer(Query *root,
203207
innerrel->cheapest_total_path,
204208
restrictlist,
205209
merge_pathkeys,
206-
get_actual_clauses(curclause_list),
210+
curclause_list,
207211
outerkeys,
208212
innerkeys));
209213
}
@@ -265,6 +269,7 @@ match_unsorted_outer(Query *root,
265269
List *trialsortkeys;
266270
Path *cheapest_startup_inner;
267271
Path *cheapest_total_inner;
272+
int num_mergeclauses;
268273
int clausecnt;
269274

270275
/*
@@ -325,7 +330,7 @@ match_unsorted_outer(Query *root,
325330
innerrel->cheapest_total_path,
326331
restrictlist,
327332
merge_pathkeys,
328-
get_actual_clauses(mergeclauses),
333+
mergeclauses,
329334
NIL,
330335
innersortkeys));
331336

@@ -337,10 +342,12 @@ match_unsorted_outer(Query *root,
337342
trialsortkeys = listCopy(innersortkeys); /* modifiable copy */
338343
cheapest_startup_inner = NULL;
339344
cheapest_total_inner = NULL;
345+
num_mergeclauses = length(mergeclauses);
340346

341-
for (clausecnt = length(mergeclauses); clausecnt > 0; clausecnt--)
347+
for (clausecnt = num_mergeclauses; clausecnt > 0; clausecnt--)
342348
{
343349
Path *innerpath;
350+
List *newclauses = NIL;
344351

345352
/* Look for an inner path ordered well enough to merge with
346353
* the first 'clausecnt' mergeclauses. NB: trialsortkeys list
@@ -356,10 +363,11 @@ match_unsorted_outer(Query *root,
356363
TOTAL_COST) < 0))
357364
{
358365
/* Found a cheap (or even-cheaper) sorted path */
359-
List *newclauses;
360-
361-
newclauses = ltruncate(clausecnt,
362-
get_actual_clauses(mergeclauses));
366+
if (clausecnt < num_mergeclauses)
367+
newclauses = ltruncate(clausecnt,
368+
listCopy(mergeclauses));
369+
else
370+
newclauses = mergeclauses;
363371
add_path(joinrel, (Path *)
364372
create_mergejoin_path(joinrel,
365373
outerpath,
@@ -383,10 +391,17 @@ match_unsorted_outer(Query *root,
383391
/* Found a cheap (or even-cheaper) sorted path */
384392
if (innerpath != cheapest_total_inner)
385393
{
386-
List *newclauses;
387-
388-
newclauses = ltruncate(clausecnt,
389-
get_actual_clauses(mergeclauses));
394+
/* Avoid rebuilding clause list if we already made one;
395+
* saves memory in big join trees...
396+
*/
397+
if (newclauses == NIL)
398+
{
399+
if (clausecnt < num_mergeclauses)
400+
newclauses = ltruncate(clausecnt,
401+
listCopy(mergeclauses));
402+
else
403+
newclauses = mergeclauses;
404+
}
390405
add_path(joinrel, (Path *)
391406
create_mergejoin_path(joinrel,
392407
outerpath,
@@ -461,7 +476,7 @@ match_unsorted_inner(Query *root,
461476
innerpath,
462477
restrictlist,
463478
merge_pathkeys,
464-
get_actual_clauses(mergeclauses),
479+
mergeclauses,
465480
outersortkeys,
466481
NIL));
467482
/*
@@ -487,7 +502,7 @@ match_unsorted_inner(Query *root,
487502
innerpath,
488503
restrictlist,
489504
merge_pathkeys,
490-
get_actual_clauses(mergeclauses),
505+
mergeclauses,
491506
NIL,
492507
NIL));
493508

@@ -505,7 +520,7 @@ match_unsorted_inner(Query *root,
505520
innerpath,
506521
restrictlist,
507522
merge_pathkeys,
508-
get_actual_clauses(mergeclauses),
523+
mergeclauses,
509524
NIL,
510525
NIL));
511526
}
@@ -552,6 +567,7 @@ hash_inner_and_outer(Query *root,
552567
Var *left,
553568
*right,
554569
*inner;
570+
List *hashclauses;
555571
Selectivity innerdisbursion;
556572

557573
if (restrictinfo->hashjoinoperator == InvalidOid)
@@ -572,6 +588,9 @@ hash_inner_and_outer(Query *root,
572588
else
573589
continue; /* no good for these input relations */
574590

591+
/* always a one-element list of hash clauses */
592+
hashclauses = lcons(restrictinfo, NIL);
593+
575594
/* estimate disbursion of inner var for costing purposes */
576595
innerdisbursion = estimate_disbursion(root, inner);
577596

@@ -585,15 +604,15 @@ hash_inner_and_outer(Query *root,
585604
outerrel->cheapest_total_path,
586605
innerrel->cheapest_total_path,
587606
restrictlist,
588-
lcons(clause, NIL),
607+
hashclauses,
589608
innerdisbursion));
590609
if (outerrel->cheapest_startup_path != outerrel->cheapest_total_path)
591610
add_path(joinrel, (Path *)
592611
create_hashjoin_path(joinrel,
593612
outerrel->cheapest_startup_path,
594613
innerrel->cheapest_total_path,
595614
restrictlist,
596-
lcons(clause, NIL),
615+
hashclauses,
597616
innerdisbursion));
598617
}
599618
}

src/backend/optimizer/path/pathkeys.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.19 2000/02/15 20:49:17 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.20 2000/02/18 23:47:19 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -778,6 +778,7 @@ make_pathkeys_for_mergeclauses(Query *root,
778778
Node *key;
779779
Oid sortop;
780780
PathKeyItem *item;
781+
List *pathkey;
781782

782783
Assert(restrictinfo->mergejoinoperator != InvalidOid);
783784

@@ -791,10 +792,21 @@ make_pathkeys_for_mergeclauses(Query *root,
791792
key = (Node *) get_leftop(restrictinfo->clause);
792793
sortop = restrictinfo->left_sortop;
793794
/*
794-
* Add a pathkey sublist for this sort item
795+
* Find pathkey sublist for this sort item. We expect to find
796+
* the canonical set including the mergeclause's left and right
797+
* sides; if we get back just the one item, something is rotten.
795798
*/
796799
item = makePathKeyItem(key, sortop);
797-
pathkeys = lappend(pathkeys, make_canonical_pathkey(root, item));
800+
pathkey = make_canonical_pathkey(root, item);
801+
Assert(length(pathkey) > 1);
802+
/*
803+
* Since the item we just made is not in the returned canonical set,
804+
* we can free it --- this saves a useful amount of storage in a
805+
* big join tree.
806+
*/
807+
pfree(item);
808+
809+
pathkeys = lappend(pathkeys, pathkey);
798810
}
799811

800812
return pathkeys;

src/backend/optimizer/plan/createplan.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
*
1212
* IDENTIFICATION
13-
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.85 2000/02/15 20:49:18 tgl Exp $
13+
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.86 2000/02/18 23:47:21 tgl Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -626,13 +626,14 @@ create_mergejoin_node(MergePath *best_path,
626626
*mergeclauses;
627627
MergeJoin *join_node;
628628

629+
mergeclauses = get_actual_clauses(best_path->path_mergeclauses);
630+
629631
/*
630632
* Remove the mergeclauses from the list of join qual clauses,
631633
* leaving the list of quals that must be checked as qpquals.
632634
* Set those clauses to contain INNER/OUTER var references.
633635
*/
634-
qpqual = join_references(set_difference(clauses,
635-
best_path->path_mergeclauses),
636+
qpqual = join_references(set_difference(clauses, mergeclauses),
636637
outer_tlist,
637638
inner_tlist,
638639
(Index) 0);
@@ -641,7 +642,7 @@ create_mergejoin_node(MergePath *best_path,
641642
* Now set the references in the mergeclauses and rearrange them so
642643
* that the outer variable is always on the left.
643644
*/
644-
mergeclauses = switch_outer(join_references(best_path->path_mergeclauses,
645+
mergeclauses = switch_outer(join_references(mergeclauses,
645646
outer_tlist,
646647
inner_tlist,
647648
(Index) 0));
@@ -692,14 +693,14 @@ create_hashjoin_node(HashPath *best_path,
692693
* We represent it as a list anyway, for convenience with routines
693694
* that want to work on lists of clauses.
694695
*/
696+
hashclauses = get_actual_clauses(best_path->path_hashclauses);
695697

696698
/*
697699
* Remove the hashclauses from the list of join qual clauses,
698700
* leaving the list of quals that must be checked as qpquals.
699701
* Set those clauses to contain INNER/OUTER var references.
700702
*/
701-
qpqual = join_references(set_difference(clauses,
702-
best_path->path_hashclauses),
703+
qpqual = join_references(set_difference(clauses, hashclauses),
703704
outer_tlist,
704705
inner_tlist,
705706
(Index) 0);
@@ -708,7 +709,7 @@ create_hashjoin_node(HashPath *best_path,
708709
* Now set the references in the hashclauses and rearrange them so
709710
* that the outer variable is always on the left.
710711
*/
711-
hashclauses = switch_outer(join_references(best_path->path_hashclauses,
712+
hashclauses = switch_outer(join_references(hashclauses,
712713
outer_tlist,
713714
inner_tlist,
714715
(Index) 0));

src/backend/optimizer/util/pathnode.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.60 2000/02/15 20:49:20 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.61 2000/02/18 23:47:30 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -416,7 +416,8 @@ create_nestloop_path(RelOptInfo *joinrel,
416416
* 'inner_path' is the inner path
417417
* 'restrict_clauses' are the RestrictInfo nodes to apply at the join
418418
* 'pathkeys' are the path keys of the new join path
419-
* 'mergeclauses' are the applicable join/restriction clauses
419+
* 'mergeclauses' are the RestrictInfo nodes to use as merge clauses
420+
* (this should be a subset of the restrict_clauses list)
420421
* 'outersortkeys' are the sort varkeys for the outer relation
421422
* 'innersortkeys' are the sort varkeys for the inner relation
422423
*
@@ -473,6 +474,7 @@ create_mergejoin_path(RelOptInfo *joinrel,
473474
* 'inner_path' is the cheapest inner path
474475
* 'restrict_clauses' are the RestrictInfo nodes to apply at the join
475476
* 'hashclauses' is a list of the hash join clause (always a 1-element list)
477+
* (this should be a subset of the restrict_clauses list)
476478
* 'innerdisbursion' is an estimate of the disbursion of the inner hash key
477479
*
478480
*/

src/backend/optimizer/util/relnode.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/relnode.c,v 1.24 2000/02/15 20:49:21 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/relnode.c,v 1.25 2000/02/18 23:47:31 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -345,11 +345,8 @@ subbuild_joinrel_restrictlist(RelOptInfo *joinrel,
345345
foreach(xjoininfo, joininfo_list)
346346
{
347347
JoinInfo *joininfo = (JoinInfo *) lfirst(xjoininfo);
348-
Relids new_unjoined_relids;
349348

350-
new_unjoined_relids = set_differencei(joininfo->unjoined_relids,
351-
joinrel->relids);
352-
if (new_unjoined_relids == NIL)
349+
if (is_subseti(joininfo->unjoined_relids, joinrel->relids))
353350
{
354351
/*
355352
* Clauses in this JoinInfo list become restriction clauses

src/include/nodes/relation.h

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: relation.h,v 1.44 2000/02/15 20:49:25 tgl Exp $
10+
* $Id: relation.h,v 1.45 2000/02/18 23:47:17 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -237,6 +237,8 @@ typedef struct Path
237237
* are usable as indexquals (as determined by indxpath.c) may appear here.
238238
* NOTE that the semantics of the top-level list in 'indexqual' is OR
239239
* combination, while the sublists are implicitly AND combinations!
240+
* Also note that indexquals lists do not contain RestrictInfo nodes,
241+
* just bare clause expressions.
240242
*
241243
* 'indexscandir' is one of:
242244
* ForwardScanDirection: forward scan of an ordered index
@@ -293,32 +295,39 @@ typedef JoinPath NestPath;
293295
/*
294296
* A mergejoin path has these fields.
295297
*
298+
* path_mergeclauses lists the clauses (in the form of RestrictInfos)
299+
* that will be used in the merge. (Before 7.0, this was a list of
300+
* bare clause expressions, but we can save on list memory by leaving
301+
* it in the form of a RestrictInfo list.)
302+
*
296303
* Note that the mergeclauses are a subset of the parent relation's
297304
* restriction-clause list. Any join clauses that are not mergejoinable
298305
* appear only in the parent's restrict list, and must be checked by a
299306
* qpqual at execution time.
307+
*
308+
* outersortkeys (resp. innersortkeys) is NIL if the outer path
309+
* (resp. inner path) is already ordered appropriately for the
310+
* mergejoin. If it is not NIL then it is a PathKeys list describing
311+
* the ordering that must be created by an explicit sort step.
300312
*/
301313

302314
typedef struct MergePath
303315
{
304316
JoinPath jpath;
305-
List *path_mergeclauses; /* join clauses used for merge */
306-
/*
307-
* outersortkeys (resp. innersortkeys) is NIL if the outer path
308-
* (resp. inner path) is already ordered appropriately for the
309-
* mergejoin. If it is not NIL then it is a PathKeys list describing
310-
* the ordering that must be created by an explicit sort step.
311-
*/
312-
List *outersortkeys;
313-
List *innersortkeys;
317+
List *path_mergeclauses; /* join clauses to be used for merge */
318+
List *outersortkeys; /* keys for explicit sort, if any */
319+
List *innersortkeys; /* keys for explicit sort, if any */
314320
} MergePath;
315321

316322
/*
317323
* A hashjoin path has these fields.
318324
*
319325
* The remarks above for mergeclauses apply for hashclauses as well.
320-
* However, hashjoin does not care what order its inputs appear in,
321-
* so we have no need for sortkeys.
326+
* (But note that path_hashclauses will always be a one-element list,
327+
* since we only hash on one hashable clause.)
328+
*
329+
* Hashjoin does not care what order its inputs appear in, so we have
330+
* no need for sortkeys.
322331
*/
323332

324333
typedef struct HashPath

0 commit comments

Comments
 (0)