* [PATCH v1 1/1] box: introduce VARBINARY field type @ 2019-06-26 16:40 Kirill Shcherbatov 2019-06-26 19:11 ` [tarantool-patches] " Konstantin Osipov 2019-07-03 10:10 ` Vladimir Davydov 0 siblings, 2 replies; 5+ messages in thread From: Kirill Shcherbatov @ 2019-06-26 16:40 UTC (permalink / raw) To: tarantool-patches, vdavydov.dev; +Cc: Kirill Shcherbatov Introduced a new field type VARBINARY to represent mp_bin values. This field type would be useful for SQL type system. Closes #4201 Needed for #4206 --- http://github.com/tarantool/tarantool/tree/kshch/gh-4201-varbinary-type https://github.com/tarantool/tarantool/issues/4201 src/box/field_def.c | 23 +++-- src/box/field_def.h | 1 + src/box/lua/key_def.c | 1 + src/box/tuple_compare.cc | 17 ++++ test/box/varbinary_type.result | 152 +++++++++++++++++++++++++++++++ test/box/varbinary_type.test.lua | 51 +++++++++++ 6 files changed, 235 insertions(+), 10 deletions(-) create mode 100644 test/box/varbinary_type.result create mode 100644 test/box/varbinary_type.test.lua diff --git a/src/box/field_def.c b/src/box/field_def.c index 0ba3d3294..346042b98 100644 --- a/src/box/field_def.c +++ b/src/box/field_def.c @@ -55,6 +55,7 @@ const uint32_t field_mp_type[] = { (1U << MP_FLOAT) | (1U << MP_DOUBLE), /* [FIELD_TYPE_INTEGER] = */ (1U << MP_UINT) | (1U << MP_INT), /* [FIELD_TYPE_BOOLEAN] = */ 1U << MP_BOOL, + /* [FIELD_TYPE_VARBINARY] = */ 1U << MP_BIN, /* [FIELD_TYPE_SCALAR] = */ (1U << MP_UINT) | (1U << MP_INT) | (1U << MP_FLOAT) | (1U << MP_DOUBLE) | (1U << MP_STR) | (1U << MP_BIN) | (1U << MP_BOOL), @@ -69,6 +70,7 @@ const char *field_type_strs[] = { /* [FIELD_TYPE_NUMBER] = */ "number", /* [FIELD_TYPE_INTEGER] = */ "integer", /* [FIELD_TYPE_BOOLEAN] = */ "boolean", + /* [FIELD_TYPE_VARBINARY] = */"varbinary", /* [FIELD_TYPE_SCALAR] = */ "scalar", /* [FIELD_TYPE_ARRAY] = */ "array", /* [FIELD_TYPE_MAP] = */ "map", @@ -96,16 +98,17 @@ field_type_by_name_wrapper(const char *str, uint32_t len) * values can be stored in the j type. */ static const bool field_type_compatibility[] = { - /* ANY UNSIGNED STRING NUMBER INTEGER BOOLEAN SCALAR ARRAY MAP */ -/* ANY */ true, false, false, false, false, false, false, false, false, -/* UNSIGNED */ true, true, false, true, true, false, true, false, false, -/* STRING */ true, false, true, false, false, false, true, false, false, -/* NUMBER */ true, false, false, true, false, false, true, false, false, -/* INTEGER */ true, false, false, true, true, false, true, false, false, -/* BOOLEAN */ true, false, false, false, false, true, true, false, false, -/* SCALAR */ true, false, false, false, false, false, true, false, false, -/* ARRAY */ true, false, false, false, false, false, false, true, false, -/* MAP */ true, false, false, false, false, false, false, false, true, + /* ANY UNSIGNED STRING NUMBER INTEGER BOOLEAN VARBINARY SCALAR ARRAY MAP */ +/* ANY */ true, false, false, false, false, false, false, false, false, false, +/* UNSIGNED */ true, true, false, true, true, false, false, true, false, false, +/* STRING */ true, false, true, false, false, false, false, true, false, false, +/* NUMBER */ true, false, false, true, false, false, false, true, false, false, +/* INTEGER */ true, false, false, true, true, false, false, true, false, false, +/* BOOLEAN */ true, false, false, false, false, true, false, true, false, false, +/* VARBINARY*/ true, false, false, false, false, false, true, true, false, false, +/* SCALAR */ true, false, false, false, false, false, false, true, false, false, +/* ARRAY */ true, false, false, false, false, false, false, false, true, false, +/* MAP */ true, false, false, false, false, false, false, false, false, true, }; bool diff --git a/src/box/field_def.h b/src/box/field_def.h index f944de9d6..c1a7ec0a9 100644 --- a/src/box/field_def.h +++ b/src/box/field_def.h @@ -56,6 +56,7 @@ enum field_type { FIELD_TYPE_NUMBER, FIELD_TYPE_INTEGER, FIELD_TYPE_BOOLEAN, + FIELD_TYPE_VARBINARY, FIELD_TYPE_SCALAR, FIELD_TYPE_ARRAY, FIELD_TYPE_MAP, diff --git a/src/box/lua/key_def.c b/src/box/lua/key_def.c index dfcc89442..052a1c85d 100644 --- a/src/box/lua/key_def.c +++ b/src/box/lua/key_def.c @@ -111,6 +111,7 @@ luaT_key_def_set_part(struct lua_State *L, struct key_part_def *part, part->type = field_type_by_name(type_name, type_len); switch (part->type) { case FIELD_TYPE_ANY: + case FIELD_TYPE_VARBINARY: case FIELD_TYPE_ARRAY: case FIELD_TYPE_MAP: /* Tuple comparators don't support these types. */ diff --git a/src/box/tuple_compare.cc b/src/box/tuple_compare.cc index c1a70a087..95a0f58c9 100644 --- a/src/box/tuple_compare.cc +++ b/src/box/tuple_compare.cc @@ -404,6 +404,8 @@ tuple_compare_field(const char *field_a, const char *field_b, return mp_compare_number(field_a, field_b); case FIELD_TYPE_BOOLEAN: return mp_compare_bool(field_a, field_b); + case FIELD_TYPE_VARBINARY: + return mp_compare_bin(field_a, field_b); case FIELD_TYPE_SCALAR: return coll != NULL ? mp_compare_scalar_coll(field_a, field_b, coll) : @@ -434,6 +436,8 @@ tuple_compare_field_with_type(const char *field_a, enum mp_type a_type, field_b, b_type); case FIELD_TYPE_BOOLEAN: return mp_compare_bool(field_a, field_b); + case FIELD_TYPE_VARBINARY: + return mp_compare_bin(field_a, field_b); case FIELD_TYPE_SCALAR: return coll != NULL ? mp_compare_scalar_coll(field_a, field_b, coll) : @@ -1502,6 +1506,14 @@ field_hint_string(const char *field, struct coll *coll) hint_str_coll(field, len, coll); } +static inline hint_t +field_hint_varbinary(const char *field) +{ + assert(mp_typeof(*field) == MP_BIN); + uint32_t len = mp_decode_binl(&field); + return hint_bin(field, len); +} + static inline hint_t field_hint_scalar(const char *field, struct coll *coll) { @@ -1547,6 +1559,8 @@ field_hint(const char *field, struct coll *coll) return field_hint_number(field); case FIELD_TYPE_STRING: return field_hint_string(field, coll); + case FIELD_TYPE_VARBINARY: + return field_hint_varbinary(field); case FIELD_TYPE_SCALAR: return field_hint_scalar(field, coll); default: @@ -1648,6 +1662,9 @@ key_def_set_hint_func(struct key_def *def) case FIELD_TYPE_STRING: key_def_set_hint_func<FIELD_TYPE_STRING>(def); break; + case FIELD_TYPE_VARBINARY: + key_def_set_hint_func<FIELD_TYPE_VARBINARY>(def); + break; case FIELD_TYPE_SCALAR: key_def_set_hint_func<FIELD_TYPE_SCALAR>(def); break; diff --git a/test/box/varbinary_type.result b/test/box/varbinary_type.result new file mode 100644 index 000000000..c7cd5700c --- /dev/null +++ b/test/box/varbinary_type.result @@ -0,0 +1,152 @@ +env = require('test_run') +--- +... +test_run = env.new() +--- +... +-- +-- gh-4201: Introduce varbinary field type. +-- +s = box.schema.space.create('withdata') +--- +... +s:format({{"b", "integer"}}) +--- +... +_ = s:create_index('pk', {parts = {1, "varbinary"}}) +--- +- error: Field 1 has type 'integer' in space format, but type 'varbinary' in index + definition +... +s:format({{"b", "varbinary"}}) +--- +... +_ = s:create_index('pk', {parts = {1, "integer"}}) +--- +- error: Field 1 has type 'varbinary' in space format, but type 'integer' in index + definition +... +pk = s:create_index('pk', {parts = {1, "varbinary"}}) +--- +... +buffer = require('buffer') +--- +... +ffi = require('ffi') +--- +... +test_run:cmd("setopt delimiter ';'") +--- +- true +... +function bintuple_insert(space, bytes) + local tmpbuf = buffer.IBUF_SHARED + tmpbuf:reset() + local p = tmpbuf:alloc(3 + #bytes) + p[0] = 0x91 + p[1] = 0xC4 + p[2] = #bytes + for i, c in pairs(bytes) do p[i + 3 - 1] = c end + ffi.cdef[[int box_insert(uint32_t space_id, const char *tuple, const char *tuple_end, box_tuple_t **result);]] + ffi.C.box_insert(space.id, tmpbuf.rpos, tmpbuf.wpos, nil) +end +test_run:cmd("setopt delimiter ''"); +--- +... +bintuple_insert(s, {0xDE, 0xAD, 0xBE, 0xAF}) +--- +... +bintuple_insert(s, {0xFE, 0xED, 0xFA, 0xCE}) +--- +... +s:select() +--- +- - [!!binary 3q2+rw==] + - [!!binary /u36zg==] +... +box.execute("SELECT * FROM \"withdata\" WHERE \"b\" < x'FEEDFACE';") +--- +- metadata: + - name: b + type: varbinary + rows: + - [!!binary 3q2+rw==] +... +pk:alter({parts = {1, "scalar"}}) +--- +... +s:format({{"b", "scalar"}}) +--- +... +s:insert({11}) +--- +- [11] +... +s:insert({22}) +--- +- [22] +... +s:insert({"11"}) +--- +- ['11'] +... +s:insert({"22"}) +--- +- ['22'] +... +s:select() +--- +- - [11] + - [22] + - ['11'] + - ['22'] + - [!!binary 3q2+rw==] + - [!!binary /u36zg==] +... +box.execute("SELECT * FROM \"withdata\" WHERE \"b\" <= x'DEADBEAF';") +--- +- metadata: + - name: b + type: scalar + rows: + - [11] + - [22] + - ['11'] + - ['22'] + - [!!binary 3q2+rw==] +... +pk:alter({parts = {1, "varbinary"}}) +--- +- error: 'Tuple field 1 type does not match one required by operation: expected varbinary' +... +s:delete({11}) +--- +- [11] +... +s:delete({22}) +--- +- [22] +... +s:delete({"11"}) +--- +- ['11'] +... +s:delete({"22"}) +--- +- ['22'] +... +bintuple_insert(s, {0xFA, 0xDE, 0xDE, 0xAD}) +--- +... +pk:alter({parts = {1, "varbinary"}}) +--- +... +s:select() +--- +- - [!!binary 3q2+rw==] + - [!!binary +t7erQ==] + - [!!binary /u36zg==] +... +s:drop() +--- +... diff --git a/test/box/varbinary_type.test.lua b/test/box/varbinary_type.test.lua new file mode 100644 index 000000000..7895a1d22 --- /dev/null +++ b/test/box/varbinary_type.test.lua @@ -0,0 +1,51 @@ +env = require('test_run') +test_run = env.new() + +-- +-- gh-4201: Introduce varbinary field type. +-- +s = box.schema.space.create('withdata') +s:format({{"b", "integer"}}) +_ = s:create_index('pk', {parts = {1, "varbinary"}}) +s:format({{"b", "varbinary"}}) +_ = s:create_index('pk', {parts = {1, "integer"}}) +pk = s:create_index('pk', {parts = {1, "varbinary"}}) + +buffer = require('buffer') +ffi = require('ffi') + +test_run:cmd("setopt delimiter ';'") +function bintuple_insert(space, bytes) + local tmpbuf = buffer.IBUF_SHARED + tmpbuf:reset() + local p = tmpbuf:alloc(3 + #bytes) + p[0] = 0x91 + p[1] = 0xC4 + p[2] = #bytes + for i, c in pairs(bytes) do p[i + 3 - 1] = c end + ffi.cdef[[int box_insert(uint32_t space_id, const char *tuple, const char *tuple_end, box_tuple_t **result);]] + ffi.C.box_insert(space.id, tmpbuf.rpos, tmpbuf.wpos, nil) +end +test_run:cmd("setopt delimiter ''"); + +bintuple_insert(s, {0xDE, 0xAD, 0xBE, 0xAF}) +bintuple_insert(s, {0xFE, 0xED, 0xFA, 0xCE}) +s:select() +box.execute("SELECT * FROM \"withdata\" WHERE \"b\" < x'FEEDFACE';") +pk:alter({parts = {1, "scalar"}}) +s:format({{"b", "scalar"}}) +s:insert({11}) +s:insert({22}) +s:insert({"11"}) +s:insert({"22"}) +s:select() +box.execute("SELECT * FROM \"withdata\" WHERE \"b\" <= x'DEADBEAF';") +pk:alter({parts = {1, "varbinary"}}) +s:delete({11}) +s:delete({22}) +s:delete({"11"}) +s:delete({"22"}) +bintuple_insert(s, {0xFA, 0xDE, 0xDE, 0xAD}) +pk:alter({parts = {1, "varbinary"}}) +s:select() +s:drop() -- 2.21.0 ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [tarantool-patches] [PATCH v1 1/1] box: introduce VARBINARY field type 2019-06-26 16:40 [PATCH v1 1/1] box: introduce VARBINARY field type Kirill Shcherbatov @ 2019-06-26 19:11 ` Konstantin Osipov 2019-06-27 7:38 ` [tarantool-patches] " Kirill Shcherbatov 2019-07-03 10:10 ` Vladimir Davydov 1 sibling, 1 reply; 5+ messages in thread From: Konstantin Osipov @ 2019-06-26 19:11 UTC (permalink / raw) To: tarantool-patches; +Cc: vdavydov.dev, Kirill Shcherbatov * Kirill Shcherbatov <kshcherbatov@tarantool.org> [19/06/26 19:46]: > Introduced a new field type VARBINARY to represent mp_bin values. > This field type would be useful for SQL type system. > please add docbot request. > Closes #4201 > Needed for #4206 > --- > http://github.com/tarantool/tarantool/tree/kshch/gh-4201-varbinary-type > https://github.com/tarantool/tarantool/issues/4201 -- Konstantin Osipov, Moscow, Russia ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [tarantool-patches] Re: [PATCH v1 1/1] box: introduce VARBINARY field type 2019-06-26 19:11 ` [tarantool-patches] " Konstantin Osipov @ 2019-06-27 7:38 ` Kirill Shcherbatov 2019-06-27 8:01 ` Konstantin Osipov 0 siblings, 1 reply; 5+ messages in thread From: Kirill Shcherbatov @ 2019-06-27 7:38 UTC (permalink / raw) To: tarantool-patches, Konstantin Osipov; +Cc: Vladimir Davydov > please add docbot request. In fact, I did not include TarantoolBot query consciously: this patch is preparatory for #4206, and only introduces a new field type, while preparing data corresponding to this field in Tarantool now is not easy (see the test case below). But in general, the documentation may be updated. So I've updated a commit message. ========================================== A new VARBINARY field type would be useful for SQL type system. Closes #4201 Needed for #4206 @TarantoolBot document Title: new varbinary field type Introduced a new field type varbinary to represent mp_bin values. The new type varbinary may be used in format or index definition. Example: s = box.schema.space.create('withdata') s:format({{"b", "varbinary"}}) pk = s:create_index('pk', {parts = {1, "varbinary"}}) --- src/box/field_def.c | 23 +++-- src/box/field_def.h | 1 + src/box/lua/key_def.c | 1 + src/box/tuple_compare.cc | 17 ++++ test/box/varbinary_type.result | 152 +++++++++++++++++++++++++++++++ test/box/varbinary_type.test.lua | 51 +++++++++++ 6 files changed, 235 insertions(+), 10 deletions(-) create mode 100644 test/box/varbinary_type.result create mode 100644 test/box/varbinary_type.test.lua diff --git a/src/box/field_def.c b/src/box/field_def.c index 0ba3d3294..346042b98 100644 --- a/src/box/field_def.c +++ b/src/box/field_def.c @@ -55,6 +55,7 @@ const uint32_t field_mp_type[] = { (1U << MP_FLOAT) | (1U << MP_DOUBLE), /* [FIELD_TYPE_INTEGER] = */ (1U << MP_UINT) | (1U << MP_INT), /* [FIELD_TYPE_BOOLEAN] = */ 1U << MP_BOOL, + /* [FIELD_TYPE_VARBINARY] = */ 1U << MP_BIN, /* [FIELD_TYPE_SCALAR] = */ (1U << MP_UINT) | (1U << MP_INT) | (1U << MP_FLOAT) | (1U << MP_DOUBLE) | (1U << MP_STR) | (1U << MP_BIN) | (1U << MP_BOOL), @@ -69,6 +70,7 @@ const char *field_type_strs[] = { /* [FIELD_TYPE_NUMBER] = */ "number", /* [FIELD_TYPE_INTEGER] = */ "integer", /* [FIELD_TYPE_BOOLEAN] = */ "boolean", + /* [FIELD_TYPE_VARBINARY] = */"varbinary", /* [FIELD_TYPE_SCALAR] = */ "scalar", /* [FIELD_TYPE_ARRAY] = */ "array", /* [FIELD_TYPE_MAP] = */ "map", @@ -96,16 +98,17 @@ field_type_by_name_wrapper(const char *str, uint32_t len) * values can be stored in the j type. */ static const bool field_type_compatibility[] = { - /* ANY UNSIGNED STRING NUMBER INTEGER BOOLEAN SCALAR ARRAY MAP */ -/* ANY */ true, false, false, false, false, false, false, false, false, -/* UNSIGNED */ true, true, false, true, true, false, true, false, false, -/* STRING */ true, false, true, false, false, false, true, false, false, -/* NUMBER */ true, false, false, true, false, false, true, false, false, -/* INTEGER */ true, false, false, true, true, false, true, false, false, -/* BOOLEAN */ true, false, false, false, false, true, true, false, false, -/* SCALAR */ true, false, false, false, false, false, true, false, false, -/* ARRAY */ true, false, false, false, false, false, false, true, false, -/* MAP */ true, false, false, false, false, false, false, false, true, + /* ANY UNSIGNED STRING NUMBER INTEGER BOOLEAN VARBINARY SCALAR ARRAY MAP */ +/* ANY */ true, false, false, false, false, false, false, false, false, false, +/* UNSIGNED */ true, true, false, true, true, false, false, true, false, false, +/* STRING */ true, false, true, false, false, false, false, true, false, false, +/* NUMBER */ true, false, false, true, false, false, false, true, false, false, +/* INTEGER */ true, false, false, true, true, false, false, true, false, false, +/* BOOLEAN */ true, false, false, false, false, true, false, true, false, false, +/* VARBINARY*/ true, false, false, false, false, false, true, true, false, false, +/* SCALAR */ true, false, false, false, false, false, false, true, false, false, +/* ARRAY */ true, false, false, false, false, false, false, false, true, false, +/* MAP */ true, false, false, false, false, false, false, false, false, true, }; bool diff --git a/src/box/field_def.h b/src/box/field_def.h index f944de9d6..c1a7ec0a9 100644 --- a/src/box/field_def.h +++ b/src/box/field_def.h @@ -56,6 +56,7 @@ enum field_type { FIELD_TYPE_NUMBER, FIELD_TYPE_INTEGER, FIELD_TYPE_BOOLEAN, + FIELD_TYPE_VARBINARY, FIELD_TYPE_SCALAR, FIELD_TYPE_ARRAY, FIELD_TYPE_MAP, diff --git a/src/box/lua/key_def.c b/src/box/lua/key_def.c index dfcc89442..052a1c85d 100644 --- a/src/box/lua/key_def.c +++ b/src/box/lua/key_def.c @@ -111,6 +111,7 @@ luaT_key_def_set_part(struct lua_State *L, struct key_part_def *part, part->type = field_type_by_name(type_name, type_len); switch (part->type) { case FIELD_TYPE_ANY: + case FIELD_TYPE_VARBINARY: case FIELD_TYPE_ARRAY: case FIELD_TYPE_MAP: /* Tuple comparators don't support these types. */ diff --git a/src/box/tuple_compare.cc b/src/box/tuple_compare.cc index c1a70a087..95a0f58c9 100644 --- a/src/box/tuple_compare.cc +++ b/src/box/tuple_compare.cc @@ -404,6 +404,8 @@ tuple_compare_field(const char *field_a, const char *field_b, return mp_compare_number(field_a, field_b); case FIELD_TYPE_BOOLEAN: return mp_compare_bool(field_a, field_b); + case FIELD_TYPE_VARBINARY: + return mp_compare_bin(field_a, field_b); case FIELD_TYPE_SCALAR: return coll != NULL ? mp_compare_scalar_coll(field_a, field_b, coll) : @@ -434,6 +436,8 @@ tuple_compare_field_with_type(const char *field_a, enum mp_type a_type, field_b, b_type); case FIELD_TYPE_BOOLEAN: return mp_compare_bool(field_a, field_b); + case FIELD_TYPE_VARBINARY: + return mp_compare_bin(field_a, field_b); case FIELD_TYPE_SCALAR: return coll != NULL ? mp_compare_scalar_coll(field_a, field_b, coll) : @@ -1502,6 +1506,14 @@ field_hint_string(const char *field, struct coll *coll) hint_str_coll(field, len, coll); } +static inline hint_t +field_hint_varbinary(const char *field) +{ + assert(mp_typeof(*field) == MP_BIN); + uint32_t len = mp_decode_binl(&field); + return hint_bin(field, len); +} + static inline hint_t field_hint_scalar(const char *field, struct coll *coll) { @@ -1547,6 +1559,8 @@ field_hint(const char *field, struct coll *coll) return field_hint_number(field); case FIELD_TYPE_STRING: return field_hint_string(field, coll); + case FIELD_TYPE_VARBINARY: + return field_hint_varbinary(field); case FIELD_TYPE_SCALAR: return field_hint_scalar(field, coll); default: @@ -1648,6 +1662,9 @@ key_def_set_hint_func(struct key_def *def) case FIELD_TYPE_STRING: key_def_set_hint_func<FIELD_TYPE_STRING>(def); break; + case FIELD_TYPE_VARBINARY: + key_def_set_hint_func<FIELD_TYPE_VARBINARY>(def); + break; case FIELD_TYPE_SCALAR: key_def_set_hint_func<FIELD_TYPE_SCALAR>(def); break; diff --git a/test/box/varbinary_type.result b/test/box/varbinary_type.result new file mode 100644 index 000000000..c7cd5700c --- /dev/null +++ b/test/box/varbinary_type.result @@ -0,0 +1,152 @@ +env = require('test_run') +--- +... +test_run = env.new() +--- +... +-- +-- gh-4201: Introduce varbinary field type. +-- +s = box.schema.space.create('withdata') +--- +... +s:format({{"b", "integer"}}) +--- +... +_ = s:create_index('pk', {parts = {1, "varbinary"}}) +--- +- error: Field 1 has type 'integer' in space format, but type 'varbinary' in index + definition +... +s:format({{"b", "varbinary"}}) +--- +... +_ = s:create_index('pk', {parts = {1, "integer"}}) +--- +- error: Field 1 has type 'varbinary' in space format, but type 'integer' in index + definition +... +pk = s:create_index('pk', {parts = {1, "varbinary"}}) +--- +... +buffer = require('buffer') +--- +... +ffi = require('ffi') +--- +... +test_run:cmd("setopt delimiter ';'") +--- +- true +... +function bintuple_insert(space, bytes) + local tmpbuf = buffer.IBUF_SHARED + tmpbuf:reset() + local p = tmpbuf:alloc(3 + #bytes) + p[0] = 0x91 + p[1] = 0xC4 + p[2] = #bytes + for i, c in pairs(bytes) do p[i + 3 - 1] = c end + ffi.cdef[[int box_insert(uint32_t space_id, const char *tuple, const char *tuple_end, box_tuple_t **result);]] + ffi.C.box_insert(space.id, tmpbuf.rpos, tmpbuf.wpos, nil) +end +test_run:cmd("setopt delimiter ''"); +--- +... +bintuple_insert(s, {0xDE, 0xAD, 0xBE, 0xAF}) +--- +... +bintuple_insert(s, {0xFE, 0xED, 0xFA, 0xCE}) +--- +... +s:select() +--- +- - [!!binary 3q2+rw==] + - [!!binary /u36zg==] +... +box.execute("SELECT * FROM \"withdata\" WHERE \"b\" < x'FEEDFACE';") +--- +- metadata: + - name: b + type: varbinary + rows: + - [!!binary 3q2+rw==] +... +pk:alter({parts = {1, "scalar"}}) +--- +... +s:format({{"b", "scalar"}}) +--- +... +s:insert({11}) +--- +- [11] +... +s:insert({22}) +--- +- [22] +... +s:insert({"11"}) +--- +- ['11'] +... +s:insert({"22"}) +--- +- ['22'] +... +s:select() +--- +- - [11] + - [22] + - ['11'] + - ['22'] + - [!!binary 3q2+rw==] + - [!!binary /u36zg==] +... +box.execute("SELECT * FROM \"withdata\" WHERE \"b\" <= x'DEADBEAF';") +--- +- metadata: + - name: b + type: scalar + rows: + - [11] + - [22] + - ['11'] + - ['22'] + - [!!binary 3q2+rw==] +... +pk:alter({parts = {1, "varbinary"}}) +--- +- error: 'Tuple field 1 type does not match one required by operation: expected varbinary' +... +s:delete({11}) +--- +- [11] +... +s:delete({22}) +--- +- [22] +... +s:delete({"11"}) +--- +- ['11'] +... +s:delete({"22"}) +--- +- ['22'] +... +bintuple_insert(s, {0xFA, 0xDE, 0xDE, 0xAD}) +--- +... +pk:alter({parts = {1, "varbinary"}}) +--- +... +s:select() +--- +- - [!!binary 3q2+rw==] + - [!!binary +t7erQ==] + - [!!binary /u36zg==] +... +s:drop() +--- +... diff --git a/test/box/varbinary_type.test.lua b/test/box/varbinary_type.test.lua new file mode 100644 index 000000000..7895a1d22 --- /dev/null +++ b/test/box/varbinary_type.test.lua @@ -0,0 +1,51 @@ +env = require('test_run') +test_run = env.new() + +-- +-- gh-4201: Introduce varbinary field type. +-- +s = box.schema.space.create('withdata') +s:format({{"b", "integer"}}) +_ = s:create_index('pk', {parts = {1, "varbinary"}}) +s:format({{"b", "varbinary"}}) +_ = s:create_index('pk', {parts = {1, "integer"}}) +pk = s:create_index('pk', {parts = {1, "varbinary"}}) + +buffer = require('buffer') +ffi = require('ffi') + +test_run:cmd("setopt delimiter ';'") +function bintuple_insert(space, bytes) + local tmpbuf = buffer.IBUF_SHARED + tmpbuf:reset() + local p = tmpbuf:alloc(3 + #bytes) + p[0] = 0x91 + p[1] = 0xC4 + p[2] = #bytes + for i, c in pairs(bytes) do p[i + 3 - 1] = c end + ffi.cdef[[int box_insert(uint32_t space_id, const char *tuple, const char *tuple_end, box_tuple_t **result);]] + ffi.C.box_insert(space.id, tmpbuf.rpos, tmpbuf.wpos, nil) +end +test_run:cmd("setopt delimiter ''"); + +bintuple_insert(s, {0xDE, 0xAD, 0xBE, 0xAF}) +bintuple_insert(s, {0xFE, 0xED, 0xFA, 0xCE}) +s:select() +box.execute("SELECT * FROM \"withdata\" WHERE \"b\" < x'FEEDFACE';") +pk:alter({parts = {1, "scalar"}}) +s:format({{"b", "scalar"}}) +s:insert({11}) +s:insert({22}) +s:insert({"11"}) +s:insert({"22"}) +s:select() +box.execute("SELECT * FROM \"withdata\" WHERE \"b\" <= x'DEADBEAF';") +pk:alter({parts = {1, "varbinary"}}) +s:delete({11}) +s:delete({22}) +s:delete({"11"}) +s:delete({"22"}) +bintuple_insert(s, {0xFA, 0xDE, 0xDE, 0xAD}) +pk:alter({parts = {1, "varbinary"}}) +s:select() +s:drop() -- 2.21.0 ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [tarantool-patches] Re: [PATCH v1 1/1] box: introduce VARBINARY field type 2019-06-27 7:38 ` [tarantool-patches] " Kirill Shcherbatov @ 2019-06-27 8:01 ` Konstantin Osipov 0 siblings, 0 replies; 5+ messages in thread From: Konstantin Osipov @ 2019-06-27 8:01 UTC (permalink / raw) To: Kirill Shcherbatov; +Cc: tarantool-patches, Vladimir Davydov * Kirill Shcherbatov <kshcherbatov@tarantool.org> [19/06/27 10:40]: > > please add docbot request. > > In fact, I did not include TarantoolBot query consciously: this patch is preparatory for #4206, and only > introduces a new field type, while preparing data corresponding to this field in Tarantool now > is not easy (see the test case below). > > But in general, the documentation may be updated. So I've updated a commit message. since it's usable in format/index definitions, it's an external behaviour change and has to be documented. Actually it's going to be a sweeping changes in many places in the docs, since the type system has multiple mentions in the docs. > ========================================== > > A new VARBINARY field type would be useful for SQL type system. > > Closes #4201 > Needed for #4206 > > @TarantoolBot document > Title: new varbinary field type > > Introduced a new field type varbinary to represent mp_bin values. > The new type varbinary may be used in format or index definition. > > Example: > s = box.schema.space.create('withdata') > s:format({{"b", "varbinary"}}) > pk = s:create_index('pk', {parts = {1, "varbinary"}}) > --- > src/box/field_def.c | 23 +++-- > src/box/field_def.h | 1 + > src/box/lua/key_def.c | 1 + > src/box/tuple_compare.cc | 17 ++++ > test/box/varbinary_type.result | 152 +++++++++++++++++++++++++++++++ > test/box/varbinary_type.test.lua | 51 +++++++++++ > 6 files changed, 235 insertions(+), 10 deletions(-) > create mode 100644 test/box/varbinary_type.result > create mode 100644 test/box/varbinary_type.test.lua > > diff --git a/src/box/field_def.c b/src/box/field_def.c > index 0ba3d3294..346042b98 100644 > --- a/src/box/field_def.c > +++ b/src/box/field_def.c > @@ -55,6 +55,7 @@ const uint32_t field_mp_type[] = { > (1U << MP_FLOAT) | (1U << MP_DOUBLE), > /* [FIELD_TYPE_INTEGER] = */ (1U << MP_UINT) | (1U << MP_INT), > /* [FIELD_TYPE_BOOLEAN] = */ 1U << MP_BOOL, > + /* [FIELD_TYPE_VARBINARY] = */ 1U << MP_BIN, > /* [FIELD_TYPE_SCALAR] = */ (1U << MP_UINT) | (1U << MP_INT) | > (1U << MP_FLOAT) | (1U << MP_DOUBLE) | (1U << MP_STR) | > (1U << MP_BIN) | (1U << MP_BOOL), > @@ -69,6 +70,7 @@ const char *field_type_strs[] = { > /* [FIELD_TYPE_NUMBER] = */ "number", > /* [FIELD_TYPE_INTEGER] = */ "integer", > /* [FIELD_TYPE_BOOLEAN] = */ "boolean", > + /* [FIELD_TYPE_VARBINARY] = */"varbinary", > /* [FIELD_TYPE_SCALAR] = */ "scalar", > /* [FIELD_TYPE_ARRAY] = */ "array", > /* [FIELD_TYPE_MAP] = */ "map", > @@ -96,16 +98,17 @@ field_type_by_name_wrapper(const char *str, uint32_t len) > * values can be stored in the j type. > */ > static const bool field_type_compatibility[] = { > - /* ANY UNSIGNED STRING NUMBER INTEGER BOOLEAN SCALAR ARRAY MAP */ > -/* ANY */ true, false, false, false, false, false, false, false, false, > -/* UNSIGNED */ true, true, false, true, true, false, true, false, false, > -/* STRING */ true, false, true, false, false, false, true, false, false, > -/* NUMBER */ true, false, false, true, false, false, true, false, false, > -/* INTEGER */ true, false, false, true, true, false, true, false, false, > -/* BOOLEAN */ true, false, false, false, false, true, true, false, false, > -/* SCALAR */ true, false, false, false, false, false, true, false, false, > -/* ARRAY */ true, false, false, false, false, false, false, true, false, > -/* MAP */ true, false, false, false, false, false, false, false, true, > + /* ANY UNSIGNED STRING NUMBER INTEGER BOOLEAN VARBINARY SCALAR ARRAY MAP */ > +/* ANY */ true, false, false, false, false, false, false, false, false, false, > +/* UNSIGNED */ true, true, false, true, true, false, false, true, false, false, > +/* STRING */ true, false, true, false, false, false, false, true, false, false, > +/* NUMBER */ true, false, false, true, false, false, false, true, false, false, > +/* INTEGER */ true, false, false, true, true, false, false, true, false, false, > +/* BOOLEAN */ true, false, false, false, false, true, false, true, false, false, > +/* VARBINARY*/ true, false, false, false, false, false, true, true, false, false, > +/* SCALAR */ true, false, false, false, false, false, false, true, false, false, > +/* ARRAY */ true, false, false, false, false, false, false, false, true, false, > +/* MAP */ true, false, false, false, false, false, false, false, false, true, > }; > > bool > diff --git a/src/box/field_def.h b/src/box/field_def.h > index f944de9d6..c1a7ec0a9 100644 > --- a/src/box/field_def.h > +++ b/src/box/field_def.h > @@ -56,6 +56,7 @@ enum field_type { > FIELD_TYPE_NUMBER, > FIELD_TYPE_INTEGER, > FIELD_TYPE_BOOLEAN, > + FIELD_TYPE_VARBINARY, > FIELD_TYPE_SCALAR, > FIELD_TYPE_ARRAY, > FIELD_TYPE_MAP, > diff --git a/src/box/lua/key_def.c b/src/box/lua/key_def.c > index dfcc89442..052a1c85d 100644 > --- a/src/box/lua/key_def.c > +++ b/src/box/lua/key_def.c > @@ -111,6 +111,7 @@ luaT_key_def_set_part(struct lua_State *L, struct key_part_def *part, > part->type = field_type_by_name(type_name, type_len); > switch (part->type) { > case FIELD_TYPE_ANY: > + case FIELD_TYPE_VARBINARY: > case FIELD_TYPE_ARRAY: > case FIELD_TYPE_MAP: > /* Tuple comparators don't support these types. */ > diff --git a/src/box/tuple_compare.cc b/src/box/tuple_compare.cc > index c1a70a087..95a0f58c9 100644 > --- a/src/box/tuple_compare.cc > +++ b/src/box/tuple_compare.cc > @@ -404,6 +404,8 @@ tuple_compare_field(const char *field_a, const char *field_b, > return mp_compare_number(field_a, field_b); > case FIELD_TYPE_BOOLEAN: > return mp_compare_bool(field_a, field_b); > + case FIELD_TYPE_VARBINARY: > + return mp_compare_bin(field_a, field_b); > case FIELD_TYPE_SCALAR: > return coll != NULL ? > mp_compare_scalar_coll(field_a, field_b, coll) : > @@ -434,6 +436,8 @@ tuple_compare_field_with_type(const char *field_a, enum mp_type a_type, > field_b, b_type); > case FIELD_TYPE_BOOLEAN: > return mp_compare_bool(field_a, field_b); > + case FIELD_TYPE_VARBINARY: > + return mp_compare_bin(field_a, field_b); > case FIELD_TYPE_SCALAR: > return coll != NULL ? > mp_compare_scalar_coll(field_a, field_b, coll) : > @@ -1502,6 +1506,14 @@ field_hint_string(const char *field, struct coll *coll) > hint_str_coll(field, len, coll); > } > > +static inline hint_t > +field_hint_varbinary(const char *field) > +{ > + assert(mp_typeof(*field) == MP_BIN); > + uint32_t len = mp_decode_binl(&field); > + return hint_bin(field, len); > +} > + > static inline hint_t > field_hint_scalar(const char *field, struct coll *coll) > { > @@ -1547,6 +1559,8 @@ field_hint(const char *field, struct coll *coll) > return field_hint_number(field); > case FIELD_TYPE_STRING: > return field_hint_string(field, coll); > + case FIELD_TYPE_VARBINARY: > + return field_hint_varbinary(field); > case FIELD_TYPE_SCALAR: > return field_hint_scalar(field, coll); > default: > @@ -1648,6 +1662,9 @@ key_def_set_hint_func(struct key_def *def) > case FIELD_TYPE_STRING: > key_def_set_hint_func<FIELD_TYPE_STRING>(def); > break; > + case FIELD_TYPE_VARBINARY: > + key_def_set_hint_func<FIELD_TYPE_VARBINARY>(def); > + break; > case FIELD_TYPE_SCALAR: > key_def_set_hint_func<FIELD_TYPE_SCALAR>(def); > break; > diff --git a/test/box/varbinary_type.result b/test/box/varbinary_type.result > new file mode 100644 > index 000000000..c7cd5700c > --- /dev/null > +++ b/test/box/varbinary_type.result > @@ -0,0 +1,152 @@ > +env = require('test_run') > +--- > +... > +test_run = env.new() > +--- > +... > +-- > +-- gh-4201: Introduce varbinary field type. > +-- > +s = box.schema.space.create('withdata') > +--- > +... > +s:format({{"b", "integer"}}) > +--- > +... > +_ = s:create_index('pk', {parts = {1, "varbinary"}}) > +--- > +- error: Field 1 has type 'integer' in space format, but type 'varbinary' in index > + definition > +... > +s:format({{"b", "varbinary"}}) > +--- > +... > +_ = s:create_index('pk', {parts = {1, "integer"}}) > +--- > +- error: Field 1 has type 'varbinary' in space format, but type 'integer' in index > + definition > +... > +pk = s:create_index('pk', {parts = {1, "varbinary"}}) > +--- > +... > +buffer = require('buffer') > +--- > +... > +ffi = require('ffi') > +--- > +... > +test_run:cmd("setopt delimiter ';'") > +--- > +- true > +... > +function bintuple_insert(space, bytes) > + local tmpbuf = buffer.IBUF_SHARED > + tmpbuf:reset() > + local p = tmpbuf:alloc(3 + #bytes) > + p[0] = 0x91 > + p[1] = 0xC4 > + p[2] = #bytes > + for i, c in pairs(bytes) do p[i + 3 - 1] = c end > + ffi.cdef[[int box_insert(uint32_t space_id, const char *tuple, const char *tuple_end, box_tuple_t **result);]] > + ffi.C.box_insert(space.id, tmpbuf.rpos, tmpbuf.wpos, nil) > +end > +test_run:cmd("setopt delimiter ''"); > +--- > +... > +bintuple_insert(s, {0xDE, 0xAD, 0xBE, 0xAF}) > +--- > +... > +bintuple_insert(s, {0xFE, 0xED, 0xFA, 0xCE}) > +--- > +... > +s:select() > +--- > +- - [!!binary 3q2+rw==] > + - [!!binary /u36zg==] > +... > +box.execute("SELECT * FROM \"withdata\" WHERE \"b\" < x'FEEDFACE';") > +--- > +- metadata: > + - name: b > + type: varbinary > + rows: > + - [!!binary 3q2+rw==] > +... > +pk:alter({parts = {1, "scalar"}}) > +--- > +... > +s:format({{"b", "scalar"}}) > +--- > +... > +s:insert({11}) > +--- > +- [11] > +... > +s:insert({22}) > +--- > +- [22] > +... > +s:insert({"11"}) > +--- > +- ['11'] > +... > +s:insert({"22"}) > +--- > +- ['22'] > +... > +s:select() > +--- > +- - [11] > + - [22] > + - ['11'] > + - ['22'] > + - [!!binary 3q2+rw==] > + - [!!binary /u36zg==] > +... > +box.execute("SELECT * FROM \"withdata\" WHERE \"b\" <= x'DEADBEAF';") > +--- > +- metadata: > + - name: b > + type: scalar > + rows: > + - [11] > + - [22] > + - ['11'] > + - ['22'] > + - [!!binary 3q2+rw==] > +... > +pk:alter({parts = {1, "varbinary"}}) > +--- > +- error: 'Tuple field 1 type does not match one required by operation: expected varbinary' > +... > +s:delete({11}) > +--- > +- [11] > +... > +s:delete({22}) > +--- > +- [22] > +... > +s:delete({"11"}) > +--- > +- ['11'] > +... > +s:delete({"22"}) > +--- > +- ['22'] > +... > +bintuple_insert(s, {0xFA, 0xDE, 0xDE, 0xAD}) > +--- > +... > +pk:alter({parts = {1, "varbinary"}}) > +--- > +... > +s:select() > +--- > +- - [!!binary 3q2+rw==] > + - [!!binary +t7erQ==] > + - [!!binary /u36zg==] > +... > +s:drop() > +--- > +... > diff --git a/test/box/varbinary_type.test.lua b/test/box/varbinary_type.test.lua > new file mode 100644 > index 000000000..7895a1d22 > --- /dev/null > +++ b/test/box/varbinary_type.test.lua > @@ -0,0 +1,51 @@ > +env = require('test_run') > +test_run = env.new() > + > +-- > +-- gh-4201: Introduce varbinary field type. > +-- > +s = box.schema.space.create('withdata') > +s:format({{"b", "integer"}}) > +_ = s:create_index('pk', {parts = {1, "varbinary"}}) > +s:format({{"b", "varbinary"}}) > +_ = s:create_index('pk', {parts = {1, "integer"}}) > +pk = s:create_index('pk', {parts = {1, "varbinary"}}) > + > +buffer = require('buffer') > +ffi = require('ffi') > + > +test_run:cmd("setopt delimiter ';'") > +function bintuple_insert(space, bytes) > + local tmpbuf = buffer.IBUF_SHARED > + tmpbuf:reset() > + local p = tmpbuf:alloc(3 + #bytes) > + p[0] = 0x91 > + p[1] = 0xC4 > + p[2] = #bytes > + for i, c in pairs(bytes) do p[i + 3 - 1] = c end > + ffi.cdef[[int box_insert(uint32_t space_id, const char *tuple, const char *tuple_end, box_tuple_t **result);]] > + ffi.C.box_insert(space.id, tmpbuf.rpos, tmpbuf.wpos, nil) > +end > +test_run:cmd("setopt delimiter ''"); > + > +bintuple_insert(s, {0xDE, 0xAD, 0xBE, 0xAF}) > +bintuple_insert(s, {0xFE, 0xED, 0xFA, 0xCE}) > +s:select() > +box.execute("SELECT * FROM \"withdata\" WHERE \"b\" < x'FEEDFACE';") > +pk:alter({parts = {1, "scalar"}}) > +s:format({{"b", "scalar"}}) > +s:insert({11}) > +s:insert({22}) > +s:insert({"11"}) > +s:insert({"22"}) > +s:select() > +box.execute("SELECT * FROM \"withdata\" WHERE \"b\" <= x'DEADBEAF';") > +pk:alter({parts = {1, "varbinary"}}) > +s:delete({11}) > +s:delete({22}) > +s:delete({"11"}) > +s:delete({"22"}) > +bintuple_insert(s, {0xFA, 0xDE, 0xDE, 0xAD}) > +pk:alter({parts = {1, "varbinary"}}) > +s:select() > +s:drop() > -- > 2.21.0 > -- Konstantin Osipov, Moscow, Russia ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v1 1/1] box: introduce VARBINARY field type 2019-06-26 16:40 [PATCH v1 1/1] box: introduce VARBINARY field type Kirill Shcherbatov 2019-06-26 19:11 ` [tarantool-patches] " Konstantin Osipov @ 2019-07-03 10:10 ` Vladimir Davydov 1 sibling, 0 replies; 5+ messages in thread From: Vladimir Davydov @ 2019-07-03 10:10 UTC (permalink / raw) To: Kirill Shcherbatov; +Cc: tarantool-patches Pushed to master, thanks! ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2019-07-03 10:10 UTC | newest] Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2019-06-26 16:40 [PATCH v1 1/1] box: introduce VARBINARY field type Kirill Shcherbatov 2019-06-26 19:11 ` [tarantool-patches] " Konstantin Osipov 2019-06-27 7:38 ` [tarantool-patches] " Kirill Shcherbatov 2019-06-27 8:01 ` Konstantin Osipov 2019-07-03 10:10 ` Vladimir Davydov
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox