forked from mirror/ledisdb
add redis-compatible HSCAN/SSCAN/ZSCAN commands (#321)
This commit is contained in:
parent
57a07edd1a
commit
015411f5ce
|
@ -1,4 +1,4 @@
|
||||||
//This file was generated by .tools/generate_commands.py on Sat Mar 14 2015 08:58:32 +0800
|
//This file was generated by .tools/generate_commands.py on Sat Oct 28 2017 18:15:49 -0500
|
||||||
package main
|
package main
|
||||||
|
|
||||||
var helpCommands = [][]string{
|
var helpCommands = [][]string{
|
||||||
|
@ -43,6 +43,7 @@ var helpCommands = [][]string{
|
||||||
{"HMGET", "key field [field ...]", "Hash"},
|
{"HMGET", "key field [field ...]", "Hash"},
|
||||||
{"HMSET", "key field value [field value ...]", "Hash"},
|
{"HMSET", "key field value [field value ...]", "Hash"},
|
||||||
{"HPERSIST", "key", "Hash"},
|
{"HPERSIST", "key", "Hash"},
|
||||||
|
{"HSCAN", "key cursor [MATCH match] [COUNT count] [ASC|DESC]", "Hash"},
|
||||||
{"HSET", "key field value", "Hash"},
|
{"HSET", "key field value", "Hash"},
|
||||||
{"HTTL", "key", "Hash"},
|
{"HTTL", "key", "Hash"},
|
||||||
{"HVALS", "key", "Hash"},
|
{"HVALS", "key", "Hash"},
|
||||||
|
@ -96,6 +97,7 @@ var helpCommands = [][]string{
|
||||||
{"SMEMBERS", "key", "Set"},
|
{"SMEMBERS", "key", "Set"},
|
||||||
{"SPERSIST", "key", "Set"},
|
{"SPERSIST", "key", "Set"},
|
||||||
{"SREM", "key member [member ...]", "Set"},
|
{"SREM", "key member [member ...]", "Set"},
|
||||||
|
{"SSCAN", "key cursor [MATCH match] [COUNT count] [ASC|DESC]", "Set"},
|
||||||
{"STRLEN", "key", "KV"},
|
{"STRLEN", "key", "KV"},
|
||||||
{"STTL", "key", "Set"},
|
{"STTL", "key", "Set"},
|
||||||
{"SUNION", "key [key ...]", "Set"},
|
{"SUNION", "key [key ...]", "Set"},
|
||||||
|
@ -134,6 +136,7 @@ var helpCommands = [][]string{
|
||||||
{"ZREVRANGE", "key start stop [WITHSCORES]", "ZSet"},
|
{"ZREVRANGE", "key start stop [WITHSCORES]", "ZSet"},
|
||||||
{"ZREVRANGEBYSCORE", "key max min [WITHSCORES][LIMIT offset count]", "ZSet"},
|
{"ZREVRANGEBYSCORE", "key max min [WITHSCORES][LIMIT offset count]", "ZSet"},
|
||||||
{"ZREVRANK", "key member", "ZSet"},
|
{"ZREVRANK", "key member", "ZSet"},
|
||||||
|
{"ZSCAN", "key cursor [MATCH match] [COUNT count] [ASC|DESC]", "ZSet"},
|
||||||
{"ZSCORE", "key member", "ZSet"},
|
{"ZSCORE", "key member", "ZSet"},
|
||||||
{"ZTTL", "key", "ZSet"},
|
{"ZTTL", "key", "ZSet"},
|
||||||
{"ZUNIONSTORE", "destkey numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]", "ZSet"},
|
{"ZUNIONSTORE", "destkey numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]", "ZSet"},
|
||||||
|
|
|
@ -32,13 +32,10 @@ ZSet only support int64 score, not double in Redis.
|
||||||
|
|
||||||
## Scan
|
## Scan
|
||||||
|
|
||||||
LedisDB supplies `xscan`, `xhscan`, `xsscan`, `xzscan` to fetch data iteratively and reverse iteratively.
|
LedisDB supplies `xscan` instead of `scan` to fetch keys iteratively and reverse iteratively.
|
||||||
|
|
||||||
```
|
```
|
||||||
XSCAN type cursor [MATCH match] [COUNT count]
|
XSCAN type cursor [MATCH match] [COUNT count]
|
||||||
XHSCAN key cursor [MATCH match] [COUNT count]
|
|
||||||
XSSCAN key cursor [MATCH match] [COUNT count]
|
|
||||||
XZSCAN key cursor [MATCH match] [COUNT count]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## DUMP
|
## DUMP
|
||||||
|
|
|
@ -115,6 +115,11 @@
|
||||||
"group": "Hash",
|
"group": "Hash",
|
||||||
"readonly": false
|
"readonly": false
|
||||||
},
|
},
|
||||||
|
"HSCAN": {
|
||||||
|
"arguments": "key cursor [MATCH match] [COUNT count] [ASC|DESC]",
|
||||||
|
"group": "Hash",
|
||||||
|
"readonly": true
|
||||||
|
},
|
||||||
"HPERSIST": {
|
"HPERSIST": {
|
||||||
"arguments": "key",
|
"arguments": "key",
|
||||||
"group": "Hash",
|
"group": "Hash",
|
||||||
|
@ -310,6 +315,11 @@
|
||||||
"group": "Set",
|
"group": "Set",
|
||||||
"readonly": true
|
"readonly": true
|
||||||
},
|
},
|
||||||
|
"SSCAN": {
|
||||||
|
"arguments": "key cursor [MATCH match] [COUNT count] [ASC|DESC]",
|
||||||
|
"group": "Set",
|
||||||
|
"readonly": true
|
||||||
|
},
|
||||||
"SREM": {
|
"SREM": {
|
||||||
"arguments": "key member [member ...]",
|
"arguments": "key member [member ...]",
|
||||||
"group": "Set",
|
"group": "Set",
|
||||||
|
@ -450,6 +460,11 @@
|
||||||
"group": "ZSet",
|
"group": "ZSet",
|
||||||
"readonly": true
|
"readonly": true
|
||||||
},
|
},
|
||||||
|
"ZSCAN": {
|
||||||
|
"arguments": "key cursor [MATCH match] [COUNT count] [ASC|DESC]",
|
||||||
|
"group": "ZSet",
|
||||||
|
"readonly": true
|
||||||
|
},
|
||||||
"ZSCORE": {
|
"ZSCORE": {
|
||||||
"arguments": "key member",
|
"arguments": "key member",
|
||||||
"group": "ZSet",
|
"group": "ZSet",
|
||||||
|
|
|
@ -48,6 +48,7 @@ Most of the Ledisdb's commands are the same as Redis's, you can see the redis co
|
||||||
- [HLEN key](#hlen-key)
|
- [HLEN key](#hlen-key)
|
||||||
- [HMGET key field [field ...]](#hmget-key-field-field-)
|
- [HMGET key field [field ...]](#hmget-key-field-field-)
|
||||||
- [HMSET key field value [field value ...]](#hmset-key-field-value-field-value-)
|
- [HMSET key field value [field value ...]](#hmset-key-field-value-field-value-)
|
||||||
|
- [HSCAN key cursor [MATCH match] [COUNT count] [ASC|DESC]](#hscan-key-cursor-match-match-count-count-asc|desc)
|
||||||
- [HSET key field value](#hset-key-field-value)
|
- [HSET key field value](#hset-key-field-value)
|
||||||
- [HVALS key](#hvals-key)
|
- [HVALS key](#hvals-key)
|
||||||
- [HCLEAR key](#hclear-key)
|
- [HCLEAR key](#hclear-key)
|
||||||
|
@ -88,6 +89,7 @@ Most of the Ledisdb's commands are the same as Redis's, you can see the redis co
|
||||||
- [SISMEMBER key member](#sismember--key-member)
|
- [SISMEMBER key member](#sismember--key-member)
|
||||||
- [SMEMBERS key](#smembers-key)
|
- [SMEMBERS key](#smembers-key)
|
||||||
- [SREM key member [member ...]](#srem--key-member-member-)
|
- [SREM key member [member ...]](#srem--key-member-member-)
|
||||||
|
- [SSCAN key cursor [MATCH match] [COUNT count] [ASC|DESC]](#sscan-key-cursor-match-match-count-count-asc|desc)
|
||||||
- [SUNION key [key ...]](#sunion-key-key-)
|
- [SUNION key [key ...]](#sunion-key-key-)
|
||||||
- [SUNIONSTORE destination key [key]](#sunionstore-destination-key-key)
|
- [SUNIONSTORE destination key [key]](#sunionstore-destination-key-key)
|
||||||
- [SCLEAR key](#sclear-key)
|
- [SCLEAR key](#sclear-key)
|
||||||
|
@ -112,6 +114,7 @@ Most of the Ledisdb's commands are the same as Redis's, you can see the redis co
|
||||||
- [ZREVRANGE key start stop [WITHSCORES]](#zrevrange-key-start-stop-withscores)
|
- [ZREVRANGE key start stop [WITHSCORES]](#zrevrange-key-start-stop-withscores)
|
||||||
- [ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]](#zrevrangebyscore--key-max-min-withscores-limit-offset-count)
|
- [ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]](#zrevrangebyscore--key-max-min-withscores-limit-offset-count)
|
||||||
- [ZREVRANK key member](#zrevrank-key-member)
|
- [ZREVRANK key member](#zrevrank-key-member)
|
||||||
|
- [ZSCAN key cursor [MATCH match] [COUNT count] [ASC|DESC]](#zscan-key-cursor-match-match-count-count-asc|desc)
|
||||||
- [ZSCORE key member](#zscore-key-member)
|
- [ZSCORE key member](#zscore-key-member)
|
||||||
- [ZCLEAR key](#zclear-key)
|
- [ZCLEAR key](#zclear-key)
|
||||||
- [ZMCLEAR key [key ...]](#zmclear-key-key-)
|
- [ZMCLEAR key [key ...]](#zmclear-key-key-)
|
||||||
|
@ -730,6 +733,12 @@ ledis> HMGET myhash field1 field2
|
||||||
2) "world"
|
2) "world"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### HSCAN key cursor [MATCH match] [COUNT count] [ASC|DESC]
|
||||||
|
|
||||||
|
Same like XHSCAN, but made redis compatible.
|
||||||
|
Meaning that the initial cursor has to be `"0"`,
|
||||||
|
and the final cursor will be `"0"` as well.
|
||||||
|
|
||||||
### HSET key field value
|
### HSET key field value
|
||||||
|
|
||||||
Sets field in the hash stored at key to value. If key does not exists, a new hash key is created.
|
Sets field in the hash stored at key to value. If key does not exists, a new hash key is created.
|
||||||
|
@ -1489,6 +1498,12 @@ ledis> SMEMBERS myset
|
||||||
2) "two"
|
2) "two"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### SSCAN key cursor [MATCH match] [COUNT count] [ASC|DESC]
|
||||||
|
|
||||||
|
Same like XSSCAN, but made redis compatible.
|
||||||
|
Meaning that the initial cursor has to be `"0"`,
|
||||||
|
and the final cursor will be `"0"` as well.
|
||||||
|
|
||||||
### SUNION key [key ...]
|
### SUNION key [key ...]
|
||||||
|
|
||||||
Returns the members of the set resulting from the union of all the given sets.
|
Returns the members of the set resulting from the union of all the given sets.
|
||||||
|
@ -2089,6 +2104,12 @@ ledis> ZSCORE myzset 'one'
|
||||||
1
|
1
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### ZSCAN key cursor [MATCH match] [COUNT count] [ASC|DESC]
|
||||||
|
|
||||||
|
Same like XZSCAN, but made redis compatible.
|
||||||
|
Meaning that the initial cursor has to be `"0"`,
|
||||||
|
and the final cursor will be `"0"` as well.
|
||||||
|
|
||||||
### ZCLEAR key
|
### ZCLEAR key
|
||||||
Delete the specified key
|
Delete the specified key
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -10,7 +11,7 @@ import (
|
||||||
"github.com/siddontang/ledisdb/ledis"
|
"github.com/siddontang/ledisdb/ledis"
|
||||||
)
|
)
|
||||||
|
|
||||||
func parseScanArgs(args [][]byte) (cursor []byte, match string, count int, desc bool, err error) {
|
func parseXScanArgs(args [][]byte) (cursor []byte, match string, count int, desc bool, err error) {
|
||||||
cursor = args[0]
|
cursor = args[0]
|
||||||
|
|
||||||
args = args[1:]
|
args = args[1:]
|
||||||
|
@ -56,8 +57,21 @@ func parseScanArgs(args [][]byte) (cursor []byte, match string, count int, desc
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseScanArgs(args [][]byte) (cursor []byte, match string, count int, desc bool, err error) {
|
||||||
|
cursor, match, count, desc, err = parseXScanArgs(args)
|
||||||
|
if bytes.Compare(cursor, nilCursorRedis) == 0 {
|
||||||
|
cursor = nilCursorLedis
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type scanCommandGroup struct {
|
||||||
|
lastCursor []byte
|
||||||
|
parseArgs func(args [][]byte) (cursor []byte, match string, count int, desc bool, err error)
|
||||||
|
}
|
||||||
|
|
||||||
// XSCAN type cursor [MATCH match] [COUNT count] [ASC|DESC]
|
// XSCAN type cursor [MATCH match] [COUNT count] [ASC|DESC]
|
||||||
func xscanCommand(c *client) error {
|
func (scg scanCommandGroup) xscanCommand(c *client) error {
|
||||||
args := c.args
|
args := c.args
|
||||||
|
|
||||||
if len(args) < 2 {
|
if len(args) < 2 {
|
||||||
|
@ -80,7 +94,7 @@ func xscanCommand(c *client) error {
|
||||||
return fmt.Errorf("invalid key type %s", args[0])
|
return fmt.Errorf("invalid key type %s", args[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor, match, count, desc, err := parseScanArgs(args[1:])
|
cursor, match, count, desc, err := scg.parseArgs(args[1:])
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -100,7 +114,7 @@ func xscanCommand(c *client) error {
|
||||||
|
|
||||||
data := make([]interface{}, 2)
|
data := make([]interface{}, 2)
|
||||||
if len(ay) < count {
|
if len(ay) < count {
|
||||||
data[0] = []byte("")
|
data[0] = scg.lastCursor
|
||||||
} else {
|
} else {
|
||||||
data[0] = ay[len(ay)-1]
|
data[0] = ay[len(ay)-1]
|
||||||
}
|
}
|
||||||
|
@ -110,7 +124,7 @@ func xscanCommand(c *client) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// XHSCAN key cursor [MATCH match] [COUNT count] [ASC|DESC]
|
// XHSCAN key cursor [MATCH match] [COUNT count] [ASC|DESC]
|
||||||
func xhscanCommand(c *client) error {
|
func (scg scanCommandGroup) xhscanCommand(c *client) error {
|
||||||
args := c.args
|
args := c.args
|
||||||
|
|
||||||
if len(args) < 2 {
|
if len(args) < 2 {
|
||||||
|
@ -119,7 +133,7 @@ func xhscanCommand(c *client) error {
|
||||||
|
|
||||||
key := args[0]
|
key := args[0]
|
||||||
|
|
||||||
cursor, match, count, desc, err := parseScanArgs(args[1:])
|
cursor, match, count, desc, err := scg.parseArgs(args[1:])
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -139,7 +153,7 @@ func xhscanCommand(c *client) error {
|
||||||
|
|
||||||
data := make([]interface{}, 2)
|
data := make([]interface{}, 2)
|
||||||
if len(ay) < count {
|
if len(ay) < count {
|
||||||
data[0] = []byte("")
|
data[0] = scg.lastCursor
|
||||||
} else {
|
} else {
|
||||||
data[0] = ay[len(ay)-1].Field
|
data[0] = ay[len(ay)-1].Field
|
||||||
}
|
}
|
||||||
|
@ -157,7 +171,7 @@ func xhscanCommand(c *client) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// XSSCAN key cursor [MATCH match] [COUNT count] [ASC|DESC]
|
// XSSCAN key cursor [MATCH match] [COUNT count] [ASC|DESC]
|
||||||
func xsscanCommand(c *client) error {
|
func (scg scanCommandGroup) xsscanCommand(c *client) error {
|
||||||
args := c.args
|
args := c.args
|
||||||
|
|
||||||
if len(args) < 2 {
|
if len(args) < 2 {
|
||||||
|
@ -166,7 +180,7 @@ func xsscanCommand(c *client) error {
|
||||||
|
|
||||||
key := args[0]
|
key := args[0]
|
||||||
|
|
||||||
cursor, match, count, desc, err := parseScanArgs(args[1:])
|
cursor, match, count, desc, err := scg.parseArgs(args[1:])
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -186,7 +200,7 @@ func xsscanCommand(c *client) error {
|
||||||
|
|
||||||
data := make([]interface{}, 2)
|
data := make([]interface{}, 2)
|
||||||
if len(ay) < count {
|
if len(ay) < count {
|
||||||
data[0] = []byte("")
|
data[0] = scg.lastCursor
|
||||||
} else {
|
} else {
|
||||||
data[0] = ay[len(ay)-1]
|
data[0] = ay[len(ay)-1]
|
||||||
}
|
}
|
||||||
|
@ -198,7 +212,7 @@ func xsscanCommand(c *client) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// XZSCAN key cursor [MATCH match] [COUNT count] [ASC|DESC]
|
// XZSCAN key cursor [MATCH match] [COUNT count] [ASC|DESC]
|
||||||
func xzscanCommand(c *client) error {
|
func (scg scanCommandGroup) xzscanCommand(c *client) error {
|
||||||
args := c.args
|
args := c.args
|
||||||
|
|
||||||
if len(args) < 2 {
|
if len(args) < 2 {
|
||||||
|
@ -207,7 +221,7 @@ func xzscanCommand(c *client) error {
|
||||||
|
|
||||||
key := args[0]
|
key := args[0]
|
||||||
|
|
||||||
cursor, match, count, desc, err := parseScanArgs(args[1:])
|
cursor, match, count, desc, err := scg.parseArgs(args[1:])
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -227,7 +241,7 @@ func xzscanCommand(c *client) error {
|
||||||
|
|
||||||
data := make([]interface{}, 2)
|
data := make([]interface{}, 2)
|
||||||
if len(ay) < count {
|
if len(ay) < count {
|
||||||
data[0] = []byte("")
|
data[0] = scg.lastCursor
|
||||||
} else {
|
} else {
|
||||||
data[0] = ay[len(ay)-1].Member
|
data[0] = ay[len(ay)-1].Member
|
||||||
}
|
}
|
||||||
|
@ -244,9 +258,23 @@ func xzscanCommand(c *client) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
xScanGroup = scanCommandGroup{nilCursorLedis, parseXScanArgs}
|
||||||
|
scanGroup = scanCommandGroup{nilCursorRedis, parseScanArgs}
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
nilCursorLedis = []byte("")
|
||||||
|
nilCursorRedis = []byte("0")
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
register("xscan", xscanCommand)
|
register("hscan", scanGroup.xhscanCommand)
|
||||||
register("xhscan", xhscanCommand)
|
register("sscan", scanGroup.xsscanCommand)
|
||||||
register("xsscan", xsscanCommand)
|
register("zscan", scanGroup.xzscanCommand)
|
||||||
register("xzscan", xzscanCommand)
|
|
||||||
|
register("xscan", xScanGroup.xscanCommand)
|
||||||
|
register("xhscan", xScanGroup.xhscanCommand)
|
||||||
|
register("xsscan", xScanGroup.xsscanCommand)
|
||||||
|
register("xzscan", xScanGroup.xzscanCommand)
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,6 @@ func TestScan(t *testing.T) {
|
||||||
testListKeyScan(t, c)
|
testListKeyScan(t, c)
|
||||||
testZSetKeyScan(t, c)
|
testZSetKeyScan(t, c)
|
||||||
testSetKeyScan(t, c)
|
testSetKeyScan(t, c)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkScanValues(t *testing.T, ay interface{}, values ...interface{}) {
|
func checkScanValues(t *testing.T, ay interface{}, values ...interface{}) {
|
||||||
|
@ -47,7 +46,7 @@ func checkScanValues(t *testing.T, ay interface{}, values ...interface{}) {
|
||||||
|
|
||||||
for i, v := range a {
|
for i, v := range a {
|
||||||
if string(v) != fmt.Sprintf("%v", values[i]) {
|
if string(v) != fmt.Sprintf("%v", values[i]) {
|
||||||
t.Fatal(fmt.Sprintf("%d %s != %v", string(v), values[i]))
|
t.Fatal(fmt.Sprintf("%d %s != %v", i, string(v), values[i]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,7 +71,6 @@ func checkScan(t *testing.T, c *goredis.Client, tp string) {
|
||||||
} else {
|
} else {
|
||||||
checkScanValues(t, ay[1], 5, 6, 7, 8, 9)
|
checkScanValues(t, ay[1], 5, 6, 7, 8, 9)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func testKVScan(t *testing.T, c *goredis.Client) {
|
func testKVScan(t *testing.T, c *goredis.Client) {
|
||||||
|
@ -125,7 +123,7 @@ func testSetKeyScan(t *testing.T, c *goredis.Client) {
|
||||||
checkScan(t, c, "SET")
|
checkScan(t, c, "SET")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHashScan(t *testing.T) {
|
func TestXHashScan(t *testing.T) {
|
||||||
c := getTestConn()
|
c := getTestConn()
|
||||||
defer c.Close()
|
defer c.Close()
|
||||||
|
|
||||||
|
@ -141,7 +139,23 @@ func TestHashScan(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSetScan(t *testing.T) {
|
func TestHashScan(t *testing.T) {
|
||||||
|
c := getTestConn()
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
key := "scan_hash"
|
||||||
|
c.Do("HMSET", key, "a", 1, "b", 2)
|
||||||
|
|
||||||
|
if ay, err := goredis.Values(c.Do("HSCAN", key, "0")); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if len(ay) != 2 {
|
||||||
|
t.Fatal(len(ay))
|
||||||
|
} else {
|
||||||
|
checkScanValues(t, ay[1], "a", 1, "b", 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestXSetScan(t *testing.T) {
|
||||||
c := getTestConn()
|
c := getTestConn()
|
||||||
defer c.Close()
|
defer c.Close()
|
||||||
|
|
||||||
|
@ -155,10 +169,25 @@ func TestSetScan(t *testing.T) {
|
||||||
} else {
|
} else {
|
||||||
checkScanValues(t, ay[1], "a", "b")
|
checkScanValues(t, ay[1], "a", "b")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestZSetScan(t *testing.T) {
|
func TestSetScan(t *testing.T) {
|
||||||
|
c := getTestConn()
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
key := "scan_set"
|
||||||
|
c.Do("SADD", key, "a", "b")
|
||||||
|
|
||||||
|
if ay, err := goredis.Values(c.Do("SSCAN", key, "0")); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if len(ay) != 2 {
|
||||||
|
t.Fatal(len(ay))
|
||||||
|
} else {
|
||||||
|
checkScanValues(t, ay[1], "a", "b")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestXZSetScan(t *testing.T) {
|
||||||
c := getTestConn()
|
c := getTestConn()
|
||||||
defer c.Close()
|
defer c.Close()
|
||||||
|
|
||||||
|
@ -172,5 +201,21 @@ func TestZSetScan(t *testing.T) {
|
||||||
} else {
|
} else {
|
||||||
checkScanValues(t, ay[1], "a", 1, "b", 2)
|
checkScanValues(t, ay[1], "a", 1, "b", 2)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestZSetScan(t *testing.T) {
|
||||||
|
c := getTestConn()
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
key := "scan_zset"
|
||||||
|
c.Do("ZADD", key, 1, "a", 2, "b")
|
||||||
|
|
||||||
|
if ay, err := goredis.Values(c.Do("XZSCAN", key, "0")); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if len(ay) != 2 {
|
||||||
|
t.Fatal(len(ay))
|
||||||
|
} else {
|
||||||
|
checkScanValues(t, ay[1], "a", 1, "b", 2)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue