src/backend/commands/aggregatecmds.c | 61 ------- src/backend/commands/alter.c | 300 +++++++++++++++++++++++++++------- src/backend/commands/conversioncmds.c | 51 ------ src/backend/commands/event_trigger.c | 41 ----- src/backend/commands/foreigncmds.c | 77 --------- src/backend/commands/functioncmds.c | 68 -------- src/backend/commands/opclasscmds.c | 148 ----------------- src/backend/commands/proclang.c | 37 ----- src/backend/commands/tsearchcmds.c | 188 --------------------- src/backend/parser/gram.y | 12 +- src/backend/parser/parse_func.c | 25 +++ src/include/commands/conversioncmds.h | 1 - src/include/commands/defrem.h | 10 -- src/include/commands/event_trigger.h | 1 - src/include/commands/proclang.h | 1 - src/include/parser/parse_func.h | 1 + 16 files changed, 270 insertions(+), 752 deletions(-) diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c index b9f8711..b37d947 100644 --- a/src/backend/commands/aggregatecmds.c +++ b/src/backend/commands/aggregatecmds.c @@ -226,64 +226,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); -} diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c index 8df875b..339890c 100644 --- a/src/backend/commands/alter.c +++ b/src/backend/commands/alter.c @@ -36,6 +36,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" @@ -45,62 +46,238 @@ #include "utils/syscache.h" #include "utils/tqual.h" +static HeapTuple get_catalog_object_by_oid(Relation catalog, Oid objectId); /* - * Executes an ALTER OBJECT / RENAME TO statement. Based on the object - * type, the function appropriate to that type is executed. + * errmsg_obj_already_exists + * + * Returns an error message, to be used as errmsg(), indicating that the + * supplied object name conflicts with an existing object in the given + * namespace, depending on the given object type. + * + * Because of message translatability, we don't use getObjectDescription() + * here. */ -void -ExecRenameStmt(RenameStmt *stmt) +static char * +errmsg_obj_already_exists(ObjectType objtype, const char *objname, + Oid namespaceId, Oid objectId, List *objargs) { - switch (stmt->renameType) + char *errorm; + + switch (objtype) { 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); + case OBJECT_FUNCTION: + errorm = format_elog_string("function %s already exists in schema \"%s\"", + func_signature_string_oid(objectId), + get_namespace_name(namespaceId)); break; - case OBJECT_CONVERSION: - RenameConversion(stmt->object, stmt->newname); + errorm = format_elog_string("conversion \"%s\" already exists in schema \"%s\"", + objname, get_namespace_name(namespaceId)); break; - - case OBJECT_DATABASE: - RenameDatabase(stmt->subname, stmt->newname); + case OBJECT_EVENT_TRIGGER: + errorm = format_elog_string("event trigger \"%s\" already exists", + objname); break; - case OBJECT_FDW: - RenameForeignDataWrapper(stmt->subname, stmt->newname); + errorm = format_elog_string("foreign-data wrapper \"%s\" already exists", + objname); break; - case OBJECT_FOREIGN_SERVER: - RenameForeignServer(stmt->subname, stmt->newname); + errorm = format_elog_string("server \"%s\" already exists", + objname); break; - - case OBJECT_EVENT_TRIGGER: - RenameEventTrigger(stmt->subname, stmt->newname); + case OBJECT_LANGUAGE: + errorm = format_elog_string("language \"%s\" already exists", + objname); break; - - case OBJECT_FUNCTION: - RenameFunction(stmt->object, stmt->objarg, stmt->newname); + case OBJECT_OPCLASS: + Assert(list_length(objargs) == 1); + errorm = format_elog_string("operator class \"%s\" for access method \"%s\" already exists in schema \"%s\"", + objname, strVal(linitial(objargs)), + get_namespace_name(namespaceId)); + break; + case OBJECT_OPFAMILY: + Assert(list_length(objargs) == 1); + errorm = format_elog_string("operator family \"%s\" for access method \"%s\" already exists in schema \"%s\"", + objname, strVal(linitial(objargs)), + get_namespace_name(namespaceId)); + break; + case OBJECT_TSCONFIGURATION: + errorm = format_elog_string("text search configuration \"%s\" already exists", + objname); + break; + case OBJECT_TSDICTIONARY: + errorm = format_elog_string("text search dictionary \"%s\" already exists", + objname); break; + case OBJECT_TSPARSER: + errorm = format_elog_string("text search parser \"%s\" already exists", + objname); + break; + case OBJECT_TSTEMPLATE: + errorm = format_elog_string("text search template \"%s\" already exists", + objname); + break; + default: + elog(ERROR, "unexpected object type: %u", (int) objtype); + errorm = NULL; /* be compiler quiet */ + break; + } - case OBJECT_LANGUAGE: - RenameLanguage(stmt->subname, stmt->newname); + return errorm; +} + +/* + * AlterObjectRename_internal + * + * Generic function to change the name of 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). + */ +static void +AlterObjectRename_internal(ObjectType objtype, List *objname, List *objargs, + char *new_name) +{ + ObjectAddress address; + Relation catalog; + Relation relation; + AttrNumber Anum_namespace; + HeapTuple oldtup; + HeapTuple newtup; + Datum datum; + bool isnull; + Oid namespaceId; + + /* Lookup class-id and object-id */ + address = get_object_address(objtype, objname, objargs, + &relation, + AccessExclusiveLock, false); + Assert(relation == NULL); + catalog = heap_open(address.classId, RowExclusiveLock); + + /* Fetch a catalog entry to be altered */ + oldtup = get_catalog_object_by_oid(catalog, address.objectId); + if (!HeapTupleIsValid(oldtup)) /* should not happen */ + elog(ERROR, "cache lookup failed for object %u of catalog \"%s\"", + address.objectId, RelationGetRelationName(catalog)); + + /* Fetch namespace, if the object class uses them */ + Anum_namespace = get_object_attnum_namespace(address.classId); + if (Anum_namespace != InvalidAttrNumber) + { + datum = heap_getattr(oldtup, Anum_namespace, + RelationGetDescr(catalog), &isnull); + Assert(!isnull); + namespaceId = DatumGetObjectId(datum); + } + else + namespaceId = InvalidOid; + + /* + * Must be owner of the target object + */ + check_object_ownership(GetUserId(), objtype, address, + objname, objargs, relation); + + /* Ensure the new name doesn't exist */ + { + List *objname_new; + ObjectAddress address_new; + Relation relation_new = NULL; + + Assert(list_length(objname) > 0); + objname_new = list_truncate(list_copy(objname), + list_length(objname) - 1); + objname_new = lappend(objname_new, makeString(new_name)); + + /* + * We don't really care about the lock we acquire here: if the object + * exists at all, we're going to abort anyway, and if it doesn't, we + * don't acquire any lock whatsoever. + */ + address_new = get_object_address(objtype, objname_new, objargs, + &relation_new, + AccessShareLock, true); + Assert(relation_new == NULL); + if (OidIsValid(address_new.objectId)) + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("%s", + errmsg_obj_already_exists(objtype, new_name, + namespaceId, + address_new.objectId, + objargs)))); + } + + /* + * 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 catalog tuple with the new name */ + { + AttrNumber Anum_name; + NameData namebuf; + AttrNumber nattrs; + Datum *values; + bool *nulls; + bool *replaces; + + nattrs = RelationGetNumberOfAttributes(catalog); + values = palloc0(nattrs * sizeof(Datum)); + nulls = palloc0(nattrs * sizeof(bool)); + replaces = palloc0(nattrs * sizeof(bool)); + + Anum_name = get_object_attnum_name(address.classId); + 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); + + /* Release memory */ + pfree(values); + pfree(nulls); + pfree(replaces); + } + + /* Perform actual update */ + simple_heap_update(catalog, &newtup->t_self, newtup); + CatalogUpdateIndexes(catalog, newtup); + + heap_close(catalog, NoLock); +} + +/* + * Executes an ALTER OBJECT / RENAME TO statement. Based on the object + * type, the function appropriate to that type is executed. + */ +void +ExecRenameStmt(RenameStmt *stmt) +{ + switch (stmt->renameType) + { + case OBJECT_COLLATION: + RenameCollation(stmt->object, stmt->newname); break; - case OBJECT_OPCLASS: - RenameOpClass(stmt->object, stmt->subname, stmt->newname); + case OBJECT_CONSTRAINT: + RenameConstraint(stmt); break; - case OBJECT_OPFAMILY: - RenameOpFamily(stmt->object, stmt->subname, stmt->newname); + case OBJECT_DATABASE: + RenameDatabase(stmt->subname, stmt->newname); break; case OBJECT_ROLE: @@ -132,25 +309,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_CONVERSION: + case OBJECT_EVENT_TRIGGER: + 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_internal(stmt->renameType, + stmt->object, + stmt->objarg, + stmt->newname); break; default: @@ -530,7 +710,7 @@ ExecAlterOwnerStmt(AlterOwnerStmt *stmt) * the given catalog (which must have been opened by the caller and suitably * locked). NULL is returned if the OID is not found. * - * We try a syscache first, if available. + * We try a syscache first, if available; otherwise an indexscan is used. * * XXX this function seems general in possible usage. Given sufficient callers * elsewhere, we should consider moving it to a more appropriate place. @@ -543,11 +723,7 @@ get_catalog_object_by_oid(Relation catalog, Oid objectId) int oidCacheId = get_object_catcache_oid(classId); if (oidCacheId > 0) - { tuple = SearchSysCacheCopy1(oidCacheId, ObjectIdGetDatum(objectId)); - if (!HeapTupleIsValid(tuple)) /* should not happen */ - return NULL; - } else { Oid oidIndexId = get_object_oid_index(classId); @@ -564,12 +740,9 @@ get_catalog_object_by_oid(Relation catalog, Oid objectId) scan = systable_beginscan(catalog, oidIndexId, true, SnapshotNow, 1, &skey); tuple = systable_getnext(scan); - if (!HeapTupleIsValid(tuple)) - { - systable_endscan(scan); - return NULL; - } - tuple = heap_copytuple(tuple); + + if (HeapTupleIsValid(tuple)) + tuple = heap_copytuple(tuple); systable_endscan(scan); } @@ -598,7 +771,7 @@ AlterObjectOwner_internal(Relation rel, Oid objectId, Oid new_ownerId) Datum datum; bool isnull; Oid old_ownerId; - Oid namespaceId = InvalidOid; + Oid namespaceId; oldtup = get_catalog_object_by_oid(rel, objectId); if (oldtup == NULL) @@ -610,6 +783,7 @@ AlterObjectOwner_internal(Relation rel, Oid objectId, Oid new_ownerId) Assert(!isnull); old_ownerId = DatumGetObjectId(datum); + /* fetch namespace, if the object class uses them */ if (Anum_namespace != InvalidAttrNumber) { datum = heap_getattr(oldtup, Anum_namespace, @@ -617,6 +791,8 @@ AlterObjectOwner_internal(Relation rel, Oid objectId, Oid new_ownerId) Assert(!isnull); namespaceId = DatumGetObjectId(datum); } + else + namespaceId = InvalidOid; if (old_ownerId != new_ownerId) { diff --git a/src/backend/commands/conversioncmds.c b/src/backend/commands/conversioncmds.c index 3a71e33..a5485e4 100644 --- a/src/backend/commands/conversioncmds.c +++ b/src/backend/commands/conversioncmds.c @@ -114,54 +114,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); -} diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c index cb4e658..2e24e0d 100644 --- a/src/backend/commands/event_trigger.c +++ b/src/backend/commands/event_trigger.c @@ -409,47 +409,6 @@ AlterEventTrigger(AlterEventTrigStmt *stmt) heap_close(tgrel, RowExclusiveLock); } - -/* - * Rename event trigger - */ -void -RenameEventTrigger(const char *trigname, const char *newname) -{ - 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); - - 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); -} - - /* * Change event trigger's owner -- by name */ diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c index f10cb52..2d73d2d 100644 --- a/src/backend/commands/foreigncmds.c +++ b/src/backend/commands/foreigncmds.c @@ -200,83 +200,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 453e33a..d5b86db 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -1036,74 +1036,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); -} - /* * 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 099bb39..7aae0d1 100644 --- a/src/backend/commands/opclasscmds.c +++ b/src/backend/commands/opclasscmds.c @@ -1656,154 +1656,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); -} - /* * get_am_oid - given an access method name, look up the OID * diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c index ee860c0..6526b7e 100644 --- a/src/backend/commands/proclang.c +++ b/src/backend/commands/proclang.c @@ -535,43 +535,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); -} - -/* * 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 e545e95..9dbfa0c 100644 --- a/src/backend/commands/tsearchcmds.c +++ b/src/backend/commands/tsearchcmds.c @@ -303,49 +303,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); -} - /* ---------------------- TS Dictionary commands -----------------------*/ /* @@ -529,57 +486,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); -} - -/* * Guts of TS dictionary deletion. */ void @@ -893,50 +799,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); -} - -/* * Guts of TS template deletion. */ void @@ -1233,56 +1095,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); -} - -/* * Guts of TS configuration deletion. */ void diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index e4ff76e..2a0ac7c 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -6772,7 +6772,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; @@ -6800,7 +6800,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; @@ -6810,7 +6810,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; @@ -6820,7 +6820,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; @@ -6838,7 +6838,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; @@ -7011,7 +7011,7 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name { RenameStmt *n = makeNode(RenameStmt); n->renameType = OBJECT_EVENT_TRIGGER; - n->subname = $4; + n->object = list_make1(makeString($4)); n->newname = $7; $$ = (Node *)n; } diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index 8bd88b0..5b5496f 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -1534,6 +1534,31 @@ func_signature_string(List *funcname, int nargs, } /* + * func_signature_string_oid + * As above, but function is identified by oid. + */ +const char * +func_signature_string_oid(Oid func_oid) +{ + HeapTuple tup; + Form_pg_proc proForm; + const char *result; + + tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(func_oid)); + if (!HeapTupleIsValid(tup)) + elog(ERROR, "cache lookup failed for function %u", func_oid); + proForm = (Form_pg_proc) GETSTRUCT(tup); + + result = funcname_signature_string(NameStr(proForm->proname), + proForm->pronargs, + NIL, + proForm->proargtypes.values); + ReleaseSysCache(tup); + + return result; +} + +/* * LookupFuncName * Given a possibly-qualified function name and a set of argument types, * look up the function. diff --git a/src/include/commands/conversioncmds.h b/src/include/commands/conversioncmds.h index 2f9abad..27048cb 100644 --- a/src/include/commands/conversioncmds.h +++ b/src/include/commands/conversioncmds.h @@ -18,6 +18,5 @@ #include "nodes/parsenodes.h" extern void CreateConversionCommand(CreateConversionStmt *parsetree); -extern void RenameConversion(List *name, const char *newname); #endif /* CONVERSIONCMDS_H */ diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h index 2c81b78..f6b2916 100644 --- a/src/include/commands/defrem.h +++ b/src/include/commands/defrem.h @@ -46,7 +46,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 AlterFunction(AlterFunctionStmt *stmt); extern void CreateCast(CreateCastStmt *stmt); extern void DropCastById(Oid castOid); @@ -63,7 +62,6 @@ extern void RemoveOperatorById(Oid operOid); /* commands/aggregatecmds.c */ extern void DefineAggregate(List *name, List *args, bool oldstyle, List *parameters); -extern void RenameAggregate(List *name, List *args, const char *newname); /* commands/opclasscmds.c */ extern void DefineOpClass(CreateOpClassStmt *stmt); @@ -73,28 +71,22 @@ 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 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 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 DefineTSTemplate(List *names, List *parameters); -extern void RenameTSTemplate(List *oldname, const char *newname); 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); @@ -102,8 +94,6 @@ 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/event_trigger.h b/src/include/commands/event_trigger.h index 459d27f..9d2123f 100644 --- a/src/include/commands/event_trigger.h +++ b/src/include/commands/event_trigger.h @@ -36,7 +36,6 @@ extern void RemoveEventTriggerById(Oid ctrigOid); extern Oid get_event_trigger_oid(const char *trigname, bool missing_ok); extern void AlterEventTrigger(AlterEventTrigStmt *stmt); -extern void RenameEventTrigger(const char* trigname, const char *newname); extern void AlterEventTriggerOwner(const char *name, Oid newOwnerId); extern void AlterEventTriggerOwner_oid(Oid, Oid newOwnerId); diff --git a/src/include/commands/proclang.h b/src/include/commands/proclang.h index faf1f1c..3349d4e 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 bool PLTemplateExists(const char *languageName); extern Oid get_language_oid(const char *langname, bool missing_ok); diff --git a/src/include/parser/parse_func.h b/src/include/parser/parse_func.h index 3a9f236..e40e79f 100644 --- a/src/include/parser/parse_func.h +++ b/src/include/parser/parse_func.h @@ -74,6 +74,7 @@ extern const char *funcname_signature_string(const char *funcname, int nargs, List *argnames, const Oid *argtypes); extern const char *func_signature_string(List *funcname, int nargs, List *argnames, const Oid *argtypes); +extern const char *func_signature_string_oid(Oid func_oid); extern Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError);