Repository: ariga/atlas
Pull request #2682 (2024-04-14 18:59:31)

sql/postgres: support inspect/marshal bpchar column types


Patch:
diff --git a/sql/postgres/convert.go b/sql/postgres/convert.go
index aff0da53..74a51f05 100644
--- a/sql/postgres/convert.go
+++ b/sql/postgres/convert.go
@@ -67,7 +67,7 @@ func FormatType(t schema.Type) (string, error) {
 		}
 	case *schema.StringType:
 		switch f = strings.ToLower(t.T); f {
-		case TypeText, typeName:
+		case TypeText, TypeBPChar, typeName:
 		// CHAR(n) is alias for CHARACTER(n). If not length was
 		// specified, the definition is equivalent to CHARACTER(1).
 		case TypeChar, TypeCharacter:
@@ -217,7 +217,10 @@ func columnType(c *columnDesc) (schema.Type, error) {
 		typ = &schema.BoolType{T: t}
 	case TypeBytea:
 		typ = &schema.BinaryType{T: t}
-	case TypeCharacter, TypeChar, TypeCharVar, TypeVarChar, TypeText, typeName:
+	case TypeCharacter, TypeChar, TypeCharVar, TypeVarChar, TypeText, TypeBPChar, typeName:
+		if t == TypeCharacter && c.size == 0 && c.fmtype == TypeBPChar {
+			t = TypeBPChar
+		}
 		// A `character` column without length specifier is equivalent to `character(1)`,
 		// but `varchar` without length accepts strings of any size (same as `text`).
 		typ = &schema.StringType{T: t, Size: int(c.size)}
diff --git a/sql/postgres/sqlspec.go b/sql/postgres/sqlspec.go
index c035f8c5..a0bd1878 100644
--- a/sql/postgres/sqlspec.go
+++ b/sql/postgres/sqlspec.go
@@ -823,6 +823,7 @@ var TypeRegistry = schemahcl.NewRegistry(
 		schemahcl.AliasTypeSpec("character_varying", TypeCharVar, schemahcl.WithAttributes(schemahcl.SizeTypeAttr(false))),
 		schemahcl.NewTypeSpec(TypeChar, schemahcl.WithAttributes(schemahcl.SizeTypeAttr(false))),
 		schemahcl.NewTypeSpec(TypeCharacter, schemahcl.WithAttributes(schemahcl.SizeTypeAttr(false))),
+		schemahcl.NewTypeSpec(TypeBPChar),
 		schemahcl.NewTypeSpec(TypeInt2),
 		schemahcl.NewTypeSpec(TypeInt4),
 		schemahcl.NewTypeSpec(TypeInt8),


Test patch:
diff --git a/internal/integration/testdata/postgres/column-default.txt b/internal/integration/testdata/postgres/column-default.txt
index 5bfe9346..23134d45 100644
--- a/internal/integration/testdata/postgres/column-default.txt
+++ b/internal/integration/testdata/postgres/column-default.txt
@@ -1,5 +1,7 @@
 apply 1.hcl
 cmpshow users 1.sql
+atlas schema inspect -u URL > got
+cmp 1.inspected.hcl got
 
 # Change column default.
 apply 2.hcl
@@ -22,8 +24,38 @@ table "users" {
     type = boolean
     default = true
   }
+  column "bpchar" {
+    type = bpchar
+    default = "foo"
+  }
 }
 
+-- 1.inspected.hcl --
+table "users" {
+  schema = schema.script_column_default
+  column "name" {
+    null    = false
+    type    = character_varying
+    default = "unknown"
+  }
+  column "age" {
+    null    = false
+    type    = integer
+    default = 1
+  }
+  column "active" {
+    null    = false
+    type    = boolean
+    default = true
+  }
+  column "bpchar" {
+    null    = false
+    type    = bpchar
+    default = "foo"
+  }
+}
+schema "script_column_default" {
+}
 -- 1.sql --
                        Table "script_column_default.users"
  Column |       Type        | Collation | Nullable |           Default
@@ -31,7 +63,7 @@ table "users" {
  name   | character varying |           | not null | 'unknown'::character varying
  age    | integer           |           | not null | 1
  active | boolean           |           | not null | true
-
+ bpchar | bpchar            |           | not null | 'foo'::bpchar
 
 -- 2.hcl --
 schema "$db" {}
diff --git a/sql/postgres/sqlspec_test.go b/sql/postgres/sqlspec_test.go
index afb48400..ab343eb9 100644
--- a/sql/postgres/sqlspec_test.go
+++ b/sql/postgres/sqlspec_test.go
@@ -1609,6 +1609,10 @@ func TestTypes(t *testing.T) {
 			typeExpr: "text",
 			expected: &schema.StringType{T: TypeText},
 		},
+		{
+			typeExpr: "bpchar",
+			expected: &schema.StringType{T: TypeBPChar},
+		},
 		{
 			typeExpr: "smallint",
 			expected: &schema.IntegerType{T: TypeSmallInt},