Merge pull request #728 from liquidata-inc/andy/schema-export-tags

added --with-tags flag to schema export
This commit is contained in:
AndyA
2020-06-05 14:49:33 -05:00
committed by GitHub
12 changed files with 65 additions and 33 deletions

View File

@@ -82,3 +82,12 @@ teardown() {
[[ ! "$output" =~ "working" ]] || false
[[ ! "$output" =~ "dolt_" ]] || false
}
@test "dolt schema export --with-tags" {
run dolt schema export
[ "$status" -eq 0 ]
[[ ! "$output" =~ "COMMENT 'tag:" ]] || false
run dolt schema export --with-tags
[ "$status" -eq 0 ]
[[ "$output" =~ "COMMENT 'tag:" ]] || false
}

View File

@@ -466,18 +466,18 @@ func tabularSchemaDiff(tableName string, tags []uint64, diffs map[uint64]diff.Sc
newPks = append(newPks, sqlfmt.QuoteIdentifier(dff.New.Name))
oldPks = append(oldPks, sqlfmt.QuoteIdentifier(dff.Old.Name))
}
cli.Println(sqlfmt.FmtCol(4, 0, 0, *dff.New))
cli.Println(sqlfmt.FmtColWithTag(4, 0, 0, *dff.New))
case diff.SchDiffColAdded:
if dff.New.IsPartOfPK {
newPks = append(newPks, sqlfmt.QuoteIdentifier(dff.New.Name))
}
cli.Println(color.GreenString("+ " + sqlfmt.FmtCol(2, 0, 0, *dff.New)))
cli.Println(color.GreenString("+ " + sqlfmt.FmtColWithTag(2, 0, 0, *dff.New)))
case diff.SchDiffColRemoved:
// removed from sch2
if dff.Old.IsPartOfPK {
oldPks = append(oldPks, sqlfmt.QuoteIdentifier(dff.Old.Name))
}
cli.Println(color.RedString("- " + sqlfmt.FmtCol(2, 0, 0, *dff.Old)))
cli.Println(color.RedString("- " + sqlfmt.FmtColWithTag(2, 0, 0, *dff.Old)))
case diff.SchDiffColModified:
// changed in sch2
oldSqlType := dff.Old.TypeInfo.ToSqlType()
@@ -507,7 +507,7 @@ func tabularSchemaDiff(tableName string, tags []uint64, diffs map[uint64]diff.Sc
} else {
newPks = append(newPks, sqlfmt.QuoteIdentifier(n1))
}
cli.Println(sqlfmt.FmtCol(4, 0, 0, *dff.New))
cli.Println(sqlfmt.FmtColWithTag(4, 0, 0, *dff.New))
} else {
cli.Println("< " + sqlfmt.FmtColWithNameAndType(2, nameLen, typeLen, n0, t0, *dff.Old))
cli.Println("> " + sqlfmt.FmtColWithNameAndType(2, nameLen, typeLen, n1, t1, *dff.New))
@@ -536,7 +536,7 @@ func sqlSchemaDiff(tableName string, tags []uint64, diffs map[uint64]diff.Schema
switch dff.DiffType {
case diff.SchDiffNone:
case diff.SchDiffColAdded:
cli.Println(sqlfmt.AlterTableAddColStmt(tableName, sqlfmt.FmtCol(0, 0, 0, *dff.New)))
cli.Println(sqlfmt.AlterTableAddColStmt(tableName, sqlfmt.FmtColWithTag(0, 0, 0, *dff.New)))
case diff.SchDiffColRemoved:
cli.Print(sqlfmt.AlterTableDropColStmt(tableName, dff.Old.Name))
case diff.SchDiffColModified:

View File

@@ -40,7 +40,7 @@ var schExportDocs = cli.CommandDocumentationContent{
}
const (
//exportAllSchFlag = "all"
withTagsFlag = "with-tags"
)
type ExportCmd struct{}
@@ -65,7 +65,7 @@ func (cmd ExportCmd) createArgParser() *argparser.ArgParser {
ap := argparser.NewArgParser()
ap.ArgListHelp = append(ap.ArgListHelp, [2]string{"table", "table whose schema is being exported."})
ap.ArgListHelp = append(ap.ArgListHelp, [2]string{"commit", "commit at which point the schema will be displayed."})
//ap.SupportsFlag(exportAllSchFlag, "a", "If provided, and <table> arg is not provided, system tables will be exported")
ap.SupportsFlag(withTagsFlag, "", "Include column tags in exported schema")
return ap
}
@@ -131,7 +131,7 @@ func exportSchemas(ctx context.Context, apr *argparser.ArgParseResults, root *do
}
for _, tn := range tablesToExport {
verr := exportTblSchema(ctx, tn, root, wr)
verr := exportTblSchema(ctx, tn, root, wr, apr.Contains(withTagsFlag))
if verr != nil {
return verr
}
@@ -140,7 +140,7 @@ func exportSchemas(ctx context.Context, apr *argparser.ArgParseResults, root *do
return nil
}
func exportTblSchema(ctx context.Context, tblName string, root *doltdb.RootValue, wr io.Writer) errhand.VerboseError {
func exportTblSchema(ctx context.Context, tblName string, root *doltdb.RootValue, wr io.Writer, withTags bool) errhand.VerboseError {
if has, err := root.HasTable(ctx, tblName); err != nil {
return errhand.BuildDError("unable to read from database").AddCause(err).Build()
} else if !has {
@@ -159,6 +159,13 @@ func exportTblSchema(ctx context.Context, tblName string, root *doltdb.RootValue
return errhand.BuildDError("error: failed to get schema for table %s", tblName).AddCause(err).Build()
}
_, err = fmt.Fprintln(wr, sqlfmt.SchemaAsCreateStmt(tblName, sch))
var stmt string
if withTags {
stmt = sqlfmt.CreateTableStmtWithTags(tblName, sch)
} else {
stmt = sqlfmt.CreateTableStmt(tblName, sch)
}
_, err = fmt.Fprintln(wr, stmt)
return errhand.BuildIf(err, "error writing schema for table %s", tblName).AddCause(err).Build()
}

View File

@@ -285,7 +285,7 @@ func importSchema(ctx context.Context, dEnv *env.DoltEnv, apr *argparser.ArgPars
}
tblName := impArgs.tableName
cli.Println(sqlfmt.SchemaAsCreateStmt(tblName, sch))
cli.Println(sqlfmt.CreateTableStmtWithTags(tblName, sch))
if !apr.Contains(dryRunFlag) {
tbl, tblExists, err := root.GetTable(ctx, tblName)

View File

@@ -165,6 +165,6 @@ func printTblSchema(ctx context.Context, cmStr string, tblName string, tbl *dolt
return errhand.BuildDError("unable to get schema").AddCause(err).Build()
}
cli.Println(sqlfmt.SchemaAsCreateStmt(tblName, sch))
cli.Println(sqlfmt.CreateTableStmtWithTags(tblName, sch))
return nil
}

View File

@@ -179,7 +179,7 @@ func PrintSqlTableDiffs(ctx context.Context, r1, r2 *doltdb.RootValue, wr io.Wri
if sch, err := tbl.GetSchema(ctx); err != nil {
return errors.New("error unable to get schema for table " + tblName)
} else {
stmt := sqlfmt.SchemaAsCreateStmt(tblName, sch)
stmt := sqlfmt.CreateTableStmtWithTags(tblName, sch)
if err = iohelp.WriteLine(wr, stmt); err != nil {
return err
}

View File

@@ -67,7 +67,7 @@ func TestSqlTableDiffAdd(t *testing.T) {
var stringWr StringBuilderCloser
_ = PrintSqlTableDiffs(ctx, newRoot, oldRoot, &stringWr)
expectedOutput := sqlfmt.SchemaAsCreateStmt("addTable", sch) + "\n"
expectedOutput := sqlfmt.CreateTableStmtWithTags("addTable", sch) + "\n"
assert.Equal(t, expectedOutput, stringWr.String())
}
@@ -88,7 +88,7 @@ func TestSqlTableDiffAddThenInsert(t *testing.T) {
var stringWr StringBuilderCloser
_ = PrintSqlTableDiffs(ctx, newRoot, oldRoot, &stringWr)
expectedOutput := sqlfmt.SchemaAsCreateStmt("addTable", sch) + "\n"
expectedOutput := sqlfmt.CreateTableStmtWithTags("addTable", sch) + "\n"
expectedOutput = expectedOutput +
"INSERT INTO `addTable` (`id`,`name`,`age`,`is_married`,`title`) " +
"VALUES ('00000000-0000-0000-0000-000000000000','Big Billy',77,FALSE,'Doctor');\n"
@@ -149,7 +149,7 @@ func TestSqlTableDiffRenameChangedTable(t *testing.T) {
_ = PrintSqlTableDiffs(ctx, newRoot, oldRoot, &stringWr)
expectedOutput := "DROP TABLE `renameTable`;\n"
expectedOutput = expectedOutput +
sqlfmt.SchemaAsCreateStmt("newTableName", sch) + "\n" +
sqlfmt.CreateTableStmtWithTags("newTableName", sch) + "\n" +
"INSERT INTO `newTableName` (`id`,`name`,`age`,`is_married`,`title`) " +
"VALUES ('00000000-0000-0000-0000-000000000000','Big Billy',77,FALSE,'Doctor');\n"
assert.Equal(t, expectedOutput, stringWr.String())

View File

@@ -56,7 +56,7 @@ type test struct {
func TestSchemaAsCreateStmt(t *testing.T) {
tSchema := sqltestutil.PeopleTestSchema
stmt := SchemaAsCreateStmt("table_name", tSchema)
stmt := CreateTableStmtWithTags("table_name", tSchema)
assert.Equal(t, expectedCreateSQL, stmt)
}

View File

@@ -23,13 +23,19 @@ import (
const TagCommentPrefix = "tag:"
// FmtCol converts a column to a string with a given indent space count, name width, and type width. If nameWidth or
// FmtCol converts a column to a string with a given indent space count, name width, and type width. If nameWidth or
// typeWidth are 0 or less than the length of the name or type, then the length of the name or type will be used
func FmtCol(indent, nameWidth, typeWidth int, col schema.Column) string {
sqlType := col.TypeInfo.ToSqlType()
return FmtColWithNameAndType(indent, nameWidth, typeWidth, col.Name, sqlType.String(), col)
}
// FmtColWithTag follows the same logic as FmtCol, but includes the column's tag as a comment
func FmtColWithTag(indent, nameWidth, typeWidth int, col schema.Column) string {
fc := FmtCol(indent, nameWidth, typeWidth, col)
return fmt.Sprintf("%s COMMENT '%s'", fc, FmtColTagComment(col.Tag))
}
// FmtColWithNameAndType creates a string representing a column within a sql create table statement with a given indent
// space count, name width, and type width. If nameWidth or typeWidth are 0 or less than the length of the name or
// type, then the length of the name or type will be used.
@@ -47,7 +53,7 @@ func FmtColWithNameAndType(indent, nameWidth, typeWidth int, colName, typeStr st
}
}
return colStr + fmt.Sprintf(" COMMENT 'tag:%d'", col.Tag)
return colStr
}
// FmtColPrimaryKey creates a string representing a primary key constraint within a sql create table statement with a
@@ -61,11 +67,26 @@ func FmtColTagComment(tag uint64) string {
return fmt.Sprintf("%s%d", TagCommentPrefix, tag)
}
// SchemaAsCreateStmt takes a Schema and returns a string representing a SQL create table command that could be used to
// create this table
func SchemaAsCreateStmt(tableName string, sch schema.Schema) string {
// CreateTableStmtWithTags generates a SQL CREATE TABLE command
func CreateTableStmt(tableName string, sch schema.Schema) string {
return createTableStmt(tableName, sch, func(col schema.Column) string {
return FmtCol(2, 0, 0, col)
})
}
// CreateTableStmtWithTags generates a SQL CREATE TABLE command that includes the column tags as comments
func CreateTableStmtWithTags(tableName string, sch schema.Schema) string {
return createTableStmt(tableName, sch, func(col schema.Column) string {
return FmtColWithTag(2, 0, 0, col)
})
}
type fmtColFunc func(col schema.Column) string
func createTableStmt(tableName string, sch schema.Schema, fmtCol fmtColFunc) string {
sb := &strings.Builder{}
fmt.Fprintf(sb, "CREATE TABLE %s (\n", QuoteIdentifier(tableName))
sb.WriteString(fmt.Sprintf("CREATE TABLE %s (\n", QuoteIdentifier(tableName)))
firstLine := true
_ = sch.GetAllCols().Iter(func(tag uint64, col schema.Column) (stop bool, err error) {
@@ -75,14 +96,14 @@ func SchemaAsCreateStmt(tableName string, sch schema.Schema) string {
sb.WriteString(",\n")
}
s := FmtCol(2, 0, 0, col)
s := fmtCol(col)
sb.WriteString(s)
return false, nil
})
firstPK := true
err := sch.GetPKCols().Iter(func(tag uint64, col schema.Column) (stop bool, err error) {
_ = sch.GetPKCols().Iter(func(tag uint64, col schema.Column) (stop bool, err error) {
if firstPK {
sb.WriteString(",\n PRIMARY KEY (")
firstPK = false
@@ -93,11 +114,6 @@ func SchemaAsCreateStmt(tableName string, sch schema.Schema) string {
return false, nil
})
// TODO: fix panics
if err != nil {
panic(err)
}
sb.WriteRune(')')
for _, index := range sch.Indexes().AllIndexes() {

View File

@@ -63,7 +63,7 @@ func TestFmtCol(t *testing.T) {
for _, test := range tests {
t.Run(test.Expected, func(t *testing.T) {
actual := FmtCol(test.Indent, test.NameWidth, test.TypeWidth, test.Col)
actual := FmtColWithTag(test.Indent, test.NameWidth, test.TypeWidth, test.Col)
assert.Equal(t, test.Expected, actual)
})
}

View File

@@ -83,7 +83,7 @@ func (w *SqlExportWriter) maybeWriteDropCreate() error {
var b strings.Builder
b.WriteString(sqlfmt.DropTableIfExistsStmt(w.tableName))
b.WriteRune('\n')
b.WriteString(sqlfmt.SchemaAsCreateStmt(w.tableName, w.sch))
b.WriteString(sqlfmt.CreateTableStmtWithTags(w.tableName, w.sch))
if err := iohelp.WriteLine(w.wr, b.String()); err != nil {
return err
}

View File

@@ -47,7 +47,7 @@ func TestEndToEnd(t *testing.T) {
id := uuid.MustParse("00000000-0000-0000-0000-000000000000")
tableName := "people"
dropCreateStatement := sqlfmt.DropTableIfExistsStmt(tableName) + "\n" + sqlfmt.SchemaAsCreateStmt(tableName, dtestutils.TypedSchema)
dropCreateStatement := sqlfmt.DropTableIfExistsStmt(tableName) + "\n" + sqlfmt.CreateTableStmtWithTags(tableName, dtestutils.TypedSchema)
type test struct {
name string