diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2011-02-09 11:55:32 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2011-02-09 11:56:37 -0500 |
commit | 5bc178b89f3ab93fb3845a941769c212f5eeaf1a (patch) | |
tree | 30f60f6497e97bf4c792bd581a3296aff5a6c5e5 /src/backend/commands/extension.c | |
parent | 70802e0dbef0af4bf73ce25489b8be6e40eca2be (diff) | |
download | postgresql-5bc178b89f3ab93fb3845a941769c212f5eeaf1a.tar.gz postgresql-5bc178b89f3ab93fb3845a941769c212f5eeaf1a.zip |
Implement "ALTER EXTENSION ADD object".
This is an essential component of making the extension feature usable;
first because it's needed in the process of converting an existing
installation containing "loose" objects of an old contrib module into
the extension-based world, and second because we'll have to use it
in pg_dump --binary-upgrade, as per recent discussion.
Loosely based on part of Dimitri Fontaine's ALTER EXTENSION UPGRADE
patch.
Diffstat (limited to 'src/backend/commands/extension.c')
-rw-r--r-- | src/backend/commands/extension.c | 59 |
1 files changed, 58 insertions, 1 deletions
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c index ee42d2e13df..41667fb3afc 100644 --- a/src/backend/commands/extension.c +++ b/src/backend/commands/extension.c @@ -1134,7 +1134,7 @@ pg_extension_config_dump(PG_FUNCTION_ARGS) if (getExtensionOfObject(RelationRelationId, tableoid) != CurrentExtensionObject) ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("table \"%s\" is not a member of the extension being created", tablename))); @@ -1392,3 +1392,60 @@ AlterExtensionNamespace(List *names, const char *newschema) changeDependencyFor(ExtensionRelationId, extensionOid, NamespaceRelationId, oldNspOid, nspOid); } + +/* + * Execute ALTER EXTENSION ADD + */ +void +ExecAlterExtensionAddStmt(AlterExtensionAddStmt *stmt) +{ + ObjectAddress extension; + ObjectAddress object; + Relation relation; + + /* + * For now, insist on superuser privilege. Later we might want to + * relax this to ownership of the target object and the extension. + */ + if (!superuser()) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + (errmsg("must be superuser to use ALTER EXTENSION")))); + + /* Do this next to fail on nonexistent extension */ + extension.classId = ExtensionRelationId; + extension.objectId = get_extension_oid(stmt->extname, false); + extension.objectSubId = 0; + + /* + * Translate the parser representation that identifies the object into + * an ObjectAddress. get_object_address() will throw an error if the + * object does not exist, and will also acquire a lock on the object + * to guard against concurrent DROP and ALTER EXTENSION ADD operations. + */ + object = get_object_address(stmt->objtype, stmt->objname, stmt->objargs, + &relation, ShareUpdateExclusiveLock); + + /* + * Complain if object is already attached to some extension. + */ + if (getExtensionOfObject(object.classId, object.objectId) != InvalidOid) + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("%s is already a member of an extension", + getObjectDescription(&object)))); + + /* + * OK, add the dependency. + */ + recordDependencyOn(&object, &extension, DEPENDENCY_EXTENSION); + + /* + * If get_object_address() opened the relation for us, we close it to keep + * the reference count correct - but we retain any locks acquired by + * get_object_address() until commit time, to guard against concurrent + * activity. + */ + if (relation != NULL) + relation_close(relation, NoLock); +} |