Repository: ariga/atlas
Pull request #295 (2021-12-08 12:55:16)

internal/integration: test sqlite
- internal/integration: extend postgres testing
- internal/integration: test sqlite



Patch:
diff --git a/schema/schemaspec/schemahcl/hcl.go b/schema/schemaspec/schemahcl/hcl.go
index 885ad871..2231decf 100644
--- a/schema/schemaspec/schemahcl/hcl.go
+++ b/schema/schemaspec/schemahcl/hcl.go
@@ -301,11 +301,18 @@ func hclType(spec *schemaspec.TypeSpec, typ *schemaspec.Type) (string, error) {
 		if !ok {
 			continue
 		}
-		lit, ok := arg.V.(*schemaspec.LiteralValue)
-		if !ok {
-			return "", errors.New("expecting literal value")
+		switch val := arg.V.(type) {
+		case *schemaspec.LiteralValue:
+			args = append(args, val.V)
+		case *schemaspec.ListValue:
+			for _, li := range val.V {
+				lit, ok := li.(*schemaspec.LiteralValue)
+				if !ok {
+					return "", errors.New("expecting literal value")
+				}
+				args = append(args, lit.V)
+			}
 		}
-		args = append(args, lit.V)
 	}
 	return fmt.Sprintf("%s(%s)", typ.T, strings.Join(args, ",")), nil
 }
diff --git a/schema/schemaspec/schemahcl/opts.go b/schema/schemaspec/schemahcl/opts.go
index 0e3e0d0c..13476e5a 100644
--- a/schema/schemaspec/schemahcl/opts.go
+++ b/schema/schemaspec/schemahcl/opts.go
@@ -44,7 +44,8 @@ func EvalContext(ctx *hcl.EvalContext) Option {
 // WithTypes configures the list of given types as identifiers in the unmarshaling context.
 func WithTypes(typeSpecs []*schemaspec.TypeSpec) Option {
 	return func(config *Config) {
-		for _, typeSpec := range typeSpecs {
+		for _, ts := range typeSpecs {
+			typeSpec := ts
 			config.types = append(config.types, typeSpec)
 			if len(typeFuncArgs(typeSpec)) == 0 {
 				typ := &schemaspec.Type{T: typeSpec.T}
@@ -60,24 +61,42 @@ func WithTypes(typeSpecs []*schemaspec.TypeSpec) Option {
 					AllowNull: !arg.Required,
 				}
 				switch arg.Kind {
+				case reflect.Slice:
+					p.Type = cty.DynamicPseudoType
+					spec.VarParam = &p
 				case reflect.String:
 					p.Type = cty.String
+					spec.Params = append(spec.Params, p)
 				case reflect.Int, reflect.Float32:
 					p.Type = cty.Number
+					spec.Params = append(spec.Params, p)
 				case reflect.Bool:
 					p.Type = cty.Bool
+					spec.Params = append(spec.Params, p)
 				}
-				spec.Params = append(spec.Params, p)
 				spec.Impl = func(args []cty.Value, retType cty.Type) (cty.Value, error) {
 					t := &schemaspec.Type{
 						T: typeSpec.T,
 					}
-					for i, arg := range args {
-						v, err := extractLiteralValue(arg)
-						if err != nil {
-							return cty.NilVal, err
+					if spec.VarParam != nil {
+						lst := &schemaspec.ListValue{}
+						for _, arg := range args {
+							v, err := extractLiteralValue(arg)
+							if err != nil {
+								return cty.NilVal, err
+							}
+							lst.V = append(lst.V, v)
+						}
+						t.Attributes = append(t.Attributes, &schemaspec.Attr{K: spec.VarParam.Name, V: lst})
+					} else {
+						for i, arg := range args {
+							v, err := extractLiteralValue(arg)
+							if err != nil {
+								return cty.NilVal, err
+							}
+							attrName := typeSpec.Attributes[i].Name
+							t.Attributes = append(t.Attributes, &schemaspec.Attr{K: attrName, V: v})
 						}
-						t.Attributes = append(t.Attributes, &schemaspec.Attr{K: typeSpec.Attributes[i].Name, V: v})
 					}
 					return cty.CapsuleVal(ctyTypeSpec, t), nil
 				}


Test patch:
diff --git a/internal/integration/sqlite_test.go b/internal/integration/sqlite_test.go
index 410f0553..8386199f 100644
--- a/internal/integration/sqlite_test.go
+++ b/internal/integration/sqlite_test.go
@@ -396,6 +396,64 @@ schema "public" {
 	})
 }
 
+func TestSQLite_Sanity(t *testing.T) {
+	n := "atlas_types_sanity"
+	ddl := `
+create table atlas_types_sanity
+(
+    "tInteger"                 integer(10)                     default 100                                   null,
+    "tReal"                    real(10)                        default 100                                   null,
+    "tText"                    text(10)                        default 'I am Text'                       not null,
+    "tBlob"                    blob(10)                        default 'A'                               not null
+);
+`
+	liteRun(t, func(t *liteTest) {
+		t.dropTables(n)
+		_, err := t.db.Exec(ddl)
+		require.NoError(t, err)
+		realm := t.loadRealm()
+		require.Len(t, realm.Schemas, 1)
+		ts, ok := realm.Schemas[0].Table(n)
+		require.True(t, ok)
+		expected := schema.Table{
+			Name:   n,
+			Schema: realm.Schemas[0],
+			Attrs:  ts.Attrs,
+			Columns: []*schema.Column{
+				{
+					Name: "tInteger",
+					Type: &schema.ColumnType{Type: &schema.IntegerType{T: "integer", Unsigned: false}, Raw: "integer(10)", Null: true},
+					Default: &schema.RawExpr{
+						X: "100",
+					},
+				},
+				{
+					Name: "tReal",
+					Type: &schema.ColumnType{Type: &schema.FloatType{T: "real", Precision: 0}, Raw: "real(10)", Null: true},
+					Default: &schema.RawExpr{
+						X: "100",
+					},
+				},
+				{
+					Name: "tText",
+					Type: &schema.ColumnType{Type: &schema.StringType{T: "text", Size: 10}, Raw: "text(10)", Null: false},
+					Default: &schema.RawExpr{
+						X: "'I am Text'",
+					},
+				},
+				{
+					Name: "tBlob",
+					Type: &schema.ColumnType{Type: &schema.BinaryType{T: "blob", Size: 0}, Raw: "blob(10)", Null: false},
+					Default: &schema.RawExpr{
+						X: "'A'",
+					},
+				},
+			},
+		}
+		require.EqualValues(t, &expected, ts)
+	})
+}
+
 func (t *liteTest) applyHcl(spec string) {
 	realm := t.loadRealm()
 	var desired schema.Schema
diff --git a/schema/schemaspec/schemahcl/context_test.go b/schema/schemaspec/schemahcl/context_test.go
index 030e9583..d4826d2c 100644
--- a/schema/schemaspec/schemahcl/context_test.go
+++ b/schema/schemaspec/schemahcl/context_test.go
@@ -352,9 +352,10 @@ x = from_ctx
 }
 
 func TestWithTypes(t *testing.T) {
-	f := `first  = int
-second = bool
-sized  = varchar(255)
+	f := `first    = int
+second   = bool
+sized    = varchar(255)
+variadic = enum("a","b","c")
 `
 	s := New(
 		WithTypes(
@@ -374,13 +375,21 @@ sized  = varchar(255)
 						{Name: "size", Kind: reflect.Int, Required: false},
 					},
 				},
+				{
+					Name: "enum",
+					T:    "enum",
+					Attributes: []*schemaspec.TypeAttr{
+						{Name: "values", Kind: reflect.Slice, Required: false},
+					},
+				},
 			},
 		),
 	)
 	var test struct {
-		First   *schemaspec.Type `spec:"first"`
-		Second  *schemaspec.Type `spec:"second"`
-		Varchar *schemaspec.Type `spec:"sized"`
+		First    *schemaspec.Type `spec:"first"`
+		Second   *schemaspec.Type `spec:"second"`
+		Varchar  *schemaspec.Type `spec:"sized"`
+		Variadic *schemaspec.Type `spec:"variadic"`
 	}
 	err := s.UnmarshalSpec([]byte(f), &test)
 	require.NoError(t, err)
@@ -392,6 +401,21 @@ sized  = varchar(255)
 			{K: "size", V: &schemaspec.LiteralValue{V: "255"}},
 		},
 	}, test.Varchar)
+	require.EqualValues(t, &schemaspec.Type{
+		T: "enum",
+		Attributes: []*schemaspec.Attr{
+			{
+				K: "values",
+				V: &schemaspec.ListValue{
+					V: []schemaspec.Value{
+						&schemaspec.LiteralValue{V: `"a"`},
+						&schemaspec.LiteralValue{V: `"b"`},
+						&schemaspec.LiteralValue{V: `"c"`},
+					},
+				},
+			},
+		},
+	}, test.Variadic)
 	after, err := s.MarshalSpec(&test)
 	require.NoError(t, err)
 	require.EqualValues(t, f, string(after))