/* *AlterObjectRename_internal * *Genericfunctiontorenamethegivenobject,forsimplecases(won't *workfortables,norothercaseswhereweneedtodomorethanchange *thenamecolumnofasinglecatalogentry). * *rel:catalogrelationcontainingobject(RowExclusiveLock'dbycaller) *objectId:OIDofobjecttoberenamed *new_name:CStringrepresentationofnewname
*/ staticvoid
AlterObjectRename_internal(Relation rel, Oid objectId, constchar *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);
HeapTuple oldtup;
HeapTuple newtup;
Datum datum; bool isnull;
Oid namespaceId;
Oid ownerId; char *old_name;
AclResult aclresult;
Datum *values; bool *nulls; bool *replaces;
NameData nameattrdata;
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 rename %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, get_object_type(classId, objectId),
old_name);
/* User must have CREATE privilege on the namespace */ if (OidIsValid(namespaceId))
{
aclresult = object_aclcheck(NamespaceRelationId, namespaceId, GetUserId(),
ACL_CREATE); if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, OBJECT_SCHEMA,
get_namespace_name(namespaceId));
}
if (classId == SubscriptionRelationId)
{
Form_pg_subscription form;
/* must have CREATE privilege on database */
aclresult = object_aclcheck(DatabaseRelationId, MyDatabaseId,
GetUserId(), ACL_CREATE); if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, OBJECT_DATABASE,
get_database_name(MyDatabaseId));
/* *Don'tallownon-superusermodificationofasubscriptionwith *password_required=false.
*/
form = (Form_pg_subscription) GETSTRUCT(oldtup); if (!form->subpasswordrequired && !superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("password_required=false is superuser-only"),
errhint("Subscriptions with the password_required option set to false may only be created or modified by the superuser.")));
}
}
/* Also enforce regression testing naming rules, if enabled */ #ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS if (strncmp(new_name, "regress_", 8) != 0)
elog(WARNING, "subscriptions created by regression test cases should have names starting with \"regress_\""); #endif
/* Wake up related replication workers to handle this change quickly */
LogicalRepWorkersWakeupAtCommit(objectId);
} elseif (nameCacheId >= 0)
{ if (OidIsValid(namespaceId))
{ if (SearchSysCacheExists2(nameCacheId,
CStringGetDatum(new_name),
ObjectIdGetDatum(namespaceId)))
report_namespace_conflict(classId, new_name, namespaceId);
} else
{ if (SearchSysCacheExists1(nameCacheId,
CStringGetDatum(new_name)))
report_name_conflict(classId, new_name);
}
}
/* *ExecutesanALTEROBJECT/RENAMETOstatement.Basedontheobject *type,thefunctionappropriatetothattypeisexecuted. * *Returnvalueistheaddressoftherenamedobject.
*/
ObjectAddress
ExecRenameStmt(RenameStmt *stmt)
{ switch (stmt->renameType)
{ case OBJECT_TABCONSTRAINT: case OBJECT_DOMCONSTRAINT: return RenameConstraint(stmt);
case OBJECT_DATABASE: return RenameDatabase(stmt->subname, stmt->newname);
case OBJECT_ROLE: return RenameRole(stmt->subname, stmt->newname);
case OBJECT_SCHEMA: return RenameSchema(stmt->subname, stmt->newname);
case OBJECT_TABLESPACE: return RenameTableSpace(stmt->subname, stmt->newname);
case OBJECT_TABLE: case OBJECT_SEQUENCE: case OBJECT_VIEW: case OBJECT_MATVIEW: case OBJECT_INDEX: case OBJECT_FOREIGN_TABLE: return RenameRelation(stmt);
case OBJECT_COLUMN: case OBJECT_ATTRIBUTE: return renameatt(stmt);
case OBJECT_RULE: return RenameRewriteRule(stmt->relation, stmt->subname,
stmt->newname);
case OBJECT_TRIGGER: return renametrig(stmt);
case OBJECT_POLICY: return rename_policy(stmt);
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_PROCEDURE: case OBJECT_ROUTINE: case OBJECT_STATISTIC_EXT: case OBJECT_TSCONFIGURATION: case OBJECT_TSDICTIONARY: case OBJECT_TSPARSER: case OBJECT_TSTEMPLATE: case OBJECT_PUBLICATION: case OBJECT_SUBSCRIPTION:
{
ObjectAddress address;
Relation catalog;
case OBJECT_FOREIGN_TABLE: case OBJECT_SEQUENCE: case OBJECT_TABLE: case OBJECT_VIEW: case OBJECT_MATVIEW:
address = AlterTableNamespace(stmt,
oldSchemaAddr ? &oldNspOid : NULL); break;
case OBJECT_DOMAIN: case OBJECT_TYPE:
address = AlterTypeNamespace(castNode(List, stmt->object), stmt->newschema,
stmt->objectType,
oldSchemaAddr ? &oldNspOid : NULL); break;
/* generic code path */ case OBJECT_AGGREGATE: case OBJECT_COLLATION: case OBJECT_CONVERSION: case OBJECT_FUNCTION: case OBJECT_OPERATOR: case OBJECT_OPCLASS: case OBJECT_OPFAMILY: case OBJECT_PROCEDURE: case OBJECT_ROUTINE: case OBJECT_STATISTIC_EXT: case OBJECT_TSCONFIGURATION: case OBJECT_TSDICTIONARY: case OBJECT_TSPARSER: case OBJECT_TSTEMPLATE:
{
Relation catalog;
Oid classId;
Oid nspOid;
case TypeRelationId:
oldNspOid = AlterTypeNamespace_oid(objid, nspOid, true, objsMoved); break;
case ProcedureRelationId: case CollationRelationId: case ConversionRelationId: case OperatorRelationId: case OperatorClassRelationId: case OperatorFamilyRelationId: case StatisticExtRelationId: case TSParserRelationId: case TSDictionaryRelationId: case TSTemplateRelationId: case TSConfigRelationId:
{
Relation catalog;
default: /* ignore object types that don't have schema-qualified names */
Assert(get_object_attnum_namespace(classId) == InvalidAttrNumber);
}
return oldNspOid;
}
/* *Genericfunctiontochangethenamespaceofagivenobject,forsimple *cases(won'tworkfortables,norothercaseswhereweneedtodomore *thanchangethenamespacecolumnofasinglecatalogentry). * *rel:catalogrelationcontainingobject(RowExclusiveLock'dbycaller) *objid:OIDofobjecttochangethenamespaceof *nspOid:OIDofnewnamespace * *ReturnstheOIDoftheobject'spreviousnamespace.
*/ static 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);
Oid oldNspOid;
Datum name, namespace; bool isnull;
HeapTuple tup,
newtup;
Datum *values; bool *nulls; bool *replaces;
tup = SearchSysCacheCopy1(oidCacheId, ObjectIdGetDatum(objid)); if (!HeapTupleIsValid(tup)) /* should not happen */
elog(ERROR, "cache lookup failed for object %u of catalog \"%s\"",
objid, RelationGetRelationName(rel));
/* Check basic namespace related issues */
CheckSetNamespace(oldNspOid, nspOid);
/* Permission checks ... superusers can always do it */ if (!superuser())
{
Datum owner;
Oid ownerId;
AclResult aclresult;
/* 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, objid))));
/* Otherwise, must be owner of the existing object */
owner = heap_getattr(tup, Anum_owner, RelationGetDescr(rel), &isnull);
Assert(!isnull);
ownerId = DatumGetObjectId(owner);
if (!has_privs_of_role(GetUserId(), ownerId))
aclcheck_error(ACLCHECK_NOT_OWNER, get_object_type(classId, objid),
NameStr(*(DatumGetName(name))));
/* User must have CREATE privilege on new namespace */
aclresult = object_aclcheck(NamespaceRelationId, nspOid, GetUserId(), ACL_CREATE); if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, OBJECT_SCHEMA,
get_namespace_name(nspOid));
}
/* update dependency to point to the new schema */ if (changeDependencyFor(classId, objid,
NamespaceRelationId, oldNspOid, nspOid) != 1)
elog(ERROR, "could not change schema dependency for object %u",
objid);
switch (stmt->objectType)
{ case OBJECT_DATABASE: return AlterDatabaseOwner(strVal(stmt->object), newowner);
case OBJECT_SCHEMA: return AlterSchemaOwner(strVal(stmt->object), newowner);
case OBJECT_TYPE: case OBJECT_DOMAIN: /* same as TYPE */ return AlterTypeOwner(castNode(List, stmt->object), newowner, stmt->objectType); break;
case OBJECT_FDW: return AlterForeignDataWrapperOwner(strVal(stmt->object),
newowner);
case OBJECT_FOREIGN_SERVER: return AlterForeignServerOwner(strVal(stmt->object),
newowner);
case OBJECT_EVENT_TRIGGER: return AlterEventTriggerOwner(strVal(stmt->object),
newowner);
case OBJECT_PUBLICATION: return AlterPublicationOwner(strVal(stmt->object),
newowner);
case OBJECT_SUBSCRIPTION: return AlterSubscriptionOwner(strVal(stmt->object),
newowner);
/* 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_PROCEDURE: case OBJECT_ROUTINE: case OBJECT_STATISTIC_EXT: case OBJECT_TABLESPACE: case OBJECT_TSDICTIONARY: case OBJECT_TSCONFIGURATION:
{
ObjectAddress address;
/* *Genericfunctiontochangetheownershipofagivenobject,forsimple *cases(won'tworkfortables,norothercaseswhereweneedtodomorethan *changetheownershipcolumnofasinglecatalogentry). * *classId:OIDofcatalogcontainingobject *objectId:OIDofobjecttochangetheownershipof *new_ownerId:OIDofnewobjectowner * *Thiswillworkonlargeobjects,butwehavetobewareofthefactthat *classIdisn'ttheOIDofthecatalogtomodifyinthatcase.
*/ void
AlterObjectOwner_internal(Oid classId, Oid objectId, Oid new_ownerId)
{ /* For large objects, the catalog to modify is pg_largeobject_metadata */
Oid catalogId = (classId == LargeObjectRelationId) ? LargeObjectMetadataRelationId : classId;
AttrNumber Anum_oid = get_object_attnum_oid(catalogId);
AttrNumber Anum_owner = get_object_attnum_owner(catalogId);
AttrNumber Anum_namespace = get_object_attnum_namespace(catalogId);
AttrNumber Anum_acl = get_object_attnum_acl(catalogId);
AttrNumber Anum_name = get_object_attnum_name(catalogId);
Relation rel;
HeapTuple oldtup;
Datum datum; bool isnull;
Oid old_ownerId;
Oid namespaceId = InvalidOid;
rel = table_open(catalogId, RowExclusiveLock);
/* Search tuple and lock it. */
oldtup =
get_catalog_object_by_oid_extended(rel, Anum_oid, objectId, true); if (oldtup == NULL)
elog(ERROR, "cache lookup failed for object %u of catalog \"%s\"",
objectId, RelationGetRelationName(rel));
datum = heap_getattr(oldtup, Anum_owner,
RelationGetDescr(rel), &isnull);
Assert(!isnull);
old_ownerId = DatumGetObjectId(datum);
if (Anum_namespace != InvalidAttrNumber)
{
datum = heap_getattr(oldtup, Anum_namespace,
RelationGetDescr(rel), &isnull);
Assert(!isnull);
namespaceId = DatumGetObjectId(datum);
}
if (old_ownerId != new_ownerId)
{
AttrNumber nattrs;
HeapTuple newtup;
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(rel), &isnull);
Assert(!isnull);
objname = NameStr(*DatumGetName(datum));
} else
{
snprintf(namebuf, sizeof(namebuf), "%u", objectId);
objname = namebuf;
}
aclcheck_error(ACLCHECK_NOT_OWNER,
get_object_type(catalogId, objectId),
objname);
} /* Must be able to become new owner */
check_can_set_role(GetUserId(), new_ownerId);
/* New owner must have CREATE privilege on namespace */ if (OidIsValid(namespaceId))
{
AclResult aclresult;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.