diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c index 19bde9f..3848af5 100644 --- a/src/backend/catalog/objectaddress.c +++ b/src/backend/catalog/objectaddress.c @@ -78,7 +78,13 @@ typedef struct Oid class_oid; /* oid of catalog */ Oid oid_index_oid; /* oid of index on system oid column */ int oid_catcache_id; /* id of catcache on system oid column */ + int name_catcache_id; /* id of catcache on a pair of name and + * namespace column */ + AttrNumber attnum_name; /* attnum of name field */ AttrNumber attnum_namespace; /* attnum of namespace field */ + AttrNumber attnum_owner; /* attnum of owner field */ + AttrNumber attnum_acl; /* attnum of acl field */ + AclObjectKind acl_kind; /* ACL_KIND_* of this object type */ } ObjectPropertyType; static ObjectPropertyType ObjectProperty[] = @@ -87,151 +93,276 @@ static ObjectPropertyType ObjectProperty[] = CastRelationId, CastOidIndexId, -1, - InvalidAttrNumber + -1, + InvalidAttrNumber, + InvalidAttrNumber, + InvalidAttrNumber, + InvalidAttrNumber, + -1 }, { CollationRelationId, CollationOidIndexId, COLLOID, - Anum_pg_collation_collnamespace + -1, /* COLLNAMEENCNSP also takes encoding */ + Anum_pg_collation_collname, + Anum_pg_collation_collnamespace, + Anum_pg_collation_collowner, + InvalidAttrNumber, + ACL_KIND_COLLATION }, { ConstraintRelationId, ConstraintOidIndexId, CONSTROID, - Anum_pg_constraint_connamespace + -1, + Anum_pg_constraint_conname, + Anum_pg_constraint_connamespace, + InvalidAttrNumber, + InvalidAttrNumber, + -1 }, { ConversionRelationId, ConversionOidIndexId, CONVOID, - Anum_pg_conversion_connamespace + CONNAMENSP, + Anum_pg_conversion_conname, + Anum_pg_conversion_connamespace, + Anum_pg_conversion_conowner, + InvalidAttrNumber, + ACL_KIND_CONVERSION }, { DatabaseRelationId, DatabaseOidIndexId, DATABASEOID, - InvalidAttrNumber + -1, + Anum_pg_database_datname, + InvalidAttrNumber, + Anum_pg_database_datdba, + Anum_pg_database_datacl, + ACL_KIND_DATABASE }, { ExtensionRelationId, ExtensionOidIndexId, -1, - InvalidAttrNumber /* extension doesn't belong to extnamespace */ + -1, + Anum_pg_extension_extname, + InvalidAttrNumber, /* extension doesn't belong to extnamespace */ + Anum_pg_extension_extowner, + InvalidAttrNumber, + ACL_KIND_EXTENSION }, { ForeignDataWrapperRelationId, ForeignDataWrapperOidIndexId, FOREIGNDATAWRAPPEROID, - InvalidAttrNumber + FOREIGNDATAWRAPPERNAME, + Anum_pg_foreign_data_wrapper_fdwname, + InvalidAttrNumber, + Anum_pg_foreign_data_wrapper_fdwowner, + Anum_pg_foreign_data_wrapper_fdwacl, + ACL_KIND_FDW }, { ForeignServerRelationId, ForeignServerOidIndexId, FOREIGNSERVEROID, - InvalidAttrNumber + FOREIGNSERVERNAME, + Anum_pg_foreign_server_srvname, + InvalidAttrNumber, + Anum_pg_foreign_server_srvowner, + Anum_pg_foreign_server_srvacl, + ACL_KIND_FOREIGN_SERVER }, { ProcedureRelationId, ProcedureOidIndexId, PROCOID, - Anum_pg_proc_pronamespace + -1, /* PROCNAMEARGSNSP also takes argument types */ + Anum_pg_proc_proname, + Anum_pg_proc_pronamespace, + Anum_pg_proc_proowner, + Anum_pg_proc_proacl, + ACL_KIND_PROC }, { LanguageRelationId, LanguageOidIndexId, LANGOID, + LANGNAME, + Anum_pg_language_lanname, InvalidAttrNumber, + Anum_pg_language_lanowner, + Anum_pg_language_lanacl, + ACL_KIND_LANGUAGE }, { LargeObjectMetadataRelationId, LargeObjectMetadataOidIndexId, -1, - InvalidAttrNumber + -1, + InvalidAttrNumber, + InvalidAttrNumber, + Anum_pg_largeobject_metadata_lomowner, + Anum_pg_largeobject_metadata_lomacl, + ACL_KIND_LARGEOBJECT }, { OperatorClassRelationId, OpclassOidIndexId, CLAOID, + -1, /* CLAAMNAMENSP also takes opcmethod */ + Anum_pg_opclass_opcname, Anum_pg_opclass_opcnamespace, + Anum_pg_opclass_opcowner, + InvalidAttrNumber, + ACL_KIND_OPCLASS }, { OperatorRelationId, OperatorOidIndexId, OPEROID, - Anum_pg_operator_oprnamespace + -1, /* OPERNAMENSP also takes left and right type */ + Anum_pg_operator_oprname, + Anum_pg_operator_oprnamespace, + Anum_pg_operator_oprowner, + InvalidAttrNumber, + ACL_KIND_OPER }, { OperatorFamilyRelationId, OpfamilyOidIndexId, OPFAMILYOID, - Anum_pg_opfamily_opfnamespace + -1, /* OPFAMILYAMNAMENSP also takes opfmethod */ + Anum_pg_opfamily_opfname, + Anum_pg_opfamily_opfnamespace, + Anum_pg_opfamily_opfowner, + InvalidAttrNumber, + ACL_KIND_OPFAMILY }, { AuthIdRelationId, AuthIdOidIndexId, AUTHOID, - InvalidAttrNumber + AUTHNAME, + Anum_pg_authid_rolname, + InvalidAttrNumber, + InvalidAttrNumber, + InvalidAttrNumber, + -1 }, { RewriteRelationId, RewriteOidIndexId, -1, - InvalidAttrNumber + -1, + Anum_pg_rewrite_rulename, + InvalidAttrNumber, + InvalidAttrNumber, + InvalidAttrNumber, + -1 }, { NamespaceRelationId, NamespaceOidIndexId, NAMESPACEOID, - InvalidAttrNumber + NAMESPACENAME, + Anum_pg_namespace_nspname, + InvalidAttrNumber, + Anum_pg_namespace_nspowner, + Anum_pg_namespace_nspacl, + ACL_KIND_NAMESPACE }, { RelationRelationId, ClassOidIndexId, RELOID, - Anum_pg_class_relnamespace + RELNAMENSP, + Anum_pg_class_relname, + Anum_pg_class_relnamespace, + Anum_pg_class_relowner, + Anum_pg_class_relacl, + ACL_KIND_CLASS }, { TableSpaceRelationId, TablespaceOidIndexId, TABLESPACEOID, - InvalidAttrNumber + -1, + Anum_pg_tablespace_spcname, + InvalidAttrNumber, + Anum_pg_tablespace_spcowner, + Anum_pg_tablespace_spcacl, + ACL_KIND_TABLESPACE }, { TriggerRelationId, TriggerOidIndexId, -1, - InvalidAttrNumber + -1, + Anum_pg_trigger_tgname, + InvalidAttrNumber, + InvalidAttrNumber, + InvalidAttrNumber, + -1, }, { TSConfigRelationId, TSConfigOidIndexId, TSCONFIGOID, - Anum_pg_ts_config_cfgnamespace + TSCONFIGNAMENSP, + Anum_pg_ts_config_cfgname, + Anum_pg_ts_config_cfgnamespace, + Anum_pg_ts_config_cfgowner, + InvalidAttrNumber, + ACL_KIND_TSCONFIGURATION }, { TSDictionaryRelationId, TSDictionaryOidIndexId, TSDICTOID, - Anum_pg_ts_dict_dictnamespace + TSDICTNAMENSP, + Anum_pg_ts_dict_dictname, + Anum_pg_ts_dict_dictnamespace, + Anum_pg_ts_dict_dictowner, + InvalidAttrNumber, + ACL_KIND_TSDICTIONARY }, { TSParserRelationId, TSParserOidIndexId, TSPARSEROID, - Anum_pg_ts_parser_prsnamespace + TSPARSERNAMENSP, + Anum_pg_ts_parser_prsname, + Anum_pg_ts_parser_prsnamespace, + InvalidAttrNumber, + InvalidAttrNumber, + -1, }, { TSTemplateRelationId, TSTemplateOidIndexId, TSTEMPLATEOID, + TSTEMPLATENAMENSP, + Anum_pg_ts_template_tmplname, Anum_pg_ts_template_tmplnamespace, + InvalidAttrNumber, + InvalidAttrNumber, + -1, }, { TypeRelationId, TypeOidIndexId, TYPEOID, - Anum_pg_type_typnamespace + TYPENAMENSP, + Anum_pg_type_typname, + Anum_pg_type_typnamespace, + Anum_pg_type_typowner, + Anum_pg_type_typacl, + ACL_KIND_TYPE } }; @@ -1110,16 +1241,86 @@ get_object_namespace(const ObjectAddress *address) } /* + * Interfaces to reference fields of ObjectPropertyType + */ +Oid +get_object_oid_index(Oid class_id) +{ + ObjectPropertyType *prop = get_object_property_data(class_id); + return prop->oid_index_oid; +} + +int +get_object_catcache_oid(Oid class_id) +{ + ObjectPropertyType *prop = get_object_property_data(class_id); + return prop->oid_catcache_id; +} + +int +get_object_catcache_name(Oid class_id) +{ + ObjectPropertyType *prop = get_object_property_data(class_id); + return prop->name_catcache_id; +} + +AttrNumber +get_object_attnum_name(Oid class_id) +{ + ObjectPropertyType *prop = get_object_property_data(class_id); + return prop->attnum_name; +} + +AttrNumber +get_object_attnum_namespace(Oid class_id) +{ + ObjectPropertyType *prop = get_object_property_data(class_id); + return prop->attnum_namespace; +} + +AttrNumber +get_object_attnum_owner(Oid class_id) +{ + ObjectPropertyType *prop = get_object_property_data(class_id); + return prop->attnum_owner; +} + +AttrNumber +get_object_attnum_acl(Oid class_id) +{ + ObjectPropertyType *prop = get_object_property_data(class_id); + return prop->attnum_acl; +} + +AclObjectKind +get_object_aclkind(Oid class_id) +{ + ObjectPropertyType *prop = get_object_property_data(class_id); + return prop->acl_kind; +} + +/* * Find ObjectProperty structure by class_id. */ static ObjectPropertyType * get_object_property_data(Oid class_id) { + static ObjectPropertyType *prop_last = NULL; int index; + /* + * A shortcut when caller want to know multiple attribute number + * towards a particular object class. + */ + if (prop_last && prop_last->class_oid == class_id) + return prop_last; + for (index = 0; index < lengthof(ObjectProperty); index++) if (ObjectProperty[index].class_oid == class_id) + { + prop_last = &ObjectProperty[index]; return &ObjectProperty[index]; + } elog(ERROR, "unrecognized class id: %u", class_id); return NULL; /* not reached */ diff --git a/src/backend/catalog/pg_largeobject.c b/src/backend/catalog/pg_largeobject.c index 1e5de6a..1fe7e2e 100644 --- a/src/backend/catalog/pg_largeobject.c +++ b/src/backend/catalog/pg_largeobject.c @@ -139,108 +139,6 @@ LargeObjectDrop(Oid loid) } /* - * LargeObjectAlterOwner - * - * Implementation of ALTER LARGE OBJECT statement - */ -void -LargeObjectAlterOwner(Oid loid, Oid newOwnerId) -{ - Form_pg_largeobject_metadata form_lo_meta; - Relation pg_lo_meta; - ScanKeyData skey[1]; - SysScanDesc scan; - HeapTuple oldtup; - HeapTuple newtup; - - pg_lo_meta = heap_open(LargeObjectMetadataRelationId, - RowExclusiveLock); - - ScanKeyInit(&skey[0], - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(loid)); - - scan = systable_beginscan(pg_lo_meta, - LargeObjectMetadataOidIndexId, true, - SnapshotNow, 1, skey); - - oldtup = systable_getnext(scan); - if (!HeapTupleIsValid(oldtup)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("large object %u does not exist", loid))); - - form_lo_meta = (Form_pg_largeobject_metadata) GETSTRUCT(oldtup); - if (form_lo_meta->lomowner != newOwnerId) - { - Datum values[Natts_pg_largeobject_metadata]; - bool nulls[Natts_pg_largeobject_metadata]; - bool replaces[Natts_pg_largeobject_metadata]; - Acl *newAcl; - Datum aclDatum; - bool isnull; - - /* Superusers can always do it */ - if (!superuser()) - { - /* - * lo_compat_privileges is not checked here, because ALTER LARGE - * OBJECT ... OWNER did not exist at all prior to PostgreSQL 9.0. - * - * We must be the owner of the existing object. - */ - if (!pg_largeobject_ownercheck(loid, GetUserId())) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must be owner of large object %u", loid))); - - /* Must be able to become new owner */ - check_is_member_of_role(GetUserId(), newOwnerId); - } - - memset(values, 0, sizeof(values)); - memset(nulls, false, sizeof(nulls)); - memset(replaces, false, sizeof(nulls)); - - values[Anum_pg_largeobject_metadata_lomowner - 1] - = ObjectIdGetDatum(newOwnerId); - replaces[Anum_pg_largeobject_metadata_lomowner - 1] = true; - - /* - * Determine the modified ACL for the new owner. This is only - * necessary when the ACL is non-null. - */ - aclDatum = heap_getattr(oldtup, - Anum_pg_largeobject_metadata_lomacl, - RelationGetDescr(pg_lo_meta), &isnull); - if (!isnull) - { - newAcl = aclnewowner(DatumGetAclP(aclDatum), - form_lo_meta->lomowner, newOwnerId); - values[Anum_pg_largeobject_metadata_lomacl - 1] - = PointerGetDatum(newAcl); - replaces[Anum_pg_largeobject_metadata_lomacl - 1] = true; - } - - newtup = heap_modify_tuple(oldtup, RelationGetDescr(pg_lo_meta), - values, nulls, replaces); - - simple_heap_update(pg_lo_meta, &newtup->t_self, newtup); - CatalogUpdateIndexes(pg_lo_meta, newtup); - - heap_freetuple(newtup); - - /* Update owner dependency reference */ - changeDependencyOnOwner(LargeObjectRelationId, - loid, newOwnerId); - } - systable_endscan(scan); - - heap_close(pg_lo_meta, RowExclusiveLock); -} - -/* * LargeObjectExists * * We don't use the system cache for large object metadata, for fear of diff --git a/src/backend/catalog/pg_shdepend.c b/src/backend/catalog/pg_shdepend.c index a2bb9f5..de82e4e 100644 --- a/src/backend/catalog/pg_shdepend.c +++ b/src/backend/catalog/pg_shdepend.c @@ -1328,22 +1328,10 @@ shdepReassignOwned(List *roleids, Oid newrole) /* Issue the appropriate ALTER OWNER call */ switch (sdepForm->classid) { - case CollationRelationId: - AlterCollationOwner_oid(sdepForm->objid, newrole); - break; - - case ConversionRelationId: - AlterConversionOwner_oid(sdepForm->objid, newrole); - break; - case TypeRelationId: AlterTypeOwnerInternal(sdepForm->objid, newrole, true); break; - case OperatorRelationId: - AlterOperatorOwner_oid(sdepForm->objid, newrole); - break; - case NamespaceRelationId: AlterSchemaOwner_oid(sdepForm->objid, newrole); break; @@ -1358,18 +1346,6 @@ shdepReassignOwned(List *roleids, Oid newrole) ATExecChangeOwner(sdepForm->objid, newrole, true, AccessExclusiveLock); break; - case ProcedureRelationId: - AlterFunctionOwner_oid(sdepForm->objid, newrole); - break; - - case LanguageRelationId: - AlterLanguageOwner_oid(sdepForm->objid, newrole); - break; - - case LargeObjectRelationId: - LargeObjectAlterOwner(sdepForm->objid, newrole); - break; - case DefaultAclRelationId: /* @@ -1378,14 +1354,6 @@ shdepReassignOwned(List *roleids, Oid newrole) */ break; - case OperatorClassRelationId: - AlterOpClassOwner_oid(sdepForm->objid, newrole); - break; - - case OperatorFamilyRelationId: - AlterOpFamilyOwner_oid(sdepForm->objid, newrole); - break; - case ForeignServerRelationId: AlterForeignServerOwner_oid(sdepForm->objid, newrole); break; @@ -1394,8 +1362,33 @@ shdepReassignOwned(List *roleids, Oid newrole) AlterForeignDataWrapperOwner_oid(sdepForm->objid, newrole); break; + /* Generic alter owner cases */ + case CollationRelationId: + case ConversionRelationId: + case OperatorRelationId: + case ProcedureRelationId: + case LanguageRelationId: + case LargeObjectRelationId: + case OperatorFamilyRelationId: + case OperatorClassRelationId: case ExtensionRelationId: - AlterExtensionOwner_oid(sdepForm->objid, newrole); + { + Oid classId = sdepForm->classid; + Relation catalog; + + catalog = heap_open(classId, RowExclusiveLock); + + AlterObjectOwner(catalog, + get_object_oid_index(classId), + get_object_catcache_oid(classId), + sdepForm->objid, newrole, + get_object_attnum_owner(classId), + get_object_attnum_namespace(classId), + get_object_attnum_acl(classId), + get_object_aclkind(classId)); + + heap_close(catalog, NoLock); + } break; default: diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c index c0dcdf7..ef10495 100644 --- a/src/backend/commands/aggregatecmds.c +++ b/src/backend/commands/aggregatecmds.c @@ -205,79 +205,3 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters) transTypeId, /* transition data type */ initval); /* initial condition */ } - - -/* - * RenameAggregate - * Rename an aggregate. - */ -void -RenameAggregate(List *name, List *args, const char *newname) -{ - Oid procOid; - Oid namespaceOid; - HeapTuple tup; - Form_pg_proc procForm; - Relation rel; - AclResult aclresult; - - rel = heap_open(ProcedureRelationId, RowExclusiveLock); - - /* Look up function and make sure it's an aggregate */ - procOid = LookupAggNameTypeNames(name, args, false); - - tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(procOid)); - if (!HeapTupleIsValid(tup)) /* should not happen */ - elog(ERROR, "cache lookup failed for function %u", procOid); - procForm = (Form_pg_proc) GETSTRUCT(tup); - - namespaceOid = procForm->pronamespace; - - /* make sure the new name doesn't exist */ - if (SearchSysCacheExists3(PROCNAMEARGSNSP, - CStringGetDatum(newname), - PointerGetDatum(&procForm->proargtypes), - ObjectIdGetDatum(namespaceOid))) - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_FUNCTION), - errmsg("function %s already exists in schema \"%s\"", - funcname_signature_string(newname, - procForm->pronargs, - NIL, - procForm->proargtypes.values), - get_namespace_name(namespaceOid)))); - - /* must be owner */ - if (!pg_proc_ownercheck(procOid, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC, - NameListToString(name)); - - /* must have CREATE privilege on namespace */ - aclresult = pg_namespace_aclcheck(namespaceOid, GetUserId(), ACL_CREATE); - if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_NAMESPACE, - get_namespace_name(namespaceOid)); - - /* rename */ - namestrcpy(&(((Form_pg_proc) GETSTRUCT(tup))->proname), newname); - simple_heap_update(rel, &tup->t_self, tup); - CatalogUpdateIndexes(rel, tup); - - heap_close(rel, NoLock); - heap_freetuple(tup); -} - -/* - * Change aggregate owner - */ -void -AlterAggregateOwner(List *name, List *args, Oid newOwnerId) -{ - Oid procOid; - - /* Look up function and make sure it's an aggregate */ - procOid = LookupAggNameTypeNames(name, args, false); - - /* The rest is just like a function */ - AlterFunctionOwner_oid(procOid, newOwnerId); -} diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c index 4dd9927..665a790 100644 --- a/src/backend/commands/alter.c +++ b/src/backend/commands/alter.c @@ -14,6 +14,7 @@ */ #include "postgres.h" +#include "access/sysattr.h" #include "catalog/dependency.h" #include "catalog/indexing.h" #include "catalog/namespace.h" @@ -35,10 +36,166 @@ #include "miscadmin.h" #include "tcop/utility.h" #include "utils/builtins.h" +#include "utils/fmgroids.h" #include "utils/lsyscache.h" #include "utils/rel.h" #include "utils/syscache.h" +#include "utils/tqual.h" +/* + * AlterObjectRename + * + * Generic function to change the name of given object, for simple + * cases (won't tables, nor other cases where we need to do more + * than change the name column of a single catalog entry). + */ +static void +AlterObjectRename(ObjectType objtype, List *objname, List *objargs, + char *new_name) +{ + ObjectAddress address; + ObjectAddress address_new; + List *objname_new; + Relation catalog; + Relation relation; + Oid oidIndexId; + int oidCacheId; + AttrNumber Anum_name; + AttrNumber Anum_namespace; + HeapTuple oldtup; + HeapTuple newtup; + Datum datum; + bool isnull; + Oid namespaceId; + NameData namebuf; + AttrNumber nattrs; + Datum *values; + bool *nulls; + bool *replaces; + + /* Lookup class-id and object-id */ + address = get_object_address(objtype, objname, objargs, + &relation, + ShareUpdateExclusiveLock, false); + + catalog = heap_open(address.classId, RowExclusiveLock); + + oidIndexId = get_object_oid_index(address.classId); + oidCacheId = get_object_catcache_oid(address.classId); + Anum_name = get_object_attnum_name(address.classId); + Anum_namespace = get_object_attnum_namespace(address.classId); + + /* Fetch a catalog entry to be altered */ + if (oidCacheId > 0) + { + oldtup = SearchSysCacheCopy1(oidCacheId, + ObjectIdGetDatum(address.objectId)); + if (!HeapTupleIsValid(oldtup)) /* should not happen */ + elog(ERROR, "cache lookup failed for object %u of catalog \"%s\"", + address.objectId, RelationGetRelationName(catalog)); + } + else + { + SysScanDesc scan; + ScanKeyData skey; + + Assert(OidIsValid(oidIndexId)); + + ScanKeyInit(&skey, + ObjectIdAttributeNumber, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(address.objectId)); + + scan = systable_beginscan(catalog, oidIndexId, true, + SnapshotNow, 1, &skey); + oldtup = systable_getnext(scan); + if (!HeapTupleIsValid(oldtup)) + elog(ERROR, "cache lookup failed for object %u of catalog \"%s\"", + address.objectId, RelationGetRelationName(catalog)); + oldtup = heap_copytuple(oldtup); + + systable_endscan(scan); + } + + /* Fetch namespace if exists */ + if (Anum_namespace != InvalidAttrNumber) + { + datum = heap_getattr(oldtup, Anum_namespace, + RelationGetDescr(catalog), &isnull); + Assert(!isnull); + namespaceId = DatumGetObjectId(datum); + } + else + namespaceId = InvalidOid; + + /* Ensure the new name doesn't exist */ + Assert(list_length(objname) > 0); + objname_new = list_truncate(list_copy(objname), + list_length(objname) - 1); + objname_new = lappend(objname_new, makeString(new_name)); + + address_new = get_object_address(objtype, objname_new, objargs, + &relation, + ShareUpdateExclusiveLock, true); + if (OidIsValid(address_new.objectId)) + { + if (OidIsValid(namespaceId)) + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("%s already exists in schema \"%s\"", + getObjectDescription(&address_new), + get_namespace_name(namespaceId)))); + else + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("%s already exists", + getObjectDescription(&address_new)))); + } + + /* + * Must be owner of the target object + */ + check_object_ownership(GetUserId(), objtype, address, + objname, objargs, relation); + + /* + * Must have CREATE privilege on namespace + */ + if (OidIsValid(namespaceId)) + { + AclResult aclresult; + + aclresult = pg_namespace_aclcheck(namespaceId, + GetUserId(), ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, ACL_KIND_NAMESPACE, + get_namespace_name(namespaceId)); + } + + /* + * Construct an entry of catalog with new name + */ + nattrs = RelationGetNumberOfAttributes(catalog); + values = palloc0(nattrs * sizeof(Datum)); + nulls = palloc0(nattrs * sizeof(bool)); + replaces = palloc0(nattrs * sizeof(bool)); + namestrcpy(&namebuf, new_name); + values[Anum_name - 1] = NameGetDatum(&namebuf); + replaces[Anum_name - 1] = true; + newtup = heap_modify_tuple(oldtup, RelationGetDescr(catalog), + values, nulls, replaces); + + /* Perform actual update */ + simple_heap_update(catalog, &oldtup->t_self, newtup); + CatalogUpdateIndexes(catalog, newtup); + + heap_close(catalog, NoLock); + + /* Release memory */ + pfree(values); + pfree(nulls); + pfree(replaces); +} /* * Executes an ALTER OBJECT / RENAME TO statement. Based on the object @@ -49,50 +206,14 @@ ExecRenameStmt(RenameStmt *stmt) { switch (stmt->renameType) { - case OBJECT_AGGREGATE: - RenameAggregate(stmt->object, stmt->objarg, stmt->newname); - break; - - case OBJECT_COLLATION: - RenameCollation(stmt->object, stmt->newname); - break; - case OBJECT_CONSTRAINT: RenameConstraint(stmt); break; - case OBJECT_CONVERSION: - RenameConversion(stmt->object, stmt->newname); - break; - case OBJECT_DATABASE: RenameDatabase(stmt->subname, stmt->newname); break; - case OBJECT_FDW: - RenameForeignDataWrapper(stmt->subname, stmt->newname); - break; - - case OBJECT_FOREIGN_SERVER: - RenameForeignServer(stmt->subname, stmt->newname); - break; - - case OBJECT_FUNCTION: - RenameFunction(stmt->object, stmt->objarg, stmt->newname); - break; - - case OBJECT_LANGUAGE: - RenameLanguage(stmt->subname, stmt->newname); - break; - - case OBJECT_OPCLASS: - RenameOpClass(stmt->object, stmt->subname, stmt->newname); - break; - - case OBJECT_OPFAMILY: - RenameOpFamily(stmt->object, stmt->subname, stmt->newname); - break; - case OBJECT_ROLE: RenameRole(stmt->subname, stmt->newname); break; @@ -122,25 +243,28 @@ ExecRenameStmt(RenameStmt *stmt) renametrig(stmt); break; - case OBJECT_TSPARSER: - RenameTSParser(stmt->object, stmt->newname); + case OBJECT_DOMAIN: + case OBJECT_TYPE: + RenameType(stmt); break; + case OBJECT_AGGREGATE: + case OBJECT_COLLATION: + case OBJECT_CONVERSION: + case OBJECT_FDW: + case OBJECT_FOREIGN_SERVER: + case OBJECT_FUNCTION: + case OBJECT_LANGUAGE: + case OBJECT_OPCLASS: + case OBJECT_OPFAMILY: + case OBJECT_TSCONFIGURATION: case OBJECT_TSDICTIONARY: - RenameTSDictionary(stmt->object, stmt->newname); - break; - + case OBJECT_TSPARSER: case OBJECT_TSTEMPLATE: - RenameTSTemplate(stmt->object, stmt->newname); - break; - - case OBJECT_TSCONFIGURATION: - RenameTSConfiguration(stmt->object, stmt->newname); - break; - - case OBJECT_DOMAIN: - case OBJECT_TYPE: - RenameType(stmt); + AlterObjectRename(stmt->renameType, + stmt->object, + stmt->objarg, + stmt->newname); break; default: @@ -167,10 +291,6 @@ ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt) AlterCollationNamespace(stmt->object, stmt->newschema); break; - case OBJECT_CONVERSION: - AlterConversionNamespace(stmt->object, stmt->newschema); - break; - case OBJECT_EXTENSION: AlterExtensionNamespace(stmt->object, stmt->newschema); break; @@ -180,18 +300,6 @@ ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt) stmt->newschema); break; - case OBJECT_OPERATOR: - AlterOperatorNamespace(stmt->object, stmt->objarg, stmt->newschema); - break; - - case OBJECT_OPCLASS: - AlterOpClassNamespace(stmt->object, stmt->addname, stmt->newschema); - break; - - case OBJECT_OPFAMILY: - AlterOpFamilyNamespace(stmt->object, stmt->addname, stmt->newschema); - break; - case OBJECT_SEQUENCE: case OBJECT_TABLE: case OBJECT_VIEW: @@ -199,27 +307,51 @@ ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt) AlterTableNamespace(stmt); break; - case OBJECT_TSPARSER: - AlterTSParserNamespace(stmt->object, stmt->newschema); + case OBJECT_TYPE: + case OBJECT_DOMAIN: + AlterTypeNamespace(stmt->object, stmt->newschema, stmt->objectType); break; + /* generic code path */ + case OBJECT_CONVERSION: + case OBJECT_OPERATOR: + case OBJECT_OPCLASS: + case OBJECT_OPFAMILY: + case OBJECT_TSPARSER: case OBJECT_TSDICTIONARY: - AlterTSDictionaryNamespace(stmt->object, stmt->newschema); - break; - case OBJECT_TSTEMPLATE: - AlterTSTemplateNamespace(stmt->object, stmt->newschema); - break; - case OBJECT_TSCONFIGURATION: - AlterTSConfigurationNamespace(stmt->object, stmt->newschema); - break; - - case OBJECT_TYPE: - case OBJECT_DOMAIN: - AlterTypeNamespace(stmt->object, stmt->newschema, stmt->objectType); + { + Relation catalog; + Relation relation; + Oid classId; + Oid nspOid; + ObjectAddress address; + + address = get_object_address(stmt->objectType, + stmt->object, + stmt->objarg, + &relation, + ShareUpdateExclusiveLock, + false); + classId = address.classId; + + catalog = heap_open(classId, RowExclusiveLock); + + nspOid = LookupCreationNamespace(stmt->newschema); + + AlterObjectNamespace(catalog, + get_object_catcache_oid(classId), + get_object_catcache_name(classId), + address.objectId, nspOid, + get_object_attnum_name(classId), + get_object_attnum_namespace(classId), + get_object_attnum_owner(classId), + get_object_aclkind(classId)); + + heap_close(catalog, RowExclusiveLock); + } break; - default: elog(ERROR, "unrecognized AlterObjectSchemaStmt type: %d", (int) stmt->objectType); @@ -287,35 +419,28 @@ AlterObjectNamespace_oid(Oid classId, Oid objid, Oid nspOid) break; case OCLASS_CONVERSION: - oldNspOid = AlterConversionNamespace_oid(objid, nspOid); - break; - case OCLASS_OPERATOR: - oldNspOid = AlterOperatorNamespace_oid(objid, nspOid); - break; - case OCLASS_OPCLASS: - oldNspOid = AlterOpClassNamespace_oid(objid, nspOid); - break; - case OCLASS_OPFAMILY: - oldNspOid = AlterOpFamilyNamespace_oid(objid, nspOid); - break; - case OCLASS_TSPARSER: - oldNspOid = AlterTSParserNamespace_oid(objid, nspOid); - break; - case OCLASS_TSDICT: - oldNspOid = AlterTSDictionaryNamespace_oid(objid, nspOid); - break; - case OCLASS_TSTEMPLATE: - oldNspOid = AlterTSTemplateNamespace_oid(objid, nspOid); - break; - case OCLASS_TSCONFIG: - oldNspOid = AlterTSConfigurationNamespace_oid(objid, nspOid); + { + Relation catalog; + + catalog = heap_open(classId, RowExclusiveLock); + + AlterObjectNamespace(catalog, + get_object_catcache_oid(classId), + get_object_catcache_name(classId), + objid, nspOid, + get_object_attnum_name(classId), + get_object_attnum_namespace(classId), + get_object_attnum_owner(classId), + get_object_aclkind(classId)); + heap_close(catalog, RowExclusiveLock); + } break; default: @@ -460,82 +585,239 @@ ExecAlterOwnerStmt(AlterOwnerStmt *stmt) switch (stmt->objectType) { - case OBJECT_AGGREGATE: - AlterAggregateOwner(stmt->object, stmt->objarg, newowner); - break; - - case OBJECT_COLLATION: - AlterCollationOwner(stmt->object, newowner); - break; - - case OBJECT_CONVERSION: - AlterConversionOwner(stmt->object, newowner); - break; - case OBJECT_DATABASE: + /* its special code due to have_createdb_privilege() check */ AlterDatabaseOwner(strVal(linitial(stmt->object)), newowner); break; - case OBJECT_FUNCTION: - AlterFunctionOwner(stmt->object, stmt->objarg, newowner); - break; - - case OBJECT_LANGUAGE: - AlterLanguageOwner(strVal(linitial(stmt->object)), newowner); - break; - - case OBJECT_LARGEOBJECT: - LargeObjectAlterOwner(oidparse(linitial(stmt->object)), newowner); - break; - - case OBJECT_OPERATOR: - Assert(list_length(stmt->objarg) == 2); - AlterOperatorOwner(stmt->object, - (TypeName *) linitial(stmt->objarg), - (TypeName *) lsecond(stmt->objarg), - newowner); - break; - - case OBJECT_OPCLASS: - AlterOpClassOwner(stmt->object, stmt->addname, newowner); - break; - - case OBJECT_OPFAMILY: - AlterOpFamilyOwner(stmt->object, stmt->addname, newowner); - break; - case OBJECT_SCHEMA: + /* its special code due to CREATE permission check on database */ AlterSchemaOwner(strVal(linitial(stmt->object)), newowner); break; - case OBJECT_TABLESPACE: - AlterTableSpaceOwner(strVal(linitial(stmt->object)), newowner); - break; - case OBJECT_TYPE: case OBJECT_DOMAIN: /* same as TYPE */ AlterTypeOwner(stmt->object, newowner, stmt->objectType); break; - case OBJECT_TSDICTIONARY: - AlterTSDictionaryOwner(stmt->object, newowner); - break; - - case OBJECT_TSCONFIGURATION: - AlterTSConfigurationOwner(stmt->object, newowner); - break; - case OBJECT_FDW: + /* its special code due to USAGE permission check on FDW */ AlterForeignDataWrapperOwner(strVal(linitial(stmt->object)), newowner); break; case OBJECT_FOREIGN_SERVER: + /* its special code due to USAGE permission check on FDW */ AlterForeignServerOwner(strVal(linitial(stmt->object)), newowner); break; + /* Generic cases */ + case OBJECT_AGGREGATE: + case OBJECT_COLLATION: + case OBJECT_CONVERSION: + case OBJECT_FUNCTION: + case OBJECT_LANGUAGE: + case OBJECT_LARGEOBJECT: + case OBJECT_OPERATOR: + case OBJECT_OPCLASS: + case OBJECT_OPFAMILY: + case OBJECT_TABLESPACE: + case OBJECT_TSDICTIONARY: + case OBJECT_TSCONFIGURATION: + { + Relation catalog; + Relation relation; + Oid classId; + ObjectAddress address; + + address = get_object_address(stmt->objectType, + stmt->object, + stmt->objarg, + &relation, + ShareUpdateExclusiveLock, + false); + classId = address.classId; + + catalog = heap_open(address.classId, RowExclusiveLock); + + AlterObjectOwner(catalog, + get_object_oid_index(classId), + get_object_catcache_oid(classId), + address.objectId, + newowner, + get_object_attnum_owner(classId), + get_object_attnum_namespace(classId), + get_object_attnum_acl(classId), + get_object_aclkind(classId)); + + heap_close(catalog, NoLock); + } + break; + default: elog(ERROR, "unrecognized AlterOwnerStmt type: %d", (int) stmt->objectType); } } + +/* + * Generic function to change the ownership of a given object, for simple + * cases (won't tables, nor other cases where we need to do more than + * change the ownership column of a single catalog entry). + * + * catalog: catalog relation containing object (RowExclusiveLock'd by caller) + * oidCacheId: syscache that indexes this catalog by OID + * objectId: OID of object to change the ownership of + * new_ownerId: OID of new object owner + * Anum_owner: column number of catalog's owner column + * Anum_namespace: column number of catalog's namespace column, + * or InvalidAttrNumber if none. + * Anum_acl: column number of catalog's owner column, + * or InvalidAttrNumber if none. + * acl_kind: ACL type for object, or -1 if none assigned + * + * Returns the OID of the object's previous namespace + */ +Oid +AlterObjectOwner(Relation catalog, Oid oidIndexId, int oidCacheId, + Oid objectId, Oid new_ownerId, + AttrNumber Anum_owner, + AttrNumber Anum_namespace, + AttrNumber Anum_acl, + AclObjectKind aclkind) +{ + HeapTuple oldtup; + HeapTuple newtup; + Datum datum; + bool isnull; + Oid old_ownerId; + Oid namespaceId = InvalidOid; + + if (oidCacheId > 0) + { + oldtup = SearchSysCacheCopy1(oidCacheId, ObjectIdGetDatum(objectId)); + if (!HeapTupleIsValid(oldtup)) /* should not happen */ + elog(ERROR, "cache lookup failed for object %u of catalog \"%s\"", + objectId, RelationGetRelationName(catalog)); + } + else + { + SysScanDesc scan; + ScanKeyData skey; + + Assert(OidIsValid(oidIndexId)); + + ScanKeyInit(&skey, + ObjectIdAttributeNumber, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(objectId)); + + scan = systable_beginscan(catalog, oidIndexId, true, + SnapshotNow, 1, &skey); + + oldtup = systable_getnext(scan); + if (!HeapTupleIsValid(oldtup)) + elog(ERROR, "cache lookup failed for object %u of catalog \"%s\"", + objectId, RelationGetRelationName(catalog)); + oldtup = heap_copytuple(oldtup); + + systable_endscan(scan); + } + + datum = heap_getattr(oldtup, Anum_owner, + RelationGetDescr(catalog), &isnull); + Assert(!isnull); + old_ownerId = DatumGetObjectId(datum); + + if (Anum_namespace != InvalidAttrNumber) + { + datum = heap_getattr(oldtup, Anum_namespace, + RelationGetDescr(catalog), &isnull); + Assert(!isnull); + namespaceId = DatumGetObjectId(datum); + } + + if (old_ownerId != new_ownerId) + { + AttrNumber nattrs; + Datum *values; + bool *nulls; + bool *replaces; + + /* Superusers can bypass permission checks */ + if (!superuser()) + { + ObjectAddress address; + + address.classId = RelationGetRelid(catalog); + address.objectId = objectId; + address.objectSubId = 0; + + /* must be owner */ + if (!has_privs_of_role(GetUserId(), old_ownerId)) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("must be owner of %s", + getObjectDescription(&address)))); + + /* Must be able to become new owner */ + check_is_member_of_role(GetUserId(), new_ownerId); + + /* New owner must have CREATE privilege on namespace */ + if (OidIsValid(namespaceId)) + { + AclResult aclresult; + + aclresult = pg_namespace_aclcheck(namespaceId, new_ownerId, + ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, aclkind, + get_namespace_name(namespaceId)); + } + } + + /* Build a modified tuple */ + nattrs = RelationGetNumberOfAttributes(catalog); + values = palloc0(nattrs * sizeof(Datum)); + nulls = palloc0(nattrs * sizeof(bool)); + replaces = palloc0(nattrs * sizeof(bool)); + values[Anum_owner - 1] = ObjectIdGetDatum(new_ownerId); + replaces[Anum_owner - 1] = true; + + /* + * Determine the modified ACL for the new owner. This is only + * necessary when the ACL is non-null. + */ + if (Anum_acl != InvalidAttrNumber) + { + datum = heap_getattr(oldtup, + Anum_acl, RelationGetDescr(catalog), &isnull); + if (!isnull) + { + Acl *newAcl; + + newAcl = aclnewowner(DatumGetAclP(datum), + old_ownerId, new_ownerId); + values[Anum_acl - 1] = PointerGetDatum(newAcl); + replaces[Anum_acl - 1] = true; + } + } + + newtup = heap_modify_tuple(oldtup, RelationGetDescr(catalog), + values, nulls, replaces); + + /* Perform actual update */ + simple_heap_update(catalog, &newtup->t_self, newtup); + CatalogUpdateIndexes(catalog, newtup); + + /* Update owner dependency reference */ + changeDependencyOnOwner(RelationGetRelid(catalog), + HeapTupleGetOid(newtup), new_ownerId); + + /* Release memory */ + pfree(values); + pfree(nulls); + pfree(replaces); + } + return old_ownerId; +} diff --git a/src/backend/commands/collationcmds.c b/src/backend/commands/collationcmds.c index e574288..0655833 100644 --- a/src/backend/commands/collationcmds.c +++ b/src/backend/commands/collationcmds.c @@ -33,9 +33,6 @@ #include "utils/rel.h" #include "utils/syscache.h" -static void AlterCollationOwner_internal(Relation rel, Oid collationOid, - Oid newOwnerId); - /* * CREATE COLLATION */ @@ -145,170 +142,6 @@ DefineCollation(List *names, List *parameters) } /* - * Rename collation - */ -void -RenameCollation(List *name, const char *newname) -{ - Oid collationOid; - Oid namespaceOid; - HeapTuple tup; - Relation rel; - AclResult aclresult; - - rel = heap_open(CollationRelationId, RowExclusiveLock); - - collationOid = get_collation_oid(name, false); - - tup = SearchSysCacheCopy1(COLLOID, ObjectIdGetDatum(collationOid)); - if (!HeapTupleIsValid(tup)) /* should not happen */ - elog(ERROR, "cache lookup failed for collation %u", collationOid); - - namespaceOid = ((Form_pg_collation) GETSTRUCT(tup))->collnamespace; - - /* make sure the new name doesn't exist */ - if (SearchSysCacheExists3(COLLNAMEENCNSP, - CStringGetDatum(newname), - Int32GetDatum(GetDatabaseEncoding()), - ObjectIdGetDatum(namespaceOid))) - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_OBJECT), - errmsg("collation \"%s\" for encoding \"%s\" already exists in schema \"%s\"", - newname, - GetDatabaseEncodingName(), - get_namespace_name(namespaceOid)))); - - /* mustn't match an any-encoding entry, either */ - if (SearchSysCacheExists3(COLLNAMEENCNSP, - CStringGetDatum(newname), - Int32GetDatum(-1), - ObjectIdGetDatum(namespaceOid))) - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_OBJECT), - errmsg("collation \"%s\" already exists in schema \"%s\"", - newname, - get_namespace_name(namespaceOid)))); - - /* must be owner */ - if (!pg_collation_ownercheck(collationOid, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_COLLATION, - NameListToString(name)); - - /* must have CREATE privilege on namespace */ - aclresult = pg_namespace_aclcheck(namespaceOid, GetUserId(), ACL_CREATE); - if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_NAMESPACE, - get_namespace_name(namespaceOid)); - - /* rename */ - namestrcpy(&(((Form_pg_collation) GETSTRUCT(tup))->collname), newname); - simple_heap_update(rel, &tup->t_self, tup); - CatalogUpdateIndexes(rel, tup); - - heap_freetuple(tup); - - heap_close(rel, RowExclusiveLock); -} - -/* - * Change collation owner, by name - */ -void -AlterCollationOwner(List *name, Oid newOwnerId) -{ - Oid collationOid; - Relation rel; - - rel = heap_open(CollationRelationId, RowExclusiveLock); - - collationOid = get_collation_oid(name, false); - - AlterCollationOwner_internal(rel, collationOid, newOwnerId); - - heap_close(rel, RowExclusiveLock); -} - -/* - * Change collation owner, by oid - */ -void -AlterCollationOwner_oid(Oid collationOid, Oid newOwnerId) -{ - Relation rel; - - rel = heap_open(CollationRelationId, RowExclusiveLock); - - AlterCollationOwner_internal(rel, collationOid, newOwnerId); - - heap_close(rel, RowExclusiveLock); -} - -/* - * AlterCollationOwner_internal - * - * Internal routine for changing the owner. rel must be pg_collation, already - * open and suitably locked; it will not be closed. - */ -static void -AlterCollationOwner_internal(Relation rel, Oid collationOid, Oid newOwnerId) -{ - Form_pg_collation collForm; - HeapTuple tup; - - Assert(RelationGetRelid(rel) == CollationRelationId); - - tup = SearchSysCacheCopy1(COLLOID, ObjectIdGetDatum(collationOid)); - if (!HeapTupleIsValid(tup)) /* should not happen */ - elog(ERROR, "cache lookup failed for collation %u", collationOid); - - collForm = (Form_pg_collation) GETSTRUCT(tup); - - /* - * If the new owner is the same as the existing owner, consider the - * command to have succeeded. This is for dump restoration purposes. - */ - if (collForm->collowner != newOwnerId) - { - AclResult aclresult; - - /* Superusers can always do it */ - if (!superuser()) - { - /* Otherwise, must be owner of the existing object */ - if (!pg_collation_ownercheck(HeapTupleGetOid(tup), GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_COLLATION, - NameStr(collForm->collname)); - - /* Must be able to become new owner */ - check_is_member_of_role(GetUserId(), newOwnerId); - - /* New owner must have CREATE privilege on namespace */ - aclresult = pg_namespace_aclcheck(collForm->collnamespace, - newOwnerId, - ACL_CREATE); - if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_NAMESPACE, - get_namespace_name(collForm->collnamespace)); - } - - /* - * Modify the owner --- okay to scribble on tup because it's a copy - */ - collForm->collowner = newOwnerId; - - simple_heap_update(rel, &tup->t_self, tup); - - CatalogUpdateIndexes(rel, tup); - - /* Update owner dependency reference */ - changeDependencyOnOwner(CollationRelationId, collationOid, - newOwnerId); - } - - heap_freetuple(tup); -} - -/* * Execute ALTER COLLATION SET SCHEMA */ void diff --git a/src/backend/commands/conversioncmds.c b/src/backend/commands/conversioncmds.c index aad7e46..e745bb8 100644 --- a/src/backend/commands/conversioncmds.c +++ b/src/backend/commands/conversioncmds.c @@ -30,9 +30,6 @@ #include "utils/rel.h" #include "utils/syscache.h" -static void AlterConversionOwner_internal(Relation rel, Oid conversionOid, - Oid newOwnerId); - /* * CREATE CONVERSION */ @@ -116,202 +113,3 @@ CreateConversionCommand(CreateConversionStmt *stmt) ConversionCreate(conversion_name, namespaceId, GetUserId(), from_encoding, to_encoding, funcoid, stmt->def); } - -/* - * Rename conversion - */ -void -RenameConversion(List *name, const char *newname) -{ - Oid conversionOid; - Oid namespaceOid; - HeapTuple tup; - Relation rel; - AclResult aclresult; - - rel = heap_open(ConversionRelationId, RowExclusiveLock); - - conversionOid = get_conversion_oid(name, false); - - tup = SearchSysCacheCopy1(CONVOID, ObjectIdGetDatum(conversionOid)); - if (!HeapTupleIsValid(tup)) /* should not happen */ - elog(ERROR, "cache lookup failed for conversion %u", conversionOid); - - namespaceOid = ((Form_pg_conversion) GETSTRUCT(tup))->connamespace; - - /* make sure the new name doesn't exist */ - if (SearchSysCacheExists2(CONNAMENSP, - CStringGetDatum(newname), - ObjectIdGetDatum(namespaceOid))) - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_OBJECT), - errmsg("conversion \"%s\" already exists in schema \"%s\"", - newname, get_namespace_name(namespaceOid)))); - - /* must be owner */ - if (!pg_conversion_ownercheck(conversionOid, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION, - NameListToString(name)); - - /* must have CREATE privilege on namespace */ - aclresult = pg_namespace_aclcheck(namespaceOid, GetUserId(), ACL_CREATE); - if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_NAMESPACE, - get_namespace_name(namespaceOid)); - - /* rename */ - namestrcpy(&(((Form_pg_conversion) GETSTRUCT(tup))->conname), newname); - simple_heap_update(rel, &tup->t_self, tup); - CatalogUpdateIndexes(rel, tup); - - heap_close(rel, NoLock); - heap_freetuple(tup); -} - -/* - * Change conversion owner, by name - */ -void -AlterConversionOwner(List *name, Oid newOwnerId) -{ - Oid conversionOid; - Relation rel; - - rel = heap_open(ConversionRelationId, RowExclusiveLock); - - conversionOid = get_conversion_oid(name, false); - - AlterConversionOwner_internal(rel, conversionOid, newOwnerId); - - heap_close(rel, NoLock); -} - -/* - * Change conversion owner, by oid - */ -void -AlterConversionOwner_oid(Oid conversionOid, Oid newOwnerId) -{ - Relation rel; - - rel = heap_open(ConversionRelationId, RowExclusiveLock); - - AlterConversionOwner_internal(rel, conversionOid, newOwnerId); - - heap_close(rel, NoLock); -} - -/* - * AlterConversionOwner_internal - * - * Internal routine for changing the owner. rel must be pg_conversion, already - * open and suitably locked; it will not be closed. - */ -static void -AlterConversionOwner_internal(Relation rel, Oid conversionOid, Oid newOwnerId) -{ - Form_pg_conversion convForm; - HeapTuple tup; - - Assert(RelationGetRelid(rel) == ConversionRelationId); - - tup = SearchSysCacheCopy1(CONVOID, ObjectIdGetDatum(conversionOid)); - if (!HeapTupleIsValid(tup)) /* should not happen */ - elog(ERROR, "cache lookup failed for conversion %u", conversionOid); - - convForm = (Form_pg_conversion) GETSTRUCT(tup); - - /* - * If the new owner is the same as the existing owner, consider the - * command to have succeeded. This is for dump restoration purposes. - */ - if (convForm->conowner != newOwnerId) - { - AclResult aclresult; - - /* Superusers can always do it */ - if (!superuser()) - { - /* Otherwise, must be owner of the existing object */ - if (!pg_conversion_ownercheck(HeapTupleGetOid(tup), GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION, - NameStr(convForm->conname)); - - /* Must be able to become new owner */ - check_is_member_of_role(GetUserId(), newOwnerId); - - /* New owner must have CREATE privilege on namespace */ - aclresult = pg_namespace_aclcheck(convForm->connamespace, - newOwnerId, - ACL_CREATE); - if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_NAMESPACE, - get_namespace_name(convForm->connamespace)); - } - - /* - * Modify the owner --- okay to scribble on tup because it's a copy - */ - convForm->conowner = newOwnerId; - - simple_heap_update(rel, &tup->t_self, tup); - - CatalogUpdateIndexes(rel, tup); - - /* Update owner dependency reference */ - changeDependencyOnOwner(ConversionRelationId, conversionOid, - newOwnerId); - } - - heap_freetuple(tup); -} - -/* - * Execute ALTER CONVERSION SET SCHEMA - */ -void -AlterConversionNamespace(List *name, const char *newschema) -{ - Oid convOid, - nspOid; - Relation rel; - - rel = heap_open(ConversionRelationId, RowExclusiveLock); - - convOid = get_conversion_oid(name, false); - - /* get schema OID */ - nspOid = LookupCreationNamespace(newschema); - - AlterObjectNamespace(rel, CONVOID, CONNAMENSP, - convOid, nspOid, - Anum_pg_conversion_conname, - Anum_pg_conversion_connamespace, - Anum_pg_conversion_conowner, - ACL_KIND_CONVERSION); - - heap_close(rel, RowExclusiveLock); -} - -/* - * Change conversion schema, by oid - */ -Oid -AlterConversionNamespace_oid(Oid convOid, Oid newNspOid) -{ - Oid oldNspOid; - Relation rel; - - rel = heap_open(ConversionRelationId, RowExclusiveLock); - - oldNspOid = AlterObjectNamespace(rel, CONVOID, CONNAMENSP, - convOid, newNspOid, - Anum_pg_conversion_conname, - Anum_pg_conversion_connamespace, - Anum_pg_conversion_conowner, - ACL_KIND_CONVERSION); - - heap_close(rel, RowExclusiveLock); - - return oldNspOid; -} diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c index 5d6bc7a..cde3d60 100644 --- a/src/backend/commands/extension.c +++ b/src/backend/commands/extension.c @@ -2724,95 +2724,3 @@ ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt) if (relation != NULL) relation_close(relation, NoLock); } - -/* - * AlterExtensionOwner_internal - * - * Internal routine for changing the owner of an extension. rel must be - * pg_extension, already open and suitably locked; it will not be closed. - * - * Note that this only changes ownership of the extension itself; it doesn't - * change the ownership of objects it contains. Since this function is - * currently only called from REASSIGN OWNED, this restriction is okay because - * said objects would also be affected by our caller. But it's not enough for - * a full-fledged ALTER OWNER implementation, so beware. - */ -static void -AlterExtensionOwner_internal(Relation rel, Oid extensionOid, Oid newOwnerId) -{ - Form_pg_extension extForm; - HeapTuple tup; - SysScanDesc scandesc; - ScanKeyData entry[1]; - - Assert(RelationGetRelid(rel) == ExtensionRelationId); - - ScanKeyInit(&entry[0], - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(extensionOid)); - - scandesc = systable_beginscan(rel, ExtensionOidIndexId, true, - SnapshotNow, 1, entry); - - /* We assume that there can be at most one matching tuple */ - tup = systable_getnext(scandesc); - if (!HeapTupleIsValid(tup)) /* should not happen */ - elog(ERROR, "cache lookup failed for extension %u", extensionOid); - - tup = heap_copytuple(tup); - systable_endscan(scandesc); - - extForm = (Form_pg_extension) GETSTRUCT(tup); - - /* - * If the new owner is the same as the existing owner, consider the - * command to have succeeded. This is for dump restoration purposes. - */ - if (extForm->extowner != newOwnerId) - { - /* Superusers can always do it */ - if (!superuser()) - { - /* Otherwise, must be owner of the existing object */ - if (!pg_extension_ownercheck(HeapTupleGetOid(tup), GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_EXTENSION, - NameStr(extForm->extname)); - - /* Must be able to become new owner */ - check_is_member_of_role(GetUserId(), newOwnerId); - - /* no privilege checks on namespace are required */ - } - - /* - * Modify the owner --- okay to scribble on tup because it's a copy - */ - extForm->extowner = newOwnerId; - - simple_heap_update(rel, &tup->t_self, tup); - - CatalogUpdateIndexes(rel, tup); - - /* Update owner dependency reference */ - changeDependencyOnOwner(ExtensionRelationId, extensionOid, - newOwnerId); - } - - heap_freetuple(tup); -} - -/* - * Change extension owner, by OID - */ -void -AlterExtensionOwner_oid(Oid extensionOid, Oid newOwnerId) -{ - Relation rel; - - rel = heap_open(ExtensionRelationId, RowExclusiveLock); - - AlterExtensionOwner_internal(rel, extensionOid, newOwnerId); - - heap_close(rel, NoLock); -} diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c index 342ecc2..d358b32 100644 --- a/src/backend/commands/foreigncmds.c +++ b/src/backend/commands/foreigncmds.c @@ -199,83 +199,6 @@ GetUserOidFromMapping(const char *username, bool missing_ok) return get_role_oid(username, missing_ok); } - -/* - * Rename foreign-data wrapper - */ -void -RenameForeignDataWrapper(const char *oldname, const char *newname) -{ - HeapTuple tup; - Relation rel; - - rel = heap_open(ForeignDataWrapperRelationId, RowExclusiveLock); - - tup = SearchSysCacheCopy1(FOREIGNDATAWRAPPERNAME, CStringGetDatum(oldname)); - if (!HeapTupleIsValid(tup)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("foreign-data wrapper \"%s\" does not exist", oldname))); - - /* make sure the new name doesn't exist */ - if (SearchSysCacheExists1(FOREIGNDATAWRAPPERNAME, CStringGetDatum(newname))) - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_OBJECT), - errmsg("foreign-data wrapper \"%s\" already exists", newname))); - - /* must be owner of FDW */ - if (!pg_foreign_data_wrapper_ownercheck(HeapTupleGetOid(tup), GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FDW, - oldname); - - /* rename */ - namestrcpy(&(((Form_pg_foreign_data_wrapper) GETSTRUCT(tup))->fdwname), newname); - simple_heap_update(rel, &tup->t_self, tup); - CatalogUpdateIndexes(rel, tup); - - heap_close(rel, NoLock); - heap_freetuple(tup); -} - - -/* - * Rename foreign server - */ -void -RenameForeignServer(const char *oldname, const char *newname) -{ - HeapTuple tup; - Relation rel; - - rel = heap_open(ForeignServerRelationId, RowExclusiveLock); - - tup = SearchSysCacheCopy1(FOREIGNSERVERNAME, CStringGetDatum(oldname)); - if (!HeapTupleIsValid(tup)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("server \"%s\" does not exist", oldname))); - - /* make sure the new name doesn't exist */ - if (SearchSysCacheExists1(FOREIGNSERVERNAME, CStringGetDatum(newname))) - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_OBJECT), - errmsg("server \"%s\" already exists", newname))); - - /* must be owner of server */ - if (!pg_foreign_server_ownercheck(HeapTupleGetOid(tup), GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FOREIGN_SERVER, - oldname); - - /* rename */ - namestrcpy(&(((Form_pg_foreign_server) GETSTRUCT(tup))->srvname), newname); - simple_heap_update(rel, &tup->t_self, tup); - CatalogUpdateIndexes(rel, tup); - - heap_close(rel, NoLock); - heap_freetuple(tup); -} - - /* * Internal workhorse for changing a data wrapper's owner. * diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index 9ba6dd8..2f81d01 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -64,11 +64,6 @@ #include "utils/syscache.h" #include "utils/tqual.h" - -static void AlterFunctionOwner_internal(Relation rel, HeapTuple tup, - Oid newOwnerId); - - /* * Examine the RETURNS clause of the CREATE FUNCTION statement * and return information about it as *prorettype_p and *returnsSet. @@ -1047,206 +1042,6 @@ RemoveFunctionById(Oid funcOid) } } - -/* - * Rename function - */ -void -RenameFunction(List *name, List *argtypes, const char *newname) -{ - Oid procOid; - Oid namespaceOid; - HeapTuple tup; - Form_pg_proc procForm; - Relation rel; - AclResult aclresult; - - rel = heap_open(ProcedureRelationId, RowExclusiveLock); - - procOid = LookupFuncNameTypeNames(name, argtypes, false); - - tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(procOid)); - if (!HeapTupleIsValid(tup)) /* should not happen */ - elog(ERROR, "cache lookup failed for function %u", procOid); - procForm = (Form_pg_proc) GETSTRUCT(tup); - - if (procForm->proisagg) - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("\"%s\" is an aggregate function", - NameListToString(name)), - errhint("Use ALTER AGGREGATE to rename aggregate functions."))); - - namespaceOid = procForm->pronamespace; - - /* make sure the new name doesn't exist */ - if (SearchSysCacheExists3(PROCNAMEARGSNSP, - CStringGetDatum(newname), - PointerGetDatum(&procForm->proargtypes), - ObjectIdGetDatum(namespaceOid))) - { - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_FUNCTION), - errmsg("function %s already exists in schema \"%s\"", - funcname_signature_string(newname, - procForm->pronargs, - NIL, - procForm->proargtypes.values), - get_namespace_name(namespaceOid)))); - } - - /* must be owner */ - if (!pg_proc_ownercheck(procOid, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC, - NameListToString(name)); - - /* must have CREATE privilege on namespace */ - aclresult = pg_namespace_aclcheck(namespaceOid, GetUserId(), ACL_CREATE); - if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_NAMESPACE, - get_namespace_name(namespaceOid)); - - /* rename */ - namestrcpy(&(procForm->proname), newname); - simple_heap_update(rel, &tup->t_self, tup); - CatalogUpdateIndexes(rel, tup); - - heap_close(rel, NoLock); - heap_freetuple(tup); -} - -/* - * Change function owner by name and args - */ -void -AlterFunctionOwner(List *name, List *argtypes, Oid newOwnerId) -{ - Relation rel; - Oid procOid; - HeapTuple tup; - - rel = heap_open(ProcedureRelationId, RowExclusiveLock); - - procOid = LookupFuncNameTypeNames(name, argtypes, false); - - tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(procOid)); - if (!HeapTupleIsValid(tup)) /* should not happen */ - elog(ERROR, "cache lookup failed for function %u", procOid); - - if (((Form_pg_proc) GETSTRUCT(tup))->proisagg) - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("\"%s\" is an aggregate function", - NameListToString(name)), - errhint("Use ALTER AGGREGATE to change owner of aggregate functions."))); - - AlterFunctionOwner_internal(rel, tup, newOwnerId); - - heap_close(rel, NoLock); -} - -/* - * Change function owner by Oid - */ -void -AlterFunctionOwner_oid(Oid procOid, Oid newOwnerId) -{ - Relation rel; - HeapTuple tup; - - rel = heap_open(ProcedureRelationId, RowExclusiveLock); - - tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(procOid)); - if (!HeapTupleIsValid(tup)) /* should not happen */ - elog(ERROR, "cache lookup failed for function %u", procOid); - AlterFunctionOwner_internal(rel, tup, newOwnerId); - - heap_close(rel, NoLock); -} - -static void -AlterFunctionOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) -{ - Form_pg_proc procForm; - AclResult aclresult; - Oid procOid; - - Assert(RelationGetRelid(rel) == ProcedureRelationId); - Assert(tup->t_tableOid == ProcedureRelationId); - - procForm = (Form_pg_proc) GETSTRUCT(tup); - procOid = HeapTupleGetOid(tup); - - /* - * If the new owner is the same as the existing owner, consider the - * command to have succeeded. This is for dump restoration purposes. - */ - if (procForm->proowner != newOwnerId) - { - Datum repl_val[Natts_pg_proc]; - bool repl_null[Natts_pg_proc]; - bool repl_repl[Natts_pg_proc]; - Acl *newAcl; - Datum aclDatum; - bool isNull; - HeapTuple newtuple; - - /* Superusers can always do it */ - if (!superuser()) - { - /* Otherwise, must be owner of the existing object */ - if (!pg_proc_ownercheck(procOid, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC, - NameStr(procForm->proname)); - - /* Must be able to become new owner */ - check_is_member_of_role(GetUserId(), newOwnerId); - - /* New owner must have CREATE privilege on namespace */ - aclresult = pg_namespace_aclcheck(procForm->pronamespace, - newOwnerId, - ACL_CREATE); - if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_NAMESPACE, - get_namespace_name(procForm->pronamespace)); - } - - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - - repl_repl[Anum_pg_proc_proowner - 1] = true; - repl_val[Anum_pg_proc_proowner - 1] = ObjectIdGetDatum(newOwnerId); - - /* - * Determine the modified ACL for the new owner. This is only - * necessary when the ACL is non-null. - */ - aclDatum = SysCacheGetAttr(PROCOID, tup, - Anum_pg_proc_proacl, - &isNull); - if (!isNull) - { - newAcl = aclnewowner(DatumGetAclP(aclDatum), - procForm->proowner, newOwnerId); - repl_repl[Anum_pg_proc_proacl - 1] = true; - repl_val[Anum_pg_proc_proacl - 1] = PointerGetDatum(newAcl); - } - - newtuple = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val, - repl_null, repl_repl); - - simple_heap_update(rel, &newtuple->t_self, newtuple); - CatalogUpdateIndexes(rel, newtuple); - - heap_freetuple(newtuple); - - /* Update owner dependency reference */ - changeDependencyOnOwner(ProcedureRelationId, procOid, newOwnerId); - } - - ReleaseSysCache(tup); -} - /* * Implements the ALTER FUNCTION utility command (except for the * RENAME and OWNER clauses, which are handled as part of the generic diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c index f564244..4c9818e 100644 --- a/src/backend/commands/opclasscmds.c +++ b/src/backend/commands/opclasscmds.c @@ -80,11 +80,6 @@ static void dropOperators(List *opfamilyname, Oid amoid, Oid opfamilyoid, List *operators); static void dropProcedures(List *opfamilyname, Oid amoid, Oid opfamilyoid, List *procedures); -static void AlterOpClassOwner_internal(Relation rel, HeapTuple tuple, - Oid newOwnerId); -static void AlterOpFamilyOwner_internal(Relation rel, HeapTuple tuple, - Oid newOwnerId); - /* * OpFamilyCacheLookup @@ -1660,449 +1655,6 @@ RemoveAmProcEntryById(Oid entryOid) heap_close(rel, RowExclusiveLock); } - -/* - * Rename opclass - */ -void -RenameOpClass(List *name, const char *access_method, const char *newname) -{ - Oid opcOid; - Oid amOid; - Oid namespaceOid; - HeapTuple origtup; - HeapTuple tup; - Relation rel; - AclResult aclresult; - - amOid = get_am_oid(access_method, false); - - rel = heap_open(OperatorClassRelationId, RowExclusiveLock); - - /* Look up the opclass. */ - origtup = OpClassCacheLookup(amOid, name, false); - tup = heap_copytuple(origtup); - ReleaseSysCache(origtup); - opcOid = HeapTupleGetOid(tup); - namespaceOid = ((Form_pg_opclass) GETSTRUCT(tup))->opcnamespace; - - /* make sure the new name doesn't exist */ - if (SearchSysCacheExists3(CLAAMNAMENSP, - ObjectIdGetDatum(amOid), - CStringGetDatum(newname), - ObjectIdGetDatum(namespaceOid))) - { - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_OBJECT), - errmsg("operator class \"%s\" for access method \"%s\" already exists in schema \"%s\"", - newname, access_method, - get_namespace_name(namespaceOid)))); - } - - /* must be owner */ - if (!pg_opclass_ownercheck(opcOid, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPCLASS, - NameListToString(name)); - - /* must have CREATE privilege on namespace */ - aclresult = pg_namespace_aclcheck(namespaceOid, GetUserId(), ACL_CREATE); - if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_NAMESPACE, - get_namespace_name(namespaceOid)); - - /* rename */ - namestrcpy(&(((Form_pg_opclass) GETSTRUCT(tup))->opcname), newname); - simple_heap_update(rel, &tup->t_self, tup); - CatalogUpdateIndexes(rel, tup); - - heap_close(rel, NoLock); - heap_freetuple(tup); -} - -/* - * Rename opfamily - */ -void -RenameOpFamily(List *name, const char *access_method, const char *newname) -{ - Oid opfOid; - Oid amOid; - Oid namespaceOid; - char *schemaname; - char *opfname; - HeapTuple tup; - Relation rel; - AclResult aclresult; - - amOid = get_am_oid(access_method, false); - - rel = heap_open(OperatorFamilyRelationId, RowExclusiveLock); - - /* - * Look up the opfamily - */ - DeconstructQualifiedName(name, &schemaname, &opfname); - - if (schemaname) - { - namespaceOid = LookupExplicitNamespace(schemaname); - - tup = SearchSysCacheCopy3(OPFAMILYAMNAMENSP, - ObjectIdGetDatum(amOid), - PointerGetDatum(opfname), - ObjectIdGetDatum(namespaceOid)); - if (!HeapTupleIsValid(tup)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("operator family \"%s\" does not exist for access method \"%s\"", - opfname, access_method))); - - opfOid = HeapTupleGetOid(tup); - } - else - { - opfOid = OpfamilynameGetOpfid(amOid, opfname); - if (!OidIsValid(opfOid)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("operator family \"%s\" does not exist for access method \"%s\"", - opfname, access_method))); - - tup = SearchSysCacheCopy1(OPFAMILYOID, ObjectIdGetDatum(opfOid)); - if (!HeapTupleIsValid(tup)) /* should not happen */ - elog(ERROR, "cache lookup failed for opfamily %u", opfOid); - - namespaceOid = ((Form_pg_opfamily) GETSTRUCT(tup))->opfnamespace; - } - - /* make sure the new name doesn't exist */ - if (SearchSysCacheExists3(OPFAMILYAMNAMENSP, - ObjectIdGetDatum(amOid), - CStringGetDatum(newname), - ObjectIdGetDatum(namespaceOid))) - { - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_OBJECT), - errmsg("operator family \"%s\" for access method \"%s\" already exists in schema \"%s\"", - newname, access_method, - get_namespace_name(namespaceOid)))); - } - - /* must be owner */ - if (!pg_opfamily_ownercheck(opfOid, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPFAMILY, - NameListToString(name)); - - /* must have CREATE privilege on namespace */ - aclresult = pg_namespace_aclcheck(namespaceOid, GetUserId(), ACL_CREATE); - if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_NAMESPACE, - get_namespace_name(namespaceOid)); - - /* rename */ - namestrcpy(&(((Form_pg_opfamily) GETSTRUCT(tup))->opfname), newname); - simple_heap_update(rel, &tup->t_self, tup); - CatalogUpdateIndexes(rel, tup); - - heap_close(rel, NoLock); - heap_freetuple(tup); -} - -/* - * Change opclass owner by name - */ -void -AlterOpClassOwner(List *name, const char *access_method, Oid newOwnerId) -{ - Oid amOid; - Relation rel; - HeapTuple tup; - HeapTuple origtup; - - amOid = get_am_oid(access_method, false); - - rel = heap_open(OperatorClassRelationId, RowExclusiveLock); - - /* Look up the opclass. */ - origtup = OpClassCacheLookup(amOid, name, false); - tup = heap_copytuple(origtup); - ReleaseSysCache(origtup); - - AlterOpClassOwner_internal(rel, tup, newOwnerId); - - heap_freetuple(tup); - heap_close(rel, NoLock); -} - -/* - * Change operator class owner, specified by OID - */ -void -AlterOpClassOwner_oid(Oid opclassOid, Oid newOwnerId) -{ - HeapTuple tup; - Relation rel; - - rel = heap_open(OperatorClassRelationId, RowExclusiveLock); - - tup = SearchSysCacheCopy1(CLAOID, ObjectIdGetDatum(opclassOid)); - if (!HeapTupleIsValid(tup)) - elog(ERROR, "cache lookup failed for opclass %u", opclassOid); - - AlterOpClassOwner_internal(rel, tup, newOwnerId); - - heap_freetuple(tup); - heap_close(rel, NoLock); -} - -/* - * The first parameter is pg_opclass, opened and suitably locked. The second - * parameter is a copy of the tuple from pg_opclass we want to modify. - */ -static void -AlterOpClassOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) -{ - Oid namespaceOid; - AclResult aclresult; - Form_pg_opclass opcForm; - - Assert(tup->t_tableOid == OperatorClassRelationId); - Assert(RelationGetRelid(rel) == OperatorClassRelationId); - - opcForm = (Form_pg_opclass) GETSTRUCT(tup); - - namespaceOid = opcForm->opcnamespace; - - /* - * If the new owner is the same as the existing owner, consider the - * command to have succeeded. This is for dump restoration purposes. - */ - if (opcForm->opcowner != newOwnerId) - { - /* Superusers can always do it */ - if (!superuser()) - { - /* Otherwise, must be owner of the existing object */ - if (!pg_opclass_ownercheck(HeapTupleGetOid(tup), GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPCLASS, - NameStr(opcForm->opcname)); - - /* Must be able to become new owner */ - check_is_member_of_role(GetUserId(), newOwnerId); - - /* New owner must have CREATE privilege on namespace */ - aclresult = pg_namespace_aclcheck(namespaceOid, newOwnerId, - ACL_CREATE); - if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_NAMESPACE, - get_namespace_name(namespaceOid)); - } - - /* - * Modify the owner --- okay to scribble on tup because it's a copy - */ - opcForm->opcowner = newOwnerId; - - simple_heap_update(rel, &tup->t_self, tup); - - CatalogUpdateIndexes(rel, tup); - - /* Update owner dependency reference */ - changeDependencyOnOwner(OperatorClassRelationId, HeapTupleGetOid(tup), - newOwnerId); - } -} - -/* - * ALTER OPERATOR CLASS any_name USING access_method SET SCHEMA name - */ -void -AlterOpClassNamespace(List *name, char *access_method, const char *newschema) -{ - Oid amOid; - Relation rel; - Oid opclassOid; - Oid nspOid; - - amOid = get_am_oid(access_method, false); - - rel = heap_open(OperatorClassRelationId, RowExclusiveLock); - - /* Look up the opclass */ - opclassOid = get_opclass_oid(amOid, name, false); - - /* get schema OID */ - nspOid = LookupCreationNamespace(newschema); - - AlterObjectNamespace(rel, CLAOID, -1, - opclassOid, nspOid, - Anum_pg_opclass_opcname, - Anum_pg_opclass_opcnamespace, - Anum_pg_opclass_opcowner, - ACL_KIND_OPCLASS); - - heap_close(rel, RowExclusiveLock); -} - -Oid -AlterOpClassNamespace_oid(Oid opclassOid, Oid newNspOid) -{ - Oid oldNspOid; - Relation rel; - - rel = heap_open(OperatorClassRelationId, RowExclusiveLock); - - oldNspOid = - AlterObjectNamespace(rel, CLAOID, -1, - opclassOid, newNspOid, - Anum_pg_opclass_opcname, - Anum_pg_opclass_opcnamespace, - Anum_pg_opclass_opcowner, - ACL_KIND_OPCLASS); - - heap_close(rel, RowExclusiveLock); - - return oldNspOid; -} - -/* - * Change opfamily owner by name - */ -void -AlterOpFamilyOwner(List *name, const char *access_method, Oid newOwnerId) -{ - Oid amOid; - Relation rel; - HeapTuple tup; - char *opfname; - char *schemaname; - - amOid = get_am_oid(access_method, false); - - rel = heap_open(OperatorFamilyRelationId, RowExclusiveLock); - - /* - * Look up the opfamily - */ - DeconstructQualifiedName(name, &schemaname, &opfname); - - if (schemaname) - { - Oid namespaceOid; - - namespaceOid = LookupExplicitNamespace(schemaname); - - tup = SearchSysCacheCopy3(OPFAMILYAMNAMENSP, - ObjectIdGetDatum(amOid), - PointerGetDatum(opfname), - ObjectIdGetDatum(namespaceOid)); - if (!HeapTupleIsValid(tup)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("operator family \"%s\" does not exist for access method \"%s\"", - opfname, access_method))); - } - else - { - Oid opfOid; - - opfOid = OpfamilynameGetOpfid(amOid, opfname); - if (!OidIsValid(opfOid)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("operator family \"%s\" does not exist for access method \"%s\"", - opfname, access_method))); - - tup = SearchSysCacheCopy1(OPFAMILYOID, ObjectIdGetDatum(opfOid)); - if (!HeapTupleIsValid(tup)) /* should not happen */ - elog(ERROR, "cache lookup failed for opfamily %u", opfOid); - } - - AlterOpFamilyOwner_internal(rel, tup, newOwnerId); - - heap_freetuple(tup); - heap_close(rel, NoLock); -} - -/* - * Change operator family owner, specified by OID - */ -void -AlterOpFamilyOwner_oid(Oid opfamilyOid, Oid newOwnerId) -{ - HeapTuple tup; - Relation rel; - - rel = heap_open(OperatorFamilyRelationId, RowExclusiveLock); - - tup = SearchSysCacheCopy1(OPFAMILYOID, ObjectIdGetDatum(opfamilyOid)); - if (!HeapTupleIsValid(tup)) - elog(ERROR, "cache lookup failed for opfamily %u", opfamilyOid); - - AlterOpFamilyOwner_internal(rel, tup, newOwnerId); - - heap_freetuple(tup); - heap_close(rel, NoLock); -} - -/* - * The first parameter is pg_opfamily, opened and suitably locked. The second - * parameter is a copy of the tuple from pg_opfamily we want to modify. - */ -static void -AlterOpFamilyOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) -{ - Oid namespaceOid; - AclResult aclresult; - Form_pg_opfamily opfForm; - - Assert(tup->t_tableOid == OperatorFamilyRelationId); - Assert(RelationGetRelid(rel) == OperatorFamilyRelationId); - - opfForm = (Form_pg_opfamily) GETSTRUCT(tup); - - namespaceOid = opfForm->opfnamespace; - - /* - * If the new owner is the same as the existing owner, consider the - * command to have succeeded. This is for dump restoration purposes. - */ - if (opfForm->opfowner != newOwnerId) - { - /* Superusers can always do it */ - if (!superuser()) - { - /* Otherwise, must be owner of the existing object */ - if (!pg_opfamily_ownercheck(HeapTupleGetOid(tup), GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPFAMILY, - NameStr(opfForm->opfname)); - - /* Must be able to become new owner */ - check_is_member_of_role(GetUserId(), newOwnerId); - - /* New owner must have CREATE privilege on namespace */ - aclresult = pg_namespace_aclcheck(namespaceOid, newOwnerId, - ACL_CREATE); - if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_NAMESPACE, - get_namespace_name(namespaceOid)); - } - - /* - * Modify the owner --- okay to scribble on tup because it's a copy - */ - opfForm->opfowner = newOwnerId; - - simple_heap_update(rel, &tup->t_self, tup); - - CatalogUpdateIndexes(rel, tup); - - /* Update owner dependency reference */ - changeDependencyOnOwner(OperatorFamilyRelationId, HeapTupleGetOid(tup), - newOwnerId); - } -} - /* * get_am_oid - given an access method name, look up the OID * @@ -2121,55 +1673,3 @@ get_am_oid(const char *amname, bool missing_ok) errmsg("access method \"%s\" does not exist", amname))); return oid; } - -/* - * ALTER OPERATOR FAMILY any_name USING access_method SET SCHEMA name - */ -void -AlterOpFamilyNamespace(List *name, char *access_method, const char *newschema) -{ - Oid amOid; - Relation rel; - Oid opfamilyOid; - Oid nspOid; - - amOid = get_am_oid(access_method, false); - - rel = heap_open(OperatorFamilyRelationId, RowExclusiveLock); - - /* Look up the opfamily */ - opfamilyOid = get_opfamily_oid(amOid, name, false); - - /* get schema OID */ - nspOid = LookupCreationNamespace(newschema); - - AlterObjectNamespace(rel, OPFAMILYOID, -1, - opfamilyOid, nspOid, - Anum_pg_opfamily_opfname, - Anum_pg_opfamily_opfnamespace, - Anum_pg_opfamily_opfowner, - ACL_KIND_OPFAMILY); - - heap_close(rel, RowExclusiveLock); -} - -Oid -AlterOpFamilyNamespace_oid(Oid opfamilyOid, Oid newNspOid) -{ - Oid oldNspOid; - Relation rel; - - rel = heap_open(OperatorFamilyRelationId, RowExclusiveLock); - - oldNspOid = - AlterObjectNamespace(rel, OPFAMILYOID, -1, - opfamilyOid, newNspOid, - Anum_pg_opfamily_opfname, - Anum_pg_opfamily_opfnamespace, - Anum_pg_opfamily_opfowner, - ACL_KIND_OPFAMILY); - - heap_close(rel, RowExclusiveLock); - - return oldNspOid; -} diff --git a/src/backend/commands/operatorcmds.c b/src/backend/commands/operatorcmds.c index 410c708..16f66c4 100644 --- a/src/backend/commands/operatorcmds.c +++ b/src/backend/commands/operatorcmds.c @@ -50,9 +50,6 @@ #include "utils/rel.h" #include "utils/syscache.h" - -static void AlterOperatorOwner_internal(Relation rel, Oid operOid, Oid newOwnerId); - /* * DefineOperator * this function extracts all the information from the @@ -332,146 +329,3 @@ RemoveOperatorById(Oid operOid) heap_close(relation, RowExclusiveLock); } - -void -AlterOperatorOwner_oid(Oid operOid, Oid newOwnerId) -{ - Relation rel; - - rel = heap_open(OperatorRelationId, RowExclusiveLock); - - AlterOperatorOwner_internal(rel, operOid, newOwnerId); - - heap_close(rel, NoLock); -} - -/* - * change operator owner - */ -void -AlterOperatorOwner(List *name, TypeName *typeName1, TypeName *typeName2, - Oid newOwnerId) -{ - Oid operOid; - Relation rel; - - rel = heap_open(OperatorRelationId, RowExclusiveLock); - - operOid = LookupOperNameTypeNames(NULL, name, - typeName1, typeName2, - false, -1); - - AlterOperatorOwner_internal(rel, operOid, newOwnerId); - - heap_close(rel, NoLock); -} - -static void -AlterOperatorOwner_internal(Relation rel, Oid operOid, Oid newOwnerId) -{ - HeapTuple tup; - AclResult aclresult; - Form_pg_operator oprForm; - - Assert(RelationGetRelid(rel) == OperatorRelationId); - - tup = SearchSysCacheCopy1(OPEROID, ObjectIdGetDatum(operOid)); - if (!HeapTupleIsValid(tup)) /* should not happen */ - elog(ERROR, "cache lookup failed for operator %u", operOid); - - oprForm = (Form_pg_operator) GETSTRUCT(tup); - - /* - * If the new owner is the same as the existing owner, consider the - * command to have succeeded. This is for dump restoration purposes. - */ - if (oprForm->oprowner != newOwnerId) - { - /* Superusers can always do it */ - if (!superuser()) - { - /* Otherwise, must be owner of the existing object */ - if (!pg_oper_ownercheck(operOid, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPER, - NameStr(oprForm->oprname)); - - /* Must be able to become new owner */ - check_is_member_of_role(GetUserId(), newOwnerId); - - /* New owner must have CREATE privilege on namespace */ - aclresult = pg_namespace_aclcheck(oprForm->oprnamespace, - newOwnerId, - ACL_CREATE); - if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_NAMESPACE, - get_namespace_name(oprForm->oprnamespace)); - } - - /* - * Modify the owner --- okay to scribble on tup because it's a copy - */ - oprForm->oprowner = newOwnerId; - - simple_heap_update(rel, &tup->t_self, tup); - - CatalogUpdateIndexes(rel, tup); - - /* Update owner dependency reference */ - changeDependencyOnOwner(OperatorRelationId, operOid, newOwnerId); - } - - heap_freetuple(tup); -} - -/* - * Execute ALTER OPERATOR SET SCHEMA - */ -void -AlterOperatorNamespace(List *names, List *argtypes, const char *newschema) -{ - List *operatorName = names; - TypeName *typeName1 = (TypeName *) linitial(argtypes); - TypeName *typeName2 = (TypeName *) lsecond(argtypes); - Oid operOid, - nspOid; - Relation rel; - - rel = heap_open(OperatorRelationId, RowExclusiveLock); - - Assert(list_length(argtypes) == 2); - operOid = LookupOperNameTypeNames(NULL, operatorName, - typeName1, typeName2, - false, -1); - - /* get schema OID */ - nspOid = LookupCreationNamespace(newschema); - - AlterObjectNamespace(rel, OPEROID, -1, - operOid, nspOid, - Anum_pg_operator_oprname, - Anum_pg_operator_oprnamespace, - Anum_pg_operator_oprowner, - ACL_KIND_OPER); - - heap_close(rel, RowExclusiveLock); -} - -Oid -AlterOperatorNamespace_oid(Oid operOid, Oid newNspOid) -{ - Oid oldNspOid; - Relation rel; - - rel = heap_open(OperatorRelationId, RowExclusiveLock); - - oldNspOid = AlterObjectNamespace(rel, OPEROID, -1, - operOid, newNspOid, - Anum_pg_operator_oprname, - Anum_pg_operator_oprnamespace, - Anum_pg_operator_oprowner, - ACL_KIND_OPER); - - heap_close(rel, RowExclusiveLock); - - return oldNspOid; -} diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c index 354389c..9d28588 100644 --- a/src/backend/commands/proclang.c +++ b/src/backend/commands/proclang.c @@ -54,9 +54,6 @@ static void create_proc_lang(const char *languageName, bool replace, Oid languageOwner, Oid handlerOid, Oid inlineOid, Oid valOid, bool trusted); static PLTemplate *find_language_template(const char *languageName); -static void AlterLanguageOwner_internal(HeapTuple tup, Relation rel, - Oid newOwnerId); - /* --------------------------------------------------------------------- * CREATE PROCEDURAL LANGUAGE @@ -537,157 +534,6 @@ DropProceduralLanguageById(Oid langOid) } /* - * Rename language - */ -void -RenameLanguage(const char *oldname, const char *newname) -{ - HeapTuple tup; - Relation rel; - - rel = heap_open(LanguageRelationId, RowExclusiveLock); - - tup = SearchSysCacheCopy1(LANGNAME, CStringGetDatum(oldname)); - if (!HeapTupleIsValid(tup)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("language \"%s\" does not exist", oldname))); - - /* make sure the new name doesn't exist */ - if (SearchSysCacheExists1(LANGNAME, CStringGetDatum(newname))) - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_OBJECT), - errmsg("language \"%s\" already exists", newname))); - - /* must be owner of PL */ - if (!pg_language_ownercheck(HeapTupleGetOid(tup), GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_LANGUAGE, - oldname); - - /* rename */ - namestrcpy(&(((Form_pg_language) GETSTRUCT(tup))->lanname), newname); - simple_heap_update(rel, &tup->t_self, tup); - CatalogUpdateIndexes(rel, tup); - - heap_close(rel, NoLock); - heap_freetuple(tup); -} - -/* - * Change language owner - */ -void -AlterLanguageOwner(const char *name, Oid newOwnerId) -{ - HeapTuple tup; - Relation rel; - - rel = heap_open(LanguageRelationId, RowExclusiveLock); - - tup = SearchSysCache1(LANGNAME, CStringGetDatum(name)); - if (!HeapTupleIsValid(tup)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("language \"%s\" does not exist", name))); - - AlterLanguageOwner_internal(tup, rel, newOwnerId); - - ReleaseSysCache(tup); - - heap_close(rel, RowExclusiveLock); - -} - -/* - * Change language owner, specified by OID - */ -void -AlterLanguageOwner_oid(Oid oid, Oid newOwnerId) -{ - HeapTuple tup; - Relation rel; - - rel = heap_open(LanguageRelationId, RowExclusiveLock); - - tup = SearchSysCache1(LANGOID, ObjectIdGetDatum(oid)); - if (!HeapTupleIsValid(tup)) - elog(ERROR, "cache lookup failed for language %u", oid); - - AlterLanguageOwner_internal(tup, rel, newOwnerId); - - ReleaseSysCache(tup); - - heap_close(rel, RowExclusiveLock); -} - -/* - * Workhorse for AlterLanguageOwner variants - */ -static void -AlterLanguageOwner_internal(HeapTuple tup, Relation rel, Oid newOwnerId) -{ - Form_pg_language lanForm; - - lanForm = (Form_pg_language) GETSTRUCT(tup); - - /* - * If the new owner is the same as the existing owner, consider the - * command to have succeeded. This is for dump restoration purposes. - */ - if (lanForm->lanowner != newOwnerId) - { - Datum repl_val[Natts_pg_language]; - bool repl_null[Natts_pg_language]; - bool repl_repl[Natts_pg_language]; - Acl *newAcl; - Datum aclDatum; - bool isNull; - HeapTuple newtuple; - - /* Otherwise, must be owner of the existing object */ - if (!pg_language_ownercheck(HeapTupleGetOid(tup), GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_LANGUAGE, - NameStr(lanForm->lanname)); - - /* Must be able to become new owner */ - check_is_member_of_role(GetUserId(), newOwnerId); - - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - - repl_repl[Anum_pg_language_lanowner - 1] = true; - repl_val[Anum_pg_language_lanowner - 1] = ObjectIdGetDatum(newOwnerId); - - /* - * Determine the modified ACL for the new owner. This is only - * necessary when the ACL is non-null. - */ - aclDatum = SysCacheGetAttr(LANGNAME, tup, - Anum_pg_language_lanacl, - &isNull); - if (!isNull) - { - newAcl = aclnewowner(DatumGetAclP(aclDatum), - lanForm->lanowner, newOwnerId); - repl_repl[Anum_pg_language_lanacl - 1] = true; - repl_val[Anum_pg_language_lanacl - 1] = PointerGetDatum(newAcl); - } - - newtuple = heap_modify_tuple(tup, RelationGetDescr(rel), - repl_val, repl_null, repl_repl); - - simple_heap_update(rel, &newtuple->t_self, newtuple); - CatalogUpdateIndexes(rel, newtuple); - - heap_freetuple(newtuple); - - /* Update owner dependency reference */ - changeDependencyOnOwner(LanguageRelationId, HeapTupleGetOid(tup), - newOwnerId); - } -} - -/* * get_language_oid - given a language name, look up the OID * * If missing_ok is false, throw an error if language name not found. If diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c index da9cb2f..75ed118 100644 --- a/src/backend/commands/tablespace.c +++ b/src/backend/commands/tablespace.c @@ -883,105 +883,6 @@ RenameTableSpace(const char *oldname, const char *newname) } /* - * Change tablespace owner - */ -void -AlterTableSpaceOwner(const char *name, Oid newOwnerId) -{ - Relation rel; - ScanKeyData entry[1]; - HeapScanDesc scandesc; - Form_pg_tablespace spcForm; - HeapTuple tup; - - /* Search pg_tablespace */ - rel = heap_open(TableSpaceRelationId, RowExclusiveLock); - - ScanKeyInit(&entry[0], - Anum_pg_tablespace_spcname, - BTEqualStrategyNumber, F_NAMEEQ, - CStringGetDatum(name)); - scandesc = heap_beginscan(rel, SnapshotNow, 1, entry); - tup = heap_getnext(scandesc, ForwardScanDirection); - if (!HeapTupleIsValid(tup)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("tablespace \"%s\" does not exist", name))); - - spcForm = (Form_pg_tablespace) GETSTRUCT(tup); - - /* - * If the new owner is the same as the existing owner, consider the - * command to have succeeded. This is for dump restoration purposes. - */ - if (spcForm->spcowner != newOwnerId) - { - Datum repl_val[Natts_pg_tablespace]; - bool repl_null[Natts_pg_tablespace]; - bool repl_repl[Natts_pg_tablespace]; - Acl *newAcl; - Datum aclDatum; - bool isNull; - HeapTuple newtuple; - - /* Otherwise, must be owner of the existing object */ - if (!pg_tablespace_ownercheck(HeapTupleGetOid(tup), GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TABLESPACE, - name); - - /* Must be able to become new owner */ - check_is_member_of_role(GetUserId(), newOwnerId); - - /* - * Normally we would also check for create permissions here, but there - * are none for tablespaces so we follow what rename tablespace does - * and omit the create permissions check. - * - * NOTE: Only superusers may create tablespaces to begin with and so - * initially only a superuser would be able to change its ownership - * anyway. - */ - - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - - repl_repl[Anum_pg_tablespace_spcowner - 1] = true; - repl_val[Anum_pg_tablespace_spcowner - 1] = ObjectIdGetDatum(newOwnerId); - - /* - * Determine the modified ACL for the new owner. This is only - * necessary when the ACL is non-null. - */ - aclDatum = heap_getattr(tup, - Anum_pg_tablespace_spcacl, - RelationGetDescr(rel), - &isNull); - if (!isNull) - { - newAcl = aclnewowner(DatumGetAclP(aclDatum), - spcForm->spcowner, newOwnerId); - repl_repl[Anum_pg_tablespace_spcacl - 1] = true; - repl_val[Anum_pg_tablespace_spcacl - 1] = PointerGetDatum(newAcl); - } - - newtuple = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val, repl_null, repl_repl); - - simple_heap_update(rel, &newtuple->t_self, newtuple); - CatalogUpdateIndexes(rel, newtuple); - - heap_freetuple(newtuple); - - /* Update owner dependency reference */ - changeDependencyOnOwner(TableSpaceRelationId, HeapTupleGetOid(tup), - newOwnerId); - } - - heap_endscan(scandesc); - heap_close(rel, NoLock); -} - - -/* * Alter table space options */ void diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c index 86cb870..2f3d7b5 100644 --- a/src/backend/commands/tsearchcmds.c +++ b/src/backend/commands/tsearchcmds.c @@ -302,95 +302,6 @@ RemoveTSParserById(Oid prsId) heap_close(relation, RowExclusiveLock); } -/* - * ALTER TEXT SEARCH PARSER RENAME - */ -void -RenameTSParser(List *oldname, const char *newname) -{ - HeapTuple tup; - Relation rel; - Oid prsId; - Oid namespaceOid; - - if (!superuser()) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must be superuser to rename text search parsers"))); - - rel = heap_open(TSParserRelationId, RowExclusiveLock); - - prsId = get_ts_parser_oid(oldname, false); - - tup = SearchSysCacheCopy1(TSPARSEROID, ObjectIdGetDatum(prsId)); - - if (!HeapTupleIsValid(tup)) /* should not happen */ - elog(ERROR, "cache lookup failed for text search parser %u", prsId); - - namespaceOid = ((Form_pg_ts_parser) GETSTRUCT(tup))->prsnamespace; - - if (SearchSysCacheExists2(TSPARSERNAMENSP, - PointerGetDatum(newname), - ObjectIdGetDatum(namespaceOid))) - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_OBJECT), - errmsg("text search parser \"%s\" already exists", - newname))); - - namestrcpy(&(((Form_pg_ts_parser) GETSTRUCT(tup))->prsname), newname); - simple_heap_update(rel, &tup->t_self, tup); - CatalogUpdateIndexes(rel, tup); - - heap_close(rel, NoLock); - heap_freetuple(tup); -} - -/* - * ALTER TEXT SEARCH PARSER any_name SET SCHEMA name - */ -void -AlterTSParserNamespace(List *name, const char *newschema) -{ - Oid prsId, - nspOid; - Relation rel; - - rel = heap_open(TSParserRelationId, RowExclusiveLock); - - prsId = get_ts_parser_oid(name, false); - - /* get schema OID */ - nspOid = LookupCreationNamespace(newschema); - - AlterObjectNamespace(rel, TSPARSEROID, TSPARSERNAMENSP, - prsId, nspOid, - Anum_pg_ts_parser_prsname, - Anum_pg_ts_parser_prsnamespace, - -1, -1); - - heap_close(rel, RowExclusiveLock); -} - -Oid -AlterTSParserNamespace_oid(Oid prsId, Oid newNspOid) -{ - Oid oldNspOid; - Relation rel; - - rel = heap_open(TSParserRelationId, RowExclusiveLock); - - oldNspOid = - AlterObjectNamespace(rel, TSPARSEROID, TSPARSERNAMENSP, - prsId, newNspOid, - Anum_pg_ts_parser_prsname, - Anum_pg_ts_parser_prsnamespace, - -1, -1); - - heap_close(rel, RowExclusiveLock); - - return oldNspOid; -} - /* ---------------------- TS Dictionary commands -----------------------*/ /* @@ -574,105 +485,6 @@ DefineTSDictionary(List *names, List *parameters) } /* - * ALTER TEXT SEARCH DICTIONARY RENAME - */ -void -RenameTSDictionary(List *oldname, const char *newname) -{ - HeapTuple tup; - Relation rel; - Oid dictId; - Oid namespaceOid; - AclResult aclresult; - - rel = heap_open(TSDictionaryRelationId, RowExclusiveLock); - - dictId = get_ts_dict_oid(oldname, false); - - tup = SearchSysCacheCopy1(TSDICTOID, ObjectIdGetDatum(dictId)); - - if (!HeapTupleIsValid(tup)) /* should not happen */ - elog(ERROR, "cache lookup failed for text search dictionary %u", - dictId); - - namespaceOid = ((Form_pg_ts_dict) GETSTRUCT(tup))->dictnamespace; - - if (SearchSysCacheExists2(TSDICTNAMENSP, - PointerGetDatum(newname), - ObjectIdGetDatum(namespaceOid))) - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_OBJECT), - errmsg("text search dictionary \"%s\" already exists", - newname))); - - /* must be owner */ - if (!pg_ts_dict_ownercheck(dictId, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSDICTIONARY, - NameListToString(oldname)); - - /* must have CREATE privilege on namespace */ - aclresult = pg_namespace_aclcheck(namespaceOid, GetUserId(), ACL_CREATE); - if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_NAMESPACE, - get_namespace_name(namespaceOid)); - - namestrcpy(&(((Form_pg_ts_dict) GETSTRUCT(tup))->dictname), newname); - simple_heap_update(rel, &tup->t_self, tup); - CatalogUpdateIndexes(rel, tup); - - heap_close(rel, NoLock); - heap_freetuple(tup); -} - -/* - * ALTER TEXT SEARCH DICTIONARY any_name SET SCHEMA name - */ -void -AlterTSDictionaryNamespace(List *name, const char *newschema) -{ - Oid dictId, - nspOid; - Relation rel; - - rel = heap_open(TSDictionaryRelationId, RowExclusiveLock); - - dictId = get_ts_dict_oid(name, false); - - /* get schema OID */ - nspOid = LookupCreationNamespace(newschema); - - AlterObjectNamespace(rel, TSDICTOID, TSDICTNAMENSP, - dictId, nspOid, - Anum_pg_ts_dict_dictname, - Anum_pg_ts_dict_dictnamespace, - Anum_pg_ts_dict_dictowner, - ACL_KIND_TSDICTIONARY); - - heap_close(rel, RowExclusiveLock); -} - -Oid -AlterTSDictionaryNamespace_oid(Oid dictId, Oid newNspOid) -{ - Oid oldNspOid; - Relation rel; - - rel = heap_open(TSDictionaryRelationId, RowExclusiveLock); - - oldNspOid = - AlterObjectNamespace(rel, TSDICTOID, TSDICTNAMENSP, - dictId, newNspOid, - Anum_pg_ts_dict_dictname, - Anum_pg_ts_dict_dictnamespace, - Anum_pg_ts_dict_dictowner, - ACL_KIND_TSDICTIONARY); - - heap_close(rel, RowExclusiveLock); - - return oldNspOid; -} - -/* * Guts of TS dictionary deletion. */ void @@ -809,66 +621,6 @@ AlterTSDictionary(AlterTSDictionaryStmt *stmt) heap_close(rel, RowExclusiveLock); } -/* - * ALTER TEXT SEARCH DICTIONARY OWNER - */ -void -AlterTSDictionaryOwner(List *name, Oid newOwnerId) -{ - HeapTuple tup; - Relation rel; - Oid dictId; - Oid namespaceOid; - AclResult aclresult; - Form_pg_ts_dict form; - - rel = heap_open(TSDictionaryRelationId, RowExclusiveLock); - - dictId = get_ts_dict_oid(name, false); - - tup = SearchSysCacheCopy1(TSDICTOID, ObjectIdGetDatum(dictId)); - - if (!HeapTupleIsValid(tup)) /* should not happen */ - elog(ERROR, "cache lookup failed for text search dictionary %u", - dictId); - - form = (Form_pg_ts_dict) GETSTRUCT(tup); - namespaceOid = form->dictnamespace; - - if (form->dictowner != newOwnerId) - { - /* Superusers can always do it */ - if (!superuser()) - { - /* must be owner */ - if (!pg_ts_dict_ownercheck(dictId, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSDICTIONARY, - NameListToString(name)); - - /* Must be able to become new owner */ - check_is_member_of_role(GetUserId(), newOwnerId); - - /* New owner must have CREATE privilege on namespace */ - aclresult = pg_namespace_aclcheck(namespaceOid, newOwnerId, ACL_CREATE); - if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_NAMESPACE, - get_namespace_name(namespaceOid)); - } - - form->dictowner = newOwnerId; - - simple_heap_update(rel, &tup->t_self, tup); - CatalogUpdateIndexes(rel, tup); - - /* Update owner dependency reference */ - changeDependencyOnOwner(TSDictionaryRelationId, HeapTupleGetOid(tup), - newOwnerId); - } - - heap_close(rel, NoLock); - heap_freetuple(tup); -} - /* ---------------------- TS Template commands -----------------------*/ /* @@ -1046,96 +798,6 @@ DefineTSTemplate(List *names, List *parameters) } /* - * ALTER TEXT SEARCH TEMPLATE RENAME - */ -void -RenameTSTemplate(List *oldname, const char *newname) -{ - HeapTuple tup; - Relation rel; - Oid tmplId; - Oid namespaceOid; - - if (!superuser()) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must be superuser to rename text search templates"))); - - rel = heap_open(TSTemplateRelationId, RowExclusiveLock); - - tmplId = get_ts_template_oid(oldname, false); - - tup = SearchSysCacheCopy1(TSTEMPLATEOID, ObjectIdGetDatum(tmplId)); - - if (!HeapTupleIsValid(tup)) /* should not happen */ - elog(ERROR, "cache lookup failed for text search template %u", - tmplId); - - namespaceOid = ((Form_pg_ts_template) GETSTRUCT(tup))->tmplnamespace; - - if (SearchSysCacheExists2(TSTEMPLATENAMENSP, - PointerGetDatum(newname), - ObjectIdGetDatum(namespaceOid))) - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_OBJECT), - errmsg("text search template \"%s\" already exists", - newname))); - - namestrcpy(&(((Form_pg_ts_template) GETSTRUCT(tup))->tmplname), newname); - simple_heap_update(rel, &tup->t_self, tup); - CatalogUpdateIndexes(rel, tup); - - heap_close(rel, NoLock); - heap_freetuple(tup); -} - -/* - * ALTER TEXT SEARCH TEMPLATE any_name SET SCHEMA name - */ -void -AlterTSTemplateNamespace(List *name, const char *newschema) -{ - Oid tmplId, - nspOid; - Relation rel; - - rel = heap_open(TSTemplateRelationId, RowExclusiveLock); - - tmplId = get_ts_template_oid(name, false); - - /* get schema OID */ - nspOid = LookupCreationNamespace(newschema); - - AlterObjectNamespace(rel, TSTEMPLATEOID, TSTEMPLATENAMENSP, - tmplId, nspOid, - Anum_pg_ts_template_tmplname, - Anum_pg_ts_template_tmplnamespace, - -1, -1); - - heap_close(rel, RowExclusiveLock); -} - -Oid -AlterTSTemplateNamespace_oid(Oid tmplId, Oid newNspOid) -{ - Oid oldNspOid; - Relation rel; - - rel = heap_open(TSTemplateRelationId, RowExclusiveLock); - - oldNspOid = - AlterObjectNamespace(rel, TSTEMPLATEOID, TSTEMPLATENAMENSP, - tmplId, newNspOid, - Anum_pg_ts_template_tmplname, - Anum_pg_ts_template_tmplnamespace, - -1, -1); - - heap_close(rel, RowExclusiveLock); - - return oldNspOid; -} - -/* * Guts of TS template deletion. */ void @@ -1432,104 +1094,6 @@ DefineTSConfiguration(List *names, List *parameters) } /* - * ALTER TEXT SEARCH CONFIGURATION RENAME - */ -void -RenameTSConfiguration(List *oldname, const char *newname) -{ - HeapTuple tup; - Relation rel; - Oid cfgId; - AclResult aclresult; - Oid namespaceOid; - - rel = heap_open(TSConfigRelationId, RowExclusiveLock); - - cfgId = get_ts_config_oid(oldname, false); - - tup = SearchSysCacheCopy1(TSCONFIGOID, ObjectIdGetDatum(cfgId)); - - if (!HeapTupleIsValid(tup)) /* should not happen */ - elog(ERROR, "cache lookup failed for text search configuration %u", - cfgId); - - namespaceOid = ((Form_pg_ts_config) GETSTRUCT(tup))->cfgnamespace; - - if (SearchSysCacheExists2(TSCONFIGNAMENSP, - PointerGetDatum(newname), - ObjectIdGetDatum(namespaceOid))) - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_OBJECT), - errmsg("text search configuration \"%s\" already exists", - newname))); - - /* must be owner */ - if (!pg_ts_config_ownercheck(cfgId, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSCONFIGURATION, - NameListToString(oldname)); - - /* must have CREATE privilege on namespace */ - aclresult = pg_namespace_aclcheck(namespaceOid, GetUserId(), ACL_CREATE); - aclcheck_error(aclresult, ACL_KIND_NAMESPACE, - get_namespace_name(namespaceOid)); - - namestrcpy(&(((Form_pg_ts_config) GETSTRUCT(tup))->cfgname), newname); - simple_heap_update(rel, &tup->t_self, tup); - CatalogUpdateIndexes(rel, tup); - - heap_close(rel, NoLock); - heap_freetuple(tup); -} - -/* - * ALTER TEXT SEARCH CONFIGURATION any_name SET SCHEMA name - */ -void -AlterTSConfigurationNamespace(List *name, const char *newschema) -{ - Oid cfgId, - nspOid; - Relation rel; - - rel = heap_open(TSConfigRelationId, RowExclusiveLock); - - cfgId = get_ts_config_oid(name, false); - - /* get schema OID */ - nspOid = LookupCreationNamespace(newschema); - - AlterObjectNamespace(rel, TSCONFIGOID, TSCONFIGNAMENSP, - cfgId, nspOid, - Anum_pg_ts_config_cfgname, - Anum_pg_ts_config_cfgnamespace, - Anum_pg_ts_config_cfgowner, - ACL_KIND_TSCONFIGURATION); - - heap_close(rel, RowExclusiveLock); -} - -Oid -AlterTSConfigurationNamespace_oid(Oid cfgId, Oid newNspOid) -{ - Oid oldNspOid; - Relation rel; - - rel = heap_open(TSConfigRelationId, RowExclusiveLock); - - oldNspOid = - AlterObjectNamespace(rel, TSCONFIGOID, TSCONFIGNAMENSP, - cfgId, newNspOid, - Anum_pg_ts_config_cfgname, - Anum_pg_ts_config_cfgnamespace, - Anum_pg_ts_config_cfgowner, - ACL_KIND_TSCONFIGURATION); - - heap_close(rel, RowExclusiveLock); - - return oldNspOid; -} - -/* * Guts of TS configuration deletion. */ void @@ -1578,66 +1142,6 @@ RemoveTSConfigurationById(Oid cfgId) } /* - * ALTER TEXT SEARCH CONFIGURATION OWNER - */ -void -AlterTSConfigurationOwner(List *name, Oid newOwnerId) -{ - HeapTuple tup; - Relation rel; - Oid cfgId; - AclResult aclresult; - Oid namespaceOid; - Form_pg_ts_config form; - - rel = heap_open(TSConfigRelationId, RowExclusiveLock); - - cfgId = get_ts_config_oid(name, false); - - tup = SearchSysCacheCopy1(TSCONFIGOID, ObjectIdGetDatum(cfgId)); - - if (!HeapTupleIsValid(tup)) /* should not happen */ - elog(ERROR, "cache lookup failed for text search configuration %u", - cfgId); - - form = (Form_pg_ts_config) GETSTRUCT(tup); - namespaceOid = form->cfgnamespace; - - if (form->cfgowner != newOwnerId) - { - /* Superusers can always do it */ - if (!superuser()) - { - /* must be owner */ - if (!pg_ts_config_ownercheck(cfgId, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSCONFIGURATION, - NameListToString(name)); - - /* Must be able to become new owner */ - check_is_member_of_role(GetUserId(), newOwnerId); - - /* New owner must have CREATE privilege on namespace */ - aclresult = pg_namespace_aclcheck(namespaceOid, newOwnerId, ACL_CREATE); - if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_NAMESPACE, - get_namespace_name(namespaceOid)); - } - - form->cfgowner = newOwnerId; - - simple_heap_update(rel, &tup->t_self, tup); - CatalogUpdateIndexes(rel, tup); - - /* Update owner dependency reference */ - changeDependencyOnOwner(TSConfigRelationId, HeapTupleGetOid(tup), - newOwnerId); - } - - heap_close(rel, NoLock); - heap_freetuple(tup); -} - -/* * ALTER TEXT SEARCH CONFIGURATION - main entry point */ void diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 1743b8f..22425b7 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -2914,7 +2914,6 @@ _copyAlterObjectSchemaStmt(const AlterObjectSchemaStmt *from) COPY_NODE_FIELD(relation); COPY_NODE_FIELD(object); COPY_NODE_FIELD(objarg); - COPY_STRING_FIELD(addname); COPY_STRING_FIELD(newschema); COPY_SCALAR_FIELD(missing_ok); @@ -2930,7 +2929,6 @@ _copyAlterOwnerStmt(const AlterOwnerStmt *from) COPY_NODE_FIELD(relation); COPY_NODE_FIELD(object); COPY_NODE_FIELD(objarg); - COPY_STRING_FIELD(addname); COPY_STRING_FIELD(newowner); return newnode; diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index f19ad77..a3c8158 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -1326,7 +1326,6 @@ _equalAlterObjectSchemaStmt(const AlterObjectSchemaStmt *a, const AlterObjectSch COMPARE_NODE_FIELD(relation); COMPARE_NODE_FIELD(object); COMPARE_NODE_FIELD(objarg); - COMPARE_STRING_FIELD(addname); COMPARE_STRING_FIELD(newschema); COMPARE_SCALAR_FIELD(missing_ok); @@ -1340,7 +1339,6 @@ _equalAlterOwnerStmt(const AlterOwnerStmt *a, const AlterOwnerStmt *b) COMPARE_NODE_FIELD(relation); COMPARE_NODE_FIELD(object); COMPARE_NODE_FIELD(objarg); - COMPARE_STRING_FIELD(addname); COMPARE_STRING_FIELD(newowner); return true; diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 7e6ceed..89a40e8 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -6608,7 +6608,7 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name { RenameStmt *n = makeNode(RenameStmt); n->renameType = OBJECT_FDW; - n->subname = $5; + n->object = list_make1(makeString($5)); n->newname = $8; n->missing_ok = false; $$ = (Node *)n; @@ -6636,7 +6636,7 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name { RenameStmt *n = makeNode(RenameStmt); n->renameType = OBJECT_LANGUAGE; - n->subname = $4; + n->object = list_make1(makeString($4)); n->newname = $7; n->missing_ok = false; $$ = (Node *)n; @@ -6646,7 +6646,7 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name RenameStmt *n = makeNode(RenameStmt); n->renameType = OBJECT_OPCLASS; n->object = $4; - n->subname = $6; + n->objarg = list_make1(makeString($6)); n->newname = $9; n->missing_ok = false; $$ = (Node *)n; @@ -6656,7 +6656,7 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name RenameStmt *n = makeNode(RenameStmt); n->renameType = OBJECT_OPFAMILY; n->object = $4; - n->subname = $6; + n->objarg = list_make1(makeString($6)); n->newname = $9; n->missing_ok = false; $$ = (Node *)n; @@ -6674,7 +6674,7 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name { RenameStmt *n = makeNode(RenameStmt); n->renameType = OBJECT_FOREIGN_SERVER; - n->subname = $3; + n->object = list_make1(makeString($3)); n->newname = $6; n->missing_ok = false; $$ = (Node *)n; @@ -7033,7 +7033,7 @@ AlterObjectSchemaStmt: AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt); n->objectType = OBJECT_OPCLASS; n->object = $4; - n->addname = $6; + n->objarg = list_make1(makeString($6)); n->newschema = $9; n->missing_ok = false; $$ = (Node *)n; @@ -7043,7 +7043,7 @@ AlterObjectSchemaStmt: AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt); n->objectType = OBJECT_OPFAMILY; n->object = $4; - n->addname = $6; + n->objarg = list_make1(makeString($6)); n->newschema = $9; n->missing_ok = false; $$ = (Node *)n; @@ -7253,7 +7253,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId AlterOwnerStmt *n = makeNode(AlterOwnerStmt); n->objectType = OBJECT_OPCLASS; n->object = $4; - n->addname = $6; + n->objarg = list_make1(makeString($6)); n->newowner = $9; $$ = (Node *)n; } @@ -7262,7 +7262,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId AlterOwnerStmt *n = makeNode(AlterOwnerStmt); n->objectType = OBJECT_OPFAMILY; n->object = $4; - n->addname = $6; + n->objarg = list_make1(makeString($6)); n->newowner = $9; $$ = (Node *)n; } diff --git a/src/include/catalog/objectaddress.h b/src/include/catalog/objectaddress.h index 0af09c6..03514ac 100644 --- a/src/include/catalog/objectaddress.h +++ b/src/include/catalog/objectaddress.h @@ -15,6 +15,7 @@ #include "nodes/parsenodes.h" #include "storage/lock.h" +#include "utils/acl.h" #include "utils/relcache.h" /* @@ -37,4 +38,13 @@ extern void check_object_ownership(Oid roleid, extern Oid get_object_namespace(const ObjectAddress *address); +extern Oid get_object_oid_index(Oid class_id); +extern int get_object_catcache_oid(Oid class_id); +extern int get_object_catcache_name(Oid class_id); +extern AttrNumber get_object_attnum_name(Oid class_id); +extern AttrNumber get_object_attnum_namespace(Oid class_id); +extern AttrNumber get_object_attnum_owner(Oid class_id); +extern AttrNumber get_object_attnum_acl(Oid class_id); +extern AclObjectKind get_object_aclkind(Oid class_id); + #endif /* PARSE_OBJECT_H */ diff --git a/src/include/catalog/pg_largeobject.h b/src/include/catalog/pg_largeobject.h index d0195ea..a5f0b00 100644 --- a/src/include/catalog/pg_largeobject.h +++ b/src/include/catalog/pg_largeobject.h @@ -55,7 +55,6 @@ typedef FormData_pg_largeobject *Form_pg_largeobject; extern Oid LargeObjectCreate(Oid loid); extern void LargeObjectDrop(Oid loid); -extern void LargeObjectAlterOwner(Oid loid, Oid newOwnerId); extern bool LargeObjectExists(Oid loid); #endif /* PG_LARGEOBJECT_H */ diff --git a/src/include/commands/alter.h b/src/include/commands/alter.h index 210cf4e..1a64d89 100644 --- a/src/include/commands/alter.h +++ b/src/include/commands/alter.h @@ -25,5 +25,10 @@ extern Oid AlterObjectNamespace(Relation rel, int oidCacheId, int nameCacheId, int Anum_name, int Anum_namespace, int Anum_owner, AclObjectKind acl_kind); extern void ExecAlterOwnerStmt(AlterOwnerStmt *stmt); - +extern Oid AlterObjectOwner(Relation catalog, Oid oidIndexId, int oidCacheId, + Oid objectId, Oid new_ownerId, + AttrNumber Anum_owner, + AttrNumber Anum_namespace, + AttrNumber Anum_acl, + AclObjectKind aclkind); #endif /* ALTER_H */ diff --git a/src/include/commands/collationcmds.h b/src/include/commands/collationcmds.h index 0587c4f..597033a 100644 --- a/src/include/commands/collationcmds.h +++ b/src/include/commands/collationcmds.h @@ -18,9 +18,6 @@ #include "nodes/parsenodes.h" extern void DefineCollation(List *names, List *parameters); -extern void RenameCollation(List *name, const char *newname); -extern void AlterCollationOwner(List *name, Oid newOwnerId); -extern void AlterCollationOwner_oid(Oid collationOid, Oid newOwnerId); extern void AlterCollationNamespace(List *name, const char *newschema); extern Oid AlterCollationNamespace_oid(Oid collOid, Oid newNspOid); diff --git a/src/include/commands/conversioncmds.h b/src/include/commands/conversioncmds.h index 00f468f..2f9abad 100644 --- a/src/include/commands/conversioncmds.h +++ b/src/include/commands/conversioncmds.h @@ -19,9 +19,5 @@ extern void CreateConversionCommand(CreateConversionStmt *parsetree); extern void RenameConversion(List *name, const char *newname); -extern void AlterConversionOwner(List *name, Oid newOwnerId); -extern void AlterConversionOwner_oid(Oid conversionOid, Oid newOwnerId); -extern void AlterConversionNamespace(List *name, const char *newschema); -extern Oid AlterConversionNamespace_oid(Oid convOid, Oid newNspOid); #endif /* CONVERSIONCMDS_H */ diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h index 8f3d2c3..7aecb1a 100644 --- a/src/include/commands/defrem.h +++ b/src/include/commands/defrem.h @@ -64,7 +64,6 @@ extern void CreateFunction(CreateFunctionStmt *stmt, const char *queryString); extern void RemoveFunctionById(Oid funcOid); extern void SetFunctionReturnType(Oid funcOid, Oid newRetType); extern void SetFunctionArgType(Oid funcOid, int argIndex, Oid newArgType); -extern void RenameFunction(List *name, List *argtypes, const char *newname); extern void AlterFunctionOwner(List *name, List *argtypes, Oid newOwnerId); extern void AlterFunctionOwner_oid(Oid procOid, Oid newOwnerId); extern void AlterFunction(AlterFunctionStmt *stmt); @@ -79,16 +78,10 @@ extern Oid get_cast_oid(Oid sourcetypeid, Oid targettypeid, bool missing_ok); /* commands/operatorcmds.c */ extern void DefineOperator(List *names, List *parameters); extern void RemoveOperatorById(Oid operOid); -extern void AlterOperatorOwner(List *name, TypeName *typeName1, - TypeName *typename2, Oid newOwnerId); -extern void AlterOperatorOwner_oid(Oid operOid, Oid newOwnerId); -extern void AlterOperatorNamespace(List *names, List *argtypes, const char *newschema); -extern Oid AlterOperatorNamespace_oid(Oid operOid, Oid newNspOid); /* commands/aggregatecmds.c */ extern void DefineAggregate(List *name, List *args, bool oldstyle, List *parameters); -extern void RenameAggregate(List *name, List *args, const char *newname); extern void AlterAggregateOwner(List *name, List *args, Oid newOwnerId); /* commands/opclasscmds.c */ @@ -99,55 +92,29 @@ extern void RemoveOpClassById(Oid opclassOid); extern void RemoveOpFamilyById(Oid opfamilyOid); extern void RemoveAmOpEntryById(Oid entryOid); extern void RemoveAmProcEntryById(Oid entryOid); -extern void RenameOpClass(List *name, const char *access_method, const char *newname); -extern void RenameOpFamily(List *name, const char *access_method, const char *newname); -extern void AlterOpClassOwner(List *name, const char *access_method, Oid newOwnerId); -extern void AlterOpClassOwner_oid(Oid opclassOid, Oid newOwnerId); -extern void AlterOpClassNamespace(List *name, char *access_method, const char *newschema); -extern Oid AlterOpClassNamespace_oid(Oid opclassOid, Oid newNspOid); -extern void AlterOpFamilyOwner(List *name, const char *access_method, Oid newOwnerId); -extern void AlterOpFamilyOwner_oid(Oid opfamilyOid, Oid newOwnerId); -extern void AlterOpFamilyNamespace(List *name, char *access_method, const char *newschema); -extern Oid AlterOpFamilyNamespace_oid(Oid opfamilyOid, Oid newNspOid); extern Oid get_am_oid(const char *amname, bool missing_ok); extern Oid get_opclass_oid(Oid amID, List *opclassname, bool missing_ok); extern Oid get_opfamily_oid(Oid amID, List *opfamilyname, bool missing_ok); /* commands/tsearchcmds.c */ extern void DefineTSParser(List *names, List *parameters); -extern void RenameTSParser(List *oldname, const char *newname); -extern void AlterTSParserNamespace(List *name, const char *newschema); -extern Oid AlterTSParserNamespace_oid(Oid prsId, Oid newNspOid); extern void RemoveTSParserById(Oid prsId); extern void DefineTSDictionary(List *names, List *parameters); -extern void RenameTSDictionary(List *oldname, const char *newname); extern void RemoveTSDictionaryById(Oid dictId); extern void AlterTSDictionary(AlterTSDictionaryStmt *stmt); -extern void AlterTSDictionaryOwner(List *name, Oid newOwnerId); -extern void AlterTSDictionaryNamespace(List *name, const char *newschema); -extern Oid AlterTSDictionaryNamespace_oid(Oid dictId, Oid newNspOid); extern void DefineTSTemplate(List *names, List *parameters); -extern void RenameTSTemplate(List *oldname, const char *newname); -extern void AlterTSTemplateNamespace(List *name, const char *newschema); -extern Oid AlterTSTemplateNamespace_oid(Oid tmplId, Oid newNspOid); extern void RemoveTSTemplateById(Oid tmplId); extern void DefineTSConfiguration(List *names, List *parameters); -extern void RenameTSConfiguration(List *oldname, const char *newname); extern void RemoveTSConfigurationById(Oid cfgId); extern void AlterTSConfiguration(AlterTSConfigurationStmt *stmt); -extern void AlterTSConfigurationOwner(List *name, Oid newOwnerId); -extern void AlterTSConfigurationNamespace(List *name, const char *newschema); -extern Oid AlterTSConfigurationNamespace_oid(Oid cfgId, Oid newNspOid); extern text *serialize_deflist(List *deflist); extern List *deserialize_deflist(Datum txt); /* commands/foreigncmds.c */ -extern void RenameForeignServer(const char *oldname, const char *newname); -extern void RenameForeignDataWrapper(const char *oldname, const char *newname); extern void AlterForeignServerOwner(const char *name, Oid newOwnerId); extern void AlterForeignServerOwner_oid(Oid, Oid newOwnerId); extern void AlterForeignDataWrapperOwner(const char *name, Oid newOwnerId); diff --git a/src/include/commands/proclang.h b/src/include/commands/proclang.h index 17d0972..11d7bf8 100644 --- a/src/include/commands/proclang.h +++ b/src/include/commands/proclang.h @@ -16,7 +16,6 @@ extern void CreateProceduralLanguage(CreatePLangStmt *stmt); extern void DropProceduralLanguageById(Oid langOid); -extern void RenameLanguage(const char *oldname, const char *newname); extern void AlterLanguageOwner(const char *name, Oid newOwnerId); extern void AlterLanguageOwner_oid(Oid oid, Oid newOwnerId); extern bool PLTemplateExists(const char *languageName); diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 50111cb..fb71615 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -2136,7 +2136,6 @@ typedef struct AlterObjectSchemaStmt RangeVar *relation; /* in case it's a table */ List *object; /* in case it's some other object */ List *objarg; /* argument types, if applicable */ - char *addname; /* additional name if needed */ char *newschema; /* the new schema */ bool missing_ok; /* skip error if missing? */ } AlterObjectSchemaStmt; @@ -2152,7 +2151,6 @@ typedef struct AlterOwnerStmt RangeVar *relation; /* in case it's a table */ List *object; /* in case it's some other object */ List *objarg; /* argument types, if applicable */ - char *addname; /* additional name if needed */ char *newowner; /* the new owner */ } AlterOwnerStmt; diff --git a/src/test/regress/expected/alter_generic.out b/src/test/regress/expected/alter_generic.out new file mode 100644 index 0000000..45e29c0 --- /dev/null +++ b/src/test/regress/expected/alter_generic.out @@ -0,0 +1,545 @@ +-- +-- Test for ALTER RENAME TO/OWNER TO/SET SCHEMA +-- +-- Clean up in case a prior regression run failed +SET client_min_messages TO 'warning'; +DROP ROLE IF EXISTS regtest_alter_user1; +DROP ROLE IF EXISTS regtest_alter_user2; +DROP ROLE IF EXISTS regtest_alter_user3; +RESET client_min_messages; +CREATE USER regtest_alter_user3; +CREATE USER regtest_alter_user2; +CREATE USER regtest_alter_user1 IN ROLE regtest_alter_user3; +CREATE SCHEMA alt_nsp1; +CREATE SCHEMA alt_nsp2; +GRANT ALL ON SCHEMA alt_nsp1, alt_nsp2 TO public; +SET search_path = alt_nsp1, public; +-- +-- Function and Aggregate +-- +SET SESSION AUTHORIZATION regtest_alter_user1; +CREATE FUNCTION alt_func1(int) RETURNS int LANGUAGE sql + AS 'SELECT $1 + 1'; +CREATE FUNCTION alt_func2(int) RETURNS int LANGUAGE sql + AS 'SELECT $1 - 1'; +CREATE AGGREGATE alt_agg1 ( + sfunc1 = int4pl, basetype = int4, stype1 = int4, initcond = 0 +); +CREATE AGGREGATE alt_agg2 ( + sfunc1 = int4mi, basetype = int4, stype1 = int4, initcond = 0 +); +ALTER AGGREGATE alt_func1(int) RENAME TO alt_func3; -- failed (not aggregate) +ERROR: function alt_func1(integer) is not an aggregate +ALTER AGGREGATE alt_func1(int) OWNER TO regtest_alter_user3; -- failed (not aggregate) +ERROR: function alt_func1(integer) is not an aggregate +ALTER AGGREGATE alt_func1(int) SET SCHEMA alt_nsp2; -- failed (not aggregate) +ERROR: function alt_func1(integer) is not an aggregate +ALTER FUNCTION alt_func1(int) RENAME TO alt_func2; -- failed (name conflict) +ERROR: function alt_func2(integer) already exists in schema "alt_nsp1" +ALTER FUNCTION alt_func1(int) RENAME TO alt_func3; -- OK +ALTER FUNCTION alt_func2(int) OWNER TO regtest_alter_user2; -- failed (no role membership) +ERROR: must be member of role "regtest_alter_user2" +ALTER FUNCTION alt_func2(int) OWNER TO regtest_alter_user3; -- OK +ALTER FUNCTION alt_func2(int) SET SCHEMA alt_nsp2; -- OK +ALTER AGGREGATE alt_agg1(int) RENAME TO alt_agg2; -- failed (name conflict) +ERROR: function alt_agg2(integer) already exists in schema "alt_nsp1" +ALTER AGGREGATE alt_agg1(int) RENAME TO alt_agg3; -- OK +ALTER AGGREGATE alt_agg2(int) OWNER TO regtest_alter_user2; -- failed (no role membership) +ERROR: must be member of role "regtest_alter_user2" +ALTER AGGREGATE alt_agg2(int) OWNER TO regtest_alter_user3; -- OK +ALTER AGGREGATE alt_agg2(int) SET SCHEMA alt_nsp2; -- OK +SET SESSION AUTHORIZATION regtest_alter_user2; +CREATE FUNCTION alt_func1(int) RETURNS int LANGUAGE sql + AS 'SELECT $1 + 2'; +CREATE FUNCTION alt_func2(int) RETURNS int LANGUAGE sql + AS 'SELECT $1 - 2'; +CREATE AGGREGATE alt_agg1 ( + sfunc1 = int4pl, basetype = int4, stype1 = int4, initcond = 100 +); +CREATE AGGREGATE alt_agg2 ( + sfunc1 = int4mi, basetype = int4, stype1 = int4, initcond = -100 +); +ALTER FUNCTION alt_func3(int) RENAME TO alt_func4; -- failed (not owner) +ERROR: must be owner of function alt_func3 +ALTER FUNCTION alt_func1(int) RENAME TO alt_func4; -- OK +ALTER FUNCTION alt_func3(int) OWNER TO regtest_alter_user2; -- failed (not owner) +ERROR: must be owner of function alt_func3(integer) +ALTER FUNCTION alt_func2(int) OWNER TO regtest_alter_user3; -- failed (no role membership) +ERROR: must be member of role "regtest_alter_user3" +ALTER FUNCTION alt_func3(int) SET SCHEMA alt_nsp2; -- failed (not owner) +ERROR: must be owner of function alt_func3 +ALTER FUNCTION alt_func2(int) SET SCHEMA alt_nsp2; -- failed (name conflicts) +ERROR: function "alt_func2" already exists in schema "alt_nsp2" +ALTER AGGREGATE alt_agg3(int) RENAME TO alt_agg4; -- failed (not owner) +ERROR: must be owner of function alt_agg3 +ALTER AGGREGATE alt_agg1(int) RENAME TO alt_agg4; -- OK +ALTER AGGREGATE alt_agg3(int) OWNER TO regtest_alter_user2; -- failed (not owner) +ERROR: must be owner of function alt_agg3(integer) +ALTER AGGREGATE alt_agg2(int) OWNER TO regtest_alter_user3; -- failed (no role membership) +ERROR: must be member of role "regtest_alter_user3" +ALTER AGGREGATE alt_agg3(int) SET SCHEMA alt_nsp2; -- failed (not owner) +ERROR: must be owner of function alt_agg3 +ALTER AGGREGATE alt_agg2(int) SET SCHEMA alt_nsp2; -- failed (name conflict) +ERROR: function "alt_agg2" already exists in schema "alt_nsp2" +RESET SESSION AUTHORIZATION; +SELECT n.nspname, proname, prorettype::regtype, proisagg, a.rolname + FROM pg_proc p, pg_namespace n, pg_authid a + WHERE p.pronamespace = n.oid AND p.proowner = a.oid + AND n.nspname IN ('alt_nsp1', 'alt_nsp2') + ORDER BY nspname, proname; + nspname | proname | prorettype | proisagg | rolname +----------+-----------+------------+----------+--------------------- + alt_nsp1 | alt_agg2 | integer | t | regtest_alter_user2 + alt_nsp1 | alt_agg3 | integer | t | regtest_alter_user1 + alt_nsp1 | alt_agg4 | integer | t | regtest_alter_user2 + alt_nsp1 | alt_func2 | integer | f | regtest_alter_user2 + alt_nsp1 | alt_func3 | integer | f | regtest_alter_user1 + alt_nsp1 | alt_func4 | integer | f | regtest_alter_user2 + alt_nsp2 | alt_agg2 | integer | t | regtest_alter_user3 + alt_nsp2 | alt_func2 | integer | f | regtest_alter_user3 +(8 rows) + +-- +-- Collation +-- +SET SESSION AUTHORIZATION regtest_alter_user1; +CREATE COLLATION alt_coll1 (locale = 'C'); +CREATE COLLATION alt_coll2 (locale = 'C'); +ALTER COLLATION alt_coll1 RENAME TO alt_coll2; -- failed (name conflict) +ERROR: collation alt_coll2 already exists in schema "alt_nsp1" +ALTER COLLATION alt_coll1 RENAME TO alt_coll3; -- OK +ALTER COLLATION alt_coll2 OWNER TO regtest_alter_user2; -- failed (no role membership) +ERROR: must be member of role "regtest_alter_user2" +ALTER COLLATION alt_coll2 OWNER TO regtest_alter_user3; -- OK +ALTER COLLATION alt_coll2 SET SCHEMA alt_nsp2; -- OK +SET SESSION AUTHORIZATION regtest_alter_user2; +CREATE COLLATION alt_coll1 (locale = 'C'); +CREATE COLLATION alt_coll2 (locale = 'C'); +ALTER COLLATION alt_coll3 RENAME TO alt_coll4; -- failed (not owner) +ERROR: must be owner of collation alt_coll3 +ALTER COLLATION alt_coll1 RENAME TO alt_coll4; -- OK +ALTER COLLATION alt_coll3 OWNER TO regtest_alter_user2; -- failed (not owner) +ERROR: must be owner of collation alt_coll3 +ALTER COLLATION alt_coll2 OWNER TO regtest_alter_user3; -- failed (no role membership) +ERROR: must be member of role "regtest_alter_user3" +ALTER COLLATION alt_coll3 SET SCHEMA alt_nsp2; -- failed (not owner) +ERROR: must be owner of collation alt_coll3 +ALTER COLLATION alt_coll2 SET SCHEMA alt_nsp2; -- failed (name conflict) +ERROR: collation "alt_coll2" for encoding "SQL_ASCII" already exists in schema "alt_nsp2" +RESET SESSION AUTHORIZATION; +SELECT n.nspname, c.collname, a.rolname + FROM pg_collation c, pg_namespace n, pg_authid a + WHERE c.collnamespace = n.oid AND c.collowner = a.oid + AND n.nspname IN ('alt_nsp1', 'alt_nsp2') + ORDER BY n.nspname, c.collname; + nspname | collname | rolname +----------+-----------+--------------------- + alt_nsp1 | alt_coll2 | regtest_alter_user2 + alt_nsp1 | alt_coll3 | regtest_alter_user1 + alt_nsp1 | alt_coll4 | regtest_alter_user2 + alt_nsp2 | alt_coll2 | regtest_alter_user3 +(4 rows) + +-- +-- Conversion +-- +SET SESSION AUTHORIZATION regtest_alter_user1; +CREATE CONVERSION alt_conv1 FOR 'LATIN1' TO 'UTF8' FROM iso8859_1_to_utf8; +CREATE CONVERSION alt_conv2 FOR 'LATIN1' TO 'UTF8' FROM iso8859_1_to_utf8; +ALTER CONVERSION alt_conv1 RENAME TO alt_conv2; -- failed (name conflict) +ERROR: conversion alt_conv2 already exists in schema "alt_nsp1" +ALTER CONVERSION alt_conv1 RENAME TO alt_conv3; -- OK +ALTER CONVERSION alt_conv2 OWNER TO regtest_alter_user2; -- failed (no role membership) +ERROR: must be member of role "regtest_alter_user2" +ALTER CONVERSION alt_conv2 OWNER TO regtest_alter_user3; -- OK +ALTER CONVERSION alt_conv2 SET SCHEMA alt_nsp2; -- OK +SET SESSION AUTHORIZATION regtest_alter_user2; +CREATE CONVERSION alt_conv1 FOR 'LATIN1' TO 'UTF8' FROM iso8859_1_to_utf8; +CREATE CONVERSION alt_conv2 FOR 'LATIN1' TO 'UTF8' FROM iso8859_1_to_utf8; +ALTER CONVERSION alt_conv3 RENAME TO alt_conv4; -- failed (not owner) +ERROR: must be owner of conversion alt_conv3 +ALTER CONVERSION alt_conv1 RENAME TO alt_conv4; -- OK +ALTER CONVERSION alt_conv3 OWNER TO regtest_alter_user2; -- failed (not owner) +ERROR: must be owner of conversion alt_conv3 +ALTER CONVERSION alt_conv2 OWNER TO regtest_alter_user3; -- failed (no role membership) +ERROR: must be member of role "regtest_alter_user3" +ALTER CONVERSION alt_conv3 SET SCHEMA alt_nsp2; -- failed (not owner) +ERROR: must be owner of conversion alt_conv3 +ALTER CONVERSION alt_conv2 SET SCHEMA alt_nsp2; -- failed (name conflict) +ERROR: conversion alt_conv2 already exists in schema "alt_nsp2" +RESET SESSION AUTHORIZATION; +SELECT n.nspname, c.conname, a.rolname + FROM pg_conversion c, pg_namespace n, pg_authid a + WHERE c.connamespace = n.oid AND c.conowner = a.oid + AND n.nspname IN ('alt_nsp1', 'alt_nsp2') + ORDER BY nspname, conname; + nspname | conname | rolname +----------+-----------+--------------------- + alt_nsp1 | alt_conv2 | regtest_alter_user2 + alt_nsp1 | alt_conv3 | regtest_alter_user1 + alt_nsp1 | alt_conv4 | regtest_alter_user2 + alt_nsp2 | alt_conv2 | regtest_alter_user3 +(4 rows) + +-- +-- Foreign Data Wrapper and Foreign Server +-- +CREATE FOREIGN DATA WRAPPER alt_fdw1; +CREATE FOREIGN DATA WRAPPER alt_fdw2; +CREATE SERVER alt_fserv1 FOREIGN DATA WRAPPER alt_fdw1; +CREATE SERVER alt_fserv2 FOREIGN DATA WRAPPER alt_fdw2; +ALTER FOREIGN DATA WRAPPER alt_fdw1 RENAME TO alt_fdw2; -- failed (name conflict) +ERROR: foreign-data wrapper alt_fdw2 already exists +ALTER FOREIGN DATA WRAPPER alt_fdw1 RENAME TO alt_fdw3; -- OK +ALTER SERVER alt_fserv1 RENAME TO alt_fserv2; -- failed (name conflict) +ERROR: server alt_fserv2 already exists +ALTER SERVER alt_fserv1 RENAME TO alt_fserv3; -- OK +SELECT fdwname FROM pg_foreign_data_wrapper WHERE fdwname like 'alt_fdw%'; + fdwname +---------- + alt_fdw2 + alt_fdw3 +(2 rows) + +SELECT srvname FROM pg_foreign_server WHERE srvname like 'alt_fserv%'; + srvname +------------ + alt_fserv2 + alt_fserv3 +(2 rows) + +-- +-- Procedural Language +-- +CREATE LANGUAGE alt_lang1 HANDLER plpgsql_call_handler; +CREATE LANGUAGE alt_lang2 HANDLER plpgsql_call_handler; +ALTER LANGUAGE alt_lang1 OWNER TO regtest_alter_user1; -- OK +ALTER LANGUAGE alt_lang2 OWNER TO regtest_alter_user2; -- OK +SET SESSION AUTHORIZATION regtest_alter_user1; +ALTER LANGUAGE alt_lang1 RENAME TO alt_lang2; -- failed (name conflict) +ERROR: language alt_lang2 already exists +ALTER LANGUAGE alt_lang2 RENAME TO alt_lang3; -- failed (not owner) +ERROR: must be owner of language alt_lang2 +ALTER LANGUAGE alt_lang1 RENAME TO alt_lang3; -- OK +ALTER LANGUAGE alt_lang2 OWNER TO regtest_alter_user3; -- failed (not owner) +ERROR: must be owner of language alt_lang2 +ALTER LANGUAGE alt_lang3 OWNER TO regtest_alter_user2; -- failed (no role membership) +ERROR: must be member of role "regtest_alter_user2" +ALTER LANGUAGE alt_lang3 OWNER TO regtest_alter_user3; -- OK +RESET SESSION AUTHORIZATION; +SELECT lanname, a.rolname + FROM pg_language l, pg_authid a + WHERE l.lanowner = a.oid AND l.lanname like 'alt_lang%' + ORDER BY lanname; + lanname | rolname +-----------+--------------------- + alt_lang2 | regtest_alter_user2 + alt_lang3 | regtest_alter_user3 +(2 rows) + +-- +-- Operator +-- +SET SESSION AUTHORIZATION regtest_alter_user1; +CREATE OPERATOR @-@ ( leftarg = int4, rightarg = int4, procedure = int4mi ); +CREATE OPERATOR @+@ ( leftarg = int4, rightarg = int4, procedure = int4pl ); +ALTER OPERATOR @+@(int4, int4) OWNER TO regtest_alter_user2; -- failed (no role membership) +ERROR: must be member of role "regtest_alter_user2" +ALTER OPERATOR @+@(int4, int4) OWNER TO regtest_alter_user3; -- OK +ALTER OPERATOR @-@(int4, int4) SET SCHEMA alt_nsp2; -- OK +SET SESSION AUTHORIZATION regtest_alter_user2; +CREATE OPERATOR @-@ ( leftarg = int4, rightarg = int4, procedure = int4mi ); +ALTER OPERATOR @+@(int4, int4) OWNER TO regtest_alter_user2; -- failed (not owner) +ERROR: must be owner of operator @+@(integer,integer) +ALTER OPERATOR @-@(int4, int4) OWNER TO regtest_alter_user3; -- failed (no role membership) +ERROR: must be member of role "regtest_alter_user3" +ALTER OPERATOR @+@(int4, int4) SET SCHEMA alt_nsp2; -- failed (not owner) +ERROR: must be owner of operator @+@ +-- ALTER OPERATOR @-@(int4, int4) SET SCHEMA alt_nsp2; -- failed (name conflict) +-- XXX it raises raw oid of namespace, it makes unneeded regression test fail... +RESET SESSION AUTHORIZATION; +SELECT n.nspname, oprname, a.rolname, oprleft::regtype, oprright::regtype, oprcode::regproc + FROM pg_operator o, pg_namespace n, pg_authid a + WHERE o.oprnamespace = n.oid AND o.oprowner = a.oid + AND n.nspname IN ('alt_nsp1', 'alt_nsp2') + ORDER BY nspname, oprname; + nspname | oprname | rolname | oprleft | oprright | oprcode +----------+---------+---------------------+---------+----------+--------- + alt_nsp1 | @+@ | regtest_alter_user3 | integer | integer | int4pl + alt_nsp1 | @-@ | regtest_alter_user2 | integer | integer | int4mi + alt_nsp2 | @-@ | regtest_alter_user1 | integer | integer | int4mi +(3 rows) + +-- +-- OpFamily and OpClass +-- +CREATE OPERATOR FAMILY alt_opf1 USING hash; +CREATE OPERATOR FAMILY alt_opf2 USING hash; +ALTER OPERATOR FAMILY alt_opf1 USING hash OWNER TO regtest_alter_user1; +ALTER OPERATOR FAMILY alt_opf2 USING hash OWNER TO regtest_alter_user1; +CREATE OPERATOR CLASS alt_opc1 FOR TYPE uuid USING hash AS STORAGE uuid; +CREATE OPERATOR CLASS alt_opc2 FOR TYPE uuid USING hash AS STORAGE uuid; +ALTER OPERATOR CLASS alt_opc1 USING hash OWNER TO regtest_alter_user1; +ALTER OPERATOR CLASS alt_opc2 USING hash OWNER TO regtest_alter_user1; +SET SESSION AUTHORIZATION regtest_alter_user1; +ALTER OPERATOR FAMILY alt_opf1 USING hash RENAME TO alt_opf2; -- failed (name conflict) +ERROR: operator family alt_opf2 for access method hash already exists in schema "alt_nsp1" +ALTER OPERATOR FAMILY alt_opf1 USING hash RENAME TO alt_opf3; -- OK +ALTER OPERATOR FAMILY alt_opf2 USING hash OWNER TO regtest_alter_user2; -- failed (no role membership) +ERROR: must be member of role "regtest_alter_user2" +ALTER OPERATOR FAMILY alt_opf2 USING hash OWNER TO regtest_alter_user3; -- OK +ALTER OPERATOR FAMILY alt_opf2 USING hash SET SCHEMA alt_nsp2; -- OK +ALTER OPERATOR CLASS alt_opc1 USING hash RENAME TO alt_opc2; -- failed (name conflict) +ERROR: operator class alt_opc2 for access method hash already exists in schema "alt_nsp1" +ALTER OPERATOR CLASS alt_opc1 USING hash RENAME TO alt_opc3; -- OK +ALTER OPERATOR CLASS alt_opc2 USING hash OWNER TO regtest_alter_user2; -- failed (no role membership) +ERROR: must be member of role "regtest_alter_user2" +ALTER OPERATOR CLASS alt_opc2 USING hash OWNER TO regtest_alter_user3; -- OK +ALTER OPERATOR CLASS alt_opc2 USING hash SET SCHEMA alt_nsp2; -- OK +RESET SESSION AUTHORIZATION; +CREATE OPERATOR FAMILY alt_opf1 USING hash; +CREATE OPERATOR FAMILY alt_opf2 USING hash; +ALTER OPERATOR FAMILY alt_opf1 USING hash OWNER TO regtest_alter_user2; +ALTER OPERATOR FAMILY alt_opf2 USING hash OWNER TO regtest_alter_user2; +CREATE OPERATOR CLASS alt_opc1 FOR TYPE macaddr USING hash AS STORAGE macaddr; +CREATE OPERATOR CLASS alt_opc2 FOR TYPE macaddr USING hash AS STORAGE macaddr; +ALTER OPERATOR CLASS alt_opc1 USING hash OWNER TO regtest_alter_user2; +ALTER OPERATOR CLASS alt_opc2 USING hash OWNER TO regtest_alter_user2; +SET SESSION AUTHORIZATION regtest_alter_user2; +ALTER OPERATOR FAMILY alt_opf3 USING hash RENAME TO alt_opf4; -- failed (not owner) +ERROR: must be owner of operator family alt_opf3 +ALTER OPERATOR FAMILY alt_opf1 USING hash RENAME TO alt_opf4; -- OK +ALTER OPERATOR FAMILY alt_opf3 USING hash OWNER TO regtest_alter_user2; -- failed (not owner) +ERROR: must be owner of operator family alt_opf3 for access method hash +ALTER OPERATOR FAMILY alt_opf2 USING hash OWNER TO regtest_alter_user3; -- failed (no role membership) +ERROR: must be member of role "regtest_alter_user3" +ALTER OPERATOR FAMILY alt_opf3 USING hash SET SCHEMA alt_nsp2; -- failed (not owner) +ERROR: must be owner of operator family alt_opf3 +-- ALTER OPERATOR FAMILY alt_opf2 USING hash SET SCHEMA alt_nsp2; -- failed (name conflict) +ALTER OPERATOR CLASS alt_opc3 USING hash RENAME TO alt_opc4; -- failed (not owner) +ERROR: must be owner of operator class alt_opc3 +ALTER OPERATOR CLASS alt_opc1 USING hash RENAME TO alt_opc4; -- OK +ALTER OPERATOR CLASS alt_opc3 USING hash OWNER TO regtest_alter_user2; -- failed (not owner) +ERROR: must be owner of operator class alt_opc3 for access method hash +ALTER OPERATOR CLASS alt_opc2 USING hash OWNER TO regtest_alter_user3; -- failed (no role membership) +ERROR: must be member of role "regtest_alter_user3" +ALTER OPERATOR CLASS alt_opc3 USING hash SET SCHEMA alt_nsp2; -- failed (not owner) +ERROR: must be owner of operator class alt_opc3 +-- ALTER OPERATOR CLASS alt_opc2 USING hash SET SCHEMA alt_nsp2; -- failed (name conflict) +RESET SESSION AUTHORIZATION; +SELECT nspname, opfname, amname, rolname + FROM pg_opfamily o, pg_am m, pg_namespace n, pg_authid a + WHERE o.opfmethod = m.oid AND o.opfnamespace = n.oid AND o.opfowner = a.oid + AND n.nspname IN ('alt_nsp1', 'alt_nsp2') + ORDER BY nspname, opfname; + nspname | opfname | amname | rolname +----------+----------+--------+--------------------- + alt_nsp1 | alt_opc1 | hash | kaigai + alt_nsp1 | alt_opc2 | hash | kaigai + alt_nsp1 | alt_opf2 | hash | regtest_alter_user2 + alt_nsp1 | alt_opf3 | hash | regtest_alter_user1 + alt_nsp1 | alt_opf4 | hash | regtest_alter_user2 + alt_nsp2 | alt_opf2 | hash | regtest_alter_user3 +(6 rows) + +SELECT nspname, opcname, amname, rolname + FROM pg_opclass o, pg_am m, pg_namespace n, pg_authid a + WHERE o.opcmethod = m.oid AND o.opcnamespace = n.oid AND o.opcowner = a.oid + AND n.nspname IN ('alt_nsp1', 'alt_nsp2') + ORDER BY nspname, opcname; + nspname | opcname | amname | rolname +----------+----------+--------+--------------------- + alt_nsp1 | alt_opc2 | hash | regtest_alter_user2 + alt_nsp1 | alt_opc3 | hash | regtest_alter_user1 + alt_nsp1 | alt_opc4 | hash | regtest_alter_user2 + alt_nsp2 | alt_opc2 | hash | regtest_alter_user3 +(4 rows) + +-- +-- Text Search Dictionary +-- +SET SESSION AUTHORIZATION regtest_alter_user1; +CREATE TEXT SEARCH DICTIONARY alt_ts_dict1 (template=simple); +CREATE TEXT SEARCH DICTIONARY alt_ts_dict2 (template=simple); +ALTER TEXT SEARCH DICTIONARY alt_ts_dict1 RENAME TO alt_ts_dict2; -- failed (name conflict) +ERROR: text search dictionary alt_ts_dict2 already exists in schema "alt_nsp1" +ALTER TEXT SEARCH DICTIONARY alt_ts_dict1 RENAME TO alt_ts_dict3; -- OK +ALTER TEXT SEARCH DICTIONARY alt_ts_dict2 OWNER TO regtest_alter_user2; -- failed (no role membership) +ERROR: must be member of role "regtest_alter_user2" +ALTER TEXT SEARCH DICTIONARY alt_ts_dict2 OWNER TO regtest_alter_user3; -- OK +ALTER TEXT SEARCH DICTIONARY alt_ts_dict2 SET SCHEMA alt_nsp2; -- OK +SET SESSION AUTHORIZATION regtest_alter_user2; +CREATE TEXT SEARCH DICTIONARY alt_ts_dict1 (template=simple); +CREATE TEXT SEARCH DICTIONARY alt_ts_dict2 (template=simple); +ALTER TEXT SEARCH DICTIONARY alt_ts_dict3 RENAME TO alt_ts_dict4; -- failed (not owner) +ERROR: must be owner of text search dictionary alt_ts_dict3 +ALTER TEXT SEARCH DICTIONARY alt_ts_dict1 RENAME TO alt_ts_dict4; -- OK +ALTER TEXT SEARCH DICTIONARY alt_ts_dict3 OWNER TO regtest_alter_user2; -- failed (not owner) +ERROR: must be owner of text search dictionary alt_ts_dict3 +ALTER TEXT SEARCH DICTIONARY alt_ts_dict2 OWNER TO regtest_alter_user3; -- failed (no role membership) +ERROR: must be member of role "regtest_alter_user3" +ALTER TEXT SEARCH DICTIONARY alt_ts_dict3 SET SCHEMA alt_nsp2; -- failed (not owner) +ERROR: must be owner of text search dictionary alt_ts_dict3 +ALTER TEXT SEARCH DICTIONARY alt_ts_dict2 SET SCHEMA alt_nsp2; -- failed (name conflict) +ERROR: text search dictionary alt_ts_dict2 already exists in schema "alt_nsp2" +RESET SESSION AUTHORIZATION; +SELECT nspname, dictname, rolname + FROM pg_ts_dict t, pg_namespace n, pg_authid a + WHERE t.dictnamespace = n.oid AND t.dictowner = a.oid + AND n.nspname in ('alt_nsp1', 'alt_nsp2') + ORDER BY nspname, dictname; + nspname | dictname | rolname +----------+--------------+--------------------- + alt_nsp1 | alt_ts_dict2 | regtest_alter_user2 + alt_nsp1 | alt_ts_dict3 | regtest_alter_user1 + alt_nsp1 | alt_ts_dict4 | regtest_alter_user2 + alt_nsp2 | alt_ts_dict2 | regtest_alter_user3 +(4 rows) + +-- +-- Text Search Configuration +-- +SET SESSION AUTHORIZATION regtest_alter_user1; +CREATE TEXT SEARCH CONFIGURATION alt_ts_conf1 (copy=english); +CREATE TEXT SEARCH CONFIGURATION alt_ts_conf2 (copy=english); +ALTER TEXT SEARCH CONFIGURATION alt_ts_conf1 RENAME TO alt_ts_conf2; -- failed (name conflict) +ERROR: text search configuration alt_ts_conf2 already exists in schema "alt_nsp1" +ALTER TEXT SEARCH CONFIGURATION alt_ts_conf1 RENAME TO alt_ts_conf3; -- OK +ALTER TEXT SEARCH CONFIGURATION alt_ts_conf2 OWNER TO regtest_alter_user2; -- failed (no role membership) +ERROR: must be member of role "regtest_alter_user2" +ALTER TEXT SEARCH CONFIGURATION alt_ts_conf2 OWNER TO regtest_alter_user3; -- OK +ALTER TEXT SEARCH CONFIGURATION alt_ts_conf2 SET SCHEMA alt_nsp2; -- OK +SET SESSION AUTHORIZATION regtest_alter_user2; +CREATE TEXT SEARCH CONFIGURATION alt_ts_conf1 (copy=english); +CREATE TEXT SEARCH CONFIGURATION alt_ts_conf2 (copy=english); +ALTER TEXT SEARCH CONFIGURATION alt_ts_conf3 RENAME TO alt_ts_conf4; -- failed (not owner) +ERROR: must be owner of text search configuration alt_ts_conf3 +ALTER TEXT SEARCH CONFIGURATION alt_ts_conf1 RENAME TO alt_ts_conf4; -- OK +ALTER TEXT SEARCH CONFIGURATION alt_ts_conf3 OWNER TO regtest_alter_user2; -- failed (not owner) +ERROR: must be owner of text search configuration alt_ts_conf3 +ALTER TEXT SEARCH CONFIGURATION alt_ts_conf2 OWNER TO regtest_alter_user3; -- failed (no role membership) +ERROR: must be member of role "regtest_alter_user3" +ALTER TEXT SEARCH CONFIGURATION alt_ts_conf3 SET SCHEMA alt_nsp2; -- failed (not owner) +ERROR: must be owner of text search configuration alt_ts_conf3 +ALTER TEXT SEARCH CONFIGURATION alt_ts_conf2 SET SCHEMA alt_nsp2; -- failed (name conflict) +ERROR: text search configuration alt_ts_conf2 already exists in schema "alt_nsp2" +RESET SESSION AUTHORIZATION; +SELECT nspname, cfgname, rolname + FROM pg_ts_config t, pg_namespace n, pg_authid a + WHERE t.cfgnamespace = n.oid AND t.cfgowner = a.oid + AND n.nspname in ('alt_nsp1', 'alt_nsp2') + ORDER BY nspname, cfgname; + nspname | cfgname | rolname +----------+--------------+--------------------- + alt_nsp1 | alt_ts_conf2 | regtest_alter_user2 + alt_nsp1 | alt_ts_conf3 | regtest_alter_user1 + alt_nsp1 | alt_ts_conf4 | regtest_alter_user2 + alt_nsp2 | alt_ts_conf2 | regtest_alter_user3 +(4 rows) + +-- +-- Text Search Template +-- +CREATE TEXT SEARCH TEMPLATE alt_ts_temp1 (lexize=dsimple_lexize); +CREATE TEXT SEARCH TEMPLATE alt_ts_temp2 (lexize=dsimple_lexize); +ALTER TEXT SEARCH TEMPLATE alt_ts_temp1 RENAME TO alt_ts_temp2; -- failed (name conflict) +ERROR: text search template alt_ts_temp2 already exists in schema "alt_nsp1" +ALTER TEXT SEARCH TEMPLATE alt_ts_temp1 RENAME TO alt_ts_temp3; -- OK +ALTER TEXT SEARCH TEMPLATE alt_ts_temp2 SET SCHEMA alt_nsp2; -- OK +CREATE TEXT SEARCH TEMPLATE alt_ts_temp2 (lexize=dsimple_lexize); +ALTER TEXT SEARCH TEMPLATE alt_ts_temp2 SET SCHEMA alt_nsp2; -- failed (name conflict) +ERROR: text search template alt_ts_temp2 already exists in schema "alt_nsp2" +SELECT nspname, tmplname + FROM pg_ts_template t, pg_namespace n + WHERE t.tmplnamespace = n.oid AND nspname like 'alt_nsp%' + ORDER BY nspname, tmplname; + nspname | tmplname +----------+-------------- + alt_nsp1 | alt_ts_temp2 + alt_nsp1 | alt_ts_temp3 + alt_nsp2 | alt_ts_temp2 +(3 rows) + +-- +-- Text Search Parser +-- +CREATE TEXT SEARCH PARSER alt_ts_prs1 + (start = prsd_start, gettoken = prsd_nexttoken, end = prsd_end, lextypes = prsd_lextype); +CREATE TEXT SEARCH PARSER alt_ts_prs2 + (start = prsd_start, gettoken = prsd_nexttoken, end = prsd_end, lextypes = prsd_lextype); +ALTER TEXT SEARCH PARSER alt_ts_prs1 RENAME TO alt_ts_prs2; -- failed (name conflict) +ERROR: text search parser alt_ts_prs2 already exists in schema "alt_nsp1" +ALTER TEXT SEARCH PARSER alt_ts_prs1 RENAME TO alt_ts_prs3; -- OK +ALTER TEXT SEARCH PARSER alt_ts_prs2 SET SCHEMA alt_nsp2; -- OK +CREATE TEXT SEARCH PARSER alt_ts_prs2 + (start = prsd_start, gettoken = prsd_nexttoken, end = prsd_end, lextypes = prsd_lextype); +ALTER TEXT SEARCH PARSER alt_ts_prs2 SET SCHEMA alt_nsp2; -- failed (name conflict) +ERROR: text search parser alt_ts_prs2 already exists in schema "alt_nsp2" +SELECT nspname, prsname + FROM pg_ts_parser t, pg_namespace n + WHERE t.prsnamespace = n.oid AND nspname like 'alt_nsp%' + ORDER BY nspname, prsname; + nspname | prsname +----------+------------- + alt_nsp1 | alt_ts_prs2 + alt_nsp1 | alt_ts_prs3 + alt_nsp2 | alt_ts_prs2 +(3 rows) + +--- +--- Cleanup resources +--- +DROP FOREIGN DATA WRAPPER alt_fdw2 CASCADE; +NOTICE: drop cascades to server alt_fserv2 +DROP FOREIGN DATA WRAPPER alt_fdw3 CASCADE; +NOTICE: drop cascades to server alt_fserv3 +DROP LANGUAGE alt_lang2 CASCADE; +DROP LANGUAGE alt_lang3 CASCADE; +DROP LANGUAGE alt_lang4 CASCADE; +ERROR: language "alt_lang4" does not exist +DROP SCHEMA alt_nsp1 CASCADE; +NOTICE: drop cascades to 29 other objects +DETAIL: drop cascades to function alt_func3(integer) +drop cascades to function alt_agg3(integer) +drop cascades to function alt_func4(integer) +drop cascades to function alt_func2(integer) +drop cascades to function alt_agg4(integer) +drop cascades to function alt_agg2(integer) +drop cascades to collation alt_coll3 +drop cascades to collation alt_coll4 +drop cascades to collation alt_coll2 +drop cascades to conversion alt_conv3 +drop cascades to conversion alt_conv4 +drop cascades to conversion alt_conv2 +drop cascades to operator @+@(integer,integer) +drop cascades to operator @-@(integer,integer) +drop cascades to operator family alt_opf3 for access method hash +drop cascades to operator family alt_opc1 for access method hash +drop cascades to operator family alt_opc2 for access method hash +drop cascades to operator family alt_opf4 for access method hash +drop cascades to operator family alt_opf2 for access method hash +drop cascades to text search dictionary alt_ts_dict3 +drop cascades to text search dictionary alt_ts_dict4 +drop cascades to text search dictionary alt_ts_dict2 +drop cascades to text search configuration alt_ts_conf3 +drop cascades to text search configuration alt_ts_conf4 +drop cascades to text search configuration alt_ts_conf2 +drop cascades to text search template alt_ts_temp3 +drop cascades to text search template alt_ts_temp2 +drop cascades to text search parser alt_ts_prs3 +drop cascades to text search parser alt_ts_prs2 +DROP SCHEMA alt_nsp2 CASCADE; +NOTICE: drop cascades to 10 other objects +DETAIL: drop cascades to function alt_nsp2.alt_func2(integer) +drop cascades to function alt_nsp2.alt_agg2(integer) +drop cascades to collation alt_coll2 +drop cascades to conversion alt_conv2 +drop cascades to operator alt_nsp2.@-@(integer,integer) +drop cascades to operator family alt_nsp2.alt_opf2 for access method hash +drop cascades to text search dictionary alt_ts_dict2 +drop cascades to text search configuration alt_ts_conf2 +drop cascades to text search template alt_ts_temp2 +drop cascades to text search parser alt_ts_prs2 +DROP USER regtest_alter_user1; +DROP USER regtest_alter_user2; +DROP USER regtest_alter_user3; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8852e0a..78be6f0 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -99,7 +99,7 @@ test: select_views portals_p2 foreign_key cluster dependency guc bitmapops combo # NB: temp.sql does a reconnect which transiently uses 2 connections, # so keep this parallel group to at most 19 tests # ---------- -test: plancache limit plpgsql copy2 temp domain rangefuncs prepare without_oid conversion truncate alter_table sequence polymorphism rowtypes returning largeobject with xml +test: plancache limit plpgsql copy2 temp domain rangefuncs prepare without_oid conversion truncate alter_table alter_generic sequence polymorphism rowtypes returning largeobject with xml # run stats by itself because its delay may be insufficient under heavy load test: stats diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule index 0bc5df7..c12bb33 100644 --- a/src/test/regress/serial_schedule +++ b/src/test/regress/serial_schedule @@ -124,6 +124,7 @@ test: without_oid test: conversion test: truncate test: alter_table +test: alter_generic test: sequence test: polymorphism test: rowtypes diff --git a/src/test/regress/sql/alter_generic.sql b/src/test/regress/sql/alter_generic.sql new file mode 100644 index 0000000..8a19949 --- /dev/null +++ b/src/test/regress/sql/alter_generic.sql @@ -0,0 +1,413 @@ +-- +-- Test for ALTER RENAME TO/OWNER TO/SET SCHEMA +-- + +-- Clean up in case a prior regression run failed +SET client_min_messages TO 'warning'; + +DROP ROLE IF EXISTS regtest_alter_user1; +DROP ROLE IF EXISTS regtest_alter_user2; +DROP ROLE IF EXISTS regtest_alter_user3; + +RESET client_min_messages; + +CREATE USER regtest_alter_user3; +CREATE USER regtest_alter_user2; +CREATE USER regtest_alter_user1 IN ROLE regtest_alter_user3; + +CREATE SCHEMA alt_nsp1; +CREATE SCHEMA alt_nsp2; + +GRANT ALL ON SCHEMA alt_nsp1, alt_nsp2 TO public; + +SET search_path = alt_nsp1, public; + +-- +-- Function and Aggregate +-- +SET SESSION AUTHORIZATION regtest_alter_user1; +CREATE FUNCTION alt_func1(int) RETURNS int LANGUAGE sql + AS 'SELECT $1 + 1'; +CREATE FUNCTION alt_func2(int) RETURNS int LANGUAGE sql + AS 'SELECT $1 - 1'; +CREATE AGGREGATE alt_agg1 ( + sfunc1 = int4pl, basetype = int4, stype1 = int4, initcond = 0 +); +CREATE AGGREGATE alt_agg2 ( + sfunc1 = int4mi, basetype = int4, stype1 = int4, initcond = 0 +); +ALTER AGGREGATE alt_func1(int) RENAME TO alt_func3; -- failed (not aggregate) +ALTER AGGREGATE alt_func1(int) OWNER TO regtest_alter_user3; -- failed (not aggregate) +ALTER AGGREGATE alt_func1(int) SET SCHEMA alt_nsp2; -- failed (not aggregate) + +ALTER FUNCTION alt_func1(int) RENAME TO alt_func2; -- failed (name conflict) +ALTER FUNCTION alt_func1(int) RENAME TO alt_func3; -- OK +ALTER FUNCTION alt_func2(int) OWNER TO regtest_alter_user2; -- failed (no role membership) +ALTER FUNCTION alt_func2(int) OWNER TO regtest_alter_user3; -- OK +ALTER FUNCTION alt_func2(int) SET SCHEMA alt_nsp2; -- OK + +ALTER AGGREGATE alt_agg1(int) RENAME TO alt_agg2; -- failed (name conflict) +ALTER AGGREGATE alt_agg1(int) RENAME TO alt_agg3; -- OK +ALTER AGGREGATE alt_agg2(int) OWNER TO regtest_alter_user2; -- failed (no role membership) +ALTER AGGREGATE alt_agg2(int) OWNER TO regtest_alter_user3; -- OK +ALTER AGGREGATE alt_agg2(int) SET SCHEMA alt_nsp2; -- OK + +SET SESSION AUTHORIZATION regtest_alter_user2; +CREATE FUNCTION alt_func1(int) RETURNS int LANGUAGE sql + AS 'SELECT $1 + 2'; +CREATE FUNCTION alt_func2(int) RETURNS int LANGUAGE sql + AS 'SELECT $1 - 2'; +CREATE AGGREGATE alt_agg1 ( + sfunc1 = int4pl, basetype = int4, stype1 = int4, initcond = 100 +); +CREATE AGGREGATE alt_agg2 ( + sfunc1 = int4mi, basetype = int4, stype1 = int4, initcond = -100 +); + +ALTER FUNCTION alt_func3(int) RENAME TO alt_func4; -- failed (not owner) +ALTER FUNCTION alt_func1(int) RENAME TO alt_func4; -- OK +ALTER FUNCTION alt_func3(int) OWNER TO regtest_alter_user2; -- failed (not owner) +ALTER FUNCTION alt_func2(int) OWNER TO regtest_alter_user3; -- failed (no role membership) +ALTER FUNCTION alt_func3(int) SET SCHEMA alt_nsp2; -- failed (not owner) +ALTER FUNCTION alt_func2(int) SET SCHEMA alt_nsp2; -- failed (name conflicts) + +ALTER AGGREGATE alt_agg3(int) RENAME TO alt_agg4; -- failed (not owner) +ALTER AGGREGATE alt_agg1(int) RENAME TO alt_agg4; -- OK +ALTER AGGREGATE alt_agg3(int) OWNER TO regtest_alter_user2; -- failed (not owner) +ALTER AGGREGATE alt_agg2(int) OWNER TO regtest_alter_user3; -- failed (no role membership) +ALTER AGGREGATE alt_agg3(int) SET SCHEMA alt_nsp2; -- failed (not owner) +ALTER AGGREGATE alt_agg2(int) SET SCHEMA alt_nsp2; -- failed (name conflict) + +RESET SESSION AUTHORIZATION; + +SELECT n.nspname, proname, prorettype::regtype, proisagg, a.rolname + FROM pg_proc p, pg_namespace n, pg_authid a + WHERE p.pronamespace = n.oid AND p.proowner = a.oid + AND n.nspname IN ('alt_nsp1', 'alt_nsp2') + ORDER BY nspname, proname; + +-- +-- Collation +-- +SET SESSION AUTHORIZATION regtest_alter_user1; +CREATE COLLATION alt_coll1 (locale = 'C'); +CREATE COLLATION alt_coll2 (locale = 'C'); + +ALTER COLLATION alt_coll1 RENAME TO alt_coll2; -- failed (name conflict) +ALTER COLLATION alt_coll1 RENAME TO alt_coll3; -- OK +ALTER COLLATION alt_coll2 OWNER TO regtest_alter_user2; -- failed (no role membership) +ALTER COLLATION alt_coll2 OWNER TO regtest_alter_user3; -- OK +ALTER COLLATION alt_coll2 SET SCHEMA alt_nsp2; -- OK + +SET SESSION AUTHORIZATION regtest_alter_user2; +CREATE COLLATION alt_coll1 (locale = 'C'); +CREATE COLLATION alt_coll2 (locale = 'C'); + +ALTER COLLATION alt_coll3 RENAME TO alt_coll4; -- failed (not owner) +ALTER COLLATION alt_coll1 RENAME TO alt_coll4; -- OK +ALTER COLLATION alt_coll3 OWNER TO regtest_alter_user2; -- failed (not owner) +ALTER COLLATION alt_coll2 OWNER TO regtest_alter_user3; -- failed (no role membership) +ALTER COLLATION alt_coll3 SET SCHEMA alt_nsp2; -- failed (not owner) +ALTER COLLATION alt_coll2 SET SCHEMA alt_nsp2; -- failed (name conflict) + +RESET SESSION AUTHORIZATION; + +SELECT n.nspname, c.collname, a.rolname + FROM pg_collation c, pg_namespace n, pg_authid a + WHERE c.collnamespace = n.oid AND c.collowner = a.oid + AND n.nspname IN ('alt_nsp1', 'alt_nsp2') + ORDER BY n.nspname, c.collname; + +-- +-- Conversion +-- +SET SESSION AUTHORIZATION regtest_alter_user1; +CREATE CONVERSION alt_conv1 FOR 'LATIN1' TO 'UTF8' FROM iso8859_1_to_utf8; +CREATE CONVERSION alt_conv2 FOR 'LATIN1' TO 'UTF8' FROM iso8859_1_to_utf8; + +ALTER CONVERSION alt_conv1 RENAME TO alt_conv2; -- failed (name conflict) +ALTER CONVERSION alt_conv1 RENAME TO alt_conv3; -- OK +ALTER CONVERSION alt_conv2 OWNER TO regtest_alter_user2; -- failed (no role membership) +ALTER CONVERSION alt_conv2 OWNER TO regtest_alter_user3; -- OK +ALTER CONVERSION alt_conv2 SET SCHEMA alt_nsp2; -- OK + +SET SESSION AUTHORIZATION regtest_alter_user2; +CREATE CONVERSION alt_conv1 FOR 'LATIN1' TO 'UTF8' FROM iso8859_1_to_utf8; +CREATE CONVERSION alt_conv2 FOR 'LATIN1' TO 'UTF8' FROM iso8859_1_to_utf8; + +ALTER CONVERSION alt_conv3 RENAME TO alt_conv4; -- failed (not owner) +ALTER CONVERSION alt_conv1 RENAME TO alt_conv4; -- OK +ALTER CONVERSION alt_conv3 OWNER TO regtest_alter_user2; -- failed (not owner) +ALTER CONVERSION alt_conv2 OWNER TO regtest_alter_user3; -- failed (no role membership) +ALTER CONVERSION alt_conv3 SET SCHEMA alt_nsp2; -- failed (not owner) +ALTER CONVERSION alt_conv2 SET SCHEMA alt_nsp2; -- failed (name conflict) + +RESET SESSION AUTHORIZATION; + +SELECT n.nspname, c.conname, a.rolname + FROM pg_conversion c, pg_namespace n, pg_authid a + WHERE c.connamespace = n.oid AND c.conowner = a.oid + AND n.nspname IN ('alt_nsp1', 'alt_nsp2') + ORDER BY nspname, conname; + +-- +-- Foreign Data Wrapper and Foreign Server +-- +CREATE FOREIGN DATA WRAPPER alt_fdw1; +CREATE FOREIGN DATA WRAPPER alt_fdw2; + +CREATE SERVER alt_fserv1 FOREIGN DATA WRAPPER alt_fdw1; +CREATE SERVER alt_fserv2 FOREIGN DATA WRAPPER alt_fdw2; + +ALTER FOREIGN DATA WRAPPER alt_fdw1 RENAME TO alt_fdw2; -- failed (name conflict) +ALTER FOREIGN DATA WRAPPER alt_fdw1 RENAME TO alt_fdw3; -- OK + +ALTER SERVER alt_fserv1 RENAME TO alt_fserv2; -- failed (name conflict) +ALTER SERVER alt_fserv1 RENAME TO alt_fserv3; -- OK + +SELECT fdwname FROM pg_foreign_data_wrapper WHERE fdwname like 'alt_fdw%'; +SELECT srvname FROM pg_foreign_server WHERE srvname like 'alt_fserv%'; + +-- +-- Procedural Language +-- +CREATE LANGUAGE alt_lang1 HANDLER plpgsql_call_handler; +CREATE LANGUAGE alt_lang2 HANDLER plpgsql_call_handler; + +ALTER LANGUAGE alt_lang1 OWNER TO regtest_alter_user1; -- OK +ALTER LANGUAGE alt_lang2 OWNER TO regtest_alter_user2; -- OK + +SET SESSION AUTHORIZATION regtest_alter_user1; +ALTER LANGUAGE alt_lang1 RENAME TO alt_lang2; -- failed (name conflict) +ALTER LANGUAGE alt_lang2 RENAME TO alt_lang3; -- failed (not owner) +ALTER LANGUAGE alt_lang1 RENAME TO alt_lang3; -- OK + +ALTER LANGUAGE alt_lang2 OWNER TO regtest_alter_user3; -- failed (not owner) +ALTER LANGUAGE alt_lang3 OWNER TO regtest_alter_user2; -- failed (no role membership) +ALTER LANGUAGE alt_lang3 OWNER TO regtest_alter_user3; -- OK + +RESET SESSION AUTHORIZATION; +SELECT lanname, a.rolname + FROM pg_language l, pg_authid a + WHERE l.lanowner = a.oid AND l.lanname like 'alt_lang%' + ORDER BY lanname; + +-- +-- Operator +-- +SET SESSION AUTHORIZATION regtest_alter_user1; + +CREATE OPERATOR @-@ ( leftarg = int4, rightarg = int4, procedure = int4mi ); +CREATE OPERATOR @+@ ( leftarg = int4, rightarg = int4, procedure = int4pl ); + +ALTER OPERATOR @+@(int4, int4) OWNER TO regtest_alter_user2; -- failed (no role membership) +ALTER OPERATOR @+@(int4, int4) OWNER TO regtest_alter_user3; -- OK +ALTER OPERATOR @-@(int4, int4) SET SCHEMA alt_nsp2; -- OK + +SET SESSION AUTHORIZATION regtest_alter_user2; + +CREATE OPERATOR @-@ ( leftarg = int4, rightarg = int4, procedure = int4mi ); + +ALTER OPERATOR @+@(int4, int4) OWNER TO regtest_alter_user2; -- failed (not owner) +ALTER OPERATOR @-@(int4, int4) OWNER TO regtest_alter_user3; -- failed (no role membership) +ALTER OPERATOR @+@(int4, int4) SET SCHEMA alt_nsp2; -- failed (not owner) +-- ALTER OPERATOR @-@(int4, int4) SET SCHEMA alt_nsp2; -- failed (name conflict) +-- XXX it raises raw oid of namespace, it makes unneeded regression test fail... + +RESET SESSION AUTHORIZATION; + +SELECT n.nspname, oprname, a.rolname, oprleft::regtype, oprright::regtype, oprcode::regproc + FROM pg_operator o, pg_namespace n, pg_authid a + WHERE o.oprnamespace = n.oid AND o.oprowner = a.oid + AND n.nspname IN ('alt_nsp1', 'alt_nsp2') + ORDER BY nspname, oprname; + +-- +-- OpFamily and OpClass +-- +CREATE OPERATOR FAMILY alt_opf1 USING hash; +CREATE OPERATOR FAMILY alt_opf2 USING hash; +ALTER OPERATOR FAMILY alt_opf1 USING hash OWNER TO regtest_alter_user1; +ALTER OPERATOR FAMILY alt_opf2 USING hash OWNER TO regtest_alter_user1; + +CREATE OPERATOR CLASS alt_opc1 FOR TYPE uuid USING hash AS STORAGE uuid; +CREATE OPERATOR CLASS alt_opc2 FOR TYPE uuid USING hash AS STORAGE uuid; +ALTER OPERATOR CLASS alt_opc1 USING hash OWNER TO regtest_alter_user1; +ALTER OPERATOR CLASS alt_opc2 USING hash OWNER TO regtest_alter_user1; + +SET SESSION AUTHORIZATION regtest_alter_user1; + +ALTER OPERATOR FAMILY alt_opf1 USING hash RENAME TO alt_opf2; -- failed (name conflict) +ALTER OPERATOR FAMILY alt_opf1 USING hash RENAME TO alt_opf3; -- OK +ALTER OPERATOR FAMILY alt_opf2 USING hash OWNER TO regtest_alter_user2; -- failed (no role membership) +ALTER OPERATOR FAMILY alt_opf2 USING hash OWNER TO regtest_alter_user3; -- OK +ALTER OPERATOR FAMILY alt_opf2 USING hash SET SCHEMA alt_nsp2; -- OK + +ALTER OPERATOR CLASS alt_opc1 USING hash RENAME TO alt_opc2; -- failed (name conflict) +ALTER OPERATOR CLASS alt_opc1 USING hash RENAME TO alt_opc3; -- OK +ALTER OPERATOR CLASS alt_opc2 USING hash OWNER TO regtest_alter_user2; -- failed (no role membership) +ALTER OPERATOR CLASS alt_opc2 USING hash OWNER TO regtest_alter_user3; -- OK +ALTER OPERATOR CLASS alt_opc2 USING hash SET SCHEMA alt_nsp2; -- OK + +RESET SESSION AUTHORIZATION; + +CREATE OPERATOR FAMILY alt_opf1 USING hash; +CREATE OPERATOR FAMILY alt_opf2 USING hash; +ALTER OPERATOR FAMILY alt_opf1 USING hash OWNER TO regtest_alter_user2; +ALTER OPERATOR FAMILY alt_opf2 USING hash OWNER TO regtest_alter_user2; + +CREATE OPERATOR CLASS alt_opc1 FOR TYPE macaddr USING hash AS STORAGE macaddr; +CREATE OPERATOR CLASS alt_opc2 FOR TYPE macaddr USING hash AS STORAGE macaddr; +ALTER OPERATOR CLASS alt_opc1 USING hash OWNER TO regtest_alter_user2; +ALTER OPERATOR CLASS alt_opc2 USING hash OWNER TO regtest_alter_user2; + +SET SESSION AUTHORIZATION regtest_alter_user2; + +ALTER OPERATOR FAMILY alt_opf3 USING hash RENAME TO alt_opf4; -- failed (not owner) +ALTER OPERATOR FAMILY alt_opf1 USING hash RENAME TO alt_opf4; -- OK +ALTER OPERATOR FAMILY alt_opf3 USING hash OWNER TO regtest_alter_user2; -- failed (not owner) +ALTER OPERATOR FAMILY alt_opf2 USING hash OWNER TO regtest_alter_user3; -- failed (no role membership) +ALTER OPERATOR FAMILY alt_opf3 USING hash SET SCHEMA alt_nsp2; -- failed (not owner) +-- ALTER OPERATOR FAMILY alt_opf2 USING hash SET SCHEMA alt_nsp2; -- failed (name conflict) + +ALTER OPERATOR CLASS alt_opc3 USING hash RENAME TO alt_opc4; -- failed (not owner) +ALTER OPERATOR CLASS alt_opc1 USING hash RENAME TO alt_opc4; -- OK +ALTER OPERATOR CLASS alt_opc3 USING hash OWNER TO regtest_alter_user2; -- failed (not owner) +ALTER OPERATOR CLASS alt_opc2 USING hash OWNER TO regtest_alter_user3; -- failed (no role membership) +ALTER OPERATOR CLASS alt_opc3 USING hash SET SCHEMA alt_nsp2; -- failed (not owner) +-- ALTER OPERATOR CLASS alt_opc2 USING hash SET SCHEMA alt_nsp2; -- failed (name conflict) + +RESET SESSION AUTHORIZATION; + +SELECT nspname, opfname, amname, rolname + FROM pg_opfamily o, pg_am m, pg_namespace n, pg_authid a + WHERE o.opfmethod = m.oid AND o.opfnamespace = n.oid AND o.opfowner = a.oid + AND n.nspname IN ('alt_nsp1', 'alt_nsp2') + ORDER BY nspname, opfname; + +SELECT nspname, opcname, amname, rolname + FROM pg_opclass o, pg_am m, pg_namespace n, pg_authid a + WHERE o.opcmethod = m.oid AND o.opcnamespace = n.oid AND o.opcowner = a.oid + AND n.nspname IN ('alt_nsp1', 'alt_nsp2') + ORDER BY nspname, opcname; + +-- +-- Text Search Dictionary +-- +SET SESSION AUTHORIZATION regtest_alter_user1; +CREATE TEXT SEARCH DICTIONARY alt_ts_dict1 (template=simple); +CREATE TEXT SEARCH DICTIONARY alt_ts_dict2 (template=simple); + +ALTER TEXT SEARCH DICTIONARY alt_ts_dict1 RENAME TO alt_ts_dict2; -- failed (name conflict) +ALTER TEXT SEARCH DICTIONARY alt_ts_dict1 RENAME TO alt_ts_dict3; -- OK +ALTER TEXT SEARCH DICTIONARY alt_ts_dict2 OWNER TO regtest_alter_user2; -- failed (no role membership) +ALTER TEXT SEARCH DICTIONARY alt_ts_dict2 OWNER TO regtest_alter_user3; -- OK +ALTER TEXT SEARCH DICTIONARY alt_ts_dict2 SET SCHEMA alt_nsp2; -- OK + +SET SESSION AUTHORIZATION regtest_alter_user2; +CREATE TEXT SEARCH DICTIONARY alt_ts_dict1 (template=simple); +CREATE TEXT SEARCH DICTIONARY alt_ts_dict2 (template=simple); + +ALTER TEXT SEARCH DICTIONARY alt_ts_dict3 RENAME TO alt_ts_dict4; -- failed (not owner) +ALTER TEXT SEARCH DICTIONARY alt_ts_dict1 RENAME TO alt_ts_dict4; -- OK +ALTER TEXT SEARCH DICTIONARY alt_ts_dict3 OWNER TO regtest_alter_user2; -- failed (not owner) +ALTER TEXT SEARCH DICTIONARY alt_ts_dict2 OWNER TO regtest_alter_user3; -- failed (no role membership) +ALTER TEXT SEARCH DICTIONARY alt_ts_dict3 SET SCHEMA alt_nsp2; -- failed (not owner) +ALTER TEXT SEARCH DICTIONARY alt_ts_dict2 SET SCHEMA alt_nsp2; -- failed (name conflict) + +RESET SESSION AUTHORIZATION; + +SELECT nspname, dictname, rolname + FROM pg_ts_dict t, pg_namespace n, pg_authid a + WHERE t.dictnamespace = n.oid AND t.dictowner = a.oid + AND n.nspname in ('alt_nsp1', 'alt_nsp2') + ORDER BY nspname, dictname; + +-- +-- Text Search Configuration +-- +SET SESSION AUTHORIZATION regtest_alter_user1; +CREATE TEXT SEARCH CONFIGURATION alt_ts_conf1 (copy=english); +CREATE TEXT SEARCH CONFIGURATION alt_ts_conf2 (copy=english); + +ALTER TEXT SEARCH CONFIGURATION alt_ts_conf1 RENAME TO alt_ts_conf2; -- failed (name conflict) +ALTER TEXT SEARCH CONFIGURATION alt_ts_conf1 RENAME TO alt_ts_conf3; -- OK +ALTER TEXT SEARCH CONFIGURATION alt_ts_conf2 OWNER TO regtest_alter_user2; -- failed (no role membership) +ALTER TEXT SEARCH CONFIGURATION alt_ts_conf2 OWNER TO regtest_alter_user3; -- OK +ALTER TEXT SEARCH CONFIGURATION alt_ts_conf2 SET SCHEMA alt_nsp2; -- OK + +SET SESSION AUTHORIZATION regtest_alter_user2; +CREATE TEXT SEARCH CONFIGURATION alt_ts_conf1 (copy=english); +CREATE TEXT SEARCH CONFIGURATION alt_ts_conf2 (copy=english); + +ALTER TEXT SEARCH CONFIGURATION alt_ts_conf3 RENAME TO alt_ts_conf4; -- failed (not owner) +ALTER TEXT SEARCH CONFIGURATION alt_ts_conf1 RENAME TO alt_ts_conf4; -- OK +ALTER TEXT SEARCH CONFIGURATION alt_ts_conf3 OWNER TO regtest_alter_user2; -- failed (not owner) +ALTER TEXT SEARCH CONFIGURATION alt_ts_conf2 OWNER TO regtest_alter_user3; -- failed (no role membership) +ALTER TEXT SEARCH CONFIGURATION alt_ts_conf3 SET SCHEMA alt_nsp2; -- failed (not owner) +ALTER TEXT SEARCH CONFIGURATION alt_ts_conf2 SET SCHEMA alt_nsp2; -- failed (name conflict) + +RESET SESSION AUTHORIZATION; + +SELECT nspname, cfgname, rolname + FROM pg_ts_config t, pg_namespace n, pg_authid a + WHERE t.cfgnamespace = n.oid AND t.cfgowner = a.oid + AND n.nspname in ('alt_nsp1', 'alt_nsp2') + ORDER BY nspname, cfgname; + +-- +-- Text Search Template +-- +CREATE TEXT SEARCH TEMPLATE alt_ts_temp1 (lexize=dsimple_lexize); +CREATE TEXT SEARCH TEMPLATE alt_ts_temp2 (lexize=dsimple_lexize); + +ALTER TEXT SEARCH TEMPLATE alt_ts_temp1 RENAME TO alt_ts_temp2; -- failed (name conflict) +ALTER TEXT SEARCH TEMPLATE alt_ts_temp1 RENAME TO alt_ts_temp3; -- OK +ALTER TEXT SEARCH TEMPLATE alt_ts_temp2 SET SCHEMA alt_nsp2; -- OK + +CREATE TEXT SEARCH TEMPLATE alt_ts_temp2 (lexize=dsimple_lexize); +ALTER TEXT SEARCH TEMPLATE alt_ts_temp2 SET SCHEMA alt_nsp2; -- failed (name conflict) + +SELECT nspname, tmplname + FROM pg_ts_template t, pg_namespace n + WHERE t.tmplnamespace = n.oid AND nspname like 'alt_nsp%' + ORDER BY nspname, tmplname; + +-- +-- Text Search Parser +-- + +CREATE TEXT SEARCH PARSER alt_ts_prs1 + (start = prsd_start, gettoken = prsd_nexttoken, end = prsd_end, lextypes = prsd_lextype); +CREATE TEXT SEARCH PARSER alt_ts_prs2 + (start = prsd_start, gettoken = prsd_nexttoken, end = prsd_end, lextypes = prsd_lextype); + +ALTER TEXT SEARCH PARSER alt_ts_prs1 RENAME TO alt_ts_prs2; -- failed (name conflict) +ALTER TEXT SEARCH PARSER alt_ts_prs1 RENAME TO alt_ts_prs3; -- OK +ALTER TEXT SEARCH PARSER alt_ts_prs2 SET SCHEMA alt_nsp2; -- OK + +CREATE TEXT SEARCH PARSER alt_ts_prs2 + (start = prsd_start, gettoken = prsd_nexttoken, end = prsd_end, lextypes = prsd_lextype); +ALTER TEXT SEARCH PARSER alt_ts_prs2 SET SCHEMA alt_nsp2; -- failed (name conflict) + +SELECT nspname, prsname + FROM pg_ts_parser t, pg_namespace n + WHERE t.prsnamespace = n.oid AND nspname like 'alt_nsp%' + ORDER BY nspname, prsname; + +--- +--- Cleanup resources +--- +DROP FOREIGN DATA WRAPPER alt_fdw2 CASCADE; +DROP FOREIGN DATA WRAPPER alt_fdw3 CASCADE; + +DROP LANGUAGE alt_lang2 CASCADE; +DROP LANGUAGE alt_lang3 CASCADE; +DROP LANGUAGE alt_lang4 CASCADE; + +DROP SCHEMA alt_nsp1 CASCADE; +DROP SCHEMA alt_nsp2 CASCADE; + +DROP USER regtest_alter_user1; +DROP USER regtest_alter_user2; +DROP USER regtest_alter_user3;