Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 97ddfc9

Browse files
committed
Ensure that EquivalenceClasses generated from ORDER BY keys contain proper
RelabelType nodes when the sort key is binary-compatible with the sort operator rather than having exactly its input type. We did this correctly for index columns but not sort keys, leading to failure to notice that a varchar index matches an ORDER BY request. This requires a bit more work in make_sort_from_pathkeys, but not anyplace else that I can find. Per bug report and subsequent discussion.
1 parent 65bd783 commit 97ddfc9

File tree

2 files changed

+44
-23
lines changed

2 files changed

+44
-23
lines changed

src/backend/optimizer/path/pathkeys.c

+25-22
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.86 2007/10/27 05:45:43 tgl Exp $
14+
* $PostgreSQL: pgsql/src/backend/optimizer/path/pathkeys.c,v 1.87 2007/11/02 18:54:15 tgl Exp $
1515
*
1616
*-------------------------------------------------------------------------
1717
*/
@@ -277,6 +277,30 @@ make_pathkey_from_sortinfo(PlannerInfo *root,
277277
elog(ERROR, "could not find opfamilies for ordering operator %u",
278278
ordering_op);
279279

280+
/*
281+
* When dealing with binary-compatible opclasses, we have to ensure that
282+
* the exposed type of the expression tree matches the declared input
283+
* type of the opclass, except when that is a polymorphic type
284+
* (compare the behavior of parse_coerce.c). This ensures that we can
285+
* correctly match the indexkey or sortclause expression to other
286+
* expressions we find in the query, because arguments of ordinary
287+
* operator expressions will be cast that way. (We have to do this
288+
* for indexkeys because they are represented without any explicit
289+
* relabel in pg_index, and for sort clauses because the parser is
290+
* likewise cavalier about putting relabels on them.)
291+
*/
292+
if (exprType((Node *) expr) != opcintype &&
293+
!IsPolymorphicType(opcintype))
294+
{
295+
/* Strip any existing RelabelType, and add a new one */
296+
while (expr && IsA(expr, RelabelType))
297+
expr = (Expr *) ((RelabelType *) expr)->arg;
298+
expr = (Expr *) makeRelabelType(expr,
299+
opcintype,
300+
-1,
301+
COERCE_DONTCARE);
302+
}
303+
280304
/* Now find or create a matching EquivalenceClass */
281305
eclass = get_eclass_for_sort_expr(root, expr, opcintype, opfamilies);
282306

@@ -495,27 +519,6 @@ build_index_pathkeys(PlannerInfo *root,
495519
indexprs_item = lnext(indexprs_item);
496520
}
497521

498-
/*
499-
* When dealing with binary-compatible indexes, we have to ensure that
500-
* the exposed type of the expression tree matches the declared input
501-
* type of the opclass, except when that is a polymorphic type
502-
* (compare the behavior of parse_coerce.c). This ensures that we can
503-
* correctly match the indexkey expression to expressions we find in
504-
* the query, because arguments of operators that could match the
505-
* index will be cast likewise.
506-
*/
507-
if (exprType((Node *) indexkey) != index->opcintype[i] &&
508-
!IsPolymorphicType(index->opcintype[i]))
509-
{
510-
/* Strip any existing RelabelType, and add a new one */
511-
while (indexkey && IsA(indexkey, RelabelType))
512-
indexkey = (Expr *) ((RelabelType *) indexkey)->arg;
513-
indexkey = (Expr *) makeRelabelType(indexkey,
514-
index->opcintype[i],
515-
-1,
516-
COERCE_DONTCARE);
517-
}
518-
519522
/* OK, make a canonical pathkey for this sort key */
520523
cpathkey = make_pathkey_from_sortinfo(root,
521524
indexkey,

src/backend/optimizer/plan/createplan.c

+19-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
*
1212
* IDENTIFICATION
13-
* $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.231 2007/05/21 17:57:34 tgl Exp $
13+
* $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.232 2007/11/02 18:54:15 tgl Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -2756,12 +2756,30 @@ make_sort_from_pathkeys(PlannerInfo *root, Plan *lefttree, List *pathkeys,
27562756

27572757
if (em->em_is_const || em->em_is_child)
27582758
continue;
2759+
27592760
tle = tlist_member((Node *) em->em_expr, tlist);
27602761
if (tle)
27612762
{
27622763
pk_datatype = em->em_datatype;
27632764
break; /* found expr already in tlist */
27642765
}
2766+
2767+
/*
2768+
* We can also use it if the pathkey expression is a relabel
2769+
* of the tlist entry. This is needed for binary-compatible
2770+
* cases (cf. make_pathkey_from_sortinfo).
2771+
*/
2772+
if (IsA(em->em_expr, RelabelType))
2773+
{
2774+
Expr *rtarg = ((RelabelType *) em->em_expr)->arg;
2775+
2776+
tle = tlist_member((Node *) rtarg, tlist);
2777+
if (tle)
2778+
{
2779+
pk_datatype = em->em_datatype;
2780+
break; /* found expr already in tlist */
2781+
}
2782+
}
27652783
}
27662784
if (!tle)
27672785
{

0 commit comments

Comments
 (0)