Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
816e22bc
Commit
816e22bc
authored
Apr 17, 2014
by
antirez
Browse files
ZREMRANGEBYLEX implemented.
parent
d28b239f
Changes
3
Hide whitespace changes
Inline
Side-by-side
src/redis.c
View file @
816e22bc
...
...
@@ -171,6 +171,7 @@ struct redisCommand redisCommandTable[] = {
{
"zrem"
,
zremCommand
,
-
3
,
"w"
,
0
,
NULL
,
1
,
1
,
1
,
0
,
0
},
{
"zremrangebyscore"
,
zremrangebyscoreCommand
,
4
,
"w"
,
0
,
NULL
,
1
,
1
,
1
,
0
,
0
},
{
"zremrangebyrank"
,
zremrangebyrankCommand
,
4
,
"w"
,
0
,
NULL
,
1
,
1
,
1
,
0
,
0
},
{
"zremrangebylex"
,
zremrangebylexCommand
,
4
,
"w"
,
0
,
NULL
,
1
,
1
,
1
,
0
,
0
},
{
"zunionstore"
,
zunionstoreCommand
,
-
4
,
"wm"
,
0
,
zunionInterGetKeys
,
0
,
0
,
0
,
0
,
0
},
{
"zinterstore"
,
zinterstoreCommand
,
-
4
,
"wm"
,
0
,
zunionInterGetKeys
,
0
,
0
,
0
,
0
,
0
},
{
"zrange"
,
zrangeCommand
,
-
4
,
"r"
,
0
,
NULL
,
1
,
1
,
1
,
0
,
0
},
...
...
src/redis.h
View file @
816e22bc
...
...
@@ -1406,6 +1406,7 @@ void zcardCommand(redisClient *c);
void
zremCommand
(
redisClient
*
c
);
void
zscoreCommand
(
redisClient
*
c
);
void
zremrangebyscoreCommand
(
redisClient
*
c
);
void
zremrangebylexCommand
(
redisClient
*
c
);
void
multiCommand
(
redisClient
*
c
);
void
execCommand
(
redisClient
*
c
);
void
discardCommand
(
redisClient
*
c
);
...
...
src/t_zset.c
View file @
816e22bc
...
...
@@ -52,6 +52,9 @@
#include "redis.h"
#include <math.h>
static
int
zslLexValueGteMin
(
robj
*
value
,
zlexrangespec
*
spec
);
static
int
zslLexValueLteMax
(
robj
*
value
,
zlexrangespec
*
spec
);
zskiplistNode
*
zslCreateNode
(
int
level
,
double
score
,
robj
*
obj
)
{
zskiplistNode
*
zn
=
zmalloc
(
sizeof
(
*
zn
)
+
level
*
sizeof
(
struct
zskiplistLevel
));
zn
->
score
=
score
;
...
...
@@ -319,6 +322,35 @@ unsigned long zslDeleteRangeByScore(zskiplist *zsl, zrangespec *range, dict *dic
return
removed
;
}
unsigned
long
zslDeleteRangeByLex
(
zskiplist
*
zsl
,
zlexrangespec
*
range
,
dict
*
dict
)
{
zskiplistNode
*
update
[
ZSKIPLIST_MAXLEVEL
],
*
x
;
unsigned
long
removed
=
0
;
int
i
;
x
=
zsl
->
header
;
for
(
i
=
zsl
->
level
-
1
;
i
>=
0
;
i
--
)
{
while
(
x
->
level
[
i
].
forward
&&
!
zslLexValueGteMin
(
x
->
level
[
i
].
forward
->
obj
,
range
))
x
=
x
->
level
[
i
].
forward
;
update
[
i
]
=
x
;
}
/* Current node is the last with score < or <= min. */
x
=
x
->
level
[
0
].
forward
;
/* Delete nodes while in range. */
while
(
x
&&
zslLexValueLteMax
(
x
->
obj
,
range
))
{
zskiplistNode
*
next
=
x
->
level
[
0
].
forward
;
zslDeleteNode
(
zsl
,
x
,
update
);
dictDelete
(
dict
,
x
->
obj
);
zslFreeNode
(
x
);
removed
++
;
x
=
next
;
}
return
removed
;
}
/* Delete all the elements with rank between start and end from the skiplist.
* Start and end are inclusive. Note that start and end need to be 1-based */
unsigned
long
zslDeleteRangeByRank
(
zskiplist
*
zsl
,
unsigned
int
start
,
unsigned
int
end
,
dict
*
dict
)
{
...
...
@@ -1008,6 +1040,33 @@ unsigned char *zzlDeleteRangeByScore(unsigned char *zl, zrangespec *range, unsig
return
zl
;
}
unsigned
char
*
zzlDeleteRangeByLex
(
unsigned
char
*
zl
,
zlexrangespec
*
range
,
unsigned
long
*
deleted
)
{
unsigned
char
*
eptr
,
*
sptr
;
unsigned
long
num
=
0
;
if
(
deleted
!=
NULL
)
*
deleted
=
0
;
eptr
=
zzlFirstInLexRange
(
zl
,
range
);
if
(
eptr
==
NULL
)
return
zl
;
/* When the tail of the ziplist is deleted, eptr will point to the sentinel
* byte and ziplistNext will return NULL. */
while
((
sptr
=
ziplistNext
(
zl
,
eptr
))
!=
NULL
)
{
if
(
zzlLexValueLteMax
(
eptr
,
range
))
{
/* Delete both the element and the score. */
zl
=
ziplistDelete
(
zl
,
&
eptr
);
zl
=
ziplistDelete
(
zl
,
&
eptr
);
num
++
;
}
else
{
/* No longer in range. */
break
;
}
}
if
(
deleted
!=
NULL
)
*
deleted
=
num
;
return
zl
;
}
/* Delete all the elements with rank between start and end from the skiplist.
* Start and end are inclusive. Note that start and end need to be 1-based */
unsigned
char
*
zzlDeleteRangeByRank
(
unsigned
char
*
zl
,
unsigned
int
start
,
unsigned
int
end
,
unsigned
long
*
deleted
)
{
...
...
@@ -1325,6 +1384,7 @@ void zremrangeGenericCommand(redisClient *c, int rangetype) {
int
keyremoved
=
0
;
unsigned
long
deleted
;
zrangespec
range
;
zlexrangespec
lexrange
;
long
start
,
end
,
llen
;
/* Step 1: Parse the range. */
...
...
@@ -1337,6 +1397,11 @@ void zremrangeGenericCommand(redisClient *c, int rangetype) {
addReplyError
(
c
,
"min or max is not a float"
);
return
;
}
}
else
if
(
rangetype
==
ZRANGE_LEX
)
{
if
(
zslParseLexRange
(
c
->
argv
[
2
],
c
->
argv
[
3
],
&
lexrange
)
!=
REDIS_OK
)
{
addReplyError
(
c
,
"min or max not valid string range item"
);
return
;
}
}
/* Step 2: Lookup & range sanity checks if needed. */
...
...
@@ -1368,6 +1433,9 @@ void zremrangeGenericCommand(redisClient *c, int rangetype) {
case
ZRANGE_SCORE
:
zobj
->
ptr
=
zzlDeleteRangeByScore
(
zobj
->
ptr
,
&
range
,
&
deleted
);
break
;
case
ZRANGE_LEX
:
zobj
->
ptr
=
zzlDeleteRangeByLex
(
zobj
->
ptr
,
&
lexrange
,
&
deleted
);
break
;
}
if
(
zzlLength
(
zobj
->
ptr
)
==
0
)
{
dbDelete
(
c
->
db
,
key
);
...
...
@@ -1382,6 +1450,9 @@ void zremrangeGenericCommand(redisClient *c, int rangetype) {
case
ZRANGE_SCORE
:
deleted
=
zslDeleteRangeByScore
(
zs
->
zsl
,
&
range
,
zs
->
dict
);
break
;
case
ZRANGE_LEX
:
deleted
=
zslDeleteRangeByLex
(
zs
->
zsl
,
&
lexrange
,
zs
->
dict
);
break
;
}
if
(
htNeedsResize
(
zs
->
dict
))
dictResize
(
zs
->
dict
);
if
(
dictSize
(
zs
->
dict
)
==
0
)
{
...
...
@@ -1412,6 +1483,10 @@ void zremrangebyscoreCommand(redisClient *c) {
zremrangeGenericCommand
(
c
,
ZRANGE_SCORE
);
}
void
zremrangebylexCommand
(
redisClient
*
c
)
{
zremrangeGenericCommand
(
c
,
ZRANGE_LEX
);
}
typedef
struct
{
robj
*
subject
;
int
type
;
/* Set, sorted set */
...
...
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