diff options
author | Stephen Frost | 2014-08-21 23:06:17 +0000 |
---|---|---|
committer | Stephen Frost | 2014-08-21 23:06:17 +0000 |
commit | 3c4cf080879b386d4ed1814667aca025caafe608 (patch) | |
tree | ec530d19313baddf3ff3ee8aa693c5f4f0326b32 /src/backend/commands/tablespace.c | |
parent | f57791985ac3d776cb67e9d69befde538cfdf13b (diff) |
Rework 'MOVE ALL' to 'ALTER .. ALL IN TABLESPACE'
As 'ALTER TABLESPACE .. MOVE ALL' really didn't change the tablespace
but instead changed objects inside tablespaces, it made sense to
rework the syntax and supporting functions to operate under the
'ALTER (TABLE|INDEX|MATERIALIZED VIEW)' syntax and to be in
tablecmds.c.
Pointed out by Alvaro, who also suggested the new syntax.
Back-patch to 9.4.
Diffstat (limited to 'src/backend/commands/tablespace.c')
-rw-r--r-- | src/backend/commands/tablespace.c | 179 |
1 files changed, 0 insertions, 179 deletions
diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c index 031be37a1e7..28e69a55510 100644 --- a/src/backend/commands/tablespace.c +++ b/src/backend/commands/tablespace.c @@ -67,7 +67,6 @@ #include "commands/seclabel.h" #include "commands/tablecmds.h" #include "commands/tablespace.h" -#include "commands/user.h" #include "miscadmin.h" #include "postmaster/bgwriter.h" #include "storage/fd.h" @@ -992,184 +991,6 @@ AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt) } /* - * Alter table space move - * - * Allows a user to move all of their objects in a given tablespace in the - * current database to another tablespace. Only objects which the user is - * considered to be an owner of are moved and the user must have CREATE rights - * on the new tablespace. These checks should mean that ALTER TABLE will never - * fail due to permissions, but note that permissions will also be checked at - * that level. Objects can be ALL, TABLES, INDEXES, or MATERIALIZED VIEWS. - * - * All to-be-moved objects are locked first. If NOWAIT is specified and the - * lock can't be acquired then we ereport(ERROR). - */ -Oid -AlterTableSpaceMove(AlterTableSpaceMoveStmt *stmt) -{ - List *relations = NIL; - ListCell *l; - ScanKeyData key[1]; - Relation rel; - HeapScanDesc scan; - HeapTuple tuple; - Oid orig_tablespaceoid; - Oid new_tablespaceoid; - List *role_oids = roleNamesToIds(stmt->roles); - - /* Ensure we were not asked to move something we can't */ - if (!stmt->move_all && stmt->objtype != OBJECT_TABLE && - stmt->objtype != OBJECT_INDEX && stmt->objtype != OBJECT_MATVIEW) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("only tables, indexes, and materialized views exist in tablespaces"))); - - /* Get the orig and new tablespace OIDs */ - orig_tablespaceoid = get_tablespace_oid(stmt->orig_tablespacename, false); - new_tablespaceoid = get_tablespace_oid(stmt->new_tablespacename, false); - - /* Can't move shared relations in to or out of pg_global */ - /* This is also checked by ATExecSetTableSpace, but nice to stop earlier */ - if (orig_tablespaceoid == GLOBALTABLESPACE_OID || - new_tablespaceoid == GLOBALTABLESPACE_OID) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("cannot move relations in to or out of pg_global tablespace"))); - - /* - * Must have CREATE rights on the new tablespace, unless it is the - * database default tablespace (which all users implicitly have CREATE - * rights on). - */ - if (OidIsValid(new_tablespaceoid) && new_tablespaceoid != MyDatabaseTableSpace) - { - AclResult aclresult; - - aclresult = pg_tablespace_aclcheck(new_tablespaceoid, GetUserId(), - ACL_CREATE); - if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_TABLESPACE, - get_tablespace_name(new_tablespaceoid)); - } - - /* - * Now that the checks are done, check if we should set either to - * InvalidOid because it is our database's default tablespace. - */ - if (orig_tablespaceoid == MyDatabaseTableSpace) - orig_tablespaceoid = InvalidOid; - - if (new_tablespaceoid == MyDatabaseTableSpace) - new_tablespaceoid = InvalidOid; - - /* no-op */ - if (orig_tablespaceoid == new_tablespaceoid) - return new_tablespaceoid; - - /* - * Walk the list of objects in the tablespace and move them. This will - * only find objects in our database, of course. - */ - ScanKeyInit(&key[0], - Anum_pg_class_reltablespace, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(orig_tablespaceoid)); - - rel = heap_open(RelationRelationId, AccessShareLock); - scan = heap_beginscan_catalog(rel, 1, key); - while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) - { - Oid relOid = HeapTupleGetOid(tuple); - Form_pg_class relForm; - - relForm = (Form_pg_class) GETSTRUCT(tuple); - - /* - * Do not move objects in pg_catalog as part of this, if an admin - * really wishes to do so, they can issue the individual ALTER - * commands directly. - * - * Also, explicitly avoid any shared tables, temp tables, or TOAST - * (TOAST will be moved with the main table). - */ - if (IsSystemNamespace(relForm->relnamespace) || relForm->relisshared || - isAnyTempNamespace(relForm->relnamespace) || - relForm->relnamespace == PG_TOAST_NAMESPACE) - continue; - - /* Only consider objects which live in tablespaces */ - if (relForm->relkind != RELKIND_RELATION && - relForm->relkind != RELKIND_INDEX && - relForm->relkind != RELKIND_MATVIEW) - continue; - - /* Check if we were asked to only move a certain type of object */ - if (!stmt->move_all && - ((stmt->objtype == OBJECT_TABLE && - relForm->relkind != RELKIND_RELATION) || - (stmt->objtype == OBJECT_INDEX && - relForm->relkind != RELKIND_INDEX) || - (stmt->objtype == OBJECT_MATVIEW && - relForm->relkind != RELKIND_MATVIEW))) - continue; - - /* Check if we are only moving objects owned by certain roles */ - if (role_oids != NIL && !list_member_oid(role_oids, relForm->relowner)) - continue; - - /* - * Handle permissions-checking here since we are locking the tables - * and also to avoid doing a bunch of work only to fail part-way. Note - * that permissions will also be checked by AlterTableInternal(). - * - * Caller must be considered an owner on the table to move it. - */ - if (!pg_class_ownercheck(relOid, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, - NameStr(relForm->relname)); - - if (stmt->nowait && - !ConditionalLockRelationOid(relOid, AccessExclusiveLock)) - ereport(ERROR, - (errcode(ERRCODE_OBJECT_IN_USE), - errmsg("aborting due to \"%s\".\"%s\" --- lock not available", - get_namespace_name(relForm->relnamespace), - NameStr(relForm->relname)))); - else - LockRelationOid(relOid, AccessExclusiveLock); - - /* Add to our list of objects to move */ - relations = lappend_oid(relations, relOid); - } - - heap_endscan(scan); - heap_close(rel, AccessShareLock); - - if (relations == NIL) - ereport(NOTICE, - (errcode(ERRCODE_NO_DATA_FOUND), - errmsg("no matching relations in tablespace \"%s\" found", - orig_tablespaceoid == InvalidOid ? "(database default)" : - get_tablespace_name(orig_tablespaceoid)))); - - /* Everything is locked, loop through and move all of the relations. */ - foreach(l, relations) - { - List *cmds = NIL; - AlterTableCmd *cmd = makeNode(AlterTableCmd); - - cmd->subtype = AT_SetTableSpace; - cmd->name = stmt->new_tablespacename; - - cmds = lappend(cmds, cmd); - - AlterTableInternal(lfirst_oid(l), cmds, false); - } - - return new_tablespaceoid; -} - -/* * Routines for handling the GUC variable 'default_tablespace'. */ |