From 892311dcd0ce23126307b5471a895a098dc0f985 Mon Sep 17 00:00:00 2001 From: qishenonly <1050026498@qq.com> Date: Wed, 5 Jul 2023 18:23:36 +0800 Subject: [PATCH] feat: new method--HIncrBy(#136) --- structure/hash.go | 62 ++++++++++++++++++++++++++++++++++++++++++ structure/hash_test.go | 33 ++++++++++++++++++++++ 2 files changed, 95 insertions(+) diff --git a/structure/hash.go b/structure/hash.go index 94a54e99..698b3895 100644 --- a/structure/hash.go +++ b/structure/hash.go @@ -5,6 +5,7 @@ import ( "github.com/ByteStorage/FlyDB/config" "github.com/ByteStorage/FlyDB/engine" _const "github.com/ByteStorage/FlyDB/lib/const" + "strconv" "time" ) @@ -432,3 +433,64 @@ func (hs *HashStructure) HUpdate(key, field, value []byte) (bool, error) { return true, nil } + +// HIncrBy increments the integer value of a hash field by the given number. +func (hs *HashStructure) HIncrBy(key, field []byte, increment int64) (int64, error) { + // Check the parameters + if len(key) == 0 || len(field) == 0 { + return 0, _const.ErrKeyIsEmpty + } + + // Find the hash metadata by the given key + hashMeta, err := hs.findHashMeta(key, Hash) + if err != nil { + return 0, err + } + + // If the counter is 0, return 0 + if hashMeta.counter == 0 { + return 0, nil + } + + // Create a new HashField + hf := &HashField{ + field: field, + key: key, + version: hashMeta.version, + } + + // Encode the HashField + hfBuf := hf.encodeHashField() + + // Get the field from the database + value, err := hs.db.Get(hfBuf) + if err != nil && err == _const.ErrKeyNotFound { + return 0, nil + } + + // Convert the value to int64 + val, err := strconv.ParseInt(string(value), 10, 64) + if err != nil { + return 0, err + } + + // Add the increment to the value + val += increment + + // Convert the value to string + value = []byte(strconv.FormatInt(val, 10)) + + // new a write batch + batch := hs.db.NewWriteBatch(config.DefaultWriteBatchOptions) + + // Put the field to the database + _ = batch.Put(hfBuf, value) + + // Commit the write batch + err = batch.Commit() + if err != nil { + return 0, err + } + + return val, nil +} diff --git a/structure/hash_test.go b/structure/hash_test.go index 2bc41dab..78051c94 100644 --- a/structure/hash_test.go +++ b/structure/hash_test.go @@ -142,3 +142,36 @@ func TestHashStructure_HUpdate(t *testing.T) { assert.Nil(t, err) assert.Equal(t, l, 3) } + +func TestHashStructure_HIncrBy(t *testing.T) { + hash := initHashDB() + + ok1, err := hash.HSet(randkv.GetTestKey(1), []byte("field1"), []byte("10")) + assert.Nil(t, err) + assert.True(t, ok1) + + ok2, err := hash.HSet(randkv.GetTestKey(1), []byte("field2"), []byte("10")) + assert.Nil(t, err) + assert.True(t, ok2) + + ok3, err := hash.HSet(randkv.GetTestKey(1), []byte("field3"), []byte("10")) + assert.Nil(t, err) + assert.True(t, ok3) + + v1, err := hash.HIncrBy(randkv.GetTestKey(1), []byte("field1"), 1) + assert.Nil(t, err) + assert.Equal(t, v1, int64(11)) + + v2, err := hash.HIncrBy(randkv.GetTestKey(1), []byte("field2"), -1) + assert.Nil(t, err) + assert.Equal(t, v2, int64(9)) + + v3, err := hash.HIncrBy(randkv.GetTestKey(1), []byte("field3"), 0) + assert.Nil(t, err) + assert.Equal(t, v3, int64(10)) + + v4, err := hash.HIncrBy(randkv.GetTestKey(1), []byte("field4"), 1) + assert.Nil(t, err) + assert.Equal(t, v4, int64(0)) + +}