packages/sql/catalog.ts
Rama main · réplica de lectura del repositorio original.
import type { NameCase } from './dialect'
export interface SqlColumn {
name: string
type: string
nullable: boolean
comment?: string | null
}
export interface SqlTable {
name: string
kind: string
/** `null` while the columns have not been loaded — column checks and suggestions skip the table. */
columns: SqlColumn[] | null
comment?: string | null
}
interface SqlSchema {
name: string
tables: SqlTable[]
}
interface SqlEnum {
name: string
values: string[]
table?: string
column?: string
}
export interface SqlCatalog {
defaultSchema: string | null
nameCase: NameCase | null
schemas: SqlSchema[]
enums: SqlEnum[]
}
const collator = new Intl.Collator(undefined, { sensitivity: 'accent' })
const namesMatch = (catalog: SqlCatalog, a: string, b: string) =>
catalog.nameCase ? a === b : collator.compare(a, b) === 0
export const findSchema = (catalog: SqlCatalog, name: string) =>
catalog.schemas.find((schema) => namesMatch(catalog, schema.name, name))
export const findTableWithSchema = (
catalog: SqlCatalog,
name: string,
schema: string | null
) => {
const schemas = schema
? [findSchema(catalog, schema)]
: [
...(catalog.defaultSchema
? [findSchema(catalog, catalog.defaultSchema)]
: []),
...catalog.schemas,
]
for (const candidate of schemas) {
const table = candidate?.tables.find((item) =>
namesMatch(catalog, item.name, name)
)
if (candidate && table) {
return { schema: candidate.name, table }
}
}
}
export const findTable = (
catalog: SqlCatalog,
name: string,
schema: string | null
) => findTableWithSchema(catalog, name, schema)?.table
export const findColumn = (
catalog: SqlCatalog,
table: SqlTable,
name: string
) => table.columns?.find((column) => namesMatch(catalog, column.name, name))
export const findEnum = (
catalog: SqlCatalog,
table: string,
column: SqlColumn
) =>
catalog.enums.find(
(item) => item.table === table && item.column === column.name
) ??
catalog.enums.find(
(item) =>
collator.compare(item.name, column.type) === 0 ||
column.type.toLowerCase().endsWith(`.${item.name.toLowerCase()}`)
)