Skip to content

Error on update of a float64 field adding another float64 #9929

@sergepetrenko

Description

@sergepetrenko

Tarantool version: Tarantool 3.1.0-entrypoint-232-gc8d8c2e8ee (current master).

Bug description

Our float64 format doesn't allow values encoded as MP_FLOAT, only the ones encoded as MP_DOUBLE:

/* [FIELD_TYPE_FLOAT32] = */ 1U << MP_FLOAT,
/* [FIELD_TYPE_FLOAT64] = */ 1U << MP_DOUBLE,
};

At the same time, we have multiple places which optimize encoded float size, and encode doubles as MP_FLOAT to spare extra 4 bytes, when this doesn't affect the precision (a double is exactly representable by a float). Example:

if (c <= FLT_MAX && c >= -FLT_MAX) {
float fc = (float)c;
if (c == (double)fc) {
ret->type = XUPDATE_TYPE_FLOAT;
ret->flt = fc;
return 0;
}
}

As a result, an update operation of a float64 field 100: update({key}, {{'+', 2, 100}}) may error like this:

---
- error: 'Tuple field 2 (value) type does not match one required by operation: expected
    float64, got float'
...

And there's literally no way to perform an update with an integer result on a float64 column.
Steps to reproduce

Run a Tarantool instance interactively:

-- Step 1.
box.cfg{}
space = box.schema.space.create('test', {format = {{'id', 'unsigned'}, {'value', 'float64'}}})
_ = space:create_index('pk')

space:insert{1, require('ffi').new('float', 100)}
-- error: 'Tuple field 2 (value) type does not match one required by operation: expected
--   float64, got float'
space:insert{1, require('ffi').new('double', 100)} -- success.

space:fselect()
--  +-----+-----+
--  | id  |value|
--  +-----+-----+
--  |  1  | 100 |
--  +-----+-----+



space:update({1}, {{'+', 2, 100}})
-- error: 'Tuple field 2 (value) type does not match one required by operation: expected
--   float64, got float'
space:update({1}, {{'+', 2, require('ffi').new('float', 100)}})
-- error: 'Tuple field 2 (value) type does not match one required by operation: expected
--   float64, got float'
space:update({1}, {{'+', 2, require('ffi').new('double', 100)}})
-- error: 'Tuple field 2 (value) type does not match one required by operation: expected
--   float64, got float'

I think we should keep the MP_FLOAT optimization for results that fit into a single-precision float, and instead allow float64 to contain MP_FLOAT in addition to MP_DOUBLE.
Besides, it would fall in line with (u)int8/16/32/64, which allows any (u)int encoding.

Metadata

Metadata

Assignees

Labels

3.2Target is 3.2 and all newer release/master branchesbugSomething isn't working

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions