Skip to content

Commit 144b0ae

Browse files
committed
Teach convert_subquery_pathkeys() to handle the case where the
subquery's pathkey is a RelabelType applied to something that appears in the subquery's output; for example where the subquery returns a varchar Var and the sort order is shown as that Var coerced to text. This comes up because varchar doesn't have its own sort operator. Per example from Peter Hardman.
1 parent 4e1bdca commit 144b0ae

File tree

1 file changed

+61
-27
lines changed

1 file changed

+61
-27
lines changed

src/backend/optimizer/path/pathkeys.c

Lines changed: 61 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
* Portions Copyright (c) 1994, Regents of the University of California
1212
*
1313
* 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 $
1515
*
1616
*-------------------------------------------------------------------------
1717
*/
@@ -1059,39 +1059,73 @@ convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel,
10591059
{
10601060
PathKeyItem *sub_item = (PathKeyItem *) lfirst(j);
10611061
Node *sub_key = sub_item->key;
1062+
Expr *rtarg;
10621063
ListCell *k;
10631064

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+
10641076
foreach(k, sub_tlist)
10651077
{
10661078
TargetEntry *tle = (TargetEntry *) lfirst(k);
1079+
Node *outer_expr;
1080+
PathKeyItem *outer_item;
1081+
int score;
10671082

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))
10701088
{
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;
10951129
}
10961130
}
10971131
}

0 commit comments

Comments
 (0)