|
7 | 7 | * Portions Copyright (c) 1994, Regents of the University of California
|
8 | 8 | *
|
9 | 9 | * IDENTIFICATION
|
10 |
| - * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.148 2009/04/05 19:59:40 tgl Exp $ |
| 10 | + * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.149 2009/04/25 16:44:56 tgl Exp $ |
11 | 11 | *
|
12 | 12 | *-------------------------------------------------------------------------
|
13 | 13 | */
|
@@ -437,13 +437,24 @@ build_subplan(PlannerInfo *root, Plan *plan, List *rtable,
|
437 | 437 |
|
438 | 438 | if (pitem->abslevel == root->query_level)
|
439 | 439 | {
|
440 |
| - splan->parParam = lappend_int(splan->parParam, paramid); |
| 440 | + Node *arg; |
| 441 | + |
441 | 442 | /*
|
442 | 443 | * The Var or Aggref has already been adjusted to have the correct
|
443 | 444 | * varlevelsup or agglevelsup. We probably don't even need to
|
444 | 445 | * copy it again, but be safe.
|
445 | 446 | */
|
446 |
| - splan->args = lappend(splan->args, copyObject(pitem->item)); |
| 447 | + arg = copyObject(pitem->item); |
| 448 | + |
| 449 | + /* |
| 450 | + * If it's an Aggref, its arguments might contain SubLinks, |
| 451 | + * which have not yet been processed. Do that now. |
| 452 | + */ |
| 453 | + if (IsA(arg, Aggref)) |
| 454 | + arg = SS_process_sublinks(root, arg, false); |
| 455 | + |
| 456 | + splan->parParam = lappend_int(splan->parParam, paramid); |
| 457 | + splan->args = lappend(splan->args, arg); |
447 | 458 | }
|
448 | 459 | }
|
449 | 460 | bms_free(tmpset);
|
@@ -1531,6 +1542,12 @@ convert_EXISTS_to_ANY(PlannerInfo *root, Query *subselect,
|
1531 | 1542 | * so after expanding its sublinks to subplans. And we don't want any steps
|
1532 | 1543 | * in between, else those steps would never get applied to the aggregate
|
1533 | 1544 | * argument expressions, either in the parent or the child level.
|
| 1545 | + * |
| 1546 | + * Another fairly tricky thing going on here is the handling of SubLinks in |
| 1547 | + * the arguments of uplevel aggregates. Those are not touched inside the |
| 1548 | + * intermediate query level, either. Instead, SS_process_sublinks recurses |
| 1549 | + * on them after copying the Aggref expression into the parent plan level |
| 1550 | + * (this is actually taken care of in build_subplan). |
1534 | 1551 | */
|
1535 | 1552 | Node *
|
1536 | 1553 | SS_replace_correlation_vars(PlannerInfo *root, Node *expr)
|
@@ -1607,6 +1624,18 @@ process_sublinks_mutator(Node *node, process_sublinks_context *context)
|
1607 | 1624 | context->isTopQual);
|
1608 | 1625 | }
|
1609 | 1626 |
|
| 1627 | + /* |
| 1628 | + * Don't recurse into the arguments of an outer aggregate here. |
| 1629 | + * Any SubLinks in the arguments have to be dealt with at the outer |
| 1630 | + * query level; they'll be handled when build_subplan collects the |
| 1631 | + * Aggref into the arguments to be passed down to the current subplan. |
| 1632 | + */ |
| 1633 | + if (IsA(node, Aggref)) |
| 1634 | + { |
| 1635 | + if (((Aggref *) node)->agglevelsup > 0) |
| 1636 | + return node; |
| 1637 | + } |
| 1638 | + |
1610 | 1639 | /*
|
1611 | 1640 | * We should never see a SubPlan expression in the input (since this is
|
1612 | 1641 | * the very routine that creates 'em to begin with). We shouldn't find
|
|
0 commit comments