aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2007-11-08 19:25:37 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2007-11-08 19:25:37 +0000
commit1be0601681197fe79a2d2d403c518e7aeff1788a (patch)
tree6d686123b9ca4e5dc70efa9dba364a558ddaa307
parentf1528b5154ed68ec37735e7125732a96aa1758e1 (diff)
downloadpostgresql-1be0601681197fe79a2d2d403c518e7aeff1788a.tar.gz
postgresql-1be0601681197fe79a2d2d403c518e7aeff1788a.zip
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.
-rw-r--r--src/backend/optimizer/path/pathkeys.c13
-rw-r--r--src/backend/optimizer/plan/createplan.c27
-rw-r--r--src/backend/optimizer/util/tlist.c30
-rw-r--r--src/include/optimizer/tlist.h3
4 files changed, 50 insertions, 23 deletions
diff --git a/src/backend/optimizer/path/pathkeys.c b/src/backend/optimizer/path/pathkeys.c
index 2ad31203697..f96d7bb5554 100644
--- a/src/backend/optimizer/path/pathkeys.c
+++ b/src/backend/optimizer/path/pathkeys.c
@@ -11,7 +11,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* 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 &&
!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))
expr = (Expr *) ((RelabelType *) expr)->arg;
- expr = (Expr *) makeRelabelType(expr,
- opcintype,
- -1,
- COERCE_DONTCARE);
+ if (exprType((Node *) expr) != opcintype)
+ expr = (Expr *) makeRelabelType(expr,
+ opcintype,
+ -1,
+ COERCE_DONTCARE);
}
/* Now find or create a matching EquivalenceClass */
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index fb9b437174f..becb8255e87 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -10,7 +10,7 @@
*
*
* 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
* 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
* 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
@@ -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
- * of the tlist entry. This is needed for binary-compatible
- * cases (cf. make_pathkey_from_sortinfo).
+ * of the tlist entry, or vice versa. This is needed for
+ * 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;
-
- tle = tlist_member((Node *) rtarg, tlist);
- if (tle)
- {
- pk_datatype = em->em_datatype;
- break; /* found expr already in tlist */
- }
+ pk_datatype = em->em_datatype;
+ break; /* found expr already in tlist */
}
}
if (!tle)
{
- /* No matching Var; look for a computable expression */
+ /* No matching tlist item; look for a computable expression */
Expr *sortexpr = NULL;
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);
foreach(k, exprvars)
{
- if (!tlist_member(lfirst(k), tlist))
+ if (!tlist_member_ignore_relabel(lfirst(k), tlist))
break;
}
list_free(exprvars);
diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c
index 1e507235c53..e58fe7dc7f1 100644
--- a/src/backend/optimizer/util/tlist.c
+++ b/src/backend/optimizer/util/tlist.c
@@ -8,7 +8,7 @@
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
@@ -45,6 +45,34 @@ tlist_member(Node *node, List *targetlist)
}
/*
+ * 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
* Create a target list that only contains unique variables.
*
diff --git a/src/include/optimizer/tlist.h b/src/include/optimizer/tlist.h
index 31156ebcbcc..bb127cbce2b 100644
--- a/src/include/optimizer/tlist.h
+++ b/src/include/optimizer/tlist.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* 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_ignore_relabel(Node *node, List *targetlist);
extern List *flatten_tlist(List *tlist);
extern List *add_to_flat_tlist(List *tlist, List *vars);