mirror of
https://github.com/postgres/postgres.git
synced 2025-05-24 00:03:23 -04:00
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.
This commit is contained in:
parent
f1528b5154
commit
1be0601681
@ -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,
|
|||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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,
|
|||||||
/*
|
/*
|
||||||
* 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,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* 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,
|
|||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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)
|
|||||||
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 @@
|
|||||||
* 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 @@
|
|||||||
|
|
||||||
|
|
||||||
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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user