Commit 1be06016 authored by Tom Lane's avatar Tom Lane

Last week's patch for make_sort_from_pathkeys wasn't good enough: it has

to be able to discard top-level RelabelType nodes on *both* sides of the
equivalence-class-to-target-list comparison, since make_pathkey_from_sortinfo
might either add or remove a RelabelType.  Also fix the latter to do the
removal case cleanly.  Per example from Peter.
parent f1528b51
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/path/pathkeys.c,v 1.87 2007/11/02 18:54:15 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/path/pathkeys.c,v 1.88 2007/11/08 19:25:37 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -292,13 +292,14 @@ make_pathkey_from_sortinfo(PlannerInfo *root, ...@@ -292,13 +292,14 @@ make_pathkey_from_sortinfo(PlannerInfo *root,
if (exprType((Node *) expr) != opcintype && if (exprType((Node *) expr) != opcintype &&
!IsPolymorphicType(opcintype)) !IsPolymorphicType(opcintype))
{ {
/* Strip any existing RelabelType, and add a new one */ /* Strip any existing RelabelType, and add a new one if needed */
while (expr && IsA(expr, RelabelType)) while (expr && IsA(expr, RelabelType))
expr = (Expr *) ((RelabelType *) expr)->arg; expr = (Expr *) ((RelabelType *) expr)->arg;
expr = (Expr *) makeRelabelType(expr, if (exprType((Node *) expr) != opcintype)
opcintype, expr = (Expr *) makeRelabelType(expr,
-1, opcintype,
COERCE_DONTCARE); -1,
COERCE_DONTCARE);
} }
/* Now find or create a matching EquivalenceClass */ /* Now find or create a matching EquivalenceClass */
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.232 2007/11/02 18:54:15 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.233 2007/11/08 19:25:37 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -2738,7 +2738,7 @@ make_sort_from_pathkeys(PlannerInfo *root, Plan *lefttree, List *pathkeys, ...@@ -2738,7 +2738,7 @@ make_sort_from_pathkeys(PlannerInfo *root, Plan *lefttree, List *pathkeys,
/* /*
* We can sort by any non-constant expression listed in the pathkey's * We can sort by any non-constant expression listed in the pathkey's
* EquivalenceClass. For now, we take the first one that corresponds * EquivalenceClass. For now, we take the first one that corresponds
* to an available Var in the tlist. If there isn't any, use the first * to an available item in the tlist. If there isn't any, use the first
* one that is an expression in the input's vars. (The non-const * one that is an expression in the input's vars. (The non-const
* restriction only matters if the EC is below_outer_join; but if it * restriction only matters if the EC is below_outer_join; but if it
* isn't, it won't contain consts anyway, else we'd have discarded * isn't, it won't contain consts anyway, else we'd have discarded
...@@ -2766,24 +2766,21 @@ make_sort_from_pathkeys(PlannerInfo *root, Plan *lefttree, List *pathkeys, ...@@ -2766,24 +2766,21 @@ make_sort_from_pathkeys(PlannerInfo *root, Plan *lefttree, List *pathkeys,
/* /*
* We can also use it if the pathkey expression is a relabel * We can also use it if the pathkey expression is a relabel
* of the tlist entry. This is needed for binary-compatible * of the tlist entry, or vice versa. This is needed for
* cases (cf. make_pathkey_from_sortinfo). * binary-compatible cases (cf. make_pathkey_from_sortinfo).
* We prefer an exact match, though, so we do the basic
* search first.
*/ */
if (IsA(em->em_expr, RelabelType)) tle = tlist_member_ignore_relabel((Node *) em->em_expr, tlist);
if (tle)
{ {
Expr *rtarg = ((RelabelType *) em->em_expr)->arg; pk_datatype = em->em_datatype;
break; /* found expr already in tlist */
tle = tlist_member((Node *) rtarg, tlist);
if (tle)
{
pk_datatype = em->em_datatype;
break; /* found expr already in tlist */
}
} }
} }
if (!tle) if (!tle)
{ {
/* No matching Var; look for a computable expression */ /* No matching tlist item; look for a computable expression */
Expr *sortexpr = NULL; Expr *sortexpr = NULL;
foreach(j, pathkey->pk_eclass->ec_members) foreach(j, pathkey->pk_eclass->ec_members)
...@@ -2798,7 +2795,7 @@ make_sort_from_pathkeys(PlannerInfo *root, Plan *lefttree, List *pathkeys, ...@@ -2798,7 +2795,7 @@ make_sort_from_pathkeys(PlannerInfo *root, Plan *lefttree, List *pathkeys,
exprvars = pull_var_clause((Node *) sortexpr, false); exprvars = pull_var_clause((Node *) sortexpr, false);
foreach(k, exprvars) foreach(k, exprvars)
{ {
if (!tlist_member(lfirst(k), tlist)) if (!tlist_member_ignore_relabel(lfirst(k), tlist))
break; break;
} }
list_free(exprvars); list_free(exprvars);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/util/tlist.c,v 1.74 2007/01/05 22:19:33 momjian Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/util/tlist.c,v 1.75 2007/11/08 19:25:37 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -44,6 +44,34 @@ tlist_member(Node *node, List *targetlist) ...@@ -44,6 +44,34 @@ tlist_member(Node *node, List *targetlist)
return NULL; return NULL;
} }
/*
* tlist_member_ignore_relabel
* Same as above, except that we ignore top-level RelabelType nodes
* while checking for a match. This is needed for some scenarios
* involving binary-compatible sort operations.
*/
TargetEntry *
tlist_member_ignore_relabel(Node *node, List *targetlist)
{
ListCell *temp;
while (node && IsA(node, RelabelType))
node = (Node *) ((RelabelType *) node)->arg;
foreach(temp, targetlist)
{
TargetEntry *tlentry = (TargetEntry *) lfirst(temp);
Expr *tlexpr = tlentry->expr;
while (tlexpr && IsA(tlexpr, RelabelType))
tlexpr = ((RelabelType *) tlexpr)->arg;
if (equal(node, tlexpr))
return tlentry;
}
return NULL;
}
/* /*
* flatten_tlist * flatten_tlist
* Create a target list that only contains unique variables. * Create a target list that only contains unique variables.
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/optimizer/tlist.h,v 1.45 2007/01/05 22:19:56 momjian Exp $ * $PostgreSQL: pgsql/src/include/optimizer/tlist.h,v 1.46 2007/11/08 19:25:37 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
extern TargetEntry *tlist_member(Node *node, List *targetlist); extern TargetEntry *tlist_member(Node *node, List *targetlist);
extern TargetEntry *tlist_member_ignore_relabel(Node *node, List *targetlist);
extern List *flatten_tlist(List *tlist); extern List *flatten_tlist(List *tlist);
extern List *add_to_flat_tlist(List *tlist, List *vars); extern List *add_to_flat_tlist(List *tlist, List *vars);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment