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
72244651
Unverified
Commit
72244651
authored
Jul 08, 2019
by
Salvatore Sanfilippo
Committed by
GitHub
Jul 08, 2019
Browse files
Merge pull request #6116 from AngusP/scan-types
SCAN: New Feature `SCAN cursor [TYPE type]` modifier suggested in issue #6107
parents
4c4b7023
6eb52e20
Changes
3
Hide whitespace changes
Inline
Side-by-side
src/db.c
View file @
72244651
...
...
@@ -614,7 +614,7 @@ int parseScanCursorOrReply(client *c, robj *o, unsigned long *cursor) {
}
/* This command implements SCAN, HSCAN and SSCAN commands.
* If object 'o' is passed, then it must be a Hash or
S
et object, otherwise
* If object 'o' is passed, then it must be a Hash
, Set
or
Zs
et object, otherwise
* if 'o' is NULL the command will operate on the dictionary associated with
* the current database.
*
...
...
@@ -630,6 +630,7 @@ void scanGenericCommand(client *c, robj *o, unsigned long cursor) {
listNode
*
node
,
*
nextnode
;
long
count
=
10
;
sds
pat
=
NULL
;
sds
typename
=
NULL
;
int
patlen
=
0
,
use_pattern
=
0
;
dict
*
ht
;
...
...
@@ -666,6 +667,10 @@ void scanGenericCommand(client *c, robj *o, unsigned long cursor) {
use_pattern
=
!
(
pat
[
0
]
==
'*'
&&
patlen
==
1
);
i
+=
2
;
}
else
if
(
!
strcasecmp
(
c
->
argv
[
i
]
->
ptr
,
"type"
)
&&
o
==
NULL
&&
j
>=
2
)
{
/* SCAN for a particular type only applies to the db dict */
typename
=
c
->
argv
[
i
+
1
]
->
ptr
;
i
+=
2
;
}
else
{
addReply
(
c
,
shared
.
syntaxerr
);
goto
cleanup
;
...
...
@@ -760,6 +765,13 @@ void scanGenericCommand(client *c, robj *o, unsigned long cursor) {
}
}
/* Filter an element if it isn't the type we want. */
if
(
!
filter
&&
o
==
NULL
&&
typename
){
robj
*
typecheck
=
lookupKeyReadWithFlags
(
c
->
db
,
kobj
,
LOOKUP_NOTOUCH
);
char
*
type
=
getObjectTypeName
(
typecheck
);
if
(
strcasecmp
((
char
*
)
typename
,
type
))
filter
=
1
;
}
/* Filter element if it is an expired key. */
if
(
!
filter
&&
o
==
NULL
&&
expireIfNeeded
(
c
->
db
,
kobj
))
filter
=
1
;
...
...
@@ -816,11 +828,8 @@ void lastsaveCommand(client *c) {
addReplyLongLong
(
c
,
server
.
lastsave
);
}
void
typeCommand
(
client
*
c
)
{
robj
*
o
;
char
*
type
;
o
=
lookupKeyReadWithFlags
(
c
->
db
,
c
->
argv
[
1
],
LOOKUP_NOTOUCH
);
char
*
getObjectTypeName
(
robj
*
o
)
{
char
*
type
;
if
(
o
==
NULL
)
{
type
=
"none"
;
}
else
{
...
...
@@ -838,7 +847,13 @@ void typeCommand(client *c) {
default:
type
=
"unknown"
;
break
;
}
}
addReplyStatus
(
c
,
type
);
return
type
;
}
void
typeCommand
(
client
*
c
)
{
robj
*
o
;
o
=
lookupKeyReadWithFlags
(
c
->
db
,
c
->
argv
[
1
],
LOOKUP_NOTOUCH
);
addReplyStatus
(
c
,
getObjectTypeName
(
o
));
}
void
shutdownCommand
(
client
*
c
)
{
...
...
src/server.h
View file @
72244651
...
...
@@ -652,6 +652,11 @@ typedef struct redisObject {
void
*
ptr
;
}
robj
;
/* The a string name for an object's type as listed above
* Native types are checked against the OBJ_STRING, OBJ_LIST, OBJ_* defines,
* and Module types have their registered name returned. */
char
*
getObjectTypeName
(
robj
*
);
/* Macro used to initialize a Redis object allocated on the stack.
* Note that this macro is taken near the structure definition to make sure
* we'll update it when the structure is changed, to avoid bugs like
...
...
tests/unit/scan.tcl
View file @
72244651
...
...
@@ -53,6 +53,51 @@ start_server {tags {"scan"}} {
assert_equal 100
[
llength $keys
]
}
test
"SCAN TYPE"
{
r flushdb
# populate only creates strings
r debug populate 1000
# Check non-strings are excluded
set cur 0
set keys
{}
while 1
{
set res
[
r scan $cur type
"list"
]
set cur
[
lindex $res 0
]
set k
[
lindex $res 1
]
lappend keys
{*}
$k
if
{
$cur
== 0
}
break
}
assert_equal 0
[
llength $keys
]
# Check strings are included
set cur 0
set keys
{}
while 1
{
set res
[
r scan $cur type
"string"
]
set cur
[
lindex $res 0
]
set k
[
lindex $res 1
]
lappend keys
{*}
$k
if
{
$cur
== 0
}
break
}
assert_equal 1000
[
llength $keys
]
# Check all three args work together
set cur 0
set keys
{}
while 1
{
set res
[
r scan $cur type
"string"
match
"key:*"
count 10
]
set cur
[
lindex $res 0
]
set k
[
lindex $res 1
]
lappend keys
{*}
$k
if
{
$cur
== 0
}
break
}
assert_equal 1000
[
llength $keys
]
}
foreach enc
{
intset hashtable
}
{
test
"SSCAN with encoding
$enc
"
{
# Create the 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