Skip to content

Commit

Permalink
sql: make SQL_BIND optional in an iproto request
Browse files Browse the repository at this point in the history
The documentation [1] says this field is optional. I don't know which
commit lead to the regression, only that 2.1.1-7-gd381a45b6 is good.

[1]: https://tarantool.io/en/doc/2.1/dev_guide/internals/sql_protocol/

Fixes #4077.

(cherry picked from commit 7676b2b)
  • Loading branch information
Totktonada authored and kyukhin committed Mar 27, 2019
1 parent e484f1c commit 3f42ef0
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 5 deletions.
12 changes: 7 additions & 5 deletions src/box/iproto.cc
Expand Up @@ -1622,8 +1622,8 @@ tx_process_sql(struct cmsg *m)
struct iproto_msg *msg = tx_accept_msg(m);
struct obuf *out;
struct sql_response response;
struct sql_bind *bind;
int bind_count;
struct sql_bind *bind = NULL;
int bind_count = 0;
const char *sql;
uint32_t len;

Expand All @@ -1633,9 +1633,11 @@ tx_process_sql(struct cmsg *m)
goto error;
assert(msg->header.type == IPROTO_EXECUTE);
tx_inject_delay();
bind_count = sql_bind_list_decode(msg->sql.bind, &bind);
if (bind_count < 0)
goto error;
if (msg->sql.bind != NULL) {
bind_count = sql_bind_list_decode(msg->sql.bind, &bind);
if (bind_count < 0)
goto error;
}
sql = msg->sql.sql_text;
sql = mp_decode_str(&sql, &len);
if (sql_prepare_and_execute(sql, len, bind, bind_count, &response,
Expand Down
69 changes: 69 additions & 0 deletions test/sql-tap/gh-4077-iproto-execute-no-bind.test.lua
@@ -0,0 +1,69 @@
#!/usr/bin/env tarantool

local tap = require('tap')
local net_box = require('net.box')
local urilib = require('uri')
local msgpack = require('msgpack')

local IPROTO_REQUEST_TYPE = 0x00
local IPROTO_EXECUTE = 0x0b
local IPROTO_SYNC = 0x01
local IPROTO_SQL_TEXT = 0x40
local IPROTO_SQL_INFO = 0x42
local IPROTO_SQL_INFO_ROW_COUNT = 0x00
local IPROTO_OK = 0x00
local IPROTO_SCHEMA_VERSION = 0x05
local IPROTO_STATUS_KEY = 0x00

box.cfg({
listen = os.getenv('LISTEN') or 'localhost:3301',
})

box.schema.user.grant('guest', 'read,write,execute', 'universe')
box.sql.execute('create table T(ID int primary key)')

local test = tap.test('gh-4077-iproto-execute-no-bind')
test:plan(3)

local uri = urilib.parse(box.cfg.listen)
local sock = net_box.establish_connection(uri.host, uri.service)

-- Send request w/o SQL_BIND field in body.
local next_request_id = 16
local header = msgpack.encode({
[IPROTO_REQUEST_TYPE] = IPROTO_EXECUTE,
[IPROTO_SYNC] = next_request_id,
})
local body = msgpack.encode({
[IPROTO_SQL_TEXT] = 'insert into T values (1)',
})
local size = msgpack.encode(header:len() + body:len())
sock:write(size .. header .. body)

-- Read response.
local size = msgpack.decode(sock:read(5))
local header_body = sock:read(size)
local header, header_len = msgpack.decode(header_body)
local body = msgpack.decode(header_body:sub(header_len))
sock:close()

-- Verify response.
header[IPROTO_SCHEMA_VERSION] = nil -- expect any
local exp_header = {
[IPROTO_STATUS_KEY] = IPROTO_OK,
[IPROTO_SYNC] = next_request_id,
}
local exp_body = {
[IPROTO_SQL_INFO] = {
[IPROTO_SQL_INFO_ROW_COUNT] = 1,
}
}
test:is_deeply(exp_header, header, 'verify response header')
test:is_deeply(exp_body, body, 'verify response body')

-- Verify space data.
local exp_res = {{1}}
local res = box.space.T:pairs():map(box.tuple.totable):totable()
test:is_deeply(res, exp_res, 'verify inserted data')

os.exit(test:check() == true and 0 or 1)

0 comments on commit 3f42ef0

Please sign in to comment.