diff --git a/ledis/t_hash.go b/ledis/t_hash.go index 98ee24f..6235acc 100644 --- a/ledis/t_hash.go +++ b/ledis/t_hash.go @@ -509,3 +509,15 @@ func (db *DB) HPersist(key []byte) (int64, error) { err = t.Commit() return n, err } + +func (db *DB) XHExists(key []byte) (int64, error) { + if err := checkKeySize(key); err != nil { + return 0, err + } + sk := db.hEncodeSizeKey(key) + v, err := db.bucket.Get(sk) + if v != nil && err == nil { + return 1, nil + } + return 0, err +} diff --git a/ledis/t_hash_test.go b/ledis/t_hash_test.go index 294746d..7fac691 100644 --- a/ledis/t_hash_test.go +++ b/ledis/t_hash_test.go @@ -79,6 +79,29 @@ func TestHashPersist(t *testing.T) { t.Fatal(n) } } +func TestXHashExists(t *testing.T) { + db := getTestDB() + key := []byte("xhexists_test") + v, err := db.XHExists(key) + if err != nil { + t.Fatal(err.Error()) + } + if v != 0 { + t.Fatal("invalid value ", v) + } + + if _, err := db.HSet(key, []byte("hello"), []byte("world")); err != nil { + t.Fatal(err.Error()) + } + + v, err = db.XHExists(key) + if err != nil { + t.Fatal(err.Error()) + } + if v != 1 { + t.Fatal("invalid value ", v) + } +} func TestHFlush(t *testing.T) { db := getTestDB() diff --git a/ledis/t_list.go b/ledis/t_list.go index 7f66bed..93c6ba2 100644 --- a/ledis/t_list.go +++ b/ledis/t_list.go @@ -506,6 +506,18 @@ func (db *DB) BRPop(keys [][]byte, timeout time.Duration) ([]interface{}, error) return db.lblockPop(keys, listTailSeq, timeout) } +func (db *DB) XLExists(key []byte) (int64, error) { + if err := checkKeySize(key); err != nil { + return 0, err + } + sk := db.lEncodeMetaKey(key) + v, err := db.bucket.Get(sk) + if v != nil && err == nil { + return 1, nil + } + return 0, err +} + func (db *DB) lblockPop(keys [][]byte, whereSeq int32, timeout time.Duration) ([]interface{}, error) { ch := make(chan []byte) diff --git a/ledis/t_list_test.go b/ledis/t_list_test.go index 4fd2633..b80af1d 100644 --- a/ledis/t_list_test.go +++ b/ledis/t_list_test.go @@ -163,3 +163,19 @@ func TestLFlush(t *testing.T) { t.Fatal("invalid value length ", len(v)) } } + +func TestXLExists(t *testing.T) { + db := getTestDB() + key := []byte("xlexists_test") + if n, err := db.XLExists(key); err != nil { + t.Fatal(err.Error()) + } else if n != 0 { + t.Fatal("invalid value ", n) + } + db.LPush(key, []byte("hello"), []byte("world")) + if n, err := db.XLExists(key); err != nil { + t.Fatal(err.Error()) + } else if n != 1 { + t.Fatal("invalid value ", n) + } +} diff --git a/ledis/t_set.go b/ledis/t_set.go index b81496d..126b407 100644 --- a/ledis/t_set.go +++ b/ledis/t_set.go @@ -286,6 +286,18 @@ func (db *DB) SDiffStore(dstKey []byte, keys ...[]byte) (int64, error) { return n, err } +func (db *DB) XSExists(key []byte) (int64, error) { + if err := checkKeySize(key); err != nil { + return 0, err + } + sk := db.sEncodeSizeKey(key) + v, err := db.bucket.Get(sk) + if v != nil && err == nil { + return 1, nil + } + return 0, err +} + func (db *DB) sInterGeneric(keys ...[]byte) ([][]byte, error) { destMap := make(map[string]bool) diff --git a/ledis/t_set_test.go b/ledis/t_set_test.go index cee8023..eb24bdb 100644 --- a/ledis/t_set_test.go +++ b/ledis/t_set_test.go @@ -371,3 +371,22 @@ func TestSFlush(t *testing.T) { } } + +func TestXSExists(t *testing.T) { + db := getTestDB() + key := []byte("xsexists_test") + if n, err := db.XSExists(key); err != nil { + t.Fatal(err.Error()) + } else if n != 0 { + t.Fatal("invalid value ", n) + } + + db.SAdd(key, []byte("hello"), []byte("world")) + + if n, err := db.XSExists(key); err != nil { + t.Fatal(err.Error()) + } else if n != 1 { + t.Fatal("invalid value ", n) + } + +} diff --git a/ledis/t_zset.go b/ledis/t_zset.go index 4719171..36f886b 100644 --- a/ledis/t_zset.go +++ b/ledis/t_zset.go @@ -1023,3 +1023,15 @@ func (db *DB) ZLexCount(key []byte, min []byte, max []byte, rangeType uint8) (in return n, nil } + +func (db *DB) XZExists(key []byte) (int64, error) { + if err := checkKeySize(key); err != nil { + return 0, err + } + sk := db.zEncodeSizeKey(key) + v, err := db.bucket.Get(sk) + if v != nil && err == nil { + return 1, nil + } + return 0, err +} diff --git a/ledis/t_zset_test.go b/ledis/t_zset_test.go index 98f0a81..cdb35bc 100644 --- a/ledis/t_zset_test.go +++ b/ledis/t_zset_test.go @@ -465,3 +465,21 @@ func TestZLex(t *testing.T) { } } + +func TestXZExists(t *testing.T) { + db := getTestDB() + key := []byte("xzexists_test") + if n, err := db.XZExists(key); err != nil { + t.Fatal(err.Error()) + } else if n != 0 { + t.Fatal("invalid value ", n) + } + + db.ZAdd(key, ScorePair{0, []byte("a")}, ScorePair{0, []byte("b")}) + + if n, err := db.XZExists(key); err != nil { + t.Fatal(err.Error()) + } else if n != 1 { + t.Fatal("invalid value ", n) + } +} diff --git a/server/cmd_hash.go b/server/cmd_hash.go index f232821..8c277ee 100644 --- a/server/cmd_hash.go +++ b/server/cmd_hash.go @@ -300,6 +300,19 @@ func hxrevscanCommand(c *client) error { return xscanGeneric(c, c.db.HRevScan) } +func xhexistsCommand(c *client) error { + args := c.args + if len(args) != 1 { + return ErrCmdParams + } + if n, err := c.db.XHExists(args[0]); err != nil { + return err + } else { + c.resp.writeInteger(n) + } + return nil +} + func init() { register("hdel", hdelCommand) register("hexists", hexistsCommand) @@ -325,4 +338,5 @@ func init() { register("hxrevscan", hxrevscanCommand) register("xhscan", hxscanCommand) register("xhrevscan", hxrevscanCommand) + register("xhexists", xhexistsCommand) } diff --git a/server/cmd_hash_test.go b/server/cmd_hash_test.go index 04388cc..7ff5f40 100644 --- a/server/cmd_hash_test.go +++ b/server/cmd_hash_test.go @@ -12,11 +12,22 @@ func TestHash(t *testing.T) { defer c.Close() key := []byte("a") + if n, err := ledis.Int(c.Do("xhexists", key)); err != nil { + t.Fatal(err) + } else if n != 0 { + t.Fatal(n) + } + if n, err := ledis.Int(c.Do("hset", key, 1, 0)); err != nil { t.Fatal(err) } else if n != 1 { t.Fatal(n) } + if n, err := ledis.Int(c.Do("xhexists", key)); err != nil { + t.Fatal(err) + } else if n != 1 { + t.Fatal(n) + } if n, err := ledis.Int(c.Do("hexists", key, 1)); err != nil { t.Fatal(err) @@ -296,5 +307,4 @@ func TestHashErrorParams(t *testing.T) { if _, err := c.Do("hpersist"); err == nil { t.Fatal("invalid err of %v", err) } - } diff --git a/server/cmd_list.go b/server/cmd_list.go index 63e6f59..7000a74 100644 --- a/server/cmd_list.go +++ b/server/cmd_list.go @@ -285,6 +285,18 @@ func lParseBPopArgs(c *client) (keys [][]byte, timeout time.Duration, err error) keys = args[0 : len(args)-1] return } +func xlexistsCommand(c *client) error { + args := c.args + if len(args) != 1 { + return ErrCmdParams + } + if n, err := c.db.XLExists(args[0]); err != nil { + return err + } else { + c.resp.writeInteger(n) + } + return nil +} func init() { register("blpop", blpopCommand) @@ -309,4 +321,5 @@ func init() { register("lxrevscan", lxrevscanCommand) register("xlscan", lxscanCommand) register("xlrevscan", lxrevscanCommand) + register("xlexists", xlexistsCommand) } diff --git a/server/cmd_list_test.go b/server/cmd_list_test.go index 5a7cf51..526862b 100644 --- a/server/cmd_list_test.go +++ b/server/cmd_list_test.go @@ -58,6 +58,11 @@ func TestList(t *testing.T) { defer c.Close() key := []byte("a") + if n, err := ledis.Int(c.Do("xlexists", key)); err != nil { + t.Fatal(err) + } else if n != 0 { + t.Fatal(n) + } if n, err := ledis.Int(c.Do("lpush", key, 1)); err != nil { t.Fatal(err) @@ -65,6 +70,12 @@ func TestList(t *testing.T) { t.Fatal(n) } + if n, err := ledis.Int(c.Do("xlexists", key)); err != nil { + t.Fatal(err) + } else if n != 1 { + t.Fatal(1) + } + if n, err := ledis.Int(c.Do("rpush", key, 2)); err != nil { t.Fatal(err) } else if n != 2 { diff --git a/server/cmd_set.go b/server/cmd_set.go index ea5a75c..ae22bc5 100644 --- a/server/cmd_set.go +++ b/server/cmd_set.go @@ -270,6 +270,19 @@ func sxrevscanCommand(c *client) error { return xscanGeneric(c, c.db.SRevScan) } +func xsexistsCommand(c *client) error { + args := c.args + if len(args) != 1 { + return ErrCmdParams + } + if n, err := c.db.XSExists(args[0]); err != nil { + return err + } else { + c.resp.writeInteger(n) + } + return nil +} + func init() { register("sadd", saddCommand) register("scard", scardCommand) @@ -292,4 +305,6 @@ func init() { register("sxrevscan", sxrevscanCommand) register("xsscan", sxscanCommand) register("xsrevscan", sxrevscanCommand) + register("xsexists", xsexistsCommand) + } diff --git a/server/cmd_set_test.go b/server/cmd_set_test.go index 0e76520..03c0702 100644 --- a/server/cmd_set_test.go +++ b/server/cmd_set_test.go @@ -12,12 +12,24 @@ func TestSet(t *testing.T) { key1 := "testdb_cmd_set_1" key2 := "testdb_cmd_set_2" + if n, err := ledis.Int(c.Do("xsexists", key1)); err != nil { + t.Fatal(err) + } else if n != 0 { + t.Fatal(n) + } + 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("xsexists", key1)); err != nil { + t.Fatal(err) + } else if n != 1 { + 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 { diff --git a/server/cmd_zset.go b/server/cmd_zset.go index a58dbbb..ddeefbd 100644 --- a/server/cmd_zset.go +++ b/server/cmd_zset.go @@ -771,6 +771,19 @@ func zlexcountCommand(c *client) error { return nil } +func xzexistsCommand(c *client) error { + args := c.args + if len(args) != 1 { + return ErrCmdParams + } + if n, err := c.db.XZExists(args[0]); err != nil { + return err + } else { + c.resp.writeInteger(n) + } + return nil +} + func init() { register("zadd", zaddCommand) register("zcard", zcardCommand) @@ -806,4 +819,5 @@ func init() { register("zxrevscan", zxrevscanCommand) register("xzscan", zxscanCommand) register("xzrevscan", zxrevscanCommand) + register("xzexists", xzexistsCommand) } diff --git a/server/cmd_zset_test.go b/server/cmd_zset_test.go index 59411c5..7760e7b 100644 --- a/server/cmd_zset_test.go +++ b/server/cmd_zset_test.go @@ -13,12 +13,25 @@ func TestZSet(t *testing.T) { defer c.Close() key := []byte("myzset") + + if n, err := ledis.Int(c.Do("xzexists", key)); err != nil { + t.Fatal(err) + } else if n != 0 { + t.Fatal(n) + } + if n, err := ledis.Int(c.Do("zadd", key, 3, "a", 4, "b")); err != nil { t.Fatal(err) } else if n != 2 { t.Fatal(n) } + if n, err := ledis.Int(c.Do("xzexists", key)); err != nil { + t.Fatal(err) + } else if n != 1 { + t.Fatal(n) + } + if n, err := ledis.Int(c.Do("zcard", key)); err != nil { t.Fatal(n) } else if n != 2 {