From dc235bae7f05823c58bbeb0fcc7e1bf17b31a336 Mon Sep 17 00:00:00 2001 From: Yevgeniy Firsov Date: Wed, 13 Apr 2022 22:00:22 -0700 Subject: [PATCH 1/7] doc: installation instruction --- README.md | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 09016d4..d0a22a4 100644 --- a/README.md +++ b/README.md @@ -5,20 +5,32 @@ # Install +## macOS + ```sh -go install github.com/tigrisdata/tigrisdb-cli@latest +curl -sSL https://github.com/tigrisdata/tigrisdb-cli/releases/download/v1.0.0-alpha.4/tigris-v1.0.0-alpha.4-darwin-amd64.tar.gz | sudo tar -xz -C /usr/local/bin +``` + +## Linux + +```sh +curl -sSL https://github.com/tigrisdata/tigrisdb-cli/releases/download/v1.0.0-alpha.4/tigris-v1.0.0-alpha.4-linux-amd64.tar.gz | sudo tar -xz -C /usr/local/bin ``` # Example ```sh +tigris db local up # brings local TigrisDB up on localhost:8081 + tigris db create database db1 -tigris db create collection db1 \ - '{ "name" : "coll1", "properties": { - "Key1": { "type": "string" }, - "Field1": { "type": "int" } }, - "primary_key": ["Key1"] - }' +tigris db create collection db1 '{ + "name" : "coll1", + "properties": { + "Key1": { "type": "string" }, + "Field1": { "type": "integer" } + }, + "primary_key": ["Key1"] +}' tigris db list databases tigris db list collections db1 @@ -52,6 +64,8 @@ tigris db read "db1" "coll1" '{}' tigris db drop collection db1 coll1 tigris db drop database db1 + +tigris db local down ``` # License From 8153ee8001fac86ff277c31f57bb62b2fa2c2c2b Mon Sep 17 00:00:00 2001 From: Yevgeniy Firsov Date: Thu, 14 Apr 2022 10:38:27 -0700 Subject: [PATCH 2/7] fix: use latest image build by default --- cmd/local.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/local.go b/cmd/local.go index 9f89176..8733063 100644 --- a/cmd/local.go +++ b/cmd/local.go @@ -45,7 +45,7 @@ const ( ContainerName = "tigrisdb-local-server" ) -var ImageTag = "1.0.0-alpha.7" +var ImageTag = "latest" func ensureVolume(cli *client.Client) { ctx := context.Background() From 8a81582a2b626cda323904782dfadb32ea3c5979 Mon Sep 17 00:00:00 2001 From: Yevgeniy Firsov Date: Thu, 21 Apr 2022 20:55:51 -0700 Subject: [PATCH 3/7] fix: handle empty lines in streams Allow to skip explicit '-' for stdin from non-interactive input --- cmd/collection.go | 12 ++++++------ cmd/insert.go | 6 +++--- cmd/iterate.go | 34 ++++++++++++++++++++++------------ cmd/replace.go | 6 +++--- cmd/transact.go | 6 +++--- tests/db.sh | 17 ++++++++++------- util/util.go | 7 ++++++- 7 files changed, 53 insertions(+), 35 deletions(-) diff --git a/cmd/collection.go b/cmd/collection.go index 49b86d4..a75dd34 100644 --- a/cmd/collection.go +++ b/cmd/collection.go @@ -36,7 +36,7 @@ func createCollection(ctx context.Context, tx driver.Tx, raw driver.Schema) { if schema.Name == "" { util.Error(fmt.Errorf("schema name is missing"), "create collection failed") } - err := tx.CreateOrUpdateCollection(ctx, schema.Name, driver.Schema(raw)) + err := tx.CreateOrUpdateCollection(ctx, schema.Name, raw) if err != nil { util.Error(err, "create collection failed") } @@ -62,10 +62,10 @@ var listCollectionsCmd = &cobra.Command{ var createCollectionCmd = &cobra.Command{ Use: "collection {db} {schema}...|-", Short: "create collection(s)", - Args: cobra.MinimumNArgs(2), + Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { 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) { + iterateInput(ctx, cmd, 1, args, func(ctx context.Context, args []string, docs []json.RawMessage) { for _, v := range docs { createCollection(ctx, tx, driver.Schema(v)) } @@ -80,7 +80,7 @@ var dropCollectionCmd = &cobra.Command{ Args: cobra.MinimumNArgs(2), Run: func(cmd *cobra.Command, args []string) { 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) { + iterateInput(ctx, cmd, 1, args, func(ctx context.Context, args []string, docs []json.RawMessage) { for _, v := range docs { err := tx.DropCollection(ctx, string(v)) if err != nil { @@ -95,10 +95,10 @@ var dropCollectionCmd = &cobra.Command{ var alterCollectionCmd = &cobra.Command{ Use: "collection {db} {collection} {schema}", Short: "update collection schema", - Args: cobra.MinimumNArgs(3), + Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { 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) { + iterateInput(ctx, cmd, 1, args, func(ctx context.Context, args []string, docs []json.RawMessage) { for _, v := range docs { createCollection(ctx, tx, driver.Schema(v)) } diff --git a/cmd/insert.go b/cmd/insert.go index db909b9..c52e631 100644 --- a/cmd/insert.go +++ b/cmd/insert.go @@ -26,13 +26,13 @@ import ( ) var insertCmd = &cobra.Command{ - Use: "insert {db} {collection} {document}...|{-}", + Use: "insert {db} {collection} {document}...|-", Short: "insert document", Long: `insert one or multiple documents from command line or standard input`, - Args: cobra.MinimumNArgs(3), + Args: cobra.MinimumNArgs(2), Run: func(cmd *cobra.Command, args []string) { - iterateInput(cmd.Context(), 2, args, func(ctx context.Context, args []string, docs []json.RawMessage) { + iterateInput(cmd.Context(), cmd, 2, args, func(ctx context.Context, args []string, docs []json.RawMessage) { ptr := unsafe.Pointer(&docs) _, err := client.Get().Insert(ctx, args[0], args[1], *(*[]driver.Document)(ptr)) if err != nil { diff --git a/cmd/iterate.go b/cmd/iterate.go index 295ae55..5949287 100644 --- a/cmd/iterate.go +++ b/cmd/iterate.go @@ -19,11 +19,14 @@ import ( "bytes" "context" "encoding/json" + "fmt" "io" "io/ioutil" "os" + "strings" "unicode" + "github.com/spf13/cobra" "github.com/tigrisdata/tigrisdb-cli/util" ) @@ -70,6 +73,9 @@ func iterateStream(ctx context.Context, args []string, r io.Reader, fn func(ctx2 docs := make([]json.RawMessage, 0, BatchSize) var i int32 for ; i < BatchSize && s.Scan(); i++ { + if len(s.Bytes()) == 0 || len(strings.TrimSpace(s.Text())) == 0 { + continue + } docs = append(docs, s.Bytes()) } if i > 0 { @@ -85,8 +91,22 @@ func iterateStream(ctx context.Context, args []string, r io.Reader, fn func(ctx2 // iterateInput reads repeated command parameters from standard input or args // Support newline delimited stream of objects and arrays of objects -func iterateInput(ctx context.Context, docsPosition int, args []string, fn func(ctx2 context.Context, args []string, docs []json.RawMessage)) { - if args[docsPosition] == "-" { +func iterateInput(ctx context.Context, cmd *cobra.Command, docsPosition int, args []string, fn func(ctx2 context.Context, args []string, docs []json.RawMessage)) { + if len(args) > docsPosition && args[docsPosition] != "-" { + docs := make([]json.RawMessage, 0, len(args)) + for _, v := range args[docsPosition:] { + if detectArray(bufio.NewReader(bytes.NewReader([]byte(v)))) { + docs = append(docs, iterateArray([]byte(v))...) + } else { + docs = append(docs, json.RawMessage(v)) + } + } + fn(ctx, args, docs) + } else if len(args) <= docsPosition && util.IsTTY(os.Stdin) { + fmt.Fprintf(os.Stderr, "not enougn arguments\n") + _ = cmd.Usage() + os.Exit(1) + } else { r := bufio.NewReader(os.Stdin) if detectArray(r) { buf, err := ioutil.ReadAll(r) @@ -98,15 +118,5 @@ func iterateInput(ctx context.Context, docsPosition int, args []string, fn func( } else { iterateStream(ctx, args, r, fn) } - } else { - docs := make([]json.RawMessage, 0, len(args)) - for _, v := range args[docsPosition:] { - if detectArray(bufio.NewReader(bytes.NewReader([]byte(v)))) { - docs = append(docs, iterateArray([]byte(v))...) - } else { - docs = append(docs, json.RawMessage(v)) - } - } - fn(ctx, args, docs) } } diff --git a/cmd/replace.go b/cmd/replace.go index 226fbf9..4289d99 100644 --- a/cmd/replace.go +++ b/cmd/replace.go @@ -26,14 +26,14 @@ import ( ) var replaceCmd = &cobra.Command{ - Use: "replace {db} {collection} {document}...|{-}", + Use: "replace {db} {collection} {document}...|-", Aliases: []string{"insert_or_replace"}, Short: "replace document", Long: `replace or insert one or multiple documents from command line or standard input`, - Args: cobra.MinimumNArgs(3), + Args: cobra.MinimumNArgs(2), Run: func(cmd *cobra.Command, args []string) { - iterateInput(cmd.Context(), 2, args, func(ctx context.Context, args []string, docs []json.RawMessage) { + iterateInput(cmd.Context(), cmd, 2, args, func(ctx context.Context, args []string, docs []json.RawMessage) { ptr := unsafe.Pointer(&docs) _, err := client.Get().Replace(ctx, args[0], args[1], *(*[]driver.Document)(ptr)) if err != nil { diff --git a/cmd/transact.go b/cmd/transact.go index 794f65d..a101c6d 100644 --- a/cmd/transact.go +++ b/cmd/transact.go @@ -116,16 +116,16 @@ func execTxOp(ctx context.Context, db string, tp string, op *Op) { } var transactCmd = &cobra.Command{ - Use: "transact {db} begin|commit|rollback|{operation}...|-", + Use: "transact {db} {operation}...|-", Aliases: []string{"tx"}, Short: "run a set of operations in a transaction", Long: `Run a set of operations in a transaction Operations can be provided in the command line or from standard input`, - Args: cobra.MinimumNArgs(2), + Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { db := args[0] client.Transact(cmd.Context(), db, func(ctx context.Context, tx driver.Tx) { - iterateInput(cmd.Context(), 1, args, func(ctx context.Context, args []string, ops []json.RawMessage) { + iterateInput(ctx, cmd, 1, args, func(ctx context.Context, args []string, ops []json.RawMessage) { for _, iop := range ops { var op TxOp if err := json.Unmarshal(iop, &op); err != nil { diff --git a/tests/db.sh b/tests/db.sh index 28f4287..26503d0 100644 --- a/tests/db.sh +++ b/tests/db.sh @@ -35,11 +35,14 @@ db_tests() { '{ "name" : "coll111", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" } }, "primary_key": ["Key1"] }' #reading schemas from stream - echo '{ "name" : "coll2", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" }, "Field2": { "type": "integer" } }, "primary_key": ["Key1"] }' | $cli create collection db1 - + # \n at the end to test empty line skipping + echo -e '{ "name" : "coll2", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" }, "Field2": { "type": "integer" } }, "primary_key": ["Key1"] }\n \n\n' | $cli create collection db1 - #reading array of schemas echo '[{ "name" : "coll3", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" } }, "primary_key": ["Key1"] }, { "name" : "coll4", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" } }, "primary_key": ["Key1"] }]' | $cli create collection db1 - -#reading schemas from command line array + #reading schemas from command line array $cli create collection db1 '[{ "name" : "coll5", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" } }, "primary_key": ["Key1"] }, { "name" : "coll6", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" } }, "primary_key": ["Key1"] }]' '{ "name" : "coll7", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" } }, "primary_key": ["Key1"] }' + # allow to skip - in non interactive input + $cli create collection db1 <<< '[{ "name" : "coll8", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" } }, "primary_key": ["Key1"] }, { "name" : "coll9", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" } }, "primary_key": ["Key1"] }]' #FIXME: implement after server implements it #$cli describe collection db1 coll1 @@ -65,13 +68,13 @@ db_tests() { '[{"Key1": "vK2", "Field1": 10}]' #insert from standard input stream - cat < Date: Mon, 25 Apr 2022 17:13:09 -0700 Subject: [PATCH 4/7] feat: add generate sample-schema command (#27) * feat: add generate sample-schema command * fix test --- cmd/collection.go | 6 +- cmd/generate.go | 144 ++++++++++++++++++++++++++++++++++++++++++++++ tests/db.sh | 36 ++++++------ 3 files changed, 165 insertions(+), 21 deletions(-) create mode 100644 cmd/generate.go diff --git a/cmd/collection.go b/cmd/collection.go index a75dd34..a5d7135 100644 --- a/cmd/collection.go +++ b/cmd/collection.go @@ -27,16 +27,16 @@ import ( func createCollection(ctx context.Context, tx driver.Tx, raw driver.Schema) { type Schema struct { - Name string + Title string } var schema Schema if err := json.Unmarshal(raw, &schema); err != nil { util.Error(err, "error parsing collection schema") } - if schema.Name == "" { + if schema.Title == "" { util.Error(fmt.Errorf("schema name is missing"), "create collection failed") } - err := tx.CreateOrUpdateCollection(ctx, schema.Name, raw) + err := tx.CreateOrUpdateCollection(ctx, schema.Title, raw) if err != nil { util.Error(err, "create collection failed") } diff --git a/cmd/generate.go b/cmd/generate.go new file mode 100644 index 0000000..6a38732 --- /dev/null +++ b/cmd/generate.go @@ -0,0 +1,144 @@ +package cmd + +import ( + "fmt" + "github.com/spf13/cobra" + "github.com/tigrisdata/tigrisdb-cli/util" + "io/ioutil" + "os" +) + +var schemas = map[string][]byte{ + "products": []byte(`{ + "title": "products", + "description": "Collection of documents with details of products available", + "properties": { + "id": { + "description": "A unique identifier for the product", + "type": "integer" + }, + "name": { + "description": "Name of the product", + "type": "string", + "maxLength": 100 + }, + "quantity": { + "description": "Number of products available in the store", + "type": "integer" + }, + "price": { + "description": "Price of the product", + "type": "number" + } + }, + "primary_key": ["id"] +}`), + "users": []byte(`{ + "title": "users", + "description": "Collection of documents with details of users", + "properties": { + "id": { + "description": "A unique identifier for the user", + "type": "integer" + }, + "name": { + "description": "Name of the user", + "type": "string", + "maxLength": 100 + }, + "balance": { + "description": "User account balance", + "type": "number" + }, + "languages": { + "description": "Languages spoken by the user", + "type": "array", + "items": { + "type": "string" + } + }, + "address": { + "description": "Street address of the user", + "type": "object", + "properties": { + "street": { + "description": "Street number", + "type": "string" + }, + "city": { + "description": "Name of the city", + "type": "string" + }, + "state": { + "description": "Name of the state", + "type": "string" + }, + "zip": { + "description": "The zip code", + "type": "integer" + } + } + } + }, + "primary_key": ["id"] +}`), + "orders": []byte(`{ + "title": "orders", + "description": "Collection of documents with details of an order", + "properties": { + "id": { + "description": "A unique identifier for the order", + "type": "integer" + }, + "user_id": { + "description": "The identifier of the user that placed the order", + "type": "integer" + }, + "order_total": { + "description": "The total cost of the order", + "type": "number" + }, + "products": { + "description": "The list of products that are part of this order", + "type": "array", + "items": { + "type": "object", + "name": "product_item", + "properties": { + "id": { + "description": "The product identifier", + "type": "integer" + }, + "quantity": { + "description": "The quantity of this product in this order", + "type": "integer" + } + } + } + } + }, + "primary_key": ["id"] +}`), +} + +var sampleSchemaCmd = &cobra.Command{ + Use: "sample-schema", + Short: "Generate sample schema consisting of three collections: products, users, orders", + Run: func(cmd *cobra.Command, args []string) { + for name, schema := range schemas { + if err := ioutil.WriteFile(fmt.Sprintf("%v.json", name), schema, os.ModePerm); err != nil { + util.Error(err, "error generating sample schema file") + } + } + }, +} + +var generateCmd = &cobra.Command{ + Use: "generate", + Short: "Generating helper assets such as sample schema", +} + +func init() { + generateCmd.AddCommand(sampleSchemaCmd) + dbCmd.AddCommand(generateCmd) +} diff --git a/tests/db.sh b/tests/db.sh index 26503d0..2688803 100644 --- a/tests/db.sh +++ b/tests/db.sh @@ -31,18 +31,18 @@ db_tests() { #reading schemas from command line parameters $cli create collection db1 \ - '{ "name" : "coll1", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" }, "Field2": { "type": "integer" } }, "primary_key": ["Key1"] }' \ - '{ "name" : "coll111", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" } }, "primary_key": ["Key1"] }' + '{ "title" : "coll1", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" }, "Field2": { "type": "integer" } }, "primary_key": ["Key1"] }' \ + '{ "title" : "coll111", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" } }, "primary_key": ["Key1"] }' #reading schemas from stream # \n at the end to test empty line skipping - echo -e '{ "name" : "coll2", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" }, "Field2": { "type": "integer" } }, "primary_key": ["Key1"] }\n \n\n' | $cli create collection db1 - + echo -e '{ "title" : "coll2", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" }, "Field2": { "type": "integer" } }, "primary_key": ["Key1"] }\n \n\n' | $cli create collection db1 - #reading array of schemas - echo '[{ "name" : "coll3", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" } }, "primary_key": ["Key1"] }, { "name" : "coll4", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" } }, "primary_key": ["Key1"] }]' | $cli create collection db1 - + echo '[{ "title" : "coll3", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" } }, "primary_key": ["Key1"] }, { "title" : "coll4", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" } }, "primary_key": ["Key1"] }]' | $cli create collection db1 - #reading schemas from command line array - $cli create collection db1 '[{ "name" : "coll5", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" } }, "primary_key": ["Key1"] }, { "name" : "coll6", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" } }, "primary_key": ["Key1"] }]' '{ "name" : "coll7", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" } }, "primary_key": ["Key1"] }' + $cli create collection db1 '[{ "title" : "coll5", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" } }, "primary_key": ["Key1"] }, { "title" : "coll6", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" } }, "primary_key": ["Key1"] }]' '{ "title" : "coll7", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" } }, "primary_key": ["Key1"] }' # allow to skip - in non interactive input - $cli create collection db1 <<< '[{ "name" : "coll8", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" } }, "primary_key": ["Key1"] }, { "name" : "coll9", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" } }, "primary_key": ["Key1"] }]' + $cli create collection db1 <<< '[{ "title" : "coll8", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" } }, "primary_key": ["Key1"] }, { "title" : "coll9", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" } }, "primary_key": ["Key1"] }]' #FIXME: implement after server implements it #$cli describe collection db1 coll1 @@ -210,22 +210,22 @@ error() { # shellcheck disable=SC2086 db_errors_tests() { error "database doesn't exists 'db2'" $cli drop database db2 - error "database doesn't exists 'db2'" $cli drop collection db2 coll1 + error "database doesn't exist 'db2'" $cli drop collection db2 coll1 - error "database doesn't exists 'db2'" $cli create collection db2 \ - '{ "name" : "coll1", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" }, "Field2": { "type": "integer" } }, "primary_key": ["Key1"] }' + error "database doesn't exist 'db2'" $cli create collection db2 \ + '{ "title" : "coll1", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" }, "Field2": { "type": "integer" } }, "primary_key": ["Key1"] }' - error "database doesn't exists 'db2'" $cli list collections db2 - error "database doesn't exists 'db2'" $cli insert db2 coll1 '{}' - error "database doesn't exists 'db2'" $cli read db2 coll1 '{}' - error "database doesn't exists 'db2'" $cli update db2 coll1 '{}' '{}' - error "database doesn't exists 'db2'" $cli delete db2 coll1 '{}' + error "database doesn't exist 'db2'" $cli list collections db2 + error "database doesn't exist 'db2'" $cli insert db2 coll1 '{}' + error "database doesn't exist 'db2'" $cli read db2 coll1 '{}' + error "database doesn't exist 'db2'" $cli update db2 coll1 '{}' '{}' + error "database doesn't exist 'db2'" $cli delete db2 coll1 '{}' $cli create database db2 - error "collection doesn't exists 'coll1'" $cli insert db2 coll1 '{}' - error "collection doesn't exists 'coll1'" $cli read db2 coll1 '{}' - error "collection doesn't exists 'coll1'" $cli update db2 coll1 '{}' '{}' - error "collection doesn't exists 'coll1'" $cli delete db2 coll1 '{}' + error "collection doesn't exist 'coll1'" $cli insert db2 coll1 '{}' + error "collection doesn't exist 'coll1'" $cli read db2 coll1 '{}' + error "collection doesn't exist 'coll1'" $cli update db2 coll1 '{}' '{}' + error "collection doesn't exist 'coll1'" $cli delete db2 coll1 '{}' error "schema name is missing" $cli create collection db1 \ '{ "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" }, "Field2": { "type": "integer" } }, "primary_key": ["Key1"] }' From 35c4061db5a145c965984c9cb6de7abd917dba4e Mon Sep 17 00:00:00 2001 From: Ovais Tariq Date: Mon, 25 Apr 2022 18:17:44 -0700 Subject: [PATCH 5/7] feat: allow the user to be able to create the sample schema (#28) * allow the user to be able to create the sample schema * add tests for generate sample schema cmd --- .gitignore | 4 ++++ cmd/generate.go | 31 +++++++++++++++++++++++++++---- cmd/local.go | 2 +- cmd/version.go | 2 +- tests/db.sh | 6 ++++++ 5 files changed, 39 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index e3ccf5e..f53d8fa 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,10 @@ *.so *.dylib tigrisdb-cli +tigris + +# JSON files +*.json # Test binary, built with `go test -c` *.test diff --git a/cmd/generate.go b/cmd/generate.go index 6a38732..950b57e 100644 --- a/cmd/generate.go +++ b/cmd/generate.go @@ -1,13 +1,17 @@ package cmd import ( + "context" "fmt" "github.com/spf13/cobra" + "github.com/tigrisdata/tigrisdb-cli/client" "github.com/tigrisdata/tigrisdb-cli/util" + "github.com/tigrisdata/tigrisdb-client-go/driver" "io/ioutil" - "os" ) +const sampleDBName = "sampledb" + var schemas = map[string][]byte{ "products": []byte(`{ "title": "products", @@ -125,9 +129,27 @@ var sampleSchemaCmd = &cobra.Command{ Use: "sample-schema", Short: "Generate sample schema consisting of three collections: products, users, orders", Run: func(cmd *cobra.Command, args []string) { - for name, schema := range schemas { - if err := ioutil.WriteFile(fmt.Sprintf("%v.json", name), schema, os.ModePerm); err != nil { - util.Error(err, "error generating sample schema file") + create, err := cmd.Flags().GetBool("create") + if err != nil { + util.Error(err, "error reading the 'create' option") + } + + if create { + if err := client.Get().CreateDatabase(cmd.Context(), sampleDBName); err != nil { + util.Error(err, "create database failed") + } + client.Transact(cmd.Context(), sampleDBName, func(ctx context.Context, tx driver.Tx) { + for _, schema := range schemas { + createCollection(ctx, tx, schema) + } + }) + + util.Stdout("%v created with the collections", sampleDBName) + } else { + for name, schema := range schemas { + if err := ioutil.WriteFile(fmt.Sprintf("%v.json", name), schema, 0644); err != nil { + util.Error(err, "error generating sample schema file") + } } } }, @@ -139,6 +161,7 @@ var generateCmd = &cobra.Command{ } func init() { + sampleSchemaCmd.Flags().BoolP("create", "c", false, "create the sample database and collections") generateCmd.AddCommand(sampleSchemaCmd) dbCmd.AddCommand(generateCmd) } diff --git a/cmd/local.go b/cmd/local.go index 8733063..d2454bf 100644 --- a/cmd/local.go +++ b/cmd/local.go @@ -266,7 +266,7 @@ var serverLogsCmd = &cobra.Command{ follow, err := cmd.Flags().GetBool("follow") if err != nil { - util.Error(err, "error getting 'follow' flag") + util.Error(err, "error reading 'follow' option") } logs, err := cli.ContainerLogs(ctx, ContainerName, types.ContainerLogsOptions{ diff --git a/cmd/version.go b/cmd/version.go index 448fc46..5b1548b 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -23,7 +23,7 @@ var versionCmd = &cobra.Command{ Use: "version", Short: "show tigrisdb-cli version", Run: func(cmd *cobra.Command, args []string) { - util.Stdout("tigrisdb-cli version %s\n", util.Version) + util.Stdout("tigris version %s\n", util.Version) }, } diff --git a/tests/db.sh b/tests/db.sh index 2688803..3eff9ca 100644 --- a/tests/db.sh +++ b/tests/db.sh @@ -172,6 +172,7 @@ EOF db_negative_tests db_errors_tests + db_generate_schema_test $cli drop collection db1 coll1 coll2 coll3 coll4 coll5 coll6 coll7 $cli drop database db1 @@ -233,6 +234,11 @@ db_errors_tests() { $cli drop database db2 } +db_generate_schema_test() { + error "sampledb created with the collections" $cli generate sample-schema --create + $cli drop database sampledb +} + unset TIGRISDB_PROTOCOL unset TIGRISDB_URL db_tests From 91f7e344434850540b9bd5268707689e40220e55 Mon Sep 17 00:00:00 2001 From: Yevgeniy Firsov Date: Mon, 25 Apr 2022 19:38:16 -0700 Subject: [PATCH 6/7] feat: describe database and collection API --- README.md | 4 ++-- cmd/collection.go | 42 +++++++++++++++++++++++++++++--- cmd/database.go | 61 +++++++++++++++++++++++++++++++++++++++++++++-- cmd/describe.go | 29 ++++++++++++++++++++++ cmd/generate.go | 16 ++++++++++--- cmd/iterate.go | 16 ++++++------- cmd/read.go | 2 +- cmd/transact.go | 4 ++-- cmd/update.go | 2 +- go.mod | 2 +- go.sum | 4 ++-- tests/db.sh | 23 ++++++++++++------ 12 files changed, 172 insertions(+), 33 deletions(-) create mode 100644 cmd/describe.go diff --git a/README.md b/README.md index d0a22a4..826c2eb 100644 --- a/README.md +++ b/README.md @@ -8,13 +8,13 @@ ## macOS ```sh -curl -sSL https://github.com/tigrisdata/tigrisdb-cli/releases/download/v1.0.0-alpha.4/tigris-v1.0.0-alpha.4-darwin-amd64.tar.gz | sudo tar -xz -C /usr/local/bin +curl -sSL https://tigris.dev/cli-macos | sudo tar -xz -C /usr/local/bin ``` ## Linux ```sh -curl -sSL https://github.com/tigrisdata/tigrisdb-cli/releases/download/v1.0.0-alpha.4/tigris-v1.0.0-alpha.4-linux-amd64.tar.gz | sudo tar -xz -C /usr/local/bin +curl -sSL https://tigris.dev/cli-linux | sudo tar -xz -C /usr/local/bin ``` # Example diff --git a/cmd/collection.go b/cmd/collection.go index a5d7135..cd3e992 100644 --- a/cmd/collection.go +++ b/cmd/collection.go @@ -22,26 +22,61 @@ import ( "github.com/spf13/cobra" "github.com/tigrisdata/tigrisdb-cli/client" "github.com/tigrisdata/tigrisdb-cli/util" + api "github.com/tigrisdata/tigrisdb-client-go/api/server/v1" "github.com/tigrisdata/tigrisdb-client-go/driver" ) func createCollection(ctx context.Context, tx driver.Tx, raw driver.Schema) { type Schema struct { - Title string + Name string `json:"title"` } var schema Schema if err := json.Unmarshal(raw, &schema); err != nil { util.Error(err, "error parsing collection schema") } - if schema.Title == "" { + if schema.Name == "" { util.Error(fmt.Errorf("schema name is missing"), "create collection failed") } - err := tx.CreateOrUpdateCollection(ctx, schema.Title, raw) + err := tx.CreateOrUpdateCollection(ctx, schema.Name, raw) if err != nil { util.Error(err, "create collection failed") } } +type DescribeCollectionResponse struct { + Collection string `json:"collection,omitempty"` + Metadata *api.CollectionMetadata `json:"metadata,omitempty"` + Schema json.RawMessage `json:"schema,omitempty"` +} + +var describeCollectionCmd = &cobra.Command{ + Use: "collection {db} {collection}", + Short: "describe collection", + Long: "describe collection returns collection metadata, including schema", + Args: cobra.MinimumNArgs(2), + Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := util.GetContext(cmd.Context()) + defer cancel() + resp, err := client.Get().DescribeCollection(ctx, args[0], args[1]) + if err != nil { + util.Error(err, "describe collection failed") + } + + tr := DescribeCollectionResponse{ + Collection: resp.Collection, + Metadata: resp.Metadata, + Schema: resp.Schema, + } + + b, err := json.Marshal(tr) + if err != nil { + util.Error(err, "describe collection failed") + } + + util.Stdout("%s\n", string(b)) + }, +} + var listCollectionsCmd = &cobra.Command{ Use: "collections {db}", Short: "list database collections", @@ -112,4 +147,5 @@ func init() { createCmd.AddCommand(createCollectionCmd) listCmd.AddCommand(listCollectionsCmd) alterCmd.AddCommand(alterCollectionCmd) + describeCmd.AddCommand(describeCollectionCmd) } diff --git a/cmd/database.go b/cmd/database.go index 873ca37..eea0c80 100644 --- a/cmd/database.go +++ b/cmd/database.go @@ -15,9 +15,12 @@ package cmd import ( + "encoding/json" + "github.com/spf13/cobra" "github.com/tigrisdata/tigrisdb-cli/client" "github.com/tigrisdata/tigrisdb-cli/util" + api "github.com/tigrisdata/tigrisdb-client-go/api/server/v1" ) var listDatabasesCmd = &cobra.Command{ @@ -36,10 +39,62 @@ var listDatabasesCmd = &cobra.Command{ }, } +type DescribeDatabaseResponse struct { + Db string `json:"db,omitempty"` + Metadata *api.DatabaseMetadata `json:"metadata,omitempty"` + Collections []*DescribeCollectionResponse `json:"collections,omitempty"` +} + +var describeDatabaseCmd = &cobra.Command{ + Use: "database {db}", + Short: "describe database", + Long: "describe database returns metadata for all the collections in the database", + Args: cobra.ExactArgs(1), + Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := util.GetContext(cmd.Context()) + defer cancel() + resp, err := client.Get().DescribeDatabase(ctx, args[0]) + if err != nil { + util.Error(err, "describe collection failed") + } + + schemaOnly, err := cmd.Flags().GetBool("schema-only") + if err != nil { + util.Error(err, "error reading the 'schema-only' option") + } + + if schemaOnly { + for _, v := range resp.Collections { + util.Stdout("%s\n", string(v.Schema)) + } + } else { + tr := DescribeDatabaseResponse{ + Db: resp.Db, + Metadata: resp.Metadata, + } + + for _, v := range resp.Collections { + tr.Collections = append(tr.Collections, &DescribeCollectionResponse{ + Collection: v.Collection, + Metadata: v.Metadata, + Schema: v.Schema, + }) + } + + b, err := json.Marshal(tr) + if err != nil { + util.Error(err, "describe database failed") + } + + util.Stdout("%s\n", string(b)) + } + }, +} + var createDatabaseCmd = &cobra.Command{ Use: "database {db}", Short: "create database", - Args: cobra.MinimumNArgs(1), + Args: cobra.ExactArgs(1), Run: func(cmd *cobra.Command, args []string) { ctx, cancel := util.GetContext(cmd.Context()) defer cancel() @@ -53,7 +108,7 @@ var createDatabaseCmd = &cobra.Command{ var dropDatabaseCmd = &cobra.Command{ Use: "database {db}", Short: "drop database", - Args: cobra.MinimumNArgs(1), + Args: cobra.ExactArgs(1), Run: func(cmd *cobra.Command, args []string) { ctx, cancel := util.GetContext(cmd.Context()) defer cancel() @@ -65,7 +120,9 @@ var dropDatabaseCmd = &cobra.Command{ } func init() { + describeDatabaseCmd.Flags().BoolP("schema-only", "s", false, "dump only schema of all database collections") dropCmd.AddCommand(dropDatabaseCmd) createCmd.AddCommand(createDatabaseCmd) listCmd.AddCommand(listDatabasesCmd) + describeCmd.AddCommand(describeDatabaseCmd) } diff --git a/cmd/describe.go b/cmd/describe.go new file mode 100644 index 0000000..eb78980 --- /dev/null +++ b/cmd/describe.go @@ -0,0 +1,29 @@ +// Copyright 2022 Tigris Data, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "github.com/spf13/cobra" +) + +var describeCmd = &cobra.Command{ + Use: "describe", + Short: "describe database or collection", + Args: cobra.MinimumNArgs(1), +} + +func init() { + dbCmd.AddCommand(describeCmd) +} diff --git a/cmd/generate.go b/cmd/generate.go index 950b57e..395dffe 100644 --- a/cmd/generate.go +++ b/cmd/generate.go @@ -3,11 +3,12 @@ package cmd import ( "context" "fmt" + "io/ioutil" + "github.com/spf13/cobra" "github.com/tigrisdata/tigrisdb-cli/client" "github.com/tigrisdata/tigrisdb-cli/util" "github.com/tigrisdata/tigrisdb-client-go/driver" - "io/ioutil" ) const sampleDBName = "sampledb" @@ -146,9 +147,17 @@ var sampleSchemaCmd = &cobra.Command{ util.Stdout("%v created with the collections", sampleDBName) } else { + stdout, err := cmd.Flags().GetBool("stdout") + if err != nil { + util.Error(err, "error reading the 'stdout' option") + } for name, schema := range schemas { - if err := ioutil.WriteFile(fmt.Sprintf("%v.json", name), schema, 0644); err != nil { - util.Error(err, "error generating sample schema file") + if stdout { + util.Stdout("%s\n", string(schema)) + } else { + if err := ioutil.WriteFile(fmt.Sprintf("%v.json", name), schema, 0644); err != nil { + util.Error(err, "error generating sample schema file") + } } } } @@ -162,6 +171,7 @@ var generateCmd = &cobra.Command{ func init() { sampleSchemaCmd.Flags().BoolP("create", "c", false, "create the sample database and collections") + sampleSchemaCmd.Flags().BoolP("stdout", "s", false, "dump sample schemas to stdout") generateCmd.AddCommand(sampleSchemaCmd) dbCmd.AddCommand(generateCmd) } diff --git a/cmd/iterate.go b/cmd/iterate.go index 5949287..4c392a4 100644 --- a/cmd/iterate.go +++ b/cmd/iterate.go @@ -23,7 +23,6 @@ import ( "io" "io/ioutil" "os" - "strings" "unicode" "github.com/spf13/cobra" @@ -68,15 +67,17 @@ func iterateArray(r []byte) []json.RawMessage { } func iterateStream(ctx context.Context, args []string, r io.Reader, fn func(ctx2 context.Context, args []string, docs []json.RawMessage)) { - s := bufio.NewScanner(r) + dec := json.NewDecoder(r) for { docs := make([]json.RawMessage, 0, BatchSize) var i int32 - for ; i < BatchSize && s.Scan(); i++ { - if len(s.Bytes()) == 0 || len(strings.TrimSpace(s.Text())) == 0 { - continue + for ; i < BatchSize && dec.More(); i++ { + var v json.RawMessage + err := dec.Decode(&v) + if err != nil { + util.Error(err, "reading documents from stream of documents") } - docs = append(docs, s.Bytes()) + docs = append(docs, v) } if i > 0 { fn(ctx, args, docs) @@ -84,9 +85,6 @@ func iterateStream(ctx context.Context, args []string, r io.Reader, fn func(ctx2 break } } - if err := s.Err(); err != nil { - util.Error(err, "reading documents from stdin") - } } // iterateInput reads repeated command parameters from standard input or args diff --git a/cmd/read.go b/cmd/read.go index 7f707a3..5b51b29 100644 --- a/cmd/read.go +++ b/cmd/read.go @@ -40,7 +40,7 @@ if fields is not provided or has special {} value, read returns all the fields o if len(args) > 3 { fields = args[3] } - it, err := client.Get().Read(ctx, args[0], args[1], driver.Filter(filter), driver.Fields(fields)) + it, err := client.Get().Read(ctx, args[0], args[1], driver.Filter(filter), driver.Projection(fields)) if err != nil { util.Error(err, "read documents failed") } diff --git a/cmd/transact.go b/cmd/transact.go index a101c6d..86a8c12 100644 --- a/cmd/transact.go +++ b/cmd/transact.go @@ -70,7 +70,7 @@ func execTxOp(ctx context.Context, db string, tp string, op *Op) { ptr := unsafe.Pointer(&op.Documents) _, err = client.Get().Insert(ctx, db, op.Collection, *(*[]driver.Document)(ptr)) case Update: - _, err = client.Get().Update(ctx, db, op.Collection, driver.Filter(op.Filter), driver.Fields(op.Fields)) + _, err = client.Get().Update(ctx, db, op.Collection, driver.Filter(op.Filter), driver.Update(op.Fields)) case Delete: _, err = client.Get().Delete(ctx, db, op.Collection, driver.Filter(op.Filter)) case Replace, InsertOrReplace: @@ -98,7 +98,7 @@ func execTxOp(ctx context.Context, db string, tp string, op *Op) { if len(op.Fields) > 0 { fields = op.Fields } - it, err := client.Get().Read(ctx, db, op.Collection, driver.Filter(filter), driver.Fields(fields)) + it, err := client.Get().Read(ctx, db, op.Collection, driver.Filter(filter), driver.Projection(fields)) if err != nil { log.Fatal().Err(err).Str("op", op.Operation).Msgf("transact operation failed") } diff --git a/cmd/update.go b/cmd/update.go index ca9c535..4231f93 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -30,7 +30,7 @@ var updateCmd = &cobra.Command{ ctx, cancel := util.GetContext(cmd.Context()) defer cancel() - _, err := client.Get().Update(ctx, args[0], args[1], driver.Filter(args[2]), driver.Fields(args[3])) + _, err := client.Get().Update(ctx, args[0], args[1], driver.Filter(args[2]), driver.Update(args[3])) if err != nil { util.Error(err, "update documents failed") } diff --git a/go.mod b/go.mod index a578a86..7135e3e 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/rs/zerolog v1.26.1 github.com/spf13/cobra v1.4.0 github.com/spf13/viper v1.10.1 - github.com/tigrisdata/tigrisdb-client-go v1.0.0-alpha.4 + github.com/tigrisdata/tigrisdb-client-go v1.0.0-alpha.7 gopkg.in/yaml.v2 v2.4.0 ) diff --git a/go.sum b/go.sum index db24ef3..0a69c52 100644 --- a/go.sum +++ b/go.sum @@ -324,8 +324,8 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/tigrisdata/tigrisdb-client-go v1.0.0-alpha.4 h1:bxmxXRVzsD9vGlFgfpMe1WtWB0wzUV2rE66ir7wacdY= -github.com/tigrisdata/tigrisdb-client-go v1.0.0-alpha.4/go.mod h1:lP4RhNml4kRHULYY+nb+nmvGz0THlwUx9w5BI7Qus7I= +github.com/tigrisdata/tigrisdb-client-go v1.0.0-alpha.7 h1:lt+eoxID4oluG+OMdI6sGAMIDFCFbMwrj7Fdqgqf7k8= +github.com/tigrisdata/tigrisdb-client-go v1.0.0-alpha.7/go.mod h1:lP4RhNml4kRHULYY+nb+nmvGz0THlwUx9w5BI7Qus7I= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= diff --git a/tests/db.sh b/tests/db.sh index 3eff9ca..b23fb33 100644 --- a/tests/db.sh +++ b/tests/db.sh @@ -29,14 +29,26 @@ db_tests() { $cli create database db1 + coll1='{"title":"coll1","properties":{"Key1":{"type":"string"},"Field1":{"type":"integer"},"Field2":{"type":"integer"}},"primary_key":["Key1"]}' + coll111='{"title":"coll111","properties":{"Key1":{"type":"string"},"Field1":{"type":"integer"}},"primary_key":["Key1"]}' + #reading schemas from command line parameters - $cli create collection db1 \ - '{ "title" : "coll1", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" }, "Field2": { "type": "integer" } }, "primary_key": ["Key1"] }' \ - '{ "title" : "coll111", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" } }, "primary_key": ["Key1"] }' + $cli create collection db1 "$coll1" "$coll111" + + out=$($cli describe collection db1 coll1) + diff -w -u <(echo '{"collection":"coll1","metadata":{},"schema":'"$coll1"'}') <(echo "$out") + + out=$($cli describe database db1) + # The output order is not-deterministic, try both combinations: + diff -u <(echo '{"db":"db1","metadata":{},"collections":[{"collection":"coll1","metadata":{},"schema":'"$coll1"'},{"collection":"coll111","metadata":{},"schema":'"$coll111"'}]}') <(echo "$out") || + diff -u <(echo '{"db":"db1","metadata":{},"collections":[{"collection":"coll111","metadata":{},"schema":'"$coll111"'},{"collection":"coll1","metadata":{},"schema":'"$coll1"'}]}') <(echo "$out") #reading schemas from stream # \n at the end to test empty line skipping - echo -e '{ "title" : "coll2", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" }, "Field2": { "type": "integer" } }, "primary_key": ["Key1"] }\n \n\n' | $cli create collection db1 - + # this also test multi-line streams + echo -e '{ "title" : "coll2", + "properties": { "Key1": { "type": "string" }, + "Field1": { "type": "integer" }, "Field2": { "type": "integer" } }, "primary_key": ["Key1"] }\n \n\n' | $cli create collection db1 - #reading array of schemas echo '[{ "title" : "coll3", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" } }, "primary_key": ["Key1"] }, { "title" : "coll4", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" } }, "primary_key": ["Key1"] }]' | $cli create collection db1 - #reading schemas from command line array @@ -44,9 +56,6 @@ db_tests() { # allow to skip - in non interactive input $cli create collection db1 <<< '[{ "title" : "coll8", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" } }, "primary_key": ["Key1"] }, { "title" : "coll9", "properties": { "Key1": { "type": "string" }, "Field1": { "type": "integer" } }, "primary_key": ["Key1"] }]' - #FIXME: implement after server implements it - #$cli describe collection db1 coll1 - $cli list databases $cli list collections db1 From 5213d8ca0faeb0723a7497968c0bc66813dbaa62 Mon Sep 17 00:00:00 2001 From: Yevgeniy Firsov Date: Mon, 25 Apr 2022 22:14:15 -0700 Subject: [PATCH 7/7] fix: removed db subspace BREAKING CHANGE: removed db subspace from all commands --- cmd/db.go | 30 ------------------------------ cmd/root.go | 2 ++ main.go | 2 +- tests/db.sh | 2 +- 4 files changed, 4 insertions(+), 32 deletions(-) delete mode 100644 cmd/db.go diff --git a/cmd/db.go b/cmd/db.go deleted file mode 100644 index 47c36c8..0000000 --- a/cmd/db.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2022 Tigris Data, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package cmd - -import ( - "github.com/spf13/cobra" -) - -var dbCmd = &cobra.Command{ - Use: "db", - Short: "Database related commands", - Long: `Database related commands. -Inluding database, collection and documents management`, -} - -func init() { - rootCmd.AddCommand(dbCmd) -} diff --git a/cmd/root.go b/cmd/root.go index d40dd20..adb4913 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -25,6 +25,8 @@ var rootCmd = &cobra.Command{ Short: "tigris is a command line interface of TigrisDB database", } +var dbCmd = rootCmd + func Execute() { err := rootCmd.Execute() if err != nil { diff --git a/main.go b/main.go index 24dd46f..634f8ea 100644 --- a/main.go +++ b/main.go @@ -30,7 +30,7 @@ func main() { util.DefaultTimeout = config.DefaultConfig.Timeout - if len(os.Args) > 2 && (os.Args[1] == "db" && os.Args[2] != "local") { + if len(os.Args) > 1 && (os.Args[1] != "local") { if err := client.Init(config.DefaultConfig); err != nil { util.Error(err, "tigrisdb client initialization failed") } diff --git a/tests/db.sh b/tests/db.sh index b23fb33..c90b7a7 100644 --- a/tests/db.sh +++ b/tests/db.sh @@ -15,7 +15,7 @@ set -ex -cli="./tigris db" +cli="./tigris" make