Skip to content

add match regx for keys #281

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Aug 13, 2023
35 changes: 28 additions & 7 deletions structure/hash.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/ByteStorage/FlyDB/config"
"github.com/ByteStorage/FlyDB/engine"
_const "github.com/ByteStorage/FlyDB/lib/const"
"regexp"
"strconv"
"time"
)
Expand Down Expand Up @@ -1158,21 +1159,41 @@ func (hs *HashStructure) HTypes(k string, f interface{}) (string, error) {
//
// []string: A list of field names in the hash.
// error: An error if occurred during the operation, or nil on success.
func (hs *HashStructure) Keys() []string {
func (hs *HashStructure) Keys(regx string) ([]string, error) {
toRegexp := convertToRegexp(regx)
compile, err := regexp.Compile(toRegexp)
if err != nil {
return nil, err
}
// Get all the keys from the database
byte_keys := hs.db.GetListKeys()
byteKeys := hs.db.GetListKeys()

// Create a new slice of strings
keys := make([]string, 0)

for _, key := range byte_keys {
// Check if the key has the identifier suffix
if !keysIdentify(key) {
keys = append(keys, string(key))
for _, key := range byteKeys {
if compile.MatchString(string(key)) {
// Check if the key has the identifier suffix
if !keysIdentify(key) {
fields := hs.GetFields(string(key))
ok := true
for _, field := range fields {
_, err := hs.HGet(string(key), field)
if err != nil {
ok = false
break
}
}
if !ok {
continue
}
keys = append(keys, string(key))
}
}

}

return keys
return keys, nil
}

// GetFields returns a list of all field names in the hash stored at the specified key.
Expand Down
16 changes: 16 additions & 0 deletions structure/hash_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,22 @@ func TestHashStructure_GetFields(t *testing.T) {
fields2 := hash.GetFields("qqqqqq")
assert.Equal(t, fields2, []string{"!qqq!1", "!qqq!2", "!qqq!3"})

keys, err := hash.Keys("*")
assert.Nil(t, err)
assert.Equal(t, keys, []string{"qqqqqq", "qweqwe"})

keys, err = hash.Keys("q*")
assert.Nil(t, err)
assert.Equal(t, keys, []string{"qqqqqq", "qweqwe"})

keys, err = hash.Keys("qq*")
assert.Nil(t, err)
assert.Equal(t, keys, []string{"qqqqqq"})

keys, err = hash.Keys("q?*")
assert.Nil(t, err)
assert.Equal(t, keys, []string{"qqqqqq", "qweqwe"})

}

func TestHashStructure_HGetAllFieldAndValue(t *testing.T) {
Expand Down
25 changes: 21 additions & 4 deletions structure/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"errors"
"reflect"
"regexp"
"time"

"encoding/gob"
Expand Down Expand Up @@ -432,11 +433,27 @@ func (l *ListStructure) LIndex(key string, index int) (interface{}, error) {
}

// Keys returns all the keys of the list structure.
func (l *ListStructure) Keys() ([]string, error) {
func (l *ListStructure) Keys(regx string) ([]string, error) {
toRegexp := convertToRegexp(regx)
compile, err := regexp.Compile(toRegexp)
if err != nil {
return nil, err
}
var keys []string
byte_keys := l.db.GetListKeys()
for _, key := range byte_keys {
keys = append(keys, string(key))
byteKeys := l.db.GetListKeys()
for _, key := range byteKeys {
// match prefix and key
if compile.MatchString(string(key)) {
// check if deleted
db, _, err := l.getListFromDB(string(key), true)
if err != nil {
continue
}
if db.Length == 0 {
continue
}
keys = append(keys, string(key))
}
}
return keys, nil
}
Expand Down
24 changes: 20 additions & 4 deletions structure/list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -363,16 +363,32 @@ func TestListStructure_Keys(t *testing.T) {
list, _ := initList()
defer list.db.Clean()

listErr = list.LPush("1", randkv.RandomValue(100), 0)
listErr = list.LPush("111", randkv.RandomValue(100), 0)
assert.Nil(t, listErr)

listErr = list.LPush("2", randkv.RandomValue(100), 0)
listErr = list.LPush("122", randkv.RandomValue(100), 0)
assert.Nil(t, listErr)

listErr = list.LPush("q", randkv.RandomValue(100), 0)
listErr = list.LPush("123", randkv.RandomValue(100), 0)
assert.Nil(t, listErr)

keys, err := list.Keys()
keys, err := list.Keys("*")
assert.Nil(t, err)
assert.Equal(t, len(keys), 3)

keys, err = list.Keys("1*")
assert.Nil(t, err)
assert.Equal(t, len(keys), 3)

keys, err = list.Keys("12*")
assert.Nil(t, err)
assert.Equal(t, len(keys), 2)

keys, err = list.Keys("123")
assert.Nil(t, err)
assert.Equal(t, len(keys), 1)

keys, err = list.Keys("1?*")
assert.Nil(t, err)
assert.Equal(t, len(keys), 3)
}
20 changes: 16 additions & 4 deletions structure/set.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/ByteStorage/FlyDB/engine"
_const "github.com/ByteStorage/FlyDB/lib/const"
"github.com/ByteStorage/FlyDB/lib/encoding"
"regexp"
)

type SetStructure struct {
Expand Down Expand Up @@ -224,11 +225,22 @@ func (s *SetStructure) SDiff(keys ...string) ([]string, error) {
}

// Keys returns all the keys of the set structure
func (s *SetStructure) Keys() ([]string, error) {
func (s *SetStructure) Keys(regx string) ([]string, error) {
toRegexp := convertToRegexp(regx)
compile, err := regexp.Compile(toRegexp)
if err != nil {
return nil, err
}
var keys []string
byte_keys := s.db.GetListKeys()
for _, key := range byte_keys {
keys = append(keys, string(key))
byteKeys := s.db.GetListKeys()
for _, key := range byteKeys {
if compile.MatchString(string(key)) {
// check if deleted
if !s.exists(string(key)) {
continue
}
keys = append(keys, string(key))
}
}
return keys, nil
}
Expand Down
22 changes: 19 additions & 3 deletions structure/set_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1062,10 +1062,10 @@ func TestSetStructure_Keys(t *testing.T) {
set, _ := initTestSetDb()
defer set.db.Clean()

err = set.SAdd("testKey1", "non1")
err = set.SAdd("testKey11", "non1")
assert.Nil(t, err)

err = set.SAdd("testKey2", "non1")
err = set.SAdd("testKey12", "non1")
assert.Nil(t, err)

err = set.SAdd("testKey3", "non1")
Expand All @@ -1074,8 +1074,24 @@ func TestSetStructure_Keys(t *testing.T) {
err = set.SAdd("testKey4", "non1")
assert.Nil(t, err)

keys, err := set.Keys()
keys, err := set.Keys("*")
assert.Nil(t, err)
assert.Equal(t, 4, len(keys))

keys, err = set.Keys("testKey*")
assert.Nil(t, err)
assert.Equal(t, 4, len(keys))

keys, err = set.Keys("testKey1*")
assert.Nil(t, err)
assert.Equal(t, 2, len(keys))

keys, err = set.Keys("testKey?*")
assert.Nil(t, err)
assert.Equal(t, 4, len(keys))

keys, err = set.Keys("testKey111?*")
assert.Nil(t, err)
assert.Equal(t, 0, len(keys))

}
21 changes: 13 additions & 8 deletions structure/string.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/ByteStorage/FlyDB/config"
"github.com/ByteStorage/FlyDB/engine"
_const "github.com/ByteStorage/FlyDB/lib/const"
"regexp"
"strconv"
"time"
)
Expand Down Expand Up @@ -311,20 +312,24 @@ func (s *StringStructure) DecrBy(key string, amount int, ttl int64) error {
}

// Keys returns all keys matching pattern
func (s *StringStructure) Keys() ([]string, error) {
func (s *StringStructure) Keys(regx string) ([]string, error) {
toRegexp := convertToRegexp(regx)
compile, err := regexp.Compile(toRegexp)
if err != nil {
return nil, err
}
var keys []string
byteKeys := s.db.GetListKeys()
for _, key := range byteKeys {
// check if key is expired
_, err := s.Get(string(key))
if err != nil {
if errors.Is(err, _const.ErrKeyIsExpired) {
if compile.MatchString(string(key)) {
// check if key is expired
_, err := s.Get(string(key))
if err != nil {
continue
} else {
return nil, err
}
keys = append(keys, string(key))
}
keys = append(keys, string(key))

}
return keys, nil
}
Expand Down
20 changes: 16 additions & 4 deletions structure/string_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -425,13 +425,13 @@ func TestStringStructure_Keys(t *testing.T) {
str, _ := initdb()
defer str.db.Clean()

err = str.Set("1", randkv.RandomValue(100), 1)
err = str.Set("11", randkv.RandomValue(100), 1)
assert.Nil(t, err)

err = str.Set("2", randkv.RandomValue(100), 2)
err = str.Set("21", randkv.RandomValue(100), 2)
assert.Nil(t, err)

err = str.Set("3", randkv.RandomValue(100), 0)
err = str.Set("31", randkv.RandomValue(100), 0)
assert.Nil(t, err)

err = str.Set("hhh", randkv.RandomValue(100), 0)
Expand All @@ -442,9 +442,21 @@ func TestStringStructure_Keys(t *testing.T) {

time.Sleep(2 * time.Second)

keys, err := str.Keys()
keys, err := str.Keys("*")
assert.Nil(t, err)
assert.Equal(t, len(keys), 3)

keys, err = str.Keys("1*")
assert.Nil(t, err)
assert.Equal(t, len(keys), 0)

keys, err = str.Keys("3*")
assert.Nil(t, err)
assert.Equal(t, len(keys), 1)

keys, err = str.Keys("*1")
assert.Nil(t, err)
assert.Equal(t, len(keys), 1)
}

func TestStringStructure_TTL(t *testing.T) {
Expand Down
14 changes: 14 additions & 0 deletions structure/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package structure

import (
"errors"
"regexp"
"strconv"
"strings"
)

type DataStructure = byte
Expand Down Expand Up @@ -189,3 +191,15 @@ func convertToFloat(Value interface{}) (float64, error) {
return 0, errors.New("unsupported type")
}
}

func convertToRegexp(pattern string) string {
// 转义正则特殊字符
re := regexp.MustCompile(`([\[\]\(\)\{\}\^\$\.\+])`)
pattern = re.ReplaceAllString(pattern, `\$1`)

// 将 * 和 ? 转换为对应的正则表达式
pattern = strings.ReplaceAll(pattern, "*", ".*")
pattern = strings.ReplaceAll(pattern, "?", ".")

return "^" + pattern + "$" // 添加 ^ 和 $ 以确保完全匹配
}