summaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_target.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser/parse_target.c')
-rw-r--r--src/backend/parser/parse_target.c31
1 files changed, 27 insertions, 4 deletions
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);