|
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 | +intscore; |
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 | | -intscore; |
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 | +elseif (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 | } |
|