mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-09-28 01:21:49 +02:00
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.
This commit is contained in:
parent
92f4786fa9
commit
b23c9fa929
@ -603,8 +603,7 @@ find_indexkey_var(PlannerInfo *root, RelOptInfo *rel, AttrNumber varattno)
|
|||||||
|
|
||||||
relid = rel->relid;
|
relid = rel->relid;
|
||||||
reloid = getrelid(relid, root->parse->rtable);
|
reloid = getrelid(relid, root->parse->rtable);
|
||||||
get_atttypetypmod(reloid, varattno, &vartypeid, &type_mod);
|
get_atttypetypmodcoll(reloid, varattno, &vartypeid, &type_mod, &varcollid);
|
||||||
varcollid = get_attcollation(reloid, varattno);
|
|
||||||
|
|
||||||
return makeVar(relid, varattno, vartypeid, type_mod, varcollid, 0);
|
return makeVar(relid, varattno, vartypeid, type_mod, varcollid, 0);
|
||||||
}
|
}
|
||||||
|
@ -2652,6 +2652,8 @@ get_switched_clauses(List *clauses, Relids outerrelids)
|
|||||||
temp->opfuncid = InvalidOid;
|
temp->opfuncid = InvalidOid;
|
||||||
temp->opresulttype = clause->opresulttype;
|
temp->opresulttype = clause->opresulttype;
|
||||||
temp->opretset = clause->opretset;
|
temp->opretset = clause->opretset;
|
||||||
|
temp->opcollid = clause->opcollid;
|
||||||
|
temp->inputcollid = clause->inputcollid;
|
||||||
temp->args = list_copy(clause->args);
|
temp->args = list_copy(clause->args);
|
||||||
temp->location = clause->location;
|
temp->location = clause->location;
|
||||||
/* Commute it --- note this modifies the temp node in-place. */
|
/* Commute it --- note this modifies the temp node in-place. */
|
||||||
|
@ -1816,7 +1816,7 @@ CommuteOpExpr(OpExpr *clause)
|
|||||||
*/
|
*/
|
||||||
clause->opno = opoid;
|
clause->opno = opoid;
|
||||||
clause->opfuncid = InvalidOid;
|
clause->opfuncid = InvalidOid;
|
||||||
/* opresulttype and opretset are assumed not to change */
|
/* opresulttype, opretset, opcollid, inputcollid need not change */
|
||||||
|
|
||||||
temp = linitial(clause->args);
|
temp = linitial(clause->args);
|
||||||
linitial(clause->args) = lsecond(clause->args);
|
linitial(clause->args) = lsecond(clause->args);
|
||||||
|
@ -906,6 +906,8 @@ arrayconst_startup_fn(Node *clause, PredIterInfo info)
|
|||||||
state->opexpr.opfuncid = saop->opfuncid;
|
state->opexpr.opfuncid = saop->opfuncid;
|
||||||
state->opexpr.opresulttype = BOOLOID;
|
state->opexpr.opresulttype = BOOLOID;
|
||||||
state->opexpr.opretset = false;
|
state->opexpr.opretset = false;
|
||||||
|
state->opexpr.opcollid = InvalidOid;
|
||||||
|
state->opexpr.inputcollid = saop->inputcollid;
|
||||||
state->opexpr.args = list_copy(saop->args);
|
state->opexpr.args = list_copy(saop->args);
|
||||||
|
|
||||||
/* Set up a dummy Const node to hold the per-element values */
|
/* 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.opfuncid = saop->opfuncid;
|
||||||
state->opexpr.opresulttype = BOOLOID;
|
state->opexpr.opresulttype = BOOLOID;
|
||||||
state->opexpr.opretset = false;
|
state->opexpr.opretset = false;
|
||||||
|
state->opexpr.opcollid = InvalidOid;
|
||||||
|
state->opexpr.inputcollid = saop->inputcollid;
|
||||||
state->opexpr.args = list_copy(saop->args);
|
state->opexpr.args = list_copy(saop->args);
|
||||||
|
|
||||||
/* Initialize iteration variable to first member of ArrayExpr */
|
/* Initialize iteration variable to first member of ArrayExpr */
|
||||||
|
@ -796,6 +796,7 @@ build_coercion_expression(Node *node,
|
|||||||
* one argument.
|
* one argument.
|
||||||
*/
|
*/
|
||||||
acoerce->resulttypmod = (nargs >= 2) ? targetTypMod : -1;
|
acoerce->resulttypmod = (nargs >= 2) ? targetTypMod : -1;
|
||||||
|
/* resultcollid will be set by parse_collate.c */
|
||||||
acoerce->isExplicit = isExplicit;
|
acoerce->isExplicit = isExplicit;
|
||||||
acoerce->coerceformat = cformat;
|
acoerce->coerceformat = cformat;
|
||||||
acoerce->location = location;
|
acoerce->location = location;
|
||||||
@ -811,6 +812,7 @@ build_coercion_expression(Node *node,
|
|||||||
|
|
||||||
iocoerce->arg = (Expr *) node;
|
iocoerce->arg = (Expr *) node;
|
||||||
iocoerce->resulttype = targetTypeId;
|
iocoerce->resulttype = targetTypeId;
|
||||||
|
/* resultcollid will be set by parse_collate.c */
|
||||||
iocoerce->coerceformat = cformat;
|
iocoerce->coerceformat = cformat;
|
||||||
iocoerce->location = location;
|
iocoerce->location = location;
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ static Node *transformAssignmentIndirection(ParseState *pstate,
|
|||||||
bool targetIsArray,
|
bool targetIsArray,
|
||||||
Oid targetTypeId,
|
Oid targetTypeId,
|
||||||
int32 targetTypMod,
|
int32 targetTypMod,
|
||||||
|
Oid targetCollation,
|
||||||
ListCell *indirection,
|
ListCell *indirection,
|
||||||
Node *rhs,
|
Node *rhs,
|
||||||
int location);
|
int location);
|
||||||
@ -48,6 +49,7 @@ static Node *transformAssignmentSubscripts(ParseState *pstate,
|
|||||||
const char *targetName,
|
const char *targetName,
|
||||||
Oid targetTypeId,
|
Oid targetTypeId,
|
||||||
int32 targetTypMod,
|
int32 targetTypMod,
|
||||||
|
Oid targetCollation,
|
||||||
List *subscripts,
|
List *subscripts,
|
||||||
bool isSlice,
|
bool isSlice,
|
||||||
ListCell *next_indirection,
|
ListCell *next_indirection,
|
||||||
@ -455,6 +457,7 @@ transformAssignedExpr(ParseState *pstate,
|
|||||||
false,
|
false,
|
||||||
attrtype,
|
attrtype,
|
||||||
attrtypmod,
|
attrtypmod,
|
||||||
|
attrcollation,
|
||||||
list_head(indirection),
|
list_head(indirection),
|
||||||
(Node *) expr,
|
(Node *) expr,
|
||||||
location);
|
location);
|
||||||
@ -548,8 +551,9 @@ updateTargetListEntry(ParseState *pstate,
|
|||||||
* targetIsArray is true if we're subscripting it. These are just for
|
* targetIsArray is true if we're subscripting it. These are just for
|
||||||
* error reporting.
|
* error reporting.
|
||||||
*
|
*
|
||||||
* targetTypeId and targetTypMod indicate the datatype of the object to
|
* targetTypeId, targetTypMod, targetCollation indicate the datatype and
|
||||||
* be assigned to (initially the target column, later some subobject).
|
* 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
|
* indirection is the sublist remaining to process. When it's NULL, we're
|
||||||
* done recursing and can just coerce and return the RHS.
|
* done recursing and can just coerce and return the RHS.
|
||||||
@ -569,6 +573,7 @@ transformAssignmentIndirection(ParseState *pstate,
|
|||||||
bool targetIsArray,
|
bool targetIsArray,
|
||||||
Oid targetTypeId,
|
Oid targetTypeId,
|
||||||
int32 targetTypMod,
|
int32 targetTypMod,
|
||||||
|
Oid targetCollation,
|
||||||
ListCell *indirection,
|
ListCell *indirection,
|
||||||
Node *rhs,
|
Node *rhs,
|
||||||
int location)
|
int location)
|
||||||
@ -585,6 +590,7 @@ transformAssignmentIndirection(ParseState *pstate,
|
|||||||
|
|
||||||
ctest->typeId = targetTypeId;
|
ctest->typeId = targetTypeId;
|
||||||
ctest->typeMod = targetTypMod;
|
ctest->typeMod = targetTypMod;
|
||||||
|
ctest->collation = targetCollation;
|
||||||
basenode = (Node *) ctest;
|
basenode = (Node *) ctest;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -617,6 +623,7 @@ transformAssignmentIndirection(ParseState *pstate,
|
|||||||
AttrNumber attnum;
|
AttrNumber attnum;
|
||||||
Oid fieldTypeId;
|
Oid fieldTypeId;
|
||||||
int32 fieldTypMod;
|
int32 fieldTypMod;
|
||||||
|
Oid fieldCollation;
|
||||||
|
|
||||||
Assert(IsA(n, String));
|
Assert(IsA(n, String));
|
||||||
|
|
||||||
@ -629,6 +636,7 @@ transformAssignmentIndirection(ParseState *pstate,
|
|||||||
targetName,
|
targetName,
|
||||||
targetTypeId,
|
targetTypeId,
|
||||||
targetTypMod,
|
targetTypMod,
|
||||||
|
targetCollation,
|
||||||
subscripts,
|
subscripts,
|
||||||
isSlice,
|
isSlice,
|
||||||
i,
|
i,
|
||||||
@ -662,8 +670,8 @@ transformAssignmentIndirection(ParseState *pstate,
|
|||||||
strVal(n)),
|
strVal(n)),
|
||||||
parser_errposition(pstate, location)));
|
parser_errposition(pstate, location)));
|
||||||
|
|
||||||
get_atttypetypmod(typrelid, attnum,
|
get_atttypetypmodcoll(typrelid, attnum,
|
||||||
&fieldTypeId, &fieldTypMod);
|
&fieldTypeId, &fieldTypMod, &fieldCollation);
|
||||||
|
|
||||||
/* recurse to create appropriate RHS for field assign */
|
/* recurse to create appropriate RHS for field assign */
|
||||||
rhs = transformAssignmentIndirection(pstate,
|
rhs = transformAssignmentIndirection(pstate,
|
||||||
@ -672,6 +680,7 @@ transformAssignmentIndirection(ParseState *pstate,
|
|||||||
false,
|
false,
|
||||||
fieldTypeId,
|
fieldTypeId,
|
||||||
fieldTypMod,
|
fieldTypMod,
|
||||||
|
fieldCollation,
|
||||||
lnext(i),
|
lnext(i),
|
||||||
rhs,
|
rhs,
|
||||||
location);
|
location);
|
||||||
@ -696,6 +705,7 @@ transformAssignmentIndirection(ParseState *pstate,
|
|||||||
targetName,
|
targetName,
|
||||||
targetTypeId,
|
targetTypeId,
|
||||||
targetTypMod,
|
targetTypMod,
|
||||||
|
targetCollation,
|
||||||
subscripts,
|
subscripts,
|
||||||
isSlice,
|
isSlice,
|
||||||
NULL,
|
NULL,
|
||||||
@ -747,6 +757,7 @@ transformAssignmentSubscripts(ParseState *pstate,
|
|||||||
const char *targetName,
|
const char *targetName,
|
||||||
Oid targetTypeId,
|
Oid targetTypeId,
|
||||||
int32 targetTypMod,
|
int32 targetTypMod,
|
||||||
|
Oid targetCollation,
|
||||||
List *subscripts,
|
List *subscripts,
|
||||||
bool isSlice,
|
bool isSlice,
|
||||||
ListCell *next_indirection,
|
ListCell *next_indirection,
|
||||||
@ -758,6 +769,7 @@ transformAssignmentSubscripts(ParseState *pstate,
|
|||||||
int32 arrayTypMod;
|
int32 arrayTypMod;
|
||||||
Oid elementTypeId;
|
Oid elementTypeId;
|
||||||
Oid typeNeeded;
|
Oid typeNeeded;
|
||||||
|
Oid collationNeeded;
|
||||||
|
|
||||||
Assert(subscripts != NIL);
|
Assert(subscripts != NIL);
|
||||||
|
|
||||||
@ -769,6 +781,16 @@ transformAssignmentSubscripts(ParseState *pstate,
|
|||||||
/* Identify type that RHS must provide */
|
/* Identify type that RHS must provide */
|
||||||
typeNeeded = isSlice ? arrayType : elementTypeId;
|
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 */
|
/* recurse to create appropriate RHS for array assign */
|
||||||
rhs = transformAssignmentIndirection(pstate,
|
rhs = transformAssignmentIndirection(pstate,
|
||||||
NULL,
|
NULL,
|
||||||
@ -776,6 +798,7 @@ transformAssignmentSubscripts(ParseState *pstate,
|
|||||||
true,
|
true,
|
||||||
typeNeeded,
|
typeNeeded,
|
||||||
arrayTypMod,
|
arrayTypMod,
|
||||||
|
collationNeeded,
|
||||||
next_indirection,
|
next_indirection,
|
||||||
rhs,
|
rhs,
|
||||||
location);
|
location);
|
||||||
|
@ -912,12 +912,14 @@ pg_get_indexdef_worker(Oid indexrelid, int colno,
|
|||||||
{
|
{
|
||||||
/* Simple index column */
|
/* Simple index column */
|
||||||
char *attname;
|
char *attname;
|
||||||
|
int32 keycoltypmod;
|
||||||
|
|
||||||
attname = get_relid_attribute_name(indrelid, attnum);
|
attname = get_relid_attribute_name(indrelid, attnum);
|
||||||
if (!colno || colno == keyno + 1)
|
if (!colno || colno == keyno + 1)
|
||||||
appendStringInfoString(&buf, quote_identifier(attname));
|
appendStringInfoString(&buf, quote_identifier(attname));
|
||||||
keycoltype = get_atttype(indrelid, attnum);
|
get_atttypetypmodcoll(indrelid, attnum,
|
||||||
keycolcollation = get_attcollation(indrelid, attnum);
|
&keycoltype, &keycoltypmod,
|
||||||
|
&keycolcollation);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
38
src/backend/utils/cache/lsyscache.c
vendored
38
src/backend/utils/cache/lsyscache.c
vendored
@ -904,44 +904,17 @@ get_atttypmod(Oid relid, AttrNumber attnum)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get_attcollation
|
* get_atttypetypmodcoll
|
||||||
*
|
*
|
||||||
* Given the relation id and the attribute number,
|
* A three-fer: given the relation id and the attribute number,
|
||||||
* return the "attcollation" field from the attribute relation.
|
* fetch atttypid, atttypmod, and attcollation in a single cache lookup.
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*
|
*
|
||||||
* Unlike the otherwise-similar get_atttype/get_atttypmod, this routine
|
* Unlike the otherwise-similar get_atttype/get_atttypmod, this routine
|
||||||
* raises an error if it can't obtain the information.
|
* raises an error if it can't obtain the information.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
get_atttypetypmod(Oid relid, AttrNumber attnum,
|
get_atttypetypmodcoll(Oid relid, AttrNumber attnum,
|
||||||
Oid *typid, int32 *typmod)
|
Oid *typid, int32 *typmod, Oid *collid)
|
||||||
{
|
{
|
||||||
HeapTuple tp;
|
HeapTuple tp;
|
||||||
Form_pg_attribute att_tup;
|
Form_pg_attribute att_tup;
|
||||||
@ -956,6 +929,7 @@ get_atttypetypmod(Oid relid, AttrNumber attnum,
|
|||||||
|
|
||||||
*typid = att_tup->atttypid;
|
*typid = att_tup->atttypid;
|
||||||
*typmod = att_tup->atttypmod;
|
*typmod = att_tup->atttypmod;
|
||||||
|
*collid = att_tup->attcollation;
|
||||||
ReleaseSysCache(tp);
|
ReleaseSysCache(tp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,9 +60,8 @@ extern char *get_relid_attribute_name(Oid relid, AttrNumber attnum);
|
|||||||
extern AttrNumber get_attnum(Oid relid, const char *attname);
|
extern AttrNumber get_attnum(Oid relid, const char *attname);
|
||||||
extern Oid get_atttype(Oid relid, AttrNumber attnum);
|
extern Oid get_atttype(Oid relid, AttrNumber attnum);
|
||||||
extern int32 get_atttypmod(Oid relid, AttrNumber attnum);
|
extern int32 get_atttypmod(Oid relid, AttrNumber attnum);
|
||||||
extern Oid get_attcollation(Oid relid, AttrNumber attnum);
|
extern void get_atttypetypmodcoll(Oid relid, AttrNumber attnum,
|
||||||
extern void get_atttypetypmod(Oid relid, AttrNumber attnum,
|
Oid *typid, int32 *typmod, Oid *collid);
|
||||||
Oid *typid, int32 *typmod);
|
|
||||||
extern char *get_collation_name(Oid colloid);
|
extern char *get_collation_name(Oid colloid);
|
||||||
extern char *get_constraint_name(Oid conoid);
|
extern char *get_constraint_name(Oid conoid);
|
||||||
extern Oid get_opclass_family(Oid opclass);
|
extern Oid get_opclass_family(Oid opclass);
|
||||||
|
Loading…
Reference in New Issue
Block a user