From: Tom Lane Date: Wed, 8 Jan 2003 21:40:49 +0000 (+0000) Subject: Repair bug noticed by Deepak Bhole: a shell type should have a dependency X-Git-Tag: REL7_3_2~49 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a899179c8cdbd74c4a3a1b9e2712b92321182f0d;p=postgresql Repair bug noticed by Deepak Bhole: a shell type should have a dependency on its namespace, so that it will go away if the schema is dropped. --- diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c index d43c1edeee..8a8db49dde 100644 --- a/src/backend/catalog/pg_type.c +++ b/src/backend/catalog/pg_type.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.82 2002/09/04 20:31:14 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.82.2.1 2003/01/08 21:40:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -105,6 +105,21 @@ TypeShellMake(const char *typeName, Oid typeNamespace) CatalogUpdateIndexes(pg_type_desc, tup); + /* + * Create dependencies. We can/must skip this in bootstrap mode. + */ + if (!IsBootstrapProcessingMode()) + GenerateTypeDependencies(typeNamespace, + typoid, + InvalidOid, + 0, + InvalidOid, + InvalidOid, + InvalidOid, + InvalidOid, + NULL, + false); + /* * clean up and return the type-oid */ @@ -129,7 +144,7 @@ Oid TypeCreate(const char *typeName, Oid typeNamespace, Oid assignedTypeOid, - Oid relationOid, /* only for 'c'atalog typeType */ + Oid relationOid, /* only for 'c'atalog types */ char relationKind, /* ditto */ int16 internalSize, char typeType, @@ -139,7 +154,7 @@ TypeCreate(const char *typeName, Oid elementType, Oid baseType, const char *defaultTypeValue, /* human readable rep */ - const char *defaultTypeBin, /* cooked rep */ + char *defaultTypeBin, /* cooked rep */ bool passedByValue, char alignment, char storage, @@ -149,6 +164,7 @@ TypeCreate(const char *typeName, { Relation pg_type_desc; Oid typeObjectId; + bool rebuildDeps = false; HeapTuple tup; char nulls[Natts_pg_type]; char replaces[Natts_pg_type]; @@ -268,6 +284,8 @@ TypeCreate(const char *typeName, simple_heap_update(pg_type_desc, &tup->t_self, tup); typeObjectId = HeapTupleGetOid(tup); + + rebuildDeps = true; /* get rid of shell type's dependencies */ } else { @@ -290,88 +308,135 @@ TypeCreate(const char *typeName, * Create dependencies. We can/must skip this in bootstrap mode. */ if (!IsBootstrapProcessingMode()) + GenerateTypeDependencies(typeNamespace, + typeObjectId, + relationOid, + relationKind, + inputProcedure, + outputProcedure, + elementType, + baseType, + (defaultTypeBin ? + stringToNode(defaultTypeBin) : + (void *) NULL), + rebuildDeps); + + /* + * finish up + */ + heap_close(pg_type_desc, RowExclusiveLock); + + return typeObjectId; +} + +/* + * GenerateTypeDependencies: build the dependencies needed for a type + * + * If rebuild is true, we remove existing dependencies and rebuild them + * from scratch. This is needed for ALTER TYPE, and also when replacing + * a shell type. + * + * NOTE: a shell type will have a dependency to its namespace, and no others. + */ +void +GenerateTypeDependencies(Oid typeNamespace, + Oid typeObjectId, + Oid relationOid, /* only for 'c'atalog types */ + char relationKind, /* ditto */ + Oid inputProcedure, + Oid outputProcedure, + Oid elementType, + Oid baseType, + Node *defaultExpr, + bool rebuild) +{ + ObjectAddress myself, + referenced; + + if (rebuild) + deleteDependencyRecordsFor(RelOid_pg_type, + typeObjectId); + + myself.classId = RelOid_pg_type; + myself.objectId = typeObjectId; + myself.objectSubId = 0; + + /* dependency on namespace */ + /* skip for relation rowtype, since we have indirect dependency */ + if (!OidIsValid(relationOid)) + { + referenced.classId = get_system_catalog_relid(NamespaceRelationName); + referenced.objectId = typeNamespace; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + } + + /* Normal dependencies on the I/O functions */ + if (OidIsValid(inputProcedure)) { - ObjectAddress myself, - referenced; - - myself.classId = RelOid_pg_type; - myself.objectId = typeObjectId; - myself.objectSubId = 0; - - /* dependency on namespace */ - /* skip for relation rowtype, since we have indirect dependency */ - if (!OidIsValid(relationOid)) - { - referenced.classId = get_system_catalog_relid(NamespaceRelationName); - referenced.objectId = typeNamespace; - referenced.objectSubId = 0; - recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); - } - - /* Normal dependencies on the I/O functions */ referenced.classId = RelOid_pg_proc; referenced.objectId = inputProcedure; referenced.objectSubId = 0; recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + } + if (OidIsValid(outputProcedure)) + { referenced.classId = RelOid_pg_proc; referenced.objectId = outputProcedure; referenced.objectSubId = 0; recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + } - /* - * If the type is a rowtype for a relation, mark it as internally - * dependent on the relation, *unless* it is a stand-alone - * composite type relation. For the latter case, we have to - * reverse the dependency. - * - * In the former case, this allows the type to be auto-dropped when - * the relation is, and not otherwise. And in the latter, of - * course we get the opposite effect. - */ - if (OidIsValid(relationOid)) - { - referenced.classId = RelOid_pg_class; - referenced.objectId = relationOid; - referenced.objectSubId = 0; - - if (relationKind != RELKIND_COMPOSITE_TYPE) - recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL); - else - recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL); - } + /* + * If the type is a rowtype for a relation, mark it as internally + * dependent on the relation, *unless* it is a stand-alone + * composite type relation. For the latter case, we have to + * reverse the dependency. + * + * In the former case, this allows the type to be auto-dropped when + * the relation is, and not otherwise. And in the latter, of + * course we get the opposite effect. + */ + if (OidIsValid(relationOid)) + { + referenced.classId = RelOid_pg_class; + referenced.objectId = relationOid; + referenced.objectSubId = 0; - /* - * If the type is an array type, mark it auto-dependent on the - * base type. (This is a compromise between the typical case - * where the array type is automatically generated and the case - * where it is manually created: we'd prefer INTERNAL for the - * former case and NORMAL for the latter.) - */ - if (OidIsValid(elementType)) - { - referenced.classId = RelOid_pg_type; - referenced.objectId = elementType; - referenced.objectSubId = 0; - recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO); - } - - /* Normal dependency from a domain to its base type. */ - if (OidIsValid(baseType)) - { - referenced.classId = RelOid_pg_type; - referenced.objectId = baseType; - referenced.objectSubId = 0; - recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); - } + if (relationKind != RELKIND_COMPOSITE_TYPE) + recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL); + else + recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL); } /* - * finish up + * If the type is an array type, mark it auto-dependent on the + * base type. (This is a compromise between the typical case + * where the array type is automatically generated and the case + * where it is manually created: we'd prefer INTERNAL for the + * former case and NORMAL for the latter.) */ - heap_close(pg_type_desc, RowExclusiveLock); + if (OidIsValid(elementType)) + { + referenced.classId = RelOid_pg_type; + referenced.objectId = elementType; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO); + } - return typeObjectId; + /* Normal dependency from a domain to its base type. */ + if (OidIsValid(baseType)) + { + referenced.classId = RelOid_pg_type; + referenced.objectId = baseType; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + } + + /* Normal dependency on the default expression. */ + if (defaultExpr) + recordDependencyOnExpr(&myself, defaultExpr, NIL, DEPENDENCY_NORMAL); } /* diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h index 06ac2f340a..31bde74513 100644 --- a/src/include/catalog/pg_type.h +++ b/src/include/catalog/pg_type.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_type.h,v 1.134 2002/09/24 21:26:44 tgl Exp $ + * $Id: pg_type.h,v 1.134.2.1 2003/01/08 21:40:49 tgl Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -19,6 +19,8 @@ #ifndef PG_TYPE_H #define PG_TYPE_H +#include "nodes/nodes.h" + /* ---------------- * postgres.h contains the system type definitions and the * CATALOG(), BOOTSTRAP and DATA() sugar words so this file @@ -537,7 +539,7 @@ DATA(insert OID = 2282 ( opaque PGNSP PGUID 4 t p t \054 0 0 opaque_in opaque */ extern Oid TypeShellMake(const char *typeName, Oid typeNamespace); -extern Oid TypeCreate(const char *typeName, +extern Oid TypeCreate(const char *typeName, Oid typeNamespace, Oid assignedTypeOid, Oid relationOid, @@ -550,7 +552,7 @@ extern Oid TypeCreate(const char *typeName, Oid elementType, Oid baseType, const char *defaultTypeValue, - const char *defaultTypeBin, + char *defaultTypeBin, bool passedByValue, char alignment, char storage, @@ -558,9 +560,20 @@ extern Oid TypeCreate(const char *typeName, int32 typNDims, bool typeNotNull); +extern void GenerateTypeDependencies(Oid typeNamespace, + Oid typeObjectId, + Oid relationOid, + char relationKind, + Oid inputProcedure, + Oid outputProcedure, + Oid elementType, + Oid baseType, + Node *defaultExpr, + bool rebuild); extern void TypeRename(const char *oldTypeName, Oid typeNamespace, const char *newTypeName); + extern char *makeArrayTypeName(const char *typeName); #endif /* PG_TYPE_H */