diff options
Diffstat (limited to 'src/backend/commands')
-rw-r--r-- | src/backend/commands/aggregatecmds.c | 63 | ||||
-rw-r--r-- | src/backend/commands/alter.c | 374 | ||||
-rw-r--r-- | src/backend/commands/collationcmds.c | 48 | ||||
-rw-r--r-- | src/backend/commands/conversioncmds.c | 53 | ||||
-rw-r--r-- | src/backend/commands/event_trigger.c | 46 | ||||
-rw-r--r-- | src/backend/commands/foreigncmds.c | 87 | ||||
-rw-r--r-- | src/backend/commands/functioncmds.c | 61 | ||||
-rw-r--r-- | src/backend/commands/opclasscmds.c | 171 | ||||
-rw-r--r-- | src/backend/commands/proclang.c | 42 | ||||
-rw-r--r-- | src/backend/commands/tsearchcmds.c | 196 |
10 files changed, 324 insertions, 817 deletions
diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c index 144768303a9..e25108192ef 100644 --- a/src/backend/commands/aggregatecmds.c +++ b/src/backend/commands/aggregatecmds.c @@ -226,66 +226,3 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters) transTypeId, /* transition data type */ initval); /* initial condition */ } - - -/* - * RenameAggregate - * Rename an aggregate. - */ -Oid -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); - - return procOid; -} diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c index b565e9b2c33..c2d4bb3ed4d 100644 --- a/src/backend/commands/alter.c +++ b/src/backend/commands/alter.c @@ -21,9 +21,15 @@ #include "catalog/namespace.h" #include "catalog/pg_collation.h" #include "catalog/pg_conversion.h" +#include "catalog/pg_event_trigger.h" +#include "catalog/pg_foreign_data_wrapper.h" +#include "catalog/pg_foreign_server.h" +#include "catalog/pg_language.h" #include "catalog/pg_largeobject.h" #include "catalog/pg_largeobject_metadata.h" #include "catalog/pg_namespace.h" +#include "catalog/pg_opclass.h" +#include "catalog/pg_opfamily.h" #include "catalog/pg_proc.h" #include "catalog/pg_ts_config.h" #include "catalog/pg_ts_dict.h" @@ -43,6 +49,7 @@ #include "commands/trigger.h" #include "commands/typecmds.h" #include "commands/user.h" +#include "parser/parse_func.h" #include "miscadmin.h" #include "tcop/utility.h" #include "utils/builtins.h" @@ -56,49 +63,246 @@ static Oid AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid); /* - * Executes an ALTER OBJECT / RENAME TO statement. Based on the object - * type, the function appropriate to that type is executed. + * Raise an error to the effect that an object of the given name is already + * present in the given namespace. */ -Oid -ExecRenameStmt(RenameStmt *stmt) +static void +report_name_conflict(Oid classId, const char *name) { - switch (stmt->renameType) + char *msgfmt; + + switch (classId) { - case OBJECT_AGGREGATE: - return RenameAggregate(stmt->object, stmt->objarg, stmt->newname); + case EventTriggerRelationId: + msgfmt = gettext_noop("event trigger \"%s\" already exists"); + break; + case ForeignDataWrapperRelationId: + msgfmt = gettext_noop("foreign-data wrapper \"%s\" already exists"); + break; + case ForeignServerRelationId: + msgfmt = gettext_noop("server \"%s\" already exists"); + break; + case LanguageRelationId: + msgfmt = gettext_noop("language \"%s\" already exists"); + break; + default: + elog(ERROR, "unsupported object class %u", classId); + break; + } - case OBJECT_COLLATION: - return RenameCollation(stmt->object, stmt->newname); + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg(msgfmt, name))); +} - case OBJECT_CONSTRAINT: - return RenameConstraint(stmt); +static void +report_namespace_conflict(Oid classId, const char *name, Oid nspOid) +{ + char *msgfmt; - case OBJECT_CONVERSION: - return RenameConversion(stmt->object, stmt->newname); + Assert(OidIsValid(nspOid)); - case OBJECT_DATABASE: - return RenameDatabase(stmt->subname, stmt->newname); + switch (classId) + { + case ConversionRelationId: + Assert(OidIsValid(nspOid)); + msgfmt = gettext_noop("conversion \"%s\" already exists in schema \"%s\""); + break; + case TSParserRelationId: + Assert(OidIsValid(nspOid)); + msgfmt = gettext_noop("text search parser \"%s\" already exists in schema \"%s\""); + break; + case TSDictionaryRelationId: + Assert(OidIsValid(nspOid)); + msgfmt = gettext_noop("text search dictionary \"%s\" already exists in schema \"%s\""); + break; + case TSTemplateRelationId: + Assert(OidIsValid(nspOid)); + msgfmt = gettext_noop("text search template \"%s\" already exists in schema \"%s\""); + break; + case TSConfigRelationId: + Assert(OidIsValid(nspOid)); + msgfmt = gettext_noop("text search configuration \"%s\" already exists in schema \"%s\""); + break; + default: + elog(ERROR, "unsupported object class %u", classId); + break; + } - case OBJECT_FDW: - return RenameForeignDataWrapper(stmt->subname, stmt->newname); + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg(msgfmt, name, get_namespace_name(nspOid)))); +} - case OBJECT_FOREIGN_SERVER: - return RenameForeignServer(stmt->subname, stmt->newname); +/* + * AlterObjectRename_internal + * + * Generic function to rename the given object, for simple cases (won't + * work for tables, nor other cases where we need to do more than change + * the name column of a single catalog entry). + * + * rel: catalog relation containing object (RowExclusiveLock'd by caller) + * objectId: OID of object to be renamed + * new_name: CString representation of new name + */ +static void +AlterObjectRename_internal(Relation rel, Oid objectId, const char *new_name) +{ + Oid classId = RelationGetRelid(rel); + int oidCacheId = get_object_catcache_oid(classId); + int nameCacheId = get_object_catcache_name(classId); + AttrNumber Anum_name = get_object_attnum_name(classId); + AttrNumber Anum_namespace = get_object_attnum_namespace(classId); + AttrNumber Anum_owner = get_object_attnum_owner(classId); + AclObjectKind acl_kind = get_object_aclkind(classId); + HeapTuple oldtup; + HeapTuple newtup; + Datum datum; + bool isnull; + Oid namespaceId; + Oid ownerId; + char *old_name; + AclResult aclresult; + Datum *values; + bool *nulls; + bool *replaces; - case OBJECT_EVENT_TRIGGER: - return RenameEventTrigger(stmt->subname, stmt->newname); + oldtup = SearchSysCache1(oidCacheId, ObjectIdGetDatum(objectId)); + if (!HeapTupleIsValid(oldtup)) + elog(ERROR, "cache lookup failed for object %u of catalog \"%s\"", + objectId, RelationGetRelationName(rel)); - case OBJECT_FUNCTION: - return RenameFunction(stmt->object, stmt->objarg, stmt->newname); + datum = heap_getattr(oldtup, Anum_name, + RelationGetDescr(rel), &isnull); + Assert(!isnull); + old_name = NameStr(*(DatumGetName(datum))); - case OBJECT_LANGUAGE: - return RenameLanguage(stmt->subname, stmt->newname); + /* Get OID of namespace */ + if (Anum_namespace > 0) + { + datum = heap_getattr(oldtup, Anum_namespace, + RelationGetDescr(rel), &isnull); + Assert(!isnull); + namespaceId = DatumGetObjectId(datum); + } + else + namespaceId = InvalidOid; - case OBJECT_OPCLASS: - return RenameOpClass(stmt->object, stmt->subname, stmt->newname); + /* Permission checks ... superusers can always do it */ + if (!superuser()) + { + /* Fail if object does not have an explicit owner */ + if (Anum_owner <= 0) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + (errmsg("must be superuser to rename %s", + getObjectDescriptionOids(classId, objectId))))); - case OBJECT_OPFAMILY: - return RenameOpFamily(stmt->object, stmt->subname, stmt->newname); + /* Otherwise, must be owner of the existing object */ + datum = heap_getattr(oldtup, Anum_owner, + RelationGetDescr(rel), &isnull); + Assert(!isnull); + ownerId = DatumGetObjectId(datum); + + if (!has_privs_of_role(GetUserId(), DatumGetObjectId(ownerId))) + aclcheck_error(ACLCHECK_NOT_OWNER, acl_kind, old_name); + + /* User must have CREATE privilege on the namespace */ + if (OidIsValid(namespaceId)) + { + aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), + ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, ACL_KIND_NAMESPACE, + get_namespace_name(namespaceId)); + } + } + + /* + * Check for duplicate name (more friendly than unique-index failure). + * Since this is just a friendliness check, we can just skip it in cases + * where there isn't suitable support. + */ + if (classId == ProcedureRelationId) + { + Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(oldtup); + + IsThereFunctionInNamespace(new_name, proc->pronargs, + proc->proargtypes, proc->pronamespace); + } + else if (classId == CollationRelationId) + { + Form_pg_collation coll = (Form_pg_collation) GETSTRUCT(oldtup); + + IsThereCollationInNamespace(new_name, coll->collnamespace); + } + else if (classId == OperatorClassRelationId) + { + Form_pg_opclass opc = (Form_pg_opclass) GETSTRUCT(oldtup); + + IsThereOpClassInNamespace(new_name, opc->opcmethod, + opc->opcnamespace); + } + else if (classId == OperatorFamilyRelationId) + { + Form_pg_opfamily opf = (Form_pg_opfamily) GETSTRUCT(oldtup); + + IsThereOpFamilyInNamespace(new_name, opf->opfmethod, + opf->opfnamespace); + } + else if (nameCacheId >= 0) + { + if (OidIsValid(namespaceId)) + { + if (SearchSysCacheExists2(nameCacheId, + CStringGetDatum(new_name), + ObjectIdGetDatum(namespaceId))) + report_namespace_conflict(classId, new_name, namespaceId); + } + else + { + if (SearchSysCacheExists1(nameCacheId, + CStringGetDatum(new_name))) + report_name_conflict(classId, new_name); + } + } + + /* Build modified tuple */ + values = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(Datum)); + nulls = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(bool)); + replaces = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(bool)); + values[Anum_name - 1] = PointerGetDatum(new_name); + replaces[Anum_name - 1] = true; + newtup = heap_modify_tuple(oldtup, RelationGetDescr(rel), + values, nulls, replaces); + + /* Perform actual update */ + simple_heap_update(rel, &oldtup->t_self, newtup); + CatalogUpdateIndexes(rel, newtup); + + /* Release memory */ + pfree(values); + pfree(nulls); + pfree(replaces); + heap_freetuple(newtup); + + ReleaseSysCache(oldtup); +} + +/* + * Executes an ALTER OBJECT / RENAME TO statement. Based on the object + * type, the function appropriate to that type is executed. + */ +Oid +ExecRenameStmt(RenameStmt *stmt) +{ + switch (stmt->renameType) + { + case OBJECT_CONSTRAINT: + return RenameConstraint(stmt); + + case OBJECT_DATABASE: + return RenameDatabase(stmt->subname, stmt->newname); case OBJECT_ROLE: return RenameRole(stmt->subname, stmt->newname); @@ -123,21 +327,43 @@ ExecRenameStmt(RenameStmt *stmt) case OBJECT_TRIGGER: return renametrig(stmt); - case OBJECT_TSPARSER: - return RenameTSParser(stmt->object, stmt->newname); + case OBJECT_DOMAIN: + case OBJECT_TYPE: + return RenameType(stmt); + case OBJECT_AGGREGATE: + case OBJECT_COLLATION: + case OBJECT_CONVERSION: + case OBJECT_EVENT_TRIGGER: + case OBJECT_FDW: + case OBJECT_FOREIGN_SERVER: + case OBJECT_FUNCTION: + case OBJECT_OPCLASS: + case OBJECT_OPFAMILY: + case OBJECT_LANGUAGE: + case OBJECT_TSCONFIGURATION: case OBJECT_TSDICTIONARY: - return RenameTSDictionary(stmt->object, stmt->newname); - + case OBJECT_TSPARSER: case OBJECT_TSTEMPLATE: - return RenameTSTemplate(stmt->object, stmt->newname); + { + ObjectAddress address; + Relation catalog; + Relation relation; - case OBJECT_TSCONFIGURATION: - return RenameTSConfiguration(stmt->object, stmt->newname); + address = get_object_address(stmt->renameType, + stmt->object, stmt->objarg, + &relation, + AccessExclusiveLock, false); + Assert(relation == NULL); - case OBJECT_DOMAIN: - case OBJECT_TYPE: - return RenameType(stmt); + catalog = heap_open(address.classId, RowExclusiveLock); + AlterObjectRename_internal(catalog, + address.objectId, + stmt->newname); + heap_close(catalog, RowExclusiveLock); + + return address.objectId; + } default: elog(ERROR, "unrecognized rename stmt type: %d", @@ -288,43 +514,6 @@ AlterObjectNamespace_oid(Oid classId, Oid objid, Oid nspOid, } /* - * Raise an error to the effect that an object of the given name is already - * present in the given namespace. - */ -static void -report_namespace_conflict(Oid classId, const char *name, Oid nspOid) -{ - char *msgfmt; - - Assert(OidIsValid(nspOid)); - switch (classId) - { - case ConversionRelationId: - msgfmt = gettext_noop("conversion \"%s\" already exists in schema \"%s\""); - break; - case TSParserRelationId: - msgfmt = gettext_noop("text search parser \"%s\" already exists in schema \"%s\""); - break; - case TSDictionaryRelationId: - msgfmt = gettext_noop("text search dictionary \"%s\" already exists in schema \"%s\""); - break; - case TSTemplateRelationId: - msgfmt = gettext_noop("text search template \"%s\" already exists in schema \"%s\""); - break; - case TSConfigRelationId: - msgfmt = gettext_noop("text search configuration \"%s\" already exists in schema \"%s\""); - break; - default: - elog(ERROR, "unsupported object class %u", classId); - break; - } - - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_OBJECT), - errmsg(msgfmt, name, get_namespace_name(nspOid)))); -} - -/* * Generic function to change the namespace of a given object, for simple * cases (won't work for tables, nor other cases where we need to do more * than change the namespace column of a single catalog entry). @@ -403,31 +592,34 @@ AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid) /* * Check for duplicate name (more friendly than unique-index failure). * Since this is just a friendliness check, we can just skip it in cases - * where there isn't a suitable syscache available. + * where there isn't suitable support. */ if (classId == ProcedureRelationId) { - HeapTuple tup; - Form_pg_proc proc; - - tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(objid)); - if (!HeapTupleIsValid(tup)) - elog(ERROR, "cache lookup failed for function %u", objid); - proc = (Form_pg_proc) GETSTRUCT(tup); + Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(tup); IsThereFunctionInNamespace(NameStr(proc->proname), proc->pronargs, proc->proargtypes, nspOid); - heap_freetuple(tup); } else if (classId == CollationRelationId) { - char *collname; + Form_pg_collation coll = (Form_pg_collation) GETSTRUCT(tup); + + IsThereCollationInNamespace(NameStr(coll->collname), nspOid); + } + else if (classId == OperatorClassRelationId) + { + Form_pg_opclass opc = (Form_pg_opclass) GETSTRUCT(tup); + + IsThereOpClassInNamespace(NameStr(opc->opcname), + opc->opcmethod, nspOid); + } + else if (classId == OperatorFamilyRelationId) + { + Form_pg_opfamily opf = (Form_pg_opfamily) GETSTRUCT(tup); - collname = get_collation_name(objid); - if (!collname) - elog(ERROR, "cache lookup failed for collation %u", objid); - IsThereCollationInNamespace(collname, nspOid); - pfree(collname); + IsThereOpFamilyInNamespace(NameStr(opf->opfname), + opf->opfmethod, nspOid); } else if (nameCacheId >= 0 && SearchSysCacheExists2(nameCacheId, name, diff --git a/src/backend/commands/collationcmds.c b/src/backend/commands/collationcmds.c index 67200f87ba5..8326cd0469f 100644 --- a/src/backend/commands/collationcmds.c +++ b/src/backend/commands/collationcmds.c @@ -145,54 +145,6 @@ DefineCollation(List *names, List *parameters) } /* - * Rename collation - */ -Oid -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 */ - IsThereCollationInNamespace(newname, 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); - - return collationOid; -} - -/* * Subroutine for ALTER COLLATION SET SCHEMA and RENAME * * Is there a collation with the same name of the given collation already in diff --git a/src/backend/commands/conversioncmds.c b/src/backend/commands/conversioncmds.c index 35d4d086802..84ab434fd70 100644 --- a/src/backend/commands/conversioncmds.c +++ b/src/backend/commands/conversioncmds.c @@ -114,56 +114,3 @@ CreateConversionCommand(CreateConversionStmt *stmt) return ConversionCreate(conversion_name, namespaceId, GetUserId(), from_encoding, to_encoding, funcoid, stmt->def); } - -/* - * Rename conversion - */ -Oid -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); - - return conversionOid; -} diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c index 99b17a03ef3..9063187f5fa 100644 --- a/src/backend/commands/event_trigger.c +++ b/src/backend/commands/event_trigger.c @@ -417,52 +417,6 @@ AlterEventTrigger(AlterEventTrigStmt *stmt) return trigoid; } - -/* - * Rename event trigger - */ -Oid -RenameEventTrigger(const char *trigname, const char *newname) -{ - Oid evtId; - HeapTuple tup; - Relation rel; - Form_pg_event_trigger evtForm; - - rel = heap_open(EventTriggerRelationId, RowExclusiveLock); - - /* newname must be available */ - if (SearchSysCacheExists1(EVENTTRIGGERNAME, CStringGetDatum(newname))) - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_OBJECT), - errmsg("event trigger \"%s\" already exists", newname))); - - /* trigname must exists */ - tup = SearchSysCacheCopy1(EVENTTRIGGERNAME, CStringGetDatum(trigname)); - if (!HeapTupleIsValid(tup)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("event trigger \"%s\" does not exist", trigname))); - if (!pg_event_trigger_ownercheck(HeapTupleGetOid(tup), GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_EVENT_TRIGGER, - trigname); - - evtId = HeapTupleGetOid(tup); - - evtForm = (Form_pg_event_trigger) GETSTRUCT(tup); - - /* tuple is a copy, so we can rename it now */ - namestrcpy(&(evtForm->evtname), newname); - simple_heap_update(rel, &tup->t_self, tup); - CatalogUpdateIndexes(rel, tup); - - heap_freetuple(tup); - heap_close(rel, RowExclusiveLock); - - return evtId; -} - - /* * Change event trigger's owner -- by name */ diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c index d3af8dc22ab..7700e91c821 100644 --- a/src/backend/commands/foreigncmds.c +++ b/src/backend/commands/foreigncmds.c @@ -200,93 +200,6 @@ GetUserOidFromMapping(const char *username, bool missing_ok) return get_role_oid(username, missing_ok); } - -/* - * Rename foreign-data wrapper - */ -Oid -RenameForeignDataWrapper(const char *oldname, const char *newname) -{ - Oid fdwId; - 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))); - - fdwId = HeapTupleGetOid(tup); - - /* 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); - - return fdwId; -} - - -/* - * Rename foreign server - */ -Oid -RenameForeignServer(const char *oldname, const char *newname) -{ - Oid srvId; - 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))); - - srvId = HeapTupleGetOid(tup); - - /* 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); - - return srvId; -} - - /* * Internal workhorse for changing a data wrapper's owner. * diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index 4f8e82a8e69..7b912332feb 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -1036,65 +1036,6 @@ RemoveFunctionById(Oid funcOid) } } - -/* - * Rename function - */ -Oid -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 */ - IsThereFunctionInNamespace(newname, procForm->pronargs, - procForm->proargtypes, - 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); - - return procOid; -} - /* * Implements the ALTER FUNCTION utility command (except for the * RENAME and OWNER clauses, which are handled as part of the generic @@ -1677,7 +1618,7 @@ DropCastById(Oid castOid) } /* - * Subroutine for ALTER FUNCTION/AGGREGATE SET SCHEMA + * Subroutine for ALTER FUNCTION/AGGREGATE SET SCHEMA/RENAME * * Is there a function with the given name and signature already in the given * namespace? If so, raise an appropriate error message. diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c index 4b57e3dbd60..2cfd89a7f9a 100644 --- a/src/backend/commands/opclasscmds.c +++ b/src/backend/commands/opclasscmds.c @@ -1660,156 +1660,65 @@ RemoveAmProcEntryById(Oid entryOid) heap_close(rel, RowExclusiveLock); } - -/* - * Rename opclass - */ -Oid -RenameOpClass(List *name, const char *access_method, const char *newname) +static char * +get_am_name(Oid amOid) { - 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); + char *result = NULL; - /* 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; + tup = SearchSysCache1(AMOID, ObjectIdGetDatum(amOid)); + if (HeapTupleIsValid(tup)) + { + result = pstrdup(NameStr(((Form_pg_am) GETSTRUCT(tup))->amname)); + ReleaseSysCache(tup); + } + return result; +} +/* + * Subroutine for ALTER OPERATOR CLASS SET SCHEMA/RENAME + * + * Is there an operator class with the given name and signature already + * in the given namespace? If so, raise an appropriate error message. + */ +void +IsThereOpClassInNamespace(const char *opcname, Oid opcmethod, + Oid opcnamespace) +{ /* make sure the new name doesn't exist */ if (SearchSysCacheExists3(CLAAMNAMENSP, - ObjectIdGetDatum(amOid), - CStringGetDatum(newname), - ObjectIdGetDatum(namespaceOid))) - { + ObjectIdGetDatum(opcmethod), + CStringGetDatum(opcname), + ObjectIdGetDatum(opcnamespace))) 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); - - return opcOid; + opcname, + get_am_name(opcmethod), + get_namespace_name(opcnamespace)))); } /* - * Rename opfamily + * Subroutine for ALTER OPERATOR FAMILY SET SCHEMA/RENAME + * + * Is there an operator family with the given name and signature already + * in the given namespace? If so, raise an appropriate error message. */ -Oid -RenameOpFamily(List *name, const char *access_method, const char *newname) +void +IsThereOpFamilyInNamespace(const char *opfname, Oid opfmethod, + Oid opfnamespace) { - 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))) - { + ObjectIdGetDatum(opfmethod), + CStringGetDatum(opfname), + ObjectIdGetDatum(opfnamespace))) 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); - - return opfOid; + opfname, + get_am_name(opfmethod), + get_namespace_name(opfnamespace)))); } /* diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c index 718b71185f8..e6c6d4e5e92 100644 --- a/src/backend/commands/proclang.c +++ b/src/backend/commands/proclang.c @@ -537,48 +537,6 @@ DropProceduralLanguageById(Oid langOid) } /* - * Rename language - */ -Oid -RenameLanguage(const char *oldname, const char *newname) -{ - Oid lanId; - 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))); - - lanId = HeapTupleGetOid(tup); - - /* 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); - - return lanId; -} - -/* * 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/tsearchcmds.c b/src/backend/commands/tsearchcmds.c index aea9fd1fac6..95377ac492d 100644 --- a/src/backend/commands/tsearchcmds.c +++ b/src/backend/commands/tsearchcmds.c @@ -305,51 +305,6 @@ RemoveTSParserById(Oid prsId) heap_close(relation, RowExclusiveLock); } -/* - * ALTER TEXT SEARCH PARSER RENAME - */ -Oid -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); - - return prsId; -} - /* ---------------------- TS Dictionary commands -----------------------*/ /* @@ -535,59 +490,6 @@ DefineTSDictionary(List *names, List *parameters) } /* - * ALTER TEXT SEARCH DICTIONARY RENAME - */ -Oid -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); - - return dictId; -} - -/* * Guts of TS dictionary deletion. */ void @@ -905,52 +807,6 @@ DefineTSTemplate(List *names, List *parameters) } /* - * ALTER TEXT SEARCH TEMPLATE RENAME - */ -Oid -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); - - return tmplId; -} - -/* * Guts of TS template deletion. */ void @@ -1249,58 +1105,6 @@ DefineTSConfiguration(List *names, List *parameters) } /* - * ALTER TEXT SEARCH CONFIGURATION RENAME - */ -Oid -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); - - return cfgId; -} - -/* * Guts of TS configuration deletion. */ void |