Commit 04e17bae authored by Simon Riggs's avatar Simon Riggs

Add explicit regression tests for ALTER TABLE lock levels.

Use this to catch a couple of lock level assignments that slipped
through manual testing, per Peter Eisentraut.
parent f0790a64
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.204 2010/07/25 23:21:21 rhaas Exp $ * $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.205 2010/07/29 11:06:34 sriggs Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -376,7 +376,7 @@ cluster_rel(Oid tableOid, Oid indexOid, bool recheck, bool verbose, ...@@ -376,7 +376,7 @@ cluster_rel(Oid tableOid, Oid indexOid, bool recheck, bool verbose,
/* Check heap and index are valid to cluster on */ /* Check heap and index are valid to cluster on */
if (OidIsValid(indexOid)) if (OidIsValid(indexOid))
check_index_is_clusterable(OldHeap, indexOid, recheck); check_index_is_clusterable(OldHeap, indexOid, recheck, AccessExclusiveLock);
/* Log what we're doing (this could use more effort) */ /* Log what we're doing (this could use more effort) */
if (OidIsValid(indexOid)) if (OidIsValid(indexOid))
...@@ -405,11 +405,11 @@ cluster_rel(Oid tableOid, Oid indexOid, bool recheck, bool verbose, ...@@ -405,11 +405,11 @@ cluster_rel(Oid tableOid, Oid indexOid, bool recheck, bool verbose,
* definition can't change under us. * definition can't change under us.
*/ */
void void
check_index_is_clusterable(Relation OldHeap, Oid indexOid, bool recheck) check_index_is_clusterable(Relation OldHeap, Oid indexOid, bool recheck, LOCKMODE lockmode)
{ {
Relation OldIndex; Relation OldIndex;
OldIndex = index_open(indexOid, AccessExclusiveLock); OldIndex = index_open(indexOid, lockmode);
/* /*
* Check that index is in fact an index on the given relation * Check that index is in fact an index on the given relation
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.335 2010/07/28 05:22:24 sriggs Exp $ * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.336 2010/07/29 11:06:34 sriggs Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -2550,6 +2550,8 @@ AlterTableGetLockLevel(List *cmds) ...@@ -2550,6 +2550,8 @@ AlterTableGetLockLevel(List *cmds)
case AT_DropCluster: case AT_DropCluster:
case AT_SetRelOptions: case AT_SetRelOptions:
case AT_ResetRelOptions: case AT_ResetRelOptions:
case AT_SetOptions:
case AT_ResetOptions:
case AT_SetStorage: case AT_SetStorage:
cmd_lockmode = ShareUpdateExclusiveLock; cmd_lockmode = ShareUpdateExclusiveLock;
break; break;
...@@ -2669,19 +2671,19 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd, ...@@ -2669,19 +2671,19 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode); ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode);
/* Performs own permission checks */ /* Performs own permission checks */
ATPrepSetStatistics(rel, cmd->name, cmd->def, lockmode); ATPrepSetStatistics(rel, cmd->name, cmd->def, lockmode);
pass = AT_PASS_COL_ATTRS; pass = AT_PASS_MISC;
break; break;
case AT_SetOptions: /* ALTER COLUMN SET ( options ) */ case AT_SetOptions: /* ALTER COLUMN SET ( options ) */
case AT_ResetOptions: /* ALTER COLUMN RESET ( options ) */ case AT_ResetOptions: /* ALTER COLUMN RESET ( options ) */
ATSimplePermissionsRelationOrIndex(rel); ATSimplePermissionsRelationOrIndex(rel);
/* This command never recurses */ /* This command never recurses */
pass = AT_PASS_COL_ATTRS; pass = AT_PASS_MISC;
break; break;
case AT_SetStorage: /* ALTER COLUMN SET STORAGE */ case AT_SetStorage: /* ALTER COLUMN SET STORAGE */
ATSimplePermissions(rel, false); ATSimplePermissions(rel, false);
ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode); ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode);
/* No command-specific prep needed */ /* No command-specific prep needed */
pass = AT_PASS_COL_ATTRS; pass = AT_PASS_MISC;
break; break;
case AT_DropColumn: /* DROP COLUMN */ case AT_DropColumn: /* DROP COLUMN */
ATSimplePermissions(rel, false); ATSimplePermissions(rel, false);
...@@ -6906,7 +6908,7 @@ ATExecClusterOn(Relation rel, const char *indexName, LOCKMODE lockmode) ...@@ -6906,7 +6908,7 @@ ATExecClusterOn(Relation rel, const char *indexName, LOCKMODE lockmode)
indexName, RelationGetRelationName(rel)))); indexName, RelationGetRelationName(rel))));
/* Check index is valid to cluster on */ /* Check index is valid to cluster on */
check_index_is_clusterable(rel, indexOid, false); check_index_is_clusterable(rel, indexOid, false, lockmode);
/* And do the work */ /* And do the work */
mark_index_clustered(rel, indexOid); mark_index_clustered(rel, indexOid);
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994-5, Regents of the University of California * Portions Copyright (c) 1994-5, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/commands/cluster.h,v 1.41 2010/02/26 02:01:24 momjian Exp $ * $PostgreSQL: pgsql/src/include/commands/cluster.h,v 1.42 2010/07/29 11:06:34 sriggs Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#define CLUSTER_H #define CLUSTER_H
#include "nodes/parsenodes.h" #include "nodes/parsenodes.h"
#include "storage/lock.h"
#include "utils/relcache.h" #include "utils/relcache.h"
...@@ -21,7 +22,7 @@ extern void cluster(ClusterStmt *stmt, bool isTopLevel); ...@@ -21,7 +22,7 @@ extern void cluster(ClusterStmt *stmt, bool isTopLevel);
extern void cluster_rel(Oid tableOid, Oid indexOid, bool recheck, extern void cluster_rel(Oid tableOid, Oid indexOid, bool recheck,
bool verbose, int freeze_min_age, int freeze_table_age); bool verbose, int freeze_min_age, int freeze_table_age);
extern void check_index_is_clusterable(Relation OldHeap, Oid indexOid, extern void check_index_is_clusterable(Relation OldHeap, Oid indexOid,
bool recheck); bool recheck, LOCKMODE lockmode);
extern void mark_index_clustered(Relation rel, Oid indexOid); extern void mark_index_clustered(Relation rel, Oid indexOid);
extern Oid make_new_heap(Oid OIDOldHeap, Oid NewTableSpace); extern Oid make_new_heap(Oid OIDOldHeap, Oid NewTableSpace);
......
...@@ -1473,6 +1473,127 @@ select * from another; ...@@ -1473,6 +1473,127 @@ select * from another;
drop table another; drop table another;
-- --
-- lock levels
--
drop type lockmodes;
ERROR: type "lockmodes" does not exist
create type lockmodes as enum (
'AccessShareLock'
,'RowShareLock'
,'RowExclusiveLock'
,'ShareUpdateExclusiveLock'
,'ShareLock'
,'ShareRowExclusiveLock'
,'ExclusiveLock'
,'AccessExclusiveLock'
);
drop view my_locks;
ERROR: view "my_locks" does not exist
create or replace view my_locks as
select case when c.relname like 'pg_toast%' then 'pg_toast' else c.relname end, max(mode::lockmodes) as max_lockmode
from pg_locks l join pg_class c on l.relation = c.oid
where virtualtransaction = (
select virtualtransaction
from pg_locks
where transactionid = txid_current()::integer)
and locktype = 'relation'
and relnamespace != (select oid from pg_namespace where nspname = 'pg_catalog')
and c.relname != 'my_locks'
group by c.relname;
create table alterlock (f1 int primary key, f2 text);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "alterlock_pkey" for table "alterlock"
-- share update exclusive
begin; alter table alterlock alter column f2 set statistics 150;
select * from my_locks order by 1;
relname | max_lockmode
-----------+--------------------------
alterlock | ShareUpdateExclusiveLock
(1 row)
rollback;
begin; alter table alterlock cluster on alterlock_pkey;
select * from my_locks order by 1;
relname | max_lockmode
----------------+--------------------------
alterlock | ShareUpdateExclusiveLock
alterlock_pkey | ShareUpdateExclusiveLock
(2 rows)
commit;
begin; alter table alterlock set without cluster;
select * from my_locks order by 1;
relname | max_lockmode
-----------+--------------------------
alterlock | ShareUpdateExclusiveLock
(1 row)
commit;
begin; alter table alterlock set (fillfactor = 100);
select * from my_locks order by 1;
relname | max_lockmode
-----------+--------------------------
alterlock | ShareUpdateExclusiveLock
pg_toast | ShareUpdateExclusiveLock
(2 rows)
commit;
begin; alter table alterlock reset (fillfactor);
select * from my_locks order by 1;
relname | max_lockmode
-----------+--------------------------
alterlock | ShareUpdateExclusiveLock
pg_toast | ShareUpdateExclusiveLock
(2 rows)
commit;
begin; alter table alterlock set (toast.autovacuum_enabled = off);
select * from my_locks order by 1;
relname | max_lockmode
-----------+--------------------------
alterlock | ShareUpdateExclusiveLock
pg_toast | ShareUpdateExclusiveLock
(2 rows)
commit;
begin; alter table alterlock set (autovacuum_enabled = off);
select * from my_locks order by 1;
relname | max_lockmode
-----------+--------------------------
alterlock | ShareUpdateExclusiveLock
pg_toast | ShareUpdateExclusiveLock
(2 rows)
commit;
begin; alter table alterlock alter column f2 set (n_distinct = 1);
select * from my_locks order by 1;
relname | max_lockmode
-----------+--------------------------
alterlock | ShareUpdateExclusiveLock
(1 row)
rollback;
begin; alter table alterlock alter column f2 set storage extended;
select * from my_locks order by 1;
relname | max_lockmode
-----------+--------------------------
alterlock | ShareUpdateExclusiveLock
(1 row)
rollback;
-- share row exclusive
begin; alter table alterlock alter column f2 set default 'x';
select * from my_locks order by 1;
relname | max_lockmode
-----------+-----------------------
alterlock | ShareRowExclusiveLock
(1 row)
rollback;
-- cleanup
drop table alterlock;
drop view my_locks;
drop type lockmodes;
--
-- alter function -- alter function
-- --
create function test_strict(text) returns text as create function test_strict(text) returns text as
......
...@@ -1090,6 +1090,83 @@ select * from another; ...@@ -1090,6 +1090,83 @@ select * from another;
drop table another; drop table another;
--
-- lock levels
--
drop type lockmodes;
create type lockmodes as enum (
'AccessShareLock'
,'RowShareLock'
,'RowExclusiveLock'
,'ShareUpdateExclusiveLock'
,'ShareLock'
,'ShareRowExclusiveLock'
,'ExclusiveLock'
,'AccessExclusiveLock'
);
drop view my_locks;
create or replace view my_locks as
select case when c.relname like 'pg_toast%' then 'pg_toast' else c.relname end, max(mode::lockmodes) as max_lockmode
from pg_locks l join pg_class c on l.relation = c.oid
where virtualtransaction = (
select virtualtransaction
from pg_locks
where transactionid = txid_current()::integer)
and locktype = 'relation'
and relnamespace != (select oid from pg_namespace where nspname = 'pg_catalog')
and c.relname != 'my_locks'
group by c.relname;
create table alterlock (f1 int primary key, f2 text);
-- share update exclusive
begin; alter table alterlock alter column f2 set statistics 150;
select * from my_locks order by 1;
rollback;
begin; alter table alterlock cluster on alterlock_pkey;
select * from my_locks order by 1;
commit;
begin; alter table alterlock set without cluster;
select * from my_locks order by 1;
commit;
begin; alter table alterlock set (fillfactor = 100);
select * from my_locks order by 1;
commit;
begin; alter table alterlock reset (fillfactor);
select * from my_locks order by 1;
commit;
begin; alter table alterlock set (toast.autovacuum_enabled = off);
select * from my_locks order by 1;
commit;
begin; alter table alterlock set (autovacuum_enabled = off);
select * from my_locks order by 1;
commit;
begin; alter table alterlock alter column f2 set (n_distinct = 1);
select * from my_locks order by 1;
rollback;
begin; alter table alterlock alter column f2 set storage extended;
select * from my_locks order by 1;
rollback;
-- share row exclusive
begin; alter table alterlock alter column f2 set default 'x';
select * from my_locks order by 1;
rollback;
-- cleanup
drop table alterlock;
drop view my_locks;
drop type lockmodes;
-- --
-- alter function -- alter function
-- --
......
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