Skip to content

Commit d9542b8

Browse files
Ilyartsisyk
Ilya
authored andcommitted
Add tnt_execute method to sql execution
1 parent 3344f8c commit d9542b8

File tree

9 files changed

+241
-4
lines changed

9 files changed

+241
-4
lines changed

include/tarantool/tarantool.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ extern "C" {
5050
#include <tarantool/tnt_object.h>
5151
#include <tarantool/tnt_iter.h>
5252
#include <tarantool/tnt_call.h>
53+
#include <tarantool/tnt_execute.h>
5354
#include <tarantool/tnt_ping.h>
5455
#include <tarantool/tnt_insert.h>
5556
#include <tarantool/tnt_delete.h>

include/tarantool/tnt_execute.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#ifndef TNT_EXECUTE_H_INCLUDED
2+
#define TNT_EXECUTE_H_INCLUDED
3+
4+
/**
5+
* \file tnt_execute.h
6+
* \brief SQL execution request
7+
*/
8+
9+
/**
10+
* \brief Construct SQL request and write it into stream
11+
*
12+
* \param s stream object to write request to
13+
* \param expr SQL query string
14+
* \param elen query length
15+
* \param args tnt_object instance with messagepack array with params
16+
* to bind to the request
17+
*
18+
* \retval number of bytes written to stream
19+
*/
20+
ssize_t
21+
tnt_execute(struct tnt_stream *s, const char *expr, size_t elen,
22+
struct tnt_stream *params);
23+
24+
#endif /* TNT_EXECUTE_H_INCLUDED */

include/tarantool/tnt_proto.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,18 @@ enum tnt_body_key_t {
6666
TNT_VCLOCK = 0x26,
6767
TNT_EXPRESSION = 0x27,
6868
TNT_OPS = 0x28,
69-
69+
TNT_SQL_TEXT = 0x40,
70+
TNT_SQL_BIND = 0x41,
7071
};
7172

7273
/**
7374
* \brief Response body field types (keys)
7475
*/
7576
enum tnt_response_key_t {
7677
TNT_DATA = 0x30,
77-
TNT_ERROR = 0x31
78+
TNT_ERROR = 0x31,
79+
TNT_METADATA = 0x32,
80+
TNT_SQL_INFO = 0x43,
7881
};
7982

8083
/**
@@ -91,6 +94,7 @@ enum tnt_request_t {
9194
TNT_OP_EVAL = 8,
9295
TNT_OP_UPSERT = 9,
9396
TNT_OP_CALL = 10,
97+
TNT_OP_EXECUTE = 11,
9498
TNT_OP_PING = 64,
9599
TNT_OP_JOIN = 65,
96100
TNT_OP_SUBSCRIBE = 66

include/tarantool/tnt_reply.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ struct tnt_reply {
6767
const char *error_end; /*!< end of error message (NULL if not present) */
6868
const char *data; /*!< tuple data (NULL if not present) */
6969
const char *data_end; /*!< end if tuple data (NULL if not present) */
70+
const char *metadata; /*!< tuple metadata (NULL if not present) */
71+
const char *metadata_end; /*!< end if tuple metadata (NULL if not present) */
72+
const char *sqlinfo; /*!< map sqlinfo (NULL if not present) */
73+
const char *sqlinfo_end;/*!< end if map sqlinfo (NULL if not present) */
7074
};
7175

7276
/*!

test/shared/box.lua

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ for k, v in pairs(lp) do
4040
if k == 'test' then
4141
box.schema.user.grant('test', 'read', 'space', '_space')
4242
box.schema.user.grant('test', 'read', 'space', '_index')
43+
box.schema.user.grant('test', 'read', 'space', '_truncate')
4344
box.schema.user.grant('test', 'execute', 'universe')
45+
box.schema.user.grant('test', 'write', 'universe')
4446
end
4547
end
4648
end

test/tarantool_unix.c

Lines changed: 115 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,121 @@ test_insert_replace_delete(char *uri) {
287287
return check_plan();
288288
}
289289

290+
static int
291+
test_execute(char *uri) {
292+
plan(43);
293+
header();
294+
295+
const char bb1[]="\x83\x00\xce\x00\x00\x00\x00\x01\xcf\x00\x00\x00\x00\x00"
296+
"\x00\x00\x01\x05\xce\x00\x00\x00\x3f\x81\x43\xdf\x00\x00"
297+
"\x00\x01\x44\x01";
298+
size_t bb1_len = sizeof(bb1) - 1;
299+
300+
const char bb2[]="\x83\x00\xce\x00\x00\x00\x00\x01\xcf\x00\x00\x00\x00\x00"
301+
"\x00\x00\x02\x05\xce\x00\x00\x00\x3f\x81\x43\xdf\x00\x00"
302+
"\x00\x01\x44\x01";
303+
size_t bb2_len = sizeof(bb2) - 1;
304+
305+
const char bb3[]="\x83\x00\xce\x00\x00\x00\x00\x01\xcf\x00\x00\x00\x00\x00"
306+
"\x00\x00\x03\x05\xce\x00\x00\x00\x3f\x82\x32\xdd\x00\x00"
307+
"\x00\x01\x81\x29\xa2\x69\x64\x30\xdd\x00\x00\x00\x01\x91"
308+
"\x00";
309+
size_t bb3_len = sizeof(bb3) - 1;
310+
311+
const char bb4[]="\x83\x00\xce\x00\x00\x00\x00\x01\xcf\x00\x00\x00\x00\x00"
312+
"\x00\x00\x04\x05\xce\x00\x00\x00\x41\x81\x43\xdf\x00\x00"
313+
"\x00\x01\x44\x01";
314+
size_t bb4_len = sizeof(bb4) - 1;
315+
316+
struct tnt_reply reply;
317+
char *query;
318+
struct tnt_stream *args = NULL;
319+
320+
struct tnt_stream *tnt = NULL; tnt = tnt_net(NULL);
321+
isnt(tnt, NULL, "Check connection creation");
322+
isnt(tnt_set(tnt, TNT_OPT_URI, uri), -1, "Setting URI");
323+
isnt(tnt_connect(tnt), -1, "Connecting");
324+
325+
args = tnt_object(NULL);
326+
isnt(args, NULL, "Check object creation");
327+
isnt(tnt_object_format(args, "[]"), -1, "check object filling");
328+
query = "CREATE TABLE test_table(id INTEGER, PRIMARY KEY (id))";
329+
isnt(tnt_execute(tnt, query, strlen(query), args), -1,
330+
"Create execute sql request: create table");
331+
isnt(tnt_flush(tnt), -1, "Send to server");
332+
tnt_stream_free(args);
333+
334+
tnt_reply_init(&reply);
335+
isnt(tnt->read_reply(tnt, &reply), -1, "Read reply from server");
336+
is (check_rbytes(&reply, bb1, bb1_len), 0, "Check response");
337+
is (reply.error, NULL, "Check error absence");
338+
isnt(reply.sqlinfo, NULL, "Check sqlinfo presence");
339+
is (reply.metadata, NULL, "Check metadata absence");
340+
is (reply.data, NULL, "Check data absence");
341+
tnt_reply_free(&reply);
342+
343+
args = tnt_object(NULL);
344+
isnt(args, NULL, "Check object creation");
345+
isnt(tnt_object_format(args, "[%d]", 0), -1, "check object filling");
346+
query = "INSERT INTO test_table(id) VALUES (?)";
347+
isnt(tnt_execute(tnt, query, strlen(query), args), -1,
348+
"Create execute sql request: insert row");
349+
isnt(tnt_flush(tnt), -1, "Send to server");
350+
tnt_stream_free(args);
351+
352+
tnt_reply_init(&reply);
353+
isnt(tnt->read_reply(tnt, &reply), -1, "Read reply from server");
354+
is (check_rbytes(&reply, bb2, bb2_len), 0, "Check response");
355+
is (reply.error, NULL, "Check error absence");
356+
isnt(reply.sqlinfo, NULL, "Check sqlinfo presence");
357+
is (reply.metadata, NULL, "Check metadata absence");
358+
is (reply.data, NULL, "Check data absence");
359+
tnt_reply_free(&reply);
360+
361+
args = tnt_object(NULL);
362+
isnt(args, NULL, "Check object creation");
363+
isnt(tnt_object_format(args, "[]"), -1, "check object filling");
364+
query = "select * from test_table";
365+
isnt(tnt_execute(tnt, query, strlen(query), args), -1,
366+
"Create execute sql request: select");
367+
isnt(tnt_flush(tnt), -1, "Send to server");
368+
tnt_stream_free(args);
369+
370+
tnt_reply_init(&reply);
371+
isnt(tnt->read_reply(tnt, &reply), -1, "Read reply from server");
372+
is (check_rbytes(&reply, bb3, bb3_len), 0, "Check response");
373+
is (reply.error, NULL, "Check error absence");
374+
is (reply.sqlinfo, NULL, "Check sqlinfo absence");
375+
isnt(reply.metadata, NULL, "Check metadata presence");
376+
isnt(reply.data, NULL, "Check data presence");
377+
tnt_reply_free(&reply);
378+
379+
args = tnt_object(NULL);
380+
isnt(args, NULL, "Check object creation");
381+
isnt(tnt_object_format(args, "[]"), -1, "check object filling");
382+
query = "drop table test_table";
383+
isnt(tnt_execute(tnt, query, strlen(query), args), -1,
384+
"Create execute sql request: drop table");
385+
isnt(tnt_flush(tnt), -1, "Send to server");
386+
tnt_stream_free(args);
387+
388+
tnt_reply_init(&reply);
389+
isnt(tnt->read_reply(tnt, &reply), -1, "Read reply from server");
390+
is (check_rbytes(&reply, bb4, bb4_len), 0, "Check response");
391+
is (reply.error, NULL, "Check error absence");
392+
isnt(reply.sqlinfo, NULL, "Check sqlinfo presence");
393+
is (reply.metadata, NULL, "Check metadata absence");
394+
is (reply.data, NULL, "Check data absence");
395+
tnt_reply_free(&reply);
396+
397+
tnt_stream_free(tnt);
398+
399+
footer();
400+
return check_plan();
401+
}
402+
290403
int main() {
291-
plan(4);
404+
plan(5);
292405

293406
char uri[128] = {0};
294407
snprintf(uri, 128, "%s%s", "test:test@", getenv("PRIMARY_PORT"));
@@ -297,6 +410,7 @@ int main() {
297410
test_ping(uri);
298411
test_auth_call(uri);
299412
test_insert_replace_delete(uri);
413+
test_execute(uri);
300414

301415
return check_plan();
302416
}

tnt/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ set (TNT_SOURCES
2828
${CMAKE_CURRENT_SOURCE_DIR}/tnt_select.c
2929
${CMAKE_CURRENT_SOURCE_DIR}/tnt_insert.c
3030
${CMAKE_CURRENT_SOURCE_DIR}/tnt_call.c
31+
${CMAKE_CURRENT_SOURCE_DIR}/tnt_execute.c
3132
${CMAKE_CURRENT_SOURCE_DIR}/tnt_delete.c
3233
${CMAKE_CURRENT_SOURCE_DIR}/tnt_update.c
3334
${CMAKE_CURRENT_SOURCE_DIR}/tnt_assoc.c

tnt/tnt_execute.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#include <assert.h>
2+
#include <stddef.h>
3+
#include <stdint.h>
4+
#include <limits.h>
5+
#include <string.h>
6+
#include <stdbool.h>
7+
#include <sys/types.h>
8+
9+
#include <msgpuck.h>
10+
11+
#include <tarantool/tnt_reply.h>
12+
#include <tarantool/tnt_stream.h>
13+
#include <tarantool/tnt_buf.h>
14+
#include <tarantool/tnt_object.h>
15+
#include <tarantool/tnt_execute.h>
16+
17+
#include "tnt_proto_internal.h"
18+
19+
ssize_t
20+
tnt_execute(struct tnt_stream *s, const char *expr, size_t elen,
21+
struct tnt_stream *params)
22+
{
23+
if (!expr || elen == 0)
24+
return -1;
25+
if (tnt_object_verify(params, MP_ARRAY))
26+
return -1;
27+
struct tnt_iheader hdr;
28+
struct iovec v[6];
29+
int v_sz = 6;
30+
char *data = NULL, *body_start = NULL;
31+
encode_header(&hdr, TNT_OP_EXECUTE, s->reqid++);
32+
v[1].iov_base = (void *) hdr.header;
33+
v[1].iov_len = hdr.end - hdr.header;
34+
char body[64];
35+
body_start = body;
36+
data = body;
37+
38+
data = mp_encode_map(data, 2);
39+
data = mp_encode_uint(data, TNT_SQL_TEXT);
40+
data = mp_encode_strl(data, elen);
41+
v[2].iov_base = body_start;
42+
v[2].iov_len = data - body_start;
43+
v[3].iov_base = (void *) expr;
44+
v[3].iov_len = elen;
45+
body_start = data;
46+
data = mp_encode_uint(data, TNT_SQL_BIND);
47+
v[4].iov_base = body_start;
48+
v[4].iov_len = data - body_start;
49+
v[5].iov_base = TNT_SBUF_DATA(params);
50+
v[5].iov_len = TNT_SBUF_SIZE(params);
51+
52+
size_t package_len = 0;
53+
for (int i = 1; i < v_sz; ++i)
54+
package_len += v[i].iov_len;
55+
char len_prefix[9];
56+
char *len_end = mp_encode_luint32(len_prefix, package_len);
57+
v[0].iov_base = len_prefix;
58+
v[0].iov_len = len_end - len_prefix;
59+
return s->writev(s, v, v_sz);
60+
}

tnt/tnt_reply.c

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,10 @@ tnt_reply_body0(struct tnt_reply *r, const char *buf, size_t size, size_t *off)
171171
return -1;
172172
if (mp_typeof(*p) != MP_MAP)
173173
return -1;
174-
const char *error = NULL, *error_end = NULL, *data = NULL, *data_end = NULL;
174+
const char *error = NULL, *error_end = NULL,
175+
*data = NULL, *data_end = NULL,
176+
*metadata = NULL, *metadata_end = NULL,
177+
*sqlinfo = NULL, *sqlinfo_end = NULL;
175178
uint64_t bitmap = 0;
176179
uint32_t n = mp_decode_map(&p);
177180
while (n-- > 0) {
@@ -193,6 +196,26 @@ tnt_reply_body0(struct tnt_reply *r, const char *buf, size_t size, size_t *off)
193196
data_end = p;
194197
break;
195198
}
199+
case TNT_METADATA: {
200+
if (mp_typeof(*p) != MP_ARRAY)
201+
return -1;
202+
metadata = p;
203+
mp_next(&p);
204+
metadata_end = p;
205+
break;
206+
}
207+
case TNT_SQL_INFO: {
208+
if (mp_typeof(*p) != MP_MAP)
209+
return -1;
210+
sqlinfo = p;
211+
mp_next(&p);
212+
sqlinfo_end = p;
213+
break;
214+
}
215+
default: {
216+
mp_next(&p);
217+
break;
218+
}
196219
}
197220
bitmap |= (1ULL << key);
198221
}
@@ -201,6 +224,10 @@ tnt_reply_body0(struct tnt_reply *r, const char *buf, size_t size, size_t *off)
201224
r->error_end = error_end;
202225
r->data = data;
203226
r->data_end = data_end;
227+
r->metadata = metadata;
228+
r->metadata_end = metadata_end;
229+
r->sqlinfo = sqlinfo;
230+
r->sqlinfo_end = sqlinfo_end;
204231
r->bitmap |= bitmap;
205232
}
206233
if (off)

0 commit comments

Comments
 (0)