Skip to content

Commit b23c9fa

Browse files
committed
Clean up a few failures to set collation fields in expression nodes.
I'm not sure these have any non-cosmetic implications, but I'm not sure they don't, either. In particular, ensure the CaseTestExpr generated by transformAssignmentIndirection to represent the base target column carries the correct collation, because parse_collate.c won't fix that. Tweak lsyscache.c API so that we can get the appropriate collation without an extra syscache lookup.
1 parent 92f4786 commit b23c9fa

File tree

9 files changed

+49
-44
lines changed

9 files changed

+49
-44
lines changed

src/backend/optimizer/path/pathkeys.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -603,8 +603,7 @@ find_indexkey_var(PlannerInfo *root, RelOptInfo *rel, AttrNumber varattno)
603603

604604
relid = rel->relid;
605605
reloid = getrelid(relid, root->parse->rtable);
606-
get_atttypetypmod(reloid, varattno, &vartypeid, &type_mod);
607-
varcollid = get_attcollation(reloid, varattno);
606+
get_atttypetypmodcoll(reloid, varattno, &vartypeid, &type_mod, &varcollid);
608607

609608
return makeVar(relid, varattno, vartypeid, type_mod, varcollid, 0);
610609
}

src/backend/optimizer/plan/createplan.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2652,6 +2652,8 @@ get_switched_clauses(List *clauses, Relids outerrelids)
26522652
temp->opfuncid = InvalidOid;
26532653
temp->opresulttype = clause->opresulttype;
26542654
temp->opretset = clause->opretset;
2655+
temp->opcollid = clause->opcollid;
2656+
temp->inputcollid = clause->inputcollid;
26552657
temp->args = list_copy(clause->args);
26562658
temp->location = clause->location;
26572659
/* Commute it --- note this modifies the temp node in-place. */

src/backend/optimizer/util/clauses.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1816,7 +1816,7 @@ CommuteOpExpr(OpExpr *clause)
18161816
*/
18171817
clause->opno = opoid;
18181818
clause->opfuncid = InvalidOid;
1819-
/* opresulttype and opretset are assumed not to change */
1819+
/* opresulttype, opretset, opcollid, inputcollid need not change */
18201820

18211821
temp = linitial(clause->args);
18221822
linitial(clause->args) = lsecond(clause->args);

src/backend/optimizer/util/predtest.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -906,6 +906,8 @@ arrayconst_startup_fn(Node *clause, PredIterInfo info)
906906
state->opexpr.opfuncid = saop->opfuncid;
907907
state->opexpr.opresulttype = BOOLOID;
908908
state->opexpr.opretset = false;
909+
state->opexpr.opcollid = InvalidOid;
910+
state->opexpr.inputcollid = saop->inputcollid;
909911
state->opexpr.args = list_copy(saop->args);
910912

911913
/* Set up a dummy Const node to hold the per-element values */
@@ -972,6 +974,8 @@ arrayexpr_startup_fn(Node *clause, PredIterInfo info)
972974
state->opexpr.opfuncid = saop->opfuncid;
973975
state->opexpr.opresulttype = BOOLOID;
974976
state->opexpr.opretset = false;
977+
state->opexpr.opcollid = InvalidOid;
978+
state->opexpr.inputcollid = saop->inputcollid;
975979
state->opexpr.args = list_copy(saop->args);
976980

977981
/* Initialize iteration variable to first member of ArrayExpr */

src/backend/parser/parse_coerce.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -796,6 +796,7 @@ build_coercion_expression(Node *node,
796796
* one argument.
797797
*/
798798
acoerce->resulttypmod = (nargs >= 2) ? targetTypMod : -1;
799+
/* resultcollid will be set by parse_collate.c */
799800
acoerce->isExplicit = isExplicit;
800801
acoerce->coerceformat = cformat;
801802
acoerce->location = location;
@@ -811,6 +812,7 @@ build_coercion_expression(Node *node,
811812

812813
iocoerce->arg = (Expr *) node;
813814
iocoerce->resulttype = targetTypeId;
815+
/* resultcollid will be set by parse_collate.c */
814816
iocoerce->coerceformat = cformat;
815817
iocoerce->location = location;
816818

src/backend/parser/parse_target.c

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ static Node *transformAssignmentIndirection(ParseState *pstate,
4040
bool targetIsArray,
4141
Oid targetTypeId,
4242
int32 targetTypMod,
43+
Oid targetCollation,
4344
ListCell *indirection,
4445
Node *rhs,
4546
int location);
@@ -48,6 +49,7 @@ static Node *transformAssignmentSubscripts(ParseState *pstate,
4849
const char *targetName,
4950
Oid targetTypeId,
5051
int32 targetTypMod,
52+
Oid targetCollation,
5153
List *subscripts,
5254
bool isSlice,
5355
ListCell *next_indirection,
@@ -455,6 +457,7 @@ transformAssignedExpr(ParseState *pstate,
455457
false,
456458
attrtype,
457459
attrtypmod,
460+
attrcollation,
458461
list_head(indirection),
459462
(Node *) expr,
460463
location);
@@ -548,8 +551,9 @@ updateTargetListEntry(ParseState *pstate,
548551
* targetIsArray is true if we're subscripting it. These are just for
549552
* error reporting.
550553
*
551-
* targetTypeId and targetTypMod indicate the datatype of the object to
552-
* be assigned to (initially the target column, later some subobject).
554+
* targetTypeId, targetTypMod, targetCollation indicate the datatype and
555+
* collation of the object to be assigned to (initially the target column,
556+
* later some subobject).
553557
*
554558
* indirection is the sublist remaining to process. When it's NULL, we're
555559
* done recursing and can just coerce and return the RHS.
@@ -569,6 +573,7 @@ transformAssignmentIndirection(ParseState *pstate,
569573
bool targetIsArray,
570574
Oid targetTypeId,
571575
int32 targetTypMod,
576+
Oid targetCollation,
572577
ListCell *indirection,
573578
Node *rhs,
574579
int location)
@@ -585,6 +590,7 @@ transformAssignmentIndirection(ParseState *pstate,
585590

586591
ctest->typeId = targetTypeId;
587592
ctest->typeMod = targetTypMod;
593+
ctest->collation = targetCollation;
588594
basenode = (Node *) ctest;
589595
}
590596

@@ -617,6 +623,7 @@ transformAssignmentIndirection(ParseState *pstate,
617623
AttrNumber attnum;
618624
Oid fieldTypeId;
619625
int32 fieldTypMod;
626+
Oid fieldCollation;
620627

621628
Assert(IsA(n, String));
622629

@@ -629,6 +636,7 @@ transformAssignmentIndirection(ParseState *pstate,
629636
targetName,
630637
targetTypeId,
631638
targetTypMod,
639+
targetCollation,
632640
subscripts,
633641
isSlice,
634642
i,
@@ -662,8 +670,8 @@ transformAssignmentIndirection(ParseState *pstate,
662670
strVal(n)),
663671
parser_errposition(pstate, location)));
664672

665-
get_atttypetypmod(typrelid, attnum,
666-
&fieldTypeId, &fieldTypMod);
673+
get_atttypetypmodcoll(typrelid, attnum,
674+
&fieldTypeId, &fieldTypMod, &fieldCollation);
667675

668676
/* recurse to create appropriate RHS for field assign */
669677
rhs = transformAssignmentIndirection(pstate,
@@ -672,6 +680,7 @@ transformAssignmentIndirection(ParseState *pstate,
672680
false,
673681
fieldTypeId,
674682
fieldTypMod,
683+
fieldCollation,
675684
lnext(i),
676685
rhs,
677686
location);
@@ -696,6 +705,7 @@ transformAssignmentIndirection(ParseState *pstate,
696705
targetName,
697706
targetTypeId,
698707
targetTypMod,
708+
targetCollation,
699709
subscripts,
700710
isSlice,
701711
NULL,
@@ -747,6 +757,7 @@ transformAssignmentSubscripts(ParseState *pstate,
747757
const char *targetName,
748758
Oid targetTypeId,
749759
int32 targetTypMod,
760+
Oid targetCollation,
750761
List *subscripts,
751762
bool isSlice,
752763
ListCell *next_indirection,
@@ -758,6 +769,7 @@ transformAssignmentSubscripts(ParseState *pstate,
758769
int32 arrayTypMod;
759770
Oid elementTypeId;
760771
Oid typeNeeded;
772+
Oid collationNeeded;
761773

762774
Assert(subscripts != NIL);
763775

@@ -769,13 +781,24 @@ transformAssignmentSubscripts(ParseState *pstate,
769781
/* Identify type that RHS must provide */
770782
typeNeeded = isSlice ? arrayType : elementTypeId;
771783

784+
/*
785+
* Array normally has same collation as elements, but there's an
786+
* exception: we might be subscripting a domain over an array type.
787+
* In that case use collation of the base type.
788+
*/
789+
if (arrayType == targetTypeId)
790+
collationNeeded = targetCollation;
791+
else
792+
collationNeeded = get_typcollation(arrayType);
793+
772794
/* recurse to create appropriate RHS for array assign */
773795
rhs = transformAssignmentIndirection(pstate,
774796
NULL,
775797
targetName,
776798
true,
777799
typeNeeded,
778800
arrayTypMod,
801+
collationNeeded,
779802
next_indirection,
780803
rhs,
781804
location);

src/backend/utils/adt/ruleutils.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -912,12 +912,14 @@ pg_get_indexdef_worker(Oid indexrelid, int colno,
912912
{
913913
/* Simple index column */
914914
char *attname;
915+
int32 keycoltypmod;
915916

916917
attname = get_relid_attribute_name(indrelid, attnum);
917918
if (!colno || colno == keyno + 1)
918919
appendStringInfoString(&buf, quote_identifier(attname));
919-
keycoltype = get_atttype(indrelid, attnum);
920-
keycolcollation = get_attcollation(indrelid, attnum);
920+
get_atttypetypmodcoll(indrelid, attnum,
921+
&keycoltype, &keycoltypmod,
922+
&keycolcollation);
921923
}
922924
else
923925
{

src/backend/utils/cache/lsyscache.c

Lines changed: 6 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -904,44 +904,17 @@ get_atttypmod(Oid relid, AttrNumber attnum)
904904
}
905905

906906
/*
907-
* get_attcollation
907+
* get_atttypetypmodcoll
908908
*
909-
* Given the relation id and the attribute number,
910-
* return the "attcollation" field from the attribute relation.
911-
*/
912-
Oid
913-
get_attcollation(Oid relid, AttrNumber attnum)
914-
{
915-
HeapTuple tp;
916-
917-
tp = SearchSysCache2(ATTNUM,
918-
ObjectIdGetDatum(relid),
919-
Int16GetDatum(attnum));
920-
if (HeapTupleIsValid(tp))
921-
{
922-
Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
923-
Oid result;
924-
925-
result = att_tup->attcollation;
926-
ReleaseSysCache(tp);
927-
return result;
928-
}
929-
else
930-
return InvalidOid;
931-
}
932-
933-
/*
934-
* get_atttypetypmod
935-
*
936-
* A two-fer: given the relation id and the attribute number,
937-
* fetch both type OID and atttypmod in a single cache lookup.
909+
* A three-fer: given the relation id and the attribute number,
910+
* fetch atttypid, atttypmod, and attcollation in a single cache lookup.
938911
*
939912
* Unlike the otherwise-similar get_atttype/get_atttypmod, this routine
940913
* raises an error if it can't obtain the information.
941914
*/
942915
void
943-
get_atttypetypmod(Oid relid, AttrNumber attnum,
944-
Oid *typid, int32 *typmod)
916+
get_atttypetypmodcoll(Oid relid, AttrNumber attnum,
917+
Oid *typid, int32 *typmod, Oid *collid)
945918
{
946919
HeapTuple tp;
947920
Form_pg_attribute att_tup;
@@ -956,6 +929,7 @@ get_atttypetypmod(Oid relid, AttrNumber attnum,
956929

957930
*typid = att_tup->atttypid;
958931
*typmod = att_tup->atttypmod;
932+
*collid = att_tup->attcollation;
959933
ReleaseSysCache(tp);
960934
}
961935

src/include/utils/lsyscache.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,8 @@ extern char *get_relid_attribute_name(Oid relid, AttrNumber attnum);
6060
extern AttrNumber get_attnum(Oid relid, const char *attname);
6161
extern Oid get_atttype(Oid relid, AttrNumber attnum);
6262
extern int32 get_atttypmod(Oid relid, AttrNumber attnum);
63-
extern Oid get_attcollation(Oid relid, AttrNumber attnum);
64-
extern void get_atttypetypmod(Oid relid, AttrNumber attnum,
65-
Oid *typid, int32 *typmod);
63+
extern void get_atttypetypmodcoll(Oid relid, AttrNumber attnum,
64+
Oid *typid, int32 *typmod, Oid *collid);
6665
extern char *get_collation_name(Oid colloid);
6766
extern char *get_constraint_name(Oid conoid);
6867
extern Oid get_opclass_family(Oid opclass);

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