Repository: ariga/atlas
Pull request #260 (2021-11-28 14:21:58)

sql: multiple bug fixes in hcl inspect/apply


Patch:
diff --git a/sql/mysql/convert.go b/sql/mysql/convert.go
index b29a4c70..993f7f28 100644
--- a/sql/mysql/convert.go
+++ b/sql/mysql/convert.go
@@ -64,6 +64,8 @@ func (d *Driver) FormatType(t schema.Type) (string, error) {
 		f = strings.ToLower(t.T)
 	case *schema.TimeType:
 		f = strings.ToLower(t.T)
+	case *schema.UnsupportedType:
+		return "", fmt.Errorf("mysql: unsupported type: %q", t.T)
 	default:
 		return "", fmt.Errorf("mysql: invalid schema type: %T", t)
 	}
diff --git a/sql/mysql/sqlspec.go b/sql/mysql/sqlspec.go
index 40aee6ca..a5b95797 100644
--- a/sql/mysql/sqlspec.go
+++ b/sql/mysql/sqlspec.go
@@ -253,7 +253,7 @@ func columnSpec(col *schema.Column) (*sqlspec.Column, error) {
 	return &sqlspec.Column{
 		Name: col.Name,
 		Type: ct.Type,
-		Null: ct.Null,
+		Null: col.Type.Null,
 		DefaultExtension: schemaspec.DefaultExtension{
 			Extra: schemaspec.Resource{Attrs: ct.DefaultExtension.Extra.Attrs},
 		},
diff --git a/sql/postgres/convert.go b/sql/postgres/convert.go
index acfe31b7..6bbacfed 100644
--- a/sql/postgres/convert.go
+++ b/sql/postgres/convert.go
@@ -129,6 +129,8 @@ func (d *Driver) FormatType(t schema.Type) (string, error) {
 		f = strings.ToLower(t.T)
 	case *UserDefinedType:
 		f = strings.ToLower(t.T)
+	case *schema.UnsupportedType:
+		return "", fmt.Errorf("postgres: unsupported type: %q", t.T)
 	default:
 		return "", fmt.Errorf("postgres: invalid schema type: %T", t)
 	}
diff --git a/sql/postgres/sqlspec.go b/sql/postgres/sqlspec.go
index ee3ccc30..7442183c 100644
--- a/sql/postgres/sqlspec.go
+++ b/sql/postgres/sqlspec.go
@@ -206,7 +206,13 @@ func parseRawType(spec *sqlspec.Column) (schema.Type, error) {
 	if t, ok := arrayType(spec.Type); ok {
 		d = &columnDesc{typ: tArray, udt: t}
 	}
-	return columnType(d), nil
+	t := columnType(d)
+	// If the type is unknown (to us), we fallback to user-defined but expect
+	// to improve this in future versions by ensuring this against the database.
+	if ut, ok := t.(*schema.UnsupportedType); ok {
+		t = &UserDefinedType{T: ut.T}
+	}
+	return t, nil
 }
 
 // schemaSpec converts from a concrete Postgres schema to Atlas specification.
@@ -228,7 +234,7 @@ func columnSpec(col *schema.Column) (*sqlspec.Column, error) {
 	return &sqlspec.Column{
 		Name: col.Name,
 		Type: ct.Type,
-		Null: ct.Null,
+		Null: col.Type.Null,
 		DefaultExtension: schemaspec.DefaultExtension{
 			Extra: schemaspec.Resource{Attrs: ct.DefaultExtension.Extra.Attrs},
 		},
@@ -275,6 +281,8 @@ func columnTypeSpec(t schema.Type) (*sqlspec.Column, error) {
 		return &sqlspec.Column{Type: t.T}, nil
 	case *UUIDType:
 		return &sqlspec.Column{Type: t.T}, nil
+	case *UserDefinedType:
+		return &sqlspec.Column{Type: t.T}, nil
 	case *XMLType:
 		return &sqlspec.Column{Type: t.T}, nil
 	default:
diff --git a/sql/sqlite/convert.go b/sql/sqlite/convert.go
index 01e325a4..928b48c2 100644
--- a/sql/sqlite/convert.go
+++ b/sql/sqlite/convert.go
@@ -40,6 +40,8 @@ func (d *Driver) FormatType(t schema.Type) (string, error) {
 		f = strings.ToLower(t.T)
 	case *UUIDType:
 		f = strings.ToLower(t.T)
+	case *schema.UnsupportedType:
+		return "", fmt.Errorf("sqlite: unsupported type: %q", t.T)
 	default:
 		return "", fmt.Errorf("sqlite: invalid schema type: %T", t)
 	}
diff --git a/sql/sqlite/sqlspec.go b/sql/sqlite/sqlspec.go
index c970c16d..1e7b3ad7 100644
--- a/sql/sqlite/sqlspec.go
+++ b/sql/sqlite/sqlspec.go
@@ -201,7 +201,7 @@ func columnSpec(col *schema.Column) (*sqlspec.Column, error) {
 	return &sqlspec.Column{
 		Name: col.Name,
 		Type: ct.Type,
-		Null: ct.Null,
+		Null: col.Type.Null,
 		DefaultExtension: schemaspec.DefaultExtension{
 			Extra: schemaspec.Resource{Attrs: ct.DefaultExtension.Extra.Attrs},
 		},


Test patch:
diff --git a/sql/postgres/sqlspec_test.go b/sql/postgres/sqlspec_test.go
index 39ab107b..b46cb8d6 100644
--- a/sql/postgres/sqlspec_test.go
+++ b/sql/postgres/sqlspec_test.go
@@ -29,6 +29,9 @@ table "table" {
 		type = "string"
 		size = 32
 	}
+	column "tags" {
+		type = "hstore"
+	}
 	primary_key {
 		columns = [table.table.column.col]
 	}
@@ -96,6 +99,14 @@ table "accounts" {
 						},
 					},
 				},
+				{
+					Name: "tags",
+					Type: &schema.ColumnType{
+						Type: &UserDefinedType{
+							T: "hstore",
+						},
+					},
+				},
 			},
 		},
 		{
@@ -470,6 +481,10 @@ func TestMarshalSpecColumnType(t *testing.T) {
 								Name: "column",
 								Type: &schema.ColumnType{Type: tt.schem},
 							},
+							{
+								Name: "nullable_column",
+								Type: &schema.ColumnType{Type: tt.schem, Null: true},
+							},
 						},
 					},
 				},
@@ -482,8 +497,14 @@ func TestMarshalSpecColumnType(t *testing.T) {
 			}
 			err = schemahcl.Unmarshal(ddl, &test)
 			require.NoError(t, err)
+
+			require.False(t, test.Table.Columns[0].Null)
 			require.EqualValues(t, tt.expected.Type, test.Table.Columns[0].Type)
 			require.ElementsMatch(t, tt.expected.Extra.Attrs, test.Table.Columns[0].Extra.Attrs)
+
+			require.True(t, test.Table.Columns[1].Null)
+			require.EqualValues(t, tt.expected.Type, test.Table.Columns[1].Type)
+			require.ElementsMatch(t, tt.expected.Extra.Attrs, test.Table.Columns[1].Extra.Attrs)
 		})
 	}
 }