mirror of
https://github.com/dolthub/dolt.git
synced 2026-02-11 18:49:14 -06:00
Merge pull request #728 from liquidata-inc/andy/schema-export-tags
added --with-tags flag to schema export
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user