]> granicus.if.org Git - postgresql/commitdiff
Rework 'MOVE ALL' to 'ALTER .. ALL IN TABLESPACE'
authorStephen Frost <sfrost@snowman.net>
Thu, 21 Aug 2014 23:06:17 +0000 (19:06 -0400)
committerStephen Frost <sfrost@snowman.net>
Thu, 21 Aug 2014 23:12:00 +0000 (19:12 -0400)
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.

18 files changed:
doc/src/sgml/ref/alter_index.sgml
doc/src/sgml/ref/alter_materialized_view.sgml
doc/src/sgml/ref/alter_table.sgml
doc/src/sgml/ref/alter_tablespace.sgml
doc/src/sgml/release-9.4.sgml
src/backend/commands/tablecmds.c
src/backend/commands/tablespace.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/parser/gram.y
src/backend/tcop/utility.c
src/include/commands/tablecmds.h
src/include/commands/tablespace.h
src/include/nodes/nodes.h
src/include/nodes/parsenodes.h
src/test/regress/input/tablespace.source
src/test/regress/output/tablespace.source
src/tools/pgindent/typedefs.list

index 94a7af0429c7561e25a5e92053baefd04890336b..ee3e3de4d6fe1cc179aa37c3a3360c946877cba2 100644 (file)
@@ -25,6 +25,8 @@ ALTER INDEX [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable> RENA
 ALTER INDEX [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable> SET TABLESPACE <replaceable class="PARAMETER">tablespace_name</replaceable>
 ALTER INDEX [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable> SET ( <replaceable class="PARAMETER">storage_parameter</replaceable> = <replaceable class="PARAMETER">value</replaceable> [, ... ] )
 ALTER INDEX [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable> RESET ( <replaceable class="PARAMETER">storage_parameter</replaceable> [, ... ] )
+ALTER INDEX ALL IN TABLESPACE <replaceable class="PARAMETER">name</replaceable> [ OWNED BY <replaceable class="PARAMETER">role_name</replaceable> [, ... ] ]
+    SET TABLESPACE <replaceable class="PARAMETER">new_tablespace</replaceable> [ NOWAIT ]
 </synopsis>
  </refsynopsisdiv>
 
@@ -63,6 +65,17 @@ ALTER INDEX [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable> RESE
      <para>
       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
+      <literal>CREATE</literal> privilege on the new tablespace.
+      All indexes in the current database in a tablespace can be moved by using
+      the <literal>ALL IN TABLESPACE</literal> form, which will lock all
+      indexes to be moved and then move each one.  This form also supports
+      <literal>OWNED BY</literal>, which will only move indexes owned by the
+      roles specified.  If the <literal>NOWAIT</literal> 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 <command>ALTER DATABASE</command> or explicit
+      <command>ALTER INDEX</command> invocations instead if desired.
       See also
       <xref linkend="SQL-CREATETABLESPACE">.
      </para>
index 1932eeb84d46272273f58a686e773c175c271c59..b0759fc5dca5af497e837f203d9edc7082820f4a 100644 (file)
@@ -29,6 +29,8 @@ ALTER MATERIALIZED VIEW [ IF EXISTS ] <replaceable class="parameter">name</repla
     RENAME TO <replaceable class="parameter">new_name</replaceable>
 ALTER MATERIALIZED VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable>
     SET SCHEMA <replaceable class="parameter">new_schema</replaceable>
+ALTER MATERIALIZED VIEW ALL IN TABLESPACE <replaceable class="parameter">name</replaceable> [ OWNED BY <replaceable class="PARAMETER">role_name</replaceable> [, ... ] ]
+    SET TABLESPACE <replaceable class="PARAMETER">new_tablespace</replaceable> [ NOWAIT ]
 
 <phrase>where <replaceable class="PARAMETER">action</replaceable> is one of:</phrase>
 
index 69a1e14bce3d9ff84b0ed44650f5d09fda59d8f4..0e7b99c934cc68db1a7251959ce2d3b9a9e08076 100644 (file)
@@ -31,6 +31,8 @@ ALTER TABLE [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable>
     RENAME TO <replaceable class="PARAMETER">new_name</replaceable>
 ALTER TABLE [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable>
     SET SCHEMA <replaceable class="PARAMETER">new_schema</replaceable>
+ALTER TABLE ALL IN TABLESPACE <replaceable class="PARAMETER">name</replaceable> [ OWNED BY <replaceable class="PARAMETER">role_name</replaceable> [, ... ] ]
+    SET TABLESPACE <replaceable class="PARAMETER">new_tablespace</replaceable> [ NOWAIT ]
 
 <phrase>where <replaceable class="PARAMETER">action</replaceable> is one of:</phrase>
 
@@ -597,6 +599,17 @@ ALTER TABLE [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable>
       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 <literal>SET TABLESPACE</literal> commands.
+      All tables in the current database in a tablespace can be moved by using
+      the <literal>ALL IN TABLESPACE</literal> form, which will lock all tables
+      to be moved first and then move each one.  This form also supports
+      <literal>OWNED BY</literal>, which will only move tables owned by the
+      roles specified.  If the <literal>NOWAIT</literal> 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 <command>ALTER DATABASE</command> or explicit
+      <command>ALTER TABLE</command> invocations instead if desired.  The
+      <literal>information_schema</literal> relations are not considered part
+      of the system catalogs and will be moved.
       See also
       <xref linkend="SQL-CREATETABLESPACE">.
      </para>
@@ -649,7 +662,8 @@ ALTER TABLE [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable>
   </para>
 
   <para>
-   All the actions except <literal>RENAME</literal> and <literal>SET SCHEMA</>
+   All the actions except <literal>RENAME</literal>,
+   <literal>SET TABLESPACE</literal> and <literal>SET SCHEMA</literal>
    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 ] <replaceable class="PARAMETER">name</replaceable>
 
   <para>
    You must own the table to use <command>ALTER TABLE</>.
-   To change the schema of a table, you must also have
-   <literal>CREATE</literal> privilege on the new schema.
+   To change the schema or tablespace of a table, you must also have
+   <literal>CREATE</literal> 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
index bd1afb4b727257932034faef944b17477d8172ef..7c4aabc582681828fd5b2c7d1bf227f1fc7ca737 100644 (file)
@@ -25,7 +25,6 @@ ALTER TABLESPACE <replaceable>name</replaceable> RENAME TO <replaceable>new_name
 ALTER TABLESPACE <replaceable>name</replaceable> OWNER TO <replaceable>new_owner</replaceable>
 ALTER TABLESPACE <replaceable>name</replaceable> SET ( <replaceable class="PARAMETER">tablespace_option</replaceable> = <replaceable class="PARAMETER">value</replaceable> [, ... ] )
 ALTER TABLESPACE <replaceable>name</replaceable> RESET ( <replaceable class="PARAMETER">tablespace_option</replaceable> [, ... ] )
-ALTER TABLESPACE <replaceable>name</replaceable> MOVE { ALL | TABLES | INDEXES | MATERIALIZED VIEWS } [ OWNED BY <replaceable class="PARAMETER">role_name</replaceable> [, ...] ] TO <replaceable>new_tablespace</replaceable> [ NOWAIT ]
 </synopsis>
  </refsynopsisdiv>
 
@@ -45,44 +44,6 @@ ALTER TABLESPACE <replaceable>name</replaceable> MOVE { ALL | TABLES | INDEXES |
    (Note that superusers have these privileges automatically.)
   </para>
 
-  <para>
-   <literal>ALTER TABLESPACE ... MOVE</literal> moves objects between
-   tablespaces.  <literal>ALL</literal> will move all tables, indexes and
-   materialized views; specifying <literal>TABLES</literal> will move only
-   tables (but not their indexes), <literal>INDEXES</literal> will only move
-   indexes (including those underneath materialized views, but not tables),
-   and <literal>MATERIALIZED VIEWS</literal> 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
-   <literal>OWNED BY</literal>.
-  </para>
-
-  <para>
-   Users must have <literal>CREATE</literal> 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 <literal>ALTER TABLESPACE ... MOVE ALL</literal> 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 <literal>OWNED BY</literal> in
-   such cases, to restrict the set of objects moved to those with the required
-   rights.)
-  </para>
-
-  <para>
-   All objects to be moved will be locked immediately by the command.  If the
-   <literal>NOWAIT</literal> is specified, it will cause the command to fail
-   if it is unable to acquire the locks.
-  </para>
-
-  <para>
-   System catalogs will not be moved by this command.  To move a whole
-   database, use <command>ALTER DATABASE</command>, or call <command>ALTER
-   TABLE</command> on the individual system catalogs.  Note that relations in
-   <literal>information_schema</literal> will be moved, just as any other
-   normal database objects, if the user is the superuser or considered an
-   owner of the relations in <literal>information_schema</literal>.
-  </para>
  </refsect1>
 
  <refsect1>
@@ -136,38 +97,6 @@ ALTER TABLESPACE <replaceable>name</replaceable> MOVE { ALL | TABLES | INDEXES |
     </listitem>
    </varlistentry>
 
-   <varlistentry>
-    <term><replaceable class="parameter">role_name</replaceable></term>
-    <listitem>
-     <para>
-      Role whose objects are to be moved.
-     </para>
-    </listitem>
-   </varlistentry>
-
-   <varlistentry>
-    <term><replaceable class="parameter">new_tablespace</replaceable></term>
-    <listitem>
-     <para>
-      The name of the tablespace to move objects into.  The user must have
-      <literal>CREATE</literal> 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.
-     </para>
-    </listitem>
-   </varlistentry>
-
-   <varlistentry>
-    <term>NOWAIT</term>
-    <listitem>
-     <para>
-      The <literal>NOWAIT</literal> option causes the <command>ALTER TABLESPACE</command> command to fail immediately
-      if it is unable to acquire the necessary lock on all of the objects being
-      moved.
-     </para>
-    </listitem>
-   </varlistentry>
-
   </variablelist>
  </refsect1>
 
@@ -185,13 +114,6 @@ ALTER TABLESPACE index_space RENAME TO fast_raid;
    Change the owner of tablespace <literal>index_space</literal>:
 <programlisting>
 ALTER TABLESPACE index_space OWNER TO mary;
-</programlisting></para>
-
-  <para>
-   Move all of the objects from the default tablespace to
-   the <literal>fast_raid</literal> tablespace:
-<programlisting>
-ALTER TABLESPACE pg_default MOVE ALL TO fast_raid;
 </programlisting></para>
  </refsect1>
 
index e338554995dfb6a93b551982e890b4a44047bce4..5233ed256aecbb9502774279abec61f3a3064a1c 100644 (file)
       <listitem>
        <para>
         Allow moving groups of objects from one tablespace to another
-        using <xref linkend="SQL-ALTERTABLESPACE"> ... <literal>MOVE</>
+        using <literal>ALL IN TABLESPACE ... SET TABLESPACE</> with
+        <link linkend="SQL-ALTERTABLE"><command>ALTER TABLE</></link>
+        <link linkend="SQL-ALTERINDEX"><command>ALTER INDEX</></link> and
+        <link linkend="SQL-ALTERMATERIALIZEDVIEW"><command>ALTER MATERIALIZED VIEW</></link>
         (Stephen Frost)
        </para>
       </listitem>
index 89bd31ab93e2e20ec1e0826d7c9ca9d7653bddbd..34c38de3fff2d6f819ba656daf0193dbfc596838 100644 (file)
@@ -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
  */
index 031be37a1e7531dc4eecdd620d3b37d502ee1088..28e69a55510aabe246d71a41251927ce5cec55d6 100644 (file)
@@ -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'.
  */
index 43530aa24a8e1fd6237c9bd91f36fa325419a207..221d0fee6bbd689f7c61d0f2bec5bb6e180a6c6e 100644 (file)
@@ -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);
index 2407cb73a380d15a2ab04dbc65c604aaaf3910fb..7e53681e70654668c13c287a3ff7e6bcb76561d0 100644 (file)
@@ -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);
index 7b9895d61ece74e80a863809764dfc2a7203b79c..2e9bbe232f9d2f3200a8b8077bd199ac8481987b 100644 (file)
@@ -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);
index 3423898c1125cf64e292f0c1939e023cf408c2b5..0558ea34b054db356ff081abc0b10d7bb2b0186d 100644 (file)
@@ -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;
index e55f45ab26f3e9f78af08c4c987096c629bd5e98..932322f144c476d4913bd09cef879016bd820616 100644 (file)
@@ -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,
index 1603f677a7de23b68d7e0ac6da7eeca0617a2d2f..c7af55917d77f15f75ede7254b237a150641aceb 100644 (file)
@@ -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);
 
index bc58e165258573c4ba4bc61fdee0d80cd26da907..5dcc66f27fff1f14a28064a6226ef6a3e821bd1b 100644 (file)
@@ -354,7 +354,7 @@ typedef enum NodeTag
        T_AlterUserMappingStmt,
        T_DropUserMappingStmt,
        T_AlterTableSpaceOptionsStmt,
-       T_AlterTableSpaceMoveStmt,
+       T_AlterTableMoveAllStmt,
        T_SecLabelStmt,
        T_CreateForeignTableStmt,
        T_CreateExtensionStmt,
index 7e560a19a3bd114c639bdc7edfa817e5d6fc91b7..3146aa53ed160d932d6c24df7ae705bd2d1ce3cd 100644 (file)
@@ -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
index 601522866d11a8e83a48c6153abb5cc21e051b99..e259254b02cb6bda9bf443ed6b8f0c2c7a5a91c4 100644 (file)
@@ -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;
index 27bc491e1959cfda79bc9136b0e3793321519148..a30651087b9d59c144a287c8d5a837295a406b86 100644 (file)
@@ -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;
index 913d6ef6b288778517dd180724add688272081e5..ab36aa3acb64014286a01208465beae5a6f41432 100644 (file)
@@ -77,7 +77,7 @@ AlterSystemStmt
 AlterTSConfigurationStmt
 AlterTSDictionaryStmt
 AlterTableCmd
-AlterTableSpaceMoveStmt
+AlterTableMoveAllStmt
 AlterTableSpaceOptionsStmt
 AlterTableStmt
 AlterTableType