diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2010-10-21 16:07:17 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2010-10-21 16:07:17 -0400 |
commit | 529cb267a6843a6a8190c86b75d091771d99d6a9 (patch) | |
tree | aea2869f7fb92b00c25e67d20d4326b77720b27c /src/backend/utils/adt | |
parent | 572ab1a542c170ddd2e4c30ef472e13f531b64a4 (diff) | |
download | postgresql-529cb267a6843a6a8190c86b75d091771d99d6a9.tar.gz postgresql-529cb267a6843a6a8190c86b75d091771d99d6a9.zip |
Improve handling of domains over arrays.
This patch eliminates various bizarre behaviors caused by sloppy thinking
about the difference between a domain type and its underlying array type.
In particular, the operation of updating one element of such an array
has to be considered as yielding a value of the underlying array type,
*not* a value of the domain, because there's no assurance that the
domain's CHECK constraints are still satisfied. If we're intending to
store the result back into a domain column, we have to re-cast to the
domain type so that constraints are re-checked.
For similar reasons, such a domain can't be blindly matched to an ANYARRAY
polymorphic parameter, because the polymorphic function is likely to apply
array-ish operations that could invalidate the domain constraints. For the
moment, we just forbid such matching. We might later wish to insert an
automatic downcast to the underlying array type, but such a change should
also change matching of domains to ANYELEMENT for consistency.
To ensure that all such logic is rechecked, this patch removes the original
hack of setting a domain's pg_type.typelem field to match its base type;
the typelem will always be zero instead. In those places where it's really
okay to look through the domain type with no other logic changes, use the
newly added get_base_element_type function in place of get_element_type.
catversion bumped due to change in pg_type contents.
Per bug #5717 from Richard Huxton and subsequent discussion.
Diffstat (limited to 'src/backend/utils/adt')
-rw-r--r-- | src/backend/utils/adt/format_type.c | 14 | ||||
-rw-r--r-- | src/backend/utils/adt/ruleutils.c | 2 | ||||
-rw-r--r-- | src/backend/utils/adt/selfuncs.c | 2 | ||||
-rw-r--r-- | src/backend/utils/adt/xml.c | 2 |
4 files changed, 9 insertions, 11 deletions
diff --git a/src/backend/utils/adt/format_type.c b/src/backend/utils/adt/format_type.c index 8fd551ef841..f6f5efe1263 100644 --- a/src/backend/utils/adt/format_type.c +++ b/src/backend/utils/adt/format_type.c @@ -134,18 +134,16 @@ format_type_internal(Oid type_oid, int32 typemod, typeform = (Form_pg_type) GETSTRUCT(tuple); /* - * Check if it's an array (and not a domain --- we don't want to show the - * substructure of a domain type). Fixed-length array types such as - * "name" shouldn't get deconstructed either. As of Postgres 8.1, rather - * than checking typlen we check the toast property, and don't deconstruct - * "plain storage" array types --- this is because we don't want to show - * oidvector as oid[]. + * Check if it's a regular (variable length) array type. Fixed-length + * array types such as "name" shouldn't get deconstructed. As of Postgres + * 8.1, rather than checking typlen we check the toast property, and don't + * deconstruct "plain storage" array types --- this is because we don't + * want to show oidvector as oid[]. */ array_base_type = typeform->typelem; if (array_base_type != InvalidOid && - typeform->typstorage != 'p' && - typeform->typtype != TYPTYPE_DOMAIN) + typeform->typstorage != 'p') { /* Switch our attention to the array element type */ ReleaseSysCache(tuple); diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 22ba948e732..d4279c0f4e5 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -4850,7 +4850,7 @@ get_rule_expr(Node *node, deparse_context *context, appendStringInfo(buf, " %s %s (", generate_operator_name(expr->opno, exprType(arg1), - get_element_type(exprType(arg2))), + get_base_element_type(exprType(arg2))), expr->useOr ? "ANY" : "ALL"); get_rule_expr_paren(arg2, context, true, node); appendStringInfoChar(buf, ')'); diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index ce6d4e2a79b..c7442218a84 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -1704,7 +1704,7 @@ scalararraysel(PlannerInfo *root, rightop = (Node *) lsecond(clause->args); /* get nominal (after relabeling) element type of rightop */ - nominal_element_type = get_element_type(exprType(rightop)); + nominal_element_type = get_base_element_type(exprType(rightop)); if (!OidIsValid(nominal_element_type)) return (Selectivity) 0.5; /* probably shouldn't happen */ diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c index a94a457cac6..6e9c7fe2b06 100644 --- a/src/backend/utils/adt/xml.c +++ b/src/backend/utils/adt/xml.c @@ -1615,7 +1615,7 @@ map_xml_name_to_sql_identifier(char *name) char * map_sql_value_to_xml_value(Datum value, Oid type, bool xml_escape_strings) { - if (type_is_array(type)) + if (type_is_array_domain(type)) { ArrayType *array; Oid elmtype; |