aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/path/prune.c
blob: 33fb67bc5735203478d0a9cdf2c85668683f724a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/*-------------------------------------------------------------------------
 *
 * prune.c
 *	  Routines to prune redundant paths and relations
 *
 * Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/prune.c,v 1.43 1999/08/16 02:17:52 tgl Exp $
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"


#include "optimizer/cost.h"
#include "optimizer/pathnode.h"
#include "optimizer/paths.h"

static List *merge_rel_with_same_relids(RelOptInfo *rel, List *unmerged_rels);

/*
 * merge_rels_with_same_relids
 *	  Removes any redundant relation entries from a list of rel nodes
 *	  'rel_list', merging their pathlists into the first non-duplicate
 *	  relation entry for each value of relids.
 *
 * Returns the resulting list.
 */
void
merge_rels_with_same_relids(List *rel_list)
{
	List	   *i;

	/*
	 * rel_list can shorten while running as duplicate relations are
	 * deleted.  Obviously, the first relation can't be a duplicate,
	 * so the list head pointer won't change.
	 */
	foreach(i, rel_list)
	{
		lnext(i) = merge_rel_with_same_relids((RelOptInfo *) lfirst(i),
											  lnext(i));
	}
}

/*
 * merge_rel_with_same_relids
 *	  Prunes those relations from 'unmerged_rels' that are redundant with
 *	  'rel'.  A relation is redundant if it is built up of the same
 *	  relations as 'rel'.  Paths for the redundant relations are merged into
 *	  the pathlist of 'rel'.
 *
 * Returns a list of non-redundant relations, and sets the pathlist field
 * of 'rel' appropriately.
 *
 */
static List *
merge_rel_with_same_relids(RelOptInfo *rel, List *unmerged_rels)
{
	List	   *result = NIL;
	List	   *i;

	foreach(i, unmerged_rels)
	{
		RelOptInfo *unmerged_rel = (RelOptInfo *) lfirst(i);

		if (same(rel->relids, unmerged_rel->relids))
		{
			/*
			 * These rels are for the same set of base relations,
			 * so get the best of their pathlists.  We assume it's
			 * ok to reassign a path to the other RelOptInfo without
			 * doing more than changing its parent pointer (cf. pathnode.c).
			 */
			rel->pathlist = add_pathlist(rel,
										 rel->pathlist,
										 unmerged_rel->pathlist);
		}
		else
			result = lappend(result, unmerged_rel);
	}
	return result;
}

/*
 * rels_set_cheapest
 *	  For each relation entry in 'rel_list' (which should contain only join
 *	  relations), set pointers to the cheapest path and compute rel size.
 */
void
rels_set_cheapest(List *rel_list)
{
	List	   *x;

	foreach(x, rel_list)
	{
		RelOptInfo	   *rel = (RelOptInfo *) lfirst(x);
		JoinPath	   *cheapest;

		cheapest = (JoinPath *) set_cheapest(rel, rel->pathlist);
		if (IsA_JoinPath(cheapest))
			rel->size = compute_joinrel_size(cheapest);
		else
			elog(ERROR, "rels_set_cheapest: non JoinPath found");
	}
}