Skip to content

Commit dedf184

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 bc43a8f commit dedf184

File tree

10 files changed

+379
-5
lines changed

10 files changed

+379
-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

34
local crud_utils = require('crud.common.utils')
45

@@ -230,6 +231,102 @@ return function()
230231
if_not_exists = true,
231232
})
232233

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

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

920925
pgroup[case_name] = function(g)

0 commit comments

Comments
 (0)