diff --git a/bats/1pk5col-ints.bats b/bats/1pk5col-ints.bats index 07d8719e7b..f80acfa7d8 100755 --- a/bats/1pk5col-ints.bats +++ b/bats/1pk5col-ints.bats @@ -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 ] diff --git a/bats/advanced-sql.bats b/bats/advanced-sql.bats index 0729ab608f..04b4c89668 100755 --- a/bats/advanced-sql.bats +++ b/bats/advanced-sql.bats @@ -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 } diff --git a/bats/capital-letter-column-names.bats b/bats/capital-letter-column-names.bats index 36549cb549..021ab7fe81 100644 --- a/bats/capital-letter-column-names.bats +++ b/bats/capital-letter-column-names.bats @@ -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 diff --git a/bats/conflict-detection.bats b/bats/conflict-detection.bats index f34561bda9..0a0eabd162 100644 --- a/bats/conflict-detection.bats +++ b/bats/conflict-detection.bats @@ -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 diff --git a/bats/create-tables.bats b/bats/create-tables.bats index 281a793dd0..69a3caf86f 100755 --- a/bats/create-tables.bats +++ b/bats/create-tables.bats @@ -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 } diff --git a/bats/diff.bats b/bats/diff.bats index 0f2978f719..32c0eb1f9c 100644 --- a/bats/diff.bats +++ b/bats/diff.bats @@ -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 ] diff --git a/bats/empty-repo.bats b/bats/empty-repo.bats index b154baa017..7c0995e115 100755 --- a/bats/empty-repo.bats +++ b/bats/empty-repo.bats @@ -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 } diff --git a/bats/multiple-tables.bats b/bats/multiple-tables.bats index e78a39e763..334ab1686b 100755 --- a/bats/multiple-tables.bats +++ b/bats/multiple-tables.bats @@ -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 diff --git a/bats/no-repo.bats b/bats/no-repo.bats index 3007cd2488..a863f9dacb 100755 --- a/bats/no-repo.bats +++ b/bats/no-repo.bats @@ -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" ] } diff --git a/bats/schema-changes.bats b/bats/schema-changes.bats index 0316508c3f..18340a34f9 100755 --- a/bats/schema-changes.bats +++ b/bats/schema-changes.bats @@ -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 ] diff --git a/go/cmd/dolt/commands/schcmds/add_column.go b/go/cmd/dolt/commands/schcmds/add_column.go new file mode 100644 index 0000000000..2a844adb14 --- /dev/null +++ b/go/cmd/dolt/commands/schcmds/add_column.go @@ -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 ] [--not-null] [--tag ] ", +} + +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) +} diff --git a/go/cmd/dolt/commands/schcmds/drop_column.go b/go/cmd/dolt/commands/schcmds/drop_column.go new file mode 100644 index 0000000000..d7e57de393 --- /dev/null +++ b/go/cmd/dolt/commands/schcmds/drop_column.go @@ -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{ + "
", +} + +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) +} diff --git a/go/cmd/dolt/commands/schcmds/export.go b/go/cmd/dolt/commands/schcmds/export.go new file mode 100644 index 0000000000..a81ce0fcb7 --- /dev/null +++ b/go/cmd/dolt/commands/schcmds/export.go @@ -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{ + "
", +} + +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() +} diff --git a/go/cmd/dolt/commands/schcmds/import.go b/go/cmd/dolt/commands/schcmds/import.go new file mode 100644 index 0000000000..b47564fab3 --- /dev/null +++ b/go/cmd/dolt/commands/schcmds/import.go @@ -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 ] [--pks ]
", +} + +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) +} diff --git a/go/cmd/dolt/commands/schcmds/rename_column.go b/go/cmd/dolt/commands/schcmds/rename_column.go new file mode 100644 index 0000000000..675238824c --- /dev/null +++ b/go/cmd/dolt/commands/schcmds/rename_column.go @@ -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 = "dolt schema rename-column 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{ + "
", +} + +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) +} diff --git a/go/cmd/dolt/commands/schcmds/schema.go b/go/cmd/dolt/commands/schcmds/schema.go new file mode 100644 index 0000000000..efbd771ce3 --- /dev/null +++ b/go/cmd/dolt/commands/schcmds/schema.go @@ -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}, +}) diff --git a/go/cmd/dolt/commands/schcmds/show.go b/go/cmd/dolt/commands/schcmds/show.go new file mode 100644 index 0000000000..eab4717564 --- /dev/null +++ b/go/cmd/dolt/commands/schcmds/show.go @@ -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{ + "[] [
...]", +} + +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() + } +} diff --git a/go/cmd/dolt/commands/schema.go b/go/cmd/dolt/commands/schema.go deleted file mode 100644 index 11adcd1140..0000000000 --- a/go/cmd/dolt/commands/schema.go +++ /dev/null @@ -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{ - "[] [
...]", - "--export
", - "--add-column [--default ] [--not-null] [--tag ]
", - "--rename-column
", - "--drop-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) -} diff --git a/go/cmd/dolt/commands/schema_test.go b/go/cmd/dolt/commands/schema_test.go deleted file mode 100644 index 5011273666..0000000000 --- a/go/cmd/dolt/commands/schema_test.go +++ /dev/null @@ -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) - } - } -} -*/ diff --git a/go/cmd/dolt/dolt.go b/go/cmd/dolt/dolt.go index 79f47be6d7..0350a53206 100644 --- a/go/cmd/dolt/dolt.go +++ b/go/cmd/dolt/dolt.go @@ -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},