Commit fbe19ee3 authored by Stephen Frost's avatar Stephen Frost

ALTER TABLESPACE ... MOVE ... OWNED BY

Add the ability to specify the objects to move by who those objects are
owned by (as relowner) and change ALL to mean ALL objects.  This
makes the command always operate against a well-defined set of objects
and not have the objects-to-be-moved based on the role of the user
running the command.

Per discussion with Simon and Tom.
parent 3ee74df2
...@@ -25,7 +25,7 @@ ALTER TABLESPACE <replaceable>name</replaceable> RENAME TO <replaceable>new_name ...@@ -25,7 +25,7 @@ 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> 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> 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> RESET ( <replaceable class="PARAMETER">tablespace_option</replaceable> [, ... ] )
ALTER TABLESPACE <replaceable>name</replaceable> MOVE { ALL | TABLES | INDEXES | MATERIALIZED VIEWS } TO <replaceable>new_tablespace</replaceable> [ NOWAIT ] 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> </synopsis>
</refsynopsisdiv> </refsynopsisdiv>
...@@ -34,8 +34,8 @@ ALTER TABLESPACE <replaceable>name</replaceable> MOVE { ALL | TABLES | INDEXES | ...@@ -34,8 +34,8 @@ ALTER TABLESPACE <replaceable>name</replaceable> MOVE { ALL | TABLES | INDEXES |
<para> <para>
<command>ALTER TABLESPACE</command> can be used to change the definition of <command>ALTER TABLESPACE</command> can be used to change the definition of
a tablespace or to migrate all of the objects in the current database which a tablespace or to migrate objects in the current database between
are owned by the user out of a given tablespace. tablespaces.
</para> </para>
<para> <para>
...@@ -44,13 +44,19 @@ ALTER TABLESPACE <replaceable>name</replaceable> MOVE { ALL | TABLES | INDEXES | ...@@ -44,13 +44,19 @@ ALTER TABLESPACE <replaceable>name</replaceable> MOVE { ALL | TABLES | INDEXES |
owning role. owning role.
(Note that superusers have these privileges automatically.) (Note that superusers have these privileges automatically.)
Users may use ALTER TABLESPACE ... MOVE to move either ALL of their objects, Users may use ALTER TABLESPACE ... MOVE to move objects between tablespaces.
or just TABLES, INDEXES, or MATERIALIZED VIEWS, but they must have CREATE ALL will move all tables, indexes and materialized views while specifying
rights on the new tablespace and only objects, directly or indirectly, owned TABLES will move only tables (but not their indexes), INDEXES will only move
by the user will be moved. Note that the superuser is considered an owner indexes (including those underneath materialized views, but not tables) and
of all objects and therefore an ALTER TABLESPACE ... MOVE ALL issued by the MATERIALIZED VIEWS will only move the table relation of the materialized
superuser will move all objects in the current database which are in the view (but no indexes associated with it). Users may also specify a list of
tablespace. 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) on 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 which are in the tablespace.
All objects to be moved will be locked immediately by the command. The All objects to be moved will be locked immediately by the command. The
NOWAIT option, if specified, will cause the command to fail if it is unable NOWAIT option, if specified, will cause the command to fail if it is unable
...@@ -115,6 +121,15 @@ ALTER TABLESPACE <replaceable>name</replaceable> MOVE { ALL | TABLES | INDEXES | ...@@ -115,6 +121,15 @@ ALTER TABLESPACE <replaceable>name</replaceable> MOVE { ALL | TABLES | INDEXES |
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><replaceable class="parameter">role_name</replaceable></term>
<listitem>
<para>
Role(s) whose objects are to be moved.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><replaceable class="parameter">new_tablespace</replaceable></term> <term><replaceable class="parameter">new_tablespace</replaceable></term>
<listitem> <listitem>
......
...@@ -67,6 +67,7 @@ ...@@ -67,6 +67,7 @@
#include "commands/seclabel.h" #include "commands/seclabel.h"
#include "commands/tablecmds.h" #include "commands/tablecmds.h"
#include "commands/tablespace.h" #include "commands/tablespace.h"
#include "commands/user.h"
#include "common/relpath.h" #include "common/relpath.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "postmaster/bgwriter.h" #include "postmaster/bgwriter.h"
...@@ -994,6 +995,7 @@ AlterTableSpaceMove(AlterTableSpaceMoveStmt *stmt) ...@@ -994,6 +995,7 @@ AlterTableSpaceMove(AlterTableSpaceMoveStmt *stmt)
HeapTuple tuple; HeapTuple tuple;
Oid orig_tablespaceoid; Oid orig_tablespaceoid;
Oid new_tablespaceoid; Oid new_tablespaceoid;
List *role_oids = roleNamesToIds(stmt->roles);
/* Ensure we were not asked to move something we can't */ /* Ensure we were not asked to move something we can't */
if (!stmt->move_all && stmt->objtype != OBJECT_TABLE && if (!stmt->move_all && stmt->objtype != OBJECT_TABLE &&
...@@ -1075,14 +1077,10 @@ AlterTableSpaceMove(AlterTableSpaceMoveStmt *stmt) ...@@ -1075,14 +1077,10 @@ AlterTableSpaceMove(AlterTableSpaceMoveStmt *stmt)
relForm->relnamespace == PG_TOAST_NAMESPACE) relForm->relnamespace == PG_TOAST_NAMESPACE)
continue; continue;
/* /* Only consider objects which live in tablespaces */
* Only move objects that we are considered an owner of and only if (relForm->relkind != RELKIND_RELATION &&
* objects which can actually have a tablespace.
*/
if (!pg_class_ownercheck(relOid, GetUserId()) ||
(relForm->relkind != RELKIND_RELATION &&
relForm->relkind != RELKIND_INDEX && relForm->relkind != RELKIND_INDEX &&
relForm->relkind != RELKIND_MATVIEW)) relForm->relkind != RELKIND_MATVIEW)
continue; continue;
/* Check if we were asked to only move a certain type of object */ /* Check if we were asked to only move a certain type of object */
...@@ -1095,6 +1093,21 @@ AlterTableSpaceMove(AlterTableSpaceMoveStmt *stmt) ...@@ -1095,6 +1093,21 @@ AlterTableSpaceMove(AlterTableSpaceMoveStmt *stmt)
relForm->relkind != RELKIND_MATVIEW))) relForm->relkind != RELKIND_MATVIEW)))
continue; 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 && if (stmt->nowait &&
!ConditionalLockRelationOid(relOid, AccessExclusiveLock)) !ConditionalLockRelationOid(relOid, AccessExclusiveLock))
ereport(ERROR, ereport(ERROR,
......
...@@ -48,7 +48,6 @@ extern bool Password_encryption; ...@@ -48,7 +48,6 @@ extern bool Password_encryption;
/* Hook to check passwords in CreateRole() and AlterRole() */ /* Hook to check passwords in CreateRole() and AlterRole() */
check_password_hook_type check_password_hook = NULL; check_password_hook_type check_password_hook = NULL;
static List *roleNamesToIds(List *memberNames);
static void AddRoleMems(const char *rolename, Oid roleid, static void AddRoleMems(const char *rolename, Oid roleid,
List *memberNames, List *memberIds, List *memberNames, List *memberIds,
Oid grantorId, bool admin_opt); Oid grantorId, bool admin_opt);
...@@ -1302,7 +1301,7 @@ ReassignOwnedObjects(ReassignOwnedStmt *stmt) ...@@ -1302,7 +1301,7 @@ ReassignOwnedObjects(ReassignOwnedStmt *stmt)
* Given a list of role names (as String nodes), generate a list of role OIDs * Given a list of role names (as String nodes), generate a list of role OIDs
* in the same order. * in the same order.
*/ */
static List * List *
roleNamesToIds(List *memberNames) roleNamesToIds(List *memberNames)
{ {
List *result = NIL; List *result = NIL;
......
...@@ -3404,6 +3404,9 @@ _copyAlterTableSpaceMoveStmt(const AlterTableSpaceMoveStmt *from) ...@@ -3404,6 +3404,9 @@ _copyAlterTableSpaceMoveStmt(const AlterTableSpaceMoveStmt *from)
AlterTableSpaceMoveStmt *newnode = makeNode(AlterTableSpaceMoveStmt); AlterTableSpaceMoveStmt *newnode = makeNode(AlterTableSpaceMoveStmt);
COPY_STRING_FIELD(orig_tablespacename); COPY_STRING_FIELD(orig_tablespacename);
COPY_SCALAR_FIELD(objtype);
COPY_SCALAR_FIELD(move_all);
COPY_NODE_FIELD(roles);
COPY_STRING_FIELD(new_tablespacename); COPY_STRING_FIELD(new_tablespacename);
COPY_SCALAR_FIELD(nowait); COPY_SCALAR_FIELD(nowait);
......
...@@ -1640,6 +1640,9 @@ _equalAlterTableSpaceMoveStmt(const AlterTableSpaceMoveStmt *a, ...@@ -1640,6 +1640,9 @@ _equalAlterTableSpaceMoveStmt(const AlterTableSpaceMoveStmt *a,
const AlterTableSpaceMoveStmt *b) const AlterTableSpaceMoveStmt *b)
{ {
COMPARE_STRING_FIELD(orig_tablespacename); COMPARE_STRING_FIELD(orig_tablespacename);
COMPARE_SCALAR_FIELD(objtype);
COMPARE_SCALAR_FIELD(move_all);
COMPARE_NODE_FIELD(roles);
COMPARE_STRING_FIELD(new_tablespacename); COMPARE_STRING_FIELD(new_tablespacename);
COMPARE_SCALAR_FIELD(nowait); COMPARE_SCALAR_FIELD(nowait);
......
...@@ -7325,9 +7325,11 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name ...@@ -7325,9 +7325,11 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
AlterTableSpaceMoveStmt *n = AlterTableSpaceMoveStmt *n =
makeNode(AlterTableSpaceMoveStmt); makeNode(AlterTableSpaceMoveStmt);
n->orig_tablespacename = $3; n->orig_tablespacename = $3;
n->objtype = -1;
n->move_all = true;
n->roles = NIL;
n->new_tablespacename = $7; n->new_tablespacename = $7;
n->nowait = $8; n->nowait = $8;
n->move_all = true;
$$ = (Node *)n; $$ = (Node *)n;
} }
| ALTER TABLESPACE name MOVE TABLES TO name opt_nowait | ALTER TABLESPACE name MOVE TABLES TO name opt_nowait
...@@ -7335,10 +7337,11 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name ...@@ -7335,10 +7337,11 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
AlterTableSpaceMoveStmt *n = AlterTableSpaceMoveStmt *n =
makeNode(AlterTableSpaceMoveStmt); makeNode(AlterTableSpaceMoveStmt);
n->orig_tablespacename = $3; n->orig_tablespacename = $3;
n->new_tablespacename = $7;
n->nowait = $8;
n->objtype = OBJECT_TABLE; n->objtype = OBJECT_TABLE;
n->move_all = false; n->move_all = false;
n->roles = NIL;
n->new_tablespacename = $7;
n->nowait = $8;
$$ = (Node *)n; $$ = (Node *)n;
} }
| ALTER TABLESPACE name MOVE INDEXES TO name opt_nowait | ALTER TABLESPACE name MOVE INDEXES TO name opt_nowait
...@@ -7346,10 +7349,11 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name ...@@ -7346,10 +7349,11 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
AlterTableSpaceMoveStmt *n = AlterTableSpaceMoveStmt *n =
makeNode(AlterTableSpaceMoveStmt); makeNode(AlterTableSpaceMoveStmt);
n->orig_tablespacename = $3; n->orig_tablespacename = $3;
n->new_tablespacename = $7;
n->nowait = $8;
n->objtype = OBJECT_INDEX; n->objtype = OBJECT_INDEX;
n->move_all = false; n->move_all = false;
n->roles = NIL;
n->new_tablespacename = $7;
n->nowait = $8;
$$ = (Node *)n; $$ = (Node *)n;
} }
| ALTER TABLESPACE name MOVE MATERIALIZED VIEWS TO name opt_nowait | ALTER TABLESPACE name MOVE MATERIALIZED VIEWS TO name opt_nowait
...@@ -7357,10 +7361,59 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name ...@@ -7357,10 +7361,59 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
AlterTableSpaceMoveStmt *n = AlterTableSpaceMoveStmt *n =
makeNode(AlterTableSpaceMoveStmt); makeNode(AlterTableSpaceMoveStmt);
n->orig_tablespacename = $3; n->orig_tablespacename = $3;
n->objtype = OBJECT_MATVIEW;
n->move_all = false;
n->roles = NIL;
n->new_tablespacename = $8; n->new_tablespacename = $8;
n->nowait = $9; 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->objtype = OBJECT_MATVIEW;
n->move_all = false; n->move_all = false;
n->roles = $9;
n->new_tablespacename = $11;
n->nowait = $12;
$$ = (Node *)n; $$ = (Node *)n;
} }
| ALTER TABLESPACE name SET reloptions | ALTER TABLESPACE name SET reloptions
......
...@@ -30,5 +30,6 @@ extern void GrantRole(GrantRoleStmt *stmt); ...@@ -30,5 +30,6 @@ extern void GrantRole(GrantRoleStmt *stmt);
extern Oid RenameRole(const char *oldname, const char *newname); extern Oid RenameRole(const char *oldname, const char *newname);
extern void DropOwnedObjects(DropOwnedStmt *stmt); extern void DropOwnedObjects(DropOwnedStmt *stmt);
extern void ReassignOwnedObjects(ReassignOwnedStmt *stmt); extern void ReassignOwnedObjects(ReassignOwnedStmt *stmt);
extern List *roleNamesToIds(List *memberNames);
#endif /* USER_H */ #endif /* USER_H */
...@@ -1691,10 +1691,11 @@ typedef struct AlterTableSpaceMoveStmt ...@@ -1691,10 +1691,11 @@ typedef struct AlterTableSpaceMoveStmt
{ {
NodeTag type; NodeTag type;
char *orig_tablespacename; char *orig_tablespacename;
ObjectType objtype; /* set to -1 if move_all is true */
bool move_all; /* move all, or just objtype objects? */
List *roles; /* List of roles to move objects of */
char *new_tablespacename; char *new_tablespacename;
ObjectType objtype;
bool nowait; bool nowait;
bool move_all;
} AlterTableSpaceMoveStmt; } AlterTableSpaceMoveStmt;
/* ---------------------- /* ----------------------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment