Skip to content

Commit 5f29872

Browse files
oleg-jukovecDifferentialOrange
authored andcommitted
select: fix EQ with negative first results
EQ with after has always been replaced by LT. The idea was to start traverse not from the after value, but from a next value. The micro-optimization allowed to fetch one less tuple per time. It worked well for unique indexes, but this led to wrong results for non-unique indexes.
1 parent 2c5eabe commit 5f29872

File tree

3 files changed

+84
-2
lines changed

3 files changed

+84
-2
lines changed

CHANGELOG.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,40 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
5353
...
5454

5555
* `crud.select()` results order with negative `first`.
56+
* `crud.select()` if a condition is '=' or '==' with negative `first`.
57+
58+
Suppose we have a non-unique secondary index by the field `age` field and a
59+
space:
60+
61+
tarantool> crud.select('developers', nil, {first = 10})
62+
---
63+
- metadata: [{'name': 'id', 'type': 'unsigned'}, {'name': 'bucket_id', 'type': 'unsigned'},
64+
{'name': 'name', 'type': 'string'}, {'name': 'surname', 'type': 'string'}, {'name': 'age',
65+
'type': 'number'}]
66+
rows:
67+
- [1, 477, 'Alexey', 'Adams', 20]
68+
- [2, 401, 'Sergey', 'Allred', 27]
69+
- [3, 2804, 'Pavel', 'Adams', 27]
70+
- [4, 1161, 'Mikhail', 'Liston', 27]
71+
- [5, 1172, 'Dmitry', 'Jacobi', 27]
72+
- [6, 1064, 'Alexey', 'Sidorov', 31]
73+
- null
74+
...
75+
76+
Before this patch:
77+
78+
tarantool> crud.select('developers', {{'=', 'age', 27}}, {first = -10, after = rows[4]}).rows
79+
---
80+
- []
81+
...
82+
83+
After this patch:
84+
85+
tarantool> crud.select('developers', {{'=', 'age', 27}}, {first = -10, after = rows[4]}).rows
86+
---
87+
- - [2, 401, 'Sergey', 'Allred', 27]
88+
- [3, 2804, 'Pavel', 'Adams', 27]
89+
...
5690

5791
## [0.11.2] - 23-05-22
5892

crud/compare/plan.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ function plan.new(space, conditions, opts)
269269
if scan_iter == box.index.EQ then
270270
scan_iter = box.index.GE
271271
elseif scan_iter == box.index.REQ then
272-
scan_iter = box.index.LT
272+
scan_iter = box.index.LE
273273
end
274274
end
275275

test/integration/select_test.lua

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,10 @@ pgroup.test_eq_condition_with_index = function(g)
579579
},{
580580
id = 7, name = "Jack", last_name = "Sparrow",
581581
age = 33, city = "Chicago",
582-
},
582+
}, {
583+
id = 8, name = "Nick", last_name = "Smith",
584+
age = 20, city = "London",
585+
}
583586
})
584587

585588
table.sort(customers, function(obj1, obj2) return obj1.id < obj2.id end)
@@ -602,6 +605,51 @@ pgroup.test_eq_condition_with_index = function(g)
602605
t.assert_equals(err, nil)
603606
local objects = crud.unflatten_rows(result.rows, result.metadata)
604607
t.assert_equals(objects, helpers.get_objects_by_idxs(customers, {5, 7})) -- in id order
608+
609+
-- after obj 5 with negative first
610+
local after = crud_utils.flatten(customers[5], g.space_format)
611+
local result, err = g.cluster.main_server.net_box:call(
612+
'crud.select', {'customers', conditions, {after=after, first=-10}})
613+
614+
t.assert_equals(err, nil)
615+
local objects = crud.unflatten_rows(result.rows, result.metadata)
616+
t.assert_equals(objects, helpers.get_objects_by_idxs(customers, {1, 3})) -- in id order
617+
618+
-- after obj 8
619+
local after = crud_utils.flatten(customers[8], g.space_format)
620+
local result, err = g.cluster.main_server.net_box:call(
621+
'crud.select', {'customers', conditions, {after=after, first=10}})
622+
623+
t.assert_equals(err, nil)
624+
local objects = crud.unflatten_rows(result.rows, result.metadata)
625+
t.assert_equals(objects, helpers.get_objects_by_idxs(customers, {1, 3, 5, 7})) -- in id order
626+
627+
-- after obj 8 with negative first
628+
local after = crud_utils.flatten(customers[8], g.space_format)
629+
local result, err = g.cluster.main_server.net_box:call(
630+
'crud.select', {'customers', conditions, {after=after, first=-10}})
631+
632+
t.assert_equals(err, nil)
633+
local objects = crud.unflatten_rows(result.rows, result.metadata)
634+
t.assert_equals(objects, helpers.get_objects_by_idxs(customers, {}))
635+
636+
-- after obj 2
637+
local after = crud_utils.flatten(customers[2], g.space_format)
638+
local result, err = g.cluster.main_server.net_box:call(
639+
'crud.select', {'customers', conditions, {after=after, first=10}})
640+
641+
t.assert_equals(err, nil)
642+
local objects = crud.unflatten_rows(result.rows, result.metadata)
643+
t.assert_equals(objects, helpers.get_objects_by_idxs(customers, {}))
644+
645+
-- after obj 2 with negative first
646+
local after = crud_utils.flatten(customers[2], g.space_format)
647+
local result, err = g.cluster.main_server.net_box:call(
648+
'crud.select', {'customers', conditions, {after=after, first=-10}})
649+
650+
t.assert_equals(err, nil)
651+
local objects = crud.unflatten_rows(result.rows, result.metadata)
652+
t.assert_equals(objects, helpers.get_objects_by_idxs(customers, {1, 3, 5, 7})) -- in id order
605653
end
606654

607655
pgroup.test_ge_condition_with_index = function(g)

0 commit comments

Comments
 (0)