|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.2 2005/04/1204:26:24 tgl Exp $ |
| 11 | + * $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.3 2005/04/1205:11:28 tgl Exp $ |
12 | 12 | *
|
13 | 13 | *-------------------------------------------------------------------------
|
14 | 14 | */
|
@@ -185,6 +185,8 @@ optimize_minmax_aggregates(Query *root, List *tlist, Path *best_path)
|
185 | 185 | {
|
186 | 186 | Assert(((ResultPath*)best_path)->subpath!=NULL);
|
187 | 187 | constant_quals= ((ResultPath*)best_path)->constantqual;
|
| 188 | +/* no need to do this more than once: */ |
| 189 | +constant_quals=order_qual_clauses(root,constant_quals); |
188 | 190 | }
|
189 | 191 | else
|
190 | 192 | constant_quals=NIL;
|
@@ -438,10 +440,10 @@ static void
|
438 | 440 | make_agg_subplan(Query*root,MinMaxAggInfo*info,List*constant_quals)
|
439 | 441 | {
|
440 | 442 | Query*subquery;
|
441 |
| -Path*path; |
442 | 443 | Plan*plan;
|
443 | 444 | TargetEntry*tle;
|
444 | 445 | SortClause*sortcl;
|
| 446 | +NullTest*ntest; |
445 | 447 |
|
446 | 448 | /*
|
447 | 449 | * Generate a suitably modified Query node. Much of the work here is
|
@@ -482,18 +484,30 @@ make_agg_subplan(Query *root, MinMaxAggInfo *info, List *constant_quals)
|
482 | 484 | * Generate the plan for the subquery. We already have a Path for
|
483 | 485 | * the basic indexscan, but we have to convert it to a Plan and
|
484 | 486 | * attach a LIMIT node above it. We might need a gating Result, too,
|
485 |
| - * which is most easily added at the Path stage. |
| 487 | + * to handle any non-variable qual clauses. |
| 488 | + * |
| 489 | + * Also we must add a "WHERE foo IS NOT NULL" restriction to the |
| 490 | + * indexscan, to be sure we don't return a NULL, which'd be contrary |
| 491 | + * to the standard behavior of MIN/MAX. XXX ideally this should be |
| 492 | + * done earlier, so that the selectivity of the restriction could be |
| 493 | + * included in our cost estimates. But that looks painful, and in |
| 494 | + * most cases the fraction of NULLs isn't high enough to change the |
| 495 | + * decision. |
486 | 496 | */
|
487 |
| -path=(Path*)info->path; |
| 497 | +plan=create_plan(subquery, (Path*)info->path); |
488 | 498 |
|
489 |
| -if (constant_quals) |
490 |
| -path= (Path*)create_result_path(NULL, |
491 |
| -path, |
492 |
| -copyObject(constant_quals)); |
| 499 | +plan->targetlist=copyObject(subquery->targetList); |
493 | 500 |
|
494 |
| -plan=create_plan(subquery,path); |
| 501 | +ntest=makeNode(NullTest); |
| 502 | +ntest->nulltesttype=IS_NOT_NULL; |
| 503 | +ntest->arg=copyObject(info->target); |
495 | 504 |
|
496 |
| -plan->targetlist=copyObject(subquery->targetList); |
| 505 | +plan->qual=lappend(plan->qual,ntest); |
| 506 | + |
| 507 | +if (constant_quals) |
| 508 | +plan= (Plan*)make_result(copyObject(plan->targetlist), |
| 509 | +copyObject(constant_quals), |
| 510 | +plan); |
497 | 511 |
|
498 | 512 | plan= (Plan*)make_limit(plan,
|
499 | 513 | subquery->limitOffset,
|
|