Skip to content

Commit 46bbfe4

Browse files
scan: fix decimal filters precision loss
Before this patch, decimals were cast to numbers in filters through `tostring` in codegen. This patch fixes this precision loss. Part of #373
1 parent c1a52eb commit 46bbfe4

File tree

10 files changed

+382
-5
lines changed

10 files changed

+382
-5
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
1010
### Fixed
1111
* Working with datetime conditions in case of non-indexed fields or
1212
non-iterating indexes (#373).
13+
* Precision loss for decimal conditions in case of non-indexed fields or
14+
non-iterating indexes (#373).
1315

1416
## [1.4.3] - 05-02-24
1517

crud/compare/filters.lua

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
local datetime_supported, datetime = pcall(require, 'datetime')
2+
local decimal_supported, decimal = pcall(require, 'decimal')
23

34
local errors = require('errors')
45

@@ -159,6 +160,9 @@ local function format_value(value)
159160
return tostring(value)
160161
elseif type(value) == 'boolean' then
161162
return tostring(value)
163+
elseif decimal_supported and decimal.is_decimal(value) then
164+
-- decimal supports comparison with string.
165+
return ("%q"):format(tostring(value))
162166
elseif utils.is_uuid(value) then
163167
return ("%q"):format(value)
164168
elseif datetime_supported and datetime.is_datetime(value) then

test/entrypoint/srv_select/storage_init.lua

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
local datetime_supported, _ = pcall(require, 'datetime')
2+
local decimal_supported, _ = pcall(require, 'decimal')
23
local crud_utils = require('crud.common.utils')
34

45
return function()
@@ -229,6 +230,102 @@ return function()
229230
if_not_exists = true,
230231
})
231232

233+
if decimal_supported then
234+
local decimal_format = {
235+
{name = 'id', type = 'unsigned'},
236+
{name = 'bucket_id', type = 'unsigned'},
237+
{name = 'decimal_field', type = 'decimal'},
238+
}
239+
240+
241+
local decimal_nonindexed_space = box.schema.space.create('decimal_nonindexed', {
242+
if_not_exists = true,
243+
engine = engine,
244+
})
245+
246+
decimal_nonindexed_space:format(decimal_format)
247+
248+
decimal_nonindexed_space:create_index('id_index', {
249+
parts = { 'id' },
250+
if_not_exists = true,
251+
})
252+
253+
decimal_nonindexed_space:create_index('bucket_id', {
254+
parts = { 'bucket_id' },
255+
unique = false,
256+
if_not_exists = true,
257+
})
258+
259+
260+
local decimal_indexed_space = box.schema.space.create('decimal_indexed', {
261+
if_not_exists = true,
262+
engine = engine,
263+
})
264+
265+
decimal_indexed_space:format(decimal_format)
266+
267+
decimal_indexed_space:create_index('id_index', {
268+
parts = { 'id' },
269+
if_not_exists = true,
270+
})
271+
272+
decimal_indexed_space:create_index('bucket_id', {
273+
parts = { 'bucket_id' },
274+
unique = false,
275+
if_not_exists = true,
276+
})
277+
278+
decimal_indexed_space:create_index('decimal_index', {
279+
parts = { 'decimal_field' },
280+
unique = false,
281+
if_not_exists = true,
282+
})
283+
284+
285+
local decimal_pk_space = box.schema.space.create('decimal_pk', {
286+
if_not_exists = true,
287+
engine = engine,
288+
})
289+
290+
decimal_pk_space:format(decimal_format)
291+
292+
decimal_pk_space:create_index('decimal_index', {
293+
parts = { 'decimal_field' },
294+
if_not_exists = true,
295+
})
296+
297+
decimal_pk_space:create_index('bucket_id', {
298+
parts = { 'bucket_id' },
299+
unique = false,
300+
if_not_exists = true,
301+
})
302+
303+
304+
local decimal_multipart_index_space = box.schema.space.create('decimal_multipart_index', {
305+
if_not_exists = true,
306+
engine = engine,
307+
})
308+
309+
decimal_multipart_index_space:format(decimal_format)
310+
311+
decimal_multipart_index_space:create_index('id_index', {
312+
parts = { 'id' },
313+
if_not_exists = true,
314+
})
315+
316+
decimal_multipart_index_space:create_index('bucket_id', {
317+
parts = { 'bucket_id' },
318+
unique = false,
319+
if_not_exists = true,
320+
})
321+
322+
decimal_multipart_index_space:create_index('decimal_index', {
323+
parts = { 'id', 'decimal_field' },
324+
unique = false,
325+
if_not_exists = true,
326+
})
327+
end
328+
232329
if datetime_supported then
233330
local datetime_format = {
234331
{name = 'id', type = 'unsigned'},

test/helper.lua

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -958,9 +958,32 @@ function helpers.prepare_ordered_data(g, space, expected_objects, bucket_id, ord
958958
t.assert_equals(objects, expected_objects)
959959
end
960960

961+
function helpers.skip_decimal_unsupported()
962+
local module_available, _ = pcall(require, 'decimal')
963+
t.skip_if(not module_available, 'decimal is not supported')
964+
end
965+
961966
function helpers.skip_datetime_unsupported()
962967
local module_available, _ = pcall(require, 'datetime')
963968
t.skip_if(not module_available, 'datetime is not supported')
964969
end
965970

971+
function helpers.merge_tables(t1, t2, ...)
972+
if t2 == nil then
973+
return t1
974+
end
975+
976+
local res = {}
977+
978+
for k, v in pairs(t1) do
979+
res[k] = v
980+
end
981+
982+
for k, v in pairs(t2) do
983+
res[k] = v
984+
end
985+
986+
return helpers.merge_tables(res, ...)
987+
end
988+
966989
return helpers

test/integration/count_test.lua

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -883,7 +883,12 @@ pgroup.test_gh_418_count_with_secondary_noneq_index_condition = function(g)
883883
read_scenario.gh_418_read_with_secondary_noneq_index_condition(g, read_impl)
884884
end
885885

886-
for case_name_template, case in pairs(read_scenario.gh_373_read_with_datetime_condition_cases) do
886+
local gh_373_types_cases = helpers.merge_tables(
887+
read_scenario.gh_373_read_with_decimal_condition_cases,
888+
read_scenario.gh_373_read_with_datetime_condition_cases
889+
)
890+
891+
for case_name_template, case in pairs(gh_373_types_cases) do
887892
local case_name = 'test_' .. case_name_template:format('count')
888893

889894
pgroup[case_name] = function(g)

test/integration/pairs_readview_test.lua

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -907,7 +907,12 @@ pgroup.test_gh_418_pairs_with_secondary_noneq_index_condition = function(g)
907907
read_scenario.gh_418_read_with_secondary_noneq_index_condition(g, read_impl)
908908
end
909909

910-
for case_name_template, case in pairs(read_scenario.gh_373_read_with_datetime_condition_cases) do
910+
local gh_373_types_cases = helpers.merge_tables(
911+
read_scenario.gh_373_read_with_decimal_condition_cases,
912+
read_scenario.gh_373_read_with_datetime_condition_cases
913+
)
914+
915+
for case_name_template, case in pairs(gh_373_types_cases) do
911916
local case_name = 'test_' .. case_name_template:format('pairs')
912917

913918
pgroup[case_name] = function(g)

test/integration/pairs_test.lua

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -915,7 +915,12 @@ pgroup.test_gh_418_pairs_with_secondary_noneq_index_condition = function(g)
915915
read_scenario.gh_418_read_with_secondary_noneq_index_condition(g, read_impl)
916916
end
917917

918-
for case_name_template, case in pairs(read_scenario.gh_373_read_with_datetime_condition_cases) do
918+
local gh_373_types_cases = helpers.merge_tables(
919+
read_scenario.gh_373_read_with_decimal_condition_cases,
920+
read_scenario.gh_373_read_with_datetime_condition_cases
921+
)
922+
923+
for case_name_template, case in pairs(gh_373_types_cases) do
919924
local case_name = 'test_' .. case_name_template:format('pairs')
920925

921926
pgroup[case_name] = function(g)

0 commit comments

Comments
 (0)