Skip to content

Commit

Permalink
add: add sadd command for db
Browse files Browse the repository at this point in the history
  • Loading branch information
xgzlucario committed Jun 17, 2024
1 parent 5e851c8 commit f64aecd
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 61 deletions.
34 changes: 28 additions & 6 deletions command.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ import (
)

type Command struct {
// name is command string name.
// it should consist of all lowercase letters.
// name is lowercase letters command name.
name string

// handler is this command real database handler function.
Expand All @@ -24,18 +23,19 @@ type Command struct {

// cmdTable is the list of all available commands.
var cmdTable []*Command = []*Command{
{"ping", pingCommand, 0, false},
{"set", setCommand, 2, true},
{"get", getCommand, 1, false},
{"incr", incrCommand, 1, true},
{"hset", hsetCommand, 3, true},
{"hget", hgetCommand, 2, false},
{"hdel", hdelCommand, 2, true},
{"hgetall", hgetallCommand, 1, false},
{"rpush", rpushCommand, 2, true},
{"lpush", lpushCommand, 2, true},
{"rpop", rpopCommand, 1, true},
{"lpop", lpopCommand, 1, true},
{"sadd", saddCommand, 2, true},
{"ping", pingCommand, 0, false},
{"hgetall", hgetallCommand, 1, false},
{"lrange", lrangeCommand, 3, false},
}

Expand Down Expand Up @@ -130,7 +130,7 @@ func hsetCommand(args []Arg) Value {
var newFields int
for i := 0; i < len(args); i += 2 {
key := args[i].ToString()
value := args[i+1].ToBytes()
value := args[i+1].Clone()
if hmap.Set(key, value) {
newFields++
}
Expand All @@ -146,7 +146,7 @@ func hgetCommand(args []Arg) Value {
if err != nil {
return newErrValue(ErrWrongType)
}
value, _, ok := hmap.Get(key)
value, ok := hmap.Get(key)
if !ok {
return ValueNull
}
Expand Down Expand Up @@ -266,6 +266,24 @@ func lrangeCommand(args []Arg) Value {
return newArrayValue(res)
}

func saddCommand(args []Arg) Value {
key := args[0].ToString()
args = args[1:]

set, err := fetchSet(key, true)
if err != nil {
return newErrValue(err)
}

var newItems int
for i := 0; i < len(args); i++ {
if set.Add(args[i].ToString()) {
newItems++
}
}
return newIntegerValue(newItems)
}

func fetchMap(key string, setnx ...bool) (Map, error) {
return fetch(key, func() Map { return structx.NewMap() }, setnx...)
}
Expand All @@ -274,6 +292,10 @@ func fetchList(key string, setnx ...bool) (List, error) {
return fetch(key, func() List { return structx.NewList() }, setnx...)
}

func fetchSet(key string, setnx ...bool) (Set, error) {
return fetch(key, func() Set { return structx.NewSet() }, setnx...)
}

func fetch[T any](key string, new func() T, setnx ...bool) (v T, err error) {
item, ok := db.extras[key]
if ok {
Expand Down
5 changes: 5 additions & 0 deletions command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,11 @@ func TestCommand(t *testing.T) {
assert.Equal(val, "f")
})

t.Run("set", func(t *testing.T) {
n, _ := rdb.SAdd(ctx, "set", "k1", "k2", "k3").Result()
assert.Equal(n, int64(3))
})

t.Run("client-closed", func(t *testing.T) {
rdb.Close()
})
Expand Down
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ go 1.22

require (
github.com/cockroachdb/swiss v0.0.0-20240612210725-f4de07ae6964
github.com/deckarep/golang-set/v2 v2.6.0
github.com/redis/go-redis/v9 v9.5.2
github.com/rs/zerolog v1.33.0
github.com/sakeven/RbTree v1.1.1
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM=
github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ=
Expand Down
13 changes: 7 additions & 6 deletions resp.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"fmt"
"io"
"slices"
"strconv"
"unsafe"
)
Expand Down Expand Up @@ -79,10 +80,6 @@ func cutByCRLF(buf []byte) (before, after []byte, found bool) {
return
}

func parseInt(b []byte) (int, error) {
return strconv.Atoi(b2s(b))
}

func (r *Resp) ReadNextCommand(argsBuf []Arg) (args []Arg, err error) {
if len(r.b) == 0 {
return nil, io.EOF
Expand All @@ -96,7 +93,7 @@ func (r *Resp) ReadNextCommand(argsBuf []Arg) (args []Arg, err error) {
if !ok {
return nil, ErrCRLFNotFound
}
count, err := parseInt(before)
count, err := strconv.Atoi(b2s(before))
if err != nil {
return nil, err
}
Expand All @@ -114,7 +111,7 @@ func (r *Resp) ReadNextCommand(argsBuf []Arg) (args []Arg, err error) {
if !ok {
return nil, ErrCRLFNotFound
}
count, err := parseInt(before)
count, err := strconv.Atoi(b2s(before))
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -152,6 +149,10 @@ func (a Arg) ToBytes() []byte {
return a
}

func (a Arg) Clone() []byte {
return slices.Clone(a)
}

func b2s(b []byte) string {
return *(*string)(unsafe.Pointer(&b))
}
Expand Down
34 changes: 13 additions & 21 deletions structx/map.go
Original file line number Diff line number Diff line change
@@ -1,44 +1,36 @@
package structx

import (
"github.com/xgzlucario/rotom/dict"
"github.com/cockroachdb/swiss"
)

type Map struct {
m *dict.Dict
m *swiss.Map[string, []byte]
}

func defaultOptions() dict.Options {
options := dict.DefaultOptions
options.ShardCount = 1
options.IndexSize = 8
options.BufferSize = 32
return options
func NewMap() *Map {
return &Map{m: swiss.New[string, []byte](8)}
}

func NewMap() (s *Map) {
return &Map{m: dict.New(defaultOptions())}
}

func (m *Map) Get(key string) ([]byte, int64, bool) {
func (m *Map) Get(key string) ([]byte, bool) {
return m.m.Get(key)
}

func (m *Map) Set(key string, val []byte) (newField bool) {
return m.m.Set(key, val)
func (m *Map) Set(key string, val []byte) bool {
_, ok := m.m.Get(key)
m.m.Put(key, val)
return !ok
}

func (m *Map) Remove(key string) bool {
return m.m.Remove(key)
_, ok := m.m.Get(key)
m.m.Delete(key)
return ok
}

func (m *Map) Scan(fn func(key string, value []byte)) {
m.m.Scan(func(key string, val []byte, _ int64) (next bool) {
m.m.All(func(key string, val []byte) (next bool) {
fn(key, val)
return true
})
}

func (m *Map) Len() (n int) {
return m.m.GetStats().Len
}
34 changes: 9 additions & 25 deletions structx/set.go
Original file line number Diff line number Diff line change
@@ -1,35 +1,19 @@
package structx

import (
mapset "github.com/deckarep/golang-set/v2"
)
import "github.com/cockroachdb/swiss"

// Set
type Set struct {
mapset.Set[string]
m *swiss.Map[string, struct{}]
}

// NewSet
func NewSet() *Set {
return &Set{mapset.NewSet[string]()}
return &Set{m: swiss.New[string, struct{}](8)}
}

// Clone
func (s *Set) Clone() *Set {
return &Set{s.Set.Clone()}
}

// Union
func (s *Set) Union(other *Set) {
s.Set = s.Set.Union(other.Set)
}

// Intersect
func (s *Set) Intersect(other *Set) {
s.Set = s.Set.Intersect(other.Set)
}

// Difference
func (s *Set) Difference(other *Set) {
s.Set = s.Set.SymmetricDifference(other.Set)
func (s *Set) Add(key string) bool {
if _, ok := s.m.Get(key); ok {
return false
}
s.m.Put(key, struct{}{})
return true
}

0 comments on commit f64aecd

Please sign in to comment.