From 5554f25e5c9750d3bf07a38614ce321b7848e317 Mon Sep 17 00:00:00 2001
From: Roman Tsisyk <roman@tarantool.org>
Date: Fri, 15 Sep 2017 18:59:50 +0300
Subject: [PATCH] alter: add the test cases for invalid field types

Needed for #2754
---
 src/box/field_def.c                 |  7 +------
 src/box/index_def.c                 |  3 +--
 src/box/key_def.cc                  |  2 +-
 src/box/memtx_space.cc              |  9 +++++---
 src/box/vinyl_space.cc              | 12 +++++++++++
 test/box/alter_limits.result        | 32 ++++++++++++++++++++++++++++-
 test/box/alter_limits.test.lua      |  8 +++++++-
 test/box/rtree_misc.result          | 16 +++++++--------
 test/engine/indices_any_type.result |  4 ++--
 test/engine/iterator.result         |  2 +-
 test/vinyl/ddl.result               | 30 +++++++++++++++++++++++++++
 test/vinyl/ddl.test.lua             |  8 ++++++++
 12 files changed, 108 insertions(+), 25 deletions(-)

diff --git a/src/box/field_def.c b/src/box/field_def.c
index 5e6dbae837..fa39d5a86f 100644
--- a/src/box/field_def.c
+++ b/src/box/field_def.c
@@ -47,12 +47,7 @@ enum field_type
 field_type_by_name(const char *name)
 {
 	enum field_type field_type = STR2ENUM(field_type, name);
-	/*
-	 * FIELD_TYPE_ANY can't be used as type of indexed field,
-	 * because it is internal type used only for filling
-	 * struct tuple_format.fields array.
-	 */
-	if (field_type != field_type_MAX && field_type != FIELD_TYPE_ANY)
+	if (field_type != field_type_MAX)
 		return field_type;
 	/* 'num' and 'str' in _index are deprecated since Tarantool 1.7 */
 	if (strcasecmp(name, "num") == 0)
diff --git a/src/box/index_def.c b/src/box/index_def.c
index 1f7d39d0cc..53689caa20 100644
--- a/src/box/index_def.c
+++ b/src/box/index_def.c
@@ -226,8 +226,7 @@ index_def_is_valid(struct index_def *index_def, const char *space_name)
 		return false;
 	}
 	for (uint32_t i = 0; i < index_def->key_def->part_count; i++) {
-		assert(index_def->key_def->parts[i].type > FIELD_TYPE_ANY &&
-		       index_def->key_def->parts[i].type < field_type_MAX);
+		assert(index_def->key_def->parts[i].type < field_type_MAX);
 		if (index_def->key_def->parts[i].fieldno > BOX_INDEX_FIELD_MAX) {
 			diag_set(ClientError, ER_MODIFY_INDEX, index_def->name,
 				 space_name, "field no is too big");
diff --git a/src/box/key_def.cc b/src/box/key_def.cc
index 725abfa12c..6132ac5a8e 100644
--- a/src/box/key_def.cc
+++ b/src/box/key_def.cc
@@ -139,7 +139,7 @@ key_def_set_part(struct key_def *def, uint32_t part_no,
 		 uint32_t fieldno, enum field_type type)
 {
 	assert(part_no < def->part_count);
-	assert(type > FIELD_TYPE_ANY && type < field_type_MAX);
+	assert(type < field_type_MAX);
 	def->parts[part_no].fieldno = fieldno;
 	def->parts[part_no].type = type;
 	column_mask_set_fieldno(&def->column_mask, fieldno);
diff --git a/src/box/memtx_space.cc b/src/box/memtx_space.cc
index 83c3491c45..fe2373a406 100644
--- a/src/box/memtx_space.cc
+++ b/src/box/memtx_space.cc
@@ -580,13 +580,16 @@ MemtxSpace::checkIndexDef(struct space *space, struct index_def *index_def)
 		break;
 	}
 	/* Only HASH and TREE indexes checks parts there */
-	/* Just check that there are no ARRAY parts */
+	/* Check that there are no ANY, ARRAY, MAP parts */
 	for (uint32_t i = 0; i < index_def->key_def->part_count; i++) {
-		if (index_def->key_def->parts[i].type == FIELD_TYPE_ARRAY) {
+		struct key_part *part = &index_def->key_def->parts[i];
+		if (part->type <= FIELD_TYPE_ANY ||
+		    part->type >= FIELD_TYPE_ARRAY) {
 			tnt_raise(ClientError, ER_MODIFY_INDEX,
 				  index_def->name,
 				  space_name(space),
-				  "ARRAY field type is not supported");
+				  tt_sprintf("field type '%s' is not supported",
+					     field_type_strs[part->type]));
 		}
 	}
 }
diff --git a/src/box/vinyl_space.cc b/src/box/vinyl_space.cc
index 12a235646f..9fb2273386 100644
--- a/src/box/vinyl_space.cc
+++ b/src/box/vinyl_space.cc
@@ -172,6 +172,18 @@ VinylSpace::checkIndexDef(struct space *space, struct index_def *index_def)
 		          index_def->name,
 			  space_name(space));
 	}
+	/* Check that there are no ANY, ARRAY, MAP parts */
+	for (uint32_t i = 0; i < index_def->key_def->part_count; i++) {
+		struct key_part *part = &index_def->key_def->parts[i];
+		if (part->type <= FIELD_TYPE_ANY ||
+		    part->type >= FIELD_TYPE_ARRAY) {
+			tnt_raise(ClientError, ER_MODIFY_INDEX,
+				  index_def->name,
+				  space_name(space),
+				  tt_sprintf("field type '%s' is not supported",
+					     field_type_strs[part->type]));
+		}
+	}
 }
 
 Index *
diff --git a/test/box/alter_limits.result b/test/box/alter_limits.result
index ed65baa856..de41414116 100644
--- a/test/box/alter_limits.result
+++ b/test/box/alter_limits.result
@@ -432,11 +432,41 @@ index = s:create_index('test', { type = 'hash', parts = { 1 }})
     pairs'
 ...
 -- unknown field type
-index = s:create_index('test', { type = 'hash', parts = { 1, 'nosuchtype' }})
+index = s:create_index('test', { type = 'hash', parts = { 2, 'nosuchtype' }})
 ---
 - error: 'Wrong index parts: unknown field type; expected field1 id (number), field1
     type (string), ...'
 ...
+index = s:create_index('test', { type = 'hash', parts = { 2, 'any' }})
+---
+- error: 'Can''t create or modify index ''test'' in space ''test'': field type ''any''
+    is not supported'
+...
+index = s:create_index('test', { type = 'hash', parts = { 2, 'array' }})
+---
+- error: 'Can''t create or modify index ''test'' in space ''test'': field type ''array''
+    is not supported'
+...
+index = s:create_index('test', { type = 'hash', parts = { 2, 'map' }})
+---
+- error: 'Can''t create or modify index ''test'' in space ''test'': field type ''map''
+    is not supported'
+...
+index = s:create_index('test', { type = 'rtree', parts = { 2, 'nosuchtype' }})
+---
+- error: 'Wrong index parts: unknown field type; expected field1 id (number), field1
+    type (string), ...'
+...
+index = s:create_index('test', { type = 'rtree', parts = { 2, 'any' }})
+---
+- error: 'Can''t create or modify index ''test'' in space ''test'': RTREE index field
+    type must be ARRAY'
+...
+index = s:create_index('test', { type = 'rtree', parts = { 2, 'map' }})
+---
+- error: 'Can''t create or modify index ''test'' in space ''test'': RTREE index field
+    type must be ARRAY'
+...
 -- bad field no
 index = s:create_index('test', { type = 'hash', parts = { 'qq', 'nosuchtype' }})
 ---
diff --git a/test/box/alter_limits.test.lua b/test/box/alter_limits.test.lua
index ec6fb02aac..cb8acdff0e 100644
--- a/test/box/alter_limits.test.lua
+++ b/test/box/alter_limits.test.lua
@@ -155,7 +155,13 @@ index = s:create_index('test', { type = 'hash', parts = {}})
 -- part count must be positive
 index = s:create_index('test', { type = 'hash', parts = { 1 }})
 -- unknown field type
-index = s:create_index('test', { type = 'hash', parts = { 1, 'nosuchtype' }})
+index = s:create_index('test', { type = 'hash', parts = { 2, 'nosuchtype' }})
+index = s:create_index('test', { type = 'hash', parts = { 2, 'any' }})
+index = s:create_index('test', { type = 'hash', parts = { 2, 'array' }})
+index = s:create_index('test', { type = 'hash', parts = { 2, 'map' }})
+index = s:create_index('test', { type = 'rtree', parts = { 2, 'nosuchtype' }})
+index = s:create_index('test', { type = 'rtree', parts = { 2, 'any' }})
+index = s:create_index('test', { type = 'rtree', parts = { 2, 'map' }})
 -- bad field no
 index = s:create_index('test', { type = 'hash', parts = { 'qq', 'nosuchtype' }})
 -- big field no
diff --git a/test/box/rtree_misc.result b/test/box/rtree_misc.result
index f787836989..4ee9a54570 100644
--- a/test/box/rtree_misc.result
+++ b/test/box/rtree_misc.result
@@ -32,13 +32,13 @@ i = s:create_index('spatial', { type = 'rtree', unique = false, parts = {1, 'arr
 -- tree and hash indexes over array field is not possible
 i = s:create_index('primary', { type = 'tree', parts = {1, 'array'}})
 ---
-- error: 'Can''t create or modify index ''primary'' in space ''spatial'': ARRAY field
-    type is not supported'
+- error: 'Can''t create or modify index ''primary'' in space ''spatial'': field type
+    ''array'' is not supported'
 ...
 i = s:create_index('primary', { type = 'hash', parts = {1, 'array'}})
 ---
-- error: 'Can''t create or modify index ''primary'' in space ''spatial'': ARRAY field
-    type is not supported'
+- error: 'Can''t create or modify index ''primary'' in space ''spatial'': field type
+    ''array'' is not supported'
 ...
 -- normal indexes
 i = s:create_index('primary', { type = 'tree', parts = {1, 'unsigned'}})
@@ -145,8 +145,8 @@ s.index.spatial:alter({unique = true})
 ...
 s.index.spatial:alter({type = 'tree'})
 ---
-- error: 'Can''t create or modify index ''spatial'' in space ''spatial'': ARRAY field
-    type is not supported'
+- error: 'Can''t create or modify index ''spatial'' in space ''spatial'': field type
+    ''array'' is not supported'
 ...
 box.space[box.schema.SPACE_ID]:update({s.id}, {{"=", 4, 'vinyl'}})
 ---
@@ -648,8 +648,8 @@ i = s:create_index('s', {type = 'rtree', parts = {2, 'array'}})
 ...
 i:alter{type = 'tree' }
 ---
-- error: 'Can''t create or modify index ''s'' in space ''s'': ARRAY field type is
-    not supported'
+- error: 'Can''t create or modify index ''s'' in space ''s'': field type ''array''
+    is not supported'
 ...
 i:alter{dimension = 3 }
 ---
diff --git a/test/engine/indices_any_type.result b/test/engine/indices_any_type.result
index 936dde0a2f..8158bda4e7 100644
--- a/test/engine/indices_any_type.result
+++ b/test/engine/indices_any_type.result
@@ -863,8 +863,8 @@ space = box.schema.space.create('test', {engine = engine})
 ...
 pk = space:create_index('primary', { parts = {1, 'any'} }) --
 ---
-- error: 'Wrong index parts: unknown field type; expected field1 id (number), field1
-    type (string), ...'
+- error: 'Can''t create or modify index ''primary'' in space ''test'': field type
+    ''any'' is not supported'
 ...
 space:insert({1})                                          -- must fail
 ---
diff --git a/test/engine/iterator.result b/test/engine/iterator.result
index 3ecc979426..df770cf5a5 100644
--- a/test/engine/iterator.result
+++ b/test/engine/iterator.result
@@ -4212,7 +4212,7 @@ s:replace{35}
 ...
 state, value = gen(param,state)
 ---
-- error: 'builtin/box/schema.lua:714: usage: next(param, state)'
+- error: 'builtin/box/schema.lua:715: usage: next(param, state)'
 ...
 value
 ---
diff --git a/test/vinyl/ddl.result b/test/vinyl/ddl.result
index e63801234f..f7b6ce26b0 100644
--- a/test/vinyl/ddl.result
+++ b/test/vinyl/ddl.result
@@ -656,3 +656,33 @@ box.commit()
 ---
 - error: Transaction has been aborted by conflict
 ...
+-- check invalid field types
+space = box.schema.space.create('test', { engine = 'vinyl' })
+---
+...
+pk = space:create_index('primary')
+---
+...
+index = space:create_index('test', { type = 'tree', parts = { 2, 'nosuchtype' }})
+---
+- error: 'Wrong index parts: unknown field type; expected field1 id (number), field1
+    type (string), ...'
+...
+index = space:create_index('test', { type = 'tree', parts = { 2, 'any' }})
+---
+- error: 'Can''t create or modify index ''test'' in space ''test'': field type ''any''
+    is not supported'
+...
+index = space:create_index('test', { type = 'tree', parts = { 2, 'array' }})
+---
+- error: 'Can''t create or modify index ''test'' in space ''test'': field type ''array''
+    is not supported'
+...
+index = space:create_index('test', { type = 'tree', parts = { 2, 'map' }})
+---
+- error: 'Can''t create or modify index ''test'' in space ''test'': field type ''map''
+    is not supported'
+...
+space:drop()
+---
+...
diff --git a/test/vinyl/ddl.test.lua b/test/vinyl/ddl.test.lua
index ad97b29018..ad31541722 100644
--- a/test/vinyl/ddl.test.lua
+++ b/test/vinyl/ddl.test.lua
@@ -255,3 +255,11 @@ _ = fiber.create(function () s:drop() ch:put(true) end)
 ch:get()
 box.commit()
 
+-- check invalid field types
+space = box.schema.space.create('test', { engine = 'vinyl' })
+pk = space:create_index('primary')
+index = space:create_index('test', { type = 'tree', parts = { 2, 'nosuchtype' }})
+index = space:create_index('test', { type = 'tree', parts = { 2, 'any' }})
+index = space:create_index('test', { type = 'tree', parts = { 2, 'array' }})
+index = space:create_index('test', { type = 'tree', parts = { 2, 'map' }})
+space:drop()
-- 
GitLab