-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
scan: fix filter erroneous early exit
The issue described below is related to the read operations which allows to scan: `crud.select`, `crud.pairs`, `crud.count`, `readview:select` and `readview:pairs`. The erroneous behavior reported by [1] and #418 is as follows: - result changes when reordering operation conditions; - when `>=` condition operation is changed to `=`, there are more rows in the result. The reason is as follows. Scanning read operates with two entities: an iterator and a filter. The iterator includes an index, a starting value and iterator type (EQ, GT, etc.). The iterator is built from conditions, if possible, otherwise primary index is used. Remaining conditions form the filter, so the actual result satisfies all operation conditions. The filter supports early exit. Let's consider the following example. For `crud.select(space, {{'>=', 'id', 1}, {'<=', 'id', 10}})`, where `id` is an index (or an indexed field), the iterator uses index `id`, starts from key = `1` and goes by GE rules, covering [1, +inf) ordered keys. On the other hand, when iterator reaches the tuple with `id` = `11`, all tuples after this one will never satisfy the second condition, because our iterator yields tuples sorted by `id` (due to underlying index). So filter tells than there is no reason to scan anymore, and we finish the scanning procedure. Before this patch, the function behind early exit decision had worked as follows: "if the condition is an index, we go in forward (reverse) order and `<=` or `<` (`>=` or `>`) condition is violated, there is no reason to scan anymore". But the valid approach is "if the condition is SCANNING index...". Before this patch, filter had assumed that if the condition for index is specified, tuples are ordered, but it works only if iterator uses the same index as in the condition. This patch fixes the issue. The erroneous behavior may happen in the following case: - there are multiple conditions, - there are at least two different index operands, - non-scanning index condition uses `<=`, `<`, `>=` or `>` operation. 1. https://jira.vk.team/browse/TNT-941 Closes #418
- Loading branch information
1 parent
495ddee
commit 9af394e
Showing
15 changed files
with
304 additions
and
26 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
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
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
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,62 @@ | ||
-- crud.select/crud.pairs/readview:select/readview:pairs | ||
-- have a lot of common scenarios, which are mostly tested with | ||
-- four nearly identical copypasted test functions now. | ||
-- This approach is expected to improve it at least for new test cases. | ||
-- Scenarios here are for `srv_select` entrypoint. | ||
|
||
local t = require('luatest') | ||
|
||
local helpers = require('test.helper') | ||
|
||
local function gh_418_read_with_secondary_noneq_index_condition(cg, read) | ||
-- Pin bucket_id to reproduce issue on a single storage. | ||
local PINNED_BUCKET_NO = 1 | ||
|
||
local expected_objects = { | ||
{ | ||
id = 1, | ||
bucket_id = PINNED_BUCKET_NO, | ||
city = 'Tatsumi Port Island', | ||
name = 'Yukari', | ||
last_login = 42, | ||
}, | ||
{ | ||
id = 2, | ||
bucket_id = PINNED_BUCKET_NO, | ||
city = 'Tatsumi Port Island', | ||
name = 'Junpei', | ||
last_login = 52, | ||
}, | ||
{ | ||
id = 3, | ||
bucket_id = PINNED_BUCKET_NO, | ||
city = 'Tatsumi Port Island', | ||
name = 'Mitsuru', | ||
last_login = 42, | ||
}, | ||
} | ||
|
||
helpers.prepare_ordered_data(cg, | ||
'logins', | ||
expected_objects, | ||
PINNED_BUCKET_NO, | ||
{'=', 'city', 'Tatsumi Port Island'} | ||
) | ||
|
||
-- Issue https://github.com/tarantool/crud/issues/418 is as follows: | ||
-- storage iterator exits early on the second tuple because | ||
-- iterator had erroneously expected tuples to be sorted by `last_login` | ||
-- index while iterating on `city` index. Before the issue had beed fixed, | ||
-- user had received only one record instead of two. | ||
local objects = read(cg, | ||
'logins', | ||
{{'=', 'city', 'Tatsumi Port Island'}, {'<=', 'last_login', 42}}, | ||
{bucket_id = PINNED_BUCKET_NO} | ||
) | ||
|
||
t.assert_equals(objects, {expected_objects[1], expected_objects[3]}) | ||
end | ||
|
||
return { | ||
gh_418_read_with_secondary_noneq_index_condition = gh_418_read_with_secondary_noneq_index_condition, | ||
} |
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
Oops, something went wrong.