Skip to content

Commit

Permalink
feat: feature dump
Browse files Browse the repository at this point in the history
* move all db related ommands to eponymous subcommand
* implement transact command
* implement input iteration from
  * stdin stream
  * stdin array
  * multiple command line arguments
* verious other fixes
* add tests
  • Loading branch information
efirs committed Apr 12, 2022
1 parent 0fe982c commit e431d6d
Show file tree
Hide file tree
Showing 30 changed files with 997 additions and 142 deletions.
17 changes: 17 additions & 0 deletions .github/workflows/go-test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: go-test
on:
push:
workflow_call:
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup Go
uses: actions/setup-go@v2
with:
go-version: '1.18'
- run: make test
4 changes: 3 additions & 1 deletion .github/workflows/package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,6 @@ jobs:
github_token: ${{ secrets.GITHUB_TOKEN }}
goos: ${{ matrix.goos }}
goarch: ${{ matrix.goarch }}
sha256sum: true
sha256sum: true
build_command: make
binary_name: tigris
2 changes: 1 addition & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ jobs:
node-version: 16
- name: release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GH_BOT_ACCESS_TOKEN }}
run: npx semantic-release --debug
15 changes: 8 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
VERSION=$(shell git describe --tags --always)
GO_SRC=$(shell find . -name "*.go" -not -name "*_test.go")
BINS=tigrisdb-cli
BIN=tigris

BUILD_PARAM=-tags=release -ldflags "-X 'github.com/tigrisdata/tigrisdb-cli/util.Version=$(VERSION)'" $(shell printenv BUILD_PARAM)
BUILD_PARAM=-tags=release -ldflags "-w -extldflags '-static' -X 'github.com/tigrisdata/tigrisdb-cli/util.Version=$(VERSION)'" -o ${BIN} $(shell printenv BUILD_PARAM)
TEST_PARAM=-cover -race -tags=test $(shell printenv TEST_PARAM)
export GOPRIVATE=github.com/tigrisdata/tigrisdb-client-go

all: ${BINS}
all: ${BIN}

${BINS}: ${GO_SRC} go.mod
go build ${BUILD_PARAM} .
${BIN}: ${GO_SRC} go.sum
CGO_ENABLED=0 go build ${BUILD_PARAM} .

lint:
golangci-lint run

go.sum: go.mod
go mod download

test: go.sum lint
test: ${BIN} go.sum
go test $(TEST_PARAM) ./...
/bin/bash tests/*.sh

clean:
rm -f ${BINS}
rm -f ${BIN}
42 changes: 24 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# TigrisDB command line interface utility

[![Build Status](https://github.com/tigrisdata/tigrisdb/workflows/go-lint/badge.svg)]()
[![Build Status](https://github.com/tigrisdata/tigrisdb/workflows/go-test/badge.svg)]()

# Install

Expand All @@ -11,41 +12,46 @@ go install github.com/tigrisdata/tigrisdb-cli@latest
# Example

```sh
tigrisdb-cli drop collection db1 coll1
tigrisdb-cli drop database db1

tigrisdb-cli create database db1
tigrisdb-cli create collection db1 coll1 \
'{ "properties": { "Key1": { "type": "string" }, "Field1": { "type": "int" } }, "primary_key": ["Key1"] }'

tigrisdb-cli list databases
tigrisdb-cli list collections db1

tigrisdb-cli insert "db1" "coll1" '{"Key1": "vK1", "Field1": 1}' \
tigris db create database db1
tigris db create collection db1 \
'{ "name" : "coll1", "properties": {
"Key1": { "type": "string" },
"Field1": { "type": "int" } },
"primary_key": ["Key1"]
}'

tigris db list databases
tigris db list collections db1

# Insert two documents into coll1
tigris db insert db1 coll1 '{"Key1": "vK1", "Field1": 1}' \
'{"Key1": "vK2", "Field1": 10}'

tigrisdb-cli read "db1" "coll1" \
# Read documents with keys equal to vK1 and vK2
tigris db read db1 coll1 \
'{"$or" : [ {"Key1": "vK1"}, {"Key1": "vK2"} ]}'
#Output:
#{"Key1": "vK1", "Field1": 1}
#{"Key1": "vK2", "Field1": 10}

tigrisdb-cli update "db1" "coll1" \
# Update Field1 of the document with the key vK1
tigris db update db1 coll1 \
'{"Key1": "vK1"}' '{"$set" : {"Field1": 1000}}'

tigrisdb-cli read "db1" "coll1" '{}'
# Read all documents from the coll1
tigris db read db1 coll1 '{}'
#Output:
#{"Key1": "vK1", "Field1": 1000}
#{"Key1": "vK2", "Field1": 10}

tigrisdb-cli delete "db1" "coll1" '{"Key1": "vK1"}'
tigris db delete "db1" "coll1" '{"Key1": "vK1"}'

tigrisdb-cli read "db1" "coll1" {}'
tigris db read "db1" "coll1" '{}'
#Output:
#{"Key1": "vK2", "Field1": 10}

tigrisdb-cli drop collection db1 coll1
tigrisdb-cli drop database db1
tigris db drop collection db1 coll1
tigris db drop database db1
```

# License
Expand Down
54 changes: 52 additions & 2 deletions client/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,50 @@ package client

import (
"context"
"fmt"
"strings"

"github.com/rs/zerolog/log"
"github.com/tigrisdata/tigrisdb-cli/config"
"github.com/tigrisdata/tigrisdb-cli/util"
"github.com/tigrisdata/tigrisdb-client-go/driver"
)

// D is single instance of client
var D driver.Driver

func Init(config config.Config) error {
driver.DefaultProtocol = driver.GRPC
drv, err := driver.NewDriver(context.Background(), config.URL, &driver.Config{Token: config.Token})
proto := strings.ToLower(strings.Trim(config.Protocol, " "))
if proto == "grpc" {
driver.DefaultProtocol = driver.GRPC
} else if proto == "https" || proto == "http" {
driver.DefaultProtocol = driver.HTTP
} else if proto != "" {
return fmt.Errorf("unknown protocol set by TIGRISDB_PROTOCOL: %s. allowed: grpc, http, https", proto)
}

// URL prefix has precedence over environment variable
url := config.URL
if strings.HasPrefix(config.URL, "http://") {
driver.DefaultProtocol = driver.HTTP
} else if strings.HasPrefix(config.URL, "https://") {
driver.DefaultProtocol = driver.HTTP
} else if strings.HasPrefix(config.URL, "grpc://") {
driver.DefaultProtocol = driver.GRPC
url = strings.TrimPrefix(config.URL, "grpc://")
}

//Client would use HTTPS if scheme is not explicitly specified
//Avoid this for localhost connections
if !strings.Contains(url, "://") && driver.DefaultProtocol == driver.HTTP &&
(strings.HasPrefix(url, "localhost") || strings.HasPrefix(url, "127.0.0.1")) {
url = "http://" + url
}

ctx, cancel := util.GetContext(context.Background())
defer cancel()

drv, err := driver.NewDriver(ctx, url, &driver.Config{Token: config.Token})
if err != nil {
return err
}
Expand All @@ -40,3 +73,20 @@ func Init(config config.Config) error {
func Get() driver.Driver {
return D
}

func Transact(bctx context.Context, db string, fn func(ctx context.Context, tx driver.Tx)) {
ctx, cancel := util.GetContext(bctx)
defer cancel()

tx, err := Get().BeginTx(ctx, db)
if err != nil {
log.Fatal().Err(err).Msg("begin transaction failed")
}
defer func() { _ = tx.Rollback(ctx) }()

fn(ctx, tx)

if err := tx.Commit(ctx); err != nil {
log.Fatal().Err(err).Msg("begin transaction failed")
}
}
2 changes: 1 addition & 1 deletion cmd/alter.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@ var alterCmd = &cobra.Command{
}

func init() {
rootCmd.AddCommand(alterCmd)
dbCmd.AddCommand(alterCmd)
}
80 changes: 53 additions & 27 deletions cmd/collection.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,36 @@
package cmd

import (
"context"
"encoding/json"

"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
"github.com/tigrisdata/tigrisdb-cli/client"
"github.com/tigrisdata/tigrisdb-cli/util"
"github.com/tigrisdata/tigrisdb-client-go/driver"
)

func createCollection(ctx context.Context, tx driver.Tx, raw driver.Schema) {
type Schema struct {
Name string
}
var schema Schema
if err := json.Unmarshal(raw, &schema); err != nil {
log.Fatal().Err(err).Msg("error parsing collection schema")
}
if schema.Name == "" {
log.Fatal().Msg("schema name is missing")
}
err := tx.CreateOrUpdateCollection(ctx, schema.Name, driver.Schema(raw))
if err != nil {
log.Fatal().Err(err).Msg("create collection failed")
}
}

var listCollectionsCmd = &cobra.Command{
Use: "collections",
Short: "list collections",
Use: "collections {db}",
Short: "list database collections",
Args: cobra.MinimumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
ctx, cancel := util.GetContext(cmd.Context())
Expand All @@ -34,50 +54,56 @@ var listCollectionsCmd = &cobra.Command{
log.Fatal().Err(err).Msg("list collections failed")
}
for _, v := range resp {
util.Stdout(v)
util.Stdout("%s\n", v)
}
},
}

var createCollectionCmd = &cobra.Command{
Use: "collection",
Short: "create collection",
Args: cobra.MinimumNArgs(3),
Use: "collection {db} {schema}...|-",
Short: "create collection(s)",
Args: cobra.MinimumNArgs(2),
Run: func(cmd *cobra.Command, args []string) {
ctx, cancel := util.GetContext(cmd.Context())
defer cancel()
err := client.Get().CreateOrUpdateCollection(ctx, args[0], args[1], driver.Schema(args[2]), &driver.CollectionOptions{})
if err != nil {
log.Fatal().Err(err).Msg("create collection failed")
}
client.Transact(cmd.Context(), args[0], func(ctx context.Context, tx driver.Tx) {
iterateInput(ctx, 1, args, func(ctx context.Context, args []string, docs []json.RawMessage) {
for _, v := range docs {
createCollection(ctx, tx, driver.Schema(v))
}
})
})
},
}

var dropCollectionCmd = &cobra.Command{
Use: "collection",
Use: "collection {db}",
Short: "drop collection",
Args: cobra.MinimumNArgs(2),
Run: func(cmd *cobra.Command, args []string) {
ctx, cancel := util.GetContext(cmd.Context())
defer cancel()
err := client.Get().DropCollection(ctx, args[0], args[1], &driver.CollectionOptions{})
if err != nil {
log.Fatal().Err(err).Msg("drop collection failed")
}
client.Transact(cmd.Context(), args[0], func(ctx context.Context, tx driver.Tx) {
iterateInput(ctx, 1, args, func(ctx context.Context, args []string, docs []json.RawMessage) {
for _, v := range docs {
err := tx.DropCollection(ctx, string(v))
if err != nil {
log.Fatal().Err(err).Msg("drop collection failed")
}
}
})
})
},
}

var alterCollectionCmd = &cobra.Command{
Use: "collection",
Short: "alter collection",
Use: "collection {db} {collection} {schema}",
Short: "update collection schema",
Args: cobra.MinimumNArgs(3),
Run: func(cmd *cobra.Command, args []string) {
ctx, cancel := util.GetContext(cmd.Context())
defer cancel()
err := client.Get().CreateOrUpdateCollection(ctx, args[0], args[1], driver.Schema(args[2]), &driver.CollectionOptions{})
if err != nil {
log.Fatal().Err(err).Msg("alter collection failed")
}
client.Transact(cmd.Context(), args[0], func(ctx context.Context, tx driver.Tx) {
iterateInput(ctx, 1, args, func(ctx context.Context, args []string, docs []json.RawMessage) {
for _, v := range docs {
createCollection(ctx, tx, driver.Schema(v))
}
})
})
},
}

Expand Down
3 changes: 1 addition & 2 deletions cmd/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,9 @@ import (
var createCmd = &cobra.Command{
Use: "create",
Short: "creates database or collection",
Long: "creates database or collection",
Args: cobra.MinimumNArgs(1),
}

func init() {
rootCmd.AddCommand(createCmd)
dbCmd.AddCommand(createCmd)
}
Loading

0 comments on commit e431d6d

Please sign in to comment.