Files
upstream-mirror 0f4df23290
Some checks failed
kotlin / test (push) Has been skipped
python / test (push) Has been skipped
typescript / test (push) Has been skipped
go / build darwin/amd64 (push) Has been cancelled
go / build linux/amd64 (push) Has been cancelled
go / build windows/amd64 (push) Has been cancelled
go / build darwin/arm64 (push) Has been cancelled
go / build linux/arm64 (push) Has been cancelled
go / build windows/arm64 (push) Has been cancelled
go / test (push) Has been cancelled
go / vuln_check (push) Has been cancelled
snapshot of https://github.com/sqlc-dev/sqlc.git (main, 2026-09-16; blobs > 131072B omitted)
2026-09-16 02:17:34 +05:00

119 lines
3.0 KiB
Go

package postgresql
import (
"context"
pgx "github.com/jackc/pgx/v5"
)
// Relations are the relations available in pg_tables and pg_views
// such as pg_catalog.pg_timezone_names
const relationQuery = `
with relations as (
select schemaname, tablename as name from pg_catalog.pg_tables
UNION ALL
select schemaname, viewname as name from pg_catalog.pg_views
)
select
relations.schemaname,
relations.name as tablename,
pg_attribute.attname as column_name,
attnotnull as column_notnull,
-- An array column's type is its element's, with the array flag set,
-- rather than pg_type's own _text spelling of the array type. Only the
-- _-prefixed array types count: int2vector and oidvector are in the
-- array category and carry an element, but are types of their own.
coalesce(element_type.typname, column_type.typname) as column_type,
nullif(coalesce(element_type.typlen, column_type.typlen), -1) as column_length,
element_type.oid is not null as column_isarray
from relations
inner join pg_catalog.pg_class on pg_class.relname = relations.name
left join pg_catalog.pg_attribute on pg_attribute.attrelid = pg_class.oid
inner join pg_catalog.pg_type column_type on pg_attribute.atttypid = column_type.oid
left join pg_catalog.pg_type element_type
on column_type.typcategory = 'A' and column_type.typname like '\_%'
and element_type.oid = column_type.typelem
where relations.schemaname = $1
-- Make sure these columns are always generated in the same order
-- so that the output is stable
order by
relations.schemaname ASC,
relations.name ASC,
pg_attribute.attnum ASC
`
type Relation struct {
Catalog string
SchemaName string
Name string
Columns []RelationColumn
}
type RelationColumn struct {
Name string
Type string
IsNotNull bool
IsArray bool
Length *int
}
func scanRelations(rows pgx.Rows) ([]Relation, error) {
defer rows.Close()
// Iterate through the result set
var relations []Relation
var prevRel *Relation
for rows.Next() {
var schemaName string
var tableName string
var columnName string
var columnNotNull bool
var columnType string
var columnLength *int
var columnIsArray bool
err := rows.Scan(
&schemaName,
&tableName,
&columnName,
&columnNotNull,
&columnType,
&columnLength,
&columnIsArray,
)
if err != nil {
return nil, err
}
if prevRel == nil || tableName != prevRel.Name {
// We are on the same table, just keep adding columns
r := Relation{
Catalog: "pg_catalog",
SchemaName: schemaName,
Name: tableName,
}
relations = append(relations, r)
prevRel = &relations[len(relations)-1]
}
prevRel.Columns = append(prevRel.Columns, RelationColumn{
Name: columnName,
Type: columnType,
IsNotNull: columnNotNull,
IsArray: columnIsArray,
Length: columnLength,
})
}
return relations, rows.Err()
}
func readRelations(ctx context.Context, conn *pgx.Conn, schemaName string) ([]Relation, error) {
rows, err := conn.Query(ctx, relationQuery, schemaName)
if err != nil {
return nil, err
}
return scanRelations(rows)
}