Make sure that TRUNCATE always opens a DDL access

pull/2220/head
Onder Kalaci 2018-06-18 14:56:55 +03:00
parent 21038f0d0e
commit 2890154420
5 changed files with 63 additions and 26 deletions

View File

@ -1316,17 +1316,14 @@ ExecuteModifyTasks(List *taskList, bool expectResults, ParamListInfo paramListIn
/* /*
* Ensure that there are no concurrent modifications on the same * Ensure that there are no concurrent modifications on the same
* shards. For DDL commands, we already obtained the appropriate * shards. In general, for DDL commands, we already obtained the
* locks in ProcessUtility. * appropriate locks in ProcessUtility. However, we still prefer to
* * acquire the executor locks for DDLs specifically for TRUNCATE
* We don't need to acquire lock for TRUNCATE_TASK since it already * command on a partition table since AcquireExecutorMultiShardLocks()
* acquires AccessExclusiveLock on the relation, and blocks any * ensures that no concurrent modifications happens on the parent
* concurrent operation. * tables.
*/ */
if (firstTask->taskType == MODIFY_TASK)
{
AcquireExecutorMultiShardLocks(taskList); AcquireExecutorMultiShardLocks(taskList);
}
BeginOrContinueCoordinatedTransaction(); BeginOrContinueCoordinatedTransaction();

View File

@ -55,7 +55,8 @@
#include "utils/memutils.h" #include "utils/memutils.h"
static List * ModifyMultipleShardsTaskList(Query *query, List *shardIntervalList); static List * ModifyMultipleShardsTaskList(Query *query, List *shardIntervalList, TaskType
taskType);
PG_FUNCTION_INFO_V1(master_modify_multiple_shards); PG_FUNCTION_INFO_V1(master_modify_multiple_shards);
@ -85,6 +86,7 @@ master_modify_multiple_shards(PG_FUNCTION_ARGS)
List *taskList = NIL; List *taskList = NIL;
int32 affectedTupleCount = 0; int32 affectedTupleCount = 0;
CmdType operation = CMD_UNKNOWN; CmdType operation = CMD_UNKNOWN;
TaskType taskType = TASK_TYPE_INVALID_FIRST;
#if (PG_VERSION_NUM >= 100000) #if (PG_VERSION_NUM >= 100000)
RawStmt *rawStmt = (RawStmt *) ParseTreeRawStmt(queryString); RawStmt *rawStmt = (RawStmt *) ParseTreeRawStmt(queryString);
queryTreeNode = rawStmt->stmt; queryTreeNode = rawStmt->stmt;
@ -159,6 +161,12 @@ master_modify_multiple_shards(PG_FUNCTION_ARGS)
{ {
RaiseDeferredError(error, ERROR); RaiseDeferredError(error, ERROR);
} }
taskType = MODIFY_TASK;
}
else
{
taskType = DDL_TASK;
} }
/* reject queries with a returning list */ /* reject queries with a returning list */
@ -179,7 +187,7 @@ master_modify_multiple_shards(PG_FUNCTION_ARGS)
CHECK_FOR_INTERRUPTS(); CHECK_FOR_INTERRUPTS();
taskList = taskList =
ModifyMultipleShardsTaskList(modifyQuery, prunedShardIntervalList); ModifyMultipleShardsTaskList(modifyQuery, prunedShardIntervalList, taskType);
if (MultiShardConnectionType == SEQUENTIAL_CONNECTION) if (MultiShardConnectionType == SEQUENTIAL_CONNECTION)
{ {
@ -200,7 +208,7 @@ master_modify_multiple_shards(PG_FUNCTION_ARGS)
* given list of shards. * given list of shards.
*/ */
static List * static List *
ModifyMultipleShardsTaskList(Query *query, List *shardIntervalList) ModifyMultipleShardsTaskList(Query *query, List *shardIntervalList, TaskType taskType)
{ {
List *taskList = NIL; List *taskList = NIL;
ListCell *shardIntervalCell = NULL; ListCell *shardIntervalCell = NULL;
@ -223,7 +231,7 @@ ModifyMultipleShardsTaskList(Query *query, List *shardIntervalList)
task = CitusMakeNode(Task); task = CitusMakeNode(Task);
task->jobId = jobId; task->jobId = jobId;
task->taskId = taskId++; task->taskId = taskId++;
task->taskType = MODIFY_TASK; task->taskType = taskType;
task->queryString = shardQueryString->data; task->queryString = shardQueryString->data;
task->dependedTaskList = NULL; task->dependedTaskList = NULL;
task->replicationModel = REPLICATION_MODEL_INVALID; task->replicationModel = REPLICATION_MODEL_INVALID;

View File

@ -1122,13 +1122,11 @@ SELECT relation::regclass, locktype, mode FROM pg_locks WHERE relation::regclass
partitioning_locks | relation | AccessShareLock partitioning_locks | relation | AccessShareLock
partitioning_locks_2009 | relation | AccessExclusiveLock partitioning_locks_2009 | relation | AccessExclusiveLock
partitioning_locks_2009 | relation | AccessShareLock partitioning_locks_2009 | relation | AccessShareLock
partitioning_locks_2009 | relation | RowExclusiveLock
partitioning_locks_2009 | relation | ShareLock partitioning_locks_2009 | relation | ShareLock
partitioning_locks_2010 | relation | AccessExclusiveLock partitioning_locks_2010 | relation | AccessExclusiveLock
partitioning_locks_2010 | relation | AccessShareLock partitioning_locks_2010 | relation | AccessShareLock
partitioning_locks_2010 | relation | RowExclusiveLock
partitioning_locks_2010 | relation | ShareLock partitioning_locks_2010 | relation | ShareLock
(10 rows) (8 rows)
COMMIT; COMMIT;
-- test shard resource locks with master_modify_multiple_shards -- test shard resource locks with master_modify_multiple_shards

View File

@ -584,13 +584,34 @@ BEGIN;
(2 rows) (2 rows)
ROLLBACK; ROLLBACK;
-- FIXME: TRUNCATE should be DDL -- TRUNCATE should be DDL
BEGIN; BEGIN;
TRUNCATE table_1; TRUNCATE table_1;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1') ORDER BY 1; SELECT * FROM relation_acesses WHERE table_name IN ('table_1') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
------------+---------------+-----------------+-------------- ------------+---------------+--------------+-----------------
table_1 | not_accessed | parallel_access | not_accessed table_1 | not_accessed | not_accessed | parallel_access
(1 row)
ROLLBACK;
-- TRUNCATE can be a sequential DDL
BEGIN;
SET LOCAL citus.multi_shard_modify_mode = 'sequential';
TRUNCATE table_1;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1') ORDER BY 1;
table_name | select_access | dml_access | ddl_access
------------+---------------+--------------+-------------------
table_1 | not_accessed | not_accessed | sequential_access
(1 row)
ROLLBACK;
-- TRUNCATE on a reference table should be sequential
BEGIN;
TRUNCATE table_6;
SELECT * FROM relation_acesses WHERE table_name IN ('table_6') ORDER BY 1;
table_name | select_access | dml_access | ddl_access
------------+---------------+--------------+-------------------
table_6 | not_accessed | not_accessed | sequential_access
(1 row) (1 row)
ROLLBACK; ROLLBACK;
@ -674,9 +695,9 @@ BEGIN;
NOTICE: truncate cascades to table "table_2" NOTICE: truncate cascades to table "table_2"
SELECT * FROM relation_acesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1; SELECT * FROM relation_acesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
------------+---------------+-----------------+-------------- ------------+---------------+--------------+-----------------
table_1 | not_accessed | parallel_access | not_accessed table_1 | not_accessed | not_accessed | parallel_access
table_2 | not_accessed | parallel_access | not_accessed table_2 | not_accessed | not_accessed | parallel_access
(2 rows) (2 rows)
ROLLBACK; ROLLBACK;

View File

@ -351,12 +351,25 @@ BEGIN;
SELECT * FROM relation_acesses WHERE table_name IN ('table_6', 'table_1'); SELECT * FROM relation_acesses WHERE table_name IN ('table_6', 'table_1');
ROLLBACK; ROLLBACK;
-- FIXME: TRUNCATE should be DDL -- TRUNCATE should be DDL
BEGIN; BEGIN;
TRUNCATE table_1; TRUNCATE table_1;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1') ORDER BY 1; SELECT * FROM relation_acesses WHERE table_name IN ('table_1') ORDER BY 1;
ROLLBACK; ROLLBACK;
-- TRUNCATE can be a sequential DDL
BEGIN;
SET LOCAL citus.multi_shard_modify_mode = 'sequential';
TRUNCATE table_1;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1') ORDER BY 1;
ROLLBACK;
-- TRUNCATE on a reference table should be sequential
BEGIN;
TRUNCATE table_6;
SELECT * FROM relation_acesses WHERE table_name IN ('table_6') ORDER BY 1;
ROLLBACK;
-- creating foreign keys should consider adding the placement accesses for the referenced table -- creating foreign keys should consider adding the placement accesses for the referenced table
ALTER TABLE table_1 ADD CONSTRAINT table_1_u UNIQUE (key); ALTER TABLE table_1 ADD CONSTRAINT table_1_u UNIQUE (key);
BEGIN; BEGIN;