From 8ae450077341e53eda0f59acfbf044d5525f2196 Mon Sep 17 00:00:00 2001
From: Magomed Kostoev <mkostoevr@yandex.ru>
Date: Wed, 3 May 2023 14:13:22 +0300
Subject: [PATCH] box: disallow to drop system spaces

The patch adds a new check to the _space on_replace trigger failing
on attempt to drop a system table.

Closes #5279

NO_DOC=bugfix
---
 .../unreleased/gh-5279-system-space-removal.md    |  3 +++
 src/box/alter.cc                                  |  7 +++++++
 test/box/alter.result                             | 15 +++++++++++----
 test/box/alter.test.lua                           | 10 +++++++---
 4 files changed, 28 insertions(+), 7 deletions(-)
 create mode 100644 changelogs/unreleased/gh-5279-system-space-removal.md

diff --git a/changelogs/unreleased/gh-5279-system-space-removal.md b/changelogs/unreleased/gh-5279-system-space-removal.md
new file mode 100644
index 0000000000..41cc123ddd
--- /dev/null
+++ b/changelogs/unreleased/gh-5279-system-space-removal.md
@@ -0,0 +1,3 @@
+## bugfix/box
+
+- Fixed the ability to drop `_vinyl_deferred_delete` system space (gh-5279).
diff --git a/src/box/alter.cc b/src/box/alter.cc
index 29199285ec..f1c434ba0f 100644
--- a/src/box/alter.cc
+++ b/src/box/alter.cc
@@ -2136,6 +2136,13 @@ on_replace_dd_space(struct trigger * /* trigger */, void *event)
 		/* Check whether old_space is used somewhere. */
 		if (space_check_pinned(old_space) != 0)
 			return -1;
+		/* One can't just remove a system space. */
+		if (space_is_system(old_space)) {
+			diag_set(ClientError, ER_DROP_SPACE,
+				 space_name(old_space),
+				 "the space is a system space");
+			return -1;
+		}
 		/**
 		 * We need to unpin spaces that are referenced by deleted one.
 		 * Let's detach space constraints - they will be deleted
diff --git a/test/box/alter.result b/test/box/alter.result
index 8f7eaad52c..b2ac94d410 100644
--- a/test/box/alter.result
+++ b/test/box/alter.result
@@ -71,7 +71,7 @@ _space:insert{_index.id, ADMIN, '_index', 'memtx', 0, EMPTY_MAP, {}}
     "type": "array"}]] and new tuple - [288, 1, "_index", "memtx", 0, {}, []]'
 ...
 --
--- Can't drop a system space
+-- Can't drop a space with an index
 --
 _space:delete{_space.id}
 ---
@@ -82,6 +82,13 @@ _space:delete{_index.id}
 - error: 'Can''t drop space ''_index'': the space has indexes'
 ...
 --
+-- Can't drop a system space
+--
+_space:delete{box.schema.VINYL_DEFERRED_DELETE_ID}
+---
+- error: 'Can''t drop space ''_vinyl_deferred_delete'': the space is a system space'
+...
+--
 -- Can't change properties of a space
 --
 _space:update({_space.id}, {{'-', 1, 1}})
@@ -95,7 +102,7 @@ _space:update({_space.id}, {{'-', 1, 2}})
 --
 -- Create a space
 --
-t = _space:auto_increment{ADMIN, 'hello', 'memtx', 0, EMPTY_MAP, {}}
+t = _space:insert{box.internal.generate_space_id(), ADMIN, 'hello', 'memtx', 0, EMPTY_MAP, {}}
 ---
 ...
 -- Check that a space exists
@@ -104,7 +111,7 @@ space = box.space[t[1]]
 ...
 space.id
 ---
-- 381
+- 512
 ...
 space.field_count
 ---
@@ -149,7 +156,7 @@ space_deleted
 ...
 space:replace{0}
 ---
-- error: Space '381' does not exist
+- error: Space '512' does not exist
 ...
 err, res = pcall(function() return _index:insert{_space.id, 0, 'primary', 'tree', {unique=true}, {{0, 'unsigned'}}} end)
 ---
diff --git a/test/box/alter.test.lua b/test/box/alter.test.lua
index 522d9ea750..2b1923358f 100644
--- a/test/box/alter.test.lua
+++ b/test/box/alter.test.lua
@@ -29,11 +29,15 @@ err, res = pcall(function() return _space:insert{_space.id, ADMIN, '_space', 'me
 assert(res.code == box.error.TUPLE_FOUND)
 _space:insert{_index.id, ADMIN, '_index', 'memtx', 0, EMPTY_MAP, {}}
 --
--- Can't drop a system space
+-- Can't drop a space with an index
 --
 _space:delete{_space.id}
 _space:delete{_index.id}
 --
+-- Can't drop a system space
+--
+_space:delete{box.schema.VINYL_DEFERRED_DELETE_ID}
+--
 -- Can't change properties of a space
 --
 _space:update({_space.id}, {{'-', 1, 1}})
@@ -41,7 +45,7 @@ _space:update({_space.id}, {{'-', 1, 2}})
 --
 -- Create a space
 --
-t = _space:auto_increment{ADMIN, 'hello', 'memtx', 0, EMPTY_MAP, {}}
+t = _space:insert{box.internal.generate_space_id(), ADMIN, 'hello', 'memtx', 0, EMPTY_MAP, {}}
 -- Check that a space exists
 space = box.space[t[1]]
 space.id
@@ -660,4 +664,4 @@ s.index.test1:bsize() < s.index.test2:bsize()
 s.index.test1:bsize() == s.index.test33:bsize()
 s.index.test1:bsize() < s.index.test4:bsize()
 
-s:drop()
\ No newline at end of file
+s:drop()
-- 
GitLab