Repository: ariga/atlas
Pull request #1190 (2022-10-11 14:49:54)

sql/postgres: support inspecting domains as user-defined types
Fixed https://github.com/ariga/atlas/issues/1186.


Patch:
diff --git a/sql/postgres/convert.go b/sql/postgres/convert.go
index 342e272b..352324d3 100644
--- a/sql/postgres/convert.go
+++ b/sql/postgres/convert.go
@@ -254,14 +254,19 @@ func columnType(c *columnDesc) (schema.Type, error) {
 		}
 	case TypeUserDefined:
 		typ = &UserDefinedType{T: c.fmtype}
+	default:
+		typ = &schema.UnsupportedType{T: t}
+	}
+	switch c.typtype {
+	case "e":
 		// The `typtype` column is set to 'e' for enum types, and the
 		// values are filled in batch after the rows above is closed.
 		// https://postgresql.org/docs/current/catalog-pg-type.html
-		if c.typtype == "e" {
-			typ = newEnumType(c.fmtype, c.typid)
-		}
-	default:
-		typ = &schema.UnsupportedType{T: t}
+		typ = newEnumType(c.fmtype, c.typid)
+	case "d":
+		// Use user-defined for domain types as we do not
+		// support their creation at this stage.
+		typ = &UserDefinedType{T: c.fmtype}
 	}
 	return typ, nil
 }
diff --git a/sql/postgres/inspect.go b/sql/postgres/inspect.go
index 146d5402..afe6fd99 100644
--- a/sql/postgres/inspect.go
+++ b/sql/postgres/inspect.go
@@ -986,7 +986,7 @@ FROM
 	JOIN pg_catalog.pg_namespace AS t2 ON t2.nspname = t1.table_schema
 	JOIN pg_catalog.pg_class AS t3 ON t3.relnamespace = t2.oid AND t3.relname = t1.table_name
 	JOIN pg_catalog.pg_attribute AS a ON a.attrelid = t3.oid AND a.attname = t1.column_name
-	LEFT JOIN pg_catalog.pg_type AS t4 ON t1.udt_name = t4.typname AND t4.typnamespace = t2.oid
+	LEFT JOIN pg_catalog.pg_type AS t4 ON t4.oid = a.atttypid
 WHERE
 	t1.table_schema = $1 AND t1.table_name IN (%s)
 ORDER BY


Test patch:
diff --git a/internal/integration/testdata/postgres/column-domain.txt b/internal/integration/testdata/postgres/column-domain.txt
new file mode 100644
index 00000000..82d4d9a0
--- /dev/null
+++ b/internal/integration/testdata/postgres/column-domain.txt
@@ -0,0 +1,32 @@
+execsql 'CREATE DOMAIN script_column_domain.positive_int AS bigint CHECK (VALUE > 0)'
+
+apply 1.hcl
+cmpshow users 1.sql
+cmphcl 1.inspect.hcl
+
+-- 1.hcl --
+schema "script_column_domain" {}
+
+table "users" {
+  schema = schema.script_column_domain
+  column "c1" {
+    type = sql("script_column_domain.positive_int")
+  }
+}
+
+-- 1.sql --
+                     Table "script_column_domain.users"
+ Column |               Type                | Collation | Nullable | Default
+--------+-----------------------------------+-----------+----------+---------
+ c1     | script_column_domain.positive_int |           | not null |
+
+-- 1.inspect.hcl --
+table "users" {
+  schema = schema.script_column_domain
+  column "c1" {
+    null = false
+    type = sql("script_column_domain.positive_int")
+  }
+}
+schema "script_column_domain" {
+}
\ No newline at end of file
diff --git a/sql/postgres/inspect_test.go b/sql/postgres/inspect_test.go
index 720ea92d..6dc62d73 100644
--- a/sql/postgres/inspect_test.go
+++ b/sql/postgres/inspect_test.go
@@ -79,6 +79,7 @@ func TestDriver_InspectTable(t *testing.T) {
  users       |  c32         | bigint                      | int4                | NO          | nextval('public.t1_c32_seq'::regclass) |                          |                32 |                    |             0 |                     |                    |                | NO          |                |                    |                  |                     |                       |         | b       |         |         |    23
  users       |  c33         | USER-DEFINED                | test."status""."    | NO          |  'unknown'::test."status""."           |                          |                   |                    |               |                     |                    |                | NO          |                |                    |                  |                     |                       |         | e       |         |         | 16775
  users       |  c34         | ARRAY                       | state[]             | NO          |                                        |                          |                   |                    |               |                     |                    |                | NO          |                |                    |                  |                     |                       |         | b       |  16774  |  e      | 16779
+ users       |  c35         | character                   | domain_char         | NO          |                                        |                          |                   |                    |               |                     |                    |                | NO          |                |                    |                  |                     |                       |         | d       |  16774  |  e      | 16779
 `))
 				m.ExpectQuery(sqltest.Escape(`SELECT enumtypid, enumlabel FROM pg_enum WHERE enumtypid IN ($1, $2)`)).
 					WithArgs(16774, 16775).
@@ -134,6 +135,7 @@ func TestDriver_InspectTable(t *testing.T) {
 					{Name: "c32", Type: &schema.ColumnType{Raw: "bigserial", Type: &SerialType{T: "bigserial", SequenceName: "t1_c32_seq"}}},
 					{Name: "c33", Type: &schema.ColumnType{Raw: `status".`, Type: &schema.EnumType{T: `status".`, Values: []string{"unknown"}, Schema: schema.New("test")}}, Default: &schema.Literal{V: "'unknown'"}},
 					{Name: "c34", Type: &schema.ColumnType{Raw: "ARRAY", Type: &ArrayType{T: "state[]", Type: &schema.EnumType{T: "state", Values: []string{"on", "off"}, Schema: t.Schema}}}},
+					{Name: "c35", Type: &schema.ColumnType{Raw: "character", Type: &UserDefinedType{T: "domain_char"}}},
 				}, t.Columns)
 			},
 		},