-
Notifications
You must be signed in to change notification settings - Fork 376
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
vinyl: fix index name in duplicate key error message
The code setting ER_TUPLE_FOUND uses index_name_by_id() to find the index name, but it passes an index in the dense index map to it while the function expects an index in the sparse index map. Apparently, this doesn't work as expected after an index is removed from the middle of the index map. This bug was introduced by commit fc3834c ("vinyl: check key uniqueness before modifying tx write set"). Instead of just fixing the index passed to index_name_by_id(), we do a bit of refactoring. We stop passing index_name and space_name to vy_check_is_unique_*() functions and instead get them right before raising ER_TUPLE_FOUND. Note, to get the space name, we need to call space_by_id() but it should be fine because (a) the space is very likely to be cached as the last accessed one and (b) this is an error path so it isn't performance critical. We also drop index_name_by_id() and extract the index name from the LSM tree object. Closes #5975 NO_DOC=bug fix
- Loading branch information
Showing
5 changed files
with
88 additions
and
60 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
## bugfix/vinyl | ||
|
||
* Fixed a bug when a duplicate key error referred to a wrong index (gh-5975). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
local t = require('luatest') | ||
|
||
local server = require('luatest.server') | ||
|
||
local g = t.group(nil, t.helpers.matrix{engine = {'memtx', 'vinyl'}}) | ||
|
||
g.before_all(function(cg) | ||
cg.server = server:new() | ||
cg.server:start() | ||
end) | ||
|
||
g.after_all(function(cg) | ||
cg.server:drop() | ||
end) | ||
|
||
g.after_each(function(cg) | ||
cg.server:exec(function() | ||
if box.space.test ~= nil then | ||
box.space.test:drop() | ||
end | ||
end) | ||
end) | ||
|
||
g.test_duplicate_key_error = function(cg) | ||
cg.server:exec(function(engine) | ||
local function check_err(space_name, index_name, old_tuple, new_tuple) | ||
local space = box.space[space_name] | ||
t.assert_error_covers({ | ||
type = 'ClientError', | ||
code = box.error.TUPLE_FOUND, | ||
message = string.format( | ||
'Duplicate key exists in unique index "%s" in space ' .. | ||
'"%s" with old tuple - %s and new tuple - %s', | ||
index_name, space_name, | ||
box.tuple.new(old_tuple), box.tuple.new(new_tuple)), | ||
space = space_name, | ||
index = index_name, | ||
old_tuple = old_tuple, | ||
new_tuple = new_tuple, | ||
}, space.insert, space, new_tuple) | ||
end | ||
|
||
local s = box.schema.space.create('test', { | ||
engine = engine, | ||
format = { | ||
{name = 'a', type = 'unsigned'}, | ||
{name = 'b', type = 'unsigned'}, | ||
}, | ||
}) | ||
s:create_index('pk', {parts = {'a'}}) | ||
s:create_index('i1', {parts = {'b'}, unique = true}) | ||
s:create_index('i2', {parts = {'b'}, unique = true}) | ||
s:insert({1, 1}) | ||
|
||
check_err('test', 'pk', {1, 1}, {1, 2}) | ||
check_err('test', 'i1', {1, 1}, {2, 1}) | ||
t.assert_equals(s:select({}, {fullscan = true}), {{1, 1}}) | ||
s.index.i1:drop() | ||
check_err('test', 'pk', {1, 1}, {1, 2}) | ||
check_err('test', 'i2', {1, 1}, {2, 1}) | ||
t.assert_equals(s:select({}, {fullscan = true}), {{1, 1}}) | ||
s.index.i2:drop() | ||
check_err('test', 'pk', {1, 1}, {1, 2}) | ||
s:insert({2, 1}) | ||
t.assert_equals(s:select({}, {fullscan = true}), {{1, 1}, {2, 1}}) | ||
end, {cg.params.engine}) | ||
end |