|
11 | 11 | * Portions Copyright (c) 1994, Regents of the University of California
|
12 | 12 | *
|
13 | 13 | * IDENTIFICATION
|
14 |
| - * $PostgreSQL: pgsql/src/backend/optimizer/path/pathkeys.c,v 1.77 2006/07/14 14:52:20 momjian Exp $ |
| 14 | + * $PostgreSQL: pgsql/src/backend/optimizer/path/pathkeys.c,v 1.78 2006/08/17 17:02:49 tgl Exp $ |
15 | 15 | *
|
16 | 16 | *-------------------------------------------------------------------------
|
17 | 17 | */
|
@@ -1059,39 +1059,73 @@ convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel,
|
1059 | 1059 | {
|
1060 | 1060 | PathKeyItem *sub_item = (PathKeyItem *) lfirst(j);
|
1061 | 1061 | Node *sub_key = sub_item->key;
|
| 1062 | + Expr *rtarg; |
1062 | 1063 | ListCell *k;
|
1063 | 1064 |
|
| 1065 | + /* |
| 1066 | + * We handle two cases: the sub_pathkey key can be either an exact |
| 1067 | + * match for a targetlist entry, or a RelabelType of a targetlist |
| 1068 | + * entry. (The latter case is worth extra code because it arises |
| 1069 | + * frequently in connection with varchar fields.) |
| 1070 | + */ |
| 1071 | + if (IsA(sub_key, RelabelType)) |
| 1072 | + rtarg = ((RelabelType *) sub_key)->arg; |
| 1073 | + else |
| 1074 | + rtarg = NULL; |
| 1075 | + |
1064 | 1076 | foreach(k, sub_tlist)
|
1065 | 1077 | {
|
1066 | 1078 | TargetEntry *tle = (TargetEntry *) lfirst(k);
|
| 1079 | + Node *outer_expr; |
| 1080 | + PathKeyItem *outer_item; |
| 1081 | + int score; |
1067 | 1082 |
|
1068 |
| - if (!tle->resjunk && |
1069 |
| - equal(tle->expr, sub_key)) |
| 1083 | + /* resjunk items aren't visible to outer query */ |
| 1084 | + if (tle->resjunk) |
| 1085 | + continue; |
| 1086 | + |
| 1087 | + if (equal(tle->expr, sub_key)) |
1070 | 1088 | {
|
1071 |
| - /* Found a representation for this sub_key */ |
1072 |
| - Var *outer_var; |
1073 |
| - PathKeyItem *outer_item; |
1074 |
| - int score; |
1075 |
| - |
1076 |
| - outer_var = makeVar(rel->relid, |
1077 |
| - tle->resno, |
1078 |
| - exprType((Node *) tle->expr), |
1079 |
| - exprTypmod((Node *) tle->expr), |
1080 |
| - 0); |
1081 |
| - outer_item = makePathKeyItem((Node *) outer_var, |
1082 |
| - sub_item->sortop, |
1083 |
| - true); |
1084 |
| - /* score = # of mergejoin peers */ |
1085 |
| - score = count_canonical_peers(root, outer_item); |
1086 |
| - /* +1 if it matches the proper query_pathkeys item */ |
1087 |
| - if (retvallen < outer_query_keys && |
1088 |
| - list_member(list_nth(root->query_pathkeys, retvallen), outer_item)) |
1089 |
| - score++; |
1090 |
| - if (score > best_score) |
1091 |
| - { |
1092 |
| - best_item = outer_item; |
1093 |
| - best_score = score; |
1094 |
| - } |
| 1089 | + /* Exact match */ |
| 1090 | + outer_expr = (Node *) |
| 1091 | + makeVar(rel->relid, |
| 1092 | + tle->resno, |
| 1093 | + exprType((Node *) tle->expr), |
| 1094 | + exprTypmod((Node *) tle->expr), |
| 1095 | + 0); |
| 1096 | + } |
| 1097 | + else if (rtarg && equal(tle->expr, rtarg)) |
| 1098 | + { |
| 1099 | + /* Match after discarding RelabelType */ |
| 1100 | + outer_expr = (Node *) |
| 1101 | + makeVar(rel->relid, |
| 1102 | + tle->resno, |
| 1103 | + exprType((Node *) tle->expr), |
| 1104 | + exprTypmod((Node *) tle->expr), |
| 1105 | + 0); |
| 1106 | + outer_expr = (Node *) |
| 1107 | + makeRelabelType((Expr *) outer_expr, |
| 1108 | + ((RelabelType *) sub_key)->resulttype, |
| 1109 | + ((RelabelType *) sub_key)->resulttypmod, |
| 1110 | + ((RelabelType *) sub_key)->relabelformat); |
| 1111 | + } |
| 1112 | + else |
| 1113 | + continue; |
| 1114 | + |
| 1115 | + /* Found a representation for this sub_key */ |
| 1116 | + outer_item = makePathKeyItem(outer_expr, |
| 1117 | + sub_item->sortop, |
| 1118 | + true); |
| 1119 | + /* score = # of mergejoin peers */ |
| 1120 | + score = count_canonical_peers(root, outer_item); |
| 1121 | + /* +1 if it matches the proper query_pathkeys item */ |
| 1122 | + if (retvallen < outer_query_keys && |
| 1123 | + list_member(list_nth(root->query_pathkeys, retvallen), outer_item)) |
| 1124 | + score++; |
| 1125 | + if (score > best_score) |
| 1126 | + { |
| 1127 | + best_item = outer_item; |
| 1128 | + best_score = score; |
1095 | 1129 | }
|
1096 | 1130 | }
|
1097 | 1131 | }
|
|
0 commit comments