diff --git a/krab/type_ddl_column.go b/krab/type_ddl_column.go index 1a23ae1..bd898e2 100644 --- a/krab/type_ddl_column.go +++ b/krab/type_ddl_column.go @@ -3,7 +3,7 @@ package krab import ( "fmt" "io" - "strconv" + "strings" "github.com/hashicorp/hcl/v2" "github.com/ohkrab/krab/krabdb" @@ -53,14 +53,43 @@ func (d *DDLColumn) ToSQL(w io.StringWriter) { switch defaultExpr.Type() { case cty.Bool: - w.WriteString(strconv.FormatBool(defaultExpr.AsBool())) + w.WriteString(krabdb.Quote(defaultExpr.AsBool())) + + case cty.Number: + switch strings.ToLower(d.Type) { + case "smallint", "integer", "int", "bigint", "smallserial", "serial", "bigserial": + w.WriteString(krabdb.Quote(defaultExpr.AsInt64())) + case "real", "double precision": + w.WriteString(krabdb.Quote(defaultExpr.AsFloat64())) + default: + //TODO: implement big numbers (numeric, decimal) + panic(fmt.Sprintf( + "%sCannot map default type of %s to SQL, if you see this error please report the issue with example so I can fix this%s", + ctc.BackgroundRed|ctc.ForegroundYellow, + d.Type, + ctc.Reset, + )) + } + + case cty.String: + w.WriteString(krabdb.Quote(defaultExpr.AsString())) default: - panic(fmt.Sprint( - ctc.BackgroundRed|ctc.ForegroundYellow, - "Cannot map default type to SQL, if you see this error please report the issue with example", - ctc.Reset, - )) + switch { + case defaultExpr.Type().IsObjectType(): + w.WriteString("'{}'") + + case defaultExpr.Type().IsTupleType(): + w.WriteString("'[]'") + + default: + panic(fmt.Sprintf( + "%sCannot map default type %s to SQL, if you see this error please report the issue with example so I can fix this%s", + ctc.BackgroundRed|ctc.ForegroundYellow, + d.Type, + ctc.Reset, + )) + } } } } diff --git a/krabhcl/value.go b/krabhcl/expression.go similarity index 52% rename from krabhcl/value.go rename to krabhcl/expression.go index 66af751..4ee1674 100644 --- a/krabhcl/value.go +++ b/krabhcl/expression.go @@ -20,6 +20,33 @@ func (e Expression) AsBool() bool { return false } +func (e Expression) AsInt64() int64 { + val, _ := e.Expr.Value(e.EvalContext) + var number int64 + if err := gocty.FromCtyValue(val, &number); err == nil { + return number + } + return 0 +} + +func (e Expression) AsFloat64() float64 { + val, _ := e.Expr.Value(e.EvalContext) + var number float64 + if err := gocty.FromCtyValue(val, &number); err == nil { + return number + } + return 0 +} + +func (e Expression) AsString() string { + val, _ := e.Expr.Value(e.EvalContext) + var str string + if err := gocty.FromCtyValue(val, &str); err == nil { + return str + } + return "" +} + func (e Expression) Ok() bool { val, _ := e.Expr.Value(e.EvalContext) return val.IsWhollyKnown() && !val.IsNull() diff --git a/spec/action_migrate_dsl_table_test.go b/spec/action_migrate_dsl_table_test.go index 28df588..374edbe 100644 --- a/spec/action_migrate_dsl_table_test.go +++ b/spec/action_migrate_dsl_table_test.go @@ -128,3 +128,43 @@ DROP TABLE "animals" } } } + +func TestActionMigrateDslTableDefaults(t *testing.T) { + c := mockCli(mockConfig(` +migration "create_animals" { + version = "v2" + + up { + create_table "animals" { + column "id" "bigint" { default = 1 } + column "x" "real" { default = 1.2 } + column "y" "double precision" { default = 1.3 } + column "name" "varchar" { default = "hello" } + column "extinct" "boolean" { default = true } + column "map" "jsonb" { default = {} } + column "list" "jsonb" { default = [] } + } + } + + down { + drop_table "animals" {} + } +} + +migration_set "animals" { + migrations = [ + migration.create_animals + ] +} +`)) + defer c.Teardown() + if c.AssertSuccessfulRun(t, []string{"migrate", "up", "animals"}) { + c.AssertSQLContains(t, "DEFAULT 1") + c.AssertSQLContains(t, "DEFAULT 1.2") + c.AssertSQLContains(t, "DEFAULT 1.3") + c.AssertSQLContains(t, "DEFAULT 'hello'") + c.AssertSQLContains(t, "DEFAULT true") + c.AssertSQLContains(t, "DEFAULT '{}'") + c.AssertSQLContains(t, "DEFAULT '[]'") + } +}