WITH models AS (
  WITH data AS (
    SELECT
        replace(initcap(table_name::text), '_', '') table_name,
        replace(initcap(column_name::text), '_', '') column_name,
        CASE data_type
        WHEN 'timestamp without time zone' THEN 'time.Time'
        WHEN 'timestamp with time zone' THEN 'time.Time'
        WHEN 'boolean' THEN 'bool'
        WHEN 'bigint' THEN 'int64'
        WHEN 'integer' THEN 'int'
        WHEN 'ARRAY' THEN 'pgtype.Array[string]'
        WHEN 'date' THEN 'pgtype.Date'
        WHEN 'character varying' THEN 'string'
        WHEN 'double precision' THEN 'float64'
        -- add your own type converters as needed or it will default to 'string'
        ELSE 'UNKNOWN'
        END AS type_info,
        '`json:"' || column_name ||'"`' AS annotation
    FROM information_schema.columns
    WHERE table_schema IN ('public')
    ORDER BY table_schema, table_name, ordinal_position
  )
    SELECT table_name, STRING_AGG(E'\t' || column_name || E'\t' || type_info || E'\t' || annotation, E'\n') fields
    FROM data
    GROUP BY table_name
)
SELECT 'type ' || table_name || E' struct {\n' || fields || E'\n}' models
FROM models ORDER BY table_name