Skip to content

Commit 15f563f

Browse files
committed
add support of a new binary protocol command for "call"
* Added support for a new binary protocol command for "call" (used since tarantool 1.7.2). Unlike the old version, returned data is not converted to tuples (like in case of using "eval"). Default - call_16 mode. * Added options to "call" method. It can be used to force call_16 / call_17 mode. Example: ``` php $c = new Tarantool('localhost', 3301); $c->connect(); $c->call("test_call", array(), array('call_17' => true)); $c->close(); ``` Closes #101
1 parent 59d0739 commit 15f563f

File tree

8 files changed

+170
-25
lines changed

8 files changed

+170
-25
lines changed

README.md

+25-5
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ Tarantool {
122122
public array Tarantool::select (mixed $space [, mixed $key = array() [, mixed $index = 0 [, int $limit = PHP_INT_MAX [, int $offset = 0 [, $iterator = Tarantool::ITERATOR_EQ ] ] ] ] ] )
123123
public array Tarantool::insert (mixed $space, array $tuple)
124124
public array Tarantool::replace (mixed $space, array $tuple)
125-
public array Tarantool::call (string $procedure [, mixed args] )
125+
public array Tarantool::call (string $procedure [, mixed args [, array $opts ] ] )
126126
public array Tarantool::evaluate (string $expression [, mixed args] )
127127
public array Tarantool::delete (mixed $space, mixed $key [, mixed $index] )
128128
public array Tarantool::update (mixed $space, mixed $key, array $ops [, number $index] )
@@ -299,27 +299,47 @@ $tnt->replace("test", array(1, 3, "smth completely different"));
299299
### Tarantool::call
300300

301301
``` php
302-
public array Tarantool::call(string $procedure [, mixed args])
302+
public array Tarantool::call(string $procedure [, mixed args [, array $opts]])
303303
```
304304

305305
_**Description**_: Call stored procedure
306306

307307
_**Parameters**_
308308
* `procedure`: String, procedure to call (mandatory)
309-
* `args`: Any value to pass to procdure as arguments (empty by default)
309+
* `args`: Any value to pass to procedure as arguments (empty by default)
310+
* `opts`: Array, options
311+
312+
_**Options**_
313+
* call_17<br />
314+
If true - call_17 mode of "call" will be used
315+
(returned data has an arbitrary structure). Since tarantool 1.7.2.<br />
316+
If false - call_16 mode of "call" will be used
317+
(returned data converted to tuples).<br />
318+
Default - call_16 mode.
319+
```
320+
array(
321+
"call_17" => <bool>
322+
),
323+
```
310324

311325
_**Return Value**_
312326

327+
**BOOL**: False and raises `Exception` in case of error.
328+
329+
call_16 mode (default):
330+
313331
**Array of arrays** in case of success - tuples that were returned by stored
314332
procedure.
315333

316-
**BOOL**: False and raises `Exception` in case of error.
334+
call_17 mode:
335+
336+
**Any value**, that was returned by stored procedure.
317337

318338
#### Example
319339

320340
``` php
321341
$tnt->call("test_2");
322-
$tnt->call("test_3", array(3, 4));
342+
$tnt->call("test_3", array(3, 4), array('call_17' => true));
323343
```
324344

325345
### Tarantool::evaluate

src/tarantool.c

+66-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <time.h>
22
#include <stdio.h>
33
#include <limits.h>
4+
#include <string.h>
45

56
#include "php_tarantool.h"
67
#include "tarantool_internal.h"
@@ -14,6 +15,7 @@
1415

1516
#include "utils.h"
1617

18+
1719
static int __tarantool_authenticate(tarantool_connection *obj);
1820
static void tarantool_stream_close(tarantool_connection *obj);
1921

@@ -548,12 +550,19 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_tarantool_delete, 0, 0, 2)
548550
ZEND_ARG_INFO(0, index)
549551
ZEND_END_ARG_INFO()
550552

551-
/* call, eval */
553+
/* eval */
552554
ZEND_BEGIN_ARG_INFO_EX(arginfo_tarantool_proc_tuple, 0, 0, 1)
553555
ZEND_ARG_INFO(0, proc)
554556
ZEND_ARG_INFO(0, tuple)
555557
ZEND_END_ARG_INFO()
556558

559+
/* call */
560+
ZEND_BEGIN_ARG_INFO_EX(arginfo_tarantool_proc_call, 0, 0, 1)
561+
ZEND_ARG_INFO(0, proc)
562+
ZEND_ARG_INFO(0, tuple)
563+
ZEND_ARG_INFO(0, opts)
564+
ZEND_END_ARG_INFO()
565+
557566
ZEND_BEGIN_ARG_INFO_EX(arginfo_tarantool_update, 0, 0, 3)
558567
ZEND_ARG_INFO(0, space)
559568
ZEND_ARG_INFO(0, key)
@@ -580,7 +589,7 @@ const zend_function_entry Tarantool_methods[] = {
580589
TNT_MEP(select, arginfo_tarantool_select )
581590
TNT_MEP(insert, arginfo_tarantool_space_tuple )
582591
TNT_MEP(replace, arginfo_tarantool_space_tuple )
583-
TNT_MEP(call, arginfo_tarantool_proc_tuple )
592+
TNT_MEP(call, arginfo_tarantool_proc_call )
584593
TNT_MEP(eval, arginfo_tarantool_proc_tuple )
585594
TNT_MEP(delete, arginfo_tarantool_delete )
586595
TNT_MEP(update, arginfo_tarantool_update )
@@ -1194,6 +1203,7 @@ PHP_METHOD(Tarantool, __construct) {
11941203
}
11951204
zend_string_release(plist_id);
11961205
}
1206+
11971207
t_obj->obj = obj;
11981208
t_obj->is_persistent = is_persistent;
11991209
return;
@@ -1485,17 +1495,69 @@ PHP_METHOD(Tarantool, delete) {
14851495
TARANTOOL_RETURN_DATA(&body, &header, &body);
14861496
}
14871497

1498+
/**
1499+
* "call" options.
1500+
*/
1501+
struct call_opts {
1502+
bool call_17;
1503+
};
1504+
1505+
/**
1506+
* Initialization value for "call" options.
1507+
*/
1508+
static const struct call_opts call_opts_def = {
1509+
.call_17 = false
1510+
};
1511+
1512+
static int parse_call_opts(zval *opts, struct call_opts *res) {
1513+
HashTable *ht = HASH_OF(opts);
1514+
if (ht == NULL) {
1515+
THROW_EXC("call(): bad type of \"options\"."
1516+
" Should be an array.");
1517+
return FAILURE;
1518+
}
1519+
1520+
zval *call_17_zval = zend_hash_str_find(ht, "call_17",
1521+
strlen("call_17"));
1522+
if (call_17_zval != NULL) {
1523+
if (Z_TYPE_P(call_17_zval) == IS_TRUE) {
1524+
res->call_17 = true;
1525+
} else if (Z_TYPE_P(call_17_zval) == IS_FALSE) {
1526+
res->call_17 = false;
1527+
} else {
1528+
THROW_EXC("call(): bad type of call_17 option."
1529+
" Should be a boolean.");
1530+
return FAILURE;
1531+
}
1532+
}
1533+
1534+
return SUCCESS;
1535+
}
1536+
14881537
PHP_METHOD(Tarantool, call) {
14891538
char *proc; size_t proc_len;
14901539
zval *tuple = NULL, tuple_new;
1540+
zval *opts = NULL;
14911541

1492-
TARANTOOL_FUNCTION_BEGIN(obj, id, "s|z", &proc, &proc_len, &tuple);
1542+
TARANTOOL_FUNCTION_BEGIN(obj, id, "s|zz", &proc, &proc_len,
1543+
&tuple, &opts);
14931544
TARANTOOL_CONNECT_ON_DEMAND(obj);
14941545

1546+
struct call_opts call_opts = call_opts_def;
1547+
if (opts != NULL && parse_call_opts(opts, &call_opts) == FAILURE) {
1548+
RETURN_FALSE;
1549+
}
1550+
14951551
pack_key(tuple, 1, &tuple_new);
14961552

14971553
long sync = TARANTOOL_G(sync_counter)++;
1498-
php_tp_encode_call(obj->value, sync, proc, proc_len, &tuple_new);
1554+
if (call_opts.call_17) {
1555+
php_tp_encode_call(obj->value, sync, proc, proc_len,
1556+
&tuple_new);
1557+
} else {
1558+
php_tp_encode_call_16(obj->value, sync, proc, proc_len,
1559+
&tuple_new);
1560+
}
14991561
zval_ptr_dtor(&tuple_new);
15001562
if (tarantool_stream_send(obj) == FAILURE)
15011563
RETURN_FALSE;

src/tarantool_proto.c

+18-8
Original file line numberDiff line numberDiff line change
@@ -172,29 +172,39 @@ void php_tp_encode_delete(smart_string *str, uint32_t sync,
172172
php_mp_pack(str, tuple);
173173
}
174174

175-
size_t php_tp_sizeof_call(uint32_t sync,
176-
uint32_t proc_len, zval *tuple) {
177-
return php_tp_sizeof_header(TNT_CALL, sync) +
175+
static size_t php_tp_sizeof_call(uint32_t sync, uint32_t proc_len,
176+
enum tnt_request_type type, zval *tuple) {
177+
return php_tp_sizeof_header(type, sync) +
178178
php_mp_sizeof_hash(2) +
179179
php_mp_sizeof_long(TNT_FUNCTION) +
180180
php_mp_sizeof_string(proc_len) +
181181
php_mp_sizeof_long(TNT_TUPLE) +
182182
php_mp_sizeof(tuple) ;
183183
}
184184

185-
void php_tp_encode_call(smart_string *str, uint32_t sync,
186-
char *proc, uint32_t proc_len, zval *tuple) {
187-
size_t packet_size = php_tp_sizeof_call(sync,
188-
proc_len, tuple);
185+
static void php_tp_encode_call_impl(smart_string *str, uint32_t sync,
186+
char *proc, uint32_t proc_len,
187+
enum tnt_request_type type, zval *tuple) {
188+
size_t packet_size = php_tp_sizeof_call(sync, proc_len, type, tuple);
189189
smart_string_ensure(str, packet_size + 5);
190-
php_tp_pack_header(str, packet_size, TNT_CALL, sync);
190+
php_tp_pack_header(str, packet_size, type, sync);
191191
php_mp_pack_hash(str, 2);
192192
php_mp_pack_long(str, TNT_FUNCTION);
193193
php_mp_pack_string(str, proc, proc_len);
194194
php_mp_pack_long(str, TNT_TUPLE);
195195
php_mp_pack(str, tuple);
196196
}
197197

198+
void php_tp_encode_call(smart_string *str, uint32_t sync, char *proc,
199+
uint32_t proc_len, zval *tuple) {
200+
php_tp_encode_call_impl(str,sync, proc, proc_len, TNT_CALL, tuple);
201+
}
202+
203+
void php_tp_encode_call_16(smart_string *str, uint32_t sync, char *proc,
204+
uint32_t proc_len, zval *tuple) {
205+
php_tp_encode_call_impl(str,sync, proc, proc_len, TNT_CALL_16, tuple);
206+
}
207+
198208
size_t php_tp_sizeof_eval(uint32_t sync,
199209
uint32_t proc_len, zval *tuple) {
200210
return php_tp_sizeof_header(TNT_EVAL, sync) +

src/tarantool_proto.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,11 @@ enum tnt_request_type {
8787
TNT_REPLACE = 0x03,
8888
TNT_UPDATE = 0x04,
8989
TNT_DELETE = 0x05,
90-
TNT_CALL = 0x06,
90+
TNT_CALL_16 = 0x06,
9191
TNT_AUTH = 0x07,
9292
TNT_EVAL = 0x08,
9393
TNT_UPSERT = 0x09,
94+
TNT_CALL = 0x0a,
9495
TNT_PING = 0x40
9596
};
9697

@@ -138,6 +139,8 @@ void php_tp_encode_delete(smart_string *str, uint32_t sync, uint32_t space_no,
138139
uint32_t index_no, zval *tuple);
139140
void php_tp_encode_call(smart_string *str, uint32_t sync, char *proc,
140141
uint32_t proc_len, zval *tuple);
142+
void php_tp_encode_call_16(smart_string *str, uint32_t sync, char *proc,
143+
uint32_t proc_len, zval *tuple);
141144
void php_tp_encode_eval(smart_string *str, uint32_t sync, char *proc,
142145
uint32_t proc_len, zval *tuple);
143146

test/DMLTest.php

+22-3
Original file line numberDiff line numberDiff line change
@@ -235,18 +235,37 @@ public function test_11_update_error() {
235235
}
236236

237237
public function test_12_call() {
238-
$result = self::$tarantool->call("test_6", array(true, false, false));
238+
$result = self::$tarantool->call("test_6", array(true, false, false),
239+
array('call_17' => false));
239240
$this->assertEquals(array(array(true), array(false), array(false)), $result);
240241
$this->assertEquals(
241242
array(
242243
'0' => array(
243244
'0' => array('k1' => 'v2', 'k2' => 'v')
244245
)
245246
),
246-
self::$tarantool->call("test_2")
247+
self::$tarantool->call("test_2", array(), array('call_17' => false))
247248
);
248249
$this->assertEquals(
249-
self::$tarantool->call("test_3", array(3, 4)), array('0' => array('0' => 7)));
250+
self::$tarantool->call("test_3", array(3, 4), array('call_17' => false)),
251+
array('0' => array('0' => 7))
252+
);
253+
254+
$check_call_17 = self::$tarantool->call('tarantool_version_at_least',
255+
array(1, 7, 2, 0));
256+
if ($check_call_17[0][0]) {
257+
$result = self::$tarantool->call("test_6", array(true, false, false),
258+
array('call_17' => true));
259+
$this->assertEquals(array(true, false, false), $result);
260+
$this->assertEquals(
261+
array('0' => array('k1' => 'v2', 'k2' => 'v')),
262+
self::$tarantool->call("test_2", array(), array('call_17' => true))
263+
);
264+
$this->assertEquals(
265+
self::$tarantool->call("test_3", array(3, 4), array('call_17' => true)),
266+
array('0' => 7)
267+
);
268+
}
250269
}
251270

252271
public function test_13_eval() {

test/MsgPackTest.php

+20-3
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,31 @@ public function test_00_msgpack_call() {
2222
'4TL2tLIXqMqyGQm_kiE7mRrS96I5E8nqU', 'B627', 0, [
2323
'browser_stats_first_session_hits' => 1
2424
]
25-
]);
25+
], ['call_17' => false]);
2626
$this->assertEquals($resp[0][0], 2);
2727
$resp = self::$tarantool->call('test_4', [
2828
'4TL2tLIXqMqyGQm_kiE7mRrS96I5E8nqU', 'B627', 0, [
2929
'browser_stats_first_session_hit' => 1
3030
]
31-
]);
31+
], ['call_17' => false]);
3232
$this->assertEquals($resp[0][0], 2);
33+
34+
$check_call_17 = self::$tarantool->call('tarantool_version_at_least',
35+
array(1,7,2,0));
36+
if ($check_call_17[0][0]) {
37+
$resp = self::$tarantool->call('test_4', [
38+
'4TL2tLIXqMqyGQm_kiE7mRrS96I5E8nqU', 'B627', 0, [
39+
'browser_stats_first_session_hits' => 1
40+
]
41+
], ['call_17' => true]);
42+
$this->assertEquals($resp[0], 2);
43+
$resp = self::$tarantool->call('test_4', [
44+
'4TL2tLIXqMqyGQm_kiE7mRrS96I5E8nqU', 'B627', 0, [
45+
'browser_stats_first_session_hit' => 1
46+
]
47+
], ['call_17' => true]);
48+
$this->assertEquals($resp[0], 2);
49+
}
3350
}
3451

3552
public function test_01_msgpack_array_key() {
@@ -81,6 +98,6 @@ public function test_05_msgpack_string_keys() {
8198
public function test_06_msgpack_array_reference() {
8299
$data = array('key1' => 'value1');
83100
$link = &$data['key1'];
84-
self::$tarantool->call('test_4', [$data]);
101+
self::$tarantool->call('test_4', [$data], ['call_17' => false]);
85102
}
86103
}

test/RandomTest.php

+12-1
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,20 @@ public function test_02_very_big_response() {
4242

4343
public function test_03_another_big_response() {
4444
for ($i = 100; $i <= 5200; $i += 100) {
45-
$result = self::$tarantool->call('test_5', array($i));
45+
$result = self::$tarantool->call('test_5', array($i),
46+
array('call_17' => false));
4647
$this->assertEquals($i, count($result));
4748
}
49+
50+
$check_call_17 = self::$tarantool->call('tarantool_version_at_least',
51+
array(1,7,2,0));
52+
if ($check_call_17[0][0]) {
53+
for ($i = 100; $i <= 5200; $i += 100) {
54+
$result = self::$tarantool->call('test_5', array($i),
55+
array('call_17' => true));
56+
$this->assertEquals($i, count($result[0]));
57+
}
58+
}
4859
}
4960

5061
/**

test/shared/box.lua

+3
Original file line numberDiff line numberDiff line change
@@ -197,5 +197,8 @@ box.session.on_connect(function()
197197
end
198198
end)
199199

200+
-- export tarantool_version_at_least function
201+
_G.tarantool_version_at_least = tarantool_version_at_least
202+
200203
require('console').listen(os.getenv('ADMIN_PORT'))
201204

0 commit comments

Comments
 (0)