diff --git a/README.md b/README.md
index ebf692b..d808e30 100644
--- a/README.md
+++ b/README.md
@@ -122,7 +122,7 @@ Tarantool {
public array Tarantool::select (mixed $space [, mixed $key = array() [, mixed $index = 0 [, int $limit = PHP_INT_MAX [, int $offset = 0 [, $iterator = Tarantool::ITERATOR_EQ ] ] ] ] ] )
public array Tarantool::insert (mixed $space, array $tuple)
public array Tarantool::replace (mixed $space, array $tuple)
- public array Tarantool::call (string $procedure [, mixed args] )
+ public array Tarantool::call (string $procedure [, mixed args [, array $opts ] ] )
public array Tarantool::evaluate (string $expression [, mixed args] )
public array Tarantool::delete (mixed $space, mixed $key [, mixed $index] )
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"));
### Tarantool::call
``` php
-public array Tarantool::call(string $procedure [, mixed args])
+public array Tarantool::call(string $procedure [, mixed args [, array $opts]])
```
_**Description**_: Call stored procedure
_**Parameters**_
* `procedure`: String, procedure to call (mandatory)
-* `args`: Any value to pass to procdure as arguments (empty by default)
+* `args`: Any value to pass to procedure as arguments (empty by default)
+* `opts`: Array, options
+
+_**Options**_
+* call_16
+ If true - call_16 mode of "call" will be used
+ (returned data converted to tuples).
+ If false - call_17 mode of "call" will be used
+ (returned data has an arbitrary structure). Since tarantool 1.7.2.
+ Default - call_16 mode.
+ ```
+ array(
+ "call_16" =>
+ ),
+ ```
_**Return Value**_
+**BOOL**: False and raises `Exception` in case of error.
+
+call_16 mode (default):
+
**Array of arrays** in case of success - tuples that were returned by stored
procedure.
-**BOOL**: False and raises `Exception` in case of error.
+call_17 mode:
+
+**Any value**, that was returned by stored procedure.
#### Example
``` php
$tnt->call("test_2");
-$tnt->call("test_3", array(3, 4));
+$tnt->call("test_3", array(3, 4), array('call_16' => false));
```
### Tarantool::evaluate
@@ -333,7 +353,7 @@ _**Description**_: Evaluate given lua code (demands current user to have
_**Parameters**_
* `expression`: String, Lua code to evaluate (mandatory)
-* `args`: Any value to pass to procdure as arguments (empty by default)
+* `args`: Any value to pass to procedure as arguments (empty by default)
_**Return Value**_
diff --git a/src/tarantool.c b/src/tarantool.c
index 2e03852..ff5b0df 100644
--- a/src/tarantool.c
+++ b/src/tarantool.c
@@ -1,6 +1,7 @@
#include
#include
#include
+#include
#include "php_tarantool.h"
#include "tarantool_internal.h"
@@ -548,12 +549,19 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_tarantool_delete, 0, 0, 2)
ZEND_ARG_INFO(0, index)
ZEND_END_ARG_INFO()
-/* call, eval */
+/* eval */
ZEND_BEGIN_ARG_INFO_EX(arginfo_tarantool_proc_tuple, 0, 0, 1)
ZEND_ARG_INFO(0, proc)
ZEND_ARG_INFO(0, tuple)
ZEND_END_ARG_INFO()
+/* call */
+ZEND_BEGIN_ARG_INFO_EX(arginfo_tarantool_proc_call, 0, 0, 1)
+ ZEND_ARG_INFO(0, proc)
+ ZEND_ARG_INFO(0, tuple)
+ ZEND_ARG_INFO(0, opts)
+ZEND_END_ARG_INFO()
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_tarantool_update, 0, 0, 3)
ZEND_ARG_INFO(0, space)
ZEND_ARG_INFO(0, key)
@@ -580,7 +588,7 @@ const zend_function_entry Tarantool_methods[] = {
TNT_MEP(select, arginfo_tarantool_select )
TNT_MEP(insert, arginfo_tarantool_space_tuple )
TNT_MEP(replace, arginfo_tarantool_space_tuple )
- TNT_MEP(call, arginfo_tarantool_proc_tuple )
+ TNT_MEP(call, arginfo_tarantool_proc_call )
TNT_MEP(eval, arginfo_tarantool_proc_tuple )
TNT_MEP(delete, arginfo_tarantool_delete )
TNT_MEP(update, arginfo_tarantool_update )
@@ -1485,17 +1493,69 @@ PHP_METHOD(Tarantool, delete) {
TARANTOOL_RETURN_DATA(&body, &header, &body);
}
+/**
+ * "call" options.
+ */
+struct call_opts {
+ bool call_16;
+};
+
+/**
+ * Initialization value for "call" options.
+ */
+static const struct call_opts call_opts_default = {
+ .call_16 = true
+};
+
+static int parse_call_opts(zval *opts, struct call_opts *res) {
+ HashTable *ht = HASH_OF(opts);
+ if (ht == NULL) {
+ THROW_EXC("call(): bad type of \"options\"."
+ " Should be an array.");
+ return FAILURE;
+ }
+
+ zval *call_16_zval = zend_hash_str_find(ht, "call_16",
+ strlen("call_16"));
+ if (call_16_zval != NULL) {
+ if (Z_TYPE_P(call_16_zval) == IS_TRUE) {
+ res->call_16 = true;
+ } else if (Z_TYPE_P(call_16_zval) == IS_FALSE) {
+ res->call_16 = false;
+ } else {
+ THROW_EXC("call(): bad type of call_16 option."
+ " Should be a boolean.");
+ return FAILURE;
+ }
+ }
+
+ return SUCCESS;
+}
+
PHP_METHOD(Tarantool, call) {
char *proc; size_t proc_len;
zval *tuple = NULL, tuple_new;
+ zval *opts = NULL;
- TARANTOOL_FUNCTION_BEGIN(obj, id, "s|z", &proc, &proc_len, &tuple);
+ TARANTOOL_FUNCTION_BEGIN(obj, id, "s|zz", &proc, &proc_len,
+ &tuple, &opts);
TARANTOOL_CONNECT_ON_DEMAND(obj);
+ struct call_opts call_opts = call_opts_default;
+ if (opts != NULL && parse_call_opts(opts, &call_opts) == FAILURE) {
+ RETURN_FALSE;
+ }
+
pack_key(tuple, 1, &tuple_new);
long sync = TARANTOOL_G(sync_counter)++;
- php_tp_encode_call(obj->value, sync, proc, proc_len, &tuple_new);
+ if (call_opts.call_16) {
+ php_tp_encode_call_16(obj->value, sync, proc, proc_len,
+ &tuple_new);
+ } else {
+ php_tp_encode_call(obj->value, sync, proc, proc_len,
+ &tuple_new);
+ }
zval_ptr_dtor(&tuple_new);
if (tarantool_stream_send(obj) == FAILURE)
RETURN_FALSE;
diff --git a/src/tarantool_proto.c b/src/tarantool_proto.c
index f8c69e5..8501a67 100644
--- a/src/tarantool_proto.c
+++ b/src/tarantool_proto.c
@@ -172,9 +172,9 @@ void php_tp_encode_delete(smart_string *str, uint32_t sync,
php_mp_pack(str, tuple);
}
-size_t php_tp_sizeof_call(uint32_t sync,
- uint32_t proc_len, zval *tuple) {
- return php_tp_sizeof_header(TNT_CALL, sync) +
+static size_t php_tp_sizeof_call(uint32_t sync, uint32_t proc_len,
+ enum tnt_request_type type, zval *tuple) {
+ return php_tp_sizeof_header(type, sync) +
php_mp_sizeof_hash(2) +
php_mp_sizeof_long(TNT_FUNCTION) +
php_mp_sizeof_string(proc_len) +
@@ -182,12 +182,12 @@ size_t php_tp_sizeof_call(uint32_t sync,
php_mp_sizeof(tuple) ;
}
-void php_tp_encode_call(smart_string *str, uint32_t sync,
- char *proc, uint32_t proc_len, zval *tuple) {
- size_t packet_size = php_tp_sizeof_call(sync,
- proc_len, tuple);
+static void php_tp_encode_call_impl(smart_string *str, uint32_t sync,
+ char *proc, uint32_t proc_len,
+ enum tnt_request_type type, zval *tuple) {
+ size_t packet_size = php_tp_sizeof_call(sync, proc_len, type, tuple);
smart_string_ensure(str, packet_size + 5);
- php_tp_pack_header(str, packet_size, TNT_CALL, sync);
+ php_tp_pack_header(str, packet_size, type, sync);
php_mp_pack_hash(str, 2);
php_mp_pack_long(str, TNT_FUNCTION);
php_mp_pack_string(str, proc, proc_len);
@@ -195,6 +195,16 @@ void php_tp_encode_call(smart_string *str, uint32_t sync,
php_mp_pack(str, tuple);
}
+void php_tp_encode_call(smart_string *str, uint32_t sync, char *proc,
+ uint32_t proc_len, zval *tuple) {
+ php_tp_encode_call_impl(str,sync, proc, proc_len, TNT_CALL, tuple);
+}
+
+void php_tp_encode_call_16(smart_string *str, uint32_t sync, char *proc,
+ uint32_t proc_len, zval *tuple) {
+ php_tp_encode_call_impl(str,sync, proc, proc_len, TNT_CALL_16, tuple);
+}
+
size_t php_tp_sizeof_eval(uint32_t sync,
uint32_t proc_len, zval *tuple) {
return php_tp_sizeof_header(TNT_EVAL, sync) +
diff --git a/src/tarantool_proto.h b/src/tarantool_proto.h
index 49f0432..5454bda 100644
--- a/src/tarantool_proto.h
+++ b/src/tarantool_proto.h
@@ -87,10 +87,11 @@ enum tnt_request_type {
TNT_REPLACE = 0x03,
TNT_UPDATE = 0x04,
TNT_DELETE = 0x05,
- TNT_CALL = 0x06,
+ TNT_CALL_16 = 0x06,
TNT_AUTH = 0x07,
TNT_EVAL = 0x08,
TNT_UPSERT = 0x09,
+ TNT_CALL = 0x0a,
TNT_PING = 0x40
};
@@ -138,6 +139,8 @@ void php_tp_encode_delete(smart_string *str, uint32_t sync, uint32_t space_no,
uint32_t index_no, zval *tuple);
void php_tp_encode_call(smart_string *str, uint32_t sync, char *proc,
uint32_t proc_len, zval *tuple);
+void php_tp_encode_call_16(smart_string *str, uint32_t sync, char *proc,
+ uint32_t proc_len, zval *tuple);
void php_tp_encode_eval(smart_string *str, uint32_t sync, char *proc,
uint32_t proc_len, zval *tuple);
diff --git a/test/DMLTest.php b/test/DMLTest.php
index 7b3bdcf..c2d1e5b 100644
--- a/test/DMLTest.php
+++ b/test/DMLTest.php
@@ -235,7 +235,8 @@ public function test_11_update_error() {
}
public function test_12_call() {
- $result = self::$tarantool->call("test_6", array(true, false, false));
+ $result = self::$tarantool->call("test_6", array(true, false, false),
+ array('call_16' => true));
$this->assertEquals(array(array(true), array(false), array(false)), $result);
$this->assertEquals(
array(
@@ -243,10 +244,28 @@ public function test_12_call() {
'0' => array('k1' => 'v2', 'k2' => 'v')
)
),
- self::$tarantool->call("test_2")
+ self::$tarantool->call("test_2", array(), array('call_16' => true))
);
$this->assertEquals(
- self::$tarantool->call("test_3", array(3, 4)), array('0' => array('0' => 7)));
+ self::$tarantool->call("test_3", array(3, 4), array('call_16' => true)),
+ array('0' => array('0' => 7))
+ );
+
+ $check_call_17 = self::$tarantool->call('tarantool_version_at_least',
+ array(1, 7, 2, 0));
+ if ($check_call_17[0][0]) {
+ $result = self::$tarantool->call("test_6", array(true, false, false),
+ array('call_16' => false));
+ $this->assertEquals(array(true, false, false), $result);
+ $this->assertEquals(
+ array('0' => array('k1' => 'v2', 'k2' => 'v')),
+ self::$tarantool->call("test_2", array(), array('call_16' => false))
+ );
+ $this->assertEquals(
+ self::$tarantool->call("test_3", array(3, 4), array('call_16' => false)),
+ array('0' => 7)
+ );
+ }
}
public function test_13_eval() {
diff --git a/test/MsgPackTest.php b/test/MsgPackTest.php
index ddc2c08..7a8d0ee 100644
--- a/test/MsgPackTest.php
+++ b/test/MsgPackTest.php
@@ -22,14 +22,31 @@ public function test_00_msgpack_call() {
'4TL2tLIXqMqyGQm_kiE7mRrS96I5E8nqU', 'B627', 0, [
'browser_stats_first_session_hits' => 1
]
- ]);
+ ], ['call_16' => true]);
$this->assertEquals($resp[0][0], 2);
$resp = self::$tarantool->call('test_4', [
'4TL2tLIXqMqyGQm_kiE7mRrS96I5E8nqU', 'B627', 0, [
'browser_stats_first_session_hit' => 1
]
- ]);
+ ], ['call_16' => true]);
$this->assertEquals($resp[0][0], 2);
+
+ $check_call_17 = self::$tarantool->call('tarantool_version_at_least',
+ array(1,7,2,0));
+ if ($check_call_17[0][0]) {
+ $resp = self::$tarantool->call('test_4', [
+ '4TL2tLIXqMqyGQm_kiE7mRrS96I5E8nqU', 'B627', 0, [
+ 'browser_stats_first_session_hits' => 1
+ ]
+ ], ['call_16' => false]);
+ $this->assertEquals($resp[0], 2);
+ $resp = self::$tarantool->call('test_4', [
+ '4TL2tLIXqMqyGQm_kiE7mRrS96I5E8nqU', 'B627', 0, [
+ 'browser_stats_first_session_hit' => 1
+ ]
+ ], ['call_16' => false]);
+ $this->assertEquals($resp[0], 2);
+ }
}
public function test_01_msgpack_array_key() {
@@ -81,6 +98,6 @@ public function test_05_msgpack_string_keys() {
public function test_06_msgpack_array_reference() {
$data = array('key1' => 'value1');
$link = &$data['key1'];
- self::$tarantool->call('test_4', [$data]);
+ self::$tarantool->call('test_4', [$data], ['call_16' => true]);
}
}
diff --git a/test/RandomTest.php b/test/RandomTest.php
index 9eb60d1..498c3b8 100644
--- a/test/RandomTest.php
+++ b/test/RandomTest.php
@@ -42,9 +42,20 @@ public function test_02_very_big_response() {
public function test_03_another_big_response() {
for ($i = 100; $i <= 5200; $i += 100) {
- $result = self::$tarantool->call('test_5', array($i));
+ $result = self::$tarantool->call('test_5', array($i),
+ array('call_16' => true));
$this->assertEquals($i, count($result));
}
+
+ $check_call_17 = self::$tarantool->call('tarantool_version_at_least',
+ array(1,7,2,0));
+ if ($check_call_17[0][0]) {
+ for ($i = 100; $i <= 5200; $i += 100) {
+ $result = self::$tarantool->call('test_5', array($i),
+ array('call_16' => false));
+ $this->assertEquals($i, count($result[0]));
+ }
+ }
}
/**
diff --git a/test/shared/box.lua b/test/shared/box.lua
index f9e2f42..0c6c5de 100755
--- a/test/shared/box.lua
+++ b/test/shared/box.lua
@@ -223,5 +223,8 @@ box.session.on_connect(function()
end
end)
+-- export tarantool_version_at_least function
+_G.tarantool_version_at_least = tarantool_version_at_least
+
require('console').listen(os.getenv('ADMIN_PORT'))