Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support call 17 #167

Merged
merged 2 commits into from
Jul 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 26 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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] )
Expand Down Expand Up @@ -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<br />
If true - call_16 mode of "call" will be used
(returned data converted to tuples).<br />
If false - call_17 mode of "call" will be used
(returned data has an arbitrary structure). Since tarantool 1.7.2.<br />
Default - call_16 mode.
```
array(
"call_16" => <bool>
),
```

_**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
Expand All @@ -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**_

Expand Down
68 changes: 64 additions & 4 deletions src/tarantool.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <time.h>
#include <stdio.h>
#include <limits.h>
#include <string.h>

#include "php_tarantool.h"
#include "tarantool_internal.h"
Expand Down Expand Up @@ -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)
Expand All @@ -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 )
Expand Down Expand Up @@ -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);
Totktonada marked this conversation as resolved.
Show resolved Hide resolved
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;
Expand Down
26 changes: 18 additions & 8 deletions src/tarantool_proto.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,29 +172,39 @@ 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) +
php_mp_sizeof_long(TNT_TUPLE) +
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);
php_mp_pack_long(str, TNT_TUPLE);
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) +
Expand Down
5 changes: 4 additions & 1 deletion src/tarantool_proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
};

Expand Down Expand Up @@ -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);

Expand Down
25 changes: 22 additions & 3 deletions test/DMLTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -235,18 +235,37 @@ 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(
'0' => array(
'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() {
Expand Down
23 changes: 20 additions & 3 deletions test/MsgPackTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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]);
}
}
13 changes: 12 additions & 1 deletion test/RandomTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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]));
}
}
}

/**
Expand Down
3 changes: 3 additions & 0 deletions test/shared/box.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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'))