Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Added msadd #20

Closed
wants to merge 3 commits into from

3 participants

@seppo0010

Acording to TODO file and http://groups.google.com/group/redis-db/browse_thread/thread/e766d84eb375cd41 implemented msadd.

It's my first contribution to the project, so let me know if there is anything I did wrong or can improve on the future!

Sebastian Wa... added some commits
Sebastian Waisbrot Added MSADD command 52333df
Sebastian Waisbrot Added set test
s
9f24a34
Sebastian Waisbrot Added todo on unit test 332bce5
@bendiken

+1 awesome, looking forward to testing this; it will come very handy for many of our Redis use cases.

@mattsta

Fixed by multi args as of Redis 2.4+

@mattsta mattsta closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Oct 29, 2010
  1. Added MSADD command

    Sebastian Waisbrot authored
  2. Added set test

    Sebastian Waisbrot authored
    s
  3. Added todo on unit test

    Sebastian Waisbrot authored
This page is out of date. Refresh to see the latest.
View
1  src/redis.c
@@ -98,6 +98,7 @@ struct redisCommand readonlyCommandTable[] = {
{"lrem",lremCommand,4,0,NULL,1,1,1},
{"rpoplpush",rpoplpushcommand,3,REDIS_CMD_DENYOOM,NULL,1,2,1},
{"sadd",saddCommand,3,REDIS_CMD_DENYOOM,NULL,1,1,1},
+ {"msadd",msaddCommand,-3,REDIS_CMD_DENYOOM,NULL,1,1,1},
{"srem",sremCommand,3,0,NULL,1,1,1},
{"smove",smoveCommand,4,0,NULL,1,2,1},
{"sismember",sismemberCommand,3,0,NULL,1,1,1},
View
1  src/redis.h
@@ -890,6 +890,7 @@ void ltrimCommand(redisClient *c);
void typeCommand(redisClient *c);
void lsetCommand(redisClient *c);
void saddCommand(redisClient *c);
+void msaddCommand(redisClient *c);
void sremCommand(redisClient *c);
void smoveCommand(redisClient *c);
void sismemberCommand(redisClient *c);
View
76 src/t_set.c
@@ -197,6 +197,82 @@ void saddCommand(redisClient *c) {
}
}
+void msaddCommand(redisClient *c) {
+ int setnum, valnum;
+ int i, j;
+ robj **sets;
+
+ setnum = atoi(c->argv[1]->ptr);
+ valnum = atoi(c->argv[2]->ptr);
+
+ if (setnum < 1) {
+ addReplyError(c,
+ "at least 1 input key is needed for MSADD");
+ return;
+ }
+
+ if (valnum < 1) {
+ addReplyError(c,
+ "at least 1 input value is needed for MSADD");
+ return;
+ }
+
+ /* test if the expected number of keys would overflow */
+ if (3+setnum+valnum > c->argc) {
+ addReply(c,shared.syntaxerr);
+ return;
+ }
+
+ int useintset = 0;
+ for (j = 0; j < valnum; j++) {
+ robj *value = c->argv[3 + setnum + j];
+ if (isObjectRepresentableAsLongLong(value,NULL) != REDIS_OK) {
+ useintset = 1;
+ break;
+ }
+ }
+
+ sets = zmalloc(sizeof(robj*)*setnum);
+ int notset = 0;
+ for (i = 0; i < setnum; i++) {
+ robj *key = c->argv[3 + i];
+ robj *set = lookupKeyWrite(c->db, key);
+ if (set == NULL) {
+ if (useintset == 1)
+ set = createIntsetObject();
+ else
+ set = createSetObject();
+ dbAdd(c->db,key,set);
+ } else {
+ if (set->type != REDIS_SET) {
+ notset = 1;
+ break;
+ }
+ }
+ sets[i] = set;
+ }
+
+ if (notset == 1) {
+ addReply(c,shared.wrongtypeerr);
+ } else {
+ long long inserted = 0;
+ for (i = 0; i < setnum; i++) {
+ for (j = 0; j < valnum; j++) {
+ robj *key = c->argv[3 + i];
+ robj *value = c->argv[3 + setnum + j];
+ robj *set = sets[i];
+ if (setTypeAdd(set,value)) {
+ touchWatchedKey(c->db,key);
+ server.dirty++;
+ inserted++;
+ }
+ }
+ }
+ addReplyLongLong(c,inserted);
+ }
+ zfree(sets);
+}
+
void sremCommand(redisClient *c) {
robj *set;
View
53 tests/unit/type/set.tcl
@@ -59,6 +59,59 @@ start_server {
assert_encoding hashtable myset
}
+ test {MSADD, SISMEMBER, SMEMBERS basics - regular sets} {
+ create_set myset {foo}
+ create_set anotherset {bar}
+ assert_encoding hashtable myset
+ assert_equal 1 [r msadd 2 1 anotherset myset bar]
+ assert_equal 0 [r msadd 2 1 anotherset myset bar]
+ assert_equal 0 [r msadd 1 1 myset bar]
+ assert_equal 1 [r msadd 1 2 anotherset bar baz]
+ assert_equal 2 [r scard myset]
+ assert_equal 1 [r sismember myset foo]
+ assert_equal 1 [r sismember myset bar]
+ assert_equal 0 [r sismember myset baz]
+ assert_equal 0 [r sismember myset bla]
+ assert_equal 0 [r sismember anotherset foo]
+ assert_equal 1 [r sismember anotherset bar]
+ assert_equal 1 [r sismember anotherset baz]
+ assert_equal 0 [r sismember anotherset bla]
+ assert_equal {bar foo} [lsort [r smembers myset]]
+ }
+
+ test {MSADD against non set} {
+ r lpush mylist foo
+ create_set myset {foo}
+ assert_error ERR*kind* {r msadd 1 1 mylist bar}
+ assert_error ERR*kind* {r msadd 2 1 mylist myset bar}
+ }
+
+ test "MSADD a non-integer against an intset" {
+ create_set myset {1 2 3}
+ create_set anotherset {foo}
+ assert_encoding intset myset
+ assert_equal 1 [r msadd 1 1 myset a]
+ assert_equal 2 [r msadd 2 1 myset anotherset b]
+ assert_encoding hashtable myset
+ }
+
+ test "MSADD overflows the maximum allowed integers in an intset" {
+ r del myset
+ for {set i 0} {$i < 512} {incr i} { r sadd myset $i }
+ assert_encoding intset myset
+ assert_equal 1 [r msadd 1 1 myset 512]
+ assert_encoding hashtable myset
+ }
+
+# TODO: do this test. It works manually, but I can't make it work with tcl
+# test "MSADD creates an intset with more than the maximum allowed" {
+# r del myset
+# set var ""
+# for {set i 0} {$i < 513} {incr i} { append var " " $i }
+# assert_equal 513 [r msadd 1 513 myset $var]
+# assert_encoding hashtable myset
+# }
+
test "Set encoding after DEBUG RELOAD" {
r del myintset myhashset mylargeintset
for {set i 0} {$i < 100} {incr i} { r sadd myintset $i }
Something went wrong with that request. Please try again.