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

Lines changed: 25 additions & 22 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.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

Lines changed: 19 additions & 1 deletion
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy