1
/*-------------------------------------------------------------------------
4
* Drivers for generic alter commands
6
* Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
7
* Portions Copyright (c) 1994, Regents of the University of California
11
* src/backend/commands/alter.c
13
*-------------------------------------------------------------------------
17
#include "catalog/dependency.h"
18
#include "catalog/indexing.h"
19
#include "catalog/namespace.h"
20
#include "catalog/pg_largeobject.h"
21
#include "catalog/pg_namespace.h"
22
#include "commands/alter.h"
23
#include "commands/collationcmds.h"
24
#include "commands/conversioncmds.h"
25
#include "commands/dbcommands.h"
26
#include "commands/defrem.h"
27
#include "commands/extension.h"
28
#include "commands/proclang.h"
29
#include "commands/schemacmds.h"
30
#include "commands/tablecmds.h"
31
#include "commands/tablespace.h"
32
#include "commands/trigger.h"
33
#include "commands/typecmds.h"
34
#include "commands/user.h"
35
#include "miscadmin.h"
36
#include "parser/parse_clause.h"
37
#include "tcop/utility.h"
38
#include "utils/acl.h"
39
#include "utils/builtins.h"
40
#include "utils/lsyscache.h"
41
#include "utils/syscache.h"
45
* Executes an ALTER OBJECT / RENAME TO statement. Based on the object
46
* type, the function appropriate to that type is executed.
49
ExecRenameStmt(RenameStmt *stmt)
51
switch (stmt->renameType)
53
case OBJECT_AGGREGATE:
54
RenameAggregate(stmt->object, stmt->objarg, stmt->newname);
57
case OBJECT_COLLATION:
58
RenameCollation(stmt->object, stmt->newname);
61
case OBJECT_CONVERSION:
62
RenameConversion(stmt->object, stmt->newname);
66
RenameDatabase(stmt->subname, stmt->newname);
70
RenameFunction(stmt->object, stmt->objarg, stmt->newname);
74
RenameLanguage(stmt->subname, stmt->newname);
78
RenameOpClass(stmt->object, stmt->subname, stmt->newname);
82
RenameOpFamily(stmt->object, stmt->subname, stmt->newname);
86
RenameRole(stmt->subname, stmt->newname);
90
RenameSchema(stmt->subname, stmt->newname);
93
case OBJECT_TABLESPACE:
94
RenameTableSpace(stmt->subname, stmt->newname);
102
case OBJECT_ATTRIBUTE:
104
case OBJECT_FOREIGN_TABLE:
108
CheckRelationOwnership(stmt->relation, true);
110
relid = RangeVarGetRelid(stmt->relation, false);
112
switch (stmt->renameType)
115
case OBJECT_SEQUENCE:
118
case OBJECT_FOREIGN_TABLE:
121
* RENAME TABLE requires that we (still) hold
122
* CREATE rights on the containing namespace, as
123
* well as ownership of the table.
125
Oid namespaceId = get_rel_namespace(relid);
128
aclresult = pg_namespace_aclcheck(namespaceId,
131
if (aclresult != ACLCHECK_OK)
132
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
133
get_namespace_name(namespaceId));
135
RenameRelation(relid, stmt->newname, stmt->renameType);
139
case OBJECT_ATTRIBUTE:
140
renameatt(relid, stmt);
144
stmt->subname, /* old att name */
145
stmt->newname); /* new att name */
153
case OBJECT_TSPARSER:
154
RenameTSParser(stmt->object, stmt->newname);
157
case OBJECT_TSDICTIONARY:
158
RenameTSDictionary(stmt->object, stmt->newname);
161
case OBJECT_TSTEMPLATE:
162
RenameTSTemplate(stmt->object, stmt->newname);
165
case OBJECT_TSCONFIGURATION:
166
RenameTSConfiguration(stmt->object, stmt->newname);
170
RenameType(stmt->object, stmt->newname);
174
elog(ERROR, "unrecognized rename stmt type: %d",
175
(int) stmt->renameType);
180
* Executes an ALTER OBJECT / SET SCHEMA statement. Based on the object
181
* type, the function appropriate to that type is executed.
184
ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt)
186
switch (stmt->objectType)
188
case OBJECT_AGGREGATE:
189
AlterFunctionNamespace(stmt->object, stmt->objarg, true,
193
case OBJECT_COLLATION:
194
AlterCollationNamespace(stmt->object, stmt->newschema);
197
case OBJECT_CONVERSION:
198
AlterConversionNamespace(stmt->object, stmt->newschema);
201
case OBJECT_EXTENSION:
202
AlterExtensionNamespace(stmt->object, stmt->newschema);
205
case OBJECT_FUNCTION:
206
AlterFunctionNamespace(stmt->object, stmt->objarg, false,
210
case OBJECT_OPERATOR:
211
AlterOperatorNamespace(stmt->object, stmt->objarg, stmt->newschema);
215
AlterOpClassNamespace(stmt->object, stmt->addname, stmt->newschema);
218
case OBJECT_OPFAMILY:
219
AlterOpFamilyNamespace(stmt->object, stmt->addname, stmt->newschema);
222
case OBJECT_SEQUENCE:
225
case OBJECT_FOREIGN_TABLE:
226
CheckRelationOwnership(stmt->relation, true);
227
AlterTableNamespace(stmt->relation, stmt->newschema,
228
stmt->objectType, AccessExclusiveLock);
231
case OBJECT_TSPARSER:
232
AlterTSParserNamespace(stmt->object, stmt->newschema);
235
case OBJECT_TSDICTIONARY:
236
AlterTSDictionaryNamespace(stmt->object, stmt->newschema);
239
case OBJECT_TSTEMPLATE:
240
AlterTSTemplateNamespace(stmt->object, stmt->newschema);
243
case OBJECT_TSCONFIGURATION:
244
AlterTSConfigurationNamespace(stmt->object, stmt->newschema);
249
AlterTypeNamespace(stmt->object, stmt->newschema);
253
elog(ERROR, "unrecognized AlterObjectSchemaStmt type: %d",
254
(int) stmt->objectType);
259
* Change an object's namespace given its classOid and object Oid.
261
* Objects that don't have a namespace should be ignored.
263
* This function is currently used only by ALTER EXTENSION SET SCHEMA,
264
* so it only needs to cover object types that can be members of an
265
* extension, and it doesn't have to deal with certain special cases
266
* such as not wanting to process array types --- those should never
267
* be direct members of an extension anyway.
269
* Returns the OID of the object's previous namespace, or InvalidOid if
270
* object doesn't have a schema.
273
AlterObjectNamespace_oid(Oid classId, Oid objid, Oid nspOid)
275
Oid oldNspOid = InvalidOid;
278
dep.classId = classId;
279
dep.objectId = objid;
282
switch (getObjectClass(&dep))
289
rel = relation_open(objid, AccessExclusiveLock);
290
oldNspOid = RelationGetNamespace(rel);
292
classRel = heap_open(RelationRelationId, RowExclusiveLock);
294
AlterRelationNamespaceInternal(classRel,
300
heap_close(classRel, RowExclusiveLock);
302
relation_close(rel, NoLock);
307
oldNspOid = AlterFunctionNamespace_oid(objid, nspOid);
311
oldNspOid = AlterTypeNamespace_oid(objid, nspOid);
314
case OCLASS_COLLATION:
315
oldNspOid = AlterCollationNamespace_oid(objid, nspOid);
318
case OCLASS_CONVERSION:
319
oldNspOid = AlterConversionNamespace_oid(objid, nspOid);
322
case OCLASS_OPERATOR:
323
oldNspOid = AlterOperatorNamespace_oid(objid, nspOid);
327
oldNspOid = AlterOpClassNamespace_oid(objid, nspOid);
330
case OCLASS_OPFAMILY:
331
oldNspOid = AlterOpFamilyNamespace_oid(objid, nspOid);
334
case OCLASS_TSPARSER:
335
oldNspOid = AlterTSParserNamespace_oid(objid, nspOid);
339
oldNspOid = AlterTSDictionaryNamespace_oid(objid, nspOid);
342
case OCLASS_TSTEMPLATE:
343
oldNspOid = AlterTSTemplateNamespace_oid(objid, nspOid);
346
case OCLASS_TSCONFIG:
347
oldNspOid = AlterTSConfigurationNamespace_oid(objid, nspOid);
358
* Generic function to change the namespace of a given object, for simple
359
* cases (won't work for tables, nor other cases where we need to do more
360
* than change the namespace column of a single catalog entry).
362
* The AlterFooNamespace() calls just above will call a function whose job
363
* is to lookup the arguments for the generic function here.
365
* rel: catalog relation containing object (RowExclusiveLock'd by caller)
366
* oidCacheId: syscache that indexes this catalog by OID
367
* nameCacheId: syscache that indexes this catalog by name and namespace
368
* (pass -1 if there is none)
369
* objid: OID of object to change the namespace of
370
* nspOid: OID of new namespace
371
* Anum_name: column number of catalog's name column
372
* Anum_namespace: column number of catalog's namespace column
373
* Anum_owner: column number of catalog's owner column, or -1 if none
374
* acl_kind: ACL type for object, or -1 if none assigned
376
* If the object does not have an owner or permissions, pass -1 for
377
* Anum_owner and acl_kind. In this case the calling user must be superuser.
379
* Returns the OID of the object's previous namespace.
382
AlterObjectNamespace(Relation rel, int oidCacheId, int nameCacheId,
383
Oid objid, Oid nspOid,
384
int Anum_name, int Anum_namespace, int Anum_owner,
385
AclObjectKind acl_kind)
387
Oid classId = RelationGetRelid(rel);
398
tup = SearchSysCacheCopy1(oidCacheId, ObjectIdGetDatum(objid));
399
if (!HeapTupleIsValid(tup)) /* should not happen */
400
elog(ERROR, "cache lookup failed for object %u of catalog \"%s\"",
401
objid, RelationGetRelationName(rel));
403
name = heap_getattr(tup, Anum_name, RelationGetDescr(rel), &isnull);
405
namespace = heap_getattr(tup, Anum_namespace, RelationGetDescr(rel), &isnull);
407
oldNspOid = DatumGetObjectId(namespace);
409
/* Check basic namespace related issues */
410
CheckSetNamespace(oldNspOid, nspOid, classId, objid);
412
/* Permission checks ... superusers can always do it */
419
/* Fail if object does not have an explicit owner */
422
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
423
(errmsg("must be superuser to SET SCHEMA of %s",
424
getObjectDescriptionOids(classId, objid)))));
426
/* Otherwise, must be owner of the existing object */
427
owner = heap_getattr(tup, Anum_owner, RelationGetDescr(rel), &isnull);
429
ownerId = DatumGetObjectId(owner);
431
if (!has_privs_of_role(GetUserId(), ownerId))
432
aclcheck_error(ACLCHECK_NOT_OWNER, acl_kind,
433
NameStr(*(DatumGetName(name))));
435
/* User must have CREATE privilege on new namespace */
436
aclresult = pg_namespace_aclcheck(nspOid, GetUserId(), ACL_CREATE);
437
if (aclresult != ACLCHECK_OK)
438
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
439
get_namespace_name(nspOid));
443
* Check for duplicate name (more friendly than unique-index failure).
444
* Since this is just a friendliness check, we can just skip it in cases
445
* where there isn't a suitable syscache available.
447
if (nameCacheId >= 0 &&
448
SearchSysCacheExists2(nameCacheId, name, ObjectIdGetDatum(nspOid)))
450
(errcode(ERRCODE_DUPLICATE_OBJECT),
451
errmsg("%s already exists in schema \"%s\"",
452
getObjectDescriptionOids(classId, objid),
453
get_namespace_name(nspOid))));
455
/* Build modified tuple */
456
values = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(Datum));
457
nulls = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(bool));
458
replaces = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(bool));
459
values[Anum_namespace - 1] = ObjectIdGetDatum(nspOid);
460
replaces[Anum_namespace - 1] = true;
461
newtup = heap_modify_tuple(tup, RelationGetDescr(rel),
462
values, nulls, replaces);
464
/* Perform actual update */
465
simple_heap_update(rel, &tup->t_self, newtup);
466
CatalogUpdateIndexes(rel, newtup);
473
/* update dependencies to point to the new schema */
474
changeDependencyFor(classId, objid,
475
NamespaceRelationId, oldNspOid, nspOid);
482
* Executes an ALTER OBJECT / OWNER TO statement. Based on the object
483
* type, the function appropriate to that type is executed.
486
ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
488
Oid newowner = get_role_oid(stmt->newowner, false);
490
switch (stmt->objectType)
492
case OBJECT_AGGREGATE:
493
AlterAggregateOwner(stmt->object, stmt->objarg, newowner);
496
case OBJECT_COLLATION:
497
AlterCollationOwner(stmt->object, newowner);
500
case OBJECT_CONVERSION:
501
AlterConversionOwner(stmt->object, newowner);
504
case OBJECT_DATABASE:
505
AlterDatabaseOwner(strVal(linitial(stmt->object)), newowner);
508
case OBJECT_FUNCTION:
509
AlterFunctionOwner(stmt->object, stmt->objarg, newowner);
512
case OBJECT_LANGUAGE:
513
AlterLanguageOwner(strVal(linitial(stmt->object)), newowner);
516
case OBJECT_LARGEOBJECT:
517
LargeObjectAlterOwner(oidparse(linitial(stmt->object)), newowner);
520
case OBJECT_OPERATOR:
521
Assert(list_length(stmt->objarg) == 2);
522
AlterOperatorOwner(stmt->object,
523
(TypeName *) linitial(stmt->objarg),
524
(TypeName *) lsecond(stmt->objarg),
529
AlterOpClassOwner(stmt->object, stmt->addname, newowner);
532
case OBJECT_OPFAMILY:
533
AlterOpFamilyOwner(stmt->object, stmt->addname, newowner);
537
AlterSchemaOwner(strVal(linitial(stmt->object)), newowner);
540
case OBJECT_TABLESPACE:
541
AlterTableSpaceOwner(strVal(linitial(stmt->object)), newowner);
545
case OBJECT_DOMAIN: /* same as TYPE */
546
AlterTypeOwner(stmt->object, newowner);
549
case OBJECT_TSDICTIONARY:
550
AlterTSDictionaryOwner(stmt->object, newowner);
553
case OBJECT_TSCONFIGURATION:
554
AlterTSConfigurationOwner(stmt->object, newowner);
558
AlterForeignDataWrapperOwner(strVal(linitial(stmt->object)),
562
case OBJECT_FOREIGN_SERVER:
563
AlterForeignServerOwner(strVal(linitial(stmt->object)), newowner);
567
elog(ERROR, "unrecognized AlterOwnerStmt type: %d",
568
(int) stmt->objectType);