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
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[] = {
...
@@ -171,6 +171,7 @@ struct redisCommand redisCommandTable[] = {
{
"zrem"
,
zremCommand
,
-
3
,
"w"
,
0
,
NULL
,
1
,
1
,
1
,
0
,
0
},
{
"zrem"
,
zremCommand
,
-
3
,
"w"
,
0
,
NULL
,
1
,
1
,
1
,
0
,
0
},
{
"zremrangebyscore"
,
zremrangebyscoreCommand
,
4
,
"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
},
{
"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
},
{
"zunionstore"
,
zunionstoreCommand
,
-
4
,
"wm"
,
0
,
zunionInterGetKeys
,
0
,
0
,
0
,
0
,
0
},
{
"zinterstore"
,
zinterstoreCommand
,
-
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
},
{
"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);
...
@@ -1406,6 +1406,7 @@ void zcardCommand(redisClient *c);
void
zremCommand
(
redisClient
*
c
);
void
zremCommand
(
redisClient
*
c
);
void
zscoreCommand
(
redisClient
*
c
);
void
zscoreCommand
(
redisClient
*
c
);
void
zremrangebyscoreCommand
(
redisClient
*
c
);
void
zremrangebyscoreCommand
(
redisClient
*
c
);
void
zremrangebylexCommand
(
redisClient
*
c
);
void
multiCommand
(
redisClient
*
c
);
void
multiCommand
(
redisClient
*
c
);
void
execCommand
(
redisClient
*
c
);
void
execCommand
(
redisClient
*
c
);
void
discardCommand
(
redisClient
*
c
);
void
discardCommand
(
redisClient
*
c
);
...
...
src/t_zset.c
View file @
816e22bc
...
@@ -52,6 +52,9 @@
...
@@ -52,6 +52,9 @@
#include "redis.h"
#include "redis.h"
#include <math.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
*
zslCreateNode
(
int
level
,
double
score
,
robj
*
obj
)
{
zskiplistNode
*
zn
=
zmalloc
(
sizeof
(
*
zn
)
+
level
*
sizeof
(
struct
zskiplistLevel
));
zskiplistNode
*
zn
=
zmalloc
(
sizeof
(
*
zn
)
+
level
*
sizeof
(
struct
zskiplistLevel
));
zn
->
score
=
score
;
zn
->
score
=
score
;
...
@@ -319,6 +322,35 @@ unsigned long zslDeleteRangeByScore(zskiplist *zsl, zrangespec *range, dict *dic
...
@@ -319,6 +322,35 @@ unsigned long zslDeleteRangeByScore(zskiplist *zsl, zrangespec *range, dict *dic
return
removed
;
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.
/* 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 */
* 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
)
{
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
...
@@ -1008,6 +1040,33 @@ unsigned char *zzlDeleteRangeByScore(unsigned char *zl, zrangespec *range, unsig
return
zl
;
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.
/* 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 */
* 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
)
{
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) {
...
@@ -1325,6 +1384,7 @@ void zremrangeGenericCommand(redisClient *c, int rangetype) {
int
keyremoved
=
0
;
int
keyremoved
=
0
;
unsigned
long
deleted
;
unsigned
long
deleted
;
zrangespec
range
;
zrangespec
range
;
zlexrangespec
lexrange
;
long
start
,
end
,
llen
;
long
start
,
end
,
llen
;
/* Step 1: Parse the range. */
/* Step 1: Parse the range. */
...
@@ -1337,6 +1397,11 @@ void zremrangeGenericCommand(redisClient *c, int rangetype) {
...
@@ -1337,6 +1397,11 @@ void zremrangeGenericCommand(redisClient *c, int rangetype) {
addReplyError
(
c
,
"min or max is not a float"
);
addReplyError
(
c
,
"min or max is not a float"
);
return
;
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. */
/* Step 2: Lookup & range sanity checks if needed. */
...
@@ -1368,6 +1433,9 @@ void zremrangeGenericCommand(redisClient *c, int rangetype) {
...
@@ -1368,6 +1433,9 @@ void zremrangeGenericCommand(redisClient *c, int rangetype) {
case
ZRANGE_SCORE
:
case
ZRANGE_SCORE
:
zobj
->
ptr
=
zzlDeleteRangeByScore
(
zobj
->
ptr
,
&
range
,
&
deleted
);
zobj
->
ptr
=
zzlDeleteRangeByScore
(
zobj
->
ptr
,
&
range
,
&
deleted
);
break
;
break
;
case
ZRANGE_LEX
:
zobj
->
ptr
=
zzlDeleteRangeByLex
(
zobj
->
ptr
,
&
lexrange
,
&
deleted
);
break
;
}
}
if
(
zzlLength
(
zobj
->
ptr
)
==
0
)
{
if
(
zzlLength
(
zobj
->
ptr
)
==
0
)
{
dbDelete
(
c
->
db
,
key
);
dbDelete
(
c
->
db
,
key
);
...
@@ -1382,6 +1450,9 @@ void zremrangeGenericCommand(redisClient *c, int rangetype) {
...
@@ -1382,6 +1450,9 @@ void zremrangeGenericCommand(redisClient *c, int rangetype) {
case
ZRANGE_SCORE
:
case
ZRANGE_SCORE
:
deleted
=
zslDeleteRangeByScore
(
zs
->
zsl
,
&
range
,
zs
->
dict
);
deleted
=
zslDeleteRangeByScore
(
zs
->
zsl
,
&
range
,
zs
->
dict
);
break
;
break
;
case
ZRANGE_LEX
:
deleted
=
zslDeleteRangeByLex
(
zs
->
zsl
,
&
lexrange
,
zs
->
dict
);
break
;
}
}
if
(
htNeedsResize
(
zs
->
dict
))
dictResize
(
zs
->
dict
);
if
(
htNeedsResize
(
zs
->
dict
))
dictResize
(
zs
->
dict
);
if
(
dictSize
(
zs
->
dict
)
==
0
)
{
if
(
dictSize
(
zs
->
dict
)
==
0
)
{
...
@@ -1412,6 +1483,10 @@ void zremrangebyscoreCommand(redisClient *c) {
...
@@ -1412,6 +1483,10 @@ void zremrangebyscoreCommand(redisClient *c) {
zremrangeGenericCommand
(
c
,
ZRANGE_SCORE
);
zremrangeGenericCommand
(
c
,
ZRANGE_SCORE
);
}
}
void
zremrangebylexCommand
(
redisClient
*
c
)
{
zremrangeGenericCommand
(
c
,
ZRANGE_LEX
);
}
typedef
struct
{
typedef
struct
{
robj
*
subject
;
robj
*
subject
;
int
type
;
/* Set, sorted set */
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