Skip to content

Commit 72763f9

Browse files
committed
vinyl: fix run iterator skipping tuples following non-terminal statement
If a run iterator is positioned at a non-terminal statement (UPSERT or UPDATE), `vy_run_iterator_next()` will iterate over older statements with the same key using `vy_run_iterator_next_lsn()` to build the key history. While doing so, it may reach the end of the run file (if the current key is the last in the run). This would stop iteration permanently, which is apparently wrong for reverse iterators (LE or LT): if this happens the run iterator won't return any keys preceding the last one in the run file. Fix this by removing `vy_run_iterator_stop()` from `vy_run_iterator_next_lsn()`. Part of tarantool#10109 NO_DOC=bug fix NO_CHANGELOG=next commit
1 parent 9b63ced commit 72763f9

File tree

2 files changed

+40
-3
lines changed

2 files changed

+40
-3
lines changed

src/box/vy_run.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1557,10 +1557,8 @@ vy_run_iterator_next_lsn(struct vy_run_iterator *itr, struct vy_entry *ret)
15571557

15581558
struct vy_run_iterator_pos next_pos;
15591559
next:
1560-
if (vy_run_iterator_next_pos(itr, ITER_GE, &next_pos) != 0) {
1561-
vy_run_iterator_stop(itr);
1560+
if (vy_run_iterator_next_pos(itr, ITER_GE, &next_pos) != 0)
15621561
return 0;
1563-
}
15641562

15651563
struct vy_entry next;
15661564
if (vy_run_iterator_read(itr, next_pos, &next) != 0)
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
local server = require('luatest.server')
2+
local t = require('luatest')
3+
4+
local g = t.group()
5+
6+
g.before_all(function(cg)
7+
t.tarantool.skip_if_not_debug()
8+
cg.server = server:new()
9+
cg.server:start()
10+
end)
11+
12+
g.after_all(function(cg)
13+
cg.server:drop()
14+
end)
15+
16+
g.after_each(function(cg)
17+
cg.server:exec(function()
18+
if box.space.test ~= nil then
19+
box.space.test:drop()
20+
end
21+
box.error.injection.set('ERRINJ_VY_COMPACTION_DELAY', false)
22+
end)
23+
end)
24+
25+
g.test_read_upsert = function(cg)
26+
cg.server:exec(function()
27+
box.error.injection.set('ERRINJ_VY_COMPACTION_DELAY', true)
28+
local s = box.schema.create_space('test', {engine = 'vinyl'})
29+
s:create_index('pk')
30+
s:insert({100})
31+
box.snapshot()
32+
s:upsert({200}, {})
33+
s:upsert({300}, {})
34+
s:upsert({400}, {})
35+
box.snapshot()
36+
t.assert_equals(s:select({500}, {iterator = 'lt', fullscan = true}),
37+
{{400}, {300}, {200}, {100}})
38+
end)
39+
end

0 commit comments

Comments
 (0)