Skip to content

Commit

Permalink
Add --start, --end and --prefix options to keys and show subcommands
Browse files Browse the repository at this point in the history
  • Loading branch information
cions committed Nov 2, 2021
1 parent 0da65c1 commit 90e93c3
Show file tree
Hide file tree
Showing 2 changed files with 179 additions and 4 deletions.
88 changes: 86 additions & 2 deletions cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,49 @@ func Main(args []string) error {
&cli.BoolFlag{
Name: "base64",
Aliases: []string{"b"},
Usage: "Show keys in base64 encoding",
Usage: "show keys in base64 encoding",
},
&cli.StringFlag{
Name: "start",
Aliases: []string{"s"},
Usage: "start of the `key` range (inclusive)",
},
&cli.StringFlag{
Name: "start-raw",
Aliases: []string{"S"},
Usage: "start of the `key` range (no backslash escapes, inclusive)",
},
&cli.StringFlag{
Name: "start-base64",
Usage: "start of the `key` range (base64, inclusive)",
},
&cli.StringFlag{
Name: "end",
Aliases: []string{"e"},
Usage: "end of the `key` range (exclusive)",
},
&cli.StringFlag{
Name: "end-raw",
Aliases: []string{"E"},
Usage: "end of the `key` range (no backslash escapes, exclusive)",
},
&cli.StringFlag{
Name: "end-base64",
Usage: "end of the `key` range (base64, exclusive)",
},
&cli.StringFlag{
Name: "prefix",
Aliases: []string{"p"},
Usage: "limit the key range to a range that satisfy the given `prefix`",
},
&cli.StringFlag{
Name: "prefix-raw",
Aliases: []string{"P"},
Usage: "limit the key range to a range that satisfy the given `prefix` (no backslash escapes)",
},
&cli.StringFlag{
Name: "prefix-base64",
Usage: "limit the key range to a range that satisfy the given `prefix` (base64)",
},
},
Action: keysCmd,
Expand All @@ -146,7 +188,7 @@ func Main(args []string) error {
&cli.BoolFlag{
Name: "base64",
Aliases: []string{"b"},
Usage: "Show keys and values in base64 encoding",
Usage: "show keys and values in base64 encoding",
},
&cli.BoolFlag{
Name: "no-json",
Expand All @@ -158,6 +200,48 @@ func Main(args []string) error {
Aliases: []string{"w"},
Usage: "do not truncate output",
},
&cli.StringFlag{
Name: "start",
Aliases: []string{"s"},
Usage: "start of the `key` range (inclusive)",
},
&cli.StringFlag{
Name: "start-raw",
Aliases: []string{"S"},
Usage: "start of the `key` range (no backslash escapes, inclusive)",
},
&cli.StringFlag{
Name: "start-base64",
Usage: "start of the `key` range (base64, inclusive)",
},
&cli.StringFlag{
Name: "end",
Aliases: []string{"e"},
Usage: "end of the `key` range (exclusive)",
},
&cli.StringFlag{
Name: "end-raw",
Aliases: []string{"E"},
Usage: "end of the `key` range (no backslash escapes, exclusive)",
},
&cli.StringFlag{
Name: "end-base64",
Usage: "end of the `key` range (base64, exclusive)",
},
&cli.StringFlag{
Name: "prefix",
Aliases: []string{"p"},
Usage: "limit the key range to a range that satisfy the given `prefix`",
},
&cli.StringFlag{
Name: "prefix-raw",
Aliases: []string{"P"},
Usage: "limit the key range to a range that satisfy the given `prefix` (no backslash escapes)",
},
&cli.StringFlag{
Name: "prefix-base64",
Usage: "limit the key range to a range that satisfy the given `prefix` (base64)",
},
},
UseShortOptionHandling: true,
Action: showCmd,
Expand Down
95 changes: 93 additions & 2 deletions commands.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package leveldbcli

import (
"bytes"
"errors"
"fmt"
"io"
"os"
Expand All @@ -12,6 +14,7 @@ import (
"github.com/syndtr/goleveldb/leveldb"
"github.com/syndtr/goleveldb/leveldb/comparer"
"github.com/syndtr/goleveldb/leveldb/opt"
"github.com/syndtr/goleveldb/leveldb/util"
"github.com/urfave/cli/v2"
"github.com/vmihailenco/msgpack/v5"
)
Expand Down Expand Up @@ -173,6 +176,84 @@ func deleteCmd(c *cli.Context) (err error) {
return nil
}

func getKeyRange(c *cli.Context) (*util.Range, error) {
if c.IsSet("prefix-base64") {
if c.Bool("indexeddb") {
return nil, errors.New("use of --prefix-base64 in conjunction with --indexeddb is not supported")
}
prefix, err := decodeBase64([]byte(c.String("prefix-base64")))
if err != nil {
return nil, fmt.Errorf("option --prefix-base64: %w", err)
}
return util.BytesPrefix(prefix), nil
}
if c.IsSet("prefix-raw") {
if c.Bool("indexeddb") {
return nil, errors.New("use of --prefix-raw in conjunction with --indexeddb is not supported")
}
return util.BytesPrefix([]byte(c.String("prefix-raw"))), nil
}
if c.IsSet("prefix") {
if c.Bool("indexeddb") {
return nil, errors.New("use of --prefix in conjunction with --indexeddb is not supported")
}
prefix, err := unescape([]byte(c.String("prefix")))
if err != nil {
return nil, fmt.Errorf("option --prefix: %w", err)
}
return util.BytesPrefix(prefix), nil
}

slice := &util.Range{}

if c.IsSet("start-base64") {
start, err := decodeBase64([]byte(c.String("start-base64")))
if err != nil {
return nil, fmt.Errorf("option --start-base64: %w", err)
}
slice.Start = start
} else if c.IsSet("start-raw") {
slice.Start = []byte(c.String("start-raw"))
} else if c.IsSet("start") {
start, err := unescape([]byte(c.String("start")))
if err != nil {
return nil, fmt.Errorf("option --start: %w", err)
}
slice.Start = start
}

if c.IsSet("end-base64") {
end, err := decodeBase64([]byte(c.String("end-base64")))
if err != nil {
return nil, fmt.Errorf("option --end-base64: %w", err)
}
slice.Limit = end
} else if c.IsSet("end-raw") {
slice.Limit = []byte(c.String("end-raw"))
} else if c.IsSet("end") {
end, err := unescape([]byte(c.String("end")))
if err != nil {
return nil, fmt.Errorf("option --end: %w", err)
}
slice.Limit = end
}

if slice.Start != nil && slice.Limit != nil {
var cmp func([]byte, []byte) int = bytes.Compare
if c.Bool("indexeddb") {
cmp = indexeddb.IndexedDBComparer.Compare
}
if cmp(slice.Start, slice.Limit) > 0 {
slice.Limit = slice.Start
}
}

if slice.Start == nil && slice.Limit == nil {
return nil, nil
}
return slice, nil
}

func keysCmd(c *cli.Context) error {
var w io.Writer = os.Stdout
if c.Bool("base64") {
Expand All @@ -186,6 +267,11 @@ func keysCmd(c *cli.Context) error {
cmp = indexeddb.IndexedDBComparer
}

slice, err := getKeyRange(c)
if err != nil {
return err
}

opts := &opt.Options{Comparer: cmp, ErrorIfMissing: true, ReadOnly: true}
db, err := leveldb.OpenFile(c.String("dbpath"), opts)
if err != nil {
Expand All @@ -199,7 +285,7 @@ func keysCmd(c *cli.Context) error {
}
defer s.Release()

iter := s.NewIterator(nil, nil)
iter := s.NewIterator(slice, nil)
defer iter.Release()
for iter.Next() {
if _, err := w.Write(iter.Key()); err != nil {
Expand Down Expand Up @@ -240,6 +326,11 @@ func showCmd(c *cli.Context) error {
cmp = indexeddb.IndexedDBComparer
}

slice, err := getKeyRange(c)
if err != nil {
return err
}

opts := &opt.Options{Comparer: cmp, ErrorIfMissing: true, ReadOnly: true}
db, err := leveldb.OpenFile(c.String("dbpath"), opts)
if err != nil {
Expand All @@ -253,7 +344,7 @@ func showCmd(c *cli.Context) error {
}
defer s.Release()

iter := s.NewIterator(nil, nil)
iter := s.NewIterator(slice, nil)
defer iter.Release()
for iter.Next() {
if _, err := kw.Write(iter.Key()); err != nil {
Expand Down

0 comments on commit 90e93c3

Please sign in to comment.