From 3e1b734ba78abed5c50ffcf41993dc43c384f147 Mon Sep 17 00:00:00 2001
From: Vladimir Davydov <vdavydov.dev@gmail.com>
Date: Tue, 20 Jun 2017 16:00:35 +0300
Subject: [PATCH] alter: disallow truncation of system spaces

It is unsafe, because system spaces use triggers to keep records in sync
with internal objects while space truncation doesn't invoke triggers.

Closes #2523
---
 src/box/alter.cc              |  9 +++++++++
 src/box/errcode.h             |  1 +
 test/box/misc.result          |  1 +
 test/engine/truncate.result   | 11 +++++++++++
 test/engine/truncate.test.lua |  6 ++++++
 5 files changed, 28 insertions(+)

diff --git a/src/box/alter.cc b/src/box/alter.cc
index 7530aff1dd..04c02a377d 100644
--- a/src/box/alter.cc
+++ b/src/box/alter.cc
@@ -1422,6 +1422,15 @@ on_replace_dd_truncate(struct trigger * /* trigger */, void *event)
 		return;
 	}
 
+	/*
+	 * System spaces use triggers to keep records in sync
+	 * with internal objects. Since space truncation doesn't
+	 * invoke triggers, we don't permit it for system spaces.
+	 */
+	if (space_is_system(old_space))
+		tnt_raise(ClientError, ER_TRUNCATE_SYSTEM_SPACE,
+			  space_name(old_space));
+
 	/*
 	 * Truncate counter is updated - truncate the space.
 	 */
diff --git a/src/box/errcode.h b/src/box/errcode.h
index 8fb1fa8c26..ce7078b6fc 100644
--- a/src/box/errcode.h
+++ b/src/box/errcode.h
@@ -189,6 +189,7 @@ struct errcode_record {
 	/*134 */_(ER_CHECKPOINT_ROLLBACK,	"Can't start a checkpoint while in cascading rollback") \
 	/*135 */_(ER_VY_QUOTA_TIMEOUT,		"Timed out waiting for Vinyl memory quota") \
 	/*136 */_(ER_PARTIAL_KEY,		"%s index  does not support selects via a partial key (expected %u parts, got %u). Please Consider changing index type to TREE.") \
+	/*137 */_(ER_TRUNCATE_SYSTEM_SPACE,	"Can't truncate a system space, space '%s'") \
 
 /*
  * !IMPORTANT! Please follow instructions at start of the file
diff --git a/test/box/misc.result b/test/box/misc.result
index cf56fd4750..1db87035e1 100644
--- a/test/box/misc.result
+++ b/test/box/misc.result
@@ -377,6 +377,7 @@ t;
   - 'box.error.SYSTEM : 115'
   - 'box.error.KEY_PART_IS_TOO_LONG : 118'
   - 'box.error.injection : table: <address>
+  - 'box.error.TRUNCATE_SYSTEM_SPACE : 137'
   - 'box.error.VY_QUOTA_TIMEOUT : 135'
   - 'box.error.USER_MAX : 56'
   - 'box.error.INVALID_XLOG_TYPE : 125'
diff --git a/test/engine/truncate.result b/test/engine/truncate.result
index ace1cd2cdd..ea8a2c05b7 100644
--- a/test/engine/truncate.result
+++ b/test/engine/truncate.result
@@ -64,6 +64,17 @@ box.space.test:drop()
 ---
 ...
 --
+-- Check that truncation of system spaces is not permitted.
+--
+box.space._space:truncate()
+---
+- error: Can't truncate a system space, space '_space'
+...
+box.space._index:truncate()
+---
+- error: Can't truncate a system space, space '_index'
+...
+--
 -- Truncate space with no indexes.
 --
 s = box.schema.create_space('test', {engine = engine})
diff --git a/test/engine/truncate.test.lua b/test/engine/truncate.test.lua
index 7cef3ba225..65b2a9fc78 100644
--- a/test/engine/truncate.test.lua
+++ b/test/engine/truncate.test.lua
@@ -27,6 +27,12 @@ box.space.test:truncate()
 box.space.test:select()
 box.space.test:drop()
 
+--
+-- Check that truncation of system spaces is not permitted.
+--
+box.space._space:truncate()
+box.space._index:truncate()
+
 --
 -- Truncate space with no indexes.
 --
-- 
GitLab