Skip to content

Commit 747492a

Browse files
committed
Add support for iterators as strings + iterator ALL by default if no key is passed/empty array
1 parent 583ca18 commit 747492a

File tree

11 files changed

+461
-224
lines changed

11 files changed

+461
-224
lines changed

README.md

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,9 @@ _**Description**_: Available Tarantool Constants
103103
* `Tarantool::ITERATOR_LE` - Less and equal iterator
104104
* `Tarantool::ITERATOR_GE` - Greater and equal iterator
105105
* `Tarantool::ITERATOR_GT` - Gtreater then iterator
106-
* `Tarantool::ITERATOR_BITSET_ALL_SET` - check if all given bits are set (BITSET only)
107-
* `Tarantool::ITERATOR_BITSET_ANY_SET` - check if any given bits are set (BITSET only)
108-
* `Tarantool::ITERATOR_BITSET_ALL_NOT_SET` - check if all given bits are not set
106+
* `Tarantool::ITERATOR_BITS_ALL_SET` - check if all given bits are set (BITSET only)
107+
* `Tarantool::ITERATOR_BITS_ANY_SET` - check if any given bits are set (BITSET only)
108+
* `Tarantool::ITERATOR_BITS_ALL_NOT_SET` - check if all given bits are not set
109109
(BITSET only)
110110
* `Tarantool::ITERATOR_OVERLAPS` - find dots in the n-dimension cube (RTREE only)
111111
* `Tarantool::ITERATOR_NEIGHBOR` - find nearest dots (RTREE only)
@@ -119,7 +119,7 @@ Tarantool {
119119
public bool Tarantool::disconnect ( void )
120120
public bool Tarantool::flushSchema ( void )
121121
public bool Tarantool::ping ( void )
122-
public array Tarantool::select (mixed $space [, mixed $key = array() [, mixed $index = 0 [, int $limit = PHP_INT_MAX [, int $offset = 0 [, $iterator = TARANTOOL_ITERATOR_EQ ] ] ] ] ] )
122+
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)
125125
public array Tarantool::call (string $procedure [, mixed args] )
@@ -219,7 +219,7 @@ Throws `Exception` on error.
219219
### Tarantool::select
220220

221221
``` php
222-
public array Tarantool::select(mixed $space [, mixed $key = array() [, mixed $index = 0 [, int $limit = PHP_INT_MAX [, int $offset = 0 [, $iterator = TARANTOOL_ITERATOR_EQ ] ] ] ] ] )
222+
public array Tarantool::select(mixed $space [, mixed $key = array() [, mixed $index = 0 [, int $limit = PHP_INT_MAX [, int $offset = 0 [, $iterator = Tarantool::ITERATOR_EQ ] ] ] ] ] )
223223
```
224224

225225
_**Description**_: Execute select query from Tarantool server.
@@ -233,7 +233,11 @@ _**Parameters**_
233233
* `limit`: Number, limit number of rows to return from select (INT_MAX by default)
234234
* `offset`: Number, offset to select from (0 by default)
235235
* `iterator`: Constant, iterator type. See [Predefined Constants](#predefined-constants)
236-
for more information (`TARANTOOL_ITERATOR_EQ` by default)
236+
for more information (`Tarantool::ITERATOR_EQ` by default). You can also use
237+
strings `'eq'`, `'req'`, `'all'`, `'lt'`, `'le'`, `'ge'`, `'gt'`,
238+
`'bits_all_set'`, `'bits_any_set'`, `'bits_all_not_set'`, `'overlaps'`,
239+
`'neighbor'`, `'bits_all_set'`, `'bits_any_set'`, `'bits_all_not_set'` (in
240+
both lowercase/uppercase) instead of constants
237241

238242
_**Return Value**_
239243

@@ -257,7 +261,7 @@ $tnt->select("test", array(1, "hello"), "isec");
257261
$tnt->select("test", null, null, 100, 100);
258262
// Selects second hundred of rows from space test in reverse equality order
259263
// It meanse: select penultimate hundred
260-
$tnt->select("test", null, null, 100, 100, TARANTOOL_ITERATOR_REQ);
264+
$tnt->select("test", null, null, 100, 100, Tarantool::ITERATOR_REQ);
261265
```
262266

263267
### Tarantool::insert, Tarantool::replace

src/tarantool.c

Lines changed: 141 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,125 @@ zval *pack_key(zval *args, char select) {
530530
return arr;
531531
}
532532

533+
int convert_iterator(zval *iter, int all) {
534+
TSRMLS_FETCH();
535+
if (iter == NULL || Z_TYPE_P(iter) == IS_NULL) {
536+
if (all) {
537+
return ITERATOR_ALL;
538+
} else {
539+
return ITERATOR_EQ;
540+
}
541+
} else if (Z_TYPE_P(iter) == IS_LONG) {
542+
return Z_LVAL_P(iter);
543+
} else if (Z_TYPE_P(iter) != IS_STRING) {
544+
THROW_EXC("Bad iterator type, expected null/String/Long, got"
545+
"%s", op_to_string(Z_TYPE_P(iter)));
546+
}
547+
const char *i = Z_STRVAL_P(iter);
548+
size_t i_len = Z_STRLEN_P(iter);
549+
int first = toupper(i[0]);
550+
switch (first) {
551+
case 'A':
552+
if (i_len == 3 && toupper(i[1]) == 'L' && toupper(i[2]) == 'L')
553+
return ITERATOR_ALL;
554+
break;
555+
case 'B':
556+
if (i_len > 7 && toupper(i[1]) == 'I' &&
557+
toupper(i[2]) == 'T' && toupper(i[3]) == 'S' &&
558+
toupper(i[4]) == 'E' && toupper(i[5]) == 'T' &&
559+
toupper(i[6]) == '_') {
560+
if (i_len == 18 && toupper(i[7]) == 'A' &&
561+
toupper(i[8]) == 'L' && toupper(i[9]) == 'L' &&
562+
toupper(i[10]) == '_' && toupper(i[11]) == 'N' &&
563+
toupper(i[12]) == 'O' && toupper(i[13]) == 'T' &&
564+
toupper(i[14]) == '_' && toupper(i[15]) == 'S' &&
565+
toupper(i[16]) == 'E' && toupper(i[17]) == 'T')
566+
return ITERATOR_BITSET_ALL_NOT_SET;
567+
else if (i_len == 14 && toupper(i[7]) == 'A' &&
568+
toupper(i[8]) == 'L' && toupper(i[9]) == 'L' &&
569+
toupper(i[10]) == '_' && toupper(i[11]) == 'S' &&
570+
toupper(i[12]) == 'E' && toupper(i[13]) == 'T')
571+
return ITERATOR_BITSET_ALL_SET;
572+
else if (i_len == 14 && toupper(i[7]) == 'A' &&
573+
toupper(i[8]) == 'N' && toupper(i[9]) == 'Y' &&
574+
toupper(i[10]) == '_' && toupper(i[11]) == 'S' &&
575+
toupper(i[12]) == 'E' && toupper(i[13]) == 'T')
576+
return ITERATOR_BITSET_ANY_SET;
577+
}
578+
if (i_len > 4 && toupper(i[1]) == 'I' &&
579+
toupper(i[2]) == 'T' && toupper(i[3]) == 'S' &&
580+
toupper(i[4]) == '_') {
581+
if (i_len == 16 && toupper(i[5]) == 'A' &&
582+
toupper(i[6]) == 'L' && toupper(i[7]) == 'L' &&
583+
toupper(i[8]) == '_' && toupper(i[9]) == 'N' &&
584+
toupper(i[10]) == 'O' && toupper(i[11]) == 'T' &&
585+
toupper(i[12]) == '_' && toupper(i[13]) == 'S' &&
586+
toupper(i[14]) == 'E' && toupper(i[15]) == 'T')
587+
return ITERATOR_BITSET_ALL_NOT_SET;
588+
else if (i_len == 12 && toupper(i[5]) == 'A' &&
589+
toupper(i[6]) == 'L' && toupper(i[7]) == 'L' &&
590+
toupper(i[8]) == '_' && toupper(i[9]) == 'S' &&
591+
toupper(i[10]) == 'E' && toupper(i[11]) == 'T')
592+
return ITERATOR_BITSET_ALL_SET;
593+
else if (i_len == 12 && toupper(i[5]) == 'A' &&
594+
toupper(i[6]) == 'N' && toupper(i[7]) == 'Y' &&
595+
toupper(i[8]) == '_' && toupper(i[9]) == 'S' &&
596+
toupper(i[10]) == 'E' && toupper(i[11]) == 'T')
597+
return ITERATOR_BITSET_ANY_SET;
598+
}
599+
break;
600+
case 'E':
601+
if (i_len == 2 && toupper(i[1]) == 'Q')
602+
return ITERATOR_EQ;
603+
break;
604+
case 'G':
605+
if (i_len == 2) {
606+
int second = toupper(i[1]);
607+
switch (second) {
608+
case 'E':
609+
return ITERATOR_GE;
610+
case 'T':
611+
return ITERATOR_GT;
612+
}
613+
}
614+
break;
615+
case 'L':
616+
if (i_len == 2) {
617+
int second = toupper(i[1]);
618+
switch (second) {
619+
case 'T':
620+
return ITERATOR_LT;
621+
case 'E':
622+
return ITERATOR_LE;
623+
}
624+
}
625+
break;
626+
case 'N':
627+
if (i_len == 8 && toupper(i[1]) == 'E' &&
628+
toupper(i[2]) == 'I' && toupper(i[3]) == 'G' &&
629+
toupper(i[4]) == 'H' && toupper(i[5]) == 'B' &&
630+
toupper(i[6]) == 'O' && toupper(i[7]) == 'R')
631+
return ITERATOR_NEIGHBOR;
632+
break;
633+
case 'O':
634+
if (i_len == 8 && toupper(i[1]) == 'V' &&
635+
toupper(i[2]) == 'E' && toupper(i[3]) == 'R' &&
636+
toupper(i[4]) == 'L' && toupper(i[5]) == 'A' &&
637+
toupper(i[6]) == 'P' && toupper(i[7]) == 'S')
638+
return ITERATOR_OVERLAPS;
639+
break;
640+
case 'R':
641+
if (i_len == 3 && toupper(i[1]) == 'E' && toupper(i[2]) == 'Q')
642+
return ITERATOR_REQ;
643+
break;
644+
default:
645+
break;
646+
};
647+
error:
648+
THROW_EXC("Bad iterator name '%.*s'", i_len, i);
649+
return -1;
650+
}
651+
533652
zval *tarantool_update_verify_op(zval *op, long position TSRMLS_DC) {
534653
if (Z_TYPE_P(op) != IS_ARRAY || !php_mp_is_hash(op)) {
535654
THROW_EXC("Op must be MAP at pos %d", position);
@@ -731,9 +850,11 @@ int get_spaceno_by_name(tarantool_connection *obj, zval *id, zval *name TSRMLS_D
731850

732851
int get_indexno_by_name(tarantool_connection *obj, zval *id,
733852
int space_no, zval *name TSRMLS_DC) {
734-
if (Z_TYPE_P(name) == IS_LONG)
853+
if (Z_TYPE_P(name) == IS_NULL) {
854+
return 0;
855+
} else if (Z_TYPE_P(name) == IS_LONG) {
735856
return Z_LVAL_P(name);
736-
if (Z_TYPE_P(name) != IS_STRING) {
857+
} else if (Z_TYPE_P(name) != IS_STRING) {
737858
THROW_EXC("Index ID must be String or Long");
738859
return FAILURE;
739860
}
@@ -876,8 +997,11 @@ PHP_MINIT_FUNCTION(tarantool) {
876997
REGISTER_TNT_CLASS_CONST_LONG(ITERATOR_LE);
877998
REGISTER_TNT_CLASS_CONST_LONG(ITERATOR_GE);
878999
REGISTER_TNT_CLASS_CONST_LONG(ITERATOR_GT);
1000+
REGISTER_TNT_CLASS_CONST_LONG(ITERATOR_BITS_ALL_SET);
8791001
REGISTER_TNT_CLASS_CONST_LONG(ITERATOR_BITSET_ALL_SET);
1002+
REGISTER_TNT_CLASS_CONST_LONG(ITERATOR_BITS_ANY_SET);
8801003
REGISTER_TNT_CLASS_CONST_LONG(ITERATOR_BITSET_ANY_SET);
1004+
REGISTER_TNT_CLASS_CONST_LONG(ITERATOR_BITS_ALL_NOT_SET);
8811005
REGISTER_TNT_CLASS_CONST_LONG(ITERATOR_BITSET_ALL_NOT_SET);
8821006
REGISTER_TNT_CLASS_CONST_LONG(ITERATOR_OVERLAPS);
8831007
REGISTER_TNT_CLASS_CONST_LONG(ITERATOR_NEIGHBOR);
@@ -918,7 +1042,7 @@ PHP_METHOD(Tarantool, __construct) {
9181042
const char *plist_id = NULL, *suffix = NULL;
9191043
int plist_id_len = 0, suffix_len = 0;
9201044

921-
TARANTOOL_PARSE_PARAMS(id, "|slsss", &host, &host_len, &port,
1045+
TARANTOOL_PARSE_PARAMS(id, "|slss!s", &host, &host_len, &port,
9221046
&login, &login_len, &passwd, &passwd_len,
9231047
&suffix, &suffix_len);
9241048
TARANTOOL_FETCH_OBJECT(obj, id);
@@ -1188,10 +1312,10 @@ PHP_METHOD(Tarantool, ping) {
11881312
PHP_METHOD(Tarantool, select) {
11891313
zval *space = NULL, *index = NULL;
11901314
zval *key = NULL, *key_new = NULL;
1191-
zval *zlimit = NULL;
1192-
long limit = LONG_MAX-1, offset = 0, iterator = 0;
1315+
zval *zlimit = NULL, *iterator = NULL;
1316+
long limit = LONG_MAX-1, offset = 0;
11931317

1194-
TARANTOOL_PARSE_PARAMS(id, "z|zzzll", &space, &key,
1318+
TARANTOOL_PARSE_PARAMS(id, "z|zzzlz", &space, &key,
11951319
&index, &zlimit, &offset, &iterator);
11961320
TARANTOOL_FETCH_OBJECT(obj, id);
11971321
TARANTOOL_CONNECT_ON_DEMAND(obj, id);
@@ -1211,14 +1335,22 @@ PHP_METHOD(Tarantool, select) {
12111335
index_no = get_indexno_by_name(obj, id, space_no, index TSRMLS_CC);
12121336
if (index_no == FAILURE) RETURN_FALSE;
12131337
}
1338+
1339+
int is_iterator_all = (!key ||
1340+
Z_TYPE_P(key) == IS_NULL ||
1341+
(Z_TYPE_P(key) == IS_ARRAY && zend_hash_num_elements(Z_ARRVAL_P(key)) == 0)
1342+
);
1343+
int iterator_id = convert_iterator(iterator, is_iterator_all);
1344+
if (iterator_id == -1)
1345+
RETURN_FALSE;
1346+
12141347
key_new = pack_key(key, 1);
12151348

12161349
long sync = TARANTOOL_G(sync_counter)++;
12171350
php_tp_encode_select(obj->value, sync, space_no, index_no,
1218-
limit, offset, iterator, key_new);
1219-
if (key != key_new) {
1351+
limit, offset, iterator_id, key_new);
1352+
if (key != key_new)
12201353
zval_ptr_dtor(&key_new);
1221-
}
12221354
if (tarantool_stream_send(obj TSRMLS_CC) == FAILURE)
12231355
RETURN_FALSE;
12241356

src/tarantool_msgpack.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ ptrdiff_t php_mp_unpack_double(zval **oval, char **str) {
279279
return mp_sizeof_double(val);
280280
}
281281

282-
static const char *op_to_string(zend_uchar type) {
282+
const char *op_to_string(zend_uchar type) {
283283
switch(type) {
284284
case(IS_NULL):
285285
return "NULL";

src/tarantool_msgpack.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ void php_mp_pack_package_size (smart_string *str, size_t val);
1919
size_t php_mp_unpack_package_size (char *buf);
2020

2121
int php_mp_is_hash(zval *val);
22+
const char *op_to_string(zend_uchar type);
2223

2324
void php_mp_pack_nil(smart_string *str);
2425
void php_mp_pack_long_pos(smart_string *str, long val);
@@ -46,5 +47,4 @@ size_t php_mp_sizeof_hash_recursively(zval *val);
4647

4748
int smart_string_ensure(smart_string *str, size_t len);
4849
void smart_string_nullify(smart_string *str);
49-
5050
#endif /* PHP_MSGPACK_H */

src/tarantool_proto.h

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -61,18 +61,21 @@ enum tnt_request_type {
6161
};
6262

6363
enum tnt_iterator_type {
64-
ITERATOR_EQ = 0,
65-
ITERATOR_REQ = 1,
66-
ITERATOR_ALL = 2,
67-
ITERATOR_LT = 3,
68-
ITERATOR_LE = 4,
69-
ITERATOR_GE = 5,
70-
ITERATOR_GT = 6,
71-
ITERATOR_BITSET_ALL_SET = 7,
72-
ITERATOR_BITSET_ANY_SET = 8,
64+
ITERATOR_EQ = 0,
65+
ITERATOR_REQ = 1,
66+
ITERATOR_ALL = 2,
67+
ITERATOR_LT = 3,
68+
ITERATOR_LE = 4,
69+
ITERATOR_GE = 5,
70+
ITERATOR_GT = 6,
71+
ITERATOR_BITS_ALL_SET = 7,
72+
ITERATOR_BITSET_ALL_SET = 7,
73+
ITERATOR_BITS_ANY_SET = 8,
74+
ITERATOR_BITSET_ANY_SET = 8,
75+
ITERATOR_BITS_ALL_NOT_SET = 9,
7376
ITERATOR_BITSET_ALL_NOT_SET = 9,
74-
ITERATOR_OVERLAPS = 10,
75-
ITERATOR_NEIGHBOR = 11,
77+
ITERATOR_OVERLAPS = 10,
78+
ITERATOR_NEIGHBOR = 11,
7679
};
7780

7881
struct tnt_response {

test/AssertTest.php

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,7 @@ class AssertTest extends PHPUnit_Framework_TestCase
55

66
public static function setUpBeforeClass()
77
{
8-
self::$tarantool = new Tarantool('localhost', getenv('PRIMARY_PORT'));
9-
self::$tarantool->authenticate('test', 'test');
10-
}
11-
12-
public static function tearDownAfterClass() {
8+
self::$tarantool = new Tarantool('localhost', getenv('PRIMARY_PORT'), 'test', 'test');
139
}
1410

1511
protected function tearDown()

0 commit comments

Comments
 (0)