@@ -831,18 +831,34 @@ PHP_METHOD(RedisArray, mget)
831
831
for (i = 0 , zend_hash_internal_pointer_reset_ex (h_keys , & pointer );
832
832
zend_hash_get_current_data_ex (h_keys , (void * * ) & data ,
833
833
& pointer ) == SUCCESS ;
834
- zend_hash_move_forward_ex (h_keys , & pointer ), ++ i ) {
835
-
836
- if (Z_TYPE_PP (data ) != IS_STRING ) {
837
- php_error_docref (NULL TSRMLS_CC , E_ERROR , "MGET: all keys must be string." );
838
- efree (argv );
839
- efree (pos );
840
- efree (redis_instances );
841
- efree (argc_each );
842
- RETURN_FALSE ;
843
- }
834
+ zend_hash_move_forward_ex (h_keys , & pointer ), ++ i )
835
+ {
836
+ /* If we need to represent a long key as a string */
837
+ unsigned int key_len ;
838
+ char kbuf [40 ], * key_lookup ;
839
+
840
+ /* phpredis proper can only use string or long keys, so restrict to that here */
841
+ if (Z_TYPE_PP (data ) != IS_STRING && Z_TYPE_PP (data ) != IS_LONG ) {
842
+ php_error_docref (NULL TSRMLS_CC , E_ERROR , "MGET: all keys must be strings or longs" );
843
+ efree (argv );
844
+ efree (pos );
845
+ efree (redis_instances );
846
+ efree (argc_each );
847
+ RETURN_FALSE ;
848
+ }
849
+
850
+ /* Convert to a string for hash lookup if it isn't one */
851
+ if (Z_TYPE_PP (data ) == IS_STRING ) {
852
+ key_len = Z_STRLEN_PP (data );
853
+ key_lookup = Z_STRVAL_PP (data );
854
+ } else {
855
+ key_len = snprintf (kbuf , sizeof (kbuf ), "%ld" , Z_LVAL_PP (data ));
856
+ key_lookup = (char * )kbuf ;
857
+ }
858
+
859
+ /* Find our node */
860
+ redis_instances [i ] = ra_find_node (ra , key_lookup , key_len , & pos [i ] TSRMLS_CC );
844
861
845
- redis_instances [i ] = ra_find_node (ra , Z_STRVAL_PP (data ), Z_STRLEN_PP (data ), & pos [i ] TSRMLS_CC );
846
862
argc_each [pos [i ]]++ ; /* count number of keys per node */
847
863
argv [i ] = * data ;
848
864
}
@@ -935,8 +951,8 @@ PHP_METHOD(RedisArray, mset)
935
951
int * pos , argc , * argc_each ;
936
952
HashTable * h_keys ;
937
953
zval * * redis_instances , * redis_inst , * * argv ;
938
- char * key , * * keys ;
939
- unsigned int key_len ;
954
+ char * key , * * keys , * * key_free , kbuf [ 40 ] ;
955
+ unsigned int key_len , free_idx = 0 ;
940
956
int type , * key_lens ;
941
957
unsigned long idx ;
942
958
@@ -958,31 +974,43 @@ PHP_METHOD(RedisArray, mset)
958
974
argv = emalloc (argc * sizeof (zval * ));
959
975
pos = emalloc (argc * sizeof (int ));
960
976
keys = emalloc (argc * sizeof (char * ));
961
- key_lens = emalloc (argc * sizeof (int ));
977
+ key_lens = emalloc (argc * sizeof (int ));
962
978
redis_instances = emalloc (argc * sizeof (zval * ));
963
979
memset (redis_instances , 0 , argc * sizeof (zval * ));
964
980
981
+ /* Allocate an array holding the indexes of any keys that need freeing */
982
+ key_free = emalloc (argc * sizeof (char * ));
983
+
965
984
argc_each = emalloc (ra -> count * sizeof (int ));
966
985
memset (argc_each , 0 , ra -> count * sizeof (int ));
967
986
968
987
/* associate each key to a redis node */
969
988
for (i = 0 , zend_hash_internal_pointer_reset (h_keys );
970
989
zend_hash_has_more_elements (h_keys ) == SUCCESS ;
971
- zend_hash_move_forward (h_keys ), i ++ ) {
972
-
973
- type = zend_hash_get_current_key_ex (h_keys , & key , & key_len , & idx , 0 , NULL );
974
- if (type != HASH_KEY_IS_STRING ) { /* ignore non-string keys */
975
- continue ;
976
- }
977
- if (zend_hash_get_current_data (h_keys , (void * * )& data ) == FAILURE ) {
978
- continue ;
979
- }
980
-
981
- redis_instances [i ] = ra_find_node (ra , key , (int )key_len - 1 , & pos [i ] TSRMLS_CC ); /* -1 because of PHP assoc keys which count \0... */
990
+ zend_hash_move_forward (h_keys ), i ++ )
991
+ {
992
+ /* We have to skip the element if we can't get the array value */
993
+ if (zend_hash_get_current_data (h_keys , (void * * )& data ) == FAILURE ) {
994
+ continue ;
995
+ }
996
+
997
+ /* Grab our key */
998
+ type = zend_hash_get_current_key_ex (h_keys , & key , & key_len , & idx , 0 , NULL );
999
+
1000
+ /* If the key isn't a string, make a string representation of it */
1001
+ if (type != HASH_KEY_IS_STRING ) {
1002
+ key_len = snprintf (kbuf , sizeof (kbuf ), "%ld" , (long )idx );
1003
+ key = estrndup (kbuf , key_len );
1004
+ key_free [free_idx ++ ]= key ;
1005
+ } else {
1006
+ key_len -- ; /* We don't want the null terminator */
1007
+ }
1008
+
1009
+ redis_instances [i ] = ra_find_node (ra , key , (int )key_len , & pos [i ] TSRMLS_CC );
982
1010
argc_each [pos [i ]]++ ; /* count number of keys per node */
983
1011
argv [i ] = * data ;
984
1012
keys [i ] = key ;
985
- key_lens [i ] = (int )key_len - 1 ;
1013
+ key_lens [i ] = (int )key_len ;
986
1014
}
987
1015
988
1016
@@ -1035,8 +1063,14 @@ PHP_METHOD(RedisArray, mset)
1035
1063
zval_ptr_dtor (& z_argarray );
1036
1064
}
1037
1065
1066
+ /* Free any keys that we needed to allocate memory for, because they weren't strings */
1067
+ for (i = 0 ; i < free_idx ; i ++ ) {
1068
+ efree (key_free [i ]);
1069
+ }
1070
+
1038
1071
/* cleanup */
1039
1072
efree (keys );
1073
+ efree (key_free );
1040
1074
efree (key_lens );
1041
1075
efree (argv );
1042
1076
efree (pos );
0 commit comments