@@ -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+
533652zval * 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
732851int 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) {
11881312PHP_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
0 commit comments