00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "postgres.h"
00016
00017 #include "access/htup_details.h"
00018 #include "access/sysattr.h"
00019 #include "catalog/dependency.h"
00020 #include "catalog/indexing.h"
00021 #include "catalog/namespace.h"
00022 #include "catalog/objectaccess.h"
00023 #include "catalog/pg_collation.h"
00024 #include "catalog/pg_conversion.h"
00025 #include "catalog/pg_event_trigger.h"
00026 #include "catalog/pg_foreign_data_wrapper.h"
00027 #include "catalog/pg_foreign_server.h"
00028 #include "catalog/pg_language.h"
00029 #include "catalog/pg_largeobject.h"
00030 #include "catalog/pg_largeobject_metadata.h"
00031 #include "catalog/pg_namespace.h"
00032 #include "catalog/pg_opclass.h"
00033 #include "catalog/pg_opfamily.h"
00034 #include "catalog/pg_proc.h"
00035 #include "catalog/pg_ts_config.h"
00036 #include "catalog/pg_ts_dict.h"
00037 #include "catalog/pg_ts_parser.h"
00038 #include "catalog/pg_ts_template.h"
00039 #include "commands/alter.h"
00040 #include "commands/collationcmds.h"
00041 #include "commands/conversioncmds.h"
00042 #include "commands/dbcommands.h"
00043 #include "commands/defrem.h"
00044 #include "commands/event_trigger.h"
00045 #include "commands/extension.h"
00046 #include "commands/proclang.h"
00047 #include "commands/schemacmds.h"
00048 #include "commands/tablecmds.h"
00049 #include "commands/tablespace.h"
00050 #include "commands/trigger.h"
00051 #include "commands/typecmds.h"
00052 #include "commands/user.h"
00053 #include "parser/parse_func.h"
00054 #include "miscadmin.h"
00055 #include "rewrite/rewriteDefine.h"
00056 #include "tcop/utility.h"
00057 #include "utils/builtins.h"
00058 #include "utils/fmgroids.h"
00059 #include "utils/lsyscache.h"
00060 #include "utils/rel.h"
00061 #include "utils/syscache.h"
00062 #include "utils/tqual.h"
00063
00064
00065 static Oid AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid);
00066
00067
00068
00069
00070
00071 static void
00072 report_name_conflict(Oid classId, const char *name)
00073 {
00074 char *msgfmt;
00075
00076 switch (classId)
00077 {
00078 case EventTriggerRelationId:
00079 msgfmt = gettext_noop("event trigger \"%s\" already exists");
00080 break;
00081 case ForeignDataWrapperRelationId:
00082 msgfmt = gettext_noop("foreign-data wrapper \"%s\" already exists");
00083 break;
00084 case ForeignServerRelationId:
00085 msgfmt = gettext_noop("server \"%s\" already exists");
00086 break;
00087 case LanguageRelationId:
00088 msgfmt = gettext_noop("language \"%s\" already exists");
00089 break;
00090 default:
00091 elog(ERROR, "unsupported object class %u", classId);
00092 break;
00093 }
00094
00095 ereport(ERROR,
00096 (errcode(ERRCODE_DUPLICATE_OBJECT),
00097 errmsg(msgfmt, name)));
00098 }
00099
00100 static void
00101 report_namespace_conflict(Oid classId, const char *name, Oid nspOid)
00102 {
00103 char *msgfmt;
00104
00105 Assert(OidIsValid(nspOid));
00106
00107 switch (classId)
00108 {
00109 case ConversionRelationId:
00110 Assert(OidIsValid(nspOid));
00111 msgfmt = gettext_noop("conversion \"%s\" already exists in schema \"%s\"");
00112 break;
00113 case TSParserRelationId:
00114 Assert(OidIsValid(nspOid));
00115 msgfmt = gettext_noop("text search parser \"%s\" already exists in schema \"%s\"");
00116 break;
00117 case TSDictionaryRelationId:
00118 Assert(OidIsValid(nspOid));
00119 msgfmt = gettext_noop("text search dictionary \"%s\" already exists in schema \"%s\"");
00120 break;
00121 case TSTemplateRelationId:
00122 Assert(OidIsValid(nspOid));
00123 msgfmt = gettext_noop("text search template \"%s\" already exists in schema \"%s\"");
00124 break;
00125 case TSConfigRelationId:
00126 Assert(OidIsValid(nspOid));
00127 msgfmt = gettext_noop("text search configuration \"%s\" already exists in schema \"%s\"");
00128 break;
00129 default:
00130 elog(ERROR, "unsupported object class %u", classId);
00131 break;
00132 }
00133
00134 ereport(ERROR,
00135 (errcode(ERRCODE_DUPLICATE_OBJECT),
00136 errmsg(msgfmt, name, get_namespace_name(nspOid))));
00137 }
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 static void
00151 AlterObjectRename_internal(Relation rel, Oid objectId, const char *new_name)
00152 {
00153 Oid classId = RelationGetRelid(rel);
00154 int oidCacheId = get_object_catcache_oid(classId);
00155 int nameCacheId = get_object_catcache_name(classId);
00156 AttrNumber Anum_name = get_object_attnum_name(classId);
00157 AttrNumber Anum_namespace = get_object_attnum_namespace(classId);
00158 AttrNumber Anum_owner = get_object_attnum_owner(classId);
00159 AclObjectKind acl_kind = get_object_aclkind(classId);
00160 HeapTuple oldtup;
00161 HeapTuple newtup;
00162 Datum datum;
00163 bool isnull;
00164 Oid namespaceId;
00165 Oid ownerId;
00166 char *old_name;
00167 AclResult aclresult;
00168 Datum *values;
00169 bool *nulls;
00170 bool *replaces;
00171
00172 oldtup = SearchSysCache1(oidCacheId, ObjectIdGetDatum(objectId));
00173 if (!HeapTupleIsValid(oldtup))
00174 elog(ERROR, "cache lookup failed for object %u of catalog \"%s\"",
00175 objectId, RelationGetRelationName(rel));
00176
00177 datum = heap_getattr(oldtup, Anum_name,
00178 RelationGetDescr(rel), &isnull);
00179 Assert(!isnull);
00180 old_name = NameStr(*(DatumGetName(datum)));
00181
00182
00183 if (Anum_namespace > 0)
00184 {
00185 datum = heap_getattr(oldtup, Anum_namespace,
00186 RelationGetDescr(rel), &isnull);
00187 Assert(!isnull);
00188 namespaceId = DatumGetObjectId(datum);
00189 }
00190 else
00191 namespaceId = InvalidOid;
00192
00193
00194 if (!superuser())
00195 {
00196
00197 if (Anum_owner <= 0)
00198 ereport(ERROR,
00199 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
00200 (errmsg("must be superuser to rename %s",
00201 getObjectDescriptionOids(classId, objectId)))));
00202
00203
00204 datum = heap_getattr(oldtup, Anum_owner,
00205 RelationGetDescr(rel), &isnull);
00206 Assert(!isnull);
00207 ownerId = DatumGetObjectId(datum);
00208
00209 if (!has_privs_of_role(GetUserId(), DatumGetObjectId(ownerId)))
00210 aclcheck_error(ACLCHECK_NOT_OWNER, acl_kind, old_name);
00211
00212
00213 if (OidIsValid(namespaceId))
00214 {
00215 aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(),
00216 ACL_CREATE);
00217 if (aclresult != ACLCHECK_OK)
00218 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
00219 get_namespace_name(namespaceId));
00220 }
00221 }
00222
00223
00224
00225
00226
00227
00228 if (classId == ProcedureRelationId)
00229 {
00230 Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(oldtup);
00231
00232 IsThereFunctionInNamespace(new_name, proc->pronargs,
00233 proc->proargtypes, proc->pronamespace);
00234 }
00235 else if (classId == CollationRelationId)
00236 {
00237 Form_pg_collation coll = (Form_pg_collation) GETSTRUCT(oldtup);
00238
00239 IsThereCollationInNamespace(new_name, coll->collnamespace);
00240 }
00241 else if (classId == OperatorClassRelationId)
00242 {
00243 Form_pg_opclass opc = (Form_pg_opclass) GETSTRUCT(oldtup);
00244
00245 IsThereOpClassInNamespace(new_name, opc->opcmethod,
00246 opc->opcnamespace);
00247 }
00248 else if (classId == OperatorFamilyRelationId)
00249 {
00250 Form_pg_opfamily opf = (Form_pg_opfamily) GETSTRUCT(oldtup);
00251
00252 IsThereOpFamilyInNamespace(new_name, opf->opfmethod,
00253 opf->opfnamespace);
00254 }
00255 else if (nameCacheId >= 0)
00256 {
00257 if (OidIsValid(namespaceId))
00258 {
00259 if (SearchSysCacheExists2(nameCacheId,
00260 CStringGetDatum(new_name),
00261 ObjectIdGetDatum(namespaceId)))
00262 report_namespace_conflict(classId, new_name, namespaceId);
00263 }
00264 else
00265 {
00266 if (SearchSysCacheExists1(nameCacheId,
00267 CStringGetDatum(new_name)))
00268 report_name_conflict(classId, new_name);
00269 }
00270 }
00271
00272
00273 values = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(Datum));
00274 nulls = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(bool));
00275 replaces = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(bool));
00276 values[Anum_name - 1] = PointerGetDatum(new_name);
00277 replaces[Anum_name - 1] = true;
00278 newtup = heap_modify_tuple(oldtup, RelationGetDescr(rel),
00279 values, nulls, replaces);
00280
00281
00282 simple_heap_update(rel, &oldtup->t_self, newtup);
00283 CatalogUpdateIndexes(rel, newtup);
00284
00285 InvokeObjectPostAlterHook(classId, objectId, 0);
00286
00287
00288 pfree(values);
00289 pfree(nulls);
00290 pfree(replaces);
00291 heap_freetuple(newtup);
00292
00293 ReleaseSysCache(oldtup);
00294 }
00295
00296
00297
00298
00299
00300 Oid
00301 ExecRenameStmt(RenameStmt *stmt)
00302 {
00303 switch (stmt->renameType)
00304 {
00305 case OBJECT_CONSTRAINT:
00306 return RenameConstraint(stmt);
00307
00308 case OBJECT_DATABASE:
00309 return RenameDatabase(stmt->subname, stmt->newname);
00310
00311 case OBJECT_ROLE:
00312 return RenameRole(stmt->subname, stmt->newname);
00313
00314 case OBJECT_SCHEMA:
00315 return RenameSchema(stmt->subname, stmt->newname);
00316
00317 case OBJECT_TABLESPACE:
00318 return RenameTableSpace(stmt->subname, stmt->newname);
00319
00320 case OBJECT_TABLE:
00321 case OBJECT_SEQUENCE:
00322 case OBJECT_VIEW:
00323 case OBJECT_MATVIEW:
00324 case OBJECT_INDEX:
00325 case OBJECT_FOREIGN_TABLE:
00326 return RenameRelation(stmt);
00327
00328 case OBJECT_COLUMN:
00329 case OBJECT_ATTRIBUTE:
00330 return renameatt(stmt);
00331
00332 case OBJECT_RULE:
00333 return RenameRewriteRule(stmt->relation, stmt->subname,
00334 stmt->newname);
00335
00336 case OBJECT_TRIGGER:
00337 return renametrig(stmt);
00338
00339 case OBJECT_DOMAIN:
00340 case OBJECT_TYPE:
00341 return RenameType(stmt);
00342
00343 case OBJECT_AGGREGATE:
00344 case OBJECT_COLLATION:
00345 case OBJECT_CONVERSION:
00346 case OBJECT_EVENT_TRIGGER:
00347 case OBJECT_FDW:
00348 case OBJECT_FOREIGN_SERVER:
00349 case OBJECT_FUNCTION:
00350 case OBJECT_OPCLASS:
00351 case OBJECT_OPFAMILY:
00352 case OBJECT_LANGUAGE:
00353 case OBJECT_TSCONFIGURATION:
00354 case OBJECT_TSDICTIONARY:
00355 case OBJECT_TSPARSER:
00356 case OBJECT_TSTEMPLATE:
00357 {
00358 ObjectAddress address;
00359 Relation catalog;
00360 Relation relation;
00361
00362 address = get_object_address(stmt->renameType,
00363 stmt->object, stmt->objarg,
00364 &relation,
00365 AccessExclusiveLock, false);
00366 Assert(relation == NULL);
00367
00368 catalog = heap_open(address.classId, RowExclusiveLock);
00369 AlterObjectRename_internal(catalog,
00370 address.objectId,
00371 stmt->newname);
00372 heap_close(catalog, RowExclusiveLock);
00373
00374 return address.objectId;
00375 }
00376
00377 default:
00378 elog(ERROR, "unrecognized rename stmt type: %d",
00379 (int) stmt->renameType);
00380 return InvalidOid;
00381 }
00382 }
00383
00384
00385
00386
00387
00388 Oid
00389 ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt)
00390 {
00391 switch (stmt->objectType)
00392 {
00393 case OBJECT_EXTENSION:
00394 return AlterExtensionNamespace(stmt->object, stmt->newschema);
00395
00396 case OBJECT_FOREIGN_TABLE:
00397 case OBJECT_SEQUENCE:
00398 case OBJECT_TABLE:
00399 case OBJECT_VIEW:
00400 case OBJECT_MATVIEW:
00401 return AlterTableNamespace(stmt);
00402
00403 case OBJECT_DOMAIN:
00404 case OBJECT_TYPE:
00405 return AlterTypeNamespace(stmt->object, stmt->newschema,
00406 stmt->objectType);
00407
00408
00409 case OBJECT_AGGREGATE:
00410 case OBJECT_COLLATION:
00411 case OBJECT_CONVERSION:
00412 case OBJECT_FUNCTION:
00413 case OBJECT_OPERATOR:
00414 case OBJECT_OPCLASS:
00415 case OBJECT_OPFAMILY:
00416 case OBJECT_TSCONFIGURATION:
00417 case OBJECT_TSDICTIONARY:
00418 case OBJECT_TSPARSER:
00419 case OBJECT_TSTEMPLATE:
00420 {
00421 Relation catalog;
00422 Relation relation;
00423 Oid classId;
00424 Oid nspOid;
00425 ObjectAddress address;
00426
00427 address = get_object_address(stmt->objectType,
00428 stmt->object,
00429 stmt->objarg,
00430 &relation,
00431 AccessExclusiveLock,
00432 false);
00433 Assert(relation == NULL);
00434 classId = address.classId;
00435 catalog = heap_open(classId, RowExclusiveLock);
00436 nspOid = LookupCreationNamespace(stmt->newschema);
00437
00438 AlterObjectNamespace_internal(catalog, address.objectId,
00439 nspOid);
00440 heap_close(catalog, RowExclusiveLock);
00441
00442 return address.objectId;
00443 }
00444 break;
00445
00446 default:
00447 elog(ERROR, "unrecognized AlterObjectSchemaStmt type: %d",
00448 (int) stmt->objectType);
00449 return InvalidOid;
00450 }
00451 }
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467 Oid
00468 AlterObjectNamespace_oid(Oid classId, Oid objid, Oid nspOid,
00469 ObjectAddresses *objsMoved)
00470 {
00471 Oid oldNspOid = InvalidOid;
00472 ObjectAddress dep;
00473
00474 dep.classId = classId;
00475 dep.objectId = objid;
00476 dep.objectSubId = 0;
00477
00478 switch (getObjectClass(&dep))
00479 {
00480 case OCLASS_CLASS:
00481 {
00482 Relation rel;
00483
00484 rel = relation_open(objid, AccessExclusiveLock);
00485 oldNspOid = RelationGetNamespace(rel);
00486
00487 AlterTableNamespaceInternal(rel, oldNspOid, nspOid, objsMoved);
00488
00489 relation_close(rel, NoLock);
00490 break;
00491 }
00492
00493 case OCLASS_TYPE:
00494 oldNspOid = AlterTypeNamespace_oid(objid, nspOid, objsMoved);
00495 break;
00496
00497 case OCLASS_COLLATION:
00498 case OCLASS_CONVERSION:
00499 case OCLASS_OPERATOR:
00500 case OCLASS_OPCLASS:
00501 case OCLASS_OPFAMILY:
00502 case OCLASS_PROC:
00503 case OCLASS_TSPARSER:
00504 case OCLASS_TSDICT:
00505 case OCLASS_TSTEMPLATE:
00506 case OCLASS_TSCONFIG:
00507 {
00508 Relation catalog;
00509
00510 catalog = heap_open(classId, RowExclusiveLock);
00511
00512 oldNspOid = AlterObjectNamespace_internal(catalog, objid,
00513 nspOid);
00514
00515 heap_close(catalog, RowExclusiveLock);
00516 }
00517 break;
00518
00519 default:
00520 break;
00521 }
00522
00523 return oldNspOid;
00524 }
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537 static Oid
00538 AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid)
00539 {
00540 Oid classId = RelationGetRelid(rel);
00541 int oidCacheId = get_object_catcache_oid(classId);
00542 int nameCacheId = get_object_catcache_name(classId);
00543 AttrNumber Anum_name = get_object_attnum_name(classId);
00544 AttrNumber Anum_namespace = get_object_attnum_namespace(classId);
00545 AttrNumber Anum_owner = get_object_attnum_owner(classId);
00546 AclObjectKind acl_kind = get_object_aclkind(classId);
00547 Oid oldNspOid;
00548 Datum name,
00549 namespace;
00550 bool isnull;
00551 HeapTuple tup,
00552 newtup;
00553 Datum *values;
00554 bool *nulls;
00555 bool *replaces;
00556
00557 tup = SearchSysCacheCopy1(oidCacheId, ObjectIdGetDatum(objid));
00558 if (!HeapTupleIsValid(tup))
00559 elog(ERROR, "cache lookup failed for object %u of catalog \"%s\"",
00560 objid, RelationGetRelationName(rel));
00561
00562 name = heap_getattr(tup, Anum_name, RelationGetDescr(rel), &isnull);
00563 Assert(!isnull);
00564 namespace = heap_getattr(tup, Anum_namespace, RelationGetDescr(rel),
00565 &isnull);
00566 Assert(!isnull);
00567 oldNspOid = DatumGetObjectId(namespace);
00568
00569
00570 CheckSetNamespace(oldNspOid, nspOid, classId, objid);
00571
00572
00573 if (!superuser())
00574 {
00575 Datum owner;
00576 Oid ownerId;
00577 AclResult aclresult;
00578
00579
00580 if (Anum_owner <= 0)
00581 ereport(ERROR,
00582 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
00583 (errmsg("must be superuser to set schema of %s",
00584 getObjectDescriptionOids(classId, objid)))));
00585
00586
00587 owner = heap_getattr(tup, Anum_owner, RelationGetDescr(rel), &isnull);
00588 Assert(!isnull);
00589 ownerId = DatumGetObjectId(owner);
00590
00591 if (!has_privs_of_role(GetUserId(), ownerId))
00592 aclcheck_error(ACLCHECK_NOT_OWNER, acl_kind,
00593 NameStr(*(DatumGetName(name))));
00594
00595
00596 aclresult = pg_namespace_aclcheck(nspOid, GetUserId(), ACL_CREATE);
00597 if (aclresult != ACLCHECK_OK)
00598 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
00599 get_namespace_name(nspOid));
00600 }
00601
00602
00603
00604
00605
00606
00607 if (classId == ProcedureRelationId)
00608 {
00609 Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(tup);
00610
00611 IsThereFunctionInNamespace(NameStr(proc->proname), proc->pronargs,
00612 proc->proargtypes, nspOid);
00613 }
00614 else if (classId == CollationRelationId)
00615 {
00616 Form_pg_collation coll = (Form_pg_collation) GETSTRUCT(tup);
00617
00618 IsThereCollationInNamespace(NameStr(coll->collname), nspOid);
00619 }
00620 else if (classId == OperatorClassRelationId)
00621 {
00622 Form_pg_opclass opc = (Form_pg_opclass) GETSTRUCT(tup);
00623
00624 IsThereOpClassInNamespace(NameStr(opc->opcname),
00625 opc->opcmethod, nspOid);
00626 }
00627 else if (classId == OperatorFamilyRelationId)
00628 {
00629 Form_pg_opfamily opf = (Form_pg_opfamily) GETSTRUCT(tup);
00630
00631 IsThereOpFamilyInNamespace(NameStr(opf->opfname),
00632 opf->opfmethod, nspOid);
00633 }
00634 else if (nameCacheId >= 0 &&
00635 SearchSysCacheExists2(nameCacheId, name,
00636 ObjectIdGetDatum(nspOid)))
00637 report_namespace_conflict(classId,
00638 NameStr(*(DatumGetName(name))),
00639 nspOid);
00640
00641
00642 values = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(Datum));
00643 nulls = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(bool));
00644 replaces = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(bool));
00645 values[Anum_namespace - 1] = ObjectIdGetDatum(nspOid);
00646 replaces[Anum_namespace - 1] = true;
00647 newtup = heap_modify_tuple(tup, RelationGetDescr(rel),
00648 values, nulls, replaces);
00649
00650
00651 simple_heap_update(rel, &tup->t_self, newtup);
00652 CatalogUpdateIndexes(rel, newtup);
00653
00654
00655 pfree(values);
00656 pfree(nulls);
00657 pfree(replaces);
00658
00659
00660 changeDependencyFor(classId, objid,
00661 NamespaceRelationId, oldNspOid, nspOid);
00662
00663 InvokeObjectPostAlterHook(classId, objid, 0);
00664
00665 return oldNspOid;
00666 }
00667
00668
00669
00670
00671
00672 Oid
00673 ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
00674 {
00675 Oid newowner = get_role_oid(stmt->newowner, false);
00676
00677 switch (stmt->objectType)
00678 {
00679 case OBJECT_DATABASE:
00680 return AlterDatabaseOwner(strVal(linitial(stmt->object)), newowner);
00681
00682 case OBJECT_SCHEMA:
00683 return AlterSchemaOwner(strVal(linitial(stmt->object)), newowner);
00684
00685 case OBJECT_TYPE:
00686 case OBJECT_DOMAIN:
00687 return AlterTypeOwner(stmt->object, newowner, stmt->objectType);
00688 break;
00689
00690 case OBJECT_FDW:
00691 return AlterForeignDataWrapperOwner(strVal(linitial(stmt->object)),
00692 newowner);
00693
00694 case OBJECT_FOREIGN_SERVER:
00695 return AlterForeignServerOwner(strVal(linitial(stmt->object)),
00696 newowner);
00697
00698 case OBJECT_EVENT_TRIGGER:
00699 return AlterEventTriggerOwner(strVal(linitial(stmt->object)),
00700 newowner);
00701
00702
00703 case OBJECT_AGGREGATE:
00704 case OBJECT_COLLATION:
00705 case OBJECT_CONVERSION:
00706 case OBJECT_FUNCTION:
00707 case OBJECT_LANGUAGE:
00708 case OBJECT_LARGEOBJECT:
00709 case OBJECT_OPERATOR:
00710 case OBJECT_OPCLASS:
00711 case OBJECT_OPFAMILY:
00712 case OBJECT_TABLESPACE:
00713 case OBJECT_TSDICTIONARY:
00714 case OBJECT_TSCONFIGURATION:
00715 {
00716 Relation catalog;
00717 Relation relation;
00718 Oid classId;
00719 ObjectAddress address;
00720
00721 address = get_object_address(stmt->objectType,
00722 stmt->object,
00723 stmt->objarg,
00724 &relation,
00725 AccessExclusiveLock,
00726 false);
00727 Assert(relation == NULL);
00728 classId = address.classId;
00729
00730
00731
00732
00733
00734
00735 if (classId == LargeObjectRelationId)
00736 classId = LargeObjectMetadataRelationId;
00737
00738 catalog = heap_open(classId, RowExclusiveLock);
00739
00740 AlterObjectOwner_internal(catalog, address.objectId, newowner);
00741 heap_close(catalog, RowExclusiveLock);
00742
00743 return address.objectId;
00744 }
00745 break;
00746
00747 default:
00748 elog(ERROR, "unrecognized AlterOwnerStmt type: %d",
00749 (int) stmt->objectType);
00750
00751 return InvalidOid;
00752 }
00753 }
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764 void
00765 AlterObjectOwner_internal(Relation rel, Oid objectId, Oid new_ownerId)
00766 {
00767 Oid classId = RelationGetRelid(rel);
00768 AttrNumber Anum_owner = get_object_attnum_owner(classId);
00769 AttrNumber Anum_namespace = get_object_attnum_namespace(classId);
00770 AttrNumber Anum_acl = get_object_attnum_acl(classId);
00771 AttrNumber Anum_name = get_object_attnum_name(classId);
00772 HeapTuple oldtup;
00773 Datum datum;
00774 bool isnull;
00775 Oid old_ownerId;
00776 Oid namespaceId = InvalidOid;
00777
00778 oldtup = get_catalog_object_by_oid(rel, objectId);
00779 if (oldtup == NULL)
00780 elog(ERROR, "cache lookup failed for object %u of catalog \"%s\"",
00781 objectId, RelationGetRelationName(rel));
00782
00783 datum = heap_getattr(oldtup, Anum_owner,
00784 RelationGetDescr(rel), &isnull);
00785 Assert(!isnull);
00786 old_ownerId = DatumGetObjectId(datum);
00787
00788 if (Anum_namespace != InvalidAttrNumber)
00789 {
00790 datum = heap_getattr(oldtup, Anum_namespace,
00791 RelationGetDescr(rel), &isnull);
00792 Assert(!isnull);
00793 namespaceId = DatumGetObjectId(datum);
00794 }
00795
00796 if (old_ownerId != new_ownerId)
00797 {
00798 AttrNumber nattrs;
00799 HeapTuple newtup;
00800 Datum *values;
00801 bool *nulls;
00802 bool *replaces;
00803
00804
00805 if (!superuser())
00806 {
00807 AclObjectKind aclkind = get_object_aclkind(classId);
00808
00809
00810 if (!has_privs_of_role(GetUserId(), old_ownerId))
00811 {
00812 char *objname;
00813 char namebuf[NAMEDATALEN];
00814
00815 if (Anum_name != InvalidAttrNumber)
00816 {
00817 datum = heap_getattr(oldtup, Anum_name,
00818 RelationGetDescr(rel), &isnull);
00819 Assert(!isnull);
00820 objname = NameStr(*DatumGetName(datum));
00821 }
00822 else
00823 {
00824 snprintf(namebuf, sizeof(namebuf), "%u",
00825 HeapTupleGetOid(oldtup));
00826 objname = namebuf;
00827 }
00828 aclcheck_error(ACLCHECK_NOT_OWNER, aclkind, objname);
00829 }
00830
00831 check_is_member_of_role(GetUserId(), new_ownerId);
00832
00833
00834 if (OidIsValid(namespaceId))
00835 {
00836 AclResult aclresult;
00837
00838 aclresult = pg_namespace_aclcheck(namespaceId, new_ownerId,
00839 ACL_CREATE);
00840 if (aclresult != ACLCHECK_OK)
00841 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
00842 get_namespace_name(namespaceId));
00843 }
00844 }
00845
00846
00847 nattrs = RelationGetNumberOfAttributes(rel);
00848 values = palloc0(nattrs * sizeof(Datum));
00849 nulls = palloc0(nattrs * sizeof(bool));
00850 replaces = palloc0(nattrs * sizeof(bool));
00851 values[Anum_owner - 1] = ObjectIdGetDatum(new_ownerId);
00852 replaces[Anum_owner - 1] = true;
00853
00854
00855
00856
00857
00858 if (Anum_acl != InvalidAttrNumber)
00859 {
00860 datum = heap_getattr(oldtup,
00861 Anum_acl, RelationGetDescr(rel), &isnull);
00862 if (!isnull)
00863 {
00864 Acl *newAcl;
00865
00866 newAcl = aclnewowner(DatumGetAclP(datum),
00867 old_ownerId, new_ownerId);
00868 values[Anum_acl - 1] = PointerGetDatum(newAcl);
00869 replaces[Anum_acl - 1] = true;
00870 }
00871 }
00872
00873 newtup = heap_modify_tuple(oldtup, RelationGetDescr(rel),
00874 values, nulls, replaces);
00875
00876
00877 simple_heap_update(rel, &newtup->t_self, newtup);
00878 CatalogUpdateIndexes(rel, newtup);
00879
00880
00881 if (classId == LargeObjectMetadataRelationId)
00882 classId = LargeObjectRelationId;
00883 changeDependencyOnOwner(classId, HeapTupleGetOid(newtup), new_ownerId);
00884
00885
00886 pfree(values);
00887 pfree(nulls);
00888 pfree(replaces);
00889 }
00890
00891 InvokeObjectPostAlterHook(classId, objectId, 0);
00892 }