|
9 | 9 | *
|
10 | 10 | *
|
11 | 11 | * IDENTIFICATION
|
12 |
| - * $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.154 2009/10/26 02:26:34 tgl Exp $ |
| 12 | + * $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.155 2009/11/16 18:04:40 tgl Exp $ |
13 | 13 | *
|
14 | 14 | *-------------------------------------------------------------------------
|
15 | 15 | */
|
@@ -101,6 +101,10 @@ static Var *search_indexed_tlist_for_var(Var *var,
|
101 | 101 | static Var *search_indexed_tlist_for_non_var(Node *node,
|
102 | 102 | indexed_tlist *itlist,
|
103 | 103 | Index newvarno);
|
| 104 | +static Var *search_indexed_tlist_for_sortgroupref(Node *node, |
| 105 | + Index sortgroupref, |
| 106 | + indexed_tlist *itlist, |
| 107 | + Index newvarno); |
104 | 108 | static List *fix_join_expr(PlannerGlobal *glob,
|
105 | 109 | List *clauses,
|
106 | 110 | indexed_tlist *outer_itlist,
|
@@ -1197,10 +1201,25 @@ set_upper_references(PlannerGlobal *glob, Plan *plan, int rtoffset)
|
1197 | 1201 | TargetEntry *tle = (TargetEntry *) lfirst(l);
|
1198 | 1202 | Node *newexpr;
|
1199 | 1203 |
|
1200 |
| - newexpr = fix_upper_expr(glob, |
1201 |
| - (Node *) tle->expr, |
1202 |
| - subplan_itlist, |
1203 |
| - rtoffset); |
| 1204 | + /* If it's a non-Var sort/group item, first try to match by sortref */ |
| 1205 | + if (tle->ressortgroupref != 0 && !IsA(tle->expr, Var)) |
| 1206 | + { |
| 1207 | + newexpr = (Node *) |
| 1208 | + search_indexed_tlist_for_sortgroupref((Node *) tle->expr, |
| 1209 | + tle->ressortgroupref, |
| 1210 | + subplan_itlist, |
| 1211 | + OUTER); |
| 1212 | + if (!newexpr) |
| 1213 | + newexpr = fix_upper_expr(glob, |
| 1214 | + (Node *) tle->expr, |
| 1215 | + subplan_itlist, |
| 1216 | + rtoffset); |
| 1217 | + } |
| 1218 | + else |
| 1219 | + newexpr = fix_upper_expr(glob, |
| 1220 | + (Node *) tle->expr, |
| 1221 | + subplan_itlist, |
| 1222 | + rtoffset); |
1204 | 1223 | tle = flatCopyTargetEntry(tle);
|
1205 | 1224 | tle->expr = (Expr *) newexpr;
|
1206 | 1225 | output_targetlist = lappend(output_targetlist, tle);
|
@@ -1444,6 +1463,49 @@ search_indexed_tlist_for_non_var(Node *node,
|
1444 | 1463 | return NULL; /* no match */
|
1445 | 1464 | }
|
1446 | 1465 |
|
| 1466 | +/* |
| 1467 | + * search_indexed_tlist_for_sortgroupref --- find a sort/group expression |
| 1468 | + * (which is assumed not to be just a Var) |
| 1469 | + * |
| 1470 | + * If a match is found, return a Var constructed to reference the tlist item. |
| 1471 | + * If no match, return NULL. |
| 1472 | + * |
| 1473 | + * This is needed to ensure that we select the right subplan TLE in cases |
| 1474 | + * where there are multiple textually-equal()-but-volatile sort expressions. |
| 1475 | + * And it's also faster than search_indexed_tlist_for_non_var. |
| 1476 | + */ |
| 1477 | +static Var * |
| 1478 | +search_indexed_tlist_for_sortgroupref(Node *node, |
| 1479 | + Index sortgroupref, |
| 1480 | + indexed_tlist *itlist, |
| 1481 | + Index newvarno) |
| 1482 | +{ |
| 1483 | + ListCell *lc; |
| 1484 | + |
| 1485 | + foreach(lc, itlist->tlist) |
| 1486 | + { |
| 1487 | + TargetEntry *tle = (TargetEntry *) lfirst(lc); |
| 1488 | + |
| 1489 | + /* The equal() check should be redundant, but let's be paranoid */ |
| 1490 | + if (tle->ressortgroupref == sortgroupref && |
| 1491 | + equal(node, tle->expr)) |
| 1492 | + { |
| 1493 | + /* Found a matching subplan output expression */ |
| 1494 | + Var *newvar; |
| 1495 | + |
| 1496 | + newvar = makeVar(newvarno, |
| 1497 | + tle->resno, |
| 1498 | + exprType((Node *) tle->expr), |
| 1499 | + exprTypmod((Node *) tle->expr), |
| 1500 | + 0); |
| 1501 | + newvar->varnoold = 0; /* wasn't ever a plain Var */ |
| 1502 | + newvar->varoattno = 0; |
| 1503 | + return newvar; |
| 1504 | + } |
| 1505 | + } |
| 1506 | + return NULL; /* no match */ |
| 1507 | +} |
| 1508 | + |
1447 | 1509 | /*
|
1448 | 1510 | * fix_join_expr
|
1449 | 1511 | * Create a new set of targetlist entries or join qual clauses by
|
|
0 commit comments