From a5544879f501420d941768e16e6b88828c3216ff Mon Sep 17 00:00:00 2001
From: Dmitry Simonenko <pmwkaa@gmail.com>
Date: Mon, 31 Aug 2015 15:23:38 +0300
Subject: [PATCH] fix for #1008: assertion if insert of wrong type

---
 src/box/sophia_engine.cc        | 10 ++++-
 test/sophia/constraint.result   | 76 +++++++++++++++++++++++++++++++++
 test/sophia/constraint.test.lua | 24 +++++++++++
 test/sophia/gh.result           | 14 ++++++
 test/sophia/gh.test.lua         |  7 +++
 5 files changed, 129 insertions(+), 2 deletions(-)
 create mode 100644 test/sophia/constraint.result
 create mode 100644 test/sophia/constraint.test.lua

diff --git a/src/box/sophia_engine.cc b/src/box/sophia_engine.cc
index d3e612ffbd..d7c39d9723 100644
--- a/src/box/sophia_engine.cc
+++ b/src/box/sophia_engine.cc
@@ -97,9 +97,17 @@ struct tuple *
 SophiaSpace::executeReplace(struct txn *txn, struct space *space,
                             struct request *request)
 {
+	SophiaIndex *index = (SophiaIndex *)index_find(space, 0);
+
 	space_validate_tuple_raw(space, request->tuple);
 	tuple_field_count_validate(space->format, request->tuple);
 
+	int size = request->tuple_end - request->tuple;
+	const char *key =
+		tuple_field_raw(request->tuple, size,
+		                index->key_def->parts[0].fieldno);
+	primary_key_validate(index->key_def, key, index->key_def->part_count);
+
 	/* Switch from INSERT to REPLACE during recovery.
 	 *
 	 * Database might hold newer key version than currenly
@@ -111,8 +119,6 @@ SophiaSpace::executeReplace(struct txn *txn, struct space *space,
 		if (engine->recovery_complete)
 			mode = DUP_INSERT;
 	}
-	SophiaIndex *index =
-		(SophiaIndex *)index_find(space, 0);
 	index->replace_or_insert(request->tuple, request->tuple_end, mode);
 	txn_commit_stmt(txn);
 	return NULL;
diff --git a/test/sophia/constraint.result b/test/sophia/constraint.result
new file mode 100644
index 0000000000..9dabea6c03
--- /dev/null
+++ b/test/sophia/constraint.result
@@ -0,0 +1,76 @@
+-- key type validations (str, num)
+space = box.schema.space.create('test', { engine = 'sophia' })
+---
+...
+index = space:create_index('primary', { type = 'tree', parts = {1, 'str'} })
+---
+...
+space:insert{1}
+---
+- error: 'Supplied key type of part 0 does not match index part type: expected STR'
+...
+space:replace{1}
+---
+- error: 'Supplied key type of part 0 does not match index part type: expected STR'
+...
+space:delete{1}
+---
+- error: 'Supplied key type of part 0 does not match index part type: expected STR'
+...
+space:update(1, {{'=', 1, 101}})
+---
+- error: 'Supplied key type of part 0 does not match index part type: expected STR'
+...
+space:upsert(1, {{'+', 1, 10}}, {0})
+---
+- error: 'Supplied key type of part 0 does not match index part type: expected STR'
+...
+space:get{1}
+---
+- error: 'Supplied key type of part 0 does not match index part type: expected STR'
+...
+index:pairs(1, {iterator = 'GE'})
+---
+- error: 'Supplied key type of part 0 does not match index part type: expected STR'
+...
+space:drop()
+---
+...
+-- key type validations (num, str)
+space = box.schema.space.create('test', { engine = 'sophia' })
+---
+...
+index = space:create_index('primary', { type = 'tree', parts = {1, 'num'} })
+---
+...
+space:insert{'A'}
+---
+- error: 'Supplied key type of part 0 does not match index part type: expected NUM'
+...
+space:replace{'A'}
+---
+- error: 'Supplied key type of part 0 does not match index part type: expected NUM'
+...
+space:delete{'A'}
+---
+- error: 'Supplied key type of part 0 does not match index part type: expected NUM'
+...
+space:update('A', {{'=', 1, 101}})
+---
+- error: 'Supplied key type of part 0 does not match index part type: expected NUM'
+...
+space:upsert('A', {{'+', 1, 10}}, {0})
+---
+- error: 'Supplied key type of part 0 does not match index part type: expected NUM'
+...
+space:get{'A'}
+---
+- error: 'Supplied key type of part 0 does not match index part type: expected NUM'
+...
+index:pairs('A', {iterator = 'GE'})
+---
+- error: 'Supplied key type of part 0 does not match index part type: expected NUM'
+...
+space:drop()
+---
+...
diff --git a/test/sophia/constraint.test.lua b/test/sophia/constraint.test.lua
new file mode 100644
index 0000000000..216b325a8e
--- /dev/null
+++ b/test/sophia/constraint.test.lua
@@ -0,0 +1,24 @@
+
+-- key type validations (str, num)
+space = box.schema.space.create('test', { engine = 'sophia' })
+index = space:create_index('primary', { type = 'tree', parts = {1, 'str'} })
+space:insert{1}
+space:replace{1}
+space:delete{1}
+space:update(1, {{'=', 1, 101}})
+space:upsert(1, {{'+', 1, 10}}, {0})
+space:get{1}
+index:pairs(1, {iterator = 'GE'})
+space:drop()
+
+-- key type validations (num, str)
+space = box.schema.space.create('test', { engine = 'sophia' })
+index = space:create_index('primary', { type = 'tree', parts = {1, 'num'} })
+space:insert{'A'}
+space:replace{'A'}
+space:delete{'A'}
+space:update('A', {{'=', 1, 101}})
+space:upsert('A', {{'+', 1, 10}}, {0})
+space:get{'A'}
+index:pairs('A', {iterator = 'GE'})
+space:drop()
diff --git a/test/sophia/gh.result b/test/sophia/gh.result
index 3e46a144a9..7c8f9e5139 100644
--- a/test/sophia/gh.result
+++ b/test/sophia/gh.result
@@ -136,3 +136,17 @@ s.index.primary:alter({parts={1,'NUM'}})
 s:drop()
 ---
 ...
+-- gh-1008: assertion if insert of wrong type
+s = box.schema.space.create('t', {engine='sophia'})
+---
+...
+i = s:create_index('primary',{parts={1, 'STR'}})
+---
+...
+box.space.t:insert{1,'A'}
+---
+- error: 'Supplied key type of part 0 does not match index part type: expected STR'
+...
+s:drop()
+---
+...
diff --git a/test/sophia/gh.test.lua b/test/sophia/gh.test.lua
index 3ef3f0b1a0..d820e91121 100644
--- a/test/sophia/gh.test.lua
+++ b/test/sophia/gh.test.lua
@@ -56,3 +56,10 @@ i = s:create_index('primary',{})
 s:insert{5}
 s.index.primary:alter({parts={1,'NUM'}})
 s:drop()
+
+
+-- gh-1008: assertion if insert of wrong type
+s = box.schema.space.create('t', {engine='sophia'})
+i = s:create_index('primary',{parts={1, 'STR'}})
+box.space.t:insert{1,'A'}
+s:drop()
-- 
GitLab