diff --git a/src/box/bind.c b/src/box/bind.c index af9f9eac54c491e16f142f786e27eaf6b381ecb0..441c9f46fff062b64fd54f9749cc94ee87d81c43 100644 --- a/src/box/bind.c +++ b/src/box/bind.c @@ -100,15 +100,12 @@ sql_bind_decode(struct sql_bind *bind, int i, const char **packet) bind->s = mp_decode_bin(packet, &bind->bytes); break; case MP_ARRAY: + case MP_MAP: case MP_EXT: bind->s = *packet; mp_next(packet); bind->bytes = *packet - bind->s; break; - case MP_MAP: - diag_set(ClientError, ER_SQL_BIND_TYPE, "MAP", - sql_bind_name(bind)); - return -1; default: unreachable(); } @@ -189,6 +186,8 @@ sql_bind_column(struct sql_stmt *stmt, const struct sql_bind *p, return sql_bind_bin_static(stmt, pos, p->s, p->bytes); case MP_ARRAY: return sql_bind_array_static(stmt, pos, p->s, p->bytes); + case MP_MAP: + return sql_bind_map_static(stmt, pos, p->s, p->bytes); case MP_EXT: assert(p->ext_type == MP_UUID || p->ext_type == MP_DECIMAL); if (p->ext_type == MP_UUID) diff --git a/src/box/lua/execute.c b/src/box/lua/execute.c index 71d4d7faed03e0f475de4ba3322b0e551da09135..b3f81d709fb962f877302295551ac7eb2dbf1c1e 100644 --- a/src/box/lua/execute.c +++ b/src/box/lua/execute.c @@ -386,6 +386,7 @@ lua_sql_bind_decode(struct lua_State *L, struct sql_bind *bind, int idx, int i) diag_set(ClientError, ER_SQL_BIND_TYPE, "USERDATA", sql_bind_name(bind)); return -1; + case MP_MAP: case MP_ARRAY: { size_t used = region_used(region); struct mpstream stream; @@ -410,10 +411,6 @@ lua_sql_bind_decode(struct lua_State *L, struct sql_bind *bind, int idx, int i) diag_set(OutOfMemory, bind->bytes, "region_join", "bind->s"); return -1; } - case MP_MAP: - diag_set(ClientError, ER_SQL_BIND_TYPE, "MAP", - sql_bind_name(bind)); - return -1; default: unreachable(); } diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h index 716110edc69b58c1fb7babf0023819da81be5c98..0db16b293c593c84ad878fcecfed4976c5fa61c1 100644 --- a/src/box/sql/sqlInt.h +++ b/src/box/sql/sqlInt.h @@ -559,6 +559,9 @@ sql_bind_bin_static(sql_stmt *stmt, int i, const char *str, uint32_t size); int sql_bind_array_static(sql_stmt *stmt, int i, const char *str, uint32_t size); +int +sql_bind_map_static(sql_stmt *stmt, int i, const char *str, uint32_t size); + int sql_bind_uuid(struct sql_stmt *stmt, int i, const struct tt_uuid *uuid); diff --git a/src/box/sql/vdbeapi.c b/src/box/sql/vdbeapi.c index 3ea155d17bce81119f44e7a7351cb74432675e49..060846572f4769b05b9e9c109d421d91e54649ab 100644 --- a/src/box/sql/vdbeapi.c +++ b/src/box/sql/vdbeapi.c @@ -532,6 +532,14 @@ sql_bind_array_static(sql_stmt *stmt, int i, const char *str, uint32_t size) return sql_bind_type(vdbe, i, "array"); } +int +sql_bind_map_static(sql_stmt *stmt, int i, const char *str, uint32_t size) +{ + struct Vdbe *vdbe = (struct Vdbe *)stmt; + mem_set_map_static(&vdbe->aVar[i - 1], (char *)str, size); + return sql_bind_type(vdbe, i, "map"); +} + int sql_bind_uuid(struct sql_stmt *stmt, int i, const struct tt_uuid *uuid) { diff --git a/test/sql-tap/map.test.lua b/test/sql-tap/map.test.lua index 1afbb2b1de600157645a7d66b1e3bc1b8fb48519..8cdbb16629b3235fba61218d94319bd44efb5f53 100755 --- a/test/sql-tap/map.test.lua +++ b/test/sql-tap/map.test.lua @@ -1,6 +1,6 @@ #!/usr/bin/env tarantool local test = require("sqltester") -test:plan(110) +test:plan(112) box.schema.func.create('M1', { language = 'Lua', @@ -982,6 +982,29 @@ test:do_catchsql_test( 1, "Failed to execute SQL statement: wrong arguments for function ZEROBLOB()" }) +-- Make sure that MAP values can be used as a bound variable. +test:do_test( + "builtins-13.1", + function() + local res = box.execute([[SELECT #a;]], {{['#a'] = {abc = 2, [1] = 3}}}) + return {res.rows[1][1]} + end, { + {abc = 2, [1] = 3} + }) + +local remote = require('net.box') +box.cfg{listen = os.getenv('LISTEN')} +local cn = remote.connect(box.cfg.listen) +test:do_test( + "builtins-13.2", + function() + local res = cn:execute([[SELECT #a;]], {{['#a'] = {abc = 2, [1] = 3}}}) + return {res.rows[1][1]} + end, { + {abc = 2, [1] = 3} + }) +cn:close() + box.execute([[DROP TABLE t1;]]) box.execute([[DROP TABLE t;]]) diff --git a/test/sql/bind.result b/test/sql/bind.result index f269056e22c98715baaf1ccdfddd0c45f436a89d..e738a91cda8f80ccc0ddfda469a813bdaa47ca0d 100644 --- a/test/sql/bind.result +++ b/test/sql/bind.result @@ -276,7 +276,11 @@ parameters[1][':value'] = {kek = 300} ... execute('SELECT :value', parameters) --- -- error: Bind value type MAP for parameter ':value' is not supported +- metadata: + - name: COLUMN_1 + type: map + rows: + - [{'kek': 300}] ... -- gh-3810: bind values of integer in range up to 2^64 - 1. --