mirror of
https://github.com/dolthub/dolt.git
synced 2026-01-07 00:39:44 -06:00
bh/schema sub commands (#128)
* changed dolt schema to be a command group
This commit is contained in:
@@ -610,8 +610,8 @@ if rows[2] != "9,8,7,6,5,4".split(","):
|
||||
diff --strip-trailing-cr $BATS_TEST_DIRNAME/helper/1pk5col-ints.sql export.sql
|
||||
}
|
||||
|
||||
@test "dolt schema" {
|
||||
run dolt schema
|
||||
@test "dolt schema show" {
|
||||
run dolt schema show
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "test @ working" ]] || false
|
||||
[[ "$output" =~ "CREATE TABLE \`test\`" ]] || false
|
||||
@@ -622,7 +622,7 @@ if rows[2] != "9,8,7,6,5,4".split(","):
|
||||
[[ "$output" =~ "\`c4\` int comment 'tag:4'" ]] || false
|
||||
[[ "$output" =~ "\`c5\` int comment 'tag:5'" ]] || false
|
||||
[[ "$output" =~ "primary key (\`pk\`)" ]] || false
|
||||
run dolt schema test
|
||||
run dolt schema show test
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "test @ working" ]] || false
|
||||
[[ "$output" =~ "CREATE TABLE \`test\`" ]] || false
|
||||
@@ -635,14 +635,14 @@ if rows[2] != "9,8,7,6,5,4".split(","):
|
||||
[[ "$output" =~ "primary key (\`pk\`)" ]] || false
|
||||
}
|
||||
|
||||
@test "dolt schema on non existant table" {
|
||||
run dolt schema foo
|
||||
@test "dolt schema show on non existant table" {
|
||||
run dolt schema show foo
|
||||
[ "$status" -eq 0 ]
|
||||
[ "$output" = "foo not found" ]
|
||||
}
|
||||
|
||||
@test "dolt schema --export" {
|
||||
run dolt schema --export test export.schema
|
||||
@test "dolt schema export" {
|
||||
run dolt schema export test export.schema
|
||||
[ "$status" -eq 0 ]
|
||||
[ "$output" = "" ]
|
||||
[ -f export.schema ]
|
||||
|
||||
@@ -245,14 +245,14 @@ teardown() {
|
||||
run dolt sql -q "describe one_pk"
|
||||
[ $status -eq 0 ]
|
||||
[[ "$output" =~ "c6" ]] || false
|
||||
run dolt schema one_pk
|
||||
run dolt schema show one_pk
|
||||
[[ "$output" =~ "c6" ]] || false
|
||||
run dolt sql -q "alter table one_pk drop column c6"
|
||||
[ $status -eq 0 ]
|
||||
run dolt sql -q "describe one_pk"
|
||||
[ $status -eq 0 ]
|
||||
[[ ! "$output" =~ "c6" ]] || false
|
||||
run dolt schema one_pk
|
||||
run dolt schema show one_pk
|
||||
[[ ! "$output" =~ "c6" ]] || false
|
||||
}
|
||||
|
||||
|
||||
@@ -35,8 +35,8 @@ teardown() {
|
||||
[[ "$output" =~ "BBB" ]] || false
|
||||
}
|
||||
|
||||
@test "capital letter col names. dolt schema" {
|
||||
run dolt schema
|
||||
@test "capital letter col names. dolt schema show" {
|
||||
run dolt schema show
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "Aaa" ]] || false
|
||||
[[ "$output" =~ "Bbb" ]] || false
|
||||
|
||||
@@ -144,11 +144,11 @@ teardown() {
|
||||
dolt add test
|
||||
dolt commit -m "table created"
|
||||
dolt branch add-column
|
||||
dolt schema --add-column test c0 int
|
||||
dolt schema add-column test c0 int
|
||||
dolt add test
|
||||
dolt commit -m "added column c0"
|
||||
dolt checkout add-column
|
||||
dolt schema --add-column test c0 int
|
||||
dolt schema add-column test c0 int
|
||||
dolt add test
|
||||
dolt commit -m "added same column c0"
|
||||
dolt checkout master
|
||||
@@ -163,11 +163,11 @@ teardown() {
|
||||
dolt add test
|
||||
dolt commit -m "table created"
|
||||
dolt branch add-column
|
||||
dolt schema --add-column test c0 int
|
||||
dolt schema add-column test c0 int
|
||||
dolt add test
|
||||
dolt commit -m "added column c0"
|
||||
dolt checkout add-column
|
||||
dolt schema --add-column test c6 int
|
||||
dolt schema add-column test c6 int
|
||||
dolt add test
|
||||
dolt commit -m "added column c6"
|
||||
dolt checkout master
|
||||
@@ -183,11 +183,11 @@ teardown() {
|
||||
dolt add test
|
||||
dolt commit -m "table created"
|
||||
dolt branch add-column
|
||||
dolt schema --add-column test c0 string
|
||||
dolt schema add-column test c0 string
|
||||
dolt add test
|
||||
dolt commit -m "added column c0 as string"
|
||||
dolt checkout add-column
|
||||
dolt schema --add-column test c0 int
|
||||
dolt schema add-column test c0 int
|
||||
dolt add test
|
||||
dolt commit -m "added column c0 as int"
|
||||
dolt checkout master
|
||||
@@ -202,11 +202,11 @@ teardown() {
|
||||
dolt add test
|
||||
dolt commit -m "table created"
|
||||
dolt branch delete-column
|
||||
dolt schema --drop-column test c5
|
||||
dolt schema drop-column test c5
|
||||
dolt add test
|
||||
dolt commit -m "deleted c45 column"
|
||||
dolt checkout delete-column
|
||||
dolt schema --drop-column test c5
|
||||
dolt schema drop-column test c5
|
||||
dolt add test
|
||||
dolt commit -m "deleted c5 again"
|
||||
dolt checkout master
|
||||
@@ -221,11 +221,11 @@ teardown() {
|
||||
dolt add test
|
||||
dolt commit -m "table created"
|
||||
dolt branch delete-column
|
||||
dolt schema --drop-column test c5
|
||||
dolt schema drop-column test c5
|
||||
dolt add test
|
||||
dolt commit -m "deleted column c5"
|
||||
dolt checkout delete-column
|
||||
dolt schema --drop-column test c4
|
||||
dolt schema drop-column test c4
|
||||
dolt add test
|
||||
dolt commit -m "deleted column c4"
|
||||
dolt checkout master
|
||||
@@ -240,11 +240,11 @@ teardown() {
|
||||
dolt add test
|
||||
dolt commit -m "table created"
|
||||
dolt branch rename-column
|
||||
dolt schema --rename-column test c5 c0
|
||||
dolt schema rename-column test c5 c0
|
||||
dolt add test
|
||||
dolt commit -m "renamed c5 to c0"
|
||||
dolt checkout rename-column
|
||||
dolt schema --rename-column test c5 c0
|
||||
dolt schema rename-column test c5 c0
|
||||
dolt add test
|
||||
dolt commit -m "renamed c5 to c0 again"
|
||||
dolt checkout master
|
||||
@@ -259,11 +259,11 @@ teardown() {
|
||||
dolt add test
|
||||
dolt commit -m "table created"
|
||||
dolt branch rename-column
|
||||
dolt schema --rename-column test c5 c0
|
||||
dolt schema rename-column test c5 c0
|
||||
dolt add test
|
||||
dolt commit -m "renamed c5 to c0"
|
||||
dolt checkout rename-column
|
||||
dolt schema --rename-column test c5 c6
|
||||
dolt schema rename-column test c5 c6
|
||||
dolt add test
|
||||
dolt commit -m "renamed c5 to c6"
|
||||
dolt checkout master
|
||||
@@ -280,11 +280,11 @@ teardown() {
|
||||
dolt add test
|
||||
dolt commit -m "table created"
|
||||
dolt branch rename-column
|
||||
dolt schema --rename-column test c5 c0
|
||||
dolt schema rename-column test c5 c0
|
||||
dolt add test
|
||||
dolt commit -m "renamed c5 to c0"
|
||||
dolt checkout rename-column
|
||||
dolt schema --rename-column test c4 c0
|
||||
dolt schema rename-column test c4 c0
|
||||
dolt add test
|
||||
dolt commit -m "renamed c5 to c6"
|
||||
dolt checkout master
|
||||
|
||||
@@ -213,7 +213,7 @@ teardown() {
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "test" ]] || false
|
||||
# use bash -c so I can | the output to grep
|
||||
run bash -c "dolt schema"
|
||||
run bash -c "dolt schema show"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "CREATE TABLE \`test\`" ]] || false
|
||||
[[ "$output" =~ "\`pk\` int not null comment 'tag:0'" ]] || false
|
||||
@@ -229,7 +229,7 @@ teardown() {
|
||||
run dolt sql -q "create table test (pk1 int, pk2 int, c1 int, c2 int, c3 int, c4 int, c5 int, primary key (pk1), primary key (pk2))"
|
||||
[ "$status" -eq 0 ]
|
||||
[ "$output" = "" ]
|
||||
run bash -c "dolt schema"
|
||||
run bash -c "dolt schema show"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "CREATE TABLE \`test\`" ]] || false
|
||||
[[ "$output" =~ "\`pk1\` int not null comment 'tag:0'" ]] || false
|
||||
@@ -246,7 +246,7 @@ teardown() {
|
||||
run dolt sql -q "create table test (pk int not null, c1 int, c2 int, c3 int, c4 int, c5 int, primary key (pk))"
|
||||
[ "$status" -eq 0 ]
|
||||
[ "$output" = "" ]
|
||||
run dolt schema test
|
||||
run dolt schema show test
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "CREATE TABLE \`test\`" ]] || false
|
||||
[[ "$output" =~ "\`pk\` int not null comment 'tag:0'" ]] || false
|
||||
@@ -262,7 +262,7 @@ teardown() {
|
||||
run dolt sql -q "create table test (pk int not null, c1 float, primary key (pk))"
|
||||
[ "$status" -eq 0 ]
|
||||
[ "$output" = "" ]
|
||||
run dolt schema test
|
||||
run dolt schema show test
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "CREATE TABLE \`test\` " ]] || false
|
||||
[[ "$output" =~ "\`pk\` int not null comment 'tag:0'" ]] || false
|
||||
@@ -275,7 +275,7 @@ teardown() {
|
||||
run dolt sql -q "create table test (pk int not null, c1 varchar, primary key (pk))"
|
||||
[ "$status" -eq 0 ]
|
||||
[ "$output" = "" ]
|
||||
run dolt schema test
|
||||
run dolt schema show test
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "CREATE TABLE \`test\`" ]] || false
|
||||
[[ "$output" =~ "\`pk\` int not null comment 'tag:0'" ]] || false
|
||||
@@ -288,7 +288,7 @@ teardown() {
|
||||
run dolt sql -q "create table test (pk int not null, c1 int unsigned, primary key (pk))"
|
||||
[ "$status" -eq 0 ]
|
||||
[ "$output" = "" ]
|
||||
run dolt schema test
|
||||
run dolt schema show test
|
||||
[[ "$output" =~ "int unsigned" ]] || false
|
||||
}
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ teardown() {
|
||||
dolt table import -c -s=`batshelper employees-sch.json` employees `batshelper employees-tbl.json`
|
||||
dolt add employees
|
||||
dolt commit -m "Added employees table with data"
|
||||
dolt schema --add-column employees city string
|
||||
dolt schema add-column employees city string
|
||||
dolt table put-row employees id:3 "first name":taylor "last name":bantle title:"software engineer" "start date":"" "end date":"" city:"Santa Monica"
|
||||
run dolt diff --summary
|
||||
[ "$status" -eq 0 ]
|
||||
|
||||
@@ -90,8 +90,8 @@ teardown() {
|
||||
[[ "$output" =~ "Error parsing SQL" ]] || false
|
||||
}
|
||||
|
||||
@test "dolt schema in new repository" {
|
||||
run dolt schema
|
||||
@test "dolt schema show in new repository" {
|
||||
run dolt schema show
|
||||
[ "$status" -eq 1 ]
|
||||
[[ "$output" =~ "usage" ]] || false
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ teardown() {
|
||||
[[ "$output" =~ "test1" ]] || false
|
||||
[[ "$output" =~ "test2" ]] || false
|
||||
[ "${#lines[@]}" -eq 3 ]
|
||||
run dolt schema
|
||||
run dolt schema show
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "test1 @ working" ]] || false
|
||||
[[ "$output" =~ "test2 @ working" ]] || false
|
||||
|
||||
@@ -198,8 +198,8 @@ NOT_VALID_REPO_ERROR="The current directory is not a valid dolt repository."
|
||||
[ "${lines[0]}" = "$NOT_VALID_REPO_ERROR" ]
|
||||
}
|
||||
|
||||
@test "dolt schema outside of a dolt repository" {
|
||||
run dolt schema
|
||||
@test "dolt schema show outside of a dolt repository" {
|
||||
run dolt schema show
|
||||
[ "$status" -ne 0 ]
|
||||
[ "${lines[0]}" = "$NOT_VALID_REPO_ERROR" ]
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ teardown() {
|
||||
|
||||
@test "changing column types should not produce a data diff error" {
|
||||
dolt table import -c --pk=pk test `batshelper 1pk5col-ints.csv`
|
||||
run dolt schema
|
||||
run dolt schema show
|
||||
[[ "$output" =~ "varchar" ]] || false
|
||||
dolt add test
|
||||
dolt commit -m "Added test table"
|
||||
@@ -32,9 +32,9 @@ teardown() {
|
||||
@test "dolt schema rename column" {
|
||||
dolt table create -s=`batshelper 1pk5col-ints.schema` test
|
||||
dolt sql -q 'insert into test values (1,1,1,1,1,1)'
|
||||
run dolt schema --rename-column test c1 c0
|
||||
run dolt schema rename-column test c1 c0
|
||||
[ "$status" -eq 0 ]
|
||||
run dolt schema test
|
||||
run dolt schema show test
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "test @ working" ]] || false
|
||||
[[ "$output" =~ "CREATE TABLE \`test\`" ]] || false
|
||||
@@ -52,9 +52,9 @@ teardown() {
|
||||
@test "dolt schema delete column" {
|
||||
dolt table create -s=`batshelper 1pk5col-ints.schema` test
|
||||
dolt sql -q 'insert into test values (1,1,1,1,1,1)'
|
||||
run dolt schema --drop-column test c1
|
||||
run dolt schema drop-column test c1
|
||||
[ "$status" -eq 0 ]
|
||||
run dolt schema test
|
||||
run dolt schema show test
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "test @ working" ]] || false
|
||||
[[ "$output" =~ "CREATE TABLE \`test\`" ]] || false
|
||||
@@ -72,7 +72,7 @@ teardown() {
|
||||
dolt table create -s=`batshelper 1pk5col-ints.schema` test
|
||||
dolt add test
|
||||
dolt commit -m "committed table so we can see diffs"
|
||||
dolt schema --add-column test c0 int
|
||||
dolt schema add-column test c0 int
|
||||
run dolt diff
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ \+[[:space:]]+\`c0\` ]] || false
|
||||
@@ -94,7 +94,7 @@ teardown() {
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ \|[[:space:]]+c0[[:space:]]+\| ]] || false
|
||||
[[ "$output" =~ \+[[:space:]]+[[:space:]]+\|[[:space:]]+0 ]] || false
|
||||
dolt schema --drop-column test c0
|
||||
dolt schema drop-column test c0
|
||||
dolt diff
|
||||
}
|
||||
|
||||
@@ -113,8 +113,8 @@ teardown() {
|
||||
dolt table create -s=`batshelper 1pk5col-ints.schema` test
|
||||
dolt add test
|
||||
dolt commit -m "committed table so we can see diffs"
|
||||
dolt schema --add-column test c0 int
|
||||
dolt schema --drop-column test c0
|
||||
dolt schema add-column test c0 int
|
||||
dolt schema drop-column test c0
|
||||
run dolt diff
|
||||
skip "This produces a diff when it should not"
|
||||
[ "$status" -eq 0 ]
|
||||
|
||||
124
go/cmd/dolt/commands/schcmds/add_column.go
Normal file
124
go/cmd/dolt/commands/schcmds/add_column.go
Normal file
@@ -0,0 +1,124 @@
|
||||
// Copyright 2019 Liquidata, 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 schcmds
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/liquidata-inc/dolt/go/cmd/dolt/cli"
|
||||
"github.com/liquidata-inc/dolt/go/cmd/dolt/commands"
|
||||
"github.com/liquidata-inc/dolt/go/cmd/dolt/errhand"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/doltcore"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/doltcore/env"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/doltcore/schema"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/doltcore/schema/alterschema"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/utils/argparser"
|
||||
"github.com/liquidata-inc/dolt/go/store/types"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultParam = "default"
|
||||
tagParam = "tag"
|
||||
notNullFlag = "not-null"
|
||||
)
|
||||
|
||||
var schAddColShortDesc = "Adds a column to specified table's schema"
|
||||
var schAddColLongDesc = "Adds a column to the specified table's schema. If no default value is provided the column will be empty"
|
||||
var schAddColSynopsis = []string{
|
||||
"[--default <default_value>] [--not-null] [--tag <tag-number>] <table> <name> <type>",
|
||||
}
|
||||
|
||||
func AddColumn(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv) int {
|
||||
ap := argparser.NewArgParser()
|
||||
ap.ArgListHelp["table"] = "table where the new column should be added."
|
||||
ap.SupportsString(defaultParam, "", "default-value", "If provided all existing rows will be given this value as their default.")
|
||||
ap.SupportsUint(tagParam, "", "tag-number", "The numeric tag for the new column.")
|
||||
ap.SupportsFlag(notNullFlag, "", "If provided rows without a value in this column will be considered invalid. If rows already exist and not-null is specified then a default value must be provided.")
|
||||
|
||||
help, usage := cli.HelpAndUsagePrinters(commandStr, schAddColShortDesc, schAddColLongDesc, schAddColSynopsis, ap)
|
||||
apr := cli.ParseArgs(ap, args, help)
|
||||
|
||||
root, verr := commands.GetWorkingWithVErr(dEnv)
|
||||
|
||||
if verr == nil {
|
||||
verr = addField(ctx, apr, root, dEnv)
|
||||
}
|
||||
|
||||
return commands.HandleVErrAndExitCode(verr, usage)
|
||||
}
|
||||
|
||||
func addField(ctx context.Context, apr *argparser.ArgParseResults, root *doltdb.RootValue, dEnv *env.DoltEnv) errhand.VerboseError {
|
||||
if apr.NArg() != 3 {
|
||||
return errhand.BuildDError("Must specify table name, column name, column type, and if column required.").SetPrintUsage().Build()
|
||||
}
|
||||
|
||||
tblName := apr.Arg(0)
|
||||
if has, err := root.HasTable(ctx, tblName); err != nil {
|
||||
return errhand.BuildDError("error: could not read tables from database").AddCause(err).Build()
|
||||
} else if !has {
|
||||
return errhand.BuildDError(tblName + " not found").Build()
|
||||
}
|
||||
|
||||
tbl, _, err := root.GetTable(ctx, tblName)
|
||||
|
||||
if err != nil {
|
||||
return errhand.BuildDError("error: failed to get table '%s'", tblName).AddCause(err).Build()
|
||||
}
|
||||
|
||||
tblSch, err := tbl.GetSchema(ctx)
|
||||
newFieldName := apr.Arg(1)
|
||||
|
||||
var tag uint64
|
||||
if val, ok := apr.GetUint(tagParam); ok {
|
||||
tag = val
|
||||
} else {
|
||||
tag = schema.AutoGenerateTag(tblSch)
|
||||
}
|
||||
|
||||
newFieldType := strings.ToLower(apr.Arg(2))
|
||||
newFieldKind, ok := schema.LwrStrToKind[newFieldType]
|
||||
if !ok {
|
||||
return errhand.BuildDError(newFieldType + " is not a valid type for this new column.").SetPrintUsage().Build()
|
||||
}
|
||||
|
||||
var defaultVal types.Value
|
||||
if val, ok := apr.GetValue(defaultParam); ok {
|
||||
if nomsVal, err := doltcore.StringToValue(val, newFieldKind); err != nil {
|
||||
return errhand.VerboseErrorFromError(err)
|
||||
} else {
|
||||
defaultVal = nomsVal
|
||||
}
|
||||
}
|
||||
|
||||
nullable := alterschema.Null
|
||||
if apr.Contains(notNullFlag) {
|
||||
nullable = alterschema.NotNull
|
||||
}
|
||||
|
||||
newTable, err := alterschema.AddColumnToTable(ctx, dEnv.DoltDB, tbl, tag, newFieldName, newFieldKind, nullable, defaultVal)
|
||||
if err != nil {
|
||||
return errhand.VerboseErrorFromError(err)
|
||||
}
|
||||
|
||||
root, err = root.PutTable(ctx, tblName, newTable)
|
||||
|
||||
if err != nil {
|
||||
return errhand.BuildDError("error: failed to write table back to database").Build()
|
||||
}
|
||||
|
||||
return commands.UpdateWorkingWithVErr(dEnv, root)
|
||||
}
|
||||
84
go/cmd/dolt/commands/schcmds/drop_column.go
Normal file
84
go/cmd/dolt/commands/schcmds/drop_column.go
Normal file
@@ -0,0 +1,84 @@
|
||||
// Copyright 2019 Liquidata, 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 schcmds
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/liquidata-inc/dolt/go/cmd/dolt/cli"
|
||||
"github.com/liquidata-inc/dolt/go/cmd/dolt/commands"
|
||||
"github.com/liquidata-inc/dolt/go/cmd/dolt/errhand"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/doltcore/env"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/doltcore/schema/alterschema"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/utils/argparser"
|
||||
)
|
||||
|
||||
var schDropColShortDesc = "Removes a column of the specified table"
|
||||
var schDropColLongDesc = ""
|
||||
var schDropColSynopsis = []string{
|
||||
"<table> <column>",
|
||||
}
|
||||
|
||||
func DropColumn(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv) int {
|
||||
ap := argparser.NewArgParser()
|
||||
ap.ArgListHelp["table"] = "table(s) whose schema is being displayed."
|
||||
|
||||
help, usage := cli.HelpAndUsagePrinters(commandStr, schDropColShortDesc, schDropColLongDesc, schDropColSynopsis, ap)
|
||||
apr := cli.ParseArgs(ap, args, help)
|
||||
|
||||
root, verr := commands.GetWorkingWithVErr(dEnv)
|
||||
|
||||
if verr == nil {
|
||||
verr = removeColumn(ctx, apr, root, dEnv)
|
||||
}
|
||||
|
||||
return commands.HandleVErrAndExitCode(verr, usage)
|
||||
}
|
||||
|
||||
func removeColumn(ctx context.Context, apr *argparser.ArgParseResults, root *doltdb.RootValue, dEnv *env.DoltEnv) errhand.VerboseError {
|
||||
if apr.NArg() != 2 {
|
||||
return errhand.BuildDError("Table name and column to be removed must be specified.").SetPrintUsage().Build()
|
||||
}
|
||||
|
||||
tblName := apr.Arg(0)
|
||||
if has, err := root.HasTable(ctx, tblName); err != nil {
|
||||
return errhand.BuildDError("error: failed to read tables from database.").Build()
|
||||
} else if !has {
|
||||
return errhand.BuildDError(tblName + " not found").Build()
|
||||
}
|
||||
|
||||
tbl, _, err := root.GetTable(ctx, tblName)
|
||||
|
||||
if err != nil {
|
||||
return errhand.BuildDError("error: failed to get table '%s'", tblName).AddCause(err).Build()
|
||||
}
|
||||
|
||||
colName := apr.Arg(1)
|
||||
|
||||
newTbl, err := alterschema.DropColumn(ctx, dEnv.DoltDB, tbl, colName)
|
||||
|
||||
if err != nil {
|
||||
return errToVerboseErr(colName, "", err)
|
||||
}
|
||||
|
||||
root, err = root.PutTable(ctx, tblName, newTbl)
|
||||
|
||||
if err != nil {
|
||||
return errhand.BuildDError("error: failed to write table back to database").AddCause(err).Build()
|
||||
}
|
||||
|
||||
return commands.UpdateWorkingWithVErr(dEnv, root)
|
||||
}
|
||||
97
go/cmd/dolt/commands/schcmds/export.go
Normal file
97
go/cmd/dolt/commands/schcmds/export.go
Normal file
@@ -0,0 +1,97 @@
|
||||
// Copyright 2019 Liquidata, 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 schcmds
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/liquidata-inc/dolt/go/cmd/dolt/cli"
|
||||
"github.com/liquidata-inc/dolt/go/cmd/dolt/commands"
|
||||
"github.com/liquidata-inc/dolt/go/cmd/dolt/errhand"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/doltcore/env"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/doltcore/schema/encoding"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/utils/argparser"
|
||||
)
|
||||
|
||||
var schExportShortDesc = "Exports a table's schema."
|
||||
var schExportLongDesc = ""
|
||||
var schExportSynopsis = []string{
|
||||
"<table> <file>",
|
||||
}
|
||||
|
||||
func Export(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv) int {
|
||||
ap := argparser.NewArgParser()
|
||||
ap.ArgListHelp["table"] = "table whose schema is being exported."
|
||||
ap.ArgListHelp["commit"] = "commit at which point the schema will be displayed."
|
||||
ap.SupportsString(defaultParam, "", "default-value", "If provided all existing rows will be given this value as their default.")
|
||||
ap.SupportsUint(tagParam, "", "tag-number", "The numeric tag for the new column.")
|
||||
ap.SupportsFlag(notNullFlag, "", "If provided rows without a value in this column will be considered invalid. If rows already exist and not-null is specified then a default value must be provided.")
|
||||
|
||||
help, usage := cli.HelpAndUsagePrinters(commandStr, schExportShortDesc, schExportLongDesc, schExportSynopsis, ap)
|
||||
apr := cli.ParseArgs(ap, args, help)
|
||||
|
||||
root, verr := commands.GetWorkingWithVErr(dEnv)
|
||||
|
||||
if verr == nil {
|
||||
verr = exportSchemas(ctx, apr, root, dEnv)
|
||||
}
|
||||
|
||||
return commands.HandleVErrAndExitCode(verr, usage)
|
||||
}
|
||||
|
||||
func exportSchemas(ctx context.Context, apr *argparser.ArgParseResults, root *doltdb.RootValue, dEnv *env.DoltEnv) errhand.VerboseError {
|
||||
if apr.NArg() != 2 {
|
||||
return errhand.BuildDError("Must specify table and file to which table will be exported.").SetPrintUsage().Build()
|
||||
}
|
||||
|
||||
tblName := apr.Arg(0)
|
||||
fileName := apr.Arg(1)
|
||||
root, _ = commands.GetWorkingWithVErr(dEnv)
|
||||
if has, err := root.HasTable(ctx, tblName); err != nil {
|
||||
return errhand.BuildDError("unable to read from database").AddCause(err).Build()
|
||||
} else if !has {
|
||||
return errhand.BuildDError(tblName + " not found").Build()
|
||||
}
|
||||
|
||||
tbl, _, err := root.GetTable(ctx, tblName)
|
||||
|
||||
if err != nil {
|
||||
return errhand.BuildDError("unable to get table").AddCause(err).Build()
|
||||
}
|
||||
|
||||
err = exportTblSchema(ctx, tbl, fileName, dEnv)
|
||||
if err != nil {
|
||||
return errhand.BuildDError("file path not valid.").Build()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func exportTblSchema(ctx context.Context, tbl *doltdb.Table, filename string, dEnv *env.DoltEnv) errhand.VerboseError {
|
||||
sch, err := tbl.GetSchema(ctx)
|
||||
|
||||
if err != nil {
|
||||
return errhand.BuildDError("error: failed to get schema").AddCause(err).Build()
|
||||
}
|
||||
|
||||
jsonSchStr, err := encoding.MarshalAsJson(sch)
|
||||
if err != nil {
|
||||
return errhand.BuildDError("Failed to encode as json").AddCause(err).Build()
|
||||
}
|
||||
|
||||
err = dEnv.FS.WriteFile(filename, []byte(jsonSchStr))
|
||||
return errhand.BuildIf(err, "Unable to write "+filename).AddCause(err).Build()
|
||||
}
|
||||
41
go/cmd/dolt/commands/schcmds/import.go
Normal file
41
go/cmd/dolt/commands/schcmds/import.go
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright 2019 Liquidata, 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 schcmds
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/liquidata-inc/dolt/go/cmd/dolt/cli"
|
||||
"github.com/liquidata-inc/dolt/go/cmd/dolt/commands"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/doltcore/env"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/utils/argparser"
|
||||
)
|
||||
|
||||
var schImportShortDesc = "Creates a new table with an inferred schema."
|
||||
var schImportLongDesc = ""
|
||||
var schImportSynopsis = []string{
|
||||
"[--force] [--dry-run] [--file-type <type>] [--pks <field...>] <table> <file>",
|
||||
}
|
||||
|
||||
func Import(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv) int {
|
||||
ap := argparser.NewArgParser()
|
||||
ap.ArgListHelp["table"] = "Name of the table to be created."
|
||||
ap.ArgListHelp["file"] = "The file being used to infer the schema."
|
||||
|
||||
help, usage := cli.HelpAndUsagePrinters(commandStr, schImportShortDesc, schImportLongDesc, schImportSynopsis, ap)
|
||||
cli.ParseArgs(ap, args, help)
|
||||
|
||||
return commands.HandleVErrAndExitCode(nil, usage)
|
||||
}
|
||||
85
go/cmd/dolt/commands/schcmds/rename_column.go
Normal file
85
go/cmd/dolt/commands/schcmds/rename_column.go
Normal file
@@ -0,0 +1,85 @@
|
||||
// Copyright 2019 Liquidata, 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 schcmds
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/liquidata-inc/dolt/go/cmd/dolt/cli"
|
||||
"github.com/liquidata-inc/dolt/go/cmd/dolt/commands"
|
||||
"github.com/liquidata-inc/dolt/go/cmd/dolt/errhand"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/doltcore/env"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/doltcore/schema/alterschema"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/utils/argparser"
|
||||
)
|
||||
|
||||
var schRenameColShortDesc = "Renames a column of the specified table."
|
||||
var schRenameColLongDesc = "<b>dolt schema rename-column</b> will change the display name of a column. Changing the name" +
|
||||
"of the column will only modify the schema and no data will change."
|
||||
var schRenameColSynopsis = []string{
|
||||
"<table> <old> <new>",
|
||||
}
|
||||
|
||||
func RenameColumn(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv) int {
|
||||
ap := argparser.NewArgParser()
|
||||
ap.ArgListHelp["table"] = "table being modified."
|
||||
|
||||
help, usage := cli.HelpAndUsagePrinters(commandStr, schRenameColShortDesc, schRenameColLongDesc, schRenameColSynopsis, ap)
|
||||
apr := cli.ParseArgs(ap, args, help)
|
||||
|
||||
root, verr := commands.GetWorkingWithVErr(dEnv)
|
||||
|
||||
if verr == nil {
|
||||
verr = renameColumn(ctx, apr, root, dEnv)
|
||||
}
|
||||
|
||||
return commands.HandleVErrAndExitCode(verr, usage)
|
||||
}
|
||||
|
||||
func renameColumn(ctx context.Context, apr *argparser.ArgParseResults, root *doltdb.RootValue, dEnv *env.DoltEnv) errhand.VerboseError {
|
||||
if apr.NArg() != 3 {
|
||||
return errhand.BuildDError("Table name, current column name, and new column name are needed to rename column.").SetPrintUsage().Build()
|
||||
}
|
||||
|
||||
tblName := apr.Arg(0)
|
||||
if has, err := root.HasTable(ctx, tblName); err != nil {
|
||||
return errhand.BuildDError("error: failed to read tables from database").AddCause(err).Build()
|
||||
} else if !has {
|
||||
return errhand.BuildDError(tblName + " not found").Build()
|
||||
}
|
||||
|
||||
tbl, _, err := root.GetTable(ctx, tblName)
|
||||
|
||||
if err != nil {
|
||||
return errhand.BuildDError("error: failed to get table '%s'", tblName).AddCause(err).Build()
|
||||
}
|
||||
|
||||
oldColName := apr.Arg(1)
|
||||
newColName := apr.Arg(2)
|
||||
|
||||
newTbl, err := alterschema.RenameColumn(ctx, dEnv.DoltDB, tbl, oldColName, newColName)
|
||||
if err != nil {
|
||||
return errToVerboseErr(oldColName, newColName, err)
|
||||
}
|
||||
|
||||
root, err = root.PutTable(ctx, tblName, newTbl)
|
||||
|
||||
if err != nil {
|
||||
return errhand.BuildDError("error: failed to write table back to database").Build()
|
||||
}
|
||||
|
||||
return commands.UpdateWorkingWithVErr(dEnv, root)
|
||||
}
|
||||
29
go/cmd/dolt/commands/schcmds/schema.go
Normal file
29
go/cmd/dolt/commands/schcmds/schema.go
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright 2019 Liquidata, 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 schcmds
|
||||
|
||||
import (
|
||||
"github.com/liquidata-inc/dolt/go/cmd/dolt/cli"
|
||||
eventsapi "github.com/liquidata-inc/dolt/go/gen/proto/dolt/services/eventsapi/v1alpha1"
|
||||
)
|
||||
|
||||
var Commands = cli.GenSubCommandHandler([]*cli.Command{
|
||||
{Name: "add-column", Desc: "Adds a column to specified table's schema.", Func: AddColumn, ReqRepo: true, EventType: eventsapi.ClientEventType_SCHEMA},
|
||||
{Name: "drop-column", Desc: "Removes a column of the specified table.", Func: DropColumn, ReqRepo: true, EventType: eventsapi.ClientEventType_SCHEMA},
|
||||
{Name: "export", Desc: "Exports a table's schema.", Func: Export, ReqRepo: true, EventType: eventsapi.ClientEventType_SCHEMA},
|
||||
//{Name: "import", Desc: "Creates a new table with an inferred schema.", Func: Import, ReqRepo: true, EventType: eventsapi.ClientEventType_SCHEMA},
|
||||
{Name: "rename-column", Desc: "Renames a column of the specified table.", Func: RenameColumn, ReqRepo: true, EventType: eventsapi.ClientEventType_SCHEMA},
|
||||
{Name: "show", Desc: "Shows the schema of one or more tables.", Func: Show, ReqRepo: true, EventType: eventsapi.ClientEventType_SCHEMA},
|
||||
})
|
||||
152
go/cmd/dolt/commands/schcmds/show.go
Normal file
152
go/cmd/dolt/commands/schcmds/show.go
Normal file
@@ -0,0 +1,152 @@
|
||||
// Copyright 2019 Liquidata, 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 schcmds
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/fatih/color"
|
||||
|
||||
"github.com/liquidata-inc/dolt/go/cmd/dolt/cli"
|
||||
"github.com/liquidata-inc/dolt/go/cmd/dolt/commands"
|
||||
"github.com/liquidata-inc/dolt/go/cmd/dolt/errhand"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/doltcore/env"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/doltcore/schema"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/doltcore/sql"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/utils/argparser"
|
||||
)
|
||||
|
||||
const ()
|
||||
|
||||
var tblSchemaShortDesc = "Shows the schema of one or more tables."
|
||||
var tblSchemaLongDesc = "dolt table schema displays the schema of tables at a given commit. If no commit is provided the working set will be used." +
|
||||
"\n" +
|
||||
"A list of tables can optionally be provided. If it is omitted all table schemas will be shown."
|
||||
|
||||
var tblSchemaSynopsis = []string{
|
||||
"[<commit>] [<table>...]",
|
||||
}
|
||||
|
||||
var bold = color.New(color.Bold)
|
||||
|
||||
func Show(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv) int {
|
||||
ap := argparser.NewArgParser()
|
||||
ap.ArgListHelp["table"] = "table(s) whose schema is being displayed."
|
||||
ap.ArgListHelp["commit"] = "commit at which point the schema will be displayed."
|
||||
|
||||
help, usage := cli.HelpAndUsagePrinters(commandStr, tblSchemaShortDesc, tblSchemaLongDesc, tblSchemaSynopsis, ap)
|
||||
apr := cli.ParseArgs(ap, args, help)
|
||||
verr := printSchemas(ctx, apr, dEnv)
|
||||
|
||||
return commands.HandleVErrAndExitCode(verr, usage)
|
||||
}
|
||||
|
||||
func printSchemas(ctx context.Context, apr *argparser.ArgParseResults, dEnv *env.DoltEnv) errhand.VerboseError {
|
||||
cmStr := "working"
|
||||
args := apr.Args()
|
||||
|
||||
var root *doltdb.RootValue
|
||||
var verr errhand.VerboseError
|
||||
var cm *doltdb.Commit
|
||||
|
||||
if apr.NArg() == 0 {
|
||||
cm, verr = nil, nil
|
||||
} else {
|
||||
cm, verr = commands.MaybeGetCommitWithVErr(dEnv, args[0])
|
||||
}
|
||||
|
||||
if verr == nil {
|
||||
if cm != nil {
|
||||
cmStr = args[0]
|
||||
args = args[1:]
|
||||
|
||||
var err error
|
||||
root, err = cm.GetRootValue()
|
||||
|
||||
if err != nil {
|
||||
verr = errhand.BuildDError("unable to get root value").AddCause(err).Build()
|
||||
}
|
||||
} else {
|
||||
root, verr = commands.GetWorkingWithVErr(dEnv)
|
||||
}
|
||||
}
|
||||
|
||||
if verr == nil {
|
||||
tables := args
|
||||
|
||||
// If the user hasn't specified table names, try to grab them all;
|
||||
// show usage and error out if there aren't any
|
||||
if len(tables) == 0 {
|
||||
var err error
|
||||
tables, err = root.GetTableNames(ctx)
|
||||
|
||||
if err != nil {
|
||||
return errhand.BuildDError("unable to get table names.").AddCause(err).Build()
|
||||
}
|
||||
|
||||
if len(tables) == 0 {
|
||||
return errhand.BuildDError("").SetPrintUsage().Build()
|
||||
}
|
||||
}
|
||||
|
||||
var notFound []string
|
||||
for _, tblName := range tables {
|
||||
tbl, ok, err := root.GetTable(ctx, tblName)
|
||||
|
||||
if err != nil {
|
||||
return errhand.BuildDError("unable to get table '%s'", tblName).AddCause(err).Build()
|
||||
}
|
||||
|
||||
if !ok {
|
||||
notFound = append(notFound, tblName)
|
||||
} else {
|
||||
verr = printTblSchema(ctx, cmStr, tblName, tbl)
|
||||
cli.Println()
|
||||
}
|
||||
}
|
||||
|
||||
for _, tblName := range notFound {
|
||||
cli.PrintErrln(color.YellowString("%s not found", tblName))
|
||||
}
|
||||
}
|
||||
|
||||
return verr
|
||||
}
|
||||
|
||||
func printTblSchema(ctx context.Context, cmStr string, tblName string, tbl *doltdb.Table) errhand.VerboseError {
|
||||
cli.Println(bold.Sprint(tblName), "@", cmStr)
|
||||
sch, err := tbl.GetSchema(ctx)
|
||||
|
||||
if err != nil {
|
||||
return errhand.BuildDError("unable to get schema").AddCause(err).Build()
|
||||
}
|
||||
|
||||
cli.Println(sql.SchemaAsCreateStmt(tblName, sch))
|
||||
return nil
|
||||
}
|
||||
|
||||
func errToVerboseErr(oldName, newName string, err error) errhand.VerboseError {
|
||||
switch err {
|
||||
case schema.ErrColNameCollision:
|
||||
return errhand.BuildDError("error: A column already exists with the name %s", newName).Build()
|
||||
|
||||
case schema.ErrColNotFound:
|
||||
return errhand.BuildDError("error: Column %s unknown", oldName).Build()
|
||||
|
||||
default:
|
||||
return errhand.BuildDError("error: Failed to alter schema").AddCause(err).Build()
|
||||
}
|
||||
}
|
||||
@@ -1,376 +0,0 @@
|
||||
// Copyright 2019 Liquidata, 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 commands
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/fatih/color"
|
||||
|
||||
"github.com/liquidata-inc/dolt/go/cmd/dolt/cli"
|
||||
"github.com/liquidata-inc/dolt/go/cmd/dolt/errhand"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/doltcore"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/doltcore/env"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/doltcore/schema"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/doltcore/schema/alterschema"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/doltcore/schema/encoding"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/doltcore/sql"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/utils/argparser"
|
||||
"github.com/liquidata-inc/dolt/go/store/types"
|
||||
)
|
||||
|
||||
const (
|
||||
exportFlag = "export"
|
||||
defaultParam = "default"
|
||||
tagParam = "tag"
|
||||
notNullFlag = "not-null"
|
||||
addFieldFlag = "add-column"
|
||||
renameFieldFlag = "rename-column"
|
||||
dropFieldFlag = "drop-column"
|
||||
)
|
||||
|
||||
var tblSchemaShortDesc = "Displays and modifies table schemas"
|
||||
var tblSchemaLongDesc = `dolt table schema displays the schema of tables at a given commit. If no commit is provided the
|
||||
working set will be used.
|
||||
|
||||
A list of tables can optionally be provided. If it is omitted all table schemas will be shown.
|
||||
|
||||
dolt schema --export exports a table's schema into a specified file. Both table and file must be specified.
|
||||
|
||||
dolt schema --add-column adds a column to specified table's schema. If no default value is provided the column
|
||||
will be empty.
|
||||
|
||||
dolt schema --rename-column renames a column of the specified table.
|
||||
|
||||
dolt schema --drop-column removes a column of the specified table.
|
||||
`
|
||||
|
||||
var tblSchemaSynopsis = []string{
|
||||
"[<commit>] [<table>...]",
|
||||
"--export <table> <file>",
|
||||
"--add-column [--default <default_value>] [--not-null] [--tag <tag-number>] <table> <name> <type>",
|
||||
"--rename-column <table> <old> <new>",
|
||||
"--drop-column <table> <column>",
|
||||
}
|
||||
|
||||
var bold = color.New(color.Bold)
|
||||
|
||||
func Schema(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv) int {
|
||||
ap := argparser.NewArgParser()
|
||||
ap.ArgListHelp["table"] = "table(s) whose schema is being displayed."
|
||||
ap.ArgListHelp["commit"] = "commit at which point the schema will be displayed."
|
||||
ap.SupportsFlag(exportFlag, "", "exports schema into file.")
|
||||
ap.SupportsString(defaultParam, "", "default-value", "If provided all existing rows will be given this value as their default.")
|
||||
ap.SupportsUint(tagParam, "", "tag-number", "The numeric tag for the new column.")
|
||||
ap.SupportsFlag(notNullFlag, "", "If provided rows without a value in this column will be considered invalid. If rows already exist and not-null is specified then a default value must be provided.")
|
||||
ap.SupportsFlag(addFieldFlag, "", "add columm to table schema.")
|
||||
ap.SupportsFlag(renameFieldFlag, "", "rename column for specified table.")
|
||||
ap.SupportsFlag(dropFieldFlag, "", "removes column from specified table.")
|
||||
|
||||
help, usage := cli.HelpAndUsagePrinters(commandStr, tblSchemaShortDesc, tblSchemaLongDesc, tblSchemaSynopsis, ap)
|
||||
apr := cli.ParseArgs(ap, args, help)
|
||||
var root *doltdb.RootValue
|
||||
root, _ = GetWorkingWithVErr(dEnv)
|
||||
|
||||
var verr errhand.VerboseError
|
||||
if apr.Contains(renameFieldFlag) {
|
||||
verr = renameColumn(ctx, apr, root, dEnv)
|
||||
} else if apr.Contains(addFieldFlag) {
|
||||
verr = addField(ctx, apr, root, dEnv)
|
||||
} else if apr.Contains(exportFlag) {
|
||||
verr = exportSchemas(ctx, apr, root, dEnv)
|
||||
} else if apr.Contains(dropFieldFlag) {
|
||||
verr = removeColumn(ctx, apr, root, dEnv)
|
||||
} else {
|
||||
verr = printSchemas(ctx, apr, dEnv)
|
||||
}
|
||||
|
||||
return HandleVErrAndExitCode(verr, usage)
|
||||
}
|
||||
|
||||
func printSchemas(ctx context.Context, apr *argparser.ArgParseResults, dEnv *env.DoltEnv) errhand.VerboseError {
|
||||
cmStr := "working"
|
||||
args := apr.Args()
|
||||
|
||||
var root *doltdb.RootValue
|
||||
var verr errhand.VerboseError
|
||||
var cm *doltdb.Commit
|
||||
|
||||
if apr.NArg() == 0 {
|
||||
cm, verr = nil, nil
|
||||
} else {
|
||||
cm, verr = MaybeGetCommitWithVErr(dEnv, args[0])
|
||||
}
|
||||
|
||||
if verr == nil {
|
||||
if cm != nil {
|
||||
cmStr = args[0]
|
||||
args = args[1:]
|
||||
|
||||
var err error
|
||||
root, err = cm.GetRootValue()
|
||||
|
||||
if err != nil {
|
||||
verr = errhand.BuildDError("unable to get root value").AddCause(err).Build()
|
||||
}
|
||||
} else {
|
||||
root, verr = GetWorkingWithVErr(dEnv)
|
||||
}
|
||||
}
|
||||
|
||||
if verr == nil {
|
||||
tables := args
|
||||
|
||||
// If the user hasn't specified table names, try to grab them all;
|
||||
// show usage and error out if there aren't any
|
||||
if len(tables) == 0 {
|
||||
var err error
|
||||
tables, err = root.GetTableNames(ctx)
|
||||
|
||||
if err != nil {
|
||||
return errhand.BuildDError("unable to get table names.").AddCause(err).Build()
|
||||
}
|
||||
|
||||
if len(tables) == 0 {
|
||||
return errhand.BuildDError("").SetPrintUsage().Build()
|
||||
}
|
||||
}
|
||||
|
||||
var notFound []string
|
||||
for _, tblName := range tables {
|
||||
tbl, ok, err := root.GetTable(ctx, tblName)
|
||||
|
||||
if err != nil {
|
||||
return errhand.BuildDError("unable to get table '%s'", tblName).AddCause(err).Build()
|
||||
}
|
||||
|
||||
if !ok {
|
||||
notFound = append(notFound, tblName)
|
||||
} else {
|
||||
verr = printTblSchema(ctx, cmStr, tblName, tbl, root)
|
||||
cli.Println()
|
||||
}
|
||||
}
|
||||
|
||||
for _, tblName := range notFound {
|
||||
cli.PrintErrln(color.YellowString("%s not found", tblName))
|
||||
}
|
||||
}
|
||||
|
||||
return verr
|
||||
}
|
||||
|
||||
func printTblSchema(ctx context.Context, cmStr string, tblName string, tbl *doltdb.Table, root *doltdb.RootValue) errhand.VerboseError {
|
||||
cli.Println(bold.Sprint(tblName), "@", cmStr)
|
||||
sch, err := tbl.GetSchema(ctx)
|
||||
|
||||
if err != nil {
|
||||
return errhand.BuildDError("unable to get schema").AddCause(err).Build()
|
||||
}
|
||||
|
||||
cli.Println(sql.SchemaAsCreateStmt(tblName, sch))
|
||||
return nil
|
||||
}
|
||||
|
||||
func exportSchemas(ctx context.Context, apr *argparser.ArgParseResults, root *doltdb.RootValue, dEnv *env.DoltEnv) errhand.VerboseError {
|
||||
if apr.NArg() != 2 {
|
||||
return errhand.BuildDError("Must specify table and file to which table will be exported.").SetPrintUsage().Build()
|
||||
}
|
||||
|
||||
tblName := apr.Arg(0)
|
||||
fileName := apr.Arg(1)
|
||||
root, _ = GetWorkingWithVErr(dEnv)
|
||||
if has, err := root.HasTable(ctx, tblName); err != nil {
|
||||
return errhand.BuildDError("unable to read from database").AddCause(err).Build()
|
||||
} else if !has {
|
||||
return errhand.BuildDError(tblName + " not found").Build()
|
||||
}
|
||||
|
||||
tbl, _, err := root.GetTable(ctx, tblName)
|
||||
|
||||
if err != nil {
|
||||
return errhand.BuildDError("unable to get table").AddCause(err).Build()
|
||||
}
|
||||
|
||||
err = exportTblSchema(ctx, tbl, fileName, dEnv)
|
||||
if err != nil {
|
||||
return errhand.BuildDError("file path not valid.").Build()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func exportTblSchema(ctx context.Context, tbl *doltdb.Table, filename string, dEnv *env.DoltEnv) errhand.VerboseError {
|
||||
sch, err := tbl.GetSchema(ctx)
|
||||
|
||||
if err != nil {
|
||||
return errhand.BuildDError("error: failed to get schema").AddCause(err).Build()
|
||||
}
|
||||
|
||||
jsonSchStr, err := encoding.MarshalAsJson(sch)
|
||||
if err != nil {
|
||||
return errhand.BuildDError("Failed to encode as json").AddCause(err).Build()
|
||||
}
|
||||
|
||||
err = dEnv.FS.WriteFile(filename, []byte(jsonSchStr))
|
||||
return errhand.BuildIf(err, "Unable to write "+filename).AddCause(err).Build()
|
||||
}
|
||||
|
||||
func addField(ctx context.Context, apr *argparser.ArgParseResults, root *doltdb.RootValue, dEnv *env.DoltEnv) errhand.VerboseError {
|
||||
if apr.NArg() != 3 {
|
||||
return errhand.BuildDError("Must specify table name, column name, column type, and if column required.").SetPrintUsage().Build()
|
||||
}
|
||||
|
||||
tblName := apr.Arg(0)
|
||||
if has, err := root.HasTable(ctx, tblName); err != nil {
|
||||
return errhand.BuildDError("error: could not read tables from database").AddCause(err).Build()
|
||||
} else if !has {
|
||||
return errhand.BuildDError(tblName + " not found").Build()
|
||||
}
|
||||
|
||||
tbl, _, err := root.GetTable(ctx, tblName)
|
||||
|
||||
if err != nil {
|
||||
return errhand.BuildDError("error: failed to get table '%s'", tblName).AddCause(err).Build()
|
||||
}
|
||||
|
||||
tblSch, err := tbl.GetSchema(ctx)
|
||||
newFieldName := apr.Arg(1)
|
||||
|
||||
var tag uint64
|
||||
if val, ok := apr.GetUint(tagParam); ok {
|
||||
tag = val
|
||||
} else {
|
||||
tag = schema.AutoGenerateTag(tblSch)
|
||||
}
|
||||
|
||||
newFieldType := strings.ToLower(apr.Arg(2))
|
||||
newFieldKind, ok := schema.LwrStrToKind[newFieldType]
|
||||
if !ok {
|
||||
return errhand.BuildDError(newFieldType + " is not a valid type for this new column.").SetPrintUsage().Build()
|
||||
}
|
||||
|
||||
var defaultVal types.Value
|
||||
if val, ok := apr.GetValue(defaultParam); ok {
|
||||
if nomsVal, err := doltcore.StringToValue(val, newFieldKind); err != nil {
|
||||
return errhand.VerboseErrorFromError(err)
|
||||
} else {
|
||||
defaultVal = nomsVal
|
||||
}
|
||||
}
|
||||
|
||||
nullable := alterschema.Null
|
||||
if apr.Contains(notNullFlag) {
|
||||
nullable = alterschema.NotNull
|
||||
}
|
||||
|
||||
newTable, err := alterschema.AddColumnToTable(ctx, dEnv.DoltDB, tbl, tag, newFieldName, newFieldKind, nullable, defaultVal)
|
||||
if err != nil {
|
||||
return errhand.VerboseErrorFromError(err)
|
||||
}
|
||||
|
||||
root, err = root.PutTable(ctx, tblName, newTable)
|
||||
|
||||
if err != nil {
|
||||
return errhand.BuildDError("error: failed to write table back to database").Build()
|
||||
}
|
||||
|
||||
return UpdateWorkingWithVErr(dEnv, root)
|
||||
}
|
||||
|
||||
func renameColumn(ctx context.Context, apr *argparser.ArgParseResults, root *doltdb.RootValue, dEnv *env.DoltEnv) errhand.VerboseError {
|
||||
if apr.NArg() != 3 {
|
||||
return errhand.BuildDError("Table name, current column name, and new column name are needed to rename column.").SetPrintUsage().Build()
|
||||
}
|
||||
|
||||
tblName := apr.Arg(0)
|
||||
if has, err := root.HasTable(ctx, tblName); err != nil {
|
||||
return errhand.BuildDError("error: failed to read tables from database").AddCause(err).Build()
|
||||
} else if !has {
|
||||
return errhand.BuildDError(tblName + " not found").Build()
|
||||
}
|
||||
|
||||
tbl, _, err := root.GetTable(ctx, tblName)
|
||||
|
||||
if err != nil {
|
||||
return errhand.BuildDError("error: failed to get table '%s'", tblName).AddCause(err).Build()
|
||||
}
|
||||
|
||||
oldColName := apr.Arg(1)
|
||||
newColName := apr.Arg(2)
|
||||
|
||||
newTbl, err := alterschema.RenameColumn(ctx, dEnv.DoltDB, tbl, oldColName, newColName)
|
||||
if err != nil {
|
||||
return errToVerboseErr(oldColName, newColName, err)
|
||||
}
|
||||
|
||||
root, err = root.PutTable(ctx, tblName, newTbl)
|
||||
|
||||
if err != nil {
|
||||
return errhand.BuildDError("error: failed to write table back to database").Build()
|
||||
}
|
||||
|
||||
return UpdateWorkingWithVErr(dEnv, root)
|
||||
}
|
||||
|
||||
func errToVerboseErr(oldName, newName string, err error) errhand.VerboseError {
|
||||
switch err {
|
||||
case schema.ErrColNameCollision:
|
||||
return errhand.BuildDError("error: A column already exists with the name %s", newName).Build()
|
||||
|
||||
case schema.ErrColNotFound:
|
||||
return errhand.BuildDError("error: Column %s unknown", oldName).Build()
|
||||
|
||||
default:
|
||||
return errhand.BuildDError("error: Failed to alter schema").AddCause(err).Build()
|
||||
}
|
||||
}
|
||||
|
||||
func removeColumn(ctx context.Context, apr *argparser.ArgParseResults, root *doltdb.RootValue, dEnv *env.DoltEnv) errhand.VerboseError {
|
||||
if apr.NArg() != 2 {
|
||||
return errhand.BuildDError("Table name and column to be removed must be specified.").SetPrintUsage().Build()
|
||||
}
|
||||
|
||||
tblName := apr.Arg(0)
|
||||
if has, err := root.HasTable(ctx, tblName); err != nil {
|
||||
return errhand.BuildDError("error: failed to read tables from database.").Build()
|
||||
} else if !has {
|
||||
return errhand.BuildDError(tblName + " not found").Build()
|
||||
}
|
||||
|
||||
tbl, _, err := root.GetTable(ctx, tblName)
|
||||
|
||||
if err != nil {
|
||||
return errhand.BuildDError("error: failed to get table '%s'", tblName).AddCause(err).Build()
|
||||
}
|
||||
|
||||
colName := apr.Arg(1)
|
||||
|
||||
newTbl, err := alterschema.DropColumn(ctx, dEnv.DoltDB, tbl, colName)
|
||||
|
||||
if err != nil {
|
||||
return errToVerboseErr(colName, "", err)
|
||||
}
|
||||
|
||||
root, err = root.PutTable(ctx, tblName, newTbl)
|
||||
|
||||
if err != nil {
|
||||
return errhand.BuildDError("error: failed to write table back to database").AddCause(err).Build()
|
||||
}
|
||||
|
||||
return UpdateWorkingWithVErr(dEnv, root)
|
||||
}
|
||||
@@ -1,148 +0,0 @@
|
||||
// Copyright 2019 Liquidata, 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 commands
|
||||
|
||||
/*
|
||||
func TestExportTblSchema(t *testing.T) {
|
||||
tests := []struct {
|
||||
table string
|
||||
outFilePath string
|
||||
}{
|
||||
{
|
||||
tableName,
|
||||
"schema.json",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
dEnv := createEnvWithSeedData(t)
|
||||
root, _ := dEnv.WorkingRoot()
|
||||
tbl, _ := root.GetTable(tableName)
|
||||
|
||||
originalSchema := tbl.GetSchema()
|
||||
result := exportTblSchema(tableName, tbl, test.outFilePath, dEnv)
|
||||
|
||||
if result != nil {
|
||||
t.Fatal("Unexpected failure.")
|
||||
}
|
||||
|
||||
data, err := dEnv.FS.ReadFile(test.outFilePath)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
newSchema, _ := jsonenc.SchemaFromJSON(data)
|
||||
|
||||
if !reflect.DeepEqual(originalSchema, newSchema) {
|
||||
t.Error(originalSchema, "!=", newSchema)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddFieldToSchema(t *testing.T) {
|
||||
tests := []struct {
|
||||
tblName string
|
||||
newColName string
|
||||
colType string
|
||||
required string
|
||||
defaultVal string
|
||||
}{
|
||||
{tableName, "date", "string", "false", ""},
|
||||
//{tableName, "date", "string", "true", ""},
|
||||
{tableName, "date", "string", "true", "02-25-2019"},
|
||||
{tableName, "number", "int", "true", "5"},
|
||||
}
|
||||
for _, test := range tests {
|
||||
dEnv := createEnvWithSeedData(t)
|
||||
root, _ := dEnv.WorkingRoot()
|
||||
tbl, _ := root.GetTable(tableName)
|
||||
originalSchemaFields := tbl.GetSchema().GetFieldNames()
|
||||
|
||||
result, err := addFieldToSchema(tableName, tbl, dEnv, test.newColName, test.colType, test.required, &test.defaultVal)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
newSchema := result.GetSchema()
|
||||
newSchemaFields := newSchema.GetFieldNames()
|
||||
originalPlusNewField := append(originalSchemaFields, test.newColName)
|
||||
|
||||
if !reflect.DeepEqual(originalPlusNewField, newSchemaFields) {
|
||||
t.Error(originalSchemaFields, "!=", newSchemaFields)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestRenameColumnOfSchema(t *testing.T) {
|
||||
tests := []struct {
|
||||
table string
|
||||
oldName string
|
||||
newName string
|
||||
newFieldNames []string
|
||||
}{
|
||||
{tableName, "is_married", "married", []string{"id", "name", "age", "title", "married"}},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
dEnv := createEnvWithSeedData(t)
|
||||
root, _ := dEnv.WorkingRoot()
|
||||
tbl, _ := root.GetTable(tableName)
|
||||
|
||||
result, err := renameColumnOfSchema(test.oldName, test.newName, tbl, dEnv)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
newSchema := result.GetSchema()
|
||||
newSchemaFields := newSchema.GetFieldNames()
|
||||
|
||||
if !reflect.DeepEqual(test.newFieldNames, newSchemaFields) {
|
||||
t.Error(test.newFieldNames, "!=", newSchemaFields)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestRemoveColumnFromTable(t *testing.T) {
|
||||
tests := []struct {
|
||||
table string
|
||||
colName string
|
||||
newFieldNames []string
|
||||
}{
|
||||
{tableName, "is_married", []string{"id", "name", "age", "title"}},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
dEnv := createEnvWithSeedData(t)
|
||||
root, _ := dEnv.WorkingRoot()
|
||||
tbl, _ := root.GetTable(tableName)
|
||||
|
||||
result, err := removeColumnFromTable(tbl, test.colName, dEnv)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
newSchema := result.GetSchema()
|
||||
newSchemaFields := newSchema.GetFieldNames()
|
||||
|
||||
if !reflect.DeepEqual(test.newFieldNames, newSchemaFields) {
|
||||
t.Error(test.newFieldNames, "!=", newSchemaFields)
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
"github.com/liquidata-inc/dolt/go/cmd/dolt/commands"
|
||||
"github.com/liquidata-inc/dolt/go/cmd/dolt/commands/cnfcmds"
|
||||
"github.com/liquidata-inc/dolt/go/cmd/dolt/commands/credcmds"
|
||||
"github.com/liquidata-inc/dolt/go/cmd/dolt/commands/schcmds"
|
||||
"github.com/liquidata-inc/dolt/go/cmd/dolt/commands/sqlserver"
|
||||
"github.com/liquidata-inc/dolt/go/cmd/dolt/commands/tblcmds"
|
||||
eventsapi "github.com/liquidata-inc/dolt/go/gen/proto/dolt/services/eventsapi/v1alpha1"
|
||||
@@ -65,7 +66,7 @@ var doltCommand = cli.GenSubCommandHandler([]*cli.Command{
|
||||
{Name: "version", Desc: "Displays the current Dolt cli version.", Func: commands.Version(Version), ReqRepo: false, EventType: eventsapi.ClientEventType_VERSION},
|
||||
{Name: "config", Desc: "Dolt configuration.", Func: commands.Config, ReqRepo: false},
|
||||
{Name: "ls", Desc: "List tables in the working set.", Func: commands.Ls, ReqRepo: true, EventType: eventsapi.ClientEventType_LS},
|
||||
{Name: "schema", Desc: "Display the schema for table(s)", Func: commands.Schema, ReqRepo: true, EventType: eventsapi.ClientEventType_SCHEMA},
|
||||
{Name: "schema", Desc: "Display the schema for table(s)", Func: schcmds.Commands, ReqRepo: true, EventType: eventsapi.ClientEventType_SCHEMA},
|
||||
{Name: "table", Desc: "Commands for creating, reading, updating, and deleting tables.", Func: tblcmds.Commands, ReqRepo: false},
|
||||
{Name: "conflicts", Desc: "Commands for viewing and resolving merge conflicts.", Func: cnfcmds.Commands, ReqRepo: false},
|
||||
{Name: commands.SendMetricsCommand, Desc: "Send events logs to server.", Func: commands.SendMetrics, ReqRepo: false, HideFromHelp: true},
|
||||
|
||||
Reference in New Issue
Block a user