diff --git a/database/kvdriver/compare.go b/database/kvdriver/compare.go new file mode 100644 index 0000000..adcaf47 --- /dev/null +++ b/database/kvdriver/compare.go @@ -0,0 +1,49 @@ +package kvdriver + +type CompareEqual[K comparable] func(ref, part K) bool +type CompareContains[K comparable] func(ref, part K) bool +type CompareEmpty[K comparable] func(part K) bool + +type Compare[K comparable] interface { + IsEqual(ref, part K) bool + IsContains(ref, part K) bool + IsEmpty(part K) bool +} + +func NewCompare[K comparable](eq CompareEqual[K], cn CompareContains[K], em CompareEmpty[K]) Compare[K] { + return &cmp[K]{ + feq: eq, + fcn: cn, + fem: em, + } +} + +type cmp[K comparable] struct { + feq CompareEqual[K] + fcn CompareContains[K] + fem CompareEmpty[K] +} + +func (o *cmp[K]) IsEqual(ref, part K) bool { + if o == nil || o.feq == nil { + return false + } + + return o.feq(ref, part) +} + +func (o *cmp[K]) IsContains(ref, part K) bool { + if o == nil || o.fcn == nil { + return false + } + + return o.fcn(ref, part) +} + +func (o *cmp[K]) IsEmpty(part K) bool { + if o == nil || o.fem == nil { + return false + } + + return o.fem(part) +} diff --git a/database/kvdriver/errors.go b/database/kvdriver/errors.go index c674dcf..0c766ab 100644 --- a/database/kvdriver/errors.go +++ b/database/kvdriver/errors.go @@ -37,6 +37,8 @@ const pkgName = "golib/database/kvdriver" const ( ErrorParamEmpty liberr.CodeError = iota + liberr.MinPkgDatabaseKVDrv ErrorBadInstance + ErrorCompareFunctionEqual + ErrorCompareFunctionContain ErrorGetFunction ErrorSetFunction ErrorDelFunction @@ -59,6 +61,10 @@ func getMessage(code liberr.CodeError) (message string) { return "given parameters is empty" case ErrorBadInstance: return "bad instance of " + pkgName + case ErrorCompareFunctionEqual: + return "missing comparable equal function of " + pkgName + case ErrorCompareFunctionContain: + return "missing comparable contain function of " + pkgName case ErrorGetFunction: return "missing get function of " + pkgName case ErrorSetFunction: diff --git a/database/kvdriver/interface.go b/database/kvdriver/interface.go index eefb9a4..2b8f028 100644 --- a/database/kvdriver/interface.go +++ b/database/kvdriver/interface.go @@ -34,25 +34,34 @@ type FuncNew[K comparable, M any] func() libkvt.KVDriver[K, M] type FuncGet[K comparable, M any] func(key K) (M, error) type FuncSet[K comparable, M any] func(key K, model M) error type FuncDel[K comparable] func(key K) error -type FuncList[K comparable, M any] func() ([]K, error) +type FuncList[K comparable] func() ([]K, error) +type FuncSearch[K comparable] func(prefix K) ([]K, error) type FuncWalk[K comparable, M any] func(fct libkvt.FctWalk[K, M]) error type drv[K comparable, M any] struct { - FctNew FuncNew[K, M] - FctGet FuncGet[K, M] - FctSet FuncSet[K, M] - FctDel FuncDel[K] - FctList FuncList[K, M] - FctWalk FuncWalk[K, M] // optional + cmp Compare[K] + + fctNew FuncNew[K, M] + fctGet FuncGet[K, M] + fctSet FuncSet[K, M] + fctDel FuncDel[K] + fctLst FuncList[K] + + fctSch FuncSearch[K] // optional + fctWlk FuncWalk[K, M] // optional } -func New[K comparable, M any](fn FuncNew[K, M], fg FuncGet[K, M], fs FuncSet[K, M], fd FuncDel[K], fl FuncList[K, M], fw FuncWalk[K, M]) libkvt.KVDriver[K, M] { +func New[K comparable, M any](cmp Compare[K], fn FuncNew[K, M], fg FuncGet[K, M], fs FuncSet[K, M], fd FuncDel[K], fl FuncList[K], fh FuncSearch[K], fw FuncWalk[K, M]) libkvt.KVDriver[K, M] { return &drv[K, M]{ - FctNew: fn, - FctGet: fg, - FctSet: fs, - FctDel: fd, - FctList: fl, - FctWalk: fw, + cmp: cmp, // compare instance + + fctNew: fn, + fctGet: fg, + fctSet: fs, + fctDel: fd, + fctLst: fl, + + fctSch: fh, // optional + fctWlk: fw, // optional } } diff --git a/database/kvdriver/model.go b/database/kvdriver/model.go index cd2536c..b29b4ef 100644 --- a/database/kvdriver/model.go +++ b/database/kvdriver/model.go @@ -31,27 +31,29 @@ import ( ) func (o *drv[K, M]) New() libkvt.KVDriver[K, M] { - if o.FctNew != nil { - return o.FctNew() + if o.fctNew != nil { + return o.fctNew() } return &drv[K, M]{ - FctNew: o.FctNew, - FctGet: o.FctGet, - FctSet: o.FctSet, - FctDel: o.FctDel, - FctList: o.FctList, - FctWalk: o.FctWalk, + cmp: o.cmp, + fctNew: o.fctNew, + fctGet: o.fctGet, + fctSet: o.fctSet, + fctDel: o.fctDel, + fctLst: o.fctLst, + fctSch: o.fctSch, + fctWlk: o.fctWlk, } } func (o *drv[K, M]) Get(key K, model *M) error { if o == nil { return ErrorBadInstance.Error(nil) - } else if o.FctGet == nil { + } else if o.fctGet == nil { return ErrorGetFunction.Error(nil) } else { - m, e := o.FctGet(key) + m, e := o.fctGet(key) *model = m return e } @@ -60,30 +62,44 @@ func (o *drv[K, M]) Get(key K, model *M) error { func (o *drv[K, M]) Set(key K, model M) error { if o == nil { return ErrorBadInstance.Error(nil) - } else if o.FctSet == nil { + } else if o.fctSet == nil { return ErrorSetFunction.Error(nil) } else { - return o.FctSet(key, model) + return o.fctSet(key, model) } } func (o *drv[K, M]) Del(key K) error { if o == nil { return ErrorBadInstance.Error(nil) - } else if o.FctDel == nil { + } else if o.fctDel == nil { return ErrorSetFunction.Error(nil) } else { - return o.FctDel(key) + return o.fctDel(key) } } func (o *drv[K, M]) List() ([]K, error) { if o == nil { return nil, ErrorBadInstance.Error(nil) - } else if o.FctList == nil { + } else if o.fctLst == nil { return nil, ErrorListFunction.Error(nil) } else { - return o.FctList() + return o.fctLst() + } +} + +func (o *drv[K, M]) Search(pattern K) ([]K, error) { + if o == nil { + return nil, ErrorBadInstance.Error(nil) + } else if o.cmp == nil { + return nil, ErrorBadInstance.Error(nil) + } else if o.cmp.IsEmpty(pattern) { + return o.List() + } else if o.fctSch != nil { + return o.fctSch(pattern) + } else { + return o.fakeSrch(pattern) } } @@ -92,10 +108,24 @@ func (o *drv[K, M]) Walk(fct libkvt.FctWalk[K, M]) error { return ErrorBadInstance.Error(nil) } else if fct == nil { return ErrorFunctionParams.Error(nil) - } else if o.FctWalk == nil { + } else if o.fctWlk == nil { return o.fakeWalk(fct) } else { - return o.FctWalk(fct) + return o.fctWlk(fct) + } +} + +func (o *drv[K, M]) fakeSrch(pattern K) ([]K, error) { + if l, e := o.List(); e != nil { + return nil, e + } else { + var res = make([]K, 0) + for _, k := range l { + if o.cmp.IsContains(k, pattern) { + res = append(res, k) + } + } + return res, nil } } diff --git a/database/kvtable/model.go b/database/kvtable/model.go index 5cf0ca3..3be4758 100644 --- a/database/kvtable/model.go +++ b/database/kvtable/model.go @@ -35,18 +35,6 @@ type tbl[K comparable, M any] struct { d libkvt.KVDriver[K, M] } -func (o *tbl[K, M]) getDriver() libkvt.KVDriver[K, M] { - if o == nil { - return nil - } - - if o.d == nil { - return nil - } else { - return o.d - } -} - func (o *tbl[K, M]) Get(key K) (libkvt.KVItem[K, M], error) { if drv := o.getDriver(); drv == nil { return nil, ErrorBadDriver.Error(nil) @@ -65,18 +53,6 @@ func (o *tbl[K, M]) Del(key K) error { } } -func (o *tbl[K, M]) Walk(fct libkvt.FuncWalk[K, M]) error { - if drv := o.getDriver(); drv == nil { - return ErrorBadDriver.Error(nil) - } else { - return drv.Walk(func(key K, model M) bool { - kvi := libkvs.New[K, M](drv.New(), key) - kvi.Set(model) - return fct(kvi) - }) - } -} - func (o *tbl[K, M]) List() ([]libkvt.KVItem[K, M], error) { var res = make([]libkvt.KVItem[K, M], 0) @@ -92,3 +68,43 @@ func (o *tbl[K, M]) List() ([]libkvt.KVItem[K, M], error) { return res, nil } } + +func (o *tbl[K, M]) Search(pattern K) ([]libkvt.KVItem[K, M], error) { + var res = make([]libkvt.KVItem[K, M], 0) + + if drv := o.getDriver(); drv == nil { + return nil, ErrorBadDriver.Error(nil) + } else if l, e := drv.Search(pattern); e != nil { + return nil, e + } else { + for _, k := range l { + res = append(res, libkvs.New[K, M](drv.New(), k)) + } + + return res, nil + } +} + +func (o *tbl[K, M]) Walk(fct libkvt.FuncWalk[K, M]) error { + if drv := o.getDriver(); drv == nil { + return ErrorBadDriver.Error(nil) + } else { + return drv.Walk(func(key K, model M) bool { + kvi := libkvs.New[K, M](drv.New(), key) + kvi.Set(model) + return fct(kvi) + }) + } +} + +func (o *tbl[K, M]) getDriver() libkvt.KVDriver[K, M] { + if o == nil { + return nil + } + + if o.d == nil { + return nil + } else { + return o.d + } +} diff --git a/database/kvtypes/driver.go b/database/kvtypes/driver.go index 9affd32..d0834e0 100644 --- a/database/kvtypes/driver.go +++ b/database/kvtypes/driver.go @@ -34,5 +34,6 @@ type KVDriver[K comparable, M any] interface { Set(key K, model M) error Del(key K) error List() ([]K, error) + Search(pattern K) ([]K, error) Walk(fct FctWalk[K, M]) error } diff --git a/database/kvtypes/table.go b/database/kvtypes/table.go index 0b2c53d..8815c25 100644 --- a/database/kvtypes/table.go +++ b/database/kvtypes/table.go @@ -32,5 +32,6 @@ type KVTable[K comparable, M any] interface { Get(key K) (KVItem[K, M], error) Del(key K) error List() ([]KVItem[K, M], error) + Search(pattern K) ([]KVItem[K, M], error) Walk(fct FuncWalk[K, M]) error } diff --git a/go.mod b/go.mod index f2f4749..a60499c 100644 --- a/go.mod +++ b/go.mod @@ -5,12 +5,12 @@ go 1.24 toolchain go1.24.1 require ( - github.com/aws/aws-sdk-go v1.55.6 + github.com/aws/aws-sdk-go v1.55.7 github.com/aws/aws-sdk-go-v2 v1.36.3 - github.com/aws/aws-sdk-go-v2/config v1.29.13 - github.com/aws/aws-sdk-go-v2/credentials v1.17.66 - github.com/aws/aws-sdk-go-v2/service/iam v1.41.1 - github.com/aws/aws-sdk-go-v2/service/s3 v1.79.1 + github.com/aws/aws-sdk-go-v2/config v1.29.14 + github.com/aws/aws-sdk-go-v2/credentials v1.17.67 + github.com/aws/aws-sdk-go-v2/service/iam v1.42.0 + github.com/aws/aws-sdk-go-v2/service/s3 v1.79.3 github.com/aws/smithy-go v1.22.3 github.com/bits-and-blooms/bitset v1.22.0 github.com/c-bata/go-prompt v0.2.6 @@ -19,7 +19,7 @@ require ( github.com/fsnotify/fsnotify v1.9.0 github.com/fxamacker/cbor/v2 v2.8.0 github.com/gin-gonic/gin v1.10.0 - github.com/go-ldap/ldap/v3 v3.4.10 + github.com/go-ldap/ldap/v3 v3.4.11 github.com/go-playground/validator/v10 v10.26.0 github.com/go-viper/mapstructure/v2 v2.2.1 github.com/google/go-github/v33 v33.0.0 @@ -32,9 +32,9 @@ require ( github.com/mattn/go-colorable v0.1.14 github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/mapstructure v1.5.0 - github.com/nats-io/jwt/v2 v2.7.3 - github.com/nats-io/nats-server/v2 v2.11.1 - github.com/nats-io/nats.go v1.41.1 + github.com/nats-io/jwt/v2 v2.7.4 + github.com/nats-io/nats-server/v2 v2.11.3 + github.com/nats-io/nats.go v1.42.0 github.com/onsi/ginkgo/v2 v2.23.4 github.com/onsi/gomega v1.37.0 github.com/pelletier/go-toml v1.9.5 @@ -48,21 +48,21 @@ require ( github.com/spf13/viper v1.20.1 github.com/ugorji/go/codec v1.2.12 github.com/ulikunitz/xz v0.5.12 - github.com/vbauerster/mpb/v8 v8.9.3 + github.com/vbauerster/mpb/v8 v8.10.1 github.com/xanzy/go-gitlab v0.115.0 github.com/xhit/go-simple-mail v2.2.2+incompatible - golang.org/x/net v0.39.0 - golang.org/x/oauth2 v0.29.0 - golang.org/x/sync v0.13.0 - golang.org/x/sys v0.32.0 - golang.org/x/term v0.31.0 + golang.org/x/net v0.40.0 + golang.org/x/oauth2 v0.30.0 + golang.org/x/sync v0.14.0 + golang.org/x/sys v0.33.0 + golang.org/x/term v0.32.0 gopkg.in/yaml.v3 v3.0.1 gorm.io/driver/clickhouse v0.6.1 gorm.io/driver/mysql v1.5.7 gorm.io/driver/postgres v1.5.11 gorm.io/driver/sqlite v1.5.7 gorm.io/driver/sqlserver v1.5.4 - gorm.io/gorm v1.25.12 + gorm.io/gorm v1.26.1 ) require ( @@ -85,12 +85,12 @@ require ( github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.34 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.0 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.1 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 // indirect github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.15 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.33.18 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bytedance/sonic v1.13.2 // indirect github.com/bytedance/sonic/loader v0.2.4 // indirect @@ -98,7 +98,7 @@ require ( github.com/cloudwego/base64x v0.1.5 // indirect github.com/gabriel-vasile/mimetype v1.4.8 // indirect github.com/gin-contrib/sse v1.1.0 // indirect - github.com/go-asn1-ber/asn1-ber v1.5.7 // indirect + github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect github.com/go-faster/city v1.0.1 // indirect github.com/go-faster/errors v0.7.1 // indirect github.com/go-logr/logr v1.4.2 // indirect @@ -145,7 +145,7 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/nats-io/nkeys v0.4.10 // indirect + github.com/nats-io/nkeys v0.4.11 // indirect github.com/nats-io/nuid v1.0.1 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/paulmach/orb v0.11.1 // indirect @@ -174,8 +174,8 @@ require ( go.uber.org/automaxprocs v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/arch v0.16.0 // indirect - golang.org/x/crypto v0.37.0 // indirect - golang.org/x/text v0.24.0 // indirect + golang.org/x/crypto v0.38.0 // indirect + golang.org/x/text v0.25.0 // indirect golang.org/x/time v0.11.0 // indirect golang.org/x/tools v0.32.0 // indirect google.golang.org/protobuf v1.36.6 // indirect