mirror of
https://github.com/EchoVault/SugarDB.git
synced 2025-09-28 12:52:10 +08:00
Implement DBSIZE command (#159)
Implement DBSIZE Command - @NicoleStrel
This commit is contained in:
@@ -206,6 +206,7 @@ Benchmark script options:
|
|||||||
<a name="commands-generic"></a>
|
<a name="commands-generic"></a>
|
||||||
## GENERIC
|
## GENERIC
|
||||||
* [COPY](https://sugardb.io/docs/commands/generic/copy)
|
* [COPY](https://sugardb.io/docs/commands/generic/copy)
|
||||||
|
* [DBSIZE](https://sugardb.io/docs/commands/generic/dbsize)
|
||||||
* [DECR](https://sugardb.io/docs/commands/generic/decr)
|
* [DECR](https://sugardb.io/docs/commands/generic/decr)
|
||||||
* [DECRBY](https://sugardb.io/docs/commands/generic/decrby)
|
* [DECRBY](https://sugardb.io/docs/commands/generic/decrby)
|
||||||
* [DEL](https://sugardb.io/docs/commands/generic/del)
|
* [DEL](https://sugardb.io/docs/commands/generic/del)
|
||||||
|
File diff suppressed because it is too large
Load Diff
47
docs/docs/commands/generic/dbsize.mdx
Normal file
47
docs/docs/commands/generic/dbsize.mdx
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import Tabs from '@theme/Tabs';
|
||||||
|
import TabItem from '@theme/TabItem';
|
||||||
|
|
||||||
|
# DBSIZE
|
||||||
|
|
||||||
|
### Syntax
|
||||||
|
```
|
||||||
|
DBSIZE
|
||||||
|
```
|
||||||
|
|
||||||
|
### Module
|
||||||
|
<span className="acl-category">generic</span>
|
||||||
|
|
||||||
|
### Categories
|
||||||
|
<span className="acl-category">fast</span>
|
||||||
|
<span className="acl-category">read</span>
|
||||||
|
<span className="acl-category">keyspace</span>
|
||||||
|
|
||||||
|
### Description
|
||||||
|
Return the number of keys in the currently-selected database.
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
<Tabs
|
||||||
|
defaultValue="go"
|
||||||
|
values={[
|
||||||
|
{ label: 'Go (Embedded)', value: 'go', },
|
||||||
|
{ label: 'CLI', value: 'cli', },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<TabItem value="go">
|
||||||
|
Get the number of keys in the database:
|
||||||
|
```go
|
||||||
|
db, err := sugardb.NewSugarDB()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
key, err := db.DBSize()
|
||||||
|
```
|
||||||
|
</TabItem>
|
||||||
|
<TabItem value="cli">
|
||||||
|
Get the number of keys in the database:
|
||||||
|
```
|
||||||
|
> DBSIZE
|
||||||
|
```
|
||||||
|
</TabItem>
|
||||||
|
</Tabs>
|
@@ -714,6 +714,11 @@ func handleRandomKey(params internal.HandlerFuncParams) ([]byte, error) {
|
|||||||
return []byte(fmt.Sprintf("+%v\r\n", key)), nil
|
return []byte(fmt.Sprintf("+%v\r\n", key)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handleDBSize(params internal.HandlerFuncParams) ([]byte, error) {
|
||||||
|
count := params.DBSize(params.Context)
|
||||||
|
return []byte(fmt.Sprintf(":%d\r\n", count)), nil
|
||||||
|
}
|
||||||
|
|
||||||
func handleGetdel(params internal.HandlerFuncParams) ([]byte, error) {
|
func handleGetdel(params internal.HandlerFuncParams) ([]byte, error) {
|
||||||
keys, err := getDelKeyFunc(params.Command)
|
keys, err := getDelKeyFunc(params.Command)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1285,6 +1290,16 @@ Delete all the keys in the currently selected database. This command is always s
|
|||||||
KeyExtractionFunc: randomKeyFunc,
|
KeyExtractionFunc: randomKeyFunc,
|
||||||
HandlerFunc: handleRandomKey,
|
HandlerFunc: handleRandomKey,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Command: "dbsize",
|
||||||
|
Module: constants.GenericModule,
|
||||||
|
Categories: []string{constants.KeyspaceCategory, constants.ReadCategory, constants.FastCategory},
|
||||||
|
Description: "(DBSIZE) Return the number of keys in the currently selected database.",
|
||||||
|
Sync: false,
|
||||||
|
Type: "BUILT_IN",
|
||||||
|
KeyExtractionFunc: dbSizeKeyFunc,
|
||||||
|
HandlerFunc: handleDBSize,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Command: "getdel",
|
Command: "getdel",
|
||||||
Module: constants.GenericModule,
|
Module: constants.GenericModule,
|
||||||
|
@@ -2909,6 +2909,45 @@ func Test_Generic(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("Test_HandleDBSIZE", func(t *testing.T) {
|
||||||
|
conn, err := internal.GetConnection("localhost", port)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
_ = conn.Close()
|
||||||
|
}()
|
||||||
|
client := resp.NewConn(conn)
|
||||||
|
|
||||||
|
// Populate the store with a few keys
|
||||||
|
expectedSize := 5
|
||||||
|
for i := 0; i < expectedSize; i++ {
|
||||||
|
_, _, err := mockServer.Set(
|
||||||
|
fmt.Sprintf("DBSizeKey%d", i),
|
||||||
|
fmt.Sprintf("Value%d", i),
|
||||||
|
sugardb.SETOptions{},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = client.WriteArray([]resp.Value{resp.StringValue("DBSIZE")}); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
res, _, err := client.ReadValue()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if res.Integer() != int(expectedSize) {
|
||||||
|
t.Errorf("expected dbsize %d, got %d", expectedSize, res.Integer())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("Test_HandleGETDEL", func(t *testing.T) {
|
t.Run("Test_HandleGETDEL", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
conn, err := internal.GetConnection("localhost", port)
|
conn, err := internal.GetConnection("localhost", port)
|
||||||
|
@@ -211,6 +211,17 @@ func randomKeyFunc(cmd []string) (internal.KeyExtractionFuncResult, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func dbSizeKeyFunc(cmd []string) (internal.KeyExtractionFuncResult, error) {
|
||||||
|
if len(cmd) != 1 {
|
||||||
|
return internal.KeyExtractionFuncResult{}, errors.New(constants.WrongArgsResponse)
|
||||||
|
}
|
||||||
|
return internal.KeyExtractionFuncResult{
|
||||||
|
Channels: make([]string, 0),
|
||||||
|
ReadKeys: make([]string, 0),
|
||||||
|
WriteKeys: make([]string, 0),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func getDelKeyFunc(cmd []string) (internal.KeyExtractionFuncResult, error) {
|
func getDelKeyFunc(cmd []string) (internal.KeyExtractionFuncResult, error) {
|
||||||
if len(cmd) != 2 {
|
if len(cmd) != 2 {
|
||||||
return internal.KeyExtractionFuncResult{}, errors.New(constants.WrongArgsResponse)
|
return internal.KeyExtractionFuncResult{}, errors.New(constants.WrongArgsResponse)
|
||||||
|
@@ -196,6 +196,8 @@ type HandlerFuncParams struct {
|
|||||||
Flush func(database int)
|
Flush func(database int)
|
||||||
// RandomKey returns a random key
|
// RandomKey returns a random key
|
||||||
RandomKey func(ctx context.Context) string
|
RandomKey func(ctx context.Context) string
|
||||||
|
// DBSize returns the number of keys in the currently selected database.
|
||||||
|
DBSize func(ctx context.Context) int
|
||||||
// (TOUCH key [key ...]) Alters the last access time or access count of the key(s)
|
// (TOUCH key [key ...]) Alters the last access time or access count of the key(s)
|
||||||
// depending on whether LFU or LRU strategy was used.
|
// depending on whether LFU or LRU strategy was used.
|
||||||
// A key is ignored if it does not exist.
|
// A key is ignored if it does not exist.
|
||||||
|
@@ -632,6 +632,16 @@ func (server *SugarDB) RandomKey() (string, error) {
|
|||||||
return internal.ParseStringResponse(b)
|
return internal.ParseStringResponse(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DBSize returns the number of keys in the currently-selected database.
|
||||||
|
// Returns: An integer number of keys
|
||||||
|
func (server *SugarDB) DBSize() (int, error) {
|
||||||
|
b, err := server.handleCommand(server.context, internal.EncodeCommand([]string{"DBSIZE"}), nil, false, true)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return internal.ParseIntegerResponse(b)
|
||||||
|
}
|
||||||
|
|
||||||
// GetDel retrieves the value at the provided key and deletes that key.
|
// GetDel retrieves the value at the provided key and deletes that key.
|
||||||
//
|
//
|
||||||
// Parameters:
|
// Parameters:
|
||||||
|
@@ -1410,6 +1410,37 @@ func TestSugarDB_RANDOMKEY(t *testing.T) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSugarDB_DBSize(t *testing.T) {
|
||||||
|
server := createSugarDB()
|
||||||
|
got, err := server.DBSize()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if got != 0 {
|
||||||
|
t.Errorf("DBSIZE error, expected 0, got %d", got)
|
||||||
|
}
|
||||||
|
|
||||||
|
// test with keys
|
||||||
|
testkeys := []string{"1", "2", "3"}
|
||||||
|
for _, k := range testkeys {
|
||||||
|
err := presetValue(server, context.Background(), k, "")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
got, err = server.DBSize()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if got != len(testkeys) {
|
||||||
|
t.Errorf("DBSIZE error, expected %d, got %d", len(testkeys), got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestSugarDB_GETDEL(t *testing.T) {
|
func TestSugarDB_GETDEL(t *testing.T) {
|
||||||
server := createSugarDB()
|
server := createSugarDB()
|
||||||
|
|
||||||
|
@@ -771,6 +771,14 @@ func (server *SugarDB) randomKey(ctx context.Context) string {
|
|||||||
return randkey
|
return randkey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (server *SugarDB) dbSize(ctx context.Context) int {
|
||||||
|
server.storeLock.RLock()
|
||||||
|
defer server.storeLock.RUnlock()
|
||||||
|
|
||||||
|
database := ctx.Value("Database").(int)
|
||||||
|
return len(server.store[database])
|
||||||
|
}
|
||||||
|
|
||||||
func (server *SugarDB) getObjectFreq(ctx context.Context, key string) (int, error) {
|
func (server *SugarDB) getObjectFreq(ctx context.Context, key string) (int, error) {
|
||||||
database := ctx.Value("Database").(int)
|
database := ctx.Value("Database").(int)
|
||||||
|
|
||||||
|
@@ -18,12 +18,13 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/echovault/sugardb/internal"
|
|
||||||
"github.com/echovault/sugardb/internal/clock"
|
|
||||||
"github.com/echovault/sugardb/internal/constants"
|
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/echovault/sugardb/internal"
|
||||||
|
"github.com/echovault/sugardb/internal/clock"
|
||||||
|
"github.com/echovault/sugardb/internal/constants"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (server *SugarDB) getCommand(cmd string) (internal.Command, error) {
|
func (server *SugarDB) getCommand(cmd string) (internal.Command, error) {
|
||||||
@@ -61,6 +62,7 @@ func (server *SugarDB) getHandlerFuncParams(ctx context.Context, cmd []string, c
|
|||||||
GetClock: server.getClock,
|
GetClock: server.getClock,
|
||||||
Flush: server.Flush,
|
Flush: server.Flush,
|
||||||
RandomKey: server.randomKey,
|
RandomKey: server.randomKey,
|
||||||
|
DBSize: server.dbSize,
|
||||||
TouchKey: server.updateKeysInCache,
|
TouchKey: server.updateKeysInCache,
|
||||||
GetObjectFrequency: server.getObjectFreq,
|
GetObjectFrequency: server.getObjectFreq,
|
||||||
GetObjectIdleTime: server.getObjectIdleTime,
|
GetObjectIdleTime: server.getObjectIdleTime,
|
||||||
|
Reference in New Issue
Block a user