Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
f4f56e1d
Commit
f4f56e1d
authored
May 17, 2009
by
antirez
Browse files
SDIFF/SDIFFSTORE implemnted unifying it with the implementation of SUNION/SUNIONSTORE
parent
1904ecc1
Changes
3
Show whitespace changes
Inline
Side-by-side
redis-cli.c
View file @
f4f56e1d
...
@@ -83,6 +83,8 @@ static struct redisCommand cmdTable[] = {
...
@@ -83,6 +83,8 @@ static struct redisCommand cmdTable[] = {
{
"sinterstore"
,
-
3
,
REDIS_CMD_INLINE
},
{
"sinterstore"
,
-
3
,
REDIS_CMD_INLINE
},
{
"sunion"
,
-
2
,
REDIS_CMD_INLINE
},
{
"sunion"
,
-
2
,
REDIS_CMD_INLINE
},
{
"sunionstore"
,
-
3
,
REDIS_CMD_INLINE
},
{
"sunionstore"
,
-
3
,
REDIS_CMD_INLINE
},
{
"sdiff"
,
-
2
,
REDIS_CMD_INLINE
},
{
"sdiffstore"
,
-
3
,
REDIS_CMD_INLINE
},
{
"smembers"
,
2
,
REDIS_CMD_INLINE
},
{
"smembers"
,
2
,
REDIS_CMD_INLINE
},
{
"incrby"
,
3
,
REDIS_CMD_INLINE
},
{
"incrby"
,
3
,
REDIS_CMD_INLINE
},
{
"decrby"
,
3
,
REDIS_CMD_INLINE
},
{
"decrby"
,
3
,
REDIS_CMD_INLINE
},
...
...
redis.c
View file @
f4f56e1d
...
@@ -348,6 +348,8 @@ static void sinterCommand(redisClient *c);
...
@@ -348,6 +348,8 @@ static void sinterCommand(redisClient *c);
static
void
sinterstoreCommand
(
redisClient
*
c
);
static
void
sinterstoreCommand
(
redisClient
*
c
);
static
void
sunionCommand
(
redisClient
*
c
);
static
void
sunionCommand
(
redisClient
*
c
);
static
void
sunionstoreCommand
(
redisClient
*
c
);
static
void
sunionstoreCommand
(
redisClient
*
c
);
static
void
sdiffCommand
(
redisClient
*
c
);
static
void
sdiffstoreCommand
(
redisClient
*
c
);
static
void
syncCommand
(
redisClient
*
c
);
static
void
syncCommand
(
redisClient
*
c
);
static
void
flushdbCommand
(
redisClient
*
c
);
static
void
flushdbCommand
(
redisClient
*
c
);
static
void
flushallCommand
(
redisClient
*
c
);
static
void
flushallCommand
(
redisClient
*
c
);
...
@@ -391,6 +393,8 @@ static struct redisCommand cmdTable[] = {
...
@@ -391,6 +393,8 @@ static struct redisCommand cmdTable[] = {
{
"sinterstore"
,
sinterstoreCommand
,
-
3
,
REDIS_CMD_INLINE
},
{
"sinterstore"
,
sinterstoreCommand
,
-
3
,
REDIS_CMD_INLINE
},
{
"sunion"
,
sunionCommand
,
-
2
,
REDIS_CMD_INLINE
},
{
"sunion"
,
sunionCommand
,
-
2
,
REDIS_CMD_INLINE
},
{
"sunionstore"
,
sunionstoreCommand
,
-
3
,
REDIS_CMD_INLINE
},
{
"sunionstore"
,
sunionstoreCommand
,
-
3
,
REDIS_CMD_INLINE
},
{
"sdiff"
,
sdiffCommand
,
-
2
,
REDIS_CMD_INLINE
},
{
"sdiffstore"
,
sdiffstoreCommand
,
-
3
,
REDIS_CMD_INLINE
},
{
"smembers"
,
sinterCommand
,
2
,
REDIS_CMD_INLINE
},
{
"smembers"
,
sinterCommand
,
2
,
REDIS_CMD_INLINE
},
{
"incrby"
,
incrbyCommand
,
3
,
REDIS_CMD_INLINE
},
{
"incrby"
,
incrbyCommand
,
3
,
REDIS_CMD_INLINE
},
{
"decrby"
,
decrbyCommand
,
3
,
REDIS_CMD_INLINE
},
{
"decrby"
,
decrbyCommand
,
3
,
REDIS_CMD_INLINE
},
...
@@ -3057,14 +3061,17 @@ static void sinterstoreCommand(redisClient *c) {
...
@@ -3057,14 +3061,17 @@ static void sinterstoreCommand(redisClient *c) {
sinterGenericCommand
(
c
,
c
->
argv
+
2
,
c
->
argc
-
2
,
c
->
argv
[
1
]);
sinterGenericCommand
(
c
,
c
->
argv
+
2
,
c
->
argc
-
2
,
c
->
argv
[
1
]);
}
}
static
void
sunionGenericCommand
(
redisClient
*
c
,
robj
**
setskeys
,
int
setsnum
,
robj
*
dstkey
)
{
#define REDIS_OP_UNION 0
#define REDIS_OP_DIFF 1
static
void
sunionDiffGenericCommand
(
redisClient
*
c
,
robj
**
setskeys
,
int
setsnum
,
robj
*
dstkey
,
int
op
)
{
dict
**
dv
=
zmalloc
(
sizeof
(
dict
*
)
*
setsnum
);
dict
**
dv
=
zmalloc
(
sizeof
(
dict
*
)
*
setsnum
);
dictIterator
*
di
;
dictIterator
*
di
;
dictEntry
*
de
;
dictEntry
*
de
;
robj
*
lenobj
=
NULL
,
*
dstset
=
NULL
;
robj
*
dstset
=
NULL
;
int
j
,
cardinality
=
0
;
int
j
,
cardinality
=
0
;
if
(
!
dv
)
oom
(
"sunionCommand"
);
if
(
!
dv
)
oom
(
"sunion
DiffGeneric
Command"
);
for
(
j
=
0
;
j
<
setsnum
;
j
++
)
{
for
(
j
=
0
;
j
<
setsnum
;
j
++
)
{
robj
*
setobj
;
robj
*
setobj
;
...
@@ -3093,11 +3100,7 @@ static void sunionGenericCommand(redisClient *c, robj **setskeys, int setsnum, r
...
@@ -3093,11 +3100,7 @@ static void sunionGenericCommand(redisClient *c, robj **setskeys, int setsnum, r
* the intersection set size, so we use a trick, append an empty object
* the intersection set size, so we use a trick, append an empty object
* to the output list and save the pointer to later modify it with the
* to the output list and save the pointer to later modify it with the
* right length */
* right length */
if
(
!
dstkey
)
{
if
(
dstkey
)
{
lenobj
=
createObject
(
REDIS_STRING
,
NULL
);
addReply
(
c
,
lenobj
);
decrRefCount
(
lenobj
);
}
else
{
/* If we have a target key where to store the resulting set
/* If we have a target key where to store the resulting set
* create this key with an empty set inside */
* create this key with an empty set inside */
deleteKey
(
c
->
db
,
dstkey
);
deleteKey
(
c
->
db
,
dstkey
);
...
@@ -3119,22 +3122,39 @@ static void sunionGenericCommand(redisClient *c, robj **setskeys, int setsnum, r
...
@@ -3119,22 +3122,39 @@ static void sunionGenericCommand(redisClient *c, robj **setskeys, int setsnum, r
/* dictAdd will not add the same element multiple times */
/* dictAdd will not add the same element multiple times */
ele
=
dictGetEntryKey
(
de
);
ele
=
dictGetEntryKey
(
de
);
if
(
op
==
REDIS_OP_UNION
||
j
==
0
)
{
if
(
dictAdd
(
dstset
->
ptr
,
ele
,
NULL
)
==
DICT_OK
)
{
if
(
dictAdd
(
dstset
->
ptr
,
ele
,
NULL
)
==
DICT_OK
)
{
incrRefCount
(
ele
);
incrRefCount
(
ele
);
cardinality
++
;
}
}
else
if
(
op
==
REDIS_OP_DIFF
)
{
if
(
dictDelete
(
dstset
->
ptr
,
ele
)
==
DICT_OK
)
{
cardinality
--
;
}
}
}
dictReleaseIterator
(
di
);
}
/* Output the content of the resulting set, if not in STORE mode */
if
(
!
dstkey
)
{
if
(
!
dstkey
)
{
addReplySds
(
c
,
sdscatprintf
(
sdsempty
(),
"*%d
\r\n
"
,
cardinality
));
di
=
dictGetIterator
(
dstset
->
ptr
);
if
(
!
di
)
oom
(
"dictGetIterator"
);
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
robj
*
ele
;
ele
=
dictGetEntryKey
(
de
);
addReplySds
(
c
,
sdscatprintf
(
sdsempty
(),
addReplySds
(
c
,
sdscatprintf
(
sdsempty
(),
"$%d
\r\n
"
,
sdslen
(
ele
->
ptr
)));
"$%d
\r\n
"
,
sdslen
(
ele
->
ptr
)));
addReply
(
c
,
ele
);
addReply
(
c
,
ele
);
addReply
(
c
,
shared
.
crlf
);
addReply
(
c
,
shared
.
crlf
);
cardinality
++
;
}
}
}
}
dictReleaseIterator
(
di
);
dictReleaseIterator
(
di
);
}
}
/* Cleanup */
if
(
!
dstkey
)
{
if
(
!
dstkey
)
{
lenobj
->
ptr
=
sdscatprintf
(
sdsempty
(),
"*%d
\r\n
"
,
cardinality
);
decrRefCount
(
dstset
);
decrRefCount
(
dstset
);
}
else
{
}
else
{
addReply
(
c
,
shared
.
ok
);
addReply
(
c
,
shared
.
ok
);
...
@@ -3144,11 +3164,19 @@ static void sunionGenericCommand(redisClient *c, robj **setskeys, int setsnum, r
...
@@ -3144,11 +3164,19 @@ static void sunionGenericCommand(redisClient *c, robj **setskeys, int setsnum, r
}
}
static
void
sunionCommand
(
redisClient
*
c
)
{
static
void
sunionCommand
(
redisClient
*
c
)
{
sunionGenericCommand
(
c
,
c
->
argv
+
1
,
c
->
argc
-
1
,
NULL
);
sunion
Diff
GenericCommand
(
c
,
c
->
argv
+
1
,
c
->
argc
-
1
,
NULL
,
REDIS_OP_UNION
);
}
}
static
void
sunionstoreCommand
(
redisClient
*
c
)
{
static
void
sunionstoreCommand
(
redisClient
*
c
)
{
sunionGenericCommand
(
c
,
c
->
argv
+
2
,
c
->
argc
-
2
,
c
->
argv
[
1
]);
sunionDiffGenericCommand
(
c
,
c
->
argv
+
2
,
c
->
argc
-
2
,
c
->
argv
[
1
],
REDIS_OP_UNION
);
}
static
void
sdiffCommand
(
redisClient
*
c
)
{
sunionDiffGenericCommand
(
c
,
c
->
argv
+
1
,
c
->
argc
-
1
,
NULL
,
REDIS_OP_DIFF
);
}
static
void
sdiffstoreCommand
(
redisClient
*
c
)
{
sunionDiffGenericCommand
(
c
,
c
->
argv
+
2
,
c
->
argc
-
2
,
c
->
argv
[
1
],
REDIS_OP_DIFF
);
}
}
static
void
flushdbCommand
(
redisClient
*
c
)
{
static
void
flushdbCommand
(
redisClient
*
c
)
{
...
...
test-redis.tcl
View file @
f4f56e1d
...
@@ -498,6 +498,23 @@ proc main {server port} {
...
@@ -498,6 +498,23 @@ proc main {server port} {
lsort
[
$r
sunion nokey1 set1 set2 nokey2
]
lsort
[
$r
sunion nokey1 set1 set2 nokey2
]
}
[
lsort -uniq
"
[
$r
smembers set1
]
[
$r
smembers set2
]
"
]
}
[
lsort -uniq
"
[
$r
smembers set1
]
[
$r
smembers set2
]
"
]
test
{
SDIFF with two sets
}
{
for
{
set i 5
}
{
$i
< 1000
}
{
incr i
}
{
$r sadd set4 $i
}
lsort
[
$r
sdiff set1 set4
]
}
{
0 1 2 3 4
}
test
{
SDIFF with three sets
}
{
$r sadd set5 0
lsort
[
$r
sdiff set1 set4 set5
]
}
{
1 2 3 4
}
test
{
SDIFFSTORE with three sets
}
{
$r sdiffstore sres set1 set4 set5
lsort
[
$r
smembers sres
]
}
{
1 2 3 4
}
test
{
SAVE - make sure there are all the types as values
}
{
test
{
SAVE - make sure there are all the types as values
}
{
$r lpush mysavelist hello
$r lpush mysavelist hello
$r lpush mysavelist world
$r lpush mysavelist world
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment