From b23c9fa9293c54a3829093d207be37a7b42cb630 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sat, 26 Mar 2011 14:25:48 -0400 Subject: 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. --- src/backend/parser/parse_target.c | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) (limited to 'src/backend/parser/parse_target.c') diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index 8e92b99b5b2..d53d1d9f008 100644 --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -40,6 +40,7 @@ static Node *transformAssignmentIndirection(ParseState *pstate, bool targetIsArray, Oid targetTypeId, int32 targetTypMod, + Oid targetCollation, ListCell *indirection, Node *rhs, int location); @@ -48,6 +49,7 @@ static Node *transformAssignmentSubscripts(ParseState *pstate, const char *targetName, Oid targetTypeId, int32 targetTypMod, + Oid targetCollation, List *subscripts, bool isSlice, ListCell *next_indirection, @@ -455,6 +457,7 @@ transformAssignedExpr(ParseState *pstate, false, attrtype, attrtypmod, + attrcollation, list_head(indirection), (Node *) expr, location); @@ -548,8 +551,9 @@ updateTargetListEntry(ParseState *pstate, * targetIsArray is true if we're subscripting it. These are just for * error reporting. * - * targetTypeId and targetTypMod indicate the datatype of the object to - * be assigned to (initially the target column, later some subobject). + * targetTypeId, targetTypMod, targetCollation indicate the datatype and + * collation of the object to be assigned to (initially the target column, + * later some subobject). * * indirection is the sublist remaining to process. When it's NULL, we're * done recursing and can just coerce and return the RHS. @@ -569,6 +573,7 @@ transformAssignmentIndirection(ParseState *pstate, bool targetIsArray, Oid targetTypeId, int32 targetTypMod, + Oid targetCollation, ListCell *indirection, Node *rhs, int location) @@ -585,6 +590,7 @@ transformAssignmentIndirection(ParseState *pstate, ctest->typeId = targetTypeId; ctest->typeMod = targetTypMod; + ctest->collation = targetCollation; basenode = (Node *) ctest; } @@ -617,6 +623,7 @@ transformAssignmentIndirection(ParseState *pstate, AttrNumber attnum; Oid fieldTypeId; int32 fieldTypMod; + Oid fieldCollation; Assert(IsA(n, String)); @@ -629,6 +636,7 @@ transformAssignmentIndirection(ParseState *pstate, targetName, targetTypeId, targetTypMod, + targetCollation, subscripts, isSlice, i, @@ -662,8 +670,8 @@ transformAssignmentIndirection(ParseState *pstate, strVal(n)), parser_errposition(pstate, location))); - get_atttypetypmod(typrelid, attnum, - &fieldTypeId, &fieldTypMod); + get_atttypetypmodcoll(typrelid, attnum, + &fieldTypeId, &fieldTypMod, &fieldCollation); /* recurse to create appropriate RHS for field assign */ rhs = transformAssignmentIndirection(pstate, @@ -672,6 +680,7 @@ transformAssignmentIndirection(ParseState *pstate, false, fieldTypeId, fieldTypMod, + fieldCollation, lnext(i), rhs, location); @@ -696,6 +705,7 @@ transformAssignmentIndirection(ParseState *pstate, targetName, targetTypeId, targetTypMod, + targetCollation, subscripts, isSlice, NULL, @@ -747,6 +757,7 @@ transformAssignmentSubscripts(ParseState *pstate, const char *targetName, Oid targetTypeId, int32 targetTypMod, + Oid targetCollation, List *subscripts, bool isSlice, ListCell *next_indirection, @@ -758,6 +769,7 @@ transformAssignmentSubscripts(ParseState *pstate, int32 arrayTypMod; Oid elementTypeId; Oid typeNeeded; + Oid collationNeeded; Assert(subscripts != NIL); @@ -769,6 +781,16 @@ transformAssignmentSubscripts(ParseState *pstate, /* Identify type that RHS must provide */ typeNeeded = isSlice ? arrayType : elementTypeId; + /* + * Array normally has same collation as elements, but there's an + * exception: we might be subscripting a domain over an array type. + * In that case use collation of the base type. + */ + if (arrayType == targetTypeId) + collationNeeded = targetCollation; + else + collationNeeded = get_typcollation(arrayType); + /* recurse to create appropriate RHS for array assign */ rhs = transformAssignmentIndirection(pstate, NULL, @@ -776,6 +798,7 @@ transformAssignmentSubscripts(ParseState *pstate, true, typeNeeded, arrayTypMod, + collationNeeded, next_indirection, rhs, location); -- cgit v1.2.3