* the datatype. However we do need a type dependency if there is no such
* indirect dependency, as for example in Const and CoerceToDomain nodes.
*
- * Similarly, we don't need to create dependencies on collations except where
- * the collation is being freshly introduced to the expression.
+ * Collations are handled primarily by recording the inputcollid's of node
+ * types that have them, as those are the ones that are semantically
+ * significant during expression evaluation. We also record the collation of
+ * CollateExpr nodes, since those will be needed to print such nodes even if
+ * they don't really affect semantics. Collations of leaf nodes such as Vars
+ * can be ignored on the grounds that if they're not default, they came from
+ * the referenced object (e.g., a table column), so the dependency on that
+ * object is enough. (Note: in a post-const-folding expression tree, a
+ * CollateExpr's collation could have been absorbed into a Const or
+ * RelabelType node. While ruleutils.c prints such collations for clarity,
+ * we may ignore them here as they have no semantic effect.)
*/
static bool
find_expr_references_walker(Node *node,
/* If it's a plain relation, reference this column */
add_object_address(OCLASS_CLASS, rte->relid, var->varattno,
context->addrs);
-
- /* Top-level collation if valid */
- if (OidIsValid(var->varcollid))
- add_object_address(OCLASS_COLLATION, var->varcollid, 0,
- context->addrs);
- /* Otherwise, it may be a type with internal collations */
- else if (var->vartype >= FirstNormalObjectId)
- {
- List *collations;
- ListCell *lc;
-
- collations = GetTypeCollations(var->vartype);
-
- foreach(lc, collations)
- {
- Oid coll = lfirst_oid(lc);
-
- if (OidIsValid(coll))
- add_object_address(OCLASS_COLLATION,
- lfirst_oid(lc), 0,
- context->addrs);
- }
- }
}
/*
add_object_address(OCLASS_TYPE, con->consttype, 0,
context->addrs);
- /*
- * We must also depend on the constant's collation: it could be
- * different from the datatype's, if a CollateExpr was const-folded to
- * a simple constant.
- */
- if (OidIsValid(con->constcollid))
- add_object_address(OCLASS_COLLATION, con->constcollid, 0,
- context->addrs);
-
/*
* If it's a regclass or similar literal referring to an existing
* object, add a reference to that object. (Currently, only the
/* A parameter must depend on the parameter's datatype */
add_object_address(OCLASS_TYPE, param->paramtype, 0,
context->addrs);
- /* and its collation, just as for Consts */
- if (OidIsValid(param->paramcollid))
- add_object_address(OCLASS_COLLATION, param->paramcollid, 0,
- context->addrs);
}
else if (IsA(node, FuncExpr))
{
add_object_address(OCLASS_PROC, funcexpr->funcid, 0,
context->addrs);
+ if (OidIsValid(funcexpr->inputcollid))
+ add_object_address(OCLASS_COLLATION, funcexpr->inputcollid, 0,
+ context->addrs);
/* fall through to examine arguments */
}
else if (IsA(node, OpExpr))
add_object_address(OCLASS_OPERATOR, opexpr->opno, 0,
context->addrs);
+ if (OidIsValid(opexpr->inputcollid))
+ add_object_address(OCLASS_COLLATION, opexpr->inputcollid, 0,
+ context->addrs);
/* fall through to examine arguments */
}
else if (IsA(node, DistinctExpr))
add_object_address(OCLASS_OPERATOR, distinctexpr->opno, 0,
context->addrs);
+ if (OidIsValid(distinctexpr->inputcollid))
+ add_object_address(OCLASS_COLLATION, distinctexpr->inputcollid, 0,
+ context->addrs);
/* fall through to examine arguments */
}
else if (IsA(node, NullIfExpr))
add_object_address(OCLASS_OPERATOR, nullifexpr->opno, 0,
context->addrs);
+ if (OidIsValid(nullifexpr->inputcollid))
+ add_object_address(OCLASS_COLLATION, nullifexpr->inputcollid, 0,
+ context->addrs);
/* fall through to examine arguments */
}
else if (IsA(node, ScalarArrayOpExpr))
add_object_address(OCLASS_OPERATOR, opexpr->opno, 0,
context->addrs);
+ if (OidIsValid(opexpr->inputcollid))
+ add_object_address(OCLASS_COLLATION, opexpr->inputcollid, 0,
+ context->addrs);
/* fall through to examine arguments */
}
else if (IsA(node, Aggref))
add_object_address(OCLASS_PROC, aggref->aggfnoid, 0,
context->addrs);
+ if (OidIsValid(aggref->inputcollid))
+ add_object_address(OCLASS_COLLATION, aggref->inputcollid, 0,
+ context->addrs);
/* fall through to examine arguments */
}
else if (IsA(node, WindowFunc))
add_object_address(OCLASS_PROC, wfunc->winfnoid, 0,
context->addrs);
+ if (OidIsValid(wfunc->inputcollid))
+ add_object_address(OCLASS_COLLATION, wfunc->inputcollid, 0,
+ context->addrs);
/* fall through to examine arguments */
}
else if (IsA(node, SubscriptingRef))
else
add_object_address(OCLASS_TYPE, fselect->resulttype, 0,
context->addrs);
- /* the collation might not be referenced anywhere else, either */
- if (OidIsValid(fselect->resultcollid))
- add_object_address(OCLASS_COLLATION, fselect->resultcollid, 0,
- context->addrs);
}
else if (IsA(node, FieldStore))
{
/* since there is no function dependency, need to depend on type */
add_object_address(OCLASS_TYPE, relab->resulttype, 0,
context->addrs);
- /* the collation might not be referenced anywhere else, either */
- if (OidIsValid(relab->resultcollid))
- add_object_address(OCLASS_COLLATION, relab->resultcollid, 0,
- context->addrs);
}
else if (IsA(node, CoerceViaIO))
{
/* since there is no exposed function, need to depend on type */
add_object_address(OCLASS_TYPE, iocoerce->resulttype, 0,
context->addrs);
- /* the collation might not be referenced anywhere else, either */
- if (OidIsValid(iocoerce->resultcollid))
- add_object_address(OCLASS_COLLATION, iocoerce->resultcollid, 0,
- context->addrs);
}
else if (IsA(node, ArrayCoerceExpr))
{
/* as above, depend on type */
add_object_address(OCLASS_TYPE, acoerce->resulttype, 0,
context->addrs);
- /* the collation might not be referenced anywhere else, either */
- if (OidIsValid(acoerce->resultcollid))
- add_object_address(OCLASS_COLLATION, acoerce->resultcollid, 0,
- context->addrs);
/* fall through to examine arguments */
}
else if (IsA(node, ConvertRowtypeExpr))
add_object_address(OCLASS_OPFAMILY, lfirst_oid(l), 0,
context->addrs);
}
+ foreach(l, rcexpr->inputcollids)
+ {
+ Oid inputcollid = lfirst_oid(l);
+
+ if (OidIsValid(inputcollid))
+ add_object_address(OCLASS_COLLATION, inputcollid, 0,
+ context->addrs);
+ }
+ /* fall through to examine arguments */
+ }
+ else if (IsA(node, MinMaxExpr))
+ {
+ MinMaxExpr *mmexpr = (MinMaxExpr *) node;
+
+ /* minmaxtype will match one of the inputs, so no need to record it */
+ if (OidIsValid(mmexpr->inputcollid))
+ add_object_address(OCLASS_COLLATION, mmexpr->inputcollid, 0,
+ context->addrs);
/* fall through to examine arguments */
}
else if (IsA(node, CoerceToDomain))
elog(ERROR, "cache lookup failed for type %u", typeoid);
typeTup = (Form_pg_type) GETSTRUCT(tuple);
+ /*
+ * If the type has a typcollation attribute, report that and we're done.
+ * Otherwise, it could be a container type that we should recurse into.
+ */
if (OidIsValid(typeTup->typcollation))
- result = list_append_unique_oid(result, typeTup->typcollation);
+ result = list_make1_oid(typeTup->typcollation);
else if (typeTup->typtype == TYPTYPE_COMPOSITE)
{
Relation rel = relation_open(typeTup->typrelid, AccessShareLock);
{
Form_pg_attribute att = TupleDescAttr(desc, i);
+ if (att->attisdropped)
+ continue;
if (OidIsValid(att->attcollation))
result = list_append_unique_oid(result, att->attcollation);
else
else if (typeTup->typtype == TYPTYPE_DOMAIN)
{
Assert(OidIsValid(typeTup->typbasetype));
-
- result = list_concat_unique_oid(result,
- GetTypeCollations(typeTup->typbasetype));
+ result = GetTypeCollations(typeTup->typbasetype);
}
else if (typeTup->typtype == TYPTYPE_RANGE)
{
- Oid rangeid = get_range_subtype(typeTup->oid);
+ Oid rangecoll = get_range_collation(typeTup->oid);
- Assert(OidIsValid(rangeid));
+ if (OidIsValid(rangecoll))
+ result = list_make1_oid(rangecoll);
+ else
+ {
+ Oid rangeid = get_range_subtype(typeTup->oid);
- result = list_concat_unique_oid(result, GetTypeCollations(rangeid));
+ Assert(OidIsValid(rangeid));
+ result = GetTypeCollations(rangeid);
+ }
}
- else if (OidIsValid(typeTup->typelem))
- result = list_concat_unique_oid(result,
- GetTypeCollations(typeTup->typelem));
+ else if (IsTrueArrayType(typeTup))
+ result = GetTypeCollations(typeTup->typelem);
ReleaseSysCache(tuple);
CREATE COLLATION custom (
LOCALE = 'fr-x-icu', PROVIDER = 'icu'
);
-CREATE TYPE myrange AS range (subtype = text);
+CREATE TYPE myrange AS range (subtype = text, collation = "POSIX");
CREATE TYPE myrange_en_fr_ga AS range(subtype = t_en_fr_ga);
CREATE TABLE collate_test (
id integer,
icuidx05_d_en_fr_ga_arr | "en-x-icu" | up to date
icuidx05_d_en_fr_ga_arr | "fr-x-icu" | up to date
icuidx05_d_en_fr_ga_arr | "ga-x-icu" | up to date
- icuidx06_d_en_fr_ga | "default" | XXX
- icuidx06_d_en_fr_ga | "en-x-icu" | up to date
icuidx06_d_en_fr_ga | "fr-x-icu" | up to date
- icuidx06_d_en_fr_ga | "ga-x-icu" | up to date
- icuidx07_d_en_fr_ga | "default" | XXX
- icuidx07_d_en_fr_ga | "en-x-icu" | up to date
- icuidx07_d_en_fr_ga | "fr-x-icu" | up to date
icuidx07_d_en_fr_ga | "ga-x-icu" | up to date
- icuidx08_d_en_fr_ga | "en-x-icu" | up to date
- icuidx08_d_en_fr_ga | "fr-x-icu" | up to date
- icuidx08_d_en_fr_ga | "ga-x-icu" | up to date
- icuidx09_d_en_fr_ga | "en-x-icu" | up to date
- icuidx09_d_en_fr_ga | "fr-x-icu" | up to date
- icuidx09_d_en_fr_ga | "ga-x-icu" | up to date
- icuidx10_d_en_fr_ga_es | "en-x-icu" | up to date
icuidx10_d_en_fr_ga_es | "es-x-icu" | up to date
- icuidx10_d_en_fr_ga_es | "fr-x-icu" | up to date
- icuidx10_d_en_fr_ga_es | "ga-x-icu" | up to date
- icuidx11_d_es | "default" | XXX
icuidx11_d_es | "es-x-icu" | up to date
- icuidx12_custom | "default" | XXX
icuidx12_custom | custom | up to date
- icuidx13_custom | "default" | XXX
icuidx13_custom | custom | up to date
- icuidx14_myrange | "default" | XXX
icuidx15_myrange_en_fr_ga | "en-x-icu" | up to date
icuidx15_myrange_en_fr_ga | "fr-x-icu" | up to date
icuidx15_myrange_en_fr_ga | "ga-x-icu" | up to date
icuidx17_part | "en-x-icu" | up to date
-(57 rows)
+(38 rows)
-- Validate that REINDEX will update the stored version.
UPDATE pg_depend SET refobjversion = 'not a version'