diff --git a/doc/src/sgml/ref/alter_index.sgml b/doc/src/sgml/ref/alter_index.sgml
index 94a7af0429c..ee3e3de4d6f 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 1932eeb84d4..b0759fc5dca 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 69a1e14bce3..0e7b99c934c 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 bd1afb4b727..7c4aabc5826 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 e338554995d..5233ed256ae 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 89bd31ab93e..34c38de3fff 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 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"
@@ -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 43530aa24a8..221d0fee6bb 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 2407cb73a38..7e53681e706 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 7b9895d61ec..2e9bbe232f9 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 3423898c112..0558ea34b05 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 e55f45ab26f..932322f144c 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 1603f677a7d..c7af55917d7 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 bc58e165258..5dcc66f27ff 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 7e560a19a3b..3146aa53ed1 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 601522866d1..e259254b02c 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 27bc491e195..a30651087b9 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 913d6ef6b28..ab36aa3acb6 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