Skip to content

Commit 3491b18

Browse files
Added a new method sAddArray to both Redis and RedisCluster
Presently, the sAdd command is variadic, meaning that it takes a key and then 1 to N additional arguments for the members being added. We need to keep this functionality to avoid breaking existing code, but there are good performance and other reasons to have an sAdd command which takes a key followed by an array of members, which is what the sAddArray method implements.
1 parent 622709f commit 3491b18

File tree

6 files changed

+65
-1
lines changed

6 files changed

+65
-1
lines changed

php_redis.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ PHP_METHOD(Redis, lGetRange);
8080
PHP_METHOD(Redis, lSet);
8181
PHP_METHOD(Redis, lInsert);
8282
PHP_METHOD(Redis, sAdd);
83+
PHP_METHOD(Redis, sAddArray);
8384
PHP_METHOD(Redis, sSize);
8485
PHP_METHOD(Redis, sRemove);
8586
PHP_METHOD(Redis, sMove);

redis.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ static zend_function_entry redis_functions[] = {
156156
PHP_ME(Redis, lSet, NULL, ZEND_ACC_PUBLIC)
157157
PHP_ME(Redis, lInsert, NULL, ZEND_ACC_PUBLIC)
158158
PHP_ME(Redis, sAdd, NULL, ZEND_ACC_PUBLIC)
159+
PHP_ME(Redis, sAddArray, NULL, ZEND_ACC_PUBLIC)
159160
PHP_ME(Redis, sSize, NULL, ZEND_ACC_PUBLIC)
160161
PHP_ME(Redis, sRemove, NULL, ZEND_ACC_PUBLIC)
161162
PHP_ME(Redis, sMove, NULL, ZEND_ACC_PUBLIC)
@@ -1252,13 +1253,18 @@ PHP_METHOD(Redis, lGetRange)
12521253
}
12531254
/* }}} */
12541255

1255-
/* {{{ proto boolean Redis::sAdd(string key , mixed value) */
1256+
/* {{{ proto long Redis::sAdd(string key , mixed value) */
12561257
PHP_METHOD(Redis, sAdd)
12571258
{
12581259
REDIS_PROCESS_KW_CMD("SADD", redis_key_varval_cmd, redis_long_response);
12591260
}
12601261
/* }}} */
12611262

1263+
/* {{{ proto boolean Redis::sAddArray(string key, array $values) */
1264+
PHP_METHOD(Redis, sAddArray) {
1265+
REDIS_PROCESS_KW_CMD("SADD", redis_key_arr_cmd, redis_long_response);
1266+
} /* }}} */
1267+
12621268
/* {{{ proto int Redis::sSize(string key) */
12631269
PHP_METHOD(Redis, sSize)
12641270
{

redis_cluster.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ zend_function_entry redis_cluster_functions[] = {
9191
PHP_ME(RedisCluster, smembers, NULL, ZEND_ACC_PUBLIC)
9292
PHP_ME(RedisCluster, sismember, NULL, ZEND_ACC_PUBLIC)
9393
PHP_ME(RedisCluster, sadd, NULL, ZEND_ACC_PUBLIC)
94+
PHP_ME(RedisCluster, saddarray, NULL, ZEND_ACC_PUBLIC)
9495
PHP_ME(RedisCluster, srem, NULL, ZEND_ACC_PUBLIC)
9596
PHP_ME(RedisCluster, sunion, NULL, ZEND_ACC_PUBLIC)
9697
PHP_ME(RedisCluster, sunionstore, NULL, ZEND_ACC_PUBLIC)
@@ -1196,6 +1197,12 @@ PHP_METHOD(RedisCluster, sadd) {
11961197
}
11971198
/* }}} */
11981199

1200+
/* {{{ proto long RedisCluster::saddarray(string key, array values) */
1201+
PHP_METHOD(RedisCluster, saddarray) {
1202+
CLUSTER_PROCESS_KW_CMD("SADD", redis_key_arr_cmd, cluster_long_resp, 0);
1203+
}
1204+
/* }}} */
1205+
11991206
/* {{{ proto long RedisCluster::srem(string key, string val1 [, ...]) */
12001207
PHP_METHOD(RedisCluster, srem) {
12011208
CLUSTER_PROCESS_KW_CMD("SREM", redis_key_varval_cmd, cluster_long_resp, 0);

redis_cluster.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ PHP_METHOD(RedisCluster, scard);
149149
PHP_METHOD(RedisCluster, smembers);
150150
PHP_METHOD(RedisCluster, sismember);
151151
PHP_METHOD(RedisCluster, sadd);
152+
PHP_METHOD(RedisCluster, saddarray);
152153
PHP_METHOD(RedisCluster, srem);
153154
PHP_METHOD(RedisCluster, sunion);
154155
PHP_METHOD(RedisCluster, sunionstore);

redis_commands.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -999,6 +999,52 @@ int redis_key_varval_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
999999
return SUCCESS;
10001000
}
10011001

1002+
/* Commands that take a key and then an array of values */
1003+
int redis_key_arr_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
1004+
char *kw, char **cmd, int *cmd_len, short *slot,
1005+
void **ctx)
1006+
{
1007+
zval *z_key, *z_arr, **z_val;
1008+
HashTable *ht_arr;
1009+
HashPosition pos;
1010+
smart_str cmdstr = {0};
1011+
int key_len, val_len, key_free, val_free, argc = 1;
1012+
char *key, *val;
1013+
1014+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa", &key, &key_len,
1015+
&z_arr) == FAILURE ||
1016+
zend_hash_num_elements(Z_ARRVAL_P(z_arr)) == 0)
1017+
{
1018+
return FAILURE;
1019+
}
1020+
1021+
/* Start constructing our command */
1022+
ht_arr = Z_ARRVAL_P(z_arr);
1023+
argc += zend_hash_num_elements(ht_arr);
1024+
redis_cmd_init_sstr(&cmdstr, argc, kw, strlen(kw));
1025+
1026+
/* Prefix if required and append the key name */
1027+
key_free = redis_key_prefix(redis_sock, &key, &key_len);
1028+
redis_cmd_append_sstr(&cmdstr, key, key_len);
1029+
CMD_SET_SLOT(slot, key, key_len);
1030+
if (key_free) efree(key);
1031+
1032+
/* Iterate our hash table, serializing and appending values */
1033+
for (zend_hash_internal_pointer_reset_ex(ht_arr, &pos);
1034+
zend_hash_get_current_data_ex(ht_arr, (void**)&z_val, &pos) == SUCCESS;
1035+
zend_hash_move_forward_ex(ht_arr, &pos))
1036+
{
1037+
val_free = redis_serialize(redis_sock, *z_val, &val, &val_len TSRMLS_CC);
1038+
redis_cmd_append_sstr(&cmdstr, val, val_len);
1039+
if (val_free) STR_FREE(val);
1040+
}
1041+
1042+
*cmd_len = cmdstr.len;
1043+
*cmd = cmdstr.c;
1044+
1045+
return SUCCESS;
1046+
}
1047+
10021048
/* Generic function that takes a variable number of keys, with an optional
10031049
* timeout value. This can handle various SUNION/SUNIONSTORE/BRPOP type
10041050
* commands. */

redis_commands.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ int redis_key_dbl_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
6767
int redis_key_varval_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
6868
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
6969

70+
int redis_key_arr_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
71+
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);
72+
7073
/* Construct SCAN and similar commands, as well as check iterator */
7174
int redis_scan_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
7275
REDIS_SCAN_TYPE type, char **cmd, int *cmd_len);

0 commit comments

Comments
 (0)