From d9b2bc45cf75f913490f1b3ce9b9263509b26704 Mon Sep 17 00:00:00 2001 From: Stephen Frost Date: Thu, 21 Aug 2014 19:06:17 -0400 Subject: [PATCH] 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. --- doc/src/sgml/ref/alter_index.sgml | 13 ++ doc/src/sgml/ref/alter_materialized_view.sgml | 2 + doc/src/sgml/ref/alter_table.sgml | 20 +- doc/src/sgml/ref/alter_tablespace.sgml | 78 -------- doc/src/sgml/release-9.4.sgml | 5 +- src/backend/commands/tablecmds.c | 171 +++++++++++++++++ src/backend/commands/tablespace.c | 179 ------------------ src/backend/nodes/copyfuncs.c | 11 +- src/backend/nodes/equalfuncs.c | 9 +- src/backend/parser/gram.y | 165 +++++++--------- src/backend/tcop/utility.c | 20 +- src/include/commands/tablecmds.h | 2 + src/include/commands/tablespace.h | 1 - src/include/nodes/nodes.h | 2 +- src/include/nodes/parsenodes.h | 7 +- src/test/regress/input/tablespace.source | 5 +- src/test/regress/output/tablespace.source | 5 +- src/tools/pgindent/typedefs.list | 2 +- 18 files changed, 305 insertions(+), 392 deletions(-) diff --git a/doc/src/sgml/ref/alter_index.sgml b/doc/src/sgml/ref/alter_index.sgml index 94a7af0429..ee3e3de4d6 100644 --- a/doc/src/sgml/ref/alter_index.sgml +++ b/doc/src/sgml/ref/alter_index.sgml @@ -25,6 +25,8 @@ ALTER INDEX [ IF EXISTS ] name RENA ALTER INDEX [ IF EXISTS ] name SET TABLESPACE tablespace_name ALTER INDEX [ IF EXISTS ] name SET ( storage_parameter = value [, ... ] ) ALTER INDEX [ IF EXISTS ] name RESET ( storage_parameter [, ... ] ) +ALTER INDEX ALL IN TABLESPACE name [ OWNED BY role_name [, ... ] ] + SET TABLESPACE new_tablespace [ NOWAIT ] @@ -63,6 +65,17 @@ ALTER INDEX [ IF EXISTS ] name RESE This form changes the index's tablespace to the specified tablespace and moves the data file(s) associated with the index to the new tablespace. + To change the tablespace of an index, you must own the index and have + CREATE privilege on the new tablespace. + All indexes in the current database in a tablespace can be moved by using + the ALL IN TABLESPACE form, which will lock all + indexes to be moved and then move each one. This form also supports + OWNED BY, which will only move indexes owned by the + roles specified. If the NOWAIT option is specified + then the command will fail if it is unable to acquire all of the locks + required immediately. Note that system catalogs will not be moved by + this command, use ALTER DATABASE or explicit + ALTER INDEX invocations instead if desired. See also . diff --git a/doc/src/sgml/ref/alter_materialized_view.sgml b/doc/src/sgml/ref/alter_materialized_view.sgml index 1932eeb84d..b0759fc5dc 100644 --- a/doc/src/sgml/ref/alter_materialized_view.sgml +++ b/doc/src/sgml/ref/alter_materialized_view.sgml @@ -29,6 +29,8 @@ ALTER MATERIALIZED VIEW [ IF EXISTS ] namenew_name ALTER MATERIALIZED VIEW [ IF EXISTS ] name SET SCHEMA new_schema +ALTER MATERIALIZED VIEW ALL IN TABLESPACE name [ OWNED BY role_name [, ... ] ] + SET TABLESPACE new_tablespace [ NOWAIT ] where action is one of: diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml index 69a1e14bce..0e7b99c934 100644 --- a/doc/src/sgml/ref/alter_table.sgml +++ b/doc/src/sgml/ref/alter_table.sgml @@ -31,6 +31,8 @@ ALTER TABLE [ IF EXISTS ] name RENAME TO new_name ALTER TABLE [ IF EXISTS ] name SET SCHEMA new_schema +ALTER TABLE ALL IN TABLESPACE name [ OWNED BY role_name [, ... ] ] + SET TABLESPACE new_tablespace [ NOWAIT ] where action is one of: @@ -597,6 +599,17 @@ ALTER TABLE [ IF EXISTS ] name moves the data file(s) associated with the table to the new tablespace. Indexes on the table, if any, are not moved; but they can be moved separately with additional SET TABLESPACE commands. + All tables in the current database in a tablespace can be moved by using + the ALL IN TABLESPACE form, which will lock all tables + to be moved first and then move each one. This form also supports + OWNED BY, which will only move tables owned by the + roles specified. If the NOWAIT option is specified + then the command will fail if it is unable to acquire all of the locks + required immediately. Note that system catalogs are not moved by this + command, use ALTER DATABASE or explicit + ALTER TABLE invocations instead if desired. The + information_schema relations are not considered part + of the system catalogs and will be moved. See also . @@ -649,7 +662,8 @@ ALTER TABLE [ IF EXISTS ] name - All the actions except RENAME and SET SCHEMA + All the actions except RENAME, + SET TABLESPACE and SET SCHEMA can be combined into a list of multiple alterations to apply in parallel. For example, it is possible to add several columns and/or alter the type of several @@ -659,8 +673,8 @@ ALTER TABLE [ IF EXISTS ] name You must own the table to use ALTER TABLE. - To change the schema of a table, you must also have - CREATE privilege on the new schema. + To change the schema or tablespace of a table, you must also have + CREATE privilege on the new schema or tablespace. To add the table as a new child of a parent table, you must own the parent table as well. To alter the owner, you must also be a direct or indirect member of the new diff --git a/doc/src/sgml/ref/alter_tablespace.sgml b/doc/src/sgml/ref/alter_tablespace.sgml index bd1afb4b72..7c4aabc582 100644 --- a/doc/src/sgml/ref/alter_tablespace.sgml +++ b/doc/src/sgml/ref/alter_tablespace.sgml @@ -25,7 +25,6 @@ ALTER TABLESPACE name RENAME TO new_name ALTER TABLESPACE name OWNER TO new_owner ALTER TABLESPACE name SET ( tablespace_option = value [, ... ] ) ALTER TABLESPACE name RESET ( tablespace_option [, ... ] ) -ALTER TABLESPACE name MOVE { ALL | TABLES | INDEXES | MATERIALIZED VIEWS } [ OWNED BY role_name [, ...] ] TO new_tablespace [ NOWAIT ] @@ -45,44 +44,6 @@ ALTER TABLESPACE name MOVE { ALL | TABLES | INDEXES | (Note that superusers have these privileges automatically.) - - ALTER TABLESPACE ... MOVE moves objects between - tablespaces. ALL will move all tables, indexes and - materialized views; specifying TABLES will move only - tables (but not their indexes), INDEXES will only move - indexes (including those underneath materialized views, but not tables), - and MATERIALIZED VIEWS will only move the table relation - of the materialized view (but no indexes associated with it). Users can - also specify a list of roles whose objects are to be moved, using - OWNED BY. - - - - Users must have CREATE rights on the new tablespace and - be considered an owner (either directly or indirectly) of all objects to be - moved. Note that the superuser is considered an owner of all objects, and - therefore an ALTER TABLESPACE ... MOVE ALL issued by the - superuser will move all objects in the current database that are in the - tablespace. (Attempting to move objects without the required rights will - result in an error. Non-superusers can use OWNED BY in - such cases, to restrict the set of objects moved to those with the required - rights.) - - - - All objects to be moved will be locked immediately by the command. If the - NOWAIT is specified, it will cause the command to fail - if it is unable to acquire the locks. - - - - System catalogs will not be moved by this command. To move a whole - database, use ALTER DATABASE, or call ALTER - TABLE on the individual system catalogs. Note that relations in - information_schema will be moved, just as any other - normal database objects, if the user is the superuser or considered an - owner of the relations in information_schema. - @@ -136,38 +97,6 @@ ALTER TABLESPACE name MOVE { ALL | TABLES | INDEXES | - - role_name - - - Role whose objects are to be moved. - - - - - - new_tablespace - - - The name of the tablespace to move objects into. The user must have - CREATE rights on the new tablespace to move objects into that - tablespace, unless the tablespace being moved into is the default - tablespace for the database connected to. - - - - - - NOWAIT - - - The NOWAIT option causes the ALTER TABLESPACE command to fail immediately - if it is unable to acquire the necessary lock on all of the objects being - moved. - - - - @@ -185,13 +114,6 @@ ALTER TABLESPACE index_space RENAME TO fast_raid; Change the owner of tablespace index_space: ALTER TABLESPACE index_space OWNER TO mary; - - - - Move all of the objects from the default tablespace to - the fast_raid tablespace: - -ALTER TABLESPACE pg_default MOVE ALL TO fast_raid; diff --git a/doc/src/sgml/release-9.4.sgml b/doc/src/sgml/release-9.4.sgml index e338554995..5233ed256a 100644 --- a/doc/src/sgml/release-9.4.sgml +++ b/doc/src/sgml/release-9.4.sgml @@ -1224,7 +1224,10 @@ Allow moving groups of objects from one tablespace to another - using ... MOVE + using ALL IN TABLESPACE ... SET TABLESPACE with + ALTER TABLE + ALTER INDEX and + ALTER MATERIALIZED VIEW (Stephen Frost) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 89bd31ab93..34c38de3ff 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -51,6 +51,7 @@ #include "commands/tablespace.h" #include "commands/trigger.h" #include "commands/typecmds.h" +#include "commands/user.h" #include "executor/executor.h" #include "foreign/foreign.h" #include "miscadmin.h" @@ -9204,6 +9205,176 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode) list_free(reltoastidxids); } +/* + * Alter Table ALL ... SET TABLESPACE + * + * Allows a user to move all objects of some type in a given tablespace in the + * current database to another tablespace. Objects can be chosen based on the + * owner of the object also, to allow users to move only their objects. + * The user must have CREATE rights on the new tablespace, as usual. The main + * permissions handling is done by the lower-level table move function. + * + * All to-be-moved objects are locked first. If NOWAIT is specified and the + * lock can't be acquired then we ereport(ERROR). + */ +Oid +AlterTableMoveAll(AlterTableMoveAllStmt *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->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 move the object type requested */ + if ((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; +} + /* * Copy data, block by block */ diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c index 031be37a1e..28e69a5551 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" @@ -991,184 +990,6 @@ AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt) return tablespaceoid; } -/* - * 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'. */ diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 43530aa24a..221d0fee6b 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -3402,14 +3402,13 @@ _copyAlterTableSpaceOptionsStmt(const AlterTableSpaceOptionsStmt *from) return newnode; } -static AlterTableSpaceMoveStmt * -_copyAlterTableSpaceMoveStmt(const AlterTableSpaceMoveStmt *from) +static AlterTableMoveAllStmt * +_copyAlterTableMoveAllStmt(const AlterTableMoveAllStmt *from) { - AlterTableSpaceMoveStmt *newnode = makeNode(AlterTableSpaceMoveStmt); + AlterTableMoveAllStmt *newnode = makeNode(AlterTableMoveAllStmt); COPY_STRING_FIELD(orig_tablespacename); COPY_SCALAR_FIELD(objtype); - COPY_SCALAR_FIELD(move_all); COPY_NODE_FIELD(roles); COPY_STRING_FIELD(new_tablespacename); COPY_SCALAR_FIELD(nowait); @@ -4428,8 +4427,8 @@ copyObject(const void *from) case T_AlterTableSpaceOptionsStmt: retval = _copyAlterTableSpaceOptionsStmt(from); break; - case T_AlterTableSpaceMoveStmt: - retval = _copyAlterTableSpaceMoveStmt(from); + case T_AlterTableMoveAllStmt: + retval = _copyAlterTableMoveAllStmt(from); break; case T_CreateExtensionStmt: retval = _copyCreateExtensionStmt(from); diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 2407cb73a3..7e53681e70 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -1638,12 +1638,11 @@ _equalAlterTableSpaceOptionsStmt(const AlterTableSpaceOptionsStmt *a, } static bool -_equalAlterTableSpaceMoveStmt(const AlterTableSpaceMoveStmt *a, - const AlterTableSpaceMoveStmt *b) +_equalAlterTableMoveAllStmt(const AlterTableMoveAllStmt *a, + const AlterTableMoveAllStmt *b) { COMPARE_STRING_FIELD(orig_tablespacename); COMPARE_SCALAR_FIELD(objtype); - COMPARE_SCALAR_FIELD(move_all); COMPARE_NODE_FIELD(roles); COMPARE_STRING_FIELD(new_tablespacename); COMPARE_SCALAR_FIELD(nowait); @@ -2896,8 +2895,8 @@ equal(const void *a, const void *b) case T_AlterTableSpaceOptionsStmt: retval = _equalAlterTableSpaceOptionsStmt(a, b); break; - case T_AlterTableSpaceMoveStmt: - retval = _equalAlterTableSpaceMoveStmt(a, b); + case T_AlterTableMoveAllStmt: + retval = _equalAlterTableMoveAllStmt(a, b); break; case T_CreateExtensionStmt: retval = _equalCreateExtensionStmt(a, b); diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 7b9895d61e..2e9bbe232f 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -1748,6 +1748,28 @@ AlterTableStmt: n->missing_ok = true; $$ = (Node *)n; } + | ALTER TABLE ALL IN_P TABLESPACE name SET TABLESPACE name opt_nowait + { + AlterTableMoveAllStmt *n = + makeNode(AlterTableMoveAllStmt); + n->orig_tablespacename = $6; + n->objtype = OBJECT_TABLE; + n->roles = NIL; + n->new_tablespacename = $9; + n->nowait = $10; + $$ = (Node *)n; + } + | ALTER TABLE ALL IN_P TABLESPACE name OWNED BY role_list SET TABLESPACE name opt_nowait + { + AlterTableMoveAllStmt *n = + makeNode(AlterTableMoveAllStmt); + n->orig_tablespacename = $6; + n->objtype = OBJECT_TABLE; + n->roles = $9; + n->new_tablespacename = $12; + n->nowait = $13; + $$ = (Node *)n; + } | ALTER INDEX qualified_name alter_table_cmds { AlterTableStmt *n = makeNode(AlterTableStmt); @@ -1766,6 +1788,28 @@ AlterTableStmt: n->missing_ok = true; $$ = (Node *)n; } + | ALTER INDEX ALL IN_P TABLESPACE name SET TABLESPACE name opt_nowait + { + AlterTableMoveAllStmt *n = + makeNode(AlterTableMoveAllStmt); + n->orig_tablespacename = $6; + n->objtype = OBJECT_INDEX; + n->roles = NIL; + n->new_tablespacename = $9; + n->nowait = $10; + $$ = (Node *)n; + } + | ALTER INDEX ALL IN_P TABLESPACE name OWNED BY role_list SET TABLESPACE name opt_nowait + { + AlterTableMoveAllStmt *n = + makeNode(AlterTableMoveAllStmt); + n->orig_tablespacename = $6; + n->objtype = OBJECT_INDEX; + n->roles = $9; + n->new_tablespacename = $12; + n->nowait = $13; + $$ = (Node *)n; + } | ALTER SEQUENCE qualified_name alter_table_cmds { AlterTableStmt *n = makeNode(AlterTableStmt); @@ -1820,6 +1864,28 @@ AlterTableStmt: n->missing_ok = true; $$ = (Node *)n; } + | ALTER MATERIALIZED VIEW ALL IN_P TABLESPACE name SET TABLESPACE name opt_nowait + { + AlterTableMoveAllStmt *n = + makeNode(AlterTableMoveAllStmt); + n->orig_tablespacename = $7; + n->objtype = OBJECT_MATVIEW; + n->roles = NIL; + n->new_tablespacename = $10; + n->nowait = $11; + $$ = (Node *)n; + } + | ALTER MATERIALIZED VIEW ALL IN_P TABLESPACE name OWNED BY role_list SET TABLESPACE name opt_nowait + { + AlterTableMoveAllStmt *n = + makeNode(AlterTableMoveAllStmt); + n->orig_tablespacename = $7; + n->objtype = OBJECT_MATVIEW; + n->roles = $10; + n->new_tablespacename = $13; + n->nowait = $14; + $$ = (Node *)n; + } ; alter_table_cmds: @@ -6941,103 +7007,8 @@ opt_force: FORCE { $$ = TRUE; } * *****************************************************************************/ -AlterTblSpcStmt: ALTER TABLESPACE name MOVE ALL TO name opt_nowait - { - AlterTableSpaceMoveStmt *n = - makeNode(AlterTableSpaceMoveStmt); - n->orig_tablespacename = $3; - n->objtype = -1; - n->move_all = true; - n->roles = NIL; - n->new_tablespacename = $7; - n->nowait = $8; - $$ = (Node *)n; - } - | ALTER TABLESPACE name MOVE TABLES TO name opt_nowait - { - AlterTableSpaceMoveStmt *n = - makeNode(AlterTableSpaceMoveStmt); - n->orig_tablespacename = $3; - n->objtype = OBJECT_TABLE; - n->move_all = false; - n->roles = NIL; - n->new_tablespacename = $7; - n->nowait = $8; - $$ = (Node *)n; - } - | ALTER TABLESPACE name MOVE INDEXES TO name opt_nowait - { - AlterTableSpaceMoveStmt *n = - makeNode(AlterTableSpaceMoveStmt); - n->orig_tablespacename = $3; - n->objtype = OBJECT_INDEX; - n->move_all = false; - n->roles = NIL; - n->new_tablespacename = $7; - n->nowait = $8; - $$ = (Node *)n; - } - | ALTER TABLESPACE name MOVE MATERIALIZED VIEWS TO name opt_nowait - { - AlterTableSpaceMoveStmt *n = - makeNode(AlterTableSpaceMoveStmt); - n->orig_tablespacename = $3; - n->objtype = OBJECT_MATVIEW; - n->move_all = false; - n->roles = NIL; - n->new_tablespacename = $8; - n->nowait = $9; - $$ = (Node *)n; - } - | ALTER TABLESPACE name MOVE ALL OWNED BY role_list TO name opt_nowait - { - AlterTableSpaceMoveStmt *n = - makeNode(AlterTableSpaceMoveStmt); - n->orig_tablespacename = $3; - n->objtype = -1; - n->move_all = true; - n->roles = $8; - n->new_tablespacename = $10; - n->nowait = $11; - $$ = (Node *)n; - } - | ALTER TABLESPACE name MOVE TABLES OWNED BY role_list TO name opt_nowait - { - AlterTableSpaceMoveStmt *n = - makeNode(AlterTableSpaceMoveStmt); - n->orig_tablespacename = $3; - n->objtype = OBJECT_TABLE; - n->move_all = false; - n->roles = $8; - n->new_tablespacename = $10; - n->nowait = $11; - $$ = (Node *)n; - } - | ALTER TABLESPACE name MOVE INDEXES OWNED BY role_list TO name opt_nowait - { - AlterTableSpaceMoveStmt *n = - makeNode(AlterTableSpaceMoveStmt); - n->orig_tablespacename = $3; - n->objtype = OBJECT_INDEX; - n->move_all = false; - n->roles = $8; - n->new_tablespacename = $10; - n->nowait = $11; - $$ = (Node *)n; - } - | ALTER TABLESPACE name MOVE MATERIALIZED VIEWS OWNED BY role_list TO name opt_nowait - { - AlterTableSpaceMoveStmt *n = - makeNode(AlterTableSpaceMoveStmt); - n->orig_tablespacename = $3; - n->objtype = OBJECT_MATVIEW; - n->move_all = false; - n->roles = $9; - n->new_tablespacename = $11; - n->nowait = $12; - $$ = (Node *)n; - } - | ALTER TABLESPACE name SET reloptions +AlterTblSpcStmt: + ALTER TABLESPACE name SET reloptions { AlterTableSpaceOptionsStmt *n = makeNode(AlterTableSpaceOptionsStmt); diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 3423898c11..0558ea34b0 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -147,6 +147,7 @@ check_xact_readonly(Node *parsetree) case T_AlterObjectSchemaStmt: case T_AlterOwnerStmt: case T_AlterSeqStmt: + case T_AlterTableMoveAllStmt: case T_AlterTableStmt: case T_RenameStmt: case T_CommentStmt: @@ -200,7 +201,6 @@ check_xact_readonly(Node *parsetree) case T_AlterUserMappingStmt: case T_DropUserMappingStmt: case T_AlterTableSpaceOptionsStmt: - case T_AlterTableSpaceMoveStmt: case T_CreateForeignTableStmt: case T_SecLabelStmt: PreventCommandIfReadOnly(CreateCommandTag(parsetree)); @@ -506,9 +506,8 @@ standard_ProcessUtility(Node *parsetree, AlterTableSpaceOptions((AlterTableSpaceOptionsStmt *) parsetree); break; - case T_AlterTableSpaceMoveStmt: - /* no event triggers for global objects */ - AlterTableSpaceMove((AlterTableSpaceMoveStmt *) parsetree); + case T_AlterTableMoveAllStmt: + AlterTableMoveAll((AlterTableMoveAllStmt *) parsetree); break; case T_TruncateStmt: @@ -1805,10 +1804,6 @@ CreateCommandTag(Node *parsetree) tag = "ALTER TABLESPACE"; break; - case T_AlterTableSpaceMoveStmt: - tag = "ALTER TABLESPACE"; - break; - case T_CreateExtensionStmt: tag = "CREATE EXTENSION"; break; @@ -1973,6 +1968,10 @@ CreateCommandTag(Node *parsetree) tag = AlterObjectTypeCommandTag(((AlterOwnerStmt *) parsetree)->objectType); break; + case T_AlterTableMoveAllStmt: + tag = AlterObjectTypeCommandTag(((AlterTableMoveAllStmt *) parsetree)->objtype); + break; + case T_AlterTableStmt: tag = AlterObjectTypeCommandTag(((AlterTableStmt *) parsetree)->relkind); break; @@ -2501,10 +2500,6 @@ GetCommandLogLevel(Node *parsetree) lev = LOGSTMT_DDL; break; - case T_AlterTableSpaceMoveStmt: - lev = LOGSTMT_DDL; - break; - case T_CreateExtensionStmt: case T_AlterExtensionStmt: case T_AlterExtensionContentsStmt: @@ -2583,6 +2578,7 @@ GetCommandLogLevel(Node *parsetree) lev = LOGSTMT_DDL; break; + case T_AlterTableMoveAllStmt: case T_AlterTableStmt: lev = LOGSTMT_DDL; break; diff --git a/src/include/commands/tablecmds.h b/src/include/commands/tablecmds.h index e55f45ab26..932322f144 100644 --- a/src/include/commands/tablecmds.h +++ b/src/include/commands/tablecmds.h @@ -35,6 +35,8 @@ extern void ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, L extern void AlterTableInternal(Oid relid, List *cmds, bool recurse); +extern Oid AlterTableMoveAll(AlterTableMoveAllStmt *stmt); + extern Oid AlterTableNamespace(AlterObjectSchemaStmt *stmt); extern void AlterTableNamespaceInternal(Relation rel, Oid oldNspOid, diff --git a/src/include/commands/tablespace.h b/src/include/commands/tablespace.h index 1603f677a7..c7af55917d 100644 --- a/src/include/commands/tablespace.h +++ b/src/include/commands/tablespace.h @@ -43,7 +43,6 @@ extern Oid CreateTableSpace(CreateTableSpaceStmt *stmt); extern void DropTableSpace(DropTableSpaceStmt *stmt); extern Oid RenameTableSpace(const char *oldname, const char *newname); extern Oid AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt); -extern Oid AlterTableSpaceMove(AlterTableSpaceMoveStmt *stmt); extern void TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo); diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index bc58e16525..5dcc66f27f 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -354,7 +354,7 @@ typedef enum NodeTag T_AlterUserMappingStmt, T_DropUserMappingStmt, T_AlterTableSpaceOptionsStmt, - T_AlterTableSpaceMoveStmt, + T_AlterTableMoveAllStmt, T_SecLabelStmt, T_CreateForeignTableStmt, T_CreateExtensionStmt, diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 7e560a19a3..3146aa53ed 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -1689,16 +1689,15 @@ typedef struct AlterTableSpaceOptionsStmt bool isReset; } AlterTableSpaceOptionsStmt; -typedef struct AlterTableSpaceMoveStmt +typedef struct AlterTableMoveAllStmt { NodeTag type; char *orig_tablespacename; - ObjectType objtype; /* set to -1 if move_all is true */ - bool move_all; /* move all, or just objtype objects? */ + ObjectType objtype; /* Object type to move */ List *roles; /* List of roles to move objects of */ char *new_tablespacename; bool nowait; -} AlterTableSpaceMoveStmt; +} AlterTableMoveAllStmt; /* ---------------------- * Create/Alter Extension Statements diff --git a/src/test/regress/input/tablespace.source b/src/test/regress/input/tablespace.source index 601522866d..e259254b02 100644 --- a/src/test/regress/input/tablespace.source +++ b/src/test/regress/input/tablespace.source @@ -76,10 +76,11 @@ CREATE TABLE tablespace_table (i int) TABLESPACE testspace; -- fail ALTER TABLESPACE testspace RENAME TO testspace_renamed; -ALTER TABLESPACE testspace_renamed MOVE ALL TO pg_default; +ALTER TABLE ALL IN TABLESPACE testspace_renamed SET TABLESPACE pg_default; +ALTER INDEX ALL IN TABLESPACE testspace_renamed SET TABLESPACE pg_default; -- Should show notice that nothing was done -ALTER TABLESPACE testspace_renamed MOVE ALL TO pg_default; +ALTER TABLE ALL IN TABLESPACE testspace_renamed SET TABLESPACE pg_default; -- Should succeed DROP TABLESPACE testspace_renamed; diff --git a/src/test/regress/output/tablespace.source b/src/test/regress/output/tablespace.source index 27bc491e19..a30651087b 100644 --- a/src/test/regress/output/tablespace.source +++ b/src/test/regress/output/tablespace.source @@ -93,9 +93,10 @@ CREATE TABLE tablespace_table (i int) TABLESPACE testspace; -- fail ERROR: permission denied for tablespace testspace \c - ALTER TABLESPACE testspace RENAME TO testspace_renamed; -ALTER TABLESPACE testspace_renamed MOVE ALL TO pg_default; +ALTER TABLE ALL IN TABLESPACE testspace_renamed SET TABLESPACE pg_default; +ALTER INDEX ALL IN TABLESPACE testspace_renamed SET TABLESPACE pg_default; -- Should show notice that nothing was done -ALTER TABLESPACE testspace_renamed MOVE ALL TO pg_default; +ALTER TABLE ALL IN TABLESPACE testspace_renamed SET TABLESPACE pg_default; NOTICE: no matching relations in tablespace "testspace_renamed" found -- Should succeed DROP TABLESPACE testspace_renamed; diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index 913d6ef6b2..ab36aa3acb 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -77,7 +77,7 @@ AlterSystemStmt AlterTSConfigurationStmt AlterTSDictionaryStmt AlterTableCmd -AlterTableSpaceMoveStmt +AlterTableMoveAllStmt AlterTableSpaceOptionsStmt AlterTableStmt AlterTableType -- 2.40.0