|
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, |
|