Alvaro Herrera <alvhe...@commandprompt.com> writes: > Hmm, seeing the amount of new includes in extension.c, I wonder if it'd > be better to move AlterExtensionNamespace to alter.c.
It was mainly missing includes cleanup. The guts of the function is now so short I can inline it in this mail: targetObjects = listDependentObjects(object); for (i = 0; i < targetObjects->numrefs; i++) { ObjectAddress *thisobj = targetObjects->refs + i; elog(DEBUG1, "SET SCHEMA on %u: %s", thisobj->objectId, getObjectDescription(thisobj)); AlterObjectNamespace_internal(thisobj, nspOid); } So really, I don't think moving it to alter.c would do any better, considering that you would then have this file include dependency related function. Please find attached v3 patch with #include cleanup. -- Dimitri Fontaine http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support
*** a/src/backend/catalog/pg_depend.c --- b/src/backend/catalog/pg_depend.c *************** *** 20,25 **** --- 20,27 ---- #include "catalog/indexing.h" #include "catalog/pg_constraint.h" #include "catalog/pg_depend.h" + #include "catalog/pg_extension.h" + #include "catalog/pg_namespace.h" #include "miscadmin.h" #include "utils/fmgroids.h" #include "utils/lsyscache.h" *************** *** 643,645 **** get_index_constraint(Oid indexId) --- 645,699 ---- return constraintId; } + + /* + * get_extension_namespace + * Given the OID of an extension, return the OID of the schema it + * depends on, or InvalidOid when not found + */ + Oid + get_extension_namespace(Oid extensionId) + { + Oid nspId = InvalidOid; + Relation depRel; + ScanKeyData key[3]; + SysScanDesc scan; + HeapTuple tup; + + /* Search the dependency table for the index */ + depRel = heap_open(DependRelationId, AccessShareLock); + + ScanKeyInit(&key[0], + Anum_pg_depend_classid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(ExtensionRelationId)); + ScanKeyInit(&key[1], + Anum_pg_depend_objid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(extensionId)); + ScanKeyInit(&key[2], + Anum_pg_depend_objsubid, + BTEqualStrategyNumber, F_INT4EQ, + Int32GetDatum(0)); + + scan = systable_beginscan(depRel, DependDependerIndexId, true, + SnapshotNow, 3, key); + + while (HeapTupleIsValid(tup = systable_getnext(scan))) + { + Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup); + + if (deprec->refclassid == NamespaceRelationId && + deprec->refobjsubid == 0 && + deprec->deptype == DEPENDENCY_NORMAL) + { + nspId = deprec->refobjid; + break; + } + } + + systable_endscan(scan); + heap_close(depRel, AccessShareLock); + + return nspId; + } *** a/src/backend/commands/alter.c --- b/src/backend/commands/alter.c *************** *** 22,27 **** --- 22,28 ---- #include "commands/conversioncmds.h" #include "commands/dbcommands.h" #include "commands/defrem.h" + #include "commands/extension.h" #include "commands/proclang.h" #include "commands/schemacmds.h" #include "commands/tablecmds.h" *************** *** 189,194 **** ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt) --- 190,199 ---- AlterConversionNamespace(stmt->object, stmt->newschema); break; + case OBJECT_EXTENSION: + AlterExtensionNamespace(stmt->object, stmt->newschema); + break; + case OBJECT_FUNCTION: AlterFunctionNamespace(stmt->object, stmt->objarg, false, stmt->newschema); *************** *** 334,339 **** AlterObjectNamespace(Relation rel, int cacheId, --- 339,436 ---- NamespaceRelationId, oldNspOid, nspOid); } + /* + * Do the SET SCHEMA depending on the object class. + * + * We only consider objects that have a namespace and that can exist + * without depending on another object (like a table) which will + * have its dependencies follow the SET SCHEMA operation. + */ + void + AlterObjectNamespace_internal(ObjectAddress *thisobj, Oid nspOid) + { + switch (getObjectClass(thisobj)) + { + case OCLASS_CLASS: + { + Relation classRel; + Relation rel = relation_open(thisobj->objectId, RowExclusiveLock); + + switch (rel->rd_rel->relkind) + { + case RELKIND_COMPOSITE_TYPE: + /* + * just skip the pg_class entry, we have a pg_type + * entry too + */ + break; + + default: + classRel = heap_open(RelationRelationId, RowExclusiveLock); + AlterRelationNamespaceInternal(classRel, + RelationGetRelid(rel), + RelationGetNamespace(rel), + nspOid, + true); + heap_close(classRel, RowExclusiveLock); + break; + } + relation_close(rel, RowExclusiveLock); + break; + } + + case OCLASS_PROC: + AlterFunctionNamespace_oid(thisobj->objectId, nspOid); + break; + + case OCLASS_TYPE: + { + /* don't allow direct alteration of array types, skip */ + Oid elemOid = get_element_type(thisobj->objectId); + if (OidIsValid(elemOid) + && get_array_type(elemOid) == thisobj->objectId) + break; + + AlterTypeNamespace_oid(thisobj->objectId, nspOid); + break; + } + + case OCLASS_CONVERSION: + AlterConversionNamespace_oid(thisobj->objectId, nspOid); + break; + + case OCLASS_OPERATOR: + AlterOperatorNamespace_oid(thisobj->objectId, nspOid); + break; + + case OCLASS_OPCLASS: + AlterOpClassNamespace_oid(thisobj->objectId, nspOid); + break; + + case OCLASS_OPFAMILY: + AlterOpFamilyNamespace_oid(thisobj->objectId, nspOid); + break; + + case OCLASS_TSPARSER: + AlterTSParserNamespace_oid(thisobj->objectId, nspOid); + break; + + case OCLASS_TSDICT: + AlterTSDictionaryNamespace_oid(thisobj->objectId, nspOid); + break; + + case OCLASS_TSTEMPLATE: + AlterTSTemplateNamespace_oid(thisobj->objectId, nspOid); + break; + + case OCLASS_TSCONFIG: + AlterTSConfigurationNamespace_oid(thisobj->objectId, nspOid); + break; + + default: + break; + } + } /* * Executes an ALTER OBJECT / OWNER TO statement. Based on the object *** a/src/backend/commands/extension.c --- b/src/backend/commands/extension.c *************** *** 42,47 **** --- 42,48 ---- #include "catalog/pg_extension.h" #include "catalog/pg_namespace.h" #include "catalog/pg_type.h" + #include "commands/alter.h" #include "commands/comment.h" #include "commands/extension.h" #include "funcapi.h" *************** *** 1275,1277 **** pg_extension_objects(PG_FUNCTION_ARGS) --- 1276,1322 ---- releaseDependentObjects(fctx->targetObjects); SRF_RETURN_DONE(funcctx); } + + /* + * Execute ALTER EXTENSION SET SCHEMA + */ + void + AlterExtensionNamespace(List *name, const char *newschema) + { + Oid extensionOid, nspOid, oldNspOid; + ObjectAddress *object; + ObjectAddresses *targetObjects; + int i; + + if (!superuser()) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + (errmsg("must be superuser to ALTER EXTENSION")))); + + Assert(list_length(name) == 1); + extensionOid = get_extension_oid(strVal(linitial(name)), false); + nspOid = LookupCreationNamespace(newschema); + + object = (ObjectAddress *)palloc(sizeof(ObjectAddress)); + object->classId = ExtensionRelationId; + object->objectId = extensionOid; + object->objectSubId = 0; + + oldNspOid = get_extension_namespace(extensionOid); + + targetObjects = listDependentObjects(object); + + for (i = 0; i < targetObjects->numrefs; i++) + { + ObjectAddress *thisobj = targetObjects->refs + i; + + elog(DEBUG1, "SET SCHEMA on %u: %s", + thisobj->objectId, getObjectDescription(thisobj)); + + AlterObjectNamespace_internal(thisobj, nspOid); + } + + /* update dependencies to point to the new schema */ + changeDependencyFor(ExtensionRelationId, extensionOid, + NamespaceRelationId, oldNspOid, nspOid); + } *** a/src/backend/commands/tsearchcmds.c --- b/src/backend/commands/tsearchcmds.c *************** *** 48,54 **** #include "utils/rel.h" #include "utils/syscache.h" #include "utils/tqual.h" - #include "commands/extension.h" static void MakeConfigurationMapping(AlterTSConfigurationStmt *stmt, --- 48,53 ---- *** a/src/backend/commands/typecmds.c --- b/src/backend/commands/typecmds.c *************** *** 2765,2784 **** AlterTypeNamespace(List *names, const char *newschema) TypeName *typename; Oid typeOid; Oid nspOid; - Oid elemOid; /* Make a TypeName so we can use standard type lookup machinery */ typename = makeTypeNameFromNameList(names); typeOid = typenameTypeId(NULL, typename); /* check permissions on type */ if (!pg_type_ownercheck(typeOid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE, format_type_be(typeOid)); - /* get schema OID and check its permissions */ - nspOid = LookupCreationNamespace(newschema); - /* don't allow direct alteration of array types */ elemOid = get_element_type(typeOid); if (OidIsValid(elemOid) && get_array_type(elemOid) == typeOid) --- 2765,2791 ---- TypeName *typename; Oid typeOid; Oid nspOid; /* Make a TypeName so we can use standard type lookup machinery */ typename = makeTypeNameFromNameList(names); typeOid = typenameTypeId(NULL, typename); + /* get schema OID and check its permissions */ + nspOid = LookupCreationNamespace(newschema); + + AlterTypeNamespace_oid(typeOid, nspOid); + } + + void + AlterTypeNamespace_oid(Oid typeOid, Oid nspOid) + { + Oid elemOid; + /* check permissions on type */ if (!pg_type_ownercheck(typeOid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE, format_type_be(typeOid)); /* don't allow direct alteration of array types */ elemOid = get_element_type(typeOid); if (OidIsValid(elemOid) && get_array_type(elemOid) == typeOid) *************** *** 2790,2796 **** AlterTypeNamespace(List *names, const char *newschema) format_type_be(elemOid)))); /* and do the work */ ! AlterTypeNamespaceInternal(typeOid, nspOid, false, true); } /* --- 2797,2803 ---- format_type_be(elemOid)))); /* and do the work */ ! AlterTypeNamespaceInternal(typeOid, nspOid, false, false); } /* *** a/src/backend/parser/gram.y --- b/src/backend/parser/gram.y *************** *** 6138,6143 **** AlterObjectSchemaStmt: --- 6138,6151 ---- n->newschema = $6; $$ = (Node *)n; } + | ALTER EXTENSION any_name SET SCHEMA name + { + AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt); + n->objectType = OBJECT_EXTENSION; + n->object = $3; + n->newschema = $6; + $$ = (Node *)n; + } | ALTER FUNCTION function_with_argtypes SET SCHEMA name { AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt); *** a/src/backend/tcop/utility.c --- b/src/backend/tcop/utility.c *************** *** 1719,1724 **** CreateCommandTag(Node *parsetree) --- 1719,1727 ---- case OBJECT_DOMAIN: tag = "ALTER DOMAIN"; break; + case OBJECT_EXTENSION: + tag = "ALTER EXTENSION"; + break; case OBJECT_OPERATOR: tag = "ALTER OPERATOR"; break; *** a/src/include/catalog/dependency.h --- b/src/include/catalog/dependency.h *************** *** 240,245 **** extern Oid get_constraint_index(Oid constraintId); --- 240,248 ---- extern Oid get_index_constraint(Oid indexId); + extern Oid get_extension_namespace(Oid extensionId); + + /* in pg_shdepend.c */ extern void recordSharedDependencyOn(ObjectAddress *depender, *** a/src/include/commands/alter.h --- b/src/include/commands/alter.h *************** *** 14,19 **** --- 14,20 ---- #ifndef ALTER_H #define ALTER_H + #include "catalog/objectaddress.h" #include "nodes/parsenodes.h" #include "utils/acl.h" #include "utils/relcache.h" *************** *** 25,30 **** extern void AlterObjectNamespace(Relation rel, int cacheId, --- 26,32 ---- int Anum_name, int Anum_namespace, int Anum_owner, AclObjectKind acl_kind, bool superuser_only); + extern void AlterObjectNamespace_internal(ObjectAddress *thisobj, Oid nspOid); extern void ExecAlterOwnerStmt(AlterOwnerStmt *stmt); #endif /* ALTER_H */ *** a/src/include/commands/extension.h --- b/src/include/commands/extension.h *************** *** 64,69 **** extern void DropExtension(DropExtensionStmt *stmt); --- 64,70 ---- extern Oid get_extension_oid(const char *extname, bool missing_ok); extern char *get_extension_name(Oid ext_oid); extern void RemoveExtensionById(Oid extId); + extern void AlterExtensionNamespace(List *name, const char *newschema); #endif /* EXTENSION_H */ *** a/src/include/commands/typecmds.h --- b/src/include/commands/typecmds.h *************** *** 41,46 **** extern void AlterTypeOwner(List *names, Oid newOwnerId); --- 41,47 ---- extern void AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId, bool hasDependEntry); extern void AlterTypeNamespace(List *names, const char *newschema); + extern void AlterTypeNamespace_oid(Oid typeOid, Oid nspOid); extern void AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid, bool isImplicitArray, bool errorOnTableType);
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers