# Reconstructed from:
# https://github.com/jordanlewis/pgjdbc/blob/462d505f01ec6180b30eaffabe51839dd126b90c/pgjdbc/src/main/java/org/postgresql/jdbc/PgDatabaseMetaData.java#L2391-L2408

# For testing, create the schema for the builtin tables.
exec-ddl
CREATE TABLE pg_type (
    oid OID NULL,
    typname NAME NOT NULL,
    typnamespace OID NULL,
    typowner OID NULL,
    typlen INT NULL,
    typbyval BOOL NULL,
    typtype STRING NULL,
    typcategory STRING NULL,
    typispreferred BOOL NULL,
    typisdefined BOOL NULL,
    typdelim STRING NULL,
    typrelid OID NULL,
    typelem OID NULL,
    typarray OID NULL,
    typinput OID NULL,
    typoutput OID NULL,
    typreceive OID NULL,
    typsend OID NULL,
    typmodin OID NULL,
    typmodout OID NULL,
    typanalyze OID NULL,
    typalign STRING NULL,
    typstorage STRING NULL,
    typnotnull BOOL NULL,
    typbasetype OID NULL,
    typtypmod INT NULL,
    typndims INT NULL,
    typcollation OID NULL,
    typdefaultbin STRING NULL,
    typdefault STRING NULL,
    typacl STRING[] NULL
)
----
TABLE pg_type
 ├── oid oid
 ├── typname name not null
 ├── typnamespace oid
 ├── typowner oid
 ├── typlen int
 ├── typbyval bool
 ├── typtype string
 ├── typcategory string
 ├── typispreferred bool
 ├── typisdefined bool
 ├── typdelim string
 ├── typrelid oid
 ├── typelem oid
 ├── typarray oid
 ├── typinput oid
 ├── typoutput oid
 ├── typreceive oid
 ├── typsend oid
 ├── typmodin oid
 ├── typmodout oid
 ├── typanalyze oid
 ├── typalign string
 ├── typstorage string
 ├── typnotnull bool
 ├── typbasetype oid
 ├── typtypmod int
 ├── typndims int
 ├── typcollation oid
 ├── typdefaultbin string
 ├── typdefault string
 ├── typacl string[]
 ├── rowid int not null (hidden)
 └── INDEX primary
      └── rowid int not null (hidden)

exec-ddl
CREATE TABLE pg_namespace (
    oid OID NULL,
    nspname NAME NOT NULL,
    nspowner OID NULL,
    nspacl STRING[] NULL
)
----
TABLE pg_namespace
 ├── oid oid
 ├── nspname name not null
 ├── nspowner oid
 ├── nspacl string[]
 ├── rowid int not null (hidden)
 └── INDEX primary
      └── rowid int not null (hidden)

opt
SELECT
    NULL AS type_cat,
    n.nspname AS type_schem,
    t.typname AS type_name,
    NULL AS class_name,
    CASE
    WHEN t.typtype = 'c' THEN 'STRUCT'
    ELSE 'DISTINCT'
    END
        AS data_type,
    pg_catalog.obj_description(t.oid, 'pg_type') AS remarks,
    CASE
    WHEN t.typtype = 'd'
    THEN (
        SELECT
            CASE
            WHEN typname = 'pgType' THEN 'sqlType'
            ELSE 'OTHER'
            END
        FROM
            pg_type
        WHERE
            oid = t.typbasetype
    )
    ELSE NULL
    END
        AS base_type
FROM
    pg_type AS t, pg_namespace AS n
WHERE
    t.typnamespace = n.oid AND n.nspname != 'pg_catalog';
----
project
 ├── columns: type_cat:71(unknown) type_schem:34(name!null) type_name:2(name!null) class_name:71(unknown) data_type:72(string) remarks:73(string) base_type:74(string)
 ├── fd: ()-->(71)
 ├── left-join-apply
 │    ├── columns: t.oid:1(oid) t.typname:2(name!null) t.typnamespace:3(oid!null) t.typtype:7(string) t.typbasetype:25(oid) n.oid:33(oid!null) nspname:34(name!null) case:70(string)
 │    ├── fd: (3)==(33), (33)==(3)
 │    ├── inner-join
 │    │    ├── columns: t.oid:1(oid) t.typname:2(name!null) t.typnamespace:3(oid!null) t.typtype:7(string) t.typbasetype:25(oid) n.oid:33(oid!null) nspname:34(name!null)
 │    │    ├── fd: (3)==(33), (33)==(3)
 │    │    ├── scan t
 │    │    │    └── columns: t.oid:1(oid) t.typname:2(name!null) t.typnamespace:3(oid) t.typtype:7(string) t.typbasetype:25(oid)
 │    │    ├── select
 │    │    │    ├── columns: n.oid:33(oid) nspname:34(name!null)
 │    │    │    ├── scan n
 │    │    │    │    └── columns: n.oid:33(oid) nspname:34(name!null)
 │    │    │    └── filters
 │    │    │         └── nspname != 'pg_catalog' [type=bool, outer=(34), constraints=(/34: (/NULL - /'pg_catalog') [/e'pg_catalog\x00' - ]; tight)]
 │    │    └── filters
 │    │         └── t.typnamespace = n.oid [type=bool, outer=(3,33), constraints=(/3: (/NULL - ]; /33: (/NULL - ]), fd=(3)==(33), (33)==(3)]
 │    ├── max1-row
 │    │    ├── columns: case:70(string)
 │    │    ├── outer: (25)
 │    │    ├── cardinality: [0 - 1]
 │    │    ├── key: ()
 │    │    ├── fd: ()-->(70)
 │    │    └── project
 │    │         ├── columns: case:70(string)
 │    │         ├── outer: (25)
 │    │         ├── select
 │    │         │    ├── columns: pg_type.oid:38(oid!null) pg_type.typname:39(name!null)
 │    │         │    ├── outer: (25)
 │    │         │    ├── fd: ()-->(38)
 │    │         │    ├── scan pg_type
 │    │         │    │    └── columns: pg_type.oid:38(oid) pg_type.typname:39(name!null)
 │    │         │    └── filters
 │    │         │         └── pg_type.oid = t.typbasetype [type=bool, outer=(25,38), constraints=(/25: (/NULL - ]; /38: (/NULL - ]), fd=(25)==(38), (38)==(25)]
 │    │         └── projections
 │    │              └── CASE WHEN pg_type.typname = 'pgType' THEN 'sqlType' ELSE 'OTHER' END [type=string, outer=(39)]
 │    └── filters (true)
 └── projections
      ├── null [type=unknown]
      ├── CASE WHEN t.typtype = 'c' THEN 'STRUCT' ELSE 'DISTINCT' END [type=string, outer=(7)]
      ├── obj_description(t.oid, 'pg_type') [type=string, outer=(1)]
      └── CASE WHEN t.typtype = 'd' THEN case END [type=string, outer=(7,70)]
