summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane2011-03-26 18:25:48 +0000
committerTom Lane2011-03-26 18:25:48 +0000
commitb23c9fa9293c54a3829093d207be37a7b42cb630 (patch)
tree4bc1df3cf95ef9b75c9ac1f85ad57eed32db4889
parent92f4786fa9b730fd12cbfe973eb96addc6e98924 (diff)
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.
-rw-r--r--src/backend/optimizer/path/pathkeys.c3
-rw-r--r--src/backend/optimizer/plan/createplan.c2
-rw-r--r--src/backend/optimizer/util/clauses.c2
-rw-r--r--src/backend/optimizer/util/predtest.c4
-rw-r--r--src/backend/parser/parse_coerce.c2
-rw-r--r--src/backend/parser/parse_target.c31
-rw-r--r--src/backend/utils/adt/ruleutils.c6
-rw-r--r--src/backend/utils/cache/lsyscache.c38
-rw-r--r--src/include/utils/lsyscache.h5
9 files changed, 49 insertions, 44 deletions
diff --git a/src/backend/optimizer/path/pathkeys.c b/src/backend/optimizer/path/pathkeys.c
index 34c772356b6..47597a5d35b 100644
--- a/src/backend/optimizer/path/pathkeys.c
+++ b/src/backend/optimizer/path/pathkeys.c
@@ -603,8 +603,7 @@ find_indexkey_var(PlannerInfo *root, RelOptInfo *rel, AttrNumber varattno)
relid = rel->relid;
reloid = getrelid(relid, root->parse->rtable);
- get_atttypetypmod(reloid, varattno, &vartypeid, &type_mod);
- varcollid = get_attcollation(reloid, varattno);
+ get_atttypetypmodcoll(reloid, varattno, &vartypeid, &type_mod, &varcollid);
return makeVar(relid, varattno, vartypeid, type_mod, varcollid, 0);
}
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index bdd14f524db..f1308812515 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -2652,6 +2652,8 @@ get_switched_clauses(List *clauses, Relids outerrelids)
temp->opfuncid = InvalidOid;
temp->opresulttype = clause->opresulttype;
temp->opretset = clause->opretset;
+ temp->opcollid = clause->opcollid;
+ temp->inputcollid = clause->inputcollid;
temp->args = list_copy(clause->args);
temp->location = clause->location;
/* Commute it --- note this modifies the temp node in-place. */
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 1a63146e6f1..b1069259f9b 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -1816,7 +1816,7 @@ CommuteOpExpr(OpExpr *clause)
*/
clause->opno = opoid;
clause->opfuncid = InvalidOid;
- /* opresulttype and opretset are assumed not to change */
+ /* opresulttype, opretset, opcollid, inputcollid need not change */
temp = linitial(clause->args);
linitial(clause->args) = lsecond(clause->args);
diff --git a/src/backend/optimizer/util/predtest.c b/src/backend/optimizer/util/predtest.c
index 6a1f7291ba5..72fd3e4ca71 100644
--- a/src/backend/optimizer/util/predtest.c
+++ b/src/backend/optimizer/util/predtest.c
@@ -906,6 +906,8 @@ arrayconst_startup_fn(Node *clause, PredIterInfo info)
state->opexpr.opfuncid = saop->opfuncid;
state->opexpr.opresulttype = BOOLOID;
state->opexpr.opretset = false;
+ state->opexpr.opcollid = InvalidOid;
+ state->opexpr.inputcollid = saop->inputcollid;
state->opexpr.args = list_copy(saop->args);
/* Set up a dummy Const node to hold the per-element values */
@@ -972,6 +974,8 @@ arrayexpr_startup_fn(Node *clause, PredIterInfo info)
state->opexpr.opfuncid = saop->opfuncid;
state->opexpr.opresulttype = BOOLOID;
state->opexpr.opretset = false;
+ state->opexpr.opcollid = InvalidOid;
+ state->opexpr.inputcollid = saop->inputcollid;
state->opexpr.args = list_copy(saop->args);
/* Initialize iteration variable to first member of ArrayExpr */
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c
index cc03f9f48e6..dd3e748c9f6 100644
--- a/src/backend/parser/parse_coerce.c
+++ b/src/backend/parser/parse_coerce.c
@@ -796,6 +796,7 @@ build_coercion_expression(Node *node,
* one argument.
*/
acoerce->resulttypmod = (nargs >= 2) ? targetTypMod : -1;
+ /* resultcollid will be set by parse_collate.c */
acoerce->isExplicit = isExplicit;
acoerce->coerceformat = cformat;
acoerce->location = location;
@@ -811,6 +812,7 @@ build_coercion_expression(Node *node,
iocoerce->arg = (Expr *) node;
iocoerce->resulttype = targetTypeId;
+ /* resultcollid will be set by parse_collate.c */
iocoerce->coerceformat = cformat;
iocoerce->location = location;
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);
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 621f1eb24ae..326079a75ba 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -912,12 +912,14 @@ pg_get_indexdef_worker(Oid indexrelid, int colno,
{
/* Simple index column */
char *attname;
+ int32 keycoltypmod;
attname = get_relid_attribute_name(indrelid, attnum);
if (!colno || colno == keyno + 1)
appendStringInfoString(&buf, quote_identifier(attname));
- keycoltype = get_atttype(indrelid, attnum);
- keycolcollation = get_attcollation(indrelid, attnum);
+ get_atttypetypmodcoll(indrelid, attnum,
+ &keycoltype, &keycoltypmod,
+ &keycolcollation);
}
else
{
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index 6bcaf30ffe7..877e50d8737 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -904,44 +904,17 @@ get_atttypmod(Oid relid, AttrNumber attnum)
}
/*
- * get_attcollation
+ * get_atttypetypmodcoll
*
- * Given the relation id and the attribute number,
- * return the "attcollation" field from the attribute relation.
- */
-Oid
-get_attcollation(Oid relid, AttrNumber attnum)
-{
- HeapTuple tp;
-
- tp = SearchSysCache2(ATTNUM,
- ObjectIdGetDatum(relid),
- Int16GetDatum(attnum));
- if (HeapTupleIsValid(tp))
- {
- Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
- Oid result;
-
- result = att_tup->attcollation;
- ReleaseSysCache(tp);
- return result;
- }
- else
- return InvalidOid;
-}
-
-/*
- * get_atttypetypmod
- *
- * A two-fer: given the relation id and the attribute number,
- * fetch both type OID and atttypmod in a single cache lookup.
+ * A three-fer: given the relation id and the attribute number,
+ * fetch atttypid, atttypmod, and attcollation in a single cache lookup.
*
* Unlike the otherwise-similar get_atttype/get_atttypmod, this routine
* raises an error if it can't obtain the information.
*/
void
-get_atttypetypmod(Oid relid, AttrNumber attnum,
- Oid *typid, int32 *typmod)
+get_atttypetypmodcoll(Oid relid, AttrNumber attnum,
+ Oid *typid, int32 *typmod, Oid *collid)
{
HeapTuple tp;
Form_pg_attribute att_tup;
@@ -956,6 +929,7 @@ get_atttypetypmod(Oid relid, AttrNumber attnum,
*typid = att_tup->atttypid;
*typmod = att_tup->atttypmod;
+ *collid = att_tup->attcollation;
ReleaseSysCache(tp);
}
diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h
index 22dfd58f0aa..b6ceb26c8be 100644
--- a/src/include/utils/lsyscache.h
+++ b/src/include/utils/lsyscache.h
@@ -60,9 +60,8 @@ extern char *get_relid_attribute_name(Oid relid, AttrNumber attnum);
extern AttrNumber get_attnum(Oid relid, const char *attname);
extern Oid get_atttype(Oid relid, AttrNumber attnum);
extern int32 get_atttypmod(Oid relid, AttrNumber attnum);
-extern Oid get_attcollation(Oid relid, AttrNumber attnum);
-extern void get_atttypetypmod(Oid relid, AttrNumber attnum,
- Oid *typid, int32 *typmod);
+extern void get_atttypetypmodcoll(Oid relid, AttrNumber attnum,
+ Oid *typid, int32 *typmod, Oid *collid);
extern char *get_collation_name(Oid colloid);
extern char *get_constraint_name(Oid conoid);
extern Oid get_opclass_family(Oid opclass);