Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/lib/sql/columns.sql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ SELECT
END
END AS data_type,
COALESCE(bt.typname, t.typname) AS format,
CASE
WHEN t.typtype = 'd' THEN nt.nspname
ELSE NULL
END AS domain_schema,
CASE
WHEN t.typtype = 'd' THEN t.typname
ELSE NULL
END AS domain_name,
a.attidentity IN ('a', 'd') AS is_identity,
CASE
a.attidentity
Expand Down
4 changes: 4 additions & 0 deletions src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ export const postgresColumnSchema = Type.Object({
default_value: Type.Unknown(),
data_type: Type.String(),
format: Type.String(),
// Set only when the column's type is a DOMAIN. `data_type` and `format` keep
// reporting the domain's base type, as information_schema.columns does.
domain_schema: Type.Union([Type.String(), Type.Null()]),
domain_name: Type.Union([Type.String(), Type.Null()]),
is_identity: Type.Boolean(),
identity_generation: Type.Union([
Type.Literal('ALWAYS'),
Expand Down
14 changes: 13 additions & 1 deletion test/db/00-init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -500,4 +500,16 @@ LANGUAGE SQL
STABLE
AS $$
SELECT interval_test_row.duration_required * 2;
$$;
$$;

-- Domain types, to check that column introspection preserves the domain
-- identity instead of collapsing to the base type.
CREATE DOMAIN public.text_search AS jsonb CHECK (jsonb_typeof(VALUE) = 'object');
CREATE DOMAIN public.positive_int AS int4 NOT NULL CHECK (VALUE > 0);

CREATE TABLE public.domain_test (
id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
search public.text_search,
quantity public.positive_int,
plain jsonb
);
93 changes: 93 additions & 0 deletions test/lib/columns.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ test('list', async () => {
"comment": null,
"data_type": "bigint",
"default_value": null,
"domain_name": null,
"domain_schema": null,
"enums": [],
"format": "int8",
"id": StringMatching /\\^\\\\d\\+\\\\\\.3\\$/,
Expand Down Expand Up @@ -60,6 +62,8 @@ test('list from a single table', async () => {
"comment": null,
"data_type": "text",
"default_value": null,
"domain_name": null,
"domain_schema": null,
"enums": [],
"format": "text",
"id": StringMatching /\\^\\\\d\\+\\\\\\.\\\\d\\+\\$/,
Expand All @@ -80,6 +84,8 @@ test('list from a single table', async () => {
"comment": null,
"data_type": "text",
"default_value": null,
"domain_name": null,
"domain_schema": null,
"enums": [],
"format": "text",
"id": StringMatching /\\^\\\\d\\+\\\\\\.\\\\d\\+\\$/,
Expand Down Expand Up @@ -158,6 +164,8 @@ test('retrieve, create, update, delete', async () => {
"comment": "foo",
"data_type": "smallint",
"default_value": "'42'::smallint",
"domain_name": null,
"domain_schema": null,
"enums": [],
"format": "int2",
"id": StringMatching /\\^\\\\d\\+\\\\\\.1\\$/,
Expand Down Expand Up @@ -189,6 +197,8 @@ test('retrieve, create, update, delete', async () => {
"comment": "foo",
"data_type": "smallint",
"default_value": "'42'::smallint",
"domain_name": null,
"domain_schema": null,
"enums": [],
"format": "int2",
"id": StringMatching /\\^\\\\d\\+\\\\\\.1\\$/,
Expand Down Expand Up @@ -228,6 +238,8 @@ test('retrieve, create, update, delete', async () => {
"comment": "bar",
"data_type": "integer",
"default_value": null,
"domain_name": null,
"domain_schema": null,
"enums": [],
"format": "int4",
"id": StringMatching /\\^\\\\d\\+\\\\\\.1\\$/,
Expand Down Expand Up @@ -259,6 +271,8 @@ test('retrieve, create, update, delete', async () => {
"comment": "bar",
"data_type": "integer",
"default_value": null,
"domain_name": null,
"domain_schema": null,
"enums": [],
"format": "int4",
"id": StringMatching /\\^\\\\d\\+\\\\\\.1\\$/,
Expand Down Expand Up @@ -304,6 +318,8 @@ test('enum column with quoted name', async () => {
"comment": null,
"data_type": "USER-DEFINED",
"default_value": null,
"domain_name": null,
"domain_schema": null,
"enums": [
"v",
],
Expand Down Expand Up @@ -412,6 +428,8 @@ test('array column', async () => {
"comment": null,
"data_type": "ARRAY",
"default_value": null,
"domain_name": null,
"domain_schema": null,
"enums": [],
"format": "_int2",
"id": StringMatching /\\^\\\\d\\+\\\\\\.1\\$/,
Expand Down Expand Up @@ -459,6 +477,8 @@ test('column with default value', async () => {
"comment": null,
"data_type": "timestamp with time zone",
"default_value": "now()",
"domain_name": null,
"domain_schema": null,
"enums": [],
"format": "timestamptz",
"id": StringMatching /\\^\\\\d\\+\\\\\\.1\\$/,
Expand Down Expand Up @@ -537,6 +557,8 @@ test('update with name unchanged', async () => {
"comment": null,
"data_type": "smallint",
"default_value": null,
"domain_name": null,
"domain_schema": null,
"enums": [],
"format": "int2",
"id": StringMatching /\\^\\\\d\\+\\\\\\.1\\$/,
Expand Down Expand Up @@ -585,6 +607,8 @@ test('update with array types', async () => {
"comment": null,
"data_type": "ARRAY",
"default_value": null,
"domain_name": null,
"domain_schema": null,
"enums": [],
"format": "_text",
"id": StringMatching /\\^\\\\d\\+\\\\\\.1\\$/,
Expand Down Expand Up @@ -633,6 +657,8 @@ test('update with incompatible types', async () => {
"comment": null,
"data_type": "integer",
"default_value": null,
"domain_name": null,
"domain_schema": null,
"enums": [],
"format": "int4",
"id": StringMatching /\\^\\\\d\\+\\\\\\.1\\$/,
Expand Down Expand Up @@ -680,6 +706,8 @@ test('update is_unique', async () => {
"comment": null,
"data_type": "text",
"default_value": null,
"domain_name": null,
"domain_schema": null,
"enums": [],
"format": "text",
"id": StringMatching /\\^\\\\d\\+\\\\\\.1\\$/,
Expand Down Expand Up @@ -714,6 +742,8 @@ test('update is_unique', async () => {
"comment": null,
"data_type": "text",
"default_value": null,
"domain_name": null,
"domain_schema": null,
"enums": [],
"format": "text",
"id": StringMatching /\\^\\\\d\\+\\\\\\.1\\$/,
Expand Down Expand Up @@ -763,6 +793,8 @@ test('alter column to type with uppercase', async () => {
"comment": null,
"data_type": "USER-DEFINED",
"default_value": null,
"domain_name": null,
"domain_schema": null,
"enums": [],
"format": "T",
"id": StringMatching /\\^\\\\d\\+\\\\\\.1\\$/,
Expand Down Expand Up @@ -810,6 +842,8 @@ test('enums are populated in enum array columns', async () => {
"comment": null,
"data_type": "ARRAY",
"default_value": null,
"domain_name": null,
"domain_schema": null,
"enums": [
"a",
],
Expand Down Expand Up @@ -864,6 +898,8 @@ create table public.t (
"comment": null,
"data_type": "bigint",
"default_value": null,
"domain_name": null,
"domain_schema": null,
"enums": [],
"format": "int8",
"id": StringMatching /\\^\\\\d\\+\\\\\\.1\\$/,
Expand Down Expand Up @@ -915,6 +951,8 @@ test('column with multiple checks', async () => {
"comment": null,
"data_type": "bigint",
"default_value": null,
"domain_name": null,
"domain_schema": null,
"enums": [],
"format": "int8",
"identity_generation": null,
Expand Down Expand Up @@ -948,6 +986,8 @@ test('column with multiple unique constraints', async () => {
"comment": null,
"data_type": "bigint",
"default_value": null,
"domain_name": null,
"domain_schema": null,
"enums": [],
"format": "int8",
"identity_generation": null,
Expand Down Expand Up @@ -1000,6 +1040,8 @@ test('column with fully-qualified type', async () => {
"comment": null,
"data_type": "USER-DEFINED",
"default_value": null,
"domain_name": null,
"domain_schema": null,
"enums": [],
"format": "my_type",
"identity_generation": null,
Expand All @@ -1017,3 +1059,54 @@ test('column with fully-qualified type', async () => {

await pgMeta.query(`drop table public.t; drop schema s cascade;`)
})

test('domain columns keep the domain identity', async () => {
const res = await pgMeta.columns.list()
const columns = res.data
?.filter(({ table }) => table === 'domain_test')
.map(({ name, data_type, format, domain_schema, domain_name, is_nullable }) => ({
name,
data_type,
format,
domain_schema,
domain_name,
is_nullable,
}))

expect(columns).toMatchInlineSnapshot(`
[
{
"data_type": "bigint",
"domain_name": null,
"domain_schema": null,
"format": "int8",
"is_nullable": false,
"name": "id",
},
{
"data_type": "jsonb",
"domain_name": "text_search",
"domain_schema": "public",
"format": "jsonb",
"is_nullable": true,
"name": "search",
},
{
"data_type": "integer",
"domain_name": "positive_int",
"domain_schema": "public",
"format": "int4",
"is_nullable": false,
"name": "quantity",
},
{
"data_type": "jsonb",
"domain_name": null,
"domain_schema": null,
"format": "jsonb",
"is_nullable": true,
"name": "plain",
},
]
`)
})
12 changes: 12 additions & 0 deletions test/lib/foreign-tables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ test('list', async () => {
"comment": null,
"data_type": "bigint",
"default_value": null,
"domain_name": null,
"domain_schema": null,
"enums": [],
"format": "int8",
"identity_generation": null,
Expand All @@ -47,6 +49,8 @@ test('list', async () => {
"comment": null,
"data_type": "text",
"default_value": null,
"domain_name": null,
"domain_schema": null,
"enums": [],
"format": "text",
"identity_generation": null,
Expand All @@ -65,6 +69,8 @@ test('list', async () => {
"comment": null,
"data_type": "USER-DEFINED",
"default_value": null,
"domain_name": null,
"domain_schema": null,
"enums": [
"ACTIVE",
"INACTIVE",
Expand Down Expand Up @@ -112,6 +118,8 @@ test('retrieve', async () => {
"comment": null,
"data_type": "bigint",
"default_value": null,
"domain_name": null,
"domain_schema": null,
"enums": [],
"format": "int8",
"identity_generation": null,
Expand All @@ -130,6 +138,8 @@ test('retrieve', async () => {
"comment": null,
"data_type": "text",
"default_value": null,
"domain_name": null,
"domain_schema": null,
"enums": [],
"format": "text",
"identity_generation": null,
Expand All @@ -148,6 +158,8 @@ test('retrieve', async () => {
"comment": null,
"data_type": "USER-DEFINED",
"default_value": null,
"domain_name": null,
"domain_schema": null,
"enums": [
"ACTIVE",
"INACTIVE",
Expand Down
Loading