7
7
* Portions Copyright (c) 1994, Regents of the University of California
8
8
*
9
9
* IDENTIFICATION
10
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.28 2000/02/15 20:49:18 tgl Exp $
10
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.29 2000/03/02 04:08:16 tgl Exp $
11
11
*
12
12
*-------------------------------------------------------------------------
13
13
*/
18
18
#include "nodes/makefuncs.h"
19
19
#include "nodes/nodeFuncs.h"
20
20
#include "optimizer/clauses.h"
21
+ #include "optimizer/cost.h"
22
+ #include "optimizer/planmain.h"
21
23
#include "optimizer/planner.h"
22
24
#include "optimizer/subselect.h"
23
25
#include "parser/parse_expr.h"
@@ -123,6 +125,7 @@ static Node *
123
125
make_subplan (SubLink * slink )
124
126
{
125
127
SubPlan * node = makeNode (SubPlan );
128
+ Query * subquery = (Query * ) (slink -> subselect );
126
129
double tuple_fraction ;
127
130
Plan * plan ;
128
131
List * lst ;
@@ -151,8 +154,7 @@ make_subplan(SubLink *slink)
151
154
else
152
155
tuple_fraction = 0.5 ;/* 50% */
153
156
154
- node -> plan = plan = union_planner ((Query * )slink -> subselect ,
155
- tuple_fraction );
157
+ node -> plan = plan = union_planner (subquery ,tuple_fraction );
156
158
157
159
/*
158
160
* Assign subPlan, extParam and locParam to plan nodes. At the moment,
@@ -179,7 +181,7 @@ make_subplan(SubLink *slink)
179
181
PlannerQueryLevel -- ;
180
182
181
183
node -> plan_id = PlannerPlanId ++ ;
182
- node -> rtable = (( Query * ) slink -> subselect ) -> rtable ;
184
+ node -> rtable = subquery -> rtable ;
183
185
node -> sublink = slink ;
184
186
slink -> subselect = NULL ;/* cool ?! */
185
187
@@ -287,12 +289,76 @@ make_subplan(SubLink *slink)
287
289
}
288
290
else
289
291
{
290
- /* make expression of SUBPLAN type */
291
292
Expr * expr = makeNode (Expr );
292
293
List * args = NIL ;
293
294
List * newoper = NIL ;
294
295
int i = 0 ;
295
296
297
+ /*
298
+ * We can't convert subplans of ALL_SUBLINK or ANY_SUBLINK types to
299
+ * initPlans, even when they are uncorrelated or undirect correlated,
300
+ * because we need to scan the output of the subplan for each outer
301
+ * tuple. However, we have the option to tack a MATERIAL node onto
302
+ * the top of an uncorrelated/undirect correlated subplan, which lets
303
+ * us do the work of evaluating the subplan only once. We do this
304
+ * if the subplan's top plan node is anything more complicated than
305
+ * a sequential or index scan, and we do it even for those plan types
306
+ * if the qual appears selective enough to eliminate many tuples.
307
+ */
308
+ if (node -> parParam == NIL )
309
+ {
310
+ bool use_material ;
311
+
312
+ switch (nodeTag (plan ))
313
+ {
314
+ case T_SeqScan :
315
+ {
316
+ Selectivity qualsel ;
317
+
318
+ qualsel = clauselist_selectivity (subquery ,plan -> qual ,0 );
319
+ /* Is 10% selectivity a good threshold?? */
320
+ use_material = qualsel < 0.10 ;
321
+ break ;
322
+ }
323
+ case T_IndexScan :
324
+ {
325
+ List * indxqual = ((IndexScan * )plan )-> indxqualorig ;
326
+ Selectivity qualsel ;
327
+
328
+ qualsel = clauselist_selectivity (subquery ,plan -> qual ,0 );
329
+ qualsel *=clauselist_selectivity (subquery ,indxqual ,0 );
330
+ /* Note: if index is lossy, we just double-counted the
331
+ * index selectivity. Worth fixing?
332
+ */
333
+ /* Is 10% selectivity a good threshold?? */
334
+ use_material = qualsel < 0.10 ;
335
+ break ;
336
+ }
337
+ case T_Material :
338
+ case T_Sort :
339
+ /* Don't add another Material node if there's one already,
340
+ * nor if the top node is a Sort, since Sort materializes
341
+ * its output anyway. (I doubt either case can happen in
342
+ * practice for a subplan, but...)
343
+ */
344
+ use_material = false;
345
+ break ;
346
+ default :
347
+ use_material = true;
348
+ break ;
349
+ }
350
+ if (use_material )
351
+ {
352
+ plan = (Plan * )make_noname (plan -> targetlist ,
353
+ NIL ,
354
+ plan );
355
+ node -> plan = plan ;
356
+ }
357
+ }
358
+
359
+ /*
360
+ * Make expression of SUBPLAN type
361
+ */
296
362
expr -> typeOid = BOOLOID ;/* bogus, but we don't really care */
297
363
expr -> opType = SUBPLAN_EXPR ;
298
364
expr -> oper = (Node * )node ;