forked from mirror/ledisdb
add cmd_set commands and its tests
This commit is contained in:
parent
b1824af7d9
commit
00abaccbf2
|
@ -1,12 +1,12 @@
|
|||
# LedisDB
|
||||
|
||||
Ledisdb is a high performance NoSQL like Redis written by go. It supports some advanced data structure like kv, list, hash, zset, bitmap, and may be alternative for Redis.
|
||||
Ledisdb is a high performance NoSQL like Redis written by go. It supports some advanced data structure like kv, list, hash, zset, bitmap,set, and may be alternative for Redis.
|
||||
|
||||
LedisDB now supports multi databases as backend to store data, you can test and choose the proper one for you.
|
||||
|
||||
## Features
|
||||
|
||||
+ Rich advanced data structure: KV, List, Hash, ZSet, Bitmap.
|
||||
+ Rich advanced data structure: KV, List, Hash, ZSet, Bitmap, Set.
|
||||
+ Stores lots of data, over the memory limit.
|
||||
+ Various backend database to use: LevelDB, goleveldb, LMDB, RocksDB, BoltDB.
|
||||
+ Supports expiration and ttl.
|
||||
|
|
|
@ -129,9 +129,9 @@ func TestDBSet(t *testing.T) {
|
|||
|
||||
func TestSetOperation(t *testing.T) {
|
||||
db := getTestDB()
|
||||
// testUnion(db, t)
|
||||
testUnion(db, t)
|
||||
testInter(db, t)
|
||||
// testDiff(db, t)
|
||||
testDiff(db, t)
|
||||
|
||||
}
|
||||
|
||||
|
@ -232,6 +232,17 @@ func testInter(db *DB, t *testing.T) {
|
|||
t.Fatal(n)
|
||||
}
|
||||
|
||||
k1 := []byte("set_k1")
|
||||
k2 := []byte("set_k2")
|
||||
|
||||
db.SAdd(k1, m1, m3, m4)
|
||||
db.SAdd(k2, m2, m3)
|
||||
if n, err := db.SInterStore([]byte("set_xxx"), k1, k2); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if n != 1 {
|
||||
t.Fatal(n)
|
||||
}
|
||||
|
||||
v1, _ := db.SInter(key1, key2)
|
||||
v2, _ := db.SInter(key2, key1)
|
||||
if len(v1) != len(v2) {
|
||||
|
|
|
@ -0,0 +1,283 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"github.com/siddontang/ledisdb/ledis"
|
||||
)
|
||||
|
||||
func saddCommand(req *requestContext) error {
|
||||
args := req.args
|
||||
if len(args) < 2 {
|
||||
return ErrCmdParams
|
||||
}
|
||||
|
||||
if n, err := req.db.SAdd(args[0], args[1:]...); err != nil {
|
||||
return err
|
||||
} else {
|
||||
req.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func soptGeneric(req *requestContext, optType byte) error {
|
||||
args := req.args
|
||||
if len(args) < 1 {
|
||||
return ErrCmdParams
|
||||
}
|
||||
|
||||
var v [][]byte
|
||||
var err error
|
||||
|
||||
switch optType {
|
||||
case ledis.UnionType:
|
||||
v, err = req.db.SUnion(args...)
|
||||
case ledis.DiffType:
|
||||
v, err = req.db.SDiff(args...)
|
||||
case ledis.InterType:
|
||||
v, err = req.db.SInter(args...)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
req.resp.writeSliceArray(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func soptStoreGeneric(req *requestContext, optType byte) error {
|
||||
args := req.args
|
||||
if len(args) < 2 {
|
||||
return ErrCmdParams
|
||||
}
|
||||
|
||||
var n int64
|
||||
var err error
|
||||
|
||||
switch optType {
|
||||
case ledis.UnionType:
|
||||
n, err = req.db.SUnionStore(args[0], args[1:]...)
|
||||
case ledis.DiffType:
|
||||
n, err = req.db.SDiffStore(args[0], args[1:]...)
|
||||
case ledis.InterType:
|
||||
n, err = req.db.SInterStore(args[0], args[1:]...)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
req.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func scardCommand(req *requestContext) error {
|
||||
args := req.args
|
||||
if len(args) != 1 {
|
||||
return ErrCmdParams
|
||||
}
|
||||
|
||||
if n, err := req.db.SCard(args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
req.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func sdiffCommand(req *requestContext) error {
|
||||
return soptGeneric(req, ledis.DiffType)
|
||||
}
|
||||
|
||||
func sdiffstoreCommand(req *requestContext) error {
|
||||
return soptStoreGeneric(req, ledis.DiffType)
|
||||
}
|
||||
|
||||
func sinterCommand(req *requestContext) error {
|
||||
return soptGeneric(req, ledis.InterType)
|
||||
|
||||
}
|
||||
|
||||
func sinterstoreCommand(req *requestContext) error {
|
||||
return soptStoreGeneric(req, ledis.InterType)
|
||||
}
|
||||
|
||||
func sismemberCommand(req *requestContext) error {
|
||||
args := req.args
|
||||
if len(args) != 2 {
|
||||
return ErrCmdParams
|
||||
}
|
||||
|
||||
if n, err := req.db.SIsMember(args[0], args[1]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
req.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func smembersCommand(req *requestContext) error {
|
||||
args := req.args
|
||||
if len(args) != 1 {
|
||||
return ErrCmdParams
|
||||
}
|
||||
|
||||
if v, err := req.db.SMembers(args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
req.resp.writeSliceArray(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func sremCommand(req *requestContext) error {
|
||||
args := req.args
|
||||
if len(args) < 2 {
|
||||
return ErrCmdParams
|
||||
}
|
||||
|
||||
if n, err := req.db.SRem(args[0], args[1:]...); err != nil {
|
||||
return err
|
||||
} else {
|
||||
req.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func sunionCommand(req *requestContext) error {
|
||||
return soptGeneric(req, ledis.UnionType)
|
||||
}
|
||||
|
||||
func sunionstoreCommand(req *requestContext) error {
|
||||
return soptStoreGeneric(req, ledis.UnionType)
|
||||
}
|
||||
|
||||
func sclearCommand(req *requestContext) error {
|
||||
args := req.args
|
||||
if len(args) != 1 {
|
||||
return ErrCmdParams
|
||||
}
|
||||
|
||||
if n, err := req.db.SClear(args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
req.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func smclearCommand(req *requestContext) error {
|
||||
args := req.args
|
||||
if len(args) < 1 {
|
||||
return ErrCmdParams
|
||||
}
|
||||
|
||||
if n, err := req.db.SMclear(args...); err != nil {
|
||||
return err
|
||||
} else {
|
||||
req.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func sexpireCommand(req *requestContext) error {
|
||||
args := req.args
|
||||
if len(args) != 2 {
|
||||
return ErrCmdParams
|
||||
}
|
||||
|
||||
duration, err := ledis.StrInt64(args[1], nil)
|
||||
if err != nil {
|
||||
return ErrValue
|
||||
}
|
||||
|
||||
if v, err := req.db.SExpire(args[0], duration); err != nil {
|
||||
return err
|
||||
} else {
|
||||
req.resp.writeInteger(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func sexpireAtCommand(req *requestContext) error {
|
||||
args := req.args
|
||||
if len(args) != 2 {
|
||||
return ErrCmdParams
|
||||
}
|
||||
|
||||
when, err := ledis.StrInt64(args[1], nil)
|
||||
if err != nil {
|
||||
return ErrValue
|
||||
}
|
||||
|
||||
if v, err := req.db.SExpireAt(args[0], when); err != nil {
|
||||
return err
|
||||
} else {
|
||||
req.resp.writeInteger(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func sttlCommand(req *requestContext) error {
|
||||
args := req.args
|
||||
if len(args) != 1 {
|
||||
return ErrCmdParams
|
||||
}
|
||||
|
||||
if v, err := req.db.STTL(args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
req.resp.writeInteger(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func spersistCommand(req *requestContext) error {
|
||||
args := req.args
|
||||
if len(args) != 1 {
|
||||
return ErrCmdParams
|
||||
}
|
||||
|
||||
if n, err := req.db.SPersist(args[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
req.resp.writeInteger(n)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
register("sadd", saddCommand)
|
||||
register("scard", scardCommand)
|
||||
register("sdiff", sdiffCommand)
|
||||
register("sdiffstore", sdiffstoreCommand)
|
||||
register("sinter", sinterCommand)
|
||||
register("sinterstore", sinterstoreCommand)
|
||||
register("sismember", sismemberCommand)
|
||||
register("smembers", smembersCommand)
|
||||
register("srem", sremCommand)
|
||||
register("sunion", sunionCommand)
|
||||
register("sunionstore", sunionstoreCommand)
|
||||
register("sclear", sclearCommand)
|
||||
register("smclear", smclearCommand)
|
||||
register("sexpire", sexpireCommand)
|
||||
register("sexpireat", sexpireAtCommand)
|
||||
register("sttl", sttlCommand)
|
||||
register("spersist", spersistCommand)
|
||||
}
|
|
@ -0,0 +1,203 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"github.com/siddontang/ledisdb/client/go/ledis"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSet(t *testing.T) {
|
||||
c := getTestConn()
|
||||
defer c.Close()
|
||||
|
||||
key1 := "testdb_cmd_set_1"
|
||||
key2 := "testdb_cmd_set_2"
|
||||
|
||||
if n, err := ledis.Int(c.Do("sadd", key1, 0, 1)); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if n != 2 {
|
||||
t.Fatal(n)
|
||||
}
|
||||
|
||||
if n, err := ledis.Int(c.Do("sadd", key2, 0, 1, 2, 3)); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if n != 4 {
|
||||
t.Fatal(n)
|
||||
}
|
||||
|
||||
if n, err := ledis.Int(c.Do("scard", key1)); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if n != 2 {
|
||||
t.Fatal(n)
|
||||
}
|
||||
|
||||
if n, err := ledis.MultiBulk(c.Do("sdiff", key2, key1)); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if len(n) != 2 {
|
||||
t.Fatal(n)
|
||||
}
|
||||
|
||||
if n, err := ledis.Int(c.Do("sdiffstore", []byte("cmd_set_em1"), key2, key1)); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if n != 2 {
|
||||
t.Fatal(n)
|
||||
}
|
||||
|
||||
if n, err := ledis.MultiBulk(c.Do("sunion", key1, key2)); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if len(n) != 4 {
|
||||
t.Fatal(n)
|
||||
}
|
||||
|
||||
if n, err := ledis.Int(c.Do("sunionstore", []byte("cmd_set_em2"), key1, key2)); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if n != 4 {
|
||||
t.Fatal(n)
|
||||
}
|
||||
|
||||
if n, err := ledis.MultiBulk(c.Do("sinter", key1, key2)); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if len(n) != 2 {
|
||||
t.Fatal(n)
|
||||
}
|
||||
|
||||
if n, err := ledis.Int(c.Do("sinterstore", []byte("cmd_set_em3"), key1, key2)); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if n != 2 {
|
||||
t.Fatal(n)
|
||||
}
|
||||
|
||||
if n, err := ledis.Int(c.Do("srem", key1, 0, 1)); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if n != 2 {
|
||||
t.Fatal(n)
|
||||
}
|
||||
|
||||
if n, err := ledis.Int(c.Do("sismember", key2, 0)); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if n != 1 {
|
||||
t.Fatal(n)
|
||||
}
|
||||
|
||||
if n, err := ledis.MultiBulk(c.Do("smembers", key2)); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if len(n) != 4 {
|
||||
t.Fatal(n)
|
||||
}
|
||||
|
||||
if n, err := ledis.Int(c.Do("sclear", key2)); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if n != 4 {
|
||||
t.Fatal(n)
|
||||
}
|
||||
|
||||
c.Do("sadd", key1, 0)
|
||||
c.Do("sadd", key2, 1)
|
||||
if n, err := ledis.Int(c.Do("smclear", key1, key2)); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if n != 2 {
|
||||
t.Fatal(n)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestSetErrorParams(t *testing.T) {
|
||||
c := getTestConn()
|
||||
defer c.Close()
|
||||
|
||||
if _, err := c.Do("sadd", "test_sadd"); err == nil {
|
||||
t.Fatal("invalid err of %v", err)
|
||||
}
|
||||
|
||||
if _, err := c.Do("scard"); err == nil {
|
||||
t.Fatal("invalid err of %v", err)
|
||||
}
|
||||
|
||||
if _, err := c.Do("scard", "k1", "k2"); err == nil {
|
||||
t.Fatal("invalid err of %v", err)
|
||||
}
|
||||
|
||||
if _, err := c.Do("sdiff"); err == nil {
|
||||
t.Fatal("invalid err of %v", err)
|
||||
}
|
||||
|
||||
if _, err := c.Do("sdiffstore", "dstkey"); err == nil {
|
||||
t.Fatal("invalid err of %v", err)
|
||||
}
|
||||
|
||||
if _, err := c.Do("sinter"); err == nil {
|
||||
t.Fatal("invalid err of %v", err)
|
||||
}
|
||||
|
||||
if _, err := c.Do("sinterstore", "dstkey"); err == nil {
|
||||
t.Fatal("invalid err of %v", err)
|
||||
}
|
||||
|
||||
if _, err := c.Do("sunion"); err == nil {
|
||||
t.Fatal("invalid err of %v", err)
|
||||
}
|
||||
|
||||
if _, err := c.Do("sunionstore", "dstkey"); err == nil {
|
||||
t.Fatal("invalid err of %v", err)
|
||||
}
|
||||
|
||||
if _, err := c.Do("sismember", "k1"); err == nil {
|
||||
t.Fatal("invalid err of %v", err)
|
||||
}
|
||||
|
||||
if _, err := c.Do("sismember", "k1", "m1", "m2"); err == nil {
|
||||
t.Fatal("invalid err of %v", err)
|
||||
}
|
||||
|
||||
if _, err := c.Do("smembers"); err == nil {
|
||||
t.Fatal("invalid err of %v", err)
|
||||
}
|
||||
|
||||
if _, err := c.Do("smembers", "k1", "k2"); err == nil {
|
||||
t.Fatal("invalid err of %v", err)
|
||||
}
|
||||
|
||||
if _, err := c.Do("srem"); err == nil {
|
||||
t.Fatal("invalid err of %v", err)
|
||||
}
|
||||
|
||||
if _, err := c.Do("srem", "key"); err == nil {
|
||||
t.Fatal("invalid err of %v", err)
|
||||
}
|
||||
|
||||
if _, err := c.Do("sclear"); err == nil {
|
||||
t.Fatal("invalid err of %v", err)
|
||||
}
|
||||
|
||||
if _, err := c.Do("sclear", "k1", "k2"); err == nil {
|
||||
t.Fatal("invalid err of %v", err)
|
||||
}
|
||||
|
||||
if _, err := c.Do("smclear"); err == nil {
|
||||
t.Fatal("invalid err of %v", err)
|
||||
}
|
||||
|
||||
if _, err := c.Do("sexpire", "set_expire"); err == nil {
|
||||
t.Fatal("invalid err of %v", err)
|
||||
}
|
||||
|
||||
if _, err := c.Do("sexpire", "set_expire", "aaa"); err == nil {
|
||||
t.Fatal("invalid err of %v", err)
|
||||
}
|
||||
|
||||
if _, err := c.Do("sexpireat", "set_expireat"); err == nil {
|
||||
t.Fatal("invalid err of %v", err)
|
||||
}
|
||||
|
||||
if _, err := c.Do("sexpireat", "set_expireat", "aaa"); err == nil {
|
||||
t.Fatal("invalid err of %v", err)
|
||||
}
|
||||
|
||||
if _, err := c.Do("sttl"); err == nil {
|
||||
t.Fatal("invalid err of %v", err)
|
||||
}
|
||||
|
||||
if _, err := c.Do("spersist"); err == nil {
|
||||
t.Fatal("invalid err of %v", err)
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue