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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
/*------------------------------------------------------------------------
*
* geqo_eval.c
* Routines to evaluate query trees
*
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: geqo_eval.c,v 1.53 2000/07/28 02:13:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/* contributed by:
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
* Martin Utesch * Institute of Automatic Control *
= = University of Mining and Technology =
* utesch@aut.tu-freiberg.de * Freiberg, Germany *
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
*/
#include "postgres.h"
#include <math.h>
#include <limits.h>
#include "optimizer/geqo.h"
#include "optimizer/pathnode.h"
#include "optimizer/paths.h"
#include "utils/memutils.h"
/*
* geqo_eval
*
* Returns cost of a query tree as an individual of the population.
*/
Cost
geqo_eval(Query *root, Gene *tour, int num_gene)
{
MemoryContext mycontext;
MemoryContext oldcxt;
RelOptInfo *joinrel;
Cost fitness;
List *savelist;
/*
* Create a private memory context that will hold all temp storage
* allocated inside gimme_tree().
*
* Since geqo_eval() will be called many times, we can't afford to let
* all that memory go unreclaimed until end of statement. Note we make
* the temp context a child of TransactionCommandContext, so that
* it will be freed even if we abort via elog(ERROR).
*/
mycontext = AllocSetContextCreate(TransactionCommandContext,
"GEQO",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
oldcxt = MemoryContextSwitchTo(mycontext);
/* preserve root->join_rel_list, which gimme_tree changes */
savelist = root->join_rel_list;
/* construct the best path for the given combination of relations */
joinrel = gimme_tree(root, tour, 0, num_gene, NULL);
/*
* compute fitness
*
* XXX geqo does not currently support optimization for partial result
* retrieval --- how to fix?
*/
fitness = joinrel->cheapest_total_path->total_cost;
/* restore join_rel_list */
root->join_rel_list = savelist;
/* release all the memory acquired within gimme_tree */
MemoryContextSwitchTo(oldcxt);
MemoryContextDelete(mycontext);
return fitness;
}
/*
* gimme_tree
* this program presumes that only LEFT-SIDED TREES are considered!
*
* 'old_rel' is the preceding join
*
* 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)
{
RelOptInfo *inner_rel; /* current relation */
int base_rel_index;
RelOptInfo *new_rel;
if (rel_count < num_gene)
{ /* tree not yet finished */
/* 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);
if (rel_count == 0)
{ /* processing first join with
* base_rel_index = (int) tour[0] */
rel_count++;
return gimme_tree(root, tour, rel_count, num_gene, inner_rel);
}
else
{ /* tree main part */
List *acceptable_rels = lcons(inner_rel, NIL);
new_rel = make_rels_by_clause_joins(root, old_rel,
acceptable_rels);
if (!new_rel)
{
new_rel = make_rels_by_clauseless_joins(root, old_rel,
acceptable_rels);
if (!new_rel)
elog(ERROR, "gimme_tree: failed to construct join rel");
}
rel_count++;
Assert(length(new_rel->relids) == rel_count);
/* Find and save the cheapest paths for this rel */
set_cheapest(new_rel);
return gimme_tree(root, tour, rel_count, num_gene, new_rel);
}
}
return old_rel; /* tree finished ... */
}
|