ALTER command reworks
The attached patch is my homework at the last commit fest of v9.2.
It consolidates some similar routines into a single generic routines
that handles ALTER RENAME TO, OWNER TO and SET SCHEMA
according to the ObjectProperty in objectaddress.c, but here is
no functionality enhancement.
As existing AlterObjectNamespace() doing, this generic routine
handles only case when a catalog entry is updated without any
extra permission checks or other stuffs.
Thus, RenameSchema was not consolidated due to CREATE
permission checks towards the database, for example.
As patched chunk in commands/alter.c shows, 13 of special
routines were consolidated into AlterObjectRename, 16 of
special ones were consolidated into AlterObjectNamespace,
and 20 of special ones were consolidated into AlterObjectOwner().
My motivation is for minimization of number of places to put
object-access-hook around alter statement. Probably, it shall
be located around or just after simple_heap_update().
This is a groundwork towards ALTER command support in
sepgsql module.
Thanks,
--
KaiGai Kohei <kaigai@kaigai.gr.jp>
Attachments:
pgsql-v9.3-alter-reworks.v1.patchapplication/octet-stream; name=pgsql-v9.3-alter-reworks.v1.patchDownload
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;
The attached patch is a refreshed version of ALTER command
reworks towards the latest tree. Here is few big changes except
for code integration of the code to rename event triggers.
BTW, I had to adjust between oid of pg_largeobject_metadata
and pg_largeobject on three points of this patch, like:
if (classId == LargeObjectRelationId)
classId = LargeObjectMetadataRelationId;
When we supported largeobject permission features, we put
special handling to track dependency of its ownership.
The pg_depend records oid of pg_largeobject, instead of
pg_largeobject_metadata. Thus, we cannot use classId of
ObjectAddress being returned from get_object_address()
as an argument of heap_open() as is, if it indicates oid of
pg_largeobject.
Was it a right decision to track dependency of large object using
oid of pg_largeobject, instead of pg_largeobject_metadata?
IIRC, the reason why we used oid of pg_largeobject is backward
compatibility for applications that tries to reference pg_depend
with built-in oids.
Don't we need to change the specification?
Or, do we continue to implement the code carefully?
Thanks,
2012/7/24 Kohei KaiGai <kaigai@kaigai.gr.jp>:
The attached patch is my homework at the last commit fest of v9.2.
It consolidates some similar routines into a single generic routines
that handles ALTER RENAME TO, OWNER TO and SET SCHEMA
according to the ObjectProperty in objectaddress.c, but here is
no functionality enhancement.As existing AlterObjectNamespace() doing, this generic routine
handles only case when a catalog entry is updated without any
extra permission checks or other stuffs.
Thus, RenameSchema was not consolidated due to CREATE
permission checks towards the database, for example.As patched chunk in commands/alter.c shows, 13 of special
routines were consolidated into AlterObjectRename, 16 of
special ones were consolidated into AlterObjectNamespace,
and 20 of special ones were consolidated into AlterObjectOwner().My motivation is for minimization of number of places to put
object-access-hook around alter statement. Probably, it shall
be located around or just after simple_heap_update().
This is a groundwork towards ALTER command support in
sepgsql module.Thanks,
--
KaiGai Kohei <kaigai@kaigai.gr.jp>
--
KaiGai Kohei <kaigai@kaigai.gr.jp>
Attachments:
pgsql-v9.3-alter-reworks.v2.patchapplication/octet-stream; name=pgsql-v9.3-alter-reworks.v2.patchDownload
src/backend/catalog/objectaddress.c | 254 ++++++++++--
src/backend/catalog/pg_largeobject.c | 102 -----
src/backend/catalog/pg_shdepend.c | 64 ++-
src/backend/commands/aggregatecmds.c | 76 ----
src/backend/commands/alter.c | 611 ++++++++++++++++++++--------
src/backend/commands/collationcmds.c | 167 --------
src/backend/commands/conversioncmds.c | 202 ---------
src/backend/commands/event_trigger.c | 41 --
src/backend/commands/extension.c | 92 -----
src/backend/commands/foreigncmds.c | 77 ----
src/backend/commands/functioncmds.c | 205 ----------
src/backend/commands/opclasscmds.c | 500 -----------------------
src/backend/commands/operatorcmds.c | 146 -------
src/backend/commands/proclang.c | 154 -------
src/backend/commands/tablespace.c | 99 -----
src/backend/commands/tsearchcmds.c | 496 ----------------------
src/backend/nodes/copyfuncs.c | 2 -
src/backend/nodes/equalfuncs.c | 2 -
src/backend/parser/gram.y | 20 +-
src/include/catalog/objectaddress.h | 10 +
src/include/catalog/pg_largeobject.h | 1 -
src/include/commands/alter.h | 7 +-
src/include/commands/collationcmds.h | 3 -
src/include/commands/conversioncmds.h | 4 -
src/include/commands/defrem.h | 33 --
src/include/commands/proclang.h | 1 -
src/include/nodes/parsenodes.h | 2 -
src/test/regress/expected/alter_generic.out | 545 +++++++++++++++++++++++++
src/test/regress/expected/event_trigger.out | 2 +-
src/test/regress/parallel_schedule | 2 +-
src/test/regress/serial_schedule | 1 +
src/test/regress/sql/alter_generic.sql | 413 +++++++++++++++++++
32 files changed, 1699 insertions(+), 2635 deletions(-)
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index 5b8140b..86af155 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -80,7 +80,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[] =
@@ -89,157 +95,287 @@ 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,
},
{
EventTriggerRelationId,
EventTriggerOidIndexId,
- -1,
- InvalidAttrNumber
+ EVENTTRIGGEROID,
+ EVENTTRIGGERNAME,
+ Anum_pg_event_trigger_evtname,
+ InvalidAttrNumber,
+ Anum_pg_event_trigger_evtowner,
+ InvalidAttrNumber,
+ ACL_KIND_EVENT_TRIGGER,
},
{
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
}
};
@@ -1132,16 +1268,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 23111ec..d7e41a3 100644
--- a/src/backend/catalog/pg_shdepend.c
+++ b/src/backend/catalog/pg_shdepend.c
@@ -31,6 +31,7 @@
#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_operator.h"
#include "catalog/pg_opclass.h"
@@ -39,6 +40,7 @@
#include "catalog/pg_shdepend.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_type.h"
+#include "commands/alter.h"
#include "commands/dbcommands.h"
#include "commands/collationcmds.h"
#include "commands/conversioncmds.h"
@@ -1330,22 +1332,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;
@@ -1360,18 +1350,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:
/*
@@ -1380,14 +1358,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;
@@ -1396,8 +1366,36 @@ 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;
+
+ if (classId == LargeObjectRelationId)
+ classId = LargeObjectMetadataRelationId;
+
+ 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;
case EventTriggerRelationId:
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 19f9895..aecb87d 100644
--- a/src/backend/commands/alter.c
+++ b/src/backend/commands/alter.c
@@ -14,10 +14,12 @@
*/
#include "postgres.h"
+#include "access/sysattr.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/pg_largeobject.h"
+#include "catalog/pg_largeobject_metadata.h"
#include "catalog/pg_namespace.h"
#include "commands/alter.h"
#include "commands/collationcmds.h"
@@ -36,66 +38,182 @@
#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"
/*
- * Executes an ALTER OBJECT / RENAME TO statement. Based on the object
- * type, the function appropriate to that type is executed.
+ * 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).
*/
-void
-ExecRenameStmt(RenameStmt *stmt)
+static void
+AlterObjectRename(ObjectType objtype, List *objname, List *objargs,
+ char *new_name)
{
- switch (stmt->renameType)
+ 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)
{
- case OBJECT_AGGREGATE:
- RenameAggregate(stmt->object, stmt->objarg, stmt->newname);
- break;
+ 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;
- case OBJECT_COLLATION:
- RenameCollation(stmt->object, stmt->newname);
- break;
+ Assert(OidIsValid(oidIndexId));
- case OBJECT_CONSTRAINT:
- RenameConstraint(stmt);
- break;
+ ScanKeyInit(&skey,
+ ObjectIdAttributeNumber,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(address.objectId));
- case OBJECT_CONVERSION:
- RenameConversion(stmt->object, stmt->newname);
- break;
+ 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);
- case OBJECT_DATABASE:
- RenameDatabase(stmt->subname, stmt->newname);
- break;
+ systable_endscan(scan);
+ }
- case OBJECT_FDW:
- RenameForeignDataWrapper(stmt->subname, stmt->newname);
- break;
+ /* 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))));
+ }
- case OBJECT_FOREIGN_SERVER:
- RenameForeignServer(stmt->subname, stmt->newname);
- break;
+ /*
+ * Must be owner of the target object
+ */
+ check_object_ownership(GetUserId(), objtype, address,
+ objname, objargs, relation);
- case OBJECT_EVENT_TRIGGER:
- RenameEventTrigger(stmt->subname, stmt->newname);
- break;
+ /*
+ * Must have CREATE privilege on namespace
+ */
+ if (OidIsValid(namespaceId))
+ {
+ AclResult aclresult;
- case OBJECT_FUNCTION:
- RenameFunction(stmt->object, stmt->objarg, stmt->newname);
- break;
+ aclresult = pg_namespace_aclcheck(namespaceId,
+ GetUserId(), ACL_CREATE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
+ get_namespace_name(namespaceId));
+ }
- case OBJECT_LANGUAGE:
- RenameLanguage(stmt->subname, stmt->newname);
- break;
+ /*
+ * 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);
- case OBJECT_OPCLASS:
- RenameOpClass(stmt->object, stmt->subname, stmt->newname);
+ /* Perform actual update */
+ simple_heap_update(catalog, &newtup->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
+ * type, the function appropriate to that type is executed.
+ */
+void
+ExecRenameStmt(RenameStmt *stmt)
+{
+ switch (stmt->renameType)
+ {
+ 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:
@@ -127,25 +245,29 @@ 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_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(stmt->renameType,
+ stmt->object,
+ stmt->objarg,
+ stmt->newname);
break;
default:
@@ -172,10 +294,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;
@@ -185,18 +303,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:
@@ -204,27 +310,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);
@@ -292,35 +422,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:
@@ -465,77 +588,29 @@ 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;
@@ -543,8 +618,224 @@ ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
AlterEventTriggerOwner(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;
+
+ /*
+ * XXX - get_object_address returns Oid of pg_largeobject
+ * catalog towards OBJECT_LARGEOBJECT because of historical
+ * reason. So, we will fix up it here.
+ */
+ if (classId == LargeObjectRelationId)
+ classId = LargeObjectMetadataRelationId;
+
+ catalog = heap_open(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 classId;
+ 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 */
+ classId = RelationGetRelid(catalog);
+ if (classId == LargeObjectMetadataRelationId)
+ classId = LargeObjectRelationId;
+ changeDependencyOnOwner(classId, 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/event_trigger.c b/src/backend/commands/event_trigger.c
index d725360..2604d55 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -408,47 +408,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/extension.c b/src/backend/commands/extension.c
index f1948f4..f0ec2af 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 dcadb3d..8d181e6 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.
@@ -1039,206 +1034,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 71d5323..c254a70 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -2918,7 +2918,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);
@@ -2934,7 +2933,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 d690ca7..9452fcd 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1327,7 +1327,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);
@@ -1341,7 +1340,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 90ea1f9..6a0d9f0 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -6706,7 +6706,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;
@@ -6734,7 +6734,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;
@@ -6744,7 +6744,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;
@@ -6754,7 +6754,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;
@@ -6772,7 +6772,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;
@@ -6945,7 +6945,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;
}
@@ -7139,7 +7139,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;
@@ -7149,7 +7149,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;
@@ -7359,7 +7359,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;
}
@@ -7368,7 +7368,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 9b6d57a..7c0efb9 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 AlterFunctionOwner(List *name, List *argtypes, Oid newOwnerId);
extern void AlterFunctionOwner_oid(Oid procOid, Oid newOwnerId);
extern void AlterFunction(AlterFunctionStmt *stmt);
@@ -61,16 +60,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 */
@@ -81,55 +74,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 f433166..7becb1e 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2168,7 +2168,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;
@@ -2184,7 +2183,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/expected/event_trigger.out b/src/test/regress/expected/event_trigger.out
index 5c8f323..67997bd 100644
--- a/src/test/regress/expected/event_trigger.out
+++ b/src/test/regress/expected/event_trigger.out
@@ -77,7 +77,7 @@ alter role regression_bob superuser;
alter event trigger regress_event_trigger owner to regression_bob;
-- should fail, name collision
alter event trigger regress_event_trigger rename to regress_event_trigger2;
-ERROR: event trigger "regress_event_trigger2" already exists
+ERROR: event trigger regress_event_trigger2 already exists
-- OK
alter event trigger regress_event_trigger rename to regress_event_trigger3;
-- should fail, doesn't exist any more
diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule
index ac29194..0e8a077 100644
--- a/src/test/regress/parallel_schedule
+++ b/src/test/regress/parallel_schedule
@@ -101,7 +101,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 8576a7f..f2813fb 100644
--- a/src/test/regress/serial_schedule
+++ b/src/test/regress/serial_schedule
@@ -125,6 +125,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;
On Mon, Aug 13, 2012 at 3:35 PM, Kohei KaiGai <kaigai@kaigai.gr.jp> wrote:
The attached patch is a refreshed version of ALTER command
reworks towards the latest tree. Here is few big changes except
for code integration of the code to rename event triggers.
This seems to have bit-rotted a bit. Please rebase.
BTW, I had to adjust between oid of pg_largeobject_metadata
and pg_largeobject on three points of this patch, like:if (classId == LargeObjectRelationId)
classId = LargeObjectMetadataRelationId;When we supported largeobject permission features, we put
special handling to track dependency of its ownership.
The pg_depend records oid of pg_largeobject, instead of
pg_largeobject_metadata. Thus, we cannot use classId of
ObjectAddress being returned from get_object_address()
as an argument of heap_open() as is, if it indicates oid of
pg_largeobject.Was it a right decision to track dependency of large object using
oid of pg_largeobject, instead of pg_largeobject_metadata?
IIRC, the reason why we used oid of pg_largeobject is backward
compatibility for applications that tries to reference pg_depend
with built-in oids.
I think it was a terrible decision and I'm pretty sure I said as much
at the time, but I lost the argument, so I'm inclined to think we're
stuck with continuing to support that kludge.
Some other preliminary comments:
- Surely you need to take AccessExclusiveLock on the object being
renamed, not just ShareUpdateExclusiveLock.
- I don't think it's acceptable to assemble the object-type
"object-name" already exists message using getObjectDescription();
it's not good for translators. Use an array of messages, one per
object-type, as we have done in other cases.
- I would like to handle either the RENAME case or the ALTER OWNER
case in one patch, and the other in a follow-on patch. Can you pick
one to do first and remove everything related to the other one?
--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
2012/8/30 Robert Haas <robertmhaas@gmail.com>:
On Mon, Aug 13, 2012 at 3:35 PM, Kohei KaiGai <kaigai@kaigai.gr.jp> wrote:
The attached patch is a refreshed version of ALTER command
reworks towards the latest tree. Here is few big changes except
for code integration of the code to rename event triggers.This seems to have bit-rotted a bit. Please rebase.
BTW, I had to adjust between oid of pg_largeobject_metadata
and pg_largeobject on three points of this patch, like:if (classId == LargeObjectRelationId)
classId = LargeObjectMetadataRelationId;When we supported largeobject permission features, we put
special handling to track dependency of its ownership.
The pg_depend records oid of pg_largeobject, instead of
pg_largeobject_metadata. Thus, we cannot use classId of
ObjectAddress being returned from get_object_address()
as an argument of heap_open() as is, if it indicates oid of
pg_largeobject.Was it a right decision to track dependency of large object using
oid of pg_largeobject, instead of pg_largeobject_metadata?
IIRC, the reason why we used oid of pg_largeobject is backward
compatibility for applications that tries to reference pg_depend
with built-in oids.I think it was a terrible decision and I'm pretty sure I said as much
at the time, but I lost the argument, so I'm inclined to think we're
stuck with continuing to support that kludge.
OK, we will keep to implement carefully...
Some other preliminary comments:
- Surely you need to take AccessExclusiveLock on the object being
renamed, not just ShareUpdateExclusiveLock.
- I don't think it's acceptable to assemble the object-type
"object-name" already exists message using getObjectDescription();
it's not good for translators. Use an array of messages, one per
object-type, as we have done in other cases.
- I would like to handle either the RENAME case or the ALTER OWNER
case in one patch, and the other in a follow-on patch. Can you pick
one to do first and remove everything related to the other one?
OK, I'll split the patch into three (isn't it?) portions; RENAME, SET OWNER
and SET SCHEMA, with all above your suggestions.
Thanks,
--
KaiGai Kohei <kaigai@kaigai.gr.jp>
2012/8/31 Kohei KaiGai <kaigai@kaigai.gr.jp>:
2012/8/30 Robert Haas <robertmhaas@gmail.com>:
On Mon, Aug 13, 2012 at 3:35 PM, Kohei KaiGai <kaigai@kaigai.gr.jp> wrote:
The attached patch is a refreshed version of ALTER command
reworks towards the latest tree. Here is few big changes except
for code integration of the code to rename event triggers.This seems to have bit-rotted a bit. Please rebase.
BTW, I had to adjust between oid of pg_largeobject_metadata
and pg_largeobject on three points of this patch, like:if (classId == LargeObjectRelationId)
classId = LargeObjectMetadataRelationId;When we supported largeobject permission features, we put
special handling to track dependency of its ownership.
The pg_depend records oid of pg_largeobject, instead of
pg_largeobject_metadata. Thus, we cannot use classId of
ObjectAddress being returned from get_object_address()
as an argument of heap_open() as is, if it indicates oid of
pg_largeobject.Was it a right decision to track dependency of large object using
oid of pg_largeobject, instead of pg_largeobject_metadata?
IIRC, the reason why we used oid of pg_largeobject is backward
compatibility for applications that tries to reference pg_depend
with built-in oids.I think it was a terrible decision and I'm pretty sure I said as much
at the time, but I lost the argument, so I'm inclined to think we're
stuck with continuing to support that kludge.OK, we will keep to implement carefully...
Some other preliminary comments:
- Surely you need to take AccessExclusiveLock on the object being
renamed, not just ShareUpdateExclusiveLock.
- I don't think it's acceptable to assemble the object-type
"object-name" already exists message using getObjectDescription();
it's not good for translators. Use an array of messages, one per
object-type, as we have done in other cases.
- I would like to handle either the RENAME case or the ALTER OWNER
case in one patch, and the other in a follow-on patch. Can you pick
one to do first and remove everything related to the other one?OK, I'll split the patch into three (isn't it?) portions; RENAME, SET OWNER
and SET SCHEMA, with all above your suggestions.
As attached, I split off the original one into three portions; for set-schema,
set-owner and rename-to. Please apply them in order of patch filename.
Regarding to the error message, RenameErrorMsgAlreadyExists() was added
to handle per object type messages in case when aclcheck_error() is not
available to utilize.
All the regression test is contained with the 1st patch to make sure the
series of reworks does not change existing behaviors.
Thanks,
--
KaiGai Kohei <kaigai@kaigai.gr.jp>
Attachments:
pgsql-v9.3-alter-reworks.1-schema.v3.patchapplication/octet-stream; name=pgsql-v9.3-alter-reworks.1-schema.v3.patchDownload
src/backend/catalog/objectaddress.c | 257 +++++++++++--
src/backend/commands/alter.c | 107 +++---
src/backend/commands/conversioncmds.c | 50 ---
src/backend/commands/opclasscmds.c | 104 ------
src/backend/commands/operatorcmds.c | 53 ---
src/backend/commands/tsearchcmds.c | 188 ----------
src/backend/nodes/copyfuncs.c | 1 -
src/backend/nodes/equalfuncs.c | 1 -
src/backend/parser/gram.y | 4 +-
src/include/catalog/objectaddress.h | 10 +
src/include/commands/conversioncmds.h | 2 -
src/include/commands/defrem.h | 14 -
src/include/nodes/parsenodes.h | 1 -
src/test/regress/expected/alter_generic.out | 545 ++++++++++++++++++++++++++++
src/test/regress/parallel_schedule | 2 +-
src/test/regress/serial_schedule | 1 +
src/test/regress/sql/alter_generic.sql | 413 +++++++++++++++++++++
17 files changed, 1258 insertions(+), 495 deletions(-)
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index c1e5e1d..820a0db 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -81,7 +81,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[] =
@@ -90,157 +96,287 @@ 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,
},
{
EventTriggerRelationId,
EventTriggerOidIndexId,
- -1,
- InvalidAttrNumber
+ EVENTTRIGGEROID,
+ EVENTTRIGGERNAME,
+ Anum_pg_event_trigger_evtname,
+ InvalidAttrNumber,
+ Anum_pg_event_trigger_evtowner,
+ InvalidAttrNumber,
+ ACL_KIND_EVENT_TRIGGER,
},
{
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
}
};
@@ -1133,17 +1269,88 @@ 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/commands/alter.c b/src/backend/commands/alter.c
index e5b813d..0d3c9ea 100644
--- a/src/backend/commands/alter.c
+++ b/src/backend/commands/alter.c
@@ -173,10 +173,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;
@@ -186,18 +182,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:
@@ -205,25 +189,49 @@ ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt)
AlterTableNamespace(stmt);
break;
- case OBJECT_TSPARSER:
- AlterTSParserNamespace(stmt->object, stmt->newschema);
- break;
-
- case OBJECT_TSDICTIONARY:
- AlterTSDictionaryNamespace(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:
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,
+ AccessExclusiveLock,
+ 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);
+ if (relation)
+ heap_close(relation, NoLock);
+ }
break;
default:
@@ -293,35 +301,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:
diff --git a/src/backend/commands/conversioncmds.c b/src/backend/commands/conversioncmds.c
index e36c91a..af690b8 100644
--- a/src/backend/commands/conversioncmds.c
+++ b/src/backend/commands/conversioncmds.c
@@ -266,53 +266,3 @@ AlterConversionOwner_internal(Relation rel, Oid conversionOid, Oid 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/opclasscmds.c b/src/backend/commands/opclasscmds.c
index 7cf4db0..e26c947 100644
--- a/src/backend/commands/opclasscmds.c
+++ b/src/backend/commands/opclasscmds.c
@@ -1915,58 +1915,6 @@ AlterOpClassOwner_internal(Relation rel, HeapTuple tup, Oid 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
@@ -2122,55 +2070,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 e0ac0e1..0d8dbe4 100644
--- a/src/backend/commands/operatorcmds.c
+++ b/src/backend/commands/operatorcmds.c
@@ -423,56 +423,3 @@ AlterOperatorOwner_internal(Relation rel, Oid operOid, Oid 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/tsearchcmds.c b/src/backend/commands/tsearchcmds.c
index 487c7fb..8d2b4c0 100644
--- a/src/backend/commands/tsearchcmds.c
+++ b/src/backend/commands/tsearchcmds.c
@@ -346,52 +346,6 @@ RenameTSParser(List *oldname, const char *newname)
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 -----------------------*/
/*
@@ -626,54 +580,6 @@ RenameTSDictionary(List *oldname, const char *newname)
}
/*
- * 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
@@ -1091,52 +997,6 @@ RenameTSTemplate(List *oldname, const char *newname)
}
/*
- * 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
@@ -1483,54 +1343,6 @@ RenameTSConfiguration(List *oldname, const char *newname)
}
/*
- * 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
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index f34f704..f5a0aaf 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -2932,7 +2932,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);
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index b4b1c22..3fad36e 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1336,7 +1336,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);
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 5894cb0..7d2ec84 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -7139,7 +7139,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;
@@ -7149,7 +7149,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;
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/commands/conversioncmds.h b/src/include/commands/conversioncmds.h
index 00f468f..778161b 100644
--- a/src/include/commands/conversioncmds.h
+++ b/src/include/commands/conversioncmds.h
@@ -21,7 +21,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 9b6d57a..300f7ea 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -64,8 +64,6 @@ 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,
@@ -85,12 +83,8 @@ extern void RenameOpClass(List *name, const char *access_method, const char *new
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);
@@ -98,8 +92,6 @@ 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);
@@ -107,13 +99,9 @@ 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);
@@ -121,8 +109,6 @@ 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);
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 19178b5..201d366 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2168,7 +2168,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;
diff --git a/src/test/regress/expected/alter_generic.out b/src/test/regress/expected/alter_generic.out
new file mode 100644
index 0000000..002f557
--- /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
+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
+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" for encoding "SQL_ASCII" 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 @+@
+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
+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
+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
+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
+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
+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
+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 ac29194..0e8a077 100644
--- a/src/test/regress/parallel_schedule
+++ b/src/test/regress/parallel_schedule
@@ -101,7 +101,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 8576a7f..f2813fb 100644
--- a/src/test/regress/serial_schedule
+++ b/src/test/regress/serial_schedule
@@ -125,6 +125,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;
pgsql-v9.3-alter-reworks.3-rename.v3.patchapplication/octet-stream; name=pgsql-v9.3-alter-reworks.3-rename.v3.patchDownload
src/backend/commands/aggregatecmds.c | 61 -------
src/backend/commands/alter.c | 309 ++++++++++++++++++++++++++++------
src/backend/commands/collationcmds.c | 2 -
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/include/commands/conversioncmds.h | 1 -
src/include/commands/defrem.h | 10 --
src/include/commands/event_trigger.h | 1 -
src/include/commands/proclang.h | 1 -
15 files changed, 265 insertions(+), 742 deletions(-)
diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c
index c99c07c..bcbab30 100644
--- a/src/backend/commands/aggregatecmds.c
+++ b/src/backend/commands/aggregatecmds.c
@@ -206,64 +206,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 ca50e06..de7b28e 100644
--- a/src/backend/commands/alter.c
+++ b/src/backend/commands/alter.c
@@ -46,60 +46,266 @@
#include "utils/tqual.h"
/*
- * Executes an ALTER OBJECT / RENAME TO statement. Based on the object
- * type, the function appropriate to that type is executed.
+ * RenameErrorMsgAlreadyExists
+ *
+ * It shall raise an error of name conflicits with message according to
+ * object-type. Because of message translation reason, we don't use
+ * getObjectDescription() here.
*/
-void
-ExecRenameStmt(RenameStmt *stmt)
+static void
+RenameErrorMsgAlreadyExists(ObjectType objtype, const char *objname,
+ Oid namespaceId, Oid objectId, List *objargs)
{
- switch (stmt->renameType)
+ 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:
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg(_("function %s already exists in schema \"%s\""),
+ format_procedure(objectId),
+ get_namespace_name(namespaceId))));
break;
-
case OBJECT_CONVERSION:
- RenameConversion(stmt->object, stmt->newname);
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg(_("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:
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg(_("event trigger \"%s\" already exists"),
+ objname)));
break;
-
case OBJECT_FDW:
- RenameForeignDataWrapper(stmt->subname, stmt->newname);
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg(_("foreign-data wrapper \"%s\" already exists"),
+ objname)));
break;
-
case OBJECT_FOREIGN_SERVER:
- RenameForeignServer(stmt->subname, stmt->newname);
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg(_("server \"%s\" already exists"),
+ objname)));
break;
-
- case OBJECT_EVENT_TRIGGER:
- RenameEventTrigger(stmt->subname, stmt->newname);
+ case OBJECT_LANGUAGE:
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg(_("language \"%s\" already exists"),
+ objname)));
break;
-
- case OBJECT_FUNCTION:
- RenameFunction(stmt->object, stmt->objarg, stmt->newname);
+ case OBJECT_OPCLASS:
+ Assert(list_length(objargs) == 1);
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg(_("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);
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg(_("operator family \"%s\" for access method \"%s\" already exists in schema \"%s\""),
+ objname, strVal(linitial(objargs)),
+ get_namespace_name(namespaceId))));
+ break;
+ case OBJECT_TSCONFIGURATION:
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg(_("text search configuration \"%s\" already exists"),
+ objname)));
break;
+ case OBJECT_TSDICTIONARY:
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg(_("text search dictionary \"%s\" already exists"),
+ objname)));
+ break;
+ case OBJECT_TSPARSER:
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg(_("text search parser \"%s\" already exists"),
+ objname)));
+ break;
+ case OBJECT_TSTEMPLATE:
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg(_("text search template \"%s\" already exists"),
+ objname)));
+ break;
+ default:
+ elog(ERROR, "unexpected object type: %u", (int)objtype);
+ break;
+ }
+}
- case OBJECT_LANGUAGE:
- RenameLanguage(stmt->subname, stmt->newname);
+/*
+ * 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;
+ Relation relation_new;
+ 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,
+ AccessExclusiveLock, 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_new,
+ ShareUpdateExclusiveLock, true);
+ if (OidIsValid(address_new.objectId))
+ RenameErrorMsgAlreadyExists(objtype, new_name, namespaceId,
+ address_new.objectId, objargs);
+
+ /*
+ * 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, &newtup->t_self, newtup);
+ CatalogUpdateIndexes(catalog, newtup);
+
+ heap_close(catalog, NoLock);
+
+ if (relation)
+ heap_close(relation, NoLock);
+
+ /* Release memory */
+ pfree(values);
+ pfree(nulls);
+ pfree(replaces);
+}
+
+/*
+ * 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:
@@ -131,25 +337,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(stmt->renameType,
+ stmt->object,
+ stmt->objarg,
+ stmt->newname);
break;
default:
diff --git a/src/backend/commands/collationcmds.c b/src/backend/commands/collationcmds.c
index fafe89e..ccde617 100644
--- a/src/backend/commands/collationcmds.c
+++ b/src/backend/commands/collationcmds.c
@@ -141,7 +141,6 @@ DefineCollation(List *names, List *parameters)
CommandCounterIncrement();
(void) pg_newlocale_from_collation(newoid);
}
-
/*
* Rename collation
*/
@@ -175,7 +174,6 @@ RenameCollation(List *name, const char *newname)
newname,
GetDatabaseEncodingName(),
get_namespace_name(namespaceOid))));
-
/* mustn't match an any-encoding entry, either */
if (SearchSysCacheExists3(COLLNAMEENCNSP,
CStringGetDatum(newname),
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 f685aad..4cb1e81 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -1035,74 +1035,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 3f23515..f2e9b85 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -6706,7 +6706,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;
@@ -6734,7 +6734,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;
@@ -6744,7 +6744,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;
@@ -6754,7 +6754,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;
@@ -6772,7 +6772,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;
@@ -6945,7 +6945,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/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);
pgsql-v9.3-alter-reworks.2-owner.v3.patchapplication/octet-stream; name=pgsql-v9.3-alter-reworks.2-owner.v3.patchDownload
src/backend/catalog/pg_largeobject.c | 102 ------------
src/backend/catalog/pg_shdepend.c | 71 +++++----
src/backend/commands/aggregatecmds.c | 15 --
src/backend/commands/alter.c | 281 +++++++++++++++++++++++++++-------
src/backend/commands/collationcmds.c | 101 ------------
src/backend/commands/conversioncmds.c | 101 ------------
src/backend/commands/extension.c | 92 -----------
src/backend/commands/functioncmds.c | 137 -----------------
src/backend/commands/opclasscmds.c | 248 ------------------------------
src/backend/commands/operatorcmds.c | 93 -----------
src/backend/commands/proclang.c | 117 --------------
src/backend/commands/tablespace.c | 99 ------------
src/backend/commands/tsearchcmds.c | 120 ---------------
src/backend/nodes/copyfuncs.c | 1 -
src/backend/nodes/equalfuncs.c | 1 -
src/backend/parser/gram.y | 4 +-
src/include/catalog/pg_largeobject.h | 1 -
src/include/commands/alter.h | 8 +-
src/include/commands/collationcmds.h | 2 -
src/include/commands/conversioncmds.h | 2 -
src/include/commands/defrem.h | 12 --
src/include/commands/proclang.h | 2 -
src/include/commands/tablespace.h | 1 -
src/include/nodes/parsenodes.h | 1 -
24 files changed, 272 insertions(+), 1340 deletions(-)
diff --git a/src/backend/catalog/pg_largeobject.c b/src/backend/catalog/pg_largeobject.c
index 3322034..b693fde 100644
--- a/src/backend/catalog/pg_largeobject.c
+++ b/src/backend/catalog/pg_largeobject.c
@@ -140,108 +140,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 5a73b48..301812c 100644
--- a/src/backend/catalog/pg_shdepend.c
+++ b/src/backend/catalog/pg_shdepend.c
@@ -32,6 +32,7 @@
#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_operator.h"
#include "catalog/pg_opclass.h"
@@ -40,6 +41,7 @@
#include "catalog/pg_shdepend.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_type.h"
+#include "commands/alter.h"
#include "commands/dbcommands.h"
#include "commands/collationcmds.h"
#include "commands/conversioncmds.h"
@@ -1331,22 +1333,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;
@@ -1361,18 +1351,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:
/*
@@ -1381,14 +1359,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;
@@ -1397,14 +1367,43 @@ shdepReassignOwned(List *roleids, Oid newrole)
AlterForeignDataWrapperOwner_oid(sdepForm->objid, newrole);
break;
- case ExtensionRelationId:
- AlterExtensionOwner_oid(sdepForm->objid, newrole);
- break;
-
case EventTriggerRelationId:
AlterEventTriggerOwner_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:
+ {
+ Oid classId = sdepForm->classid;
+ Relation catalog;
+
+ if (classId == LargeObjectRelationId)
+ classId = LargeObjectMetadataRelationId;
+
+ 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_name(classId),
+ get_object_attnum_acl(classId),
+ get_object_aclkind(classId));
+
+ heap_close(catalog, NoLock);
+ }
+ break;
+
default:
elog(ERROR, "unexpected classid %u", sdepForm->classid);
break;
diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c
index 57adfe8..c99c07c 100644
--- a/src/backend/commands/aggregatecmds.c
+++ b/src/backend/commands/aggregatecmds.c
@@ -267,18 +267,3 @@ RenameAggregate(List *name, List *args, const char *newname)
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 0d3c9ea..ca50e06 100644
--- a/src/backend/commands/alter.c
+++ b/src/backend/commands/alter.c
@@ -15,10 +15,12 @@
#include "postgres.h"
#include "access/htup_details.h"
+#include "access/sysattr.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/pg_largeobject.h"
+#include "catalog/pg_largeobject_metadata.h"
#include "catalog/pg_namespace.h"
#include "commands/alter.h"
#include "commands/collationcmds.h"
@@ -37,10 +39,11 @@
#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"
/*
* Executes an ALTER OBJECT / RENAME TO statement. Based on the object
@@ -467,71 +470,19 @@ 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:
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:
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:
AlterForeignDataWrapperOwner(strVal(linitial(stmt->object)),
newowner);
@@ -545,8 +496,232 @@ ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
AlterEventTriggerOwner(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,
+ AccessExclusiveLock,
+ false);
+ classId = address.classId;
+
+ /*
+ * XXX - get_object_address returns Oid of pg_largeobject
+ * catalog towards OBJECT_LARGEOBJECT because of historical
+ * reason. So, we will fix up it here.
+ */
+ if (classId == LargeObjectRelationId)
+ classId = LargeObjectMetadataRelationId;
+
+ catalog = heap_open(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_name(classId),
+ get_object_attnum_acl(classId),
+ get_object_aclkind(classId));
+ heap_close(catalog, RowExclusiveLock);
+ if (relation)
+ heap_close(relation, 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_name,
+ AttrNumber Anum_acl,
+ AclObjectKind aclkind)
+{
+ HeapTuple oldtup;
+ HeapTuple newtup;
+ Datum datum;
+ bool isnull;
+ Oid classId;
+ 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())
+ {
+ /* must be owner */
+ if (!has_privs_of_role(GetUserId(), old_ownerId))
+ {
+ char *objname;
+ char namebuf[NAMEDATALEN];
+
+ if (Anum_name != InvalidAttrNumber)
+ {
+ datum = heap_getattr(oldtup, Anum_name,
+ RelationGetDescr(catalog), &isnull);
+ Assert(!isnull);
+ objname = NameStr(*DatumGetName(datum));
+ }
+ else
+ {
+ snprintf(namebuf, sizeof(namebuf), "%u",
+ HeapTupleGetOid(oldtup));
+ objname = namebuf;
+ }
+ aclcheck_error(ACLCHECK_NOT_OWNER, aclkind, objname);
+ }
+ /* 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 */
+ classId = RelationGetRelid(catalog);
+ if (classId == LargeObjectMetadataRelationId)
+ classId = LargeObjectRelationId;
+ changeDependencyOnOwner(classId, 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 ad75288..fafe89e 100644
--- a/src/backend/commands/collationcmds.c
+++ b/src/backend/commands/collationcmds.c
@@ -34,9 +34,6 @@
#include "utils/rel.h"
#include "utils/syscache.h"
-static void AlterCollationOwner_internal(Relation rel, Oid collationOid,
- Oid newOwnerId);
-
/*
* CREATE COLLATION
*/
@@ -212,104 +209,6 @@ RenameCollation(List *name, const char *newname)
}
/*
- * 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 af690b8..3a71e33 100644
--- a/src/backend/commands/conversioncmds.c
+++ b/src/backend/commands/conversioncmds.c
@@ -31,9 +31,6 @@
#include "utils/rel.h"
#include "utils/syscache.h"
-static void AlterConversionOwner_internal(Relation rel, Oid conversionOid,
- Oid newOwnerId);
-
/*
* CREATE CONVERSION
*/
@@ -168,101 +165,3 @@ RenameConversion(List *name, const char *newname)
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);
-}
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index ec8aa17..5712fe1 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -2750,95 +2750,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/functioncmds.c b/src/backend/commands/functioncmds.c
index bf04073..f685aad 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -65,11 +65,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.
@@ -1109,138 +1104,6 @@ RenameFunction(List *name, List *argtypes, const char *newname)
}
/*
- * 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
* ALTER framework).
diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c
index e26c947..099bb39 100644
--- a/src/backend/commands/opclasscmds.c
+++ b/src/backend/commands/opclasscmds.c
@@ -81,11 +81,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
@@ -1810,249 +1805,6 @@ RenameOpFamily(List *name, const char *access_method, const char *newname)
}
/*
- * 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);
- }
-}
-
-/*
- * 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
*
* If missing_ok is false, throw an error if access method not found. If
diff --git a/src/backend/commands/operatorcmds.c b/src/backend/commands/operatorcmds.c
index 0d8dbe4..f31bf36 100644
--- a/src/backend/commands/operatorcmds.c
+++ b/src/backend/commands/operatorcmds.c
@@ -51,9 +51,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
@@ -333,93 +330,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);
-}
diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c
index 31139bd..ee860c0 100644
--- a/src/backend/commands/proclang.c
+++ b/src/backend/commands/proclang.c
@@ -55,9 +55,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
@@ -575,120 +572,6 @@ RenameLanguage(const char *oldname, const char *newname)
}
/*
- * 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 d1718c1..08899ae 100644
--- a/src/backend/commands/tablespace.c
+++ b/src/backend/commands/tablespace.c
@@ -884,105 +884,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 8d2b4c0..e545e95 100644
--- a/src/backend/commands/tsearchcmds.c
+++ b/src/backend/commands/tsearchcmds.c
@@ -716,66 +716,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 -----------------------*/
/*
@@ -1391,66 +1331,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 f5a0aaf..9efc156 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -2947,7 +2947,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 3fad36e..afd0a96 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1349,7 +1349,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 7d2ec84..3f23515 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -7359,7 +7359,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;
}
@@ -7368,7 +7368,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/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..6665121 100644
--- a/src/include/commands/alter.h
+++ b/src/include/commands/alter.h
@@ -25,5 +25,11 @@ 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_name,
+ AttrNumber Anum_acl,
+ AclObjectKind aclkind);
#endif /* ALTER_H */
diff --git a/src/include/commands/collationcmds.h b/src/include/commands/collationcmds.h
index 0587c4f..6d9db09 100644
--- a/src/include/commands/collationcmds.h
+++ b/src/include/commands/collationcmds.h
@@ -19,8 +19,6 @@
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 778161b..2f9abad 100644
--- a/src/include/commands/conversioncmds.h
+++ b/src/include/commands/conversioncmds.h
@@ -19,7 +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);
#endif /* CONVERSIONCMDS_H */
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 300f7ea..2c81b78 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -47,8 +47,6 @@ 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);
extern void CreateCast(CreateCastStmt *stmt);
extern void DropCastById(Oid castOid);
@@ -61,15 +59,11 @@ 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);
/* 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 */
extern void DefineOpClass(CreateOpClassStmt *stmt);
@@ -81,10 +75,6 @@ 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 AlterOpFamilyOwner(List *name, const char *access_method, Oid newOwnerId);
-extern void AlterOpFamilyOwner_oid(Oid opfamilyOid, Oid newOwnerId);
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);
@@ -98,7 +88,6 @@ 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 DefineTSTemplate(List *names, List *parameters);
extern void RenameTSTemplate(List *oldname, const char *newname);
@@ -108,7 +97,6 @@ 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 text *serialize_deflist(List *deflist);
extern List *deserialize_deflist(Datum txt);
diff --git a/src/include/commands/proclang.h b/src/include/commands/proclang.h
index 17d0972..faf1f1c 100644
--- a/src/include/commands/proclang.h
+++ b/src/include/commands/proclang.h
@@ -17,8 +17,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);
extern Oid get_language_oid(const char *langname, bool missing_ok);
diff --git a/src/include/commands/tablespace.h b/src/include/commands/tablespace.h
index fe8b6a5..be45c87 100644
--- a/src/include/commands/tablespace.h
+++ b/src/include/commands/tablespace.h
@@ -42,7 +42,6 @@ typedef struct TableSpaceOpts
extern void CreateTableSpace(CreateTableSpaceStmt *stmt);
extern void DropTableSpace(DropTableSpaceStmt *stmt);
extern void RenameTableSpace(const char *oldname, const char *newname);
-extern void AlterTableSpaceOwner(const char *name, Oid newOwnerId);
extern void AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt);
extern void TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo);
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 201d366..7a2fbde 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2183,7 +2183,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;
Excerpts from Kohei KaiGai's message of lun sep 10 08:08:32 -0300 2012:
As attached, I split off the original one into three portions; for set-schema,
set-owner and rename-to. Please apply them in order of patch filename.
Regarding to the error message, RenameErrorMsgAlreadyExists() was added
to handle per object type messages in case when aclcheck_error() is not
available to utilize.
All the regression test is contained with the 1st patch to make sure the
series of reworks does not change existing behaviors.
I checked this and noticed that the regression test has a couple of
failures -- see below. I think we should remove the test for the first
two hunks, and fix the query for the final one to remove the offending
column.
The good news is that I ran this without applying the whole patch, only
the new regression test' files. I didn't check the files in detail.
I have skimmed over the patches and they seem reasonable too; I will
look at them in more detail later. I think we should go ahead and apply
the (tweaked) regression test alone, as a first step.
*** /pgsql/source/HEAD/src/test/regress/expected/alter_generic.out 2012-09-27 17:23:05.000000000 -0300
--- /home/alvherre/Code/pgsql/build/HEAD/src/test/regress/results/alter_generic.out 2012-09-27 17:29:21.000000000 -0300
***************
*** 106,112 ****
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" for encoding "SQL_ASCII" 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"
--- 106,112 ----
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" for encoding "UTF8" 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"
***************
*** 125,131 ****
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
--- 125,131 ----
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 "UTF8" 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
***************
*** 334,341 ****
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
--- 334,341 ----
ORDER BY nspname, opfname;
nspname | opfname | amname | rolname
----------+----------+--------+---------------------
! alt_nsp1 | alt_opc1 | hash | alvherre
! alt_nsp1 | alt_opc2 | hash | alvherre
alt_nsp1 | alt_opf2 | hash | regtest_alter_user2
alt_nsp1 | alt_opf3 | hash | regtest_alter_user1
alt_nsp1 | alt_opf4 | hash | regtest_alter_user2
======================================================================
--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
Excerpts from Kohei KaiGai's message of lun sep 10 08:08:32 -0300 2012:
As attached, I split off the original one into three portions; for set-schema,
set-owner and rename-to. Please apply them in order of patch filename.
Hmm, in the first patch, it seems to me we can simplify
AlterObjectNamespace's signature: instead of passing all the details of
the object class (cache Ids and attribute numbers and so on), just do
AlterObjectNamespace(catalog-containing-object, objectId, newNamespaceOid)
AlterObjectNamespace then looks up the catcache_oid and so on
internally. The only difference from what's happening in the submitted
patch is that in the AlterCollationNamespace case, AlterObjectNamespace
would have to look them up instead of getting them directly from the
caller as the patch currently has it.
--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
Excerpts from Alvaro Herrera's message of vie sep 28 18:17:32 -0300 2012:
Excerpts from Kohei KaiGai's message of lun sep 10 08:08:32 -0300 2012:
As attached, I split off the original one into three portions; for set-schema,
set-owner and rename-to. Please apply them in order of patch filename.Hmm, in the first patch, it seems to me we can simplify
AlterObjectNamespace's signature: instead of passing all the details of
the object class (cache Ids and attribute numbers and so on), just doAlterObjectNamespace(catalog-containing-object, objectId, newNamespaceOid)
Like in the attached reworked version, in which I renamed the function
to AlterObjectNamespace_internal because the other name seemed a bit
wrong in the fact of the existing AlterObjectNamespace_oid.
I also made the ALTER FUNCTION case go through
AlterObjectNamespace_internal; it seems pointless to have a separate
code path to go through when the generic one does just fine (also, this
makes functions identical to collations in implementation). That's one
less hook point for sepgsql, I guess.
--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
Attachments:
pgsql-v9.3-alter-reworks.1-schema.v4.patchapplication/octet-stream; name=pgsql-v9.3-alter-reworks.1-schema.v4.patchDownload
*** a/src/backend/catalog/objectaddress.c
--- b/src/backend/catalog/objectaddress.c
***************
*** 63,69 ****
#include "rewrite/rewriteSupport.h"
#include "storage/lmgr.h"
#include "storage/sinval.h"
- #include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
--- 63,68 ----
***************
*** 81,87 **** typedef struct
--- 80,91 ----
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 (name,namespace) */
+ 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[] =
***************
*** 90,246 **** static ObjectPropertyType ObjectProperty[] =
CastRelationId,
CastOidIndexId,
-1,
! InvalidAttrNumber
},
{
CollationRelationId,
CollationOidIndexId,
COLLOID,
! Anum_pg_collation_collnamespace
},
{
ConstraintRelationId,
ConstraintOidIndexId,
CONSTROID,
! Anum_pg_constraint_connamespace
},
{
ConversionRelationId,
ConversionOidIndexId,
CONVOID,
! Anum_pg_conversion_connamespace
},
{
DatabaseRelationId,
DatabaseOidIndexId,
DATABASEOID,
! InvalidAttrNumber
},
{
ExtensionRelationId,
ExtensionOidIndexId,
-1,
! InvalidAttrNumber /* extension doesn't belong to extnamespace */
},
{
ForeignDataWrapperRelationId,
ForeignDataWrapperOidIndexId,
FOREIGNDATAWRAPPEROID,
! InvalidAttrNumber
},
{
ForeignServerRelationId,
ForeignServerOidIndexId,
FOREIGNSERVEROID,
! InvalidAttrNumber
},
{
ProcedureRelationId,
ProcedureOidIndexId,
PROCOID,
! Anum_pg_proc_pronamespace
},
{
LanguageRelationId,
LanguageOidIndexId,
LANGOID,
InvalidAttrNumber,
},
{
LargeObjectMetadataRelationId,
LargeObjectMetadataOidIndexId,
-1,
! InvalidAttrNumber
},
{
OperatorClassRelationId,
OpclassOidIndexId,
CLAOID,
Anum_pg_opclass_opcnamespace,
},
{
OperatorRelationId,
OperatorOidIndexId,
OPEROID,
! Anum_pg_operator_oprnamespace
},
{
OperatorFamilyRelationId,
OpfamilyOidIndexId,
OPFAMILYOID,
! Anum_pg_opfamily_opfnamespace
},
{
AuthIdRelationId,
AuthIdOidIndexId,
AUTHOID,
! InvalidAttrNumber
},
{
RewriteRelationId,
RewriteOidIndexId,
-1,
! InvalidAttrNumber
},
{
NamespaceRelationId,
NamespaceOidIndexId,
NAMESPACEOID,
! InvalidAttrNumber
},
{
RelationRelationId,
ClassOidIndexId,
RELOID,
! Anum_pg_class_relnamespace
},
{
TableSpaceRelationId,
TablespaceOidIndexId,
TABLESPACEOID,
! InvalidAttrNumber
},
{
TriggerRelationId,
TriggerOidIndexId,
-1,
! InvalidAttrNumber
},
{
EventTriggerRelationId,
EventTriggerOidIndexId,
! -1,
! InvalidAttrNumber
},
{
TSConfigRelationId,
TSConfigOidIndexId,
TSCONFIGOID,
! Anum_pg_ts_config_cfgnamespace
},
{
TSDictionaryRelationId,
TSDictionaryOidIndexId,
TSDICTOID,
! Anum_pg_ts_dict_dictnamespace
},
{
TSParserRelationId,
TSParserOidIndexId,
TSPARSEROID,
! Anum_pg_ts_parser_prsnamespace
},
{
TSTemplateRelationId,
TSTemplateOidIndexId,
TSTEMPLATEOID,
Anum_pg_ts_template_tmplnamespace,
},
{
TypeRelationId,
TypeOidIndexId,
TYPEOID,
! Anum_pg_type_typnamespace
}
};
--- 94,380 ----
CastRelationId,
CastOidIndexId,
-1,
! -1,
! InvalidAttrNumber,
! InvalidAttrNumber,
! InvalidAttrNumber,
! InvalidAttrNumber,
! -1
},
{
CollationRelationId,
CollationOidIndexId,
COLLOID,
! -1, /* COLLNAMEENCNSP also takes encoding */
! Anum_pg_collation_collname,
! Anum_pg_collation_collnamespace,
! Anum_pg_collation_collowner,
! InvalidAttrNumber,
! ACL_KIND_COLLATION
},
{
ConstraintRelationId,
ConstraintOidIndexId,
CONSTROID,
! -1,
! Anum_pg_constraint_conname,
! Anum_pg_constraint_connamespace,
! InvalidAttrNumber,
! InvalidAttrNumber,
! -1
},
{
ConversionRelationId,
ConversionOidIndexId,
CONVOID,
! CONNAMENSP,
! Anum_pg_conversion_conname,
! Anum_pg_conversion_connamespace,
! Anum_pg_conversion_conowner,
! InvalidAttrNumber,
! ACL_KIND_CONVERSION
},
{
DatabaseRelationId,
DatabaseOidIndexId,
DATABASEOID,
! -1,
! Anum_pg_database_datname,
! InvalidAttrNumber,
! Anum_pg_database_datdba,
! Anum_pg_database_datacl,
! ACL_KIND_DATABASE
},
{
ExtensionRelationId,
ExtensionOidIndexId,
-1,
! -1,
! Anum_pg_extension_extname,
! InvalidAttrNumber, /* extension doesn't belong to extnamespace */
! Anum_pg_extension_extowner,
! InvalidAttrNumber,
! ACL_KIND_EXTENSION
},
{
ForeignDataWrapperRelationId,
ForeignDataWrapperOidIndexId,
FOREIGNDATAWRAPPEROID,
! 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,
! FOREIGNSERVERNAME,
! Anum_pg_foreign_server_srvname,
! InvalidAttrNumber,
! Anum_pg_foreign_server_srvowner,
! Anum_pg_foreign_server_srvacl,
! ACL_KIND_FOREIGN_SERVER
},
{
ProcedureRelationId,
ProcedureOidIndexId,
PROCOID,
! -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,
! -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,
! -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,
! -1, /* OPFAMILYAMNAMENSP also takes opfmethod */
! Anum_pg_opfamily_opfname,
! Anum_pg_opfamily_opfnamespace,
! Anum_pg_opfamily_opfowner,
! InvalidAttrNumber,
! ACL_KIND_OPFAMILY
},
{
AuthIdRelationId,
AuthIdOidIndexId,
AUTHOID,
! AUTHNAME,
! Anum_pg_authid_rolname,
! InvalidAttrNumber,
! InvalidAttrNumber,
! InvalidAttrNumber,
! -1
},
{
RewriteRelationId,
RewriteOidIndexId,
-1,
! -1,
! Anum_pg_rewrite_rulename,
! InvalidAttrNumber,
! InvalidAttrNumber,
! InvalidAttrNumber,
! -1
},
{
NamespaceRelationId,
NamespaceOidIndexId,
NAMESPACEOID,
! NAMESPACENAME,
! Anum_pg_namespace_nspname,
! InvalidAttrNumber,
! Anum_pg_namespace_nspowner,
! Anum_pg_namespace_nspacl,
! ACL_KIND_NAMESPACE
},
{
RelationRelationId,
ClassOidIndexId,
RELOID,
! RELNAMENSP,
! Anum_pg_class_relname,
! Anum_pg_class_relnamespace,
! Anum_pg_class_relowner,
! Anum_pg_class_relacl,
! ACL_KIND_CLASS
},
{
TableSpaceRelationId,
TablespaceOidIndexId,
TABLESPACEOID,
! -1,
! Anum_pg_tablespace_spcname,
! InvalidAttrNumber,
! Anum_pg_tablespace_spcowner,
! Anum_pg_tablespace_spcacl,
! ACL_KIND_TABLESPACE
},
{
TriggerRelationId,
TriggerOidIndexId,
-1,
! -1,
! Anum_pg_trigger_tgname,
! InvalidAttrNumber,
! InvalidAttrNumber,
! InvalidAttrNumber,
! -1,
},
{
EventTriggerRelationId,
EventTriggerOidIndexId,
! EVENTTRIGGEROID,
! EVENTTRIGGERNAME,
! Anum_pg_event_trigger_evtname,
! InvalidAttrNumber,
! Anum_pg_event_trigger_evtowner,
! InvalidAttrNumber,
! ACL_KIND_EVENT_TRIGGER,
},
{
TSConfigRelationId,
TSConfigOidIndexId,
TSCONFIGOID,
! TSCONFIGNAMENSP,
! Anum_pg_ts_config_cfgname,
! Anum_pg_ts_config_cfgnamespace,
! Anum_pg_ts_config_cfgowner,
! InvalidAttrNumber,
! ACL_KIND_TSCONFIGURATION
},
{
TSDictionaryRelationId,
TSDictionaryOidIndexId,
TSDICTOID,
! TSDICTNAMENSP,
! Anum_pg_ts_dict_dictname,
! Anum_pg_ts_dict_dictnamespace,
! Anum_pg_ts_dict_dictowner,
! InvalidAttrNumber,
! ACL_KIND_TSDICTIONARY
},
{
TSParserRelationId,
TSParserOidIndexId,
TSPARSEROID,
! 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,
! TYPENAMENSP,
! Anum_pg_type_typname,
! Anum_pg_type_typnamespace,
! Anum_pg_type_typowner,
! Anum_pg_type_typacl,
! ACL_KIND_TYPE
}
};
***************
*** 1133,1149 **** get_object_namespace(const ObjectAddress *address)
}
/*
* Find ObjectProperty structure by class_id.
*/
static ObjectPropertyType *
get_object_property_data(Oid class_id)
{
int index;
for (index = 0; index < lengthof(ObjectProperty); index++)
if (ObjectProperty[index].class_oid == class_id)
return &ObjectProperty[index];
! elog(ERROR, "unrecognized class id: %u", class_id);
! return NULL; /* not reached */
}
--- 1267,1363 ----
}
/*
+ * 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 to speed up multiple consecutive lookups of 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];
+ }
+ }
! ereport(ERROR,
! (errmsg_internal("unrecognized class id: %u", class_id)));
}
*** a/src/backend/commands/alter.c
--- b/src/backend/commands/alter.c
***************
*** 173,182 **** 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;
--- 173,178 ----
***************
*** 186,203 **** 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:
--- 182,187 ----
***************
*** 205,229 **** ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt)
AlterTableNamespace(stmt);
break;
! case OBJECT_TSPARSER:
! AlterTSParserNamespace(stmt->object, stmt->newschema);
break;
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);
break;
default:
--- 189,230 ----
AlterTableNamespace(stmt);
break;
! 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:
case OBJECT_TSTEMPLATE:
case OBJECT_TSCONFIGURATION:
! {
! Relation catalog;
! Relation relation;
! Oid classId;
! Oid nspOid;
! ObjectAddress address;
!
! address = get_object_address(stmt->objectType,
! stmt->object,
! stmt->objarg,
! &relation,
! AccessExclusiveLock,
! false);
! Assert(relation == NULL);
! classId = address.classId;
! catalog = heap_open(classId, RowExclusiveLock);
! nspOid = LookupCreationNamespace(stmt->newschema);
!
! AlterObjectNamespace_internal(catalog, address.objectId,
! nspOid);
! heap_close(catalog, RowExclusiveLock);
! }
break;
default:
***************
*** 293,327 **** 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);
break;
default:
--- 294,316 ----
break;
case OCLASS_CONVERSION:
case OCLASS_OPERATOR:
case OCLASS_OPCLASS:
case OCLASS_OPFAMILY:
case OCLASS_TSPARSER:
case OCLASS_TSDICT:
case OCLASS_TSTEMPLATE:
case OCLASS_TSCONFIG:
! {
! Relation catalog;
!
! catalog = heap_open(classId, RowExclusiveLock);
!
! oldNspOid = AlterObjectNamespace_internal(catalog, objid,
! nspOid);
!
! heap_close(catalog, RowExclusiveLock);
! }
break;
default:
***************
*** 336,367 **** AlterObjectNamespace_oid(Oid classId, Oid objid, Oid nspOid)
* 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).
*
- * The AlterFooNamespace() calls just above will call a function whose job
- * is to lookup the arguments for the generic function here.
- *
* rel: catalog relation containing object (RowExclusiveLock'd by caller)
- * oidCacheId: syscache that indexes this catalog by OID
- * nameCacheId: syscache that indexes this catalog by name and namespace
- * (pass -1 if there is none)
* objid: OID of object to change the namespace of
* nspOid: OID of new namespace
- * Anum_name: column number of catalog's name column
- * Anum_namespace: column number of catalog's namespace column
- * Anum_owner: column number of catalog's owner column, or -1 if none
- * acl_kind: ACL type for object, or -1 if none assigned
- *
- * If the object does not have an owner or permissions, pass -1 for
- * Anum_owner and acl_kind. In this case the calling user must be superuser.
*
* Returns the OID of the object's previous namespace.
*/
Oid
! AlterObjectNamespace(Relation rel, int oidCacheId, int nameCacheId,
! Oid objid, Oid nspOid,
! int Anum_name, int Anum_namespace, int Anum_owner,
! AclObjectKind acl_kind)
{
Oid classId = RelationGetRelid(rel);
Oid oldNspOid;
Datum name,
namespace;
--- 325,346 ----
* 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).
*
* rel: catalog relation containing object (RowExclusiveLock'd by caller)
* objid: OID of object to change the namespace of
* nspOid: OID of new namespace
*
* Returns the OID of the object's previous namespace.
*/
Oid
! AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid)
{
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);
Oid oldNspOid;
Datum name,
namespace;
***************
*** 379,385 **** AlterObjectNamespace(Relation rel, int oidCacheId, int nameCacheId,
name = heap_getattr(tup, Anum_name, RelationGetDescr(rel), &isnull);
Assert(!isnull);
! namespace = heap_getattr(tup, Anum_namespace, RelationGetDescr(rel), &isnull);
Assert(!isnull);
oldNspOid = DatumGetObjectId(namespace);
--- 358,365 ----
name = heap_getattr(tup, Anum_name, RelationGetDescr(rel), &isnull);
Assert(!isnull);
! namespace = heap_getattr(tup, Anum_namespace, RelationGetDescr(rel),
! &isnull);
Assert(!isnull);
oldNspOid = DatumGetObjectId(namespace);
*** a/src/backend/commands/collationcmds.c
--- b/src/backend/commands/collationcmds.c
***************
*** 339,345 **** AlterCollationNamespace_oid(Oid collOid, Oid newNspOid)
/*
* We have to check for name collision ourselves, because
! * AlterObjectNamespace doesn't know how to deal with the encoding
* considerations.
*/
collation_name = get_collation_name(collOid);
--- 339,345 ----
/*
* We have to check for name collision ourselves, because
! * AlterObjectNamespace_internal doesn't know how to deal with the encoding
* considerations.
*/
collation_name = get_collation_name(collOid);
***************
*** 370,381 **** AlterCollationNamespace_oid(Oid collOid, Oid newNspOid)
get_namespace_name(newNspOid))));
/* OK, do the work */
! oldNspOid = AlterObjectNamespace(rel, COLLOID, -1,
! collOid, newNspOid,
! Anum_pg_collation_collname,
! Anum_pg_collation_collnamespace,
! Anum_pg_collation_collowner,
! ACL_KIND_COLLATION);
heap_close(rel, RowExclusiveLock);
--- 370,376 ----
get_namespace_name(newNspOid))));
/* OK, do the work */
! oldNspOid = AlterObjectNamespace_internal(rel, collOid, newNspOid);
heap_close(rel, RowExclusiveLock);
*** a/src/backend/commands/conversioncmds.c
--- b/src/backend/commands/conversioncmds.c
***************
*** 266,318 **** AlterConversionOwner_internal(Relation rel, Oid conversionOid, Oid 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;
- }
--- 266,268 ----
*** a/src/backend/commands/dropcmds.c
--- b/src/backend/commands/dropcmds.c
***************
*** 26,32 ****
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "parser/parse_type.h"
- #include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/syscache.h"
--- 26,31 ----
*** a/src/backend/commands/functioncmds.c
--- b/src/backend/commands/functioncmds.c
***************
*** 1851,1871 **** AlterFunctionNamespace_oid(Oid procOid, Oid nspOid)
procRel = heap_open(ProcedureRelationId, RowExclusiveLock);
tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(procOid));
if (!HeapTupleIsValid(tup))
elog(ERROR, "cache lookup failed for function %u", procOid);
proc = (Form_pg_proc) GETSTRUCT(tup);
- /* check permissions on function */
- if (!pg_proc_ownercheck(procOid, GetUserId()))
- aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
- NameStr(proc->proname));
-
- oldNspOid = proc->pronamespace;
-
- /* common checks on switching namespaces */
- CheckSetNamespace(oldNspOid, nspOid, ProcedureRelationId, procOid);
-
/* check for duplicate name (more friendly than unique-index failure) */
if (SearchSysCacheExists3(PROCNAMEARGSNSP,
CStringGetDatum(NameStr(proc->proname)),
--- 1851,1866 ----
procRel = heap_open(ProcedureRelationId, RowExclusiveLock);
+ /*
+ * We have to check for name collisions ourselves, because
+ * AlterObjectNamespace_internal doesn't know how to deal with the
+ * argument types.
+ */
tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(procOid));
if (!HeapTupleIsValid(tup))
elog(ERROR, "cache lookup failed for function %u", procOid);
proc = (Form_pg_proc) GETSTRUCT(tup);
/* check for duplicate name (more friendly than unique-index failure) */
if (SearchSysCacheExists3(PROCNAMEARGSNSP,
CStringGetDatum(NameStr(proc->proname)),
***************
*** 1877,1897 **** AlterFunctionNamespace_oid(Oid procOid, Oid nspOid)
NameStr(proc->proname),
get_namespace_name(nspOid))));
! /* OK, modify the pg_proc row */
!
! /* tup is a copy, so we can scribble directly on it */
! proc->pronamespace = nspOid;
!
! simple_heap_update(procRel, &tup->t_self, tup);
! CatalogUpdateIndexes(procRel, tup);
!
! /* Update dependency on schema */
! if (changeDependencyFor(ProcedureRelationId, procOid,
! NamespaceRelationId, oldNspOid, nspOid) != 1)
! elog(ERROR, "failed to change schema dependency for function \"%s\"",
! NameStr(proc->proname));
!
! heap_freetuple(tup);
heap_close(procRel, RowExclusiveLock);
--- 1872,1879 ----
NameStr(proc->proname),
get_namespace_name(nspOid))));
! /* OK, do the work */
! oldNspOid = AlterObjectNamespace_internal(procRel, procOid, nspOid);
heap_close(procRel, RowExclusiveLock);
*** a/src/backend/commands/opclasscmds.c
--- b/src/backend/commands/opclasscmds.c
***************
*** 1915,1972 **** AlterOpClassOwner_internal(Relation rel, HeapTuple tup, Oid 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
--- 1915,1920 ----
***************
*** 2122,2176 **** 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;
- }
--- 2070,2072 ----
*** a/src/backend/commands/operatorcmds.c
--- b/src/backend/commands/operatorcmds.c
***************
*** 423,478 **** AlterOperatorOwner_internal(Relation rel, Oid operOid, Oid 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;
- }
--- 423,425 ----
*** a/src/backend/commands/tsearchcmds.c
--- b/src/backend/commands/tsearchcmds.c
***************
*** 346,397 **** RenameTSParser(List *oldname, const char *newname)
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 -----------------------*/
/*
--- 346,351 ----
***************
*** 626,679 **** RenameTSDictionary(List *oldname, const char *newname)
}
/*
- * 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
--- 580,585 ----
***************
*** 1091,1142 **** RenameTSTemplate(List *oldname, const char *newname)
}
/*
- * 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
--- 997,1002 ----
***************
*** 1483,1536 **** RenameTSConfiguration(List *oldname, const char *newname)
}
/*
- * 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
--- 1343,1348 ----
*** a/src/backend/nodes/copyfuncs.c
--- b/src/backend/nodes/copyfuncs.c
***************
*** 2932,2938 **** _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);
--- 2932,2937 ----
*** a/src/backend/nodes/equalfuncs.c
--- b/src/backend/nodes/equalfuncs.c
***************
*** 1336,1342 **** _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);
--- 1336,1341 ----
*** a/src/backend/parser/gram.y
--- b/src/backend/parser/gram.y
***************
*** 7146,7152 **** AlterObjectSchemaStmt:
AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
n->objectType = OBJECT_OPCLASS;
n->object = $4;
! n->addname = $6;
n->newschema = $9;
n->missing_ok = false;
$$ = (Node *)n;
--- 7146,7152 ----
AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
n->objectType = OBJECT_OPCLASS;
n->object = $4;
! n->objarg = list_make1(makeString($6));
n->newschema = $9;
n->missing_ok = false;
$$ = (Node *)n;
***************
*** 7156,7162 **** AlterObjectSchemaStmt:
AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
n->objectType = OBJECT_OPFAMILY;
n->object = $4;
! n->addname = $6;
n->newschema = $9;
n->missing_ok = false;
$$ = (Node *)n;
--- 7156,7162 ----
AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
n->objectType = OBJECT_OPFAMILY;
n->object = $4;
! n->objarg = list_make1(makeString($6));
n->newschema = $9;
n->missing_ok = false;
$$ = (Node *)n;
*** a/src/include/catalog/objectaddress.h
--- b/src/include/catalog/objectaddress.h
***************
*** 15,20 ****
--- 15,21 ----
#include "nodes/parsenodes.h"
#include "storage/lock.h"
+ #include "utils/acl.h"
#include "utils/relcache.h"
/*
***************
*** 37,40 **** extern void check_object_ownership(Oid roleid,
--- 38,50 ----
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 */
*** a/src/include/commands/alter.h
--- b/src/include/commands/alter.h
***************
*** 14,29 ****
#ifndef ALTER_H
#define ALTER_H
! #include "utils/acl.h"
#include "utils/relcache.h"
extern void ExecRenameStmt(RenameStmt *stmt);
extern void ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt);
extern Oid AlterObjectNamespace_oid(Oid classId, Oid objid, Oid nspOid);
! extern Oid AlterObjectNamespace(Relation rel, int oidCacheId, int nameCacheId,
! Oid objid, Oid nspOid,
! int Anum_name, int Anum_namespace, int Anum_owner,
! AclObjectKind acl_kind);
extern void ExecAlterOwnerStmt(AlterOwnerStmt *stmt);
#endif /* ALTER_H */
--- 14,26 ----
#ifndef ALTER_H
#define ALTER_H
! #include "nodes/parsenodes.h"
#include "utils/relcache.h"
extern void ExecRenameStmt(RenameStmt *stmt);
extern void ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt);
extern Oid AlterObjectNamespace_oid(Oid classId, Oid objid, Oid nspOid);
! extern Oid AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid);
extern void ExecAlterOwnerStmt(AlterOwnerStmt *stmt);
#endif /* ALTER_H */
*** a/src/include/commands/conversioncmds.h
--- b/src/include/commands/conversioncmds.h
***************
*** 21,27 **** 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 */
--- 21,25 ----
*** a/src/include/commands/defrem.h
--- b/src/include/commands/defrem.h
***************
*** 64,71 **** 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,
--- 64,69 ----
***************
*** 85,96 **** extern void RenameOpClass(List *name, const char *access_method, const char *new
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);
--- 83,90 ----
***************
*** 98,105 **** 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);
--- 92,97 ----
***************
*** 107,119 **** 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);
--- 99,107 ----
***************
*** 121,128 **** 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);
--- 109,114 ----
*** a/src/include/nodes/parsenodes.h
--- b/src/include/nodes/parsenodes.h
***************
*** 2168,2174 **** 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;
--- 2168,2173 ----
Excerpts from Kohei KaiGai's message of lun sep 10 08:08:32 -0300 2012:
As attached, I split off the original one into three portions; for set-schema,
set-owner and rename-to. Please apply them in order of patch filename.
Regarding to the error message, RenameErrorMsgAlreadyExists() was added
to handle per object type messages in case when aclcheck_error() is not
available to utilize.
I have pushed the regression tests and parts 1 and 2. Only part 3 is
missing from this series, but I'm not as sure about that one as the
other two. Not really a fan of RenameErrorMsgAlreadyExists() as coded,
but I'll think more about it.
--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
Excerpts from Alvaro Herrera's message of mié oct 03 18:25:54 -0300 2012:
Excerpts from Kohei KaiGai's message of lun sep 10 08:08:32 -0300 2012:
As attached, I split off the original one into three portions; for set-schema,
set-owner and rename-to. Please apply them in order of patch filename.
Regarding to the error message, RenameErrorMsgAlreadyExists() was added
to handle per object type messages in case when aclcheck_error() is not
available to utilize.I have pushed the regression tests and parts 1 and 2. Only part 3 is
missing from this series, but I'm not as sure about that one as the
other two. Not really a fan of RenameErrorMsgAlreadyExists() as coded,
but I'll think more about it.
I forgot to mention: I think with a little more effort (a callback to be
registered as the permission check to run during SET OWNER, maybe?) we
could move the foreign stuff and event triggers into the generic SET
OWNER implementation.
--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
Kohei KaiGai escribió:
2012/8/31 Kohei KaiGai <kaigai@kaigai.gr.jp>:
2012/8/30 Robert Haas <robertmhaas@gmail.com>:
On Mon, Aug 13, 2012 at 3:35 PM, Kohei KaiGai <kaigai@kaigai.gr.jp> wrote:
Was it a right decision to track dependency of large object using
oid of pg_largeobject, instead of pg_largeobject_metadata?
IIRC, the reason why we used oid of pg_largeobject is backward
compatibility for applications that tries to reference pg_depend
with built-in oids.I think it was a terrible decision and I'm pretty sure I said as much
at the time, but I lost the argument, so I'm inclined to think we're
stuck with continuing to support that kludge.OK, we will keep to implement carefully...
After reviewing this patch, I think we need to revisit this decision.
OK, I'll split the patch into three (isn't it?) portions; RENAME, SET OWNER
and SET SCHEMA, with all above your suggestions.As attached, I split off the original one into three portions; for set-schema,
set-owner and rename-to. Please apply them in order of patch filename.
Regarding to the error message, RenameErrorMsgAlreadyExists() was added
to handle per object type messages in case when aclcheck_error() is not
available to utilize.
Here's the remaining piece; the RENAME part. I have reworked it a bit,
but it needs a bit more work yet. Note this:
alvherre=# alter function foo.g(int, int) rename to g;
ERROR: function foo.g(integer,integer) already exists in schema "foo"
The previous code would have said
alvherre=# alter function foo.g(int, int) rename to g;
ERROR: function g(integer, integer) already exists in schema "foo"
Note that the function name is not qualified here. The difference is
that the original code was calling funcname_signature_string() to format
the function name, and the new code is calling format_procedure(). This
seems wrong to me; please rework.
I haven't checked other object renames, but I think they should be okay
because functions are the only objects for which we pass the OID instead
of the name to the error message function.
--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
Attachments:
pgsql-v9.3-alter-reworks.3-rename.v4.patchtext/x-diff; charset=us-asciiDownload
*** a/src/backend/commands/aggregatecmds.c
--- b/src/backend/commands/aggregatecmds.c
***************
*** 206,269 **** 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);
- }
--- 206,208 ----
*** a/src/backend/commands/alter.c
--- b/src/backend/commands/alter.c
***************
*** 45,50 ****
--- 45,261 ----
#include "utils/syscache.h"
#include "utils/tqual.h"
+ static HeapTuple get_catalog_object_by_oid(Relation catalog, Oid objectId);
+
+ /*
+ * 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.
+ */
+ static char *
+ errmsg_obj_already_exists(ObjectType objtype, const char *objname,
+ Oid namespaceId, Oid objectId, List *objargs)
+ {
+ char *errorm;
+
+ switch (objtype)
+ {
+ case OBJECT_AGGREGATE:
+ case OBJECT_FUNCTION:
+ errorm = format_elog_string("function %s already exists in schema \"%s\"",
+ format_procedure(objectId),
+ get_namespace_name(namespaceId));
+ break;
+ case OBJECT_CONVERSION:
+ errorm = format_elog_string("conversion \"%s\" already exists in schema \"%s\"",
+ objname, get_namespace_name(namespaceId));
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ errorm = format_elog_string("event trigger \"%s\" already exists",
+ objname);
+ break;
+ case OBJECT_FDW:
+ errorm = format_elog_string("foreign-data wrapper \"%s\" already exists",
+ objname);
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ errorm = format_elog_string("server \"%s\" already exists",
+ objname);
+ break;
+ case OBJECT_LANGUAGE:
+ errorm = format_elog_string("language \"%s\" already exists",
+ objname);
+ break;
+ 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);
+ break;
+ }
+
+ 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;
+
+ 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
***************
*** 55,64 **** 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;
--- 266,271 ----
***************
*** 67,108 **** ExecRenameStmt(RenameStmt *stmt)
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_EVENT_TRIGGER:
- RenameEventTrigger(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;
--- 274,283 ----
***************
*** 132,158 **** ExecRenameStmt(RenameStmt *stmt)
renametrig(stmt);
break;
- case OBJECT_TSPARSER:
- RenameTSParser(stmt->object, stmt->newname);
- break;
-
- case OBJECT_TSDICTIONARY:
- RenameTSDictionary(stmt->object, stmt->newname);
- break;
-
- 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);
break;
default:
elog(ERROR, "unrecognized rename stmt type: %d",
(int) stmt->renameType);
--- 307,336 ----
renametrig(stmt);
break;
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:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSTEMPLATE:
+ AlterObjectRename_internal(stmt->renameType,
+ stmt->object,
+ stmt->objarg,
+ stmt->newname);
+ break;
+
default:
elog(ERROR, "unrecognized rename stmt type: %d",
(int) stmt->renameType);
***************
*** 530,536 **** 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.
*
* XXX this function seems general in possible usage. Given sufficient callers
* elsewhere, we should consider moving it to a more appropriate place.
--- 708,714 ----
* 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; 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,553 **** 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);
--- 721,727 ----
***************
*** 564,575 **** 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);
systable_endscan(scan);
}
--- 738,746 ----
scan = systable_beginscan(catalog, oidIndexId, true,
SnapshotNow, 1, &skey);
tuple = systable_getnext(scan);
!
! if (HeapTupleIsValid(tuple))
! tuple = heap_copytuple(tuple);
systable_endscan(scan);
}
***************
*** 598,604 **** AlterObjectOwner_internal(Relation rel, Oid objectId, Oid new_ownerId)
Datum datum;
bool isnull;
Oid old_ownerId;
! Oid namespaceId = InvalidOid;
oldtup = get_catalog_object_by_oid(rel, objectId);
if (oldtup == NULL)
--- 769,775 ----
Datum datum;
bool isnull;
Oid old_ownerId;
! Oid namespaceId;
oldtup = get_catalog_object_by_oid(rel, objectId);
if (oldtup == NULL)
***************
*** 610,615 **** AlterObjectOwner_internal(Relation rel, Oid objectId, Oid new_ownerId)
--- 781,787 ----
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,622 **** AlterObjectOwner_internal(Relation rel, Oid objectId, Oid new_ownerId)
--- 789,796 ----
Assert(!isnull);
namespaceId = DatumGetObjectId(datum);
}
+ else
+ namespaceId = InvalidOid;
if (old_ownerId != new_ownerId)
{
*** a/src/backend/commands/conversioncmds.c
--- b/src/backend/commands/conversioncmds.c
***************
*** 114,167 **** 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);
- }
--- 114,116 ----
*** a/src/backend/commands/event_trigger.c
--- b/src/backend/commands/event_trigger.c
***************
*** 409,455 **** 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
*/
--- 409,414 ----
*** a/src/backend/commands/foreigncmds.c
--- b/src/backend/commands/foreigncmds.c
***************
*** 200,282 **** 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.
*
--- 200,205 ----
*** a/src/backend/commands/functioncmds.c
--- b/src/backend/commands/functioncmds.c
***************
*** 1036,1109 **** 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
--- 1036,1041 ----
*** a/src/backend/commands/opclasscmds.c
--- b/src/backend/commands/opclasscmds.c
***************
*** 1656,1809 **** 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
*
--- 1656,1661 ----
*** a/src/backend/commands/proclang.c
--- b/src/backend/commands/proclang.c
***************
*** 535,577 **** 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
--- 535,540 ----
*** a/src/backend/commands/tsearchcmds.c
--- b/src/backend/commands/tsearchcmds.c
***************
*** 303,351 **** 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 -----------------------*/
/*
--- 303,308 ----
***************
*** 529,585 **** 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
--- 486,491 ----
***************
*** 893,942 **** 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
--- 799,804 ----
***************
*** 1233,1288 **** 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
--- 1095,1100 ----
*** a/src/backend/parser/gram.y
--- b/src/backend/parser/gram.y
***************
*** 6748,6754 **** RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_FDW;
! n->subname = $5;
n->newname = $8;
n->missing_ok = false;
$$ = (Node *)n;
--- 6748,6754 ----
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_FDW;
! n->object = list_make1(makeString($5));
n->newname = $8;
n->missing_ok = false;
$$ = (Node *)n;
***************
*** 6776,6782 **** RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_LANGUAGE;
! n->subname = $4;
n->newname = $7;
n->missing_ok = false;
$$ = (Node *)n;
--- 6776,6782 ----
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_LANGUAGE;
! n->object = list_make1(makeString($4));
n->newname = $7;
n->missing_ok = false;
$$ = (Node *)n;
***************
*** 6786,6792 **** 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->newname = $9;
n->missing_ok = false;
$$ = (Node *)n;
--- 6786,6792 ----
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_OPCLASS;
n->object = $4;
! n->objarg = list_make1(makeString($6));
n->newname = $9;
n->missing_ok = false;
$$ = (Node *)n;
***************
*** 6796,6802 **** 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->newname = $9;
n->missing_ok = false;
$$ = (Node *)n;
--- 6796,6802 ----
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_OPFAMILY;
n->object = $4;
! n->objarg = list_make1(makeString($6));
n->newname = $9;
n->missing_ok = false;
$$ = (Node *)n;
***************
*** 6814,6820 **** RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_FOREIGN_SERVER;
! n->subname = $3;
n->newname = $6;
n->missing_ok = false;
$$ = (Node *)n;
--- 6814,6820 ----
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_FOREIGN_SERVER;
! n->object = list_make1(makeString($3));
n->newname = $6;
n->missing_ok = false;
$$ = (Node *)n;
***************
*** 6987,6993 **** RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_EVENT_TRIGGER;
! n->subname = $4;
n->newname = $7;
$$ = (Node *)n;
}
--- 6987,6993 ----
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_EVENT_TRIGGER;
! n->object = list_make1(makeString($4));
n->newname = $7;
$$ = (Node *)n;
}
*** a/src/include/commands/conversioncmds.h
--- b/src/include/commands/conversioncmds.h
***************
*** 18,23 ****
#include "nodes/parsenodes.h"
extern void CreateConversionCommand(CreateConversionStmt *parsetree);
- extern void RenameConversion(List *name, const char *newname);
#endif /* CONVERSIONCMDS_H */
--- 18,22 ----
*** a/src/include/commands/defrem.h
--- b/src/include/commands/defrem.h
***************
*** 46,52 **** 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);
--- 46,51 ----
***************
*** 63,69 **** 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);
--- 62,67 ----
***************
*** 73,100 **** 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);
--- 71,92 ----
***************
*** 102,109 **** 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);
--- 94,99 ----
*** a/src/include/commands/event_trigger.h
--- b/src/include/commands/event_trigger.h
***************
*** 36,42 **** 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);
--- 36,41 ----
*** a/src/include/commands/proclang.h
--- b/src/include/commands/proclang.h
***************
*** 16,22 ****
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);
--- 16,21 ----
2012/10/2 Alvaro Herrera <alvherre@2ndquadrant.com>:
Excerpts from Alvaro Herrera's message of vie sep 28 18:17:32 -0300 2012:
Excerpts from Kohei KaiGai's message of lun sep 10 08:08:32 -0300 2012:
As attached, I split off the original one into three portions; for set-schema,
set-owner and rename-to. Please apply them in order of patch filename.Hmm, in the first patch, it seems to me we can simplify
AlterObjectNamespace's signature: instead of passing all the details of
the object class (cache Ids and attribute numbers and so on), just doAlterObjectNamespace(catalog-containing-object, objectId, newNamespaceOid)
Like in the attached reworked version, in which I renamed the function
to AlterObjectNamespace_internal because the other name seemed a bit
wrong in the fact of the existing AlterObjectNamespace_oid.I also made the ALTER FUNCTION case go through
AlterObjectNamespace_internal; it seems pointless to have a separate
code path to go through when the generic one does just fine (also, this
makes functions identical to collations in implementation). That's one
less hook point for sepgsql, I guess.
Thanks for your reviewing, and sorry for my late response.
I definitely agree with your solution. The reason why my original patch
had separate code path for function and collation was they took
additional elements (such as argument-list of function) to check
duplicate names. So, I think it is a wise idea to invoke the common
code after name duplication checks.
Best regards,
--
KaiGai Kohei <kaigai@kaigai.gr.jp>
2012/10/5 Alvaro Herrera <alvherre@2ndquadrant.com>:
Kohei KaiGai escribió:
2012/8/31 Kohei KaiGai <kaigai@kaigai.gr.jp>:
2012/8/30 Robert Haas <robertmhaas@gmail.com>:
On Mon, Aug 13, 2012 at 3:35 PM, Kohei KaiGai <kaigai@kaigai.gr.jp> wrote:
Was it a right decision to track dependency of large object using
oid of pg_largeobject, instead of pg_largeobject_metadata?
IIRC, the reason why we used oid of pg_largeobject is backward
compatibility for applications that tries to reference pg_depend
with built-in oids.I think it was a terrible decision and I'm pretty sure I said as much
at the time, but I lost the argument, so I'm inclined to think we're
stuck with continuing to support that kludge.OK, we will keep to implement carefully...
After reviewing this patch, I think we need to revisit this decision.
OK, I'll split the patch into three (isn't it?) portions; RENAME, SET OWNER
and SET SCHEMA, with all above your suggestions.As attached, I split off the original one into three portions; for set-schema,
set-owner and rename-to. Please apply them in order of patch filename.
Regarding to the error message, RenameErrorMsgAlreadyExists() was added
to handle per object type messages in case when aclcheck_error() is not
available to utilize.Here's the remaining piece; the RENAME part. I have reworked it a bit,
but it needs a bit more work yet. Note this:alvherre=# alter function foo.g(int, int) rename to g;
ERROR: function foo.g(integer,integer) already exists in schema "foo"The previous code would have said
alvherre=# alter function foo.g(int, int) rename to g;
ERROR: function g(integer, integer) already exists in schema "foo"Note that the function name is not qualified here. The difference is
that the original code was calling funcname_signature_string() to format
the function name, and the new code is calling format_procedure(). This
seems wrong to me; please rework.I haven't checked other object renames, but I think they should be okay
because functions are the only objects for which we pass the OID instead
of the name to the error message function.
The attached patch fixes the messaging issue.
I newly add func_signature_string_oid() that returns compatible function's
signature, but takes its object-id.
So, the error message is now constructed as:
+ case OBJECT_AGGREGATE:
+ case OBJECT_FUNCTION:
+ errorm = format_elog_string("function %s already exists in
schema \"%s\"",
+ func_signature_string_oid(objectId),
+ get_namespace_name(namespaceId));
+ break;
Thanks,
--
KaiGai Kohei <kaigai@kaigai.gr.jp>
Attachments:
pgsql-v9.3-alter-reworks.3-rename.v5.patchapplication/octet-stream; name=pgsql-v9.3-alter-reworks.3-rename.v5.patchDownload
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);
Kohei KaiGai escribió:
2012/10/5 Alvaro Herrera <alvherre@2ndquadrant.com>:
The attached patch fixes the messaging issue.
I newly add func_signature_string_oid() that returns compatible function's
signature, but takes its object-id.So, the error message is now constructed as: + case OBJECT_AGGREGATE: + case OBJECT_FUNCTION: + errorm = format_elog_string("function %s already exists in schema \"%s\"", + func_signature_string_oid(objectId), + get_namespace_name(namespaceId)); + break;
Thanks, yeah, this works for me.
I am now wondering if it would make sense to merge the duplicate-name
error cases in AlterObjectNamespace_internal and
AlterObjectRename_internal. The former only works when there is a name
catcache for the object type. Maybe we can create a single function to
which we give the object type, name/args, oid, etc, and it uses a
catcache if available and falls back to get_object_address (with the
IMO ugly name list manipulations) if not.
--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
The attached patch is the revised version of ALTER RENAME TO
consolidation. According to the previous suggestion, it uses
a common logic to check object-naming duplication at
check_duplicate_objectname().
At the code path on AlterObjectNamespace_internal, it lost
ObjectType information to the supplied object, so I also added
get_object_type() function at objectaddress.c for inverse
translation from a couple of classId/objectId to OBJECT_* label.
Rest of parts are unchanged since the previous versions.
Thanks,
2012/10/17 Alvaro Herrera <alvherre@2ndquadrant.com>:
Kohei KaiGai escribió:
2012/10/5 Alvaro Herrera <alvherre@2ndquadrant.com>:
The attached patch fixes the messaging issue.
I newly add func_signature_string_oid() that returns compatible function's
signature, but takes its object-id.So, the error message is now constructed as: + case OBJECT_AGGREGATE: + case OBJECT_FUNCTION: + errorm = format_elog_string("function %s already exists in schema \"%s\"", + func_signature_string_oid(objectId), + get_namespace_name(namespaceId)); + break;Thanks, yeah, this works for me.
I am now wondering if it would make sense to merge the duplicate-name
error cases in AlterObjectNamespace_internal and
AlterObjectRename_internal. The former only works when there is a name
catcache for the object type. Maybe we can create a single function to
which we give the object type, name/args, oid, etc, and it uses a
catcache if available and falls back to get_object_address (with the
IMO ugly name list manipulations) if not.--
Įlvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
--
KaiGai Kohei <kaigai@kaigai.gr.jp>
Attachments:
pgsql-v9.3-alter-reworks.3-rename.v6.patchapplication/octet-stream; name=pgsql-v9.3-alter-reworks.3-rename.v6.patchDownload
src/backend/catalog/objectaddress.c | 141 ++++++++++++
src/backend/commands/aggregatecmds.c | 61 -----
src/backend/commands/alter.c | 345 +++++++++++++++++++++++-----
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/catalog/objectaddress.h | 1 +
src/include/commands/conversioncmds.h | 1 -
src/include/commands/defrem.h | 6 -
src/include/commands/event_trigger.h | 1 -
src/include/commands/proclang.h | 1 -
src/include/parser/parse_func.h | 1 +
src/test/regress/expected/alter_generic.out | 18 +-
19 files changed, 469 insertions(+), 754 deletions(-)
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index d7a726c..df9246d 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -1363,3 +1363,144 @@ get_object_property_data(Oid class_id)
return NULL; /* keep MSC compiler happy */
}
+
+/*
+ * get_object_type
+ *
+ * It returns OBJECT_* label according to the given ObjectAddress object.
+ * Some object type don't have one-to-one relationship between classId
+ * and object type, so it may take syscache lookup on demand.
+ */
+ObjectType
+get_object_type(const ObjectAddress *address)
+{
+ ObjectType result = -1;
+
+ switch (address->classId)
+ {
+ case RelationRelationId:
+ if (address->objectSubId != 0)
+ result = OBJECT_COLUMN;
+ else
+ {
+ char relkind = get_rel_relkind(address->objectId);
+
+ switch (relkind)
+ {
+ case RELKIND_RELATION:
+ result = OBJECT_TABLE;
+ break;
+ case RELKIND_SEQUENCE:
+ result = OBJECT_SEQUENCE;
+ break;
+ case RELKIND_VIEW:
+ result = OBJECT_VIEW;
+ break;
+ case RELKIND_INDEX:
+ result = OBJECT_INDEX;
+ break;
+ case RELKIND_FOREIGN_TABLE:
+ result = OBJECT_FOREIGN_TABLE;
+ break;
+ default:
+ elog(ERROR, "unrecognized relkind '%c' of relation %u",
+ relkind, address->objectId);
+ }
+ }
+ break;
+ case RewriteRelationId:
+ result = OBJECT_RULE;
+ break;
+ case TriggerRelationId:
+ result = OBJECT_TRIGGER;
+ break;
+ case ConstraintRelationId:
+ result = OBJECT_CONSTRAINT;
+ break;
+ case DatabaseRelationId:
+ result = OBJECT_DATABASE;
+ break;
+ case ExtensionRelationId:
+ result = OBJECT_EXTENSION;
+ break;
+ case TableSpaceRelationId:
+ result = OBJECT_TABLESPACE;
+ break;
+ case AuthIdRelationId:
+ result = OBJECT_ROLE;
+ break;
+ case NamespaceRelationId:
+ result = OBJECT_SCHEMA;
+ break;
+ case LanguageRelationId:
+ result = OBJECT_LANGUAGE;
+ break;
+ case ForeignDataWrapperRelationId:
+ result = OBJECT_FDW;
+ break;
+ case ForeignServerRelationId:
+ result = OBJECT_FOREIGN_SERVER;
+ break;
+ case EventTriggerRelationId:
+ result = OBJECT_EVENT_TRIGGER;
+ break;
+ case TypeRelationId:
+ if (get_typtype(address->objectId) == TYPTYPE_DOMAIN)
+ result = OBJECT_DOMAIN;
+ else
+ result = OBJECT_TYPE;
+ break;
+ case ProcedureRelationId:
+ {
+ HeapTuple tup;
+
+ tup = SearchSysCache1(PROCOID,
+ ObjectIdGetDatum(address->objectId));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for function %u",
+ address->objectId);
+ if (((Form_pg_proc) GETSTRUCT(tup))->proisagg)
+ result = OBJECT_AGGREGATE;
+ else
+ result = OBJECT_FUNCTION;
+ ReleaseSysCache(tup);
+ }
+ break;
+ case OperatorRelationId:
+ result = OBJECT_OPERATOR;
+ break;
+ case OperatorClassRelationId:
+ result = OBJECT_OPCLASS;
+ break;
+ case OperatorFamilyRelationId:
+ result = OBJECT_OPFAMILY;
+ break;
+ case CollationRelationId:
+ result = OBJECT_COLLATION;
+ break;
+ case ConversionRelationId:
+ result = OBJECT_CONVERSION;
+ break;
+ case LargeObjectRelationId:
+ result = OBJECT_LARGEOBJECT;
+ break;
+ case CastRelationId:
+ result = OBJECT_CAST;
+ break;
+ case TSParserRelationId:
+ result = OBJECT_TSPARSER;
+ break;
+ case TSDictionaryRelationId:
+ result = OBJECT_TSDICTIONARY;
+ break;
+ case TSTemplateRelationId:
+ result = OBJECT_TSTEMPLATE;
+ break;
+ case TSConfigRelationId:
+ result = OBJECT_TSCONFIGURATION;
+ break;
+ default:
+ elog(ERROR, "unsupported system catalog: %u", address->classId);
+ }
+ return result;
+}
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 9e271c3..39fa510 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,276 @@
#include "utils/syscache.h"
#include "utils/tqual.h"
-
/*
- * Executes an ALTER OBJECT / RENAME TO statement. Based on the object
- * type, the function appropriate to that type is executed.
+ * check_duplicate_objectname
+ *
+ * It checks whether here is another object with same name, or not.
+ * If exists, it raise an error message.
*/
-void
-ExecRenameStmt(RenameStmt *stmt)
+static void
+check_duplicate_objectname(ObjectType objtype,
+ Oid new_namespace, const char *new_name,
+ List *objargs)
{
- switch (stmt->renameType)
+ List *objname;
+ Relation relation;
+ ObjectAddress new_address;
+
+ if (OidIsValid(new_namespace))
{
- case OBJECT_AGGREGATE:
- RenameAggregate(stmt->object, stmt->objarg, stmt->newname);
- break;
+ objname = list_make2(makeString(get_namespace_name(new_namespace)),
+ makeString(pstrdup(new_name)));
+ }
+ else
+ {
+ objname = list_make1(makeString(pstrdup(new_name)));
+ }
+ new_address = get_object_address(objtype, objname, objargs,
+ &relation,
+ AccessShareLock, true);
+ if (!OidIsValid(new_address.objectId))
+ return;
- case OBJECT_COLLATION:
- RenameCollation(stmt->object, stmt->newname);
- break;
+ if (relation)
+ heap_close(relation, AccessShareLock);
- case OBJECT_CONSTRAINT:
- RenameConstraint(stmt);
+ switch (objtype)
+ {
+ case OBJECT_AGGREGATE:
+ case OBJECT_FUNCTION:
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("function %s already exists in schema \"%s\"",
+ func_signature_string_oid(new_address.objectId),
+ get_namespace_name(new_namespace))));
break;
-
case OBJECT_CONVERSION:
- RenameConversion(stmt->object, stmt->newname);
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("conversion \"%s\" already exists in schema \"%s\"",
+ new_name, get_namespace_name(new_namespace))));
break;
-
- case OBJECT_DATABASE:
- RenameDatabase(stmt->subname, stmt->newname);
+ case OBJECT_EVENT_TRIGGER:
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("event trigger \"%s\" already exists",
+ new_name)));
break;
-
case OBJECT_FDW:
- RenameForeignDataWrapper(stmt->subname, stmt->newname);
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("foreign-data wrapper \"%s\" already exists",
+ new_name)));
break;
-
- case OBJECT_FOREIGN_SERVER:
- RenameForeignServer(stmt->subname, stmt->newname);
+ case OBJECT_FOREIGN_SERVER:
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("server \"%s\" already exists", new_name)));
break;
-
- case OBJECT_EVENT_TRIGGER:
- RenameEventTrigger(stmt->subname, stmt->newname);
+ case OBJECT_LANGUAGE:
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("language \"%s\" already exists", new_name)));
break;
-
- case OBJECT_FUNCTION:
- RenameFunction(stmt->object, stmt->objarg, stmt->newname);
+ case OBJECT_OPCLASS:
+ Assert(list_length(objargs) == 1);
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("operator class \"%s\" for access method \"%s\" already exists in schema \"%s\"",
+ new_name, strVal(linitial(objargs)),
+ get_namespace_name(new_namespace))));
+ break;
+ case OBJECT_OPFAMILY:
+ Assert(list_length(objargs) == 1);
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("operator family \"%s\" for access method \"%s\" already exists in schema \"%s\"",
+ new_name, strVal(linitial(objargs)),
+ get_namespace_name(new_namespace))));
+ break;
+ case OBJECT_TSCONFIGURATION:
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("text search configuration \"%s\" already exists in scheme \"%s\"",
+ new_name, get_namespace_name(new_namespace))));
+ break;
+ case OBJECT_TSDICTIONARY:
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("text search dictionary \"%s\" already exists in scheme \"%s\"",
+ new_name, get_namespace_name(new_namespace))));
+ break;
+ case OBJECT_TSPARSER:
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("text search parser \"%s\" already exists in scheme \"%s\"",
+ new_name, get_namespace_name(new_namespace))));
+ break;
+ case OBJECT_TSTEMPLATE:
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("text search template \"%s\" already exists in scheme \"%s\"",
+ new_name, get_namespace_name(new_namespace))));
+ break;
+ default:
+ elog(ERROR, "unexpected object type: %u", (int) objtype);
break;
+ }
+}
- case OBJECT_LANGUAGE:
- RenameLanguage(stmt->subname, stmt->newname);
+/*
+ * 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;
+ 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,
+ AccessExclusiveLock, 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 does not exist
+ */
+ check_duplicate_objectname(objtype, namespaceId, new_name, objargs);
+
+ /*
+ * 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, &newtup->t_self, newtup);
+ CatalogUpdateIndexes(catalog, newtup);
+
+ heap_close(catalog, NoLock);
+
+ if (relation)
+ heap_close(relation, NoLock);
+
+ /* Release memory */
+ pfree(values);
+ pfree(nulls);
+ pfree(replaces);
+}
+
+/*
+ * 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 +347,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(stmt->renameType,
+ stmt->object,
+ stmt->objarg,
+ stmt->newname);
break;
default:
@@ -332,11 +550,11 @@ AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid)
{
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);
+ ObjectType objtype;
Oid oldNspOid;
Datum name,
namespace;
@@ -396,14 +614,23 @@ 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.
+ *
+ * XXX - the caller should check object-name duplication, if the supplied
+ * object type need to take object arguments for identification, such as
+ * functions.
*/
- if (nameCacheId >= 0 &&
- SearchSysCacheExists2(nameCacheId, name, ObjectIdGetDatum(nspOid)))
- ereport(ERROR,
- (errcode(ERRCODE_DUPLICATE_OBJECT),
- errmsg("%s already exists in schema \"%s\"",
- getObjectDescriptionOids(classId, objid),
- get_namespace_name(nspOid))));
+ if (get_object_catcache_name(classId) >= 0)
+ {
+ ObjectAddress address;
+
+ address.classId = classId;
+ address.objectId = objid;
+ address.objectSubId = 0;
+
+ objtype = get_object_type(&address);
+ check_duplicate_objectname(objtype, nspOid,
+ NameStr(*DatumGetName(name)), NIL);
+ }
/* Build modified tuple */
values = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(Datum));
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..6c1d008 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/catalog/objectaddress.h b/src/include/catalog/objectaddress.h
index 1268c5e..2bc233a 100644
--- a/src/include/catalog/objectaddress.h
+++ b/src/include/catalog/objectaddress.h
@@ -46,5 +46,6 @@ 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);
+extern ObjectType get_object_type(const ObjectAddress *address);
#endif /* PARSE_OBJECT_H */
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..12aba5d 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,8 +71,6 @@ 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);
@@ -102,8 +98,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);
diff --git a/src/test/regress/expected/alter_generic.out b/src/test/regress/expected/alter_generic.out
index 3beddd7..7af05db 100644
--- a/src/test/regress/expected/alter_generic.out
+++ b/src/test/regress/expected/alter_generic.out
@@ -129,7 +129,7 @@ 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"
+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
@@ -327,7 +327,7 @@ 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
+ERROR: text search dictionary "alt_ts_dict2" already exists in scheme "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"
@@ -346,7 +346,7 @@ 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"
+ERROR: text search dictionary "alt_ts_dict2" already exists in scheme "alt_nsp2"
RESET SESSION AUTHORIZATION;
SELECT nspname, dictname, rolname
FROM pg_ts_dict t, pg_namespace n, pg_authid a
@@ -368,7 +368,7 @@ 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
+ERROR: text search configuration "alt_ts_conf2" already exists in scheme "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"
@@ -387,7 +387,7 @@ 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"
+ERROR: text search configuration "alt_ts_conf2" already exists in scheme "alt_nsp2"
RESET SESSION AUTHORIZATION;
SELECT nspname, cfgname, rolname
FROM pg_ts_config t, pg_namespace n, pg_authid a
@@ -408,12 +408,12 @@ SELECT nspname, cfgname, rolname
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
+ERROR: text search template "alt_ts_temp2" already exists in scheme "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"
+ERROR: text search template "alt_ts_temp2" already exists in scheme "alt_nsp2"
SELECT nspname, tmplname
FROM pg_ts_template t, pg_namespace n
WHERE t.tmplnamespace = n.oid AND nspname like 'alt_nsp%'
@@ -433,13 +433,13 @@ CREATE TEXT SEARCH PARSER alt_ts_prs1
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
+ERROR: text search parser "alt_ts_prs2" already exists in scheme "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"
+ERROR: text search parser "alt_ts_prs2" already exists in scheme "alt_nsp2"
SELECT nspname, prsname
FROM pg_ts_parser t, pg_namespace n
WHERE t.prsnamespace = n.oid AND nspname like 'alt_nsp%'
Hi,
Thanks for working on that cleanup job!
Kohei KaiGai <kaigai@kaigai.gr.jp> writes:
The attached patch is the revised version of ALTER RENAME TO
consolidation. According to the previous suggestion, it uses
a common logic to check object-naming duplication at
check_duplicate_objectname().
I think you need to better comment which object types are supported by
the new generic function and which are not in AlterObjectRename().
At the code path on AlterObjectNamespace_internal, it lost
ObjectType information to the supplied object, so I also added
get_object_type() function at objectaddress.c for inverse
translation from a couple of classId/objectId to OBJECT_* label.
I don't understand that part, and it looks like it would be way better
to find a way to pass down the information you already have earlier in
the code than to compute it again doing syscache lookups…
Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support
Hi Dimitri,
Thanks for your checks.
2012/11/19 Dimitri Fontaine <dimitri@2ndquadrant.fr>:
Kohei KaiGai <kaigai@kaigai.gr.jp> writes:
The attached patch is the revised version of ALTER RENAME TO
consolidation. According to the previous suggestion, it uses
a common logic to check object-naming duplication at
check_duplicate_objectname().I think you need to better comment which object types are supported by
the new generic function and which are not in AlterObjectRename().
OK, Are you suggesting to add a "generic" comments such as "Generic
function to change the name of a given object, for simple cases ...",
not a list of OBJECT_* at the head of this function, aren't you?
At the code path on AlterObjectNamespace_internal, it lost
ObjectType information to the supplied object, so I also added
get_object_type() function at objectaddress.c for inverse
translation from a couple of classId/objectId to OBJECT_* label.I don't understand that part, and it looks like it would be way better
to find a way to pass down the information you already have earlier in
the code than to compute it again doing syscache lookups…
The pain point is AlterObjectNamespace_internal is not invoked by
only ExecAlterObjectSchemaStmt(), but AlterObjectNamespace_oid()
also.
It is the reason why I had to put get_object_type() to find out OBJECT_*
from the supplied ObjectAddress, because this code path does not
available to pass down its ObjectType from the caller.
Thanks,
--
KaiGai Kohei <kaigai@kaigai.gr.jp>
Kohei KaiGai <kaigai@kaigai.gr.jp> writes:
OK, Are you suggesting to add a "generic" comments such as "Generic
function to change the name of a given object, for simple cases ...",
not a list of OBJECT_* at the head of this function, aren't you?
Just something like
* Most simple objects are covered by a generic function, the other
* still need special processing.
Mainly I was surprised to see collation not supported here, but I didn't
take enough time to understand why that is the case. I will do that
later in the review process.
The pain point is AlterObjectNamespace_internal is not invoked by
only ExecAlterObjectSchemaStmt(), but AlterObjectNamespace_oid()
also.
I should remember better about that as the use case is extensions…
It is the reason why I had to put get_object_type() to find out OBJECT_*
from the supplied ObjectAddress, because this code path does not
available to pass down its ObjectType from the caller.
If we really want to do that, I think I would only do that in
AlterObjectNamespace_oid and add an argument to
AlterObjectNamespace_internal, that you already have in
ExecAlterObjectSchemaStmt().
But really, what about just removing that part of your patch instead:
@@ -396,14 +614,23 @@ 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.
+ *
+ * XXX - the caller should check object-name duplication, if the supplied
+ * object type need to take object arguments for identification, such as
+ * functions.
*/
- if (nameCacheId >= 0 &&
- SearchSysCacheExists2(nameCacheId, name, ObjectIdGetDatum(nspOid)))
- ereport(ERROR,
- (errcode(ERRCODE_DUPLICATE_OBJECT),
- errmsg("%s already exists in schema \"%s\"",
- getObjectDescriptionOids(classId, objid),
- get_namespace_name(nspOid))));
+ if (get_object_catcache_name(classId) >= 0)
+ {
+ ObjectAddress address;
+
+ address.classId = classId;
+ address.objectId = objid;
+ address.objectSubId = 0;
+
+ objtype = get_object_type(&address);
+ check_duplicate_objectname(objtype, nspOid,
+ NameStr(*DatumGetName(name)), NIL);
+ }
It would be much simpler to retain the old-style duplicate object check,
and compared to doing extra cache lookups, it'd still be much cleaner in
my view.
Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support
2012/11/19 Dimitri Fontaine <dimitri@2ndquadrant.fr>:
Kohei KaiGai <kaigai@kaigai.gr.jp> writes:
OK, Are you suggesting to add a "generic" comments such as "Generic
function to change the name of a given object, for simple cases ...",
not a list of OBJECT_* at the head of this function, aren't you?Just something like
* Most simple objects are covered by a generic function, the other
* still need special processing.Mainly I was surprised to see collation not supported here, but I didn't
take enough time to understand why that is the case. I will do that
later in the review process.
The reason why collation is not supported is that takes special name-
duplication checks. The new collation name must have no collision on
both of current database encoding and "any" encoding.
It might be an idea to have a simple rule similar to
AlterObjectNamespace_internal(); that requires caller to check
namespace-duplication, if the given object type has no catcache-id
with name-key.
The pain point is AlterObjectNamespace_internal is not invoked by
only ExecAlterObjectSchemaStmt(), but AlterObjectNamespace_oid()
also.I should remember better about that as the use case is extensions…
It is the reason why I had to put get_object_type() to find out OBJECT_*
from the supplied ObjectAddress, because this code path does not
available to pass down its ObjectType from the caller.If we really want to do that, I think I would only do that in
AlterObjectNamespace_oid and add an argument to
AlterObjectNamespace_internal, that you already have in
ExecAlterObjectSchemaStmt().But really, what about just removing that part of your patch instead:
@@ -396,14 +614,23 @@ 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. + * + * XXX - the caller should check object-name duplication, if the supplied + * object type need to take object arguments for identification, such as + * functions. */ - if (nameCacheId >= 0 && - SearchSysCacheExists2(nameCacheId, name, ObjectIdGetDatum(nspOid))) - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_OBJECT), - errmsg("%s already exists in schema \"%s\"", - getObjectDescriptionOids(classId, objid), - get_namespace_name(nspOid)))); + if (get_object_catcache_name(classId) >= 0) + { + ObjectAddress address; + + address.classId = classId; + address.objectId = objid; + address.objectSubId = 0; + + objtype = get_object_type(&address); + check_duplicate_objectname(objtype, nspOid, + NameStr(*DatumGetName(name)), NIL); + }It would be much simpler to retain the old-style duplicate object check,
and compared to doing extra cache lookups, it'd still be much cleaner in
my view.
Now, I get inclined to follow the manner of AlterObjectNamespace_internal
at AlterObjectRename also; that requires caller to check name duplication
in case when no catcache entry is supported.
That simplifies the logic to check name duplication, and allows to eliminate
get_object_type() here, even though RenameAggregate and
RenameFunction have to be remained.
Thanks,
--
KaiGai Kohei <kaigai@kaigai.gr.jp>
2012/11/19 Kohei KaiGai <kaigai@kaigai.gr.jp>:
2012/11/19 Dimitri Fontaine <dimitri@2ndquadrant.fr>:
Kohei KaiGai <kaigai@kaigai.gr.jp> writes:
OK, Are you suggesting to add a "generic" comments such as "Generic
function to change the name of a given object, for simple cases ...",
not a list of OBJECT_* at the head of this function, aren't you?Just something like
* Most simple objects are covered by a generic function, the other
* still need special processing.Mainly I was surprised to see collation not supported here, but I didn't
take enough time to understand why that is the case. I will do that
later in the review process.The reason why collation is not supported is that takes special name-
duplication checks. The new collation name must have no collision on
both of current database encoding and "any" encoding.
It might be an idea to have a simple rule similar to
AlterObjectNamespace_internal(); that requires caller to check
namespace-duplication, if the given object type has no catcache-id
with name-key.The pain point is AlterObjectNamespace_internal is not invoked by
only ExecAlterObjectSchemaStmt(), but AlterObjectNamespace_oid()
also.I should remember better about that as the use case is extensions…
It is the reason why I had to put get_object_type() to find out OBJECT_*
from the supplied ObjectAddress, because this code path does not
available to pass down its ObjectType from the caller.If we really want to do that, I think I would only do that in
AlterObjectNamespace_oid and add an argument to
AlterObjectNamespace_internal, that you already have in
ExecAlterObjectSchemaStmt().But really, what about just removing that part of your patch instead:
@@ -396,14 +614,23 @@ 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. + * + * XXX - the caller should check object-name duplication, if the supplied + * object type need to take object arguments for identification, such as + * functions. */ - if (nameCacheId >= 0 && - SearchSysCacheExists2(nameCacheId, name, ObjectIdGetDatum(nspOid))) - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_OBJECT), - errmsg("%s already exists in schema \"%s\"", - getObjectDescriptionOids(classId, objid), - get_namespace_name(nspOid)))); + if (get_object_catcache_name(classId) >= 0) + { + ObjectAddress address; + + address.classId = classId; + address.objectId = objid; + address.objectSubId = 0; + + objtype = get_object_type(&address); + check_duplicate_objectname(objtype, nspOid, + NameStr(*DatumGetName(name)), NIL); + }It would be much simpler to retain the old-style duplicate object check,
and compared to doing extra cache lookups, it'd still be much cleaner in
my view.Now, I get inclined to follow the manner of AlterObjectNamespace_internal
at AlterObjectRename also; that requires caller to check name duplication
in case when no catcache entry is supported.That simplifies the logic to check name duplication, and allows to eliminate
get_object_type() here, even though RenameAggregate and
RenameFunction have to be remained.
The attached patch is a revised version.
It follows the manner in ExecAlterObjectSchemaStmt(); that tries to check
name duplication for object classes that support catcache with name-key.
Elsewhere, it calls individual routines for each object class to solve object
name and check namespace conflicts.
For example, RenameFunction() is still called from ExecRenameStmt(),
however, it looks up the given function name and checks namespace
conflict only, then it just invokes AlterObjectRename_internal() in spite
of system catalog updates by itself.
It allows to use this consolidated routine by object classes with special
rule for namespace conflicts, such as collation.
In addition, this design allowed to eliminate get_object_type() to pull
OBJECT_* enum from class_id/object_id pair.
Please check this patch.
Thanks,
--
KaiGai Kohei <kaigai@kaigai.gr.jp>
Attachments:
pgsql-v9.3-alter-reworks.3-rename.v7.patchapplication/octet-stream; name=pgsql-v9.3-alter-reworks.3-rename.v7.patchDownload
src/backend/commands/aggregatecmds.c | 25 +---
src/backend/commands/alter.c | 209 ++++++++++++++++++++++-----
src/backend/commands/collationcmds.c | 20 +--
src/backend/commands/conversioncmds.c | 51 -------
src/backend/commands/event_trigger.c | 41 ------
src/backend/commands/foreigncmds.c | 77 ----------
src/backend/commands/functioncmds.c | 26 +---
src/backend/commands/opclasscmds.c | 78 ++++------
src/backend/commands/proclang.c | 37 -----
src/backend/commands/tablespace.c | 18 +--
src/backend/commands/tsearchcmds.c | 188 ------------------------
src/backend/parser/gram.y | 8 +-
src/include/commands/alter.h | 2 +
src/include/commands/conversioncmds.h | 1 -
src/include/commands/defrem.h | 2 -
src/include/commands/event_trigger.h | 1 -
src/include/commands/proclang.h | 1 -
src/test/regress/expected/alter_generic.out | 16 +-
src/test/regress/expected/event_trigger.out | 2 +-
19 files changed, 229 insertions(+), 574 deletions(-)
diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c
index b9f8711..62d364e 100644
--- a/src/backend/commands/aggregatecmds.c
+++ b/src/backend/commands/aggregatecmds.c
@@ -29,6 +29,7 @@
#include "catalog/pg_aggregate.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
+#include "commands/alter.h"
#include "commands/defrem.h"
#include "miscadmin.h"
#include "parser/parse_func.h"
@@ -240,15 +241,14 @@ RenameAggregate(List *name, List *args, const char *newname)
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 */
+ tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(procOid));
+ if (!HeapTupleIsValid(tup)) /* should not happen */
elog(ERROR, "cache lookup failed for function %u", procOid);
procForm = (Form_pg_proc) GETSTRUCT(tup);
@@ -268,22 +268,9 @@ RenameAggregate(List *name, List *args, const char *newname)
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);
+ /* OK, do the work */
+ AlterObjectRename_internal(rel, procOid, newname);
+ ReleaseSysCache(tup);
heap_close(rel, NoLock);
- heap_freetuple(tup);
}
diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c
index 9e271c3..6f08210 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,6 +46,145 @@
#include "utils/syscache.h"
#include "utils/tqual.h"
+/*
+ * 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).
+ * It checks name duplication only when catalog cache by name as key is
+ * available. Otherwise, the caller should ensure here is no object with
+ * identical name.
+ *
+ * rel: catalog relation containing object (RowExclusiveLock'd by caller)
+ * objectId: OID of object to be renamed
+ * new_name: CString representation of new name
+ */
+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;
+
+ oldtup = SearchSysCache1(oidCacheId, ObjectIdGetDatum(objectId));
+ if (!HeapTupleIsValid(oldtup))
+ elog(ERROR, "cache lookup failed for object %u of catalog \"%s\"",
+ objectId, RelationGetRelationName(rel));
+
+ datum = heap_getattr(oldtup, Anum_name,
+ RelationGetDescr(rel), &isnull);
+ Assert(!isnull);
+ old_name = NameStr(*(DatumGetName(datum)));
+
+ /* 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;
+
+ /* 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 set schema of %s",
+ getObjectDescriptionOids(classId, objectId)))));
+
+ /* 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 a suitable syscache available.
+ */
+ if (nameCacheId >= 0)
+ {
+ HeapTuple tup;
+
+ tup = SearchSysCache2(nameCacheId,
+ CStringGetDatum(new_name),
+ ObjectIdGetDatum(namespaceId));
+ if (HeapTupleIsValid(tup))
+ {
+ Oid exists = HeapTupleGetOid(tup);
+
+ if (OidIsValid(namespaceId))
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("%s already exists in schema \"%s\"",
+ getObjectDescriptionOids(classId, exists),
+ get_namespace_name(namespaceId))));
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("%s already exists",
+ getObjectDescriptionOids(classId, exists))));
+ ReleaseSysCache(tup);
+ }
+ }
+
+ /* 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
@@ -67,34 +207,10 @@ ExecRenameStmt(RenameStmt *stmt)
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_EVENT_TRIGGER:
- RenameEventTrigger(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;
@@ -103,6 +219,10 @@ ExecRenameStmt(RenameStmt *stmt)
RenameOpFamily(stmt->object, stmt->subname, stmt->newname);
break;
+ case OBJECT_FUNCTION:
+ RenameFunction(stmt->object, stmt->objarg, stmt->newname);
+ break;
+
case OBJECT_ROLE:
RenameRole(stmt->subname, stmt->newname);
break;
@@ -132,25 +252,38 @@ 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_CONVERSION:
+ case OBJECT_EVENT_TRIGGER:
+ case OBJECT_FDW:
+ case OBJECT_FOREIGN_SERVER:
+ case OBJECT_LANGUAGE:
+ 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;
+ {
+ ObjectAddress address;
+ Relation catalog;
+ Relation relation;
- case OBJECT_DOMAIN:
- case OBJECT_TYPE:
- RenameType(stmt);
+ address = get_object_address(stmt->renameType,
+ stmt->object, stmt->objarg,
+ &relation,
+ AccessExclusiveLock, false);
+ catalog = heap_open(address.classId, RowExclusiveLock);
+
+ AlterObjectRename_internal(catalog,
+ address.objectId,
+ stmt->newname);
+ if (relation)
+ heap_close(relation, NoLock);
+ heap_close(catalog, RowExclusiveLock);
+ }
break;
default:
diff --git a/src/backend/commands/collationcmds.c b/src/backend/commands/collationcmds.c
index ec22d11..458b573 100644
--- a/src/backend/commands/collationcmds.c
+++ b/src/backend/commands/collationcmds.c
@@ -152,7 +152,6 @@ RenameCollation(List *name, const char *newname)
Oid namespaceOid;
HeapTuple tup;
Relation rel;
- AclResult aclresult;
rel = heap_open(CollationRelationId, RowExclusiveLock);
@@ -187,23 +186,8 @@ RenameCollation(List *name, const char *newname)
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);
+ /* ok, do the task */
+ AlterObjectRename_internal(rel, collationOid, newname);
heap_close(rel, RowExclusiveLock);
}
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..cf0613f 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -1048,14 +1048,13 @@ RenameFunction(List *name, List *argtypes, const char *newname)
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 */
+ tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(procOid));
+ if (!HeapTupleIsValid(tup)) /* should not happen */
elog(ERROR, "cache lookup failed for function %u", procOid);
procForm = (Form_pg_proc) GETSTRUCT(tup);
@@ -1080,28 +1079,15 @@ RenameFunction(List *name, List *argtypes, const char *newname)
funcname_signature_string(newname,
procForm->pronargs,
NIL,
- procForm->proargtypes.values),
+ 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);
+ /* ok, do the work */
+ AlterObjectRename_internal(rel, procOid, newname);
+ ReleaseSysCache(tup);
heap_close(rel, NoLock);
- heap_freetuple(tup);
}
/*
diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c
index 099bb39..044ddd3 100644
--- a/src/backend/commands/opclasscmds.c
+++ b/src/backend/commands/opclasscmds.c
@@ -1666,19 +1666,16 @@ 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);
+ tup = OpClassCacheLookup(amOid, name, false);
+
opcOid = HeapTupleGetOid(tup);
namespaceOid = ((Form_pg_opclass) GETSTRUCT(tup))->opcnamespace;
@@ -1694,25 +1691,11 @@ RenameOpClass(List *name, const char *access_method, const char *newname)
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);
+ /* ok, do the work */
+ AlterObjectRename_internal(rel, opcOid, newname);
heap_close(rel, NoLock);
- heap_freetuple(tup);
+ ReleaseSysCache(tup);
}
/*
@@ -1721,14 +1704,13 @@ RenameOpClass(List *name, const char *access_method, const char *newname)
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;
+ Oid opfOid;
+ Oid amOid;
+ Oid namespaceOid;
+ char *schemaname;
+ char *opfname;
+ HeapTuple tup;
+ Relation rel;
amOid = get_am_oid(access_method, false);
@@ -1743,10 +1725,10 @@ RenameOpFamily(List *name, const char *access_method, const char *newname)
{
namespaceOid = LookupExplicitNamespace(schemaname);
- tup = SearchSysCacheCopy3(OPFAMILYAMNAMENSP,
- ObjectIdGetDatum(amOid),
- PointerGetDatum(opfname),
- ObjectIdGetDatum(namespaceOid));
+ tup = SearchSysCache3(OPFAMILYAMNAMENSP,
+ ObjectIdGetDatum(amOid),
+ PointerGetDatum(opfname),
+ ObjectIdGetDatum(namespaceOid));
if (!HeapTupleIsValid(tup))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
@@ -1754,6 +1736,8 @@ RenameOpFamily(List *name, const char *access_method, const char *newname)
opfname, access_method)));
opfOid = HeapTupleGetOid(tup);
+
+ ReleaseSysCache(tup);
}
else
{
@@ -1764,11 +1748,13 @@ RenameOpFamily(List *name, const char *access_method, const char *newname)
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);
+ tup = SearchSysCache1(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;
+
+ ReleaseSysCache(tup);
}
/* make sure the new name doesn't exist */
@@ -1784,24 +1770,10 @@ RenameOpFamily(List *name, const char *access_method, const char *newname)
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);
+ /* ok, do the work */
+ AlterObjectRename_internal(rel, opfOid, newname);
heap_close(rel, NoLock);
- heap_freetuple(tup);
}
/*
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/tablespace.c b/src/backend/commands/tablespace.c
index 5081d84..d80b3a6 100644
--- a/src/backend/commands/tablespace.c
+++ b/src/backend/commands/tablespace.c
@@ -61,6 +61,7 @@
#include "catalog/indexing.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_tablespace.h"
+#include "commands/alter.h"
#include "commands/comment.h"
#include "commands/seclabel.h"
#include "commands/tablespace.h"
@@ -825,8 +826,7 @@ RenameTableSpace(const char *oldname, const char *newname)
ScanKeyData entry[1];
HeapScanDesc scan;
HeapTuple tup;
- HeapTuple newtuple;
- Form_pg_tablespace newform;
+ Oid tableSpaceId;
/* Search pg_tablespace */
rel = heap_open(TableSpaceRelationId, RowExclusiveLock);
@@ -842,16 +842,9 @@ RenameTableSpace(const char *oldname, const char *newname)
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("tablespace \"%s\" does not exist",
oldname)));
-
- newtuple = heap_copytuple(tup);
- newform = (Form_pg_tablespace) GETSTRUCT(newtuple);
-
+ tableSpaceId = HeapTupleGetOid(tup);
heap_endscan(scan);
- /* Must be owner */
- if (!pg_tablespace_ownercheck(HeapTupleGetOid(newtuple), GetUserId()))
- aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_TABLESPACE, oldname);
-
/* Validate new name */
if (!allowSystemTableMods && IsReservedName(newname))
ereport(ERROR,
@@ -875,10 +868,7 @@ RenameTableSpace(const char *oldname, const char *newname)
heap_endscan(scan);
/* OK, update the entry */
- namestrcpy(&(newform->spcname), newname);
-
- simple_heap_update(rel, &newtuple->t_self, newtuple);
- CatalogUpdateIndexes(rel, newtuple);
+ AlterObjectRename_internal(rel, tableSpaceId, newname);
heap_close(rel, NoLock);
}
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..525e690 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;
@@ -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/include/commands/alter.h b/src/include/commands/alter.h
index 4493985..4d0ed8a 100644
--- a/src/include/commands/alter.h
+++ b/src/include/commands/alter.h
@@ -18,6 +18,8 @@
#include "nodes/parsenodes.h"
#include "utils/relcache.h"
+extern void AlterObjectRename_internal(Relation rel, Oid objid,
+ const char *newname);
extern void ExecRenameStmt(RenameStmt *stmt);
extern void ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt);
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..d5d4b98 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -102,8 +102,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/test/regress/expected/alter_generic.out b/src/test/regress/expected/alter_generic.out
index 3beddd7..43fcc55 100644
--- a/src/test/regress/expected/alter_generic.out
+++ b/src/test/regress/expected/alter_generic.out
@@ -110,7 +110,7 @@ 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"
+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"
@@ -152,10 +152,10 @@ 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
+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
+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
@@ -180,7 +180,7 @@ 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
+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
@@ -327,7 +327,7 @@ 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
+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"
@@ -368,7 +368,7 @@ 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
+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"
@@ -408,7 +408,7 @@ SELECT nspname, cfgname, rolname
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
+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);
@@ -433,7 +433,7 @@ CREATE TEXT SEARCH PARSER alt_ts_prs1
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
+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
diff --git a/src/test/regress/expected/event_trigger.out b/src/test/regress/expected/event_trigger.out
index 5c8f323..67997bd 100644
--- a/src/test/regress/expected/event_trigger.out
+++ b/src/test/regress/expected/event_trigger.out
@@ -77,7 +77,7 @@ alter role regression_bob superuser;
alter event trigger regress_event_trigger owner to regression_bob;
-- should fail, name collision
alter event trigger regress_event_trigger rename to regress_event_trigger2;
-ERROR: event trigger "regress_event_trigger2" already exists
+ERROR: event trigger regress_event_trigger2 already exists
-- OK
alter event trigger regress_event_trigger rename to regress_event_trigger3;
-- should fail, doesn't exist any more
Kohei KaiGai <kaigai@kaigai.gr.jp> writes:
The attached patch is a revised version.
I think you fixed all the problems I could see with your patch. It
applies cleanly (with some offsets), compiles cleanly (I have a custom
Makefile with CUSTOM_COPT=-Werror) and passes regression tests.
I'll go mark it as ready for commiter. Thanks!
It follows the manner in ExecAlterObjectSchemaStmt(); that tries to check
name duplication for object classes that support catcache with name-key.
Elsewhere, it calls individual routines for each object class to solve object
name and check namespace conflicts.
For example, RenameFunction() is still called from ExecRenameStmt(),
however, it looks up the given function name and checks namespace
conflict only, then it just invokes AlterObjectRename_internal() in spite
of system catalog updates by itself.
I think that's much better this way.
It allows to use this consolidated routine by object classes with special
rule for namespace conflicts, such as collation.
In addition, this design allowed to eliminate get_object_type() to pull
OBJECT_* enum from class_id/object_id pair.
Thanks for having done this refactoring.
Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
Kohei KaiGai escribió:
The attached patch is a revised version.
It follows the manner in ExecAlterObjectSchemaStmt(); that tries to check
name duplication for object classes that support catcache with name-key.
Elsewhere, it calls individual routines for each object class to solve object
name and check namespace conflicts.
For example, RenameFunction() is still called from ExecRenameStmt(),
however, it looks up the given function name and checks namespace
conflict only, then it just invokes AlterObjectRename_internal() in spite
of system catalog updates by itself.
It allows to use this consolidated routine by object classes with special
rule for namespace conflicts, such as collation.
In addition, this design allowed to eliminate get_object_type() to pull
OBJECT_* enum from class_id/object_id pair.
I checked this patch. It needed a rebase for the changes to return
OIDs. Attached patch applies to current HEAD. In general this looks
good, with one exception: it's using getObjectDescriptionOids() to build
the messages to complain in case the object already exists in the
current schema, which results in diffs like this:
-ERROR: event trigger "regress_event_trigger2" already exists
+ERROR: event trigger regress_event_trigger2 already exists
I don't know how tense we are about keeping the quotes, but I fear there
would be complaints because it took us lots of sweat, blood and tears to
get where we are now.
If this is considered a problem, I think the way to fix it is to have a
getObjectDescriptionOids() variant that quotes the object name in the
output. This would be pretty intrusive: we'd have to change things
so that, for instance,
appendStringInfo(&buffer, _("collation %s"),
NameStr(coll->collname));
would become
if (quotes)
appendStringInfo(&buffer, _("collation \"%s\""),
NameStr(coll->collname));
else
appendStringInfo(&buffer, _("collation %s"),
NameStr(coll->collname));
Not really thrilled with this idea. Of course,
getObjectDescription() itself should keep the same API as now, to avoid
useless churn all over the place.
--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
Attachments:
pgsql-v9.3-alter-reworks.3-rename.v8.patchtext/plain; charset=us-asciiDownload
*** a/src/backend/commands/aggregatecmds.c
--- b/src/backend/commands/aggregatecmds.c
***************
*** 29,34 ****
--- 29,35 ----
#include "catalog/pg_aggregate.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
+ #include "commands/alter.h"
#include "commands/defrem.h"
#include "miscadmin.h"
#include "parser/parse_func.h"
***************
*** 240,254 **** RenameAggregate(List *name, List *args, const char *newname)
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);
--- 241,254 ----
HeapTuple tup;
Form_pg_proc procForm;
Relation rel;
rel = heap_open(ProcedureRelationId, RowExclusiveLock);
/* Look up function and make sure it's an aggregate */
procOid = LookupAggNameTypeNames(name, args, false);
! tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(procOid));
! if (!HeapTupleIsValid(tup)) /* should not happen */
elog(ERROR, "cache lookup failed for function %u", procOid);
procForm = (Form_pg_proc) GETSTRUCT(tup);
***************
*** 268,291 **** RenameAggregate(List *name, List *args, const char *newname)
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;
}
--- 268,278 ----
procForm->proargtypes.values),
get_namespace_name(namespaceOid))));
! /* OK, do the work */
! AlterObjectRename_internal(rel, procOid, newname);
+ ReleaseSysCache(tup);
heap_close(rel, NoLock);
return procOid;
}
*** a/src/backend/commands/alter.c
--- b/src/backend/commands/alter.c
***************
*** 36,41 ****
--- 36,42 ----
#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,50 ****
--- 46,190 ----
#include "utils/syscache.h"
#include "utils/tqual.h"
+ /*
+ * 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).
+ * It checks name duplication only when catalog cache by name as key is
+ * available. Otherwise, the caller should ensure here is no object with
+ * identical name.
+ *
+ * rel: catalog relation containing object (RowExclusiveLock'd by caller)
+ * objectId: OID of object to be renamed
+ * new_name: CString representation of new name
+ */
+ 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;
+
+ oldtup = SearchSysCache1(oidCacheId, ObjectIdGetDatum(objectId));
+ if (!HeapTupleIsValid(oldtup))
+ elog(ERROR, "cache lookup failed for object %u of catalog \"%s\"",
+ objectId, RelationGetRelationName(rel));
+
+ datum = heap_getattr(oldtup, Anum_name,
+ RelationGetDescr(rel), &isnull);
+ Assert(!isnull);
+ old_name = NameStr(*(DatumGetName(datum)));
+
+ /* 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;
+
+ /* 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 set schema of %s",
+ getObjectDescriptionOids(classId, objectId)))));
+
+ /* 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 a suitable syscache available.
+ */
+ if (nameCacheId >= 0)
+ {
+ HeapTuple tup;
+
+ tup = SearchSysCache2(nameCacheId,
+ CStringGetDatum(new_name),
+ ObjectIdGetDatum(namespaceId));
+ if (HeapTupleIsValid(tup))
+ {
+ Oid exists = HeapTupleGetOid(tup);
+
+ if (OidIsValid(namespaceId))
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("%s already exists in schema \"%s\"",
+ getObjectDescriptionOids(classId, exists),
+ get_namespace_name(namespaceId))));
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("%s already exists",
+ getObjectDescriptionOids(classId, exists))));
+ ReleaseSysCache(tup);
+ }
+ }
+
+ /* 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
***************
*** 64,96 **** ExecRenameStmt(RenameStmt *stmt)
case OBJECT_CONSTRAINT:
return RenameConstraint(stmt);
- case OBJECT_CONVERSION:
- return RenameConversion(stmt->object, stmt->newname);
-
case OBJECT_DATABASE:
return RenameDatabase(stmt->subname, stmt->newname);
- case OBJECT_FDW:
- return RenameForeignDataWrapper(stmt->subname, stmt->newname);
-
- case OBJECT_FOREIGN_SERVER:
- return RenameForeignServer(stmt->subname, stmt->newname);
-
- case OBJECT_EVENT_TRIGGER:
- return RenameEventTrigger(stmt->subname, stmt->newname);
-
- case OBJECT_FUNCTION:
- return RenameFunction(stmt->object, stmt->objarg, stmt->newname);
-
- case OBJECT_LANGUAGE:
- return RenameLanguage(stmt->subname, stmt->newname);
-
case OBJECT_OPCLASS:
return RenameOpClass(stmt->object, stmt->subname, stmt->newname);
case OBJECT_OPFAMILY:
return RenameOpFamily(stmt->object, stmt->subname, stmt->newname);
case OBJECT_ROLE:
return RenameRole(stmt->subname, stmt->newname);
--- 204,221 ----
case OBJECT_CONSTRAINT:
return RenameConstraint(stmt);
case OBJECT_DATABASE:
return RenameDatabase(stmt->subname, stmt->newname);
case OBJECT_OPCLASS:
return RenameOpClass(stmt->object, stmt->subname, stmt->newname);
case OBJECT_OPFAMILY:
return RenameOpFamily(stmt->object, stmt->subname, stmt->newname);
+ case OBJECT_FUNCTION:
+ return RenameFunction(stmt->object, stmt->objarg, stmt->newname);
+
case OBJECT_ROLE:
return RenameRole(stmt->subname, stmt->newname);
***************
*** 114,134 **** ExecRenameStmt(RenameStmt *stmt)
case OBJECT_TRIGGER:
return renametrig(stmt);
! case OBJECT_TSPARSER:
! return RenameTSParser(stmt->object, stmt->newname);
case OBJECT_TSDICTIONARY:
! return RenameTSDictionary(stmt->object, stmt->newname);
!
case OBJECT_TSTEMPLATE:
! return RenameTSTemplate(stmt->object, stmt->newname);
! case OBJECT_TSCONFIGURATION:
! return RenameTSConfiguration(stmt->object, stmt->newname);
! case OBJECT_DOMAIN:
! case OBJECT_TYPE:
! return RenameType(stmt);
default:
elog(ERROR, "unrecognized rename stmt type: %d",
--- 239,277 ----
case OBJECT_TRIGGER:
return renametrig(stmt);
! case OBJECT_DOMAIN:
! case OBJECT_TYPE:
! return RenameType(stmt);
+ case OBJECT_CONVERSION:
+ case OBJECT_EVENT_TRIGGER:
+ case OBJECT_FDW:
+ case OBJECT_FOREIGN_SERVER:
+ case OBJECT_LANGUAGE:
+ case OBJECT_TSCONFIGURATION:
case OBJECT_TSDICTIONARY:
! case OBJECT_TSPARSER:
case OBJECT_TSTEMPLATE:
! {
! ObjectAddress address;
! Relation catalog;
! Relation relation;
! address = get_object_address(stmt->renameType,
! stmt->object, stmt->objarg,
! &relation,
! AccessExclusiveLock, false);
! catalog = heap_open(address.classId, RowExclusiveLock);
!
! AlterObjectRename_internal(catalog,
! address.objectId,
! stmt->newname);
! if (relation)
! heap_close(relation, NoLock);
! heap_close(catalog, RowExclusiveLock);
! return address.objectId;
! }
default:
elog(ERROR, "unrecognized rename stmt type: %d",
*** a/src/backend/commands/collationcmds.c
--- b/src/backend/commands/collationcmds.c
***************
*** 154,160 **** RenameCollation(List *name, const char *newname)
Oid namespaceOid;
HeapTuple tup;
Relation rel;
- AclResult aclresult;
rel = heap_open(CollationRelationId, RowExclusiveLock);
--- 154,159 ----
***************
*** 189,211 **** RenameCollation(List *name, const char *newname)
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);
--- 188,195 ----
newname,
get_namespace_name(namespaceOid))));
! /* ok, do the task */
! AlterObjectRename_internal(rel, collationOid, newname);
heap_close(rel, RowExclusiveLock);
*** a/src/backend/commands/conversioncmds.c
--- b/src/backend/commands/conversioncmds.c
***************
*** 114,169 **** 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;
- }
--- 114,116 ----
*** a/src/backend/commands/event_trigger.c
--- b/src/backend/commands/event_trigger.c
***************
*** 417,468 **** 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
*/
--- 417,422 ----
*** a/src/backend/commands/foreigncmds.c
--- b/src/backend/commands/foreigncmds.c
***************
*** 200,292 **** 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.
*
--- 200,205 ----
*** a/src/backend/commands/functioncmds.c
--- b/src/backend/commands/functioncmds.c
***************
*** 1048,1061 **** RenameFunction(List *name, List *argtypes, const char *newname)
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);
--- 1048,1060 ----
HeapTuple tup;
Form_pg_proc procForm;
Relation rel;
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);
procForm = (Form_pg_proc) GETSTRUCT(tup);
***************
*** 1084,1107 **** RenameFunction(List *name, List *argtypes, const char *newname)
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);
return procOid;
}
--- 1083,1093 ----
get_namespace_name(namespaceOid))));
}
! /* ok, do the work */
! AlterObjectRename_internal(rel, procOid, newname);
+ ReleaseSysCache(tup);
heap_close(rel, NoLock);
return procOid;
}
*** a/src/backend/commands/opclasscmds.c
--- b/src/backend/commands/opclasscmds.c
***************
*** 1670,1688 **** 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;
--- 1670,1685 ----
Oid opcOid;
Oid amOid;
Oid namespaceOid;
HeapTuple tup;
Relation rel;
amOid = get_am_oid(access_method, false);
rel = heap_open(OperatorClassRelationId, RowExclusiveLock);
/* Look up the opclass. */
! tup = OpClassCacheLookup(amOid, name, false);
!
opcOid = HeapTupleGetOid(tup);
namespaceOid = ((Form_pg_opclass) GETSTRUCT(tup))->opcnamespace;
***************
*** 1699,1722 **** RenameOpClass(List *name, const char *access_method, const char *newname)
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;
}
--- 1696,1706 ----
get_namespace_name(namespaceOid))));
}
! /* ok, do the work */
! AlterObjectRename_internal(rel, opcOid, newname);
heap_close(rel, NoLock);
! ReleaseSysCache(tup);
return opcOid;
}
***************
*** 1734,1740 **** RenameOpFamily(List *name, const char *access_method, const char *newname)
char *opfname;
HeapTuple tup;
Relation rel;
- AclResult aclresult;
amOid = get_am_oid(access_method, false);
--- 1718,1723 ----
***************
*** 1749,1758 **** RenameOpFamily(List *name, const char *access_method, const char *newname)
{
namespaceOid = LookupExplicitNamespace(schemaname);
! tup = SearchSysCacheCopy3(OPFAMILYAMNAMENSP,
! ObjectIdGetDatum(amOid),
! PointerGetDatum(opfname),
! ObjectIdGetDatum(namespaceOid));
if (!HeapTupleIsValid(tup))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
--- 1732,1741 ----
{
namespaceOid = LookupExplicitNamespace(schemaname);
! tup = SearchSysCache3(OPFAMILYAMNAMENSP,
! ObjectIdGetDatum(amOid),
! PointerGetDatum(opfname),
! ObjectIdGetDatum(namespaceOid));
if (!HeapTupleIsValid(tup))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
***************
*** 1760,1765 **** RenameOpFamily(List *name, const char *access_method, const char *newname)
--- 1743,1750 ----
opfname, access_method)));
opfOid = HeapTupleGetOid(tup);
+
+ ReleaseSysCache(tup);
}
else
{
***************
*** 1770,1780 **** RenameOpFamily(List *name, const char *access_method, const char *newname)
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 */
--- 1755,1767 ----
errmsg("operator family \"%s\" does not exist for access method \"%s\"",
opfname, access_method)));
! tup = SearchSysCache1(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;
+
+ ReleaseSysCache(tup);
}
/* make sure the new name doesn't exist */
***************
*** 1790,1813 **** RenameOpFamily(List *name, const char *access_method, const char *newname)
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;
}
--- 1777,1786 ----
get_namespace_name(namespaceOid))));
}
! /* ok, do the work */
! AlterObjectRename_internal(rel, opfOid, newname);
heap_close(rel, NoLock);
return opfOid;
}
*** a/src/backend/commands/proclang.c
--- b/src/backend/commands/proclang.c
***************
*** 537,584 **** 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
--- 537,542 ----
*** a/src/backend/commands/tablespace.c
--- b/src/backend/commands/tablespace.c
***************
*** 61,66 ****
--- 61,67 ----
#include "catalog/indexing.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_tablespace.h"
+ #include "commands/alter.h"
#include "commands/comment.h"
#include "commands/seclabel.h"
#include "commands/tablespace.h"
***************
*** 828,835 **** RenameTableSpace(const char *oldname, const char *newname)
ScanKeyData entry[1];
HeapScanDesc scan;
HeapTuple tup;
- HeapTuple newtuple;
- Form_pg_tablespace newform;
/* Search pg_tablespace */
rel = heap_open(TableSpaceRelationId, RowExclusiveLock);
--- 829,834 ----
***************
*** 847,861 **** RenameTableSpace(const char *oldname, const char *newname)
oldname)));
tspId = HeapTupleGetOid(tup);
- newtuple = heap_copytuple(tup);
- newform = (Form_pg_tablespace) GETSTRUCT(newtuple);
heap_endscan(scan);
- /* Must be owner */
- if (!pg_tablespace_ownercheck(HeapTupleGetOid(newtuple), GetUserId()))
- aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_TABLESPACE, oldname);
-
/* Validate new name */
if (!allowSystemTableMods && IsReservedName(newname))
ereport(ERROR,
--- 846,854 ----
***************
*** 879,888 **** RenameTableSpace(const char *oldname, const char *newname)
heap_endscan(scan);
/* OK, update the entry */
! namestrcpy(&(newform->spcname), newname);
!
! simple_heap_update(rel, &newtuple->t_self, newtuple);
! CatalogUpdateIndexes(rel, newtuple);
heap_close(rel, NoLock);
--- 872,878 ----
heap_endscan(scan);
/* OK, update the entry */
! AlterObjectRename_internal(rel, tspId, newname);
heap_close(rel, NoLock);
*** a/src/backend/commands/tsearchcmds.c
--- b/src/backend/commands/tsearchcmds.c
***************
*** 305,355 **** 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 -----------------------*/
/*
--- 305,310 ----
***************
*** 535,593 **** 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
--- 490,495 ----
***************
*** 905,956 **** 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
--- 807,812 ----
***************
*** 1249,1306 **** 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
--- 1105,1110 ----
*** a/src/backend/parser/gram.y
--- b/src/backend/parser/gram.y
***************
*** 6776,6782 **** RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_FDW;
! n->subname = $5;
n->newname = $8;
n->missing_ok = false;
$$ = (Node *)n;
--- 6776,6782 ----
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_FDW;
! n->object = list_make1(makeString($5));
n->newname = $8;
n->missing_ok = false;
$$ = (Node *)n;
***************
*** 6804,6810 **** RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_LANGUAGE;
! n->subname = $4;
n->newname = $7;
n->missing_ok = false;
$$ = (Node *)n;
--- 6804,6810 ----
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_LANGUAGE;
! n->object = list_make1(makeString($4));
n->newname = $7;
n->missing_ok = false;
$$ = (Node *)n;
***************
*** 6842,6848 **** RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_FOREIGN_SERVER;
! n->subname = $3;
n->newname = $6;
n->missing_ok = false;
$$ = (Node *)n;
--- 6842,6848 ----
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_FOREIGN_SERVER;
! n->object = list_make1(makeString($3));
n->newname = $6;
n->missing_ok = false;
$$ = (Node *)n;
***************
*** 7015,7021 **** RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_EVENT_TRIGGER;
! n->subname = $4;
n->newname = $7;
$$ = (Node *)n;
}
--- 7015,7021 ----
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_EVENT_TRIGGER;
! n->object = list_make1(makeString($4));
n->newname = $7;
$$ = (Node *)n;
}
*** a/src/include/commands/alter.h
--- b/src/include/commands/alter.h
***************
*** 18,23 ****
--- 18,25 ----
#include "nodes/parsenodes.h"
#include "utils/relcache.h"
+ extern void AlterObjectRename_internal(Relation rel, Oid objid,
+ const char *newname);
extern Oid ExecRenameStmt(RenameStmt *stmt);
extern Oid ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt);
*** a/src/include/commands/conversioncmds.h
--- b/src/include/commands/conversioncmds.h
***************
*** 18,23 ****
#include "nodes/parsenodes.h"
extern Oid CreateConversionCommand(CreateConversionStmt *parsetree);
- extern Oid RenameConversion(List *name, const char *newname);
#endif /* CONVERSIONCMDS_H */
--- 18,22 ----
*** a/src/include/commands/defrem.h
--- b/src/include/commands/defrem.h
***************
*** 102,109 **** extern text *serialize_deflist(List *deflist);
extern List *deserialize_deflist(Datum txt);
/* commands/foreigncmds.c */
- extern Oid RenameForeignServer(const char *oldname, const char *newname);
- extern Oid RenameForeignDataWrapper(const char *oldname, const char *newname);
extern Oid AlterForeignServerOwner(const char *name, Oid newOwnerId);
extern void AlterForeignServerOwner_oid(Oid, Oid newOwnerId);
extern Oid AlterForeignDataWrapperOwner(const char *name, Oid newOwnerId);
--- 102,107 ----
*** a/src/include/commands/event_trigger.h
--- b/src/include/commands/event_trigger.h
***************
*** 36,42 **** extern void RemoveEventTriggerById(Oid ctrigOid);
extern Oid get_event_trigger_oid(const char *trigname, bool missing_ok);
extern Oid AlterEventTrigger(AlterEventTrigStmt *stmt);
- extern Oid RenameEventTrigger(const char* trigname, const char *newname);
extern Oid AlterEventTriggerOwner(const char *name, Oid newOwnerId);
extern void AlterEventTriggerOwner_oid(Oid, Oid newOwnerId);
--- 36,41 ----
*** a/src/include/commands/proclang.h
--- b/src/include/commands/proclang.h
***************
*** 16,22 ****
extern Oid CreateProceduralLanguage(CreatePLangStmt *stmt);
extern void DropProceduralLanguageById(Oid langOid);
- extern Oid RenameLanguage(const char *oldname, const char *newname);
extern bool PLTemplateExists(const char *languageName);
extern Oid get_language_oid(const char *langname, bool missing_ok);
--- 16,21 ----
*** a/src/test/regress/expected/alter_generic.out
--- b/src/test/regress/expected/alter_generic.out
***************
*** 110,116 **** 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"
--- 110,116 ----
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"
***************
*** 152,161 **** 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
--- 152,161 ----
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
***************
*** 180,186 **** 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
--- 180,186 ----
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
***************
*** 327,333 **** 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
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"
--- 327,333 ----
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"
***************
*** 368,374 **** 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
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"
--- 368,374 ----
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"
***************
*** 408,414 **** SELECT nspname, cfgname, rolname
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
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);
--- 408,414 ----
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);
***************
*** 433,439 **** CREATE TEXT SEARCH PARSER alt_ts_prs1
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
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
--- 433,439 ----
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
*** a/src/test/regress/expected/event_trigger.out
--- b/src/test/regress/expected/event_trigger.out
***************
*** 77,83 **** alter role regression_bob superuser;
alter event trigger regress_event_trigger owner to regression_bob;
-- should fail, name collision
alter event trigger regress_event_trigger rename to regress_event_trigger2;
! ERROR: event trigger "regress_event_trigger2" already exists
-- OK
alter event trigger regress_event_trigger rename to regress_event_trigger3;
-- should fail, doesn't exist any more
--- 77,83 ----
alter event trigger regress_event_trigger owner to regression_bob;
-- should fail, name collision
alter event trigger regress_event_trigger rename to regress_event_trigger2;
! ERROR: event trigger regress_event_trigger2 already exists
-- OK
alter event trigger regress_event_trigger rename to regress_event_trigger3;
-- should fail, doesn't exist any more
On Mon, Jan 7, 2013 at 3:43 PM, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:
Kohei KaiGai escribió:
The attached patch is a revised version.
It follows the manner in ExecAlterObjectSchemaStmt(); that tries to check
name duplication for object classes that support catcache with name-key.
Elsewhere, it calls individual routines for each object class to solve object
name and check namespace conflicts.
For example, RenameFunction() is still called from ExecRenameStmt(),
however, it looks up the given function name and checks namespace
conflict only, then it just invokes AlterObjectRename_internal() in spite
of system catalog updates by itself.
It allows to use this consolidated routine by object classes with special
rule for namespace conflicts, such as collation.
In addition, this design allowed to eliminate get_object_type() to pull
OBJECT_* enum from class_id/object_id pair.I checked this patch. It needed a rebase for the changes to return
OIDs. Attached patch applies to current HEAD. In general this looks
good, with one exception: it's using getObjectDescriptionOids() to build
the messages to complain in case the object already exists in the
current schema, which results in diffs like this:-ERROR: event trigger "regress_event_trigger2" already exists +ERROR: event trigger regress_event_trigger2 already existsI don't know how tense we are about keeping the quotes, but I fear there
would be complaints because it took us lots of sweat, blood and tears to
get where we are now.If this is considered a problem, I think the way to fix it is to have a
getObjectDescriptionOids() variant that quotes the object name in the
output. This would be pretty intrusive: we'd have to change things
so that, for instance,appendStringInfo(&buffer, _("collation %s"),
NameStr(coll->collname));would become
if (quotes)
appendStringInfo(&buffer, _("collation \"%s\""),
NameStr(coll->collname));
else
appendStringInfo(&buffer, _("collation %s"),
NameStr(coll->collname));Not really thrilled with this idea. Of course,
getObjectDescription() itself should keep the same API as now, to avoid
useless churn all over the place.
This sort of thing has been rejected repeatedly in the past on
translation grounds:
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("%s already exists in schema \"%s\"",
+ getObjectDescriptionOids(classId, exists),
+ get_namespace_name(namespaceId))));
If we're going to start allowing that, there's plenty of other code
that can be hit with the same hammer, but I'm pretty sure that all
previous proposals in this area have been slapped down.
--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
Robert Haas <robertmhaas@gmail.com> writes:
On Mon, Jan 7, 2013 at 3:43 PM, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:
I checked this patch. It needed a rebase for the changes to return
OIDs. Attached patch applies to current HEAD. In general this looks
good, with one exception: it's using getObjectDescriptionOids() to build
the messages to complain in case the object already exists in the
current schema, which results in diffs like this:-ERROR: event trigger "regress_event_trigger2" already exists +ERROR: event trigger regress_event_trigger2 already existsI don't know how tense we are about keeping the quotes, but I fear there
would be complaints because it took us lots of sweat, blood and tears to
get where we are now.If this is considered a problem, I think the way to fix it is to have a
getObjectDescriptionOids() variant that quotes the object name in the
output.
This sort of thing has been rejected repeatedly in the past on
translation grounds:
Yes. I'm surprised Alvaro isn't well aware of the rules against trying
to build error messages out of sentence fragments: see first item under
http://www.postgresql.org/docs/devel/static/nls-programmer.html#NLS-GUIDELINES
Presence or absence of quotes is the very least of this code's i18n
problems.
If we had no other choice, we might consider a workaround such as that
suggested in "Assembling Error Messages"
http://www.postgresql.org/docs/devel/static/error-style-guide.html#AEN98605
but frankly I'm not convinced that this patch is attractive enough to
justify a degradation in message readability.
regards, tom lane
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
2013/1/7 Tom Lane <tgl@sss.pgh.pa.us>:
Robert Haas <robertmhaas@gmail.com> writes:
On Mon, Jan 7, 2013 at 3:43 PM, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:
I checked this patch. It needed a rebase for the changes to return
OIDs. Attached patch applies to current HEAD. In general this looks
good, with one exception: it's using getObjectDescriptionOids() to build
the messages to complain in case the object already exists in the
current schema, which results in diffs like this:-ERROR: event trigger "regress_event_trigger2" already exists +ERROR: event trigger regress_event_trigger2 already existsI don't know how tense we are about keeping the quotes, but I fear there
would be complaints because it took us lots of sweat, blood and tears to
get where we are now.If this is considered a problem, I think the way to fix it is to have a
getObjectDescriptionOids() variant that quotes the object name in the
output.This sort of thing has been rejected repeatedly in the past on
translation grounds:Yes. I'm surprised Alvaro isn't well aware of the rules against trying
to build error messages out of sentence fragments: see first item under
http://www.postgresql.org/docs/devel/static/nls-programmer.html#NLS-GUIDELINESPresence or absence of quotes is the very least of this code's i18n
problems.If we had no other choice, we might consider a workaround such as that
suggested in "Assembling Error Messages"
http://www.postgresql.org/docs/devel/static/error-style-guide.html#AEN98605
but frankly I'm not convinced that this patch is attractive enough to
justify a degradation in message readability.
Sorry, I forgot Robert pointed out same thing before.
I'll reconstruct the portion to raise an error message.
Thanks,
--
KaiGai Kohei <kaigai@kaigai.gr.jp>
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
Tom Lane escribió:
Robert Haas <robertmhaas@gmail.com> writes:
On Mon, Jan 7, 2013 at 3:43 PM, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:
If this is considered a problem, I think the way to fix it is to have a
getObjectDescriptionOids() variant that quotes the object name in the
output.This sort of thing has been rejected repeatedly in the past on
translation grounds:Yes. I'm surprised Alvaro isn't well aware of the rules against trying
to build error messages out of sentence fragments: see first item under
http://www.postgresql.org/docs/devel/static/nls-programmer.html#NLS-GUIDELINES
Actually I'm fully aware of the limitations; I just had a brain fade. I
knew there was something wrong with that usage of getObjectDescription,
but managed to miss what it was exactly. Doh. Thankfully there are
other hackers paying attention.
BTW this patch was correct in this regard in a previous version -- there
was one separate copy of the error message per object type. I think
it's just a matter of returning to that older coding.
--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
2013/1/7 Alvaro Herrera <alvherre@2ndquadrant.com>:
Tom Lane escribió:
Robert Haas <robertmhaas@gmail.com> writes:
On Mon, Jan 7, 2013 at 3:43 PM, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:
If this is considered a problem, I think the way to fix it is to have a
getObjectDescriptionOids() variant that quotes the object name in the
output.This sort of thing has been rejected repeatedly in the past on
translation grounds:Yes. I'm surprised Alvaro isn't well aware of the rules against trying
to build error messages out of sentence fragments: see first item under
http://www.postgresql.org/docs/devel/static/nls-programmer.html#NLS-GUIDELINESActually I'm fully aware of the limitations; I just had a brain fade. I
knew there was something wrong with that usage of getObjectDescription,
but managed to miss what it was exactly. Doh. Thankfully there are
other hackers paying attention.BTW this patch was correct in this regard in a previous version -- there
was one separate copy of the error message per object type. I think
it's just a matter of returning to that older coding.
The attached patch is a rebased version towards the latest master
branch, and fix up the issue around error messages on name conflicts.
I could also find an abused of getObjectDescription() for error message
of namespace conflicts at AlterObjectNamespace_internal().
The newly added ereport_on_namespace_conflict() can handle the
both of cases, so I also replaced it.
As we have a discussion in another thread, we may add special case
handling for functions and collation on checks on namespace conflicts,
however, I didn't tough code path of them, right now.
Thanks,
--
KaiGai Kohei <kaigai@kaigai.gr.jp>
Attachments:
pgsql-v9.3-alter-reworks.3-rename.v8.patchapplication/octet-stream; name=pgsql-v9.3-alter-reworks.3-rename.v8.patchDownload
src/backend/commands/aggregatecmds.c | 25 +--
src/backend/commands/alter.c | 247 +++++++++++++++++++++++----
src/backend/commands/collationcmds.c | 20 +--
src/backend/commands/conversioncmds.c | 53 ------
src/backend/commands/event_trigger.c | 46 -----
src/backend/commands/foreigncmds.c | 87 ----------
src/backend/commands/functioncmds.c | 26 +--
src/backend/commands/opclasscmds.c | 78 +++------
src/backend/commands/proclang.c | 42 -----
src/backend/commands/tablespace.c | 14 +-
src/backend/commands/tsearchcmds.c | 196 ---------------------
src/backend/parser/gram.y | 8 +-
src/backend/storage/lmgr/lock.c | 29 +++-
src/include/commands/alter.h | 2 +
src/include/commands/conversioncmds.h | 1 -
src/include/commands/defrem.h | 2 -
src/include/commands/event_trigger.h | 1 -
src/include/commands/proclang.h | 1 -
src/test/regress/expected/alter_generic.out | 12 +-
19 files changed, 295 insertions(+), 595 deletions(-)
diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c
index 1447683..b069040 100644
--- a/src/backend/commands/aggregatecmds.c
+++ b/src/backend/commands/aggregatecmds.c
@@ -29,6 +29,7 @@
#include "catalog/pg_aggregate.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
+#include "commands/alter.h"
#include "commands/defrem.h"
#include "miscadmin.h"
#include "parser/parse_func.h"
@@ -240,15 +241,14 @@ RenameAggregate(List *name, List *args, const char *newname)
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 */
+ tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(procOid));
+ if (!HeapTupleIsValid(tup)) /* should not happen */
elog(ERROR, "cache lookup failed for function %u", procOid);
procForm = (Form_pg_proc) GETSTRUCT(tup);
@@ -268,24 +268,11 @@ RenameAggregate(List *name, List *args, const char *newname)
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);
+ /* OK, do the work */
+ AlterObjectRename_internal(rel, procOid, newname);
+ ReleaseSysCache(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 73138f9..461e61c 100644
--- a/src/backend/commands/alter.c
+++ b/src/backend/commands/alter.c
@@ -19,9 +19,18 @@
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/namespace.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_ts_config.h"
+#include "catalog/pg_ts_dict.h"
+#include "catalog/pg_ts_parser.h"
+#include "catalog/pg_ts_template.h"
#include "commands/alter.h"
#include "commands/collationcmds.h"
#include "commands/conversioncmds.h"
@@ -36,6 +45,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,6 +55,184 @@
#include "utils/syscache.h"
#include "utils/tqual.h"
+/*
+ * ereport_on_namespace_conflict
+ *
+ * It raises an error with appropriate message for namespace conflict.
+ */
+static void
+ereport_on_namespace_conflict(Oid classId, Oid namespaceId, const char *name)
+{
+ const char *fmt = NULL;
+
+ switch (classId)
+ {
+ case ConversionRelationId:
+ fmt = "conversion \"%s\" already exists in schema \"%s\"";
+ break;
+
+ case EventTriggerRelationId:
+ fmt = "event trigger \"%s\" already exists";
+ break;
+
+ case ForeignDataWrapperRelationId:
+ fmt = "foreign-data wrapper \"%s\" already exists";
+ break;
+
+ case ForeignServerRelationId:
+ fmt = "server \"%s\" already exists";
+ break;
+
+ case LanguageRelationId:
+ fmt = "language \"%s\" already exists";
+ break;
+
+ case TSConfigRelationId:
+ fmt = "text search parser \"%s\" already exists";
+ break;
+
+ case TSDictionaryRelationId:
+ fmt = "text search dictionary \"%s\" already exists";
+ break;
+
+ case TSParserRelationId:
+ fmt = "text search parser \"%s\" already exists";
+ break;
+
+ case TSTemplateRelationId:
+ fmt = "text search template \"%s\" already exists";
+ break;
+
+ default: /* should not happen */
+ elog(ERROR, "unexpected class-id: %u", classId);
+ }
+
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ (OidIsValid(namespaceId) ?
+ errmsg(fmt, name, get_namespace_name(namespaceId)) :
+ errmsg(fmt, name))));
+}
+
+/*
+ * 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).
+ * It checks name duplication only when catalog cache by name as key is
+ * available. Otherwise, the caller should ensure here is no object with
+ * identical name.
+ *
+ * rel: catalog relation containing object (RowExclusiveLock'd by caller)
+ * objectId: OID of object to be renamed
+ * new_name: CString representation of new name
+ */
+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;
+
+ oldtup = SearchSysCache1(oidCacheId, ObjectIdGetDatum(objectId));
+ if (!HeapTupleIsValid(oldtup))
+ elog(ERROR, "cache lookup failed for object %u of catalog \"%s\"",
+ objectId, RelationGetRelationName(rel));
+
+ datum = heap_getattr(oldtup, Anum_name,
+ RelationGetDescr(rel), &isnull);
+ Assert(!isnull);
+ old_name = NameStr(*(DatumGetName(datum)));
+
+ /* 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;
+
+ /* 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 set schema of %s",
+ getObjectDescriptionOids(classId, objectId)))));
+
+ /* 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 a suitable syscache available.
+ */
+ if (nameCacheId >= 0 &&
+ SearchSysCacheExists2(nameCacheId,
+ CStringGetDatum(new_name),
+ ObjectIdGetDatum(namespaceId)))
+ ereport_on_namespace_conflict(classId, namespaceId, 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
@@ -64,27 +252,12 @@ ExecRenameStmt(RenameStmt *stmt)
case OBJECT_CONSTRAINT:
return RenameConstraint(stmt);
- case OBJECT_CONVERSION:
- return RenameConversion(stmt->object, stmt->newname);
-
case OBJECT_DATABASE:
return RenameDatabase(stmt->subname, stmt->newname);
- case OBJECT_FDW:
- return RenameForeignDataWrapper(stmt->subname, stmt->newname);
-
- case OBJECT_FOREIGN_SERVER:
- return RenameForeignServer(stmt->subname, stmt->newname);
-
- case OBJECT_EVENT_TRIGGER:
- return RenameEventTrigger(stmt->subname, stmt->newname);
-
case OBJECT_FUNCTION:
return RenameFunction(stmt->object, stmt->objarg, stmt->newname);
- case OBJECT_LANGUAGE:
- return RenameLanguage(stmt->subname, stmt->newname);
-
case OBJECT_OPCLASS:
return RenameOpClass(stmt->object, stmt->subname, stmt->newname);
@@ -114,21 +287,39 @@ 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_CONVERSION:
+ case OBJECT_EVENT_TRIGGER:
+ case OBJECT_FDW:
+ case OBJECT_FOREIGN_SERVER:
+ 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);
+ catalog = heap_open(address.classId, RowExclusiveLock);
+
+ AlterObjectRename_internal(catalog,
+ address.objectId,
+ stmt->newname);
+ if (relation)
+ heap_close(relation, NoLock);
+ heap_close(catalog, RowExclusiveLock);
- case OBJECT_DOMAIN:
- case OBJECT_TYPE:
- return RenameType(stmt);
+ return address.objectId;
+ }
default:
elog(ERROR, "unrecognized rename stmt type: %d",
@@ -375,11 +566,7 @@ AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid)
*/
if (nameCacheId >= 0 &&
SearchSysCacheExists2(nameCacheId, name, ObjectIdGetDatum(nspOid)))
- ereport(ERROR,
- (errcode(ERRCODE_DUPLICATE_OBJECT),
- errmsg("%s already exists in schema \"%s\"",
- getObjectDescriptionOids(classId, objid),
- get_namespace_name(nspOid))));
+ ereport_on_namespace_conflict(classId, nspOid, DatumGetCString(name));
/* Build modified tuple */
values = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(Datum));
diff --git a/src/backend/commands/collationcmds.c b/src/backend/commands/collationcmds.c
index b763f15..f0933b4 100644
--- a/src/backend/commands/collationcmds.c
+++ b/src/backend/commands/collationcmds.c
@@ -154,7 +154,6 @@ RenameCollation(List *name, const char *newname)
Oid namespaceOid;
HeapTuple tup;
Relation rel;
- AclResult aclresult;
rel = heap_open(CollationRelationId, RowExclusiveLock);
@@ -189,23 +188,8 @@ RenameCollation(List *name, const char *newname)
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);
+ /* ok, do the task */
+ AlterObjectRename_internal(rel, collationOid, newname);
heap_close(rel, RowExclusiveLock);
diff --git a/src/backend/commands/conversioncmds.c b/src/backend/commands/conversioncmds.c
index 35d4d08..84ab434 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 99b17a0..9063187 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 d3af8dc..7700e91 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 c858511..cbfd737 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -1048,14 +1048,13 @@ RenameFunction(List *name, List *argtypes, const char *newname)
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 */
+ tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(procOid));
+ if (!HeapTupleIsValid(tup)) /* should not happen */
elog(ERROR, "cache lookup failed for function %u", procOid);
procForm = (Form_pg_proc) GETSTRUCT(tup);
@@ -1080,28 +1079,15 @@ RenameFunction(List *name, List *argtypes, const char *newname)
funcname_signature_string(newname,
procForm->pronargs,
NIL,
- procForm->proargtypes.values),
+ 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);
+ /* ok, do the work */
+ AlterObjectRename_internal(rel, procOid, newname);
+ ReleaseSysCache(tup);
heap_close(rel, NoLock);
- heap_freetuple(tup);
return procOid;
}
diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c
index 4b57e3d..d12149a 100644
--- a/src/backend/commands/opclasscmds.c
+++ b/src/backend/commands/opclasscmds.c
@@ -1670,19 +1670,16 @@ 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);
+ tup = OpClassCacheLookup(amOid, name, false);
+
opcOid = HeapTupleGetOid(tup);
namespaceOid = ((Form_pg_opclass) GETSTRUCT(tup))->opcnamespace;
@@ -1698,25 +1695,11 @@ RenameOpClass(List *name, const char *access_method, const char *newname)
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);
+ /* ok, do the work */
+ AlterObjectRename_internal(rel, opcOid, newname);
heap_close(rel, NoLock);
- heap_freetuple(tup);
+ ReleaseSysCache(tup);
return opcOid;
}
@@ -1727,14 +1710,13 @@ RenameOpClass(List *name, const char *access_method, const char *newname)
Oid
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;
+ Oid opfOid;
+ Oid amOid;
+ Oid namespaceOid;
+ char *schemaname;
+ char *opfname;
+ HeapTuple tup;
+ Relation rel;
amOid = get_am_oid(access_method, false);
@@ -1749,10 +1731,10 @@ RenameOpFamily(List *name, const char *access_method, const char *newname)
{
namespaceOid = LookupExplicitNamespace(schemaname);
- tup = SearchSysCacheCopy3(OPFAMILYAMNAMENSP,
- ObjectIdGetDatum(amOid),
- PointerGetDatum(opfname),
- ObjectIdGetDatum(namespaceOid));
+ tup = SearchSysCache3(OPFAMILYAMNAMENSP,
+ ObjectIdGetDatum(amOid),
+ PointerGetDatum(opfname),
+ ObjectIdGetDatum(namespaceOid));
if (!HeapTupleIsValid(tup))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
@@ -1760,6 +1742,8 @@ RenameOpFamily(List *name, const char *access_method, const char *newname)
opfname, access_method)));
opfOid = HeapTupleGetOid(tup);
+
+ ReleaseSysCache(tup);
}
else
{
@@ -1770,11 +1754,13 @@ RenameOpFamily(List *name, const char *access_method, const char *newname)
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);
+ tup = SearchSysCache1(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;
+
+ ReleaseSysCache(tup);
}
/* make sure the new name doesn't exist */
@@ -1790,24 +1776,10 @@ RenameOpFamily(List *name, const char *access_method, const char *newname)
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);
+ /* ok, do the work */
+ AlterObjectRename_internal(rel, opfOid, newname);
heap_close(rel, NoLock);
- heap_freetuple(tup);
return opfOid;
}
diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c
index 718b711..e6c6d4e 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/tablespace.c b/src/backend/commands/tablespace.c
index 9bba75b..f099789 100644
--- a/src/backend/commands/tablespace.c
+++ b/src/backend/commands/tablespace.c
@@ -61,6 +61,7 @@
#include "catalog/indexing.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_tablespace.h"
+#include "commands/alter.h"
#include "commands/comment.h"
#include "commands/seclabel.h"
#include "commands/tablespace.h"
@@ -828,8 +829,6 @@ RenameTableSpace(const char *oldname, const char *newname)
ScanKeyData entry[1];
HeapScanDesc scan;
HeapTuple tup;
- HeapTuple newtuple;
- Form_pg_tablespace newform;
/* Search pg_tablespace */
rel = heap_open(TableSpaceRelationId, RowExclusiveLock);
@@ -847,15 +846,9 @@ RenameTableSpace(const char *oldname, const char *newname)
oldname)));
tspId = HeapTupleGetOid(tup);
- newtuple = heap_copytuple(tup);
- newform = (Form_pg_tablespace) GETSTRUCT(newtuple);
heap_endscan(scan);
- /* Must be owner */
- if (!pg_tablespace_ownercheck(HeapTupleGetOid(newtuple), GetUserId()))
- aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_TABLESPACE, oldname);
-
/* Validate new name */
if (!allowSystemTableMods && IsReservedName(newname))
ereport(ERROR,
@@ -879,10 +872,7 @@ RenameTableSpace(const char *oldname, const char *newname)
heap_endscan(scan);
/* OK, update the entry */
- namestrcpy(&(newform->spcname), newname);
-
- simple_heap_update(rel, &newtuple->t_self, newtuple);
- CatalogUpdateIndexes(rel, newtuple);
+ AlterObjectRename_internal(rel, tspId, newname);
heap_close(rel, NoLock);
diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c
index aea9fd1..95377ac 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
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 76ef11e..f62cd3d 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -6776,7 +6776,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;
@@ -6804,7 +6804,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;
@@ -6842,7 +6842,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;
@@ -7015,7 +7015,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/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 49dadd1..5f2239f 100644
--- a/src/backend/storage/lmgr/lock.c
+++ b/src/backend/storage/lmgr/lock.c
@@ -1017,6 +1017,12 @@ LockAcquireExtended(const LOCKTAG *locktag,
/*
* Find or create LOCK and PROCLOCK objects as needed for a new lock
* request.
+ *
+ * Returns the PROCLOCK object, or NULL if we failed to create the objects
+ * for lack of shared memory.
+ *
+ * The appropriate partition lock must be held at entry, and will be
+ * held at exit.
*/
static PROCLOCK *
SetupLockInTable(LockMethod lockMethodTable, PGPROC *proc,
@@ -2414,6 +2420,8 @@ FastPathUnGrantRelationLock(Oid relid, LOCKMODE lockmode)
* FastPathTransferRelationLocks
* Transfer locks matching the given lock tag from per-backend fast-path
* arrays to the shared hash table.
+ *
+ * Returns true if successful, false if ran out of shared memory.
*/
static bool
FastPathTransferRelationLocks(LockMethod lockMethodTable, const LOCKTAG *locktag,
@@ -2529,6 +2537,7 @@ FastPathGetRelationLockEntry(LOCALLOCK *locallock)
locallock->hashcode, lockmode);
if (!proclock)
{
+ LWLockRelease(partitionLock);
ereport(ERROR,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of shared memory"),
@@ -3422,9 +3431,6 @@ GetRunningTransactionLocks(int *nlocks)
for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
LWLockAcquire(FirstLockMgrLock + i, LW_SHARED);
- /* Now scan the tables to copy the data */
- hash_seq_init(&seqstat, LockMethodProcLockHash);
-
/* Now we can safely count the number of proclocks */
els = hash_get_num_entries(LockMethodProcLockHash);
@@ -3434,6 +3440,9 @@ GetRunningTransactionLocks(int *nlocks)
*/
accessExclusiveLocks = palloc(els * sizeof(xl_standby_lock));
+ /* Now scan the tables to copy the data */
+ hash_seq_init(&seqstat, LockMethodProcLockHash);
+
/*
* If lock is a currently granted AccessExclusiveLock then it will have
* just one proclock holder, so locks are never accessed twice in this
@@ -3978,22 +3987,34 @@ VirtualXactLock(VirtualTransactionId vxid, bool wait)
/*
* OK, we're going to need to sleep on the VXID. But first, we must set
- * up the primary lock table entry, if needed.
+ * up the primary lock table entry, if needed (ie, convert the proc's
+ * fast-path lock on its VXID to a regular lock).
*/
if (proc->fpVXIDLock)
{
PROCLOCK *proclock;
uint32 hashcode;
+ LWLockId partitionLock;
hashcode = LockTagHashCode(&tag);
+
+ partitionLock = LockHashPartitionLock(hashcode);
+ LWLockAcquire(partitionLock, LW_EXCLUSIVE);
+
proclock = SetupLockInTable(LockMethods[DEFAULT_LOCKMETHOD], proc,
&tag, hashcode, ExclusiveLock);
if (!proclock)
+ {
+ LWLockRelease(partitionLock);
ereport(ERROR,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of shared memory"),
errhint("You might need to increase max_locks_per_transaction.")));
+ }
GrantLock(proclock->tag.myLock, proclock, ExclusiveLock);
+
+ LWLockRelease(partitionLock);
+
proc->fpVXIDLock = false;
}
diff --git a/src/include/commands/alter.h b/src/include/commands/alter.h
index 37e095e..cf93790 100644
--- a/src/include/commands/alter.h
+++ b/src/include/commands/alter.h
@@ -19,6 +19,8 @@
#include "utils/relcache.h"
extern Oid ExecRenameStmt(RenameStmt *stmt);
+extern void AlterObjectRename_internal(Relation rel, Oid objectId,
+ const char *new_name);
extern Oid ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt);
extern Oid AlterObjectNamespace_oid(Oid classId, Oid objid, Oid nspOid,
diff --git a/src/include/commands/conversioncmds.h b/src/include/commands/conversioncmds.h
index 3995628..75e42f5 100644
--- a/src/include/commands/conversioncmds.h
+++ b/src/include/commands/conversioncmds.h
@@ -18,6 +18,5 @@
#include "nodes/parsenodes.h"
extern Oid CreateConversionCommand(CreateConversionStmt *parsetree);
-extern Oid RenameConversion(List *name, const char *newname);
#endif /* CONVERSIONCMDS_H */
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index c327136..7a80f41 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -102,8 +102,6 @@ extern text *serialize_deflist(List *deflist);
extern List *deserialize_deflist(Datum txt);
/* commands/foreigncmds.c */
-extern Oid RenameForeignServer(const char *oldname, const char *newname);
-extern Oid RenameForeignDataWrapper(const char *oldname, const char *newname);
extern Oid AlterForeignServerOwner(const char *name, Oid newOwnerId);
extern void AlterForeignServerOwner_oid(Oid, Oid newOwnerId);
extern Oid AlterForeignDataWrapperOwner(const char *name, Oid newOwnerId);
diff --git a/src/include/commands/event_trigger.h b/src/include/commands/event_trigger.h
index 8b86b70..6d84b15 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 Oid AlterEventTrigger(AlterEventTrigStmt *stmt);
-extern Oid RenameEventTrigger(const char* trigname, const char *newname);
extern Oid 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 1f17ae4..f93b62c 100644
--- a/src/include/commands/proclang.h
+++ b/src/include/commands/proclang.h
@@ -16,7 +16,6 @@
extern Oid CreateProceduralLanguage(CreatePLangStmt *stmt);
extern void DropProceduralLanguageById(Oid langOid);
-extern Oid 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/test/regress/expected/alter_generic.out b/src/test/regress/expected/alter_generic.out
index 3beddd7..faed327 100644
--- a/src/test/regress/expected/alter_generic.out
+++ b/src/test/regress/expected/alter_generic.out
@@ -129,7 +129,7 @@ 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"
+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
@@ -346,7 +346,7 @@ 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"
+ERROR: text search dictionary "alt_ts_dict2" already exists
RESET SESSION AUTHORIZATION;
SELECT nspname, dictname, rolname
FROM pg_ts_dict t, pg_namespace n, pg_authid a
@@ -368,7 +368,7 @@ 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
+ERROR: text search parser "alt_ts_conf2" already exists
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"
@@ -387,7 +387,7 @@ 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"
+ERROR: text search parser "alt_ts_conf2" already exists
RESET SESSION AUTHORIZATION;
SELECT nspname, cfgname, rolname
FROM pg_ts_config t, pg_namespace n, pg_authid a
@@ -413,7 +413,7 @@ 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"
+ERROR: text search template "alt_ts_temp2" already exists
SELECT nspname, tmplname
FROM pg_ts_template t, pg_namespace n
WHERE t.tmplnamespace = n.oid AND nspname like 'alt_nsp%'
@@ -439,7 +439,7 @@ 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"
+ERROR: text search parser "alt_ts_prs2" already exists
SELECT nspname, prsname
FROM pg_ts_parser t, pg_namespace n
WHERE t.prsnamespace = n.oid AND nspname like 'alt_nsp%'
Kohei KaiGai escribió:
The attached patch is a rebased version towards the latest master
branch, and fix up the issue around error messages on name conflicts.
I assume the lock.c changes are just a bollixed merge, right?
I am not sure about some of the changes in the regression test expected
output; are we really okay with losing the "in schema foo" part in some
of these cases?
--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
2013/1/15 Alvaro Herrera <alvherre@2ndquadrant.com>:
Kohei KaiGai escribió:
The attached patch is a rebased version towards the latest master
branch, and fix up the issue around error messages on name conflicts.I assume the lock.c changes are just a bollixed merge, right?
Yes, I'll check it and rebase it.
I am not sure about some of the changes in the regression test expected
output; are we really okay with losing the "in schema foo" part in some
of these cases?
The changes in the expected results in regression test originated from
elimination of getObjectDescription, but "in schema foo" should be kept.
It looks like an obvious my mistake. Sorry.
Thanks,
--
KaiGai Kohei <kaigai@kaigai.gr.jp>
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
Kohei KaiGai escribió:
2013/1/15 Alvaro Herrera <alvherre@2ndquadrant.com>:
Kohei KaiGai escribió:
The attached patch is a rebased version towards the latest master
branch, and fix up the issue around error messages on name conflicts.I assume the lock.c changes are just a bollixed merge, right?
Yes, I'll check it and rebase it.
Wait for a bit before publishing a new version -- I'm going to push the
other patch so that you can merge on top.
Note that I'm going to commit a new function like this:
/*
* 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));
For this patch you will need to create a separate function which does
the conflicting-name report for objects that are not in a namespace.
Mixing both in-schema and schemaless objects in the same report function
seems messy to me.
--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
2013/1/15 Alvaro Herrera <alvherre@2ndquadrant.com>:
Kohei KaiGai escribió:
2013/1/15 Alvaro Herrera <alvherre@2ndquadrant.com>:
Kohei KaiGai escribió:
The attached patch is a rebased version towards the latest master
branch, and fix up the issue around error messages on name conflicts.I assume the lock.c changes are just a bollixed merge, right?
Yes, I'll check it and rebase it.
Wait for a bit before publishing a new version -- I'm going to push the
other patch so that you can merge on top.Note that I'm going to commit a new function like this:
/*
* 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));
For this patch you will need to create a separate function which does
the conflicting-name report for objects that are not in a namespace.
Mixing both in-schema and schemaless objects in the same report function
seems messy to me.
This attached patch is the rebased one towards the latest master branch.
I noticed that your proposed design also allows to unify ALTER code of
OPERATOR CLASS / FAMILY; that takes index access method for its
namespace in addition to name and namespace.
So, AlterObjectRename_internal and AlterObjectNamespace_internal have
four of special case handling to check name / namespace conflict.
The latest master lookups syscache within special case handing block
as follows:
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);
IsThereFunctionInNamespace(NameStr(proc->proname), proc->pronargs,
proc->proargtypes, nspOid);
heap_freetuple(tup);
}
But, we already pulls a relevant tuple from syscache on top of
AlterObjectNamespace_internal. So, I removed cache lookup code here.
Thanks,
--
KaiGai Kohei <kaigai@kaigai.gr.jp>
Attachments:
pgsql-v9.3-alter-reworks.3-rename.v9.patchapplication/octet-stream; name=pgsql-v9.3-alter-reworks.3-rename.v9.patchDownload
src/backend/commands/aggregatecmds.c | 64 +----
src/backend/commands/alter.c | 367 +++++++++++++++++++++-------
src/backend/commands/collationcmds.c | 48 ----
src/backend/commands/conversioncmds.c | 53 ----
src/backend/commands/event_trigger.c | 46 ----
src/backend/commands/foreigncmds.c | 87 -------
src/backend/commands/functioncmds.c | 63 +----
src/backend/commands/opclasscmds.c | 169 +++----------
src/backend/commands/proclang.c | 42 ----
src/backend/commands/tsearchcmds.c | 196 ---------------
src/backend/parser/gram.y | 12 +-
src/include/commands/collationcmds.h | 3 +-
src/include/commands/conversioncmds.h | 1 -
src/include/commands/defrem.h | 14 +-
src/include/commands/event_trigger.h | 1 -
src/include/commands/proclang.h | 1 -
src/test/regress/expected/alter_generic.out | 16 +-
src/test/regress/sql/alter_generic.sql | 6 +-
18 files changed, 336 insertions(+), 853 deletions(-)
diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c
index 1447683..d34a102 100644
--- a/src/backend/commands/aggregatecmds.c
+++ b/src/backend/commands/aggregatecmds.c
@@ -29,6 +29,7 @@
#include "catalog/pg_aggregate.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
+#include "commands/alter.h"
#include "commands/defrem.h"
#include "miscadmin.h"
#include "parser/parse_func.h"
@@ -226,66 +227,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 b565e9b..6f58027 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"
@@ -52,53 +59,242 @@
#include "utils/syscache.h"
#include "utils/tqual.h"
+/*
+ * Raise an error to the effect that an object of the given name is already
+ * present in the given namespace.
+ */
+static void
+report_name_conflict(Oid classId, const char *name)
+{
+ char *msgfmt;
-static Oid AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid);
+ switch (classId)
+ {
+ 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;
+ }
+
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg(msgfmt, name)));
+}
+
+static void
+report_namespace_conflict(Oid classId, const char *name, Oid nspOid)
+{
+ char *msgfmt;
+
+ if (!OidIsValid(nspOid))
+ report_name_conflict(classId, name);
+
+ 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;
+ }
+
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg(msgfmt, name, get_namespace_name(nspOid))));
+}
/*
- * Executes an ALTER OBJECT / RENAME TO statement. Based on the object
- * type, the function appropriate to that type is executed.
+ * 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).
+ * It checks name duplication only when catalog cache by name as key is
+ * available. Otherwise, the caller should ensure here is no object with
+ * identical name.
+ *
+ * rel: catalog relation containing object (RowExclusiveLock'd by caller)
+ * objectId: OID of object to be renamed
+ * new_name: CString representation of new name
*/
-Oid
-ExecRenameStmt(RenameStmt *stmt)
+static void
+AlterObjectRename_internal(Relation rel, Oid objectId, const char *new_name)
{
- switch (stmt->renameType)
+ 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;
+
+ oldtup = SearchSysCache1(oidCacheId, ObjectIdGetDatum(objectId));
+ if (!HeapTupleIsValid(oldtup))
+ elog(ERROR, "cache lookup failed for object %u of catalog \"%s\"",
+ objectId, RelationGetRelationName(rel));
+
+ datum = heap_getattr(oldtup, Anum_name,
+ RelationGetDescr(rel), &isnull);
+ Assert(!isnull);
+ old_name = NameStr(*(DatumGetName(datum)));
+
+ /* Get OID of namespace */
+ if (Anum_namespace > 0)
{
- case OBJECT_AGGREGATE:
- return RenameAggregate(stmt->object, stmt->objarg, stmt->newname);
+ datum = heap_getattr(oldtup, Anum_namespace,
+ RelationGetDescr(rel), &isnull);
+ Assert(!isnull);
+ namespaceId = DatumGetObjectId(datum);
+ }
+ else
+ namespaceId = InvalidOid;
- case OBJECT_COLLATION:
- return RenameCollation(stmt->object, 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 set schema of %s",
+ getObjectDescriptionOids(classId, objectId)))));
- case OBJECT_CONSTRAINT:
- return RenameConstraint(stmt);
+ /* Otherwise, must be owner of the existing object */
+ datum = heap_getattr(oldtup, Anum_owner,
+ RelationGetDescr(rel), &isnull);
+ Assert(!isnull);
+ ownerId = DatumGetObjectId(datum);
- case OBJECT_CONVERSION:
- return RenameConversion(stmt->object, stmt->newname);
+ if (!has_privs_of_role(GetUserId(), DatumGetObjectId(ownerId)))
+ aclcheck_error(ACLCHECK_NOT_OWNER, acl_kind, old_name);
- case OBJECT_DATABASE:
- return RenameDatabase(stmt->subname, stmt->newname);
+ /* 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));
+ }
+ }
- case OBJECT_FDW:
- return RenameForeignDataWrapper(stmt->subname, stmt->newname);
+ /*
+ * 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.
+ */
+ if (classId == ProcedureRelationId)
+ {
+ Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(oldtup);
- case OBJECT_FOREIGN_SERVER:
- return RenameForeignServer(stmt->subname, stmt->newname);
+ IsThereFunctionInNamespace(new_name, proc->pronargs,
+ proc->proargtypes, proc->pronamespace);
+ }
+ else if (classId == CollationRelationId)
+ {
+ Form_pg_collation coll = (Form_pg_collation) GETSTRUCT(oldtup);
- case OBJECT_EVENT_TRIGGER:
- return RenameEventTrigger(stmt->subname, stmt->newname);
+ IsThereCollationInNamespace(new_name, coll->collnamespace);
+ }
+ else if (classId == OperatorClassRelationId)
+ {
+ Form_pg_opclass opc = (Form_pg_opclass) GETSTRUCT(oldtup);
- case OBJECT_FUNCTION:
- return RenameFunction(stmt->object, stmt->objarg, stmt->newname);
+ IsThereOpClassInNamespace(new_name, opc->opcmethod,
+ opc->opcnamespace);
+ }
+ else if (classId == OperatorFamilyRelationId)
+ {
+ Form_pg_opfamily opf = (Form_pg_opfamily) GETSTRUCT(oldtup);
- case OBJECT_LANGUAGE:
- return RenameLanguage(stmt->subname, stmt->newname);
+ IsThereOpFamilyInNamespace(new_name, opf->opfmethod,
+ opf->opfnamespace);
+ }
+ if (nameCacheId >= 0 &&
+ SearchSysCacheExists2(nameCacheId,
+ CStringGetDatum(new_name),
+ ObjectIdGetDatum(namespaceId)))
+ report_namespace_conflict(classId, new_name, namespaceId);
- case OBJECT_OPCLASS:
- return RenameOpClass(stmt->object, stmt->subname, stmt->newname);
+ /* 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);
- case OBJECT_OPFAMILY:
- return RenameOpFamily(stmt->object, stmt->subname, stmt->newname);
+ /* 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);
+}
+
+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.
+ */
+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 +319,44 @@ 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);
+ catalog = heap_open(address.classId, RowExclusiveLock);
+
+ AlterObjectRename_internal(catalog,
+ address.objectId,
+ stmt->newname);
+ if (relation)
+ heap_close(relation, NoLock);
+ heap_close(catalog, RowExclusiveLock);
- case OBJECT_DOMAIN:
- case OBJECT_TYPE:
- return RenameType(stmt);
+ return address.objectId;
+ }
default:
elog(ERROR, "unrecognized rename stmt type: %d",
@@ -288,43 +507,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).
@@ -407,27 +589,30 @@ AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid)
*/
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 67200f8..8326cd0 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 35d4d08..84ab434 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 99b17a0..9063187 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 d3af8dc..7700e91 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 4f8e82a..bc56c03 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,14 +1618,14 @@ DropCastById(Oid castOid)
}
/*
- * Subroutine for ALTER FUNCTION/AGGREGATE SET SCHEMA
+ * Subroutine for ALTER FUNCTION/AGGREGATE SET SCHEMA/RENAME TO
*
* Is there a function with the given name and signature already in the given
* namespace? If so, raise an appropriate error message.
*/
void
IsThereFunctionInNamespace(const char *proname, int pronargs,
- oidvector proargtypes, Oid nspOid)
+ oidvector proargtypes, Oid nspOid)
{
/* check for duplicate name (more friendly than unique-index failure) */
if (SearchSysCacheExists3(PROCNAMEARGSNSP,
diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c
index 4b57e3d..4cd1511 100644
--- a/src/backend/commands/opclasscmds.c
+++ b/src/backend/commands/opclasscmds.c
@@ -1660,156 +1660,59 @@ 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 FAMILY/CLASS SET SCHEMA/RENAME TO
+ *
+ * Is there a operaor class/family 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
- */
-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 718b711..e6c6d4e 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 aea9fd1..95377ac 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
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 76ef11e..b19afa8 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -6776,7 +6776,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;
@@ -6804,7 +6804,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;
@@ -6814,7 +6814,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;
@@ -6824,7 +6824,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;
@@ -6842,7 +6842,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;
@@ -7015,7 +7015,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/include/commands/collationcmds.h b/src/include/commands/collationcmds.h
index 5aaa178..178f704 100644
--- a/src/include/commands/collationcmds.h
+++ b/src/include/commands/collationcmds.h
@@ -18,7 +18,6 @@
#include "nodes/parsenodes.h"
extern Oid DefineCollation(List *names, List *parameters);
-extern Oid RenameCollation(List *name, const char *newname);
-extern void IsThereCollationInNamespace(const char *collname, Oid newNspOid);
+extern void IsThereCollationInNamespace(const char *collname, Oid nspOid);
#endif /* COLLATIONCMDS_H */
diff --git a/src/include/commands/conversioncmds.h b/src/include/commands/conversioncmds.h
index 3995628..75e42f5 100644
--- a/src/include/commands/conversioncmds.h
+++ b/src/include/commands/conversioncmds.h
@@ -18,6 +18,5 @@
#include "nodes/parsenodes.h"
extern Oid CreateConversionCommand(CreateConversionStmt *parsetree);
-extern Oid RenameConversion(List *name, const char *newname);
#endif /* CONVERSIONCMDS_H */
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 7de6d5d..62515b2 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -46,7 +46,6 @@ extern Oid 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 Oid RenameFunction(List *name, List *argtypes, const char *newname);
extern Oid AlterFunction(AlterFunctionStmt *stmt);
extern Oid CreateCast(CreateCastStmt *stmt);
extern void DropCastById(Oid castOid);
@@ -62,7 +61,6 @@ extern void RemoveOperatorById(Oid operOid);
/* commands/aggregatecmds.c */
extern Oid DefineAggregate(List *name, List *args, bool oldstyle,
List *parameters);
-extern Oid RenameAggregate(List *name, List *args, const char *newname);
/* commands/opclasscmds.c */
extern Oid DefineOpClass(CreateOpClassStmt *stmt);
@@ -72,28 +70,26 @@ extern void RemoveOpClassById(Oid opclassOid);
extern void RemoveOpFamilyById(Oid opfamilyOid);
extern void RemoveAmOpEntryById(Oid entryOid);
extern void RemoveAmProcEntryById(Oid entryOid);
-extern Oid RenameOpClass(List *name, const char *access_method, const char *newname);
-extern Oid RenameOpFamily(List *name, const char *access_method, const char *newname);
+extern void IsThereOpClassInNamespace(const char *opcname, Oid opcmethod,
+ Oid opcnamespace);
+extern void IsThereOpFamilyInNamespace(const char *opfname, Oid opfmethod,
+ Oid opfnamespace);
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 Oid DefineTSParser(List *names, List *parameters);
-extern Oid RenameTSParser(List *oldname, const char *newname);
extern void RemoveTSParserById(Oid prsId);
extern Oid DefineTSDictionary(List *names, List *parameters);
-extern Oid RenameTSDictionary(List *oldname, const char *newname);
extern void RemoveTSDictionaryById(Oid dictId);
extern Oid AlterTSDictionary(AlterTSDictionaryStmt *stmt);
extern Oid DefineTSTemplate(List *names, List *parameters);
-extern Oid RenameTSTemplate(List *oldname, const char *newname);
extern void RemoveTSTemplateById(Oid tmplId);
extern Oid DefineTSConfiguration(List *names, List *parameters);
-extern Oid RenameTSConfiguration(List *oldname, const char *newname);
extern void RemoveTSConfigurationById(Oid cfgId);
extern Oid AlterTSConfiguration(AlterTSConfigurationStmt *stmt);
@@ -101,8 +97,6 @@ extern text *serialize_deflist(List *deflist);
extern List *deserialize_deflist(Datum txt);
/* commands/foreigncmds.c */
-extern Oid RenameForeignServer(const char *oldname, const char *newname);
-extern Oid RenameForeignDataWrapper(const char *oldname, const char *newname);
extern Oid AlterForeignServerOwner(const char *name, Oid newOwnerId);
extern void AlterForeignServerOwner_oid(Oid, Oid newOwnerId);
extern Oid AlterForeignDataWrapperOwner(const char *name, Oid newOwnerId);
diff --git a/src/include/commands/event_trigger.h b/src/include/commands/event_trigger.h
index 8b86b70..6d84b15 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 Oid AlterEventTrigger(AlterEventTrigStmt *stmt);
-extern Oid RenameEventTrigger(const char* trigname, const char *newname);
extern Oid 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 1f17ae4..f93b62c 100644
--- a/src/include/commands/proclang.h
+++ b/src/include/commands/proclang.h
@@ -16,7 +16,6 @@
extern Oid CreateProceduralLanguage(CreatePLangStmt *stmt);
extern void DropProceduralLanguageById(Oid langOid);
-extern Oid 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/test/regress/expected/alter_generic.out b/src/test/regress/expected/alter_generic.out
index f27d217..1d7e524 100644
--- a/src/test/regress/expected/alter_generic.out
+++ b/src/test/regress/expected/alter_generic.out
@@ -279,8 +279,8 @@ ALTER OPERATOR FAMILY alt_opf2 USING hash OWNER TO regtest_alter_user3; -- fail
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
--- can't test this: the error message includes the raw oid of namespace
--- ALTER OPERATOR FAMILY alt_opf2 USING hash SET SCHEMA alt_nsp2; -- failed (name conflict)
+ALTER OPERATOR FAMILY alt_opf2 USING hash SET SCHEMA alt_nsp2; -- failed (name conflict)
+ERROR: operator family "alt_opf2" for access method "hash" already exists in schema "alt_nsp2"
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
@@ -290,8 +290,8 @@ ALTER OPERATOR CLASS alt_opc2 USING hash OWNER TO regtest_alter_user3; -- faile
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
--- can't test this: the error message includes the raw oid of namespace
--- ALTER OPERATOR CLASS alt_opc2 USING hash SET SCHEMA alt_nsp2; -- failed (name conflict)
+ALTER OPERATOR CLASS alt_opc2 USING hash SET SCHEMA alt_nsp2; -- failed (name conflict)
+ERROR: operator class "alt_opc2" for access method "hash" already exists in schema "alt_nsp2"
RESET SESSION AUTHORIZATION;
SELECT nspname, opfname, amname, rolname
FROM pg_opfamily o, pg_am m, pg_namespace n, pg_authid a
@@ -327,7 +327,7 @@ 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
+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"
@@ -368,7 +368,7 @@ 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
+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"
@@ -408,7 +408,7 @@ SELECT nspname, cfgname, rolname
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
+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);
@@ -433,7 +433,7 @@ CREATE TEXT SEARCH PARSER alt_ts_prs1
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
+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
diff --git a/src/test/regress/sql/alter_generic.sql b/src/test/regress/sql/alter_generic.sql
index 6313ed9..04c5cc1 100644
--- a/src/test/regress/sql/alter_generic.sql
+++ b/src/test/regress/sql/alter_generic.sql
@@ -242,16 +242,14 @@ 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)
--- can't test this: the error message includes the raw oid of namespace
--- ALTER OPERATOR FAMILY alt_opf2 USING hash SET SCHEMA alt_nsp2; -- failed (name conflict)
+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)
--- can't test this: the error message includes the raw oid of namespace
--- ALTER OPERATOR CLASS alt_opc2 USING hash SET SCHEMA alt_nsp2; -- failed (name conflict)
+ALTER OPERATOR CLASS alt_opc2 USING hash SET SCHEMA alt_nsp2; -- failed (name conflict)
RESET SESSION AUTHORIZATION;
Kohei KaiGai escribió:
This attached patch is the rebased one towards the latest master branch.
Great, thanks. I played with it a bit and it looks almost done to me.
The only issue I can find is that it lets you rename an aggregate by
using ALTER FUNCTION, which is supposed to be forbidden. (Funnily
enough, renaming a non-agg function with ALTER AGGREGATE does raise an
error). Didn't immediately spot the right place to add a check.
I think these two error cases ought to have regression tests of their
own.
I attach a version with my changes.
I noticed that your proposed design also allows to unify ALTER code of
OPERATOR CLASS / FAMILY; that takes index access method for its
namespace in addition to name and namespace.
Yeah, I had noticed that and was planning on implementing it later.
Thanks for saving me the work.
So, AlterObjectRename_internal and AlterObjectNamespace_internal have
four of special case handling to check name / namespace conflict.
Right. (I wonder if it would make sense to encapsulate all those checks
in a single function for both to call.)
The latest master lookups syscache within special case handing block
as follows:
[code]But, we already pulls a relevant tuple from syscache on top of
AlterObjectNamespace_internal. So, I removed cache lookup code here.
Silly me. Thanks.
--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
Attachments:
2013/1/17 Alvaro Herrera <alvherre@2ndquadrant.com>:
Kohei KaiGai escribió:
This attached patch is the rebased one towards the latest master branch.
Great, thanks. I played with it a bit and it looks almost done to me.
The only issue I can find is that it lets you rename an aggregate by
using ALTER FUNCTION, which is supposed to be forbidden. (Funnily
enough, renaming a non-agg function with ALTER AGGREGATE does raise an
error). Didn't immediately spot the right place to add a check.I think these two error cases ought to have regression tests of their
own.I attach a version with my changes.
The patch itself looks to me good.
About ALTER FUNCTION towards aggregate function, why we should raise
an error strictly? Some code allows to modify properties of aggregate function
specified with FUNCTION qualifier.
postgres=# COMMENT ON FUNCTION max(int) IS 'maximum number of integer';
COMMENT
postgres=# COMMENT ON AGGREGATE in4eq(int,int) IS 'comparison of integers';
ERROR: aggregate in4eq(integer, integer) does not exist
I think using AGGREGATE towards regular function is wrong, but it is not
100% wrong to use FUNCTION towards aggregate "function".
In addition, aggregate function and regular function share same namespace,
so it never makes problem even if we allows to identify aggregate function
using ALTER FUNCTION.
How about your opinion? Thanks,
--
KaiGai Kohei <kaigai@kaigai.gr.jp>
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
Kohei KaiGai <kaigai@kaigai.gr.jp> writes:
About ALTER FUNCTION towards aggregate function, why we should raise
an error strictly?
I agree we probably shouldn't --- traditionally we have allowed that,
AFAIR, so changing it would break existing applications for little
benefit.
Similarly, you should not be throwing error when ALTER TABLE is applied
to a view, sequence, etc, and the command would otherwise be sensible.
regards, tom lane
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
Tom Lane escribió:
Kohei KaiGai <kaigai@kaigai.gr.jp> writes:
About ALTER FUNCTION towards aggregate function, why we should raise
an error strictly?I agree we probably shouldn't --- traditionally we have allowed that,
AFAIR, so changing it would break existing applications for little
benefit.
Okay, I have pushed the version I posted last week.
Similarly, you should not be throwing error when ALTER TABLE is applied
to a view, sequence, etc, and the command would otherwise be sensible.
As far as ALTER some-obj RENAME goes, this is already working, so I
haven't changed anything.
Thanks,
--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
Alvaro Herrera <alvherre@2ndquadrant.com> writes:
[ pgsql-v9.3-alter-reworks.3-rename.v10.patch.gz ]
Say ... I hadn't been paying too close attention to this patch, but
is there any particularly principled reason for it having unified
only 14 of the 29 object types handled by ExecRenameStmt()?
If so, how to tell which object types are supposed to be covered?
The reason I'm asking is that it's very unclear to me whether
https://commitfest.postgresql.org/action/patch_view?id=1043
(ALTER RENAME RULE) is okay in more-or-less its current form,
or whether it ought to be bounced back to be reworked for integration
in this framework.
regards, tom lane
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
2013/2/3 Tom Lane <tgl@sss.pgh.pa.us>:
Alvaro Herrera <alvherre@2ndquadrant.com> writes:
[ pgsql-v9.3-alter-reworks.3-rename.v10.patch.gz ]
Say ... I hadn't been paying too close attention to this patch, but
is there any particularly principled reason for it having unified
only 14 of the 29 object types handled by ExecRenameStmt()?
If so, how to tell which object types are supposed to be covered?The reason I'm asking is that it's very unclear to me whether
https://commitfest.postgresql.org/action/patch_view?id=1043
(ALTER RENAME RULE) is okay in more-or-less its current form,
or whether it ought to be bounced back to be reworked for integration
in this framework.
Like trigger or constraint, rule is unavailable to integrate the generic
rename logic using AlterObjectRename_internal().
So, I don't think this patch needs to take much design change.
Thanks,
--
KaiGai Kohei <kaigai@kaigai.gr.jp>
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
Kohei KaiGai escribió:
2013/2/3 Tom Lane <tgl@sss.pgh.pa.us>:
Alvaro Herrera <alvherre@2ndquadrant.com> writes:
[ pgsql-v9.3-alter-reworks.3-rename.v10.patch.gz ]
Say ... I hadn't been paying too close attention to this patch, but
is there any particularly principled reason for it having unified
only 14 of the 29 object types handled by ExecRenameStmt()?
If so, how to tell which object types are supposed to be covered?The reason I'm asking is that it's very unclear to me whether
https://commitfest.postgresql.org/action/patch_view?id=1043
(ALTER RENAME RULE) is okay in more-or-less its current form,
or whether it ought to be bounced back to be reworked for integration
in this framework.Like trigger or constraint, rule is unavailable to integrate the generic
rename logic using AlterObjectRename_internal().
So, I don't think this patch needs to take much design change.
I did give that patch a glance last week, asked myself the same question
as Tom, and gave myself the same answer as KaiGai. Sorry I didn't post
that.
--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers