8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $PostgreSQL: pgsql/src/backend/optimizer/util/relnode.c,v 1.67 2005/06/05 22:32:56 tgl Exp $
11
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/relnode.c,v 1.68 2005/06/06 04:13:36 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
25
25
26
26
static RelOptInfo * make_reloptinfo (PlannerInfo * root , int relid ,
27
27
RelOptKind reloptkind );
28
- static void build_joinrel_tlist (PlannerInfo * root , RelOptInfo * joinrel );
28
+ static void build_joinrel_tlist (PlannerInfo * root , RelOptInfo * joinrel ,
29
+ RelOptInfo * input_rel );
29
30
static List * build_joinrel_restrictlist (PlannerInfo * root ,
30
31
RelOptInfo * joinrel ,
31
32
RelOptInfo * outer_rel ,
@@ -43,78 +44,60 @@ static void subbuild_joinrel_joinlist(RelOptInfo *joinrel,
43
44
/*
44
45
* build_base_rel
45
46
* Construct a new base relation RelOptInfo, and put it in the query's
46
- * base_rel_list .
47
+ * base_rel_array .
47
48
*/
48
49
void
49
50
build_base_rel (PlannerInfo * root , int relid )
50
51
{
51
- ListCell * l ;
52
- RelOptInfo * rel ;
52
+ Assert (relid > 0 );
53
53
54
54
/* Rel should not exist already */
55
- foreach (l , root -> base_rel_list )
56
- {
57
- rel = (RelOptInfo * ) lfirst (l );
58
- if (relid == rel -> relid )
59
- elog (ERROR , "rel already exists" );
60
- }
61
-
62
- /* It should not exist as an "other" rel, either */
63
- foreach (l , root -> other_rel_list )
64
- {
65
- rel = (RelOptInfo * ) lfirst (l );
66
- if (relid == rel -> relid )
67
- elog (ERROR , "rel already exists as \"other\" rel" );
68
- }
55
+ if (relid < root -> base_rel_array_size &&
56
+ root -> base_rel_array [relid ] != NULL )
57
+ elog (ERROR , "rel already exists" );
69
58
70
59
/* No existing RelOptInfo for this base rel, so make a new one */
71
- rel = make_reloptinfo (root , relid , RELOPT_BASEREL );
72
-
73
- /* and add it to the list */
74
- root -> base_rel_list = lcons (rel , root -> base_rel_list );
60
+ (void ) make_reloptinfo (root , relid , RELOPT_BASEREL );
75
61
}
76
62
77
63
/*
78
64
* build_other_rel
79
65
* Returns relation entry corresponding to 'relid', creating a new one
80
66
* if necessary. This is for 'other' relations, which are much like
81
- * base relations except that they live in a different list .
67
+ * base relations except that they have a different RelOptKind .
82
68
*/
83
69
RelOptInfo *
84
70
build_other_rel (PlannerInfo * root , int relid )
85
71
{
86
- ListCell * l ;
87
72
RelOptInfo * rel ;
88
73
74
+ Assert (relid > 0 );
75
+
89
76
/* Already made? */
90
- foreach ( l , root -> other_rel_list )
77
+ if ( relid < root -> base_rel_array_size )
91
78
{
92
- rel = (RelOptInfo * ) lfirst (l );
93
- if (relid == rel -> relid )
79
+ rel = root -> base_rel_array [relid ];
80
+ if (rel )
81
+ {
82
+ /* it should not exist as a base rel */
83
+ if (rel -> reloptkind == RELOPT_BASEREL )
84
+ elog (ERROR , "rel already exists as base rel" );
85
+ /* otherwise, A-OK */
94
86
return rel ;
95
- }
96
-
97
- /* It should not exist as a base rel */
98
- foreach (l , root -> base_rel_list )
99
- {
100
- rel = (RelOptInfo * ) lfirst (l );
101
- if (relid == rel -> relid )
102
- elog (ERROR , "rel already exists as base rel" );
87
+ }
103
88
}
104
89
105
90
/* No existing RelOptInfo for this other rel, so make a new one */
106
91
/* presently, must be an inheritance child rel */
107
92
rel = make_reloptinfo (root , relid , RELOPT_OTHER_CHILD_REL );
108
93
109
- /* and add it to the list */
110
- root -> other_rel_list = lcons (rel , root -> other_rel_list );
111
-
112
94
return rel ;
113
95
}
114
96
115
97
/*
116
98
* make_reloptinfo
117
- * Construct a RelOptInfo for the specified rangetable index.
99
+ * Construct a RelOptInfo for the specified rangetable index,
100
+ * and enter it into base_rel_array.
118
101
*
119
102
* Common code for build_base_rel and build_other_rel.
120
103
*/
@@ -172,31 +155,40 @@ make_reloptinfo(PlannerInfo *root, int relid, RelOptKind reloptkind)
172
155
break ;
173
156
}
174
157
158
+ /* Add the finished struct to the base_rel_array */
159
+ if (relid >= root -> base_rel_array_size )
160
+ {
161
+ int oldsize = root -> base_rel_array_size ;
162
+ int newsize ;
163
+
164
+ newsize = Max (oldsize * 2 , relid + 1 );
165
+ root -> base_rel_array = (RelOptInfo * * )
166
+ repalloc (root -> base_rel_array , newsize * sizeof (RelOptInfo * ));
167
+ MemSet (root -> base_rel_array + oldsize , 0 ,
168
+ (newsize - oldsize ) * sizeof (RelOptInfo * ));
169
+ root -> base_rel_array_size = newsize ;
170
+ }
171
+
172
+ root -> base_rel_array [relid ] = rel ;
173
+
175
174
return rel ;
176
175
}
177
176
178
177
/*
179
178
* find_base_rel
180
- * Find a base or other relation entry, which must already exist
181
- * (since we'd have no idea which list to add it to).
179
+ * Find a base or other relation entry, which must already exist.
182
180
*/
183
181
RelOptInfo *
184
182
find_base_rel (PlannerInfo * root , int relid )
185
183
{
186
- ListCell * l ;
187
184
RelOptInfo * rel ;
188
185
189
- foreach (l , root -> base_rel_list )
190
- {
191
- rel = (RelOptInfo * ) lfirst (l );
192
- if (relid == rel -> relid )
193
- return rel ;
194
- }
186
+ Assert (relid > 0 );
195
187
196
- foreach ( l , root -> other_rel_list )
188
+ if ( relid < root -> base_rel_array_size )
197
189
{
198
- rel = ( RelOptInfo * ) lfirst ( l ) ;
199
- if (relid == rel -> relid )
190
+ rel = root -> base_rel_array [ relid ] ;
191
+ if (rel )
200
192
return rel ;
201
193
}
202
194
@@ -308,8 +300,13 @@ build_join_rel(PlannerInfo *root,
308
300
* Create a new tlist containing just the vars that need to be output
309
301
* from this join (ie, are needed for higher joinclauses or final
310
302
* output).
303
+ *
304
+ * NOTE: the tlist order for a join rel will depend on which pair of
305
+ * outer and inner rels we first try to build it from. But the
306
+ * contents should be the same regardless.
311
307
*/
312
- build_joinrel_tlist (root , joinrel );
308
+ build_joinrel_tlist (root , joinrel , outer_rel );
309
+ build_joinrel_tlist (root , joinrel , inner_rel );
313
310
314
311
/*
315
312
* Construct restrict and join clause lists for the new joinrel. (The
@@ -344,48 +341,39 @@ build_join_rel(PlannerInfo *root,
344
341
* Builds a join relation's target list.
345
342
*
346
343
* The join's targetlist includes all Vars of its member relations that
347
- * will still be needed above the join.
348
- *
349
- * In a former lifetime, this just merged the tlists of the two member
350
- * relations first presented. While we could still do that, working from
351
- * lists of Vars would mean doing a find_base_rel lookup for each Var.
352
- * It seems more efficient to scan the list of base rels and collect the
353
- * needed vars directly from there.
344
+ * will still be needed above the join. This subroutine adds all such
345
+ * Vars from the specified input rel's tlist to the join rel's tlist.
354
346
*
355
347
* We also compute the expected width of the join's output, making use
356
348
* of data that was cached at the baserel level by set_rel_width().
357
349
*/
358
350
static void
359
- build_joinrel_tlist (PlannerInfo * root , RelOptInfo * joinrel )
351
+ build_joinrel_tlist (PlannerInfo * root , RelOptInfo * joinrel ,
352
+ RelOptInfo * input_rel )
360
353
{
361
354
Relids relids = joinrel -> relids ;
362
- ListCell * rels ;
355
+ ListCell * vars ;
363
356
364
- joinrel -> reltargetlist = NIL ;
365
- joinrel -> width = 0 ;
366
-
367
- foreach (rels , root -> base_rel_list )
357
+ foreach (vars , input_rel -> reltargetlist )
368
358
{
369
- RelOptInfo * baserel = (RelOptInfo * ) lfirst (rels );
370
- ListCell * vars ;
359
+ Var * var = (Var * ) lfirst (vars );
360
+ RelOptInfo * baserel ;
361
+ int ndx ;
362
+
363
+ /* We can't run into any child RowExprs here */
364
+ Assert (IsA (var , Var ));
371
365
372
- if (! bms_is_member ( baserel -> relid , relids ))
373
- continue ;
366
+ /* Get the Var's original base rel */
367
+ baserel = find_base_rel ( root , var -> varno ) ;
374
368
375
- foreach (vars , baserel -> reltargetlist )
369
+ /* Is it still needed above this joinrel? */
370
+ ndx = var -> varattno - baserel -> min_attr ;
371
+ if (bms_nonempty_difference (baserel -> attr_needed [ndx ], relids ))
376
372
{
377
- Var * var = (Var * ) lfirst (vars );
378
- int ndx = var -> varattno - baserel -> min_attr ;
379
-
380
- /* We can't run into any child RowExprs here */
381
- Assert (IsA (var , Var ));
382
-
383
- if (bms_nonempty_difference (baserel -> attr_needed [ndx ], relids ))
384
- {
385
- joinrel -> reltargetlist = lappend (joinrel -> reltargetlist , var );
386
- Assert (baserel -> attr_widths [ndx ] > 0 );
387
- joinrel -> width += baserel -> attr_widths [ndx ];
388
- }
373
+ /* Yup, add it to the output */
374
+ joinrel -> reltargetlist = lappend (joinrel -> reltargetlist , var );
375
+ Assert (baserel -> attr_widths [ndx ] > 0 );
376
+ joinrel -> width += baserel -> attr_widths [ndx ];
389
377
}
390
378
}
391
379
}
0 commit comments