diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2017-10-27 12:18:57 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2017-10-27 12:18:57 -0400 |
commit | cf0331a54c9b173f778ae09fbd30a432da247afc (patch) | |
tree | cbd5bb5d2ab4c2e0d90e52067e1976cd8219fed4 /src/backend | |
parent | 0ff56a59d2496a8f896362b91d1faa9b14f6a6d9 (diff) | |
download | postgresql-cf0331a54c9b173f778ae09fbd30a432da247afc.tar.gz postgresql-cf0331a54c9b173f778ae09fbd30a432da247afc.zip |
Rethink the dependencies recorded for FieldSelect/FieldStore nodes.
On closer investigation, commits f3ea3e3e8 et al were a few bricks
shy of a load. What we need is not so much to lock down the result
type of a FieldSelect, as to lock down the existence of the column
it's trying to extract. Otherwise, we can break it by dropping that
column. The dependency on the result type is then held indirectly
through the column, and doesn't need to be recorded explicitly.
Out of paranoia, I left in the code to record a dependency on the
result type, but it's used only if we can't identify the pg_class OID
for the column. That shouldn't ever happen right now, AFAICS, but
it seems possible that in future the input node could be marked as
being of type RECORD rather than some specific composite type.
Likewise for FieldStore.
Like the previous patch, back-patch to all supported branches.
Discussion: https://postgr.es/m/22571.1509064146@sss.pgh.pa.us
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/catalog/dependency.c | 36 |
1 files changed, 30 insertions, 6 deletions
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index eec66d20116..8e9f101f223 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -1713,10 +1713,24 @@ find_expr_references_walker(Node *node, else if (IsA(node, FieldSelect)) { FieldSelect *fselect = (FieldSelect *) node; + Oid argtype = exprType((Node *) fselect->arg); + Oid reltype = get_typ_typrelid(argtype); - /* result type might not appear anywhere else in expression */ - add_object_address(OCLASS_TYPE, fselect->resulttype, 0, - context->addrs); + /* + * We need a dependency on the specific column named in FieldSelect, + * assuming we can identify the pg_class OID for it. (Probably we + * always can at the moment, but in future it might be possible for + * argtype to be RECORDOID.) If we can make a column dependency then + * we shouldn't need a dependency on the column's type; but if we + * can't, make a dependency on the type, as it might not appear + * anywhere else in the expression. + */ + if (OidIsValid(reltype)) + add_object_address(OCLASS_CLASS, reltype, fselect->fieldnum, + context->addrs); + else + add_object_address(OCLASS_TYPE, fselect->resulttype, 0, + context->addrs); /* the collation might not be referenced anywhere else, either */ if (OidIsValid(fselect->resultcollid) && fselect->resultcollid != DEFAULT_COLLATION_OID) @@ -1726,10 +1740,20 @@ find_expr_references_walker(Node *node, else if (IsA(node, FieldStore)) { FieldStore *fstore = (FieldStore *) node; + Oid reltype = get_typ_typrelid(fstore->resulttype); - /* result type might not appear anywhere else in expression */ - add_object_address(OCLASS_TYPE, fstore->resulttype, 0, - context->addrs); + /* similar considerations to FieldSelect, but multiple column(s) */ + if (OidIsValid(reltype)) + { + ListCell *l; + + foreach(l, fstore->fieldnums) + add_object_address(OCLASS_CLASS, reltype, lfirst_int(l), + context->addrs); + } + else + add_object_address(OCLASS_TYPE, fstore->resulttype, 0, + context->addrs); } else if (IsA(node, RelabelType)) { |