Skip to content

Commit

Permalink
Fix: Add getAvailableValues for enums to Postgres parser;
Browse files Browse the repository at this point in the history
  • Loading branch information
rokmohar committed Jul 19, 2024
1 parent b82a013 commit 097ef9e
Showing 1 changed file with 80 additions and 60 deletions.
140 changes: 80 additions & 60 deletions src/dialects/postgres.parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,66 +9,58 @@ const pgArrayAggToArray = (agg: string) => agg.replace(/{/g, '').replace(/}/g, '

const getColumnType = (dbType: string): PropertyType => {
switch (dbType) {
case 'uuid': return 'uuid';
case 'bigint':
case 'int8':
case 'bigserial':
case 'serial8':
case 'integer':
case 'int':
case 'int4':
case 'smallint':
case 'int2':
case 'serial':
case 'serial4':
case 'smallserial':
case 'serial2':
return 'number';
case 'double precision':
case 'float8':
case 'numeric':
case 'decimal':
case 'real':
case 'float4':
return 'float';
case 'money':
return 'currency';
case 'boolean':
return 'boolean';
case 'time':
case 'time with time zone':
case 'timetz':
case 'time without time zone':
case 'timestamp':
case 'timestamp with time zone':
case 'timestamptz':
case 'timestamp without time zone':
return 'datetime';
case 'date':
return 'date';
case 'json':
case 'jsonb':
return 'key-value';
case 'text':
case 'character varying':
case 'char':
case 'varchar':
default:
return 'string';
case 'USER-DEFINED':
return 'mixed';
case 'uuid':
return 'uuid';
case 'bigint':
case 'int8':
case 'bigserial':
case 'serial8':
case 'integer':
case 'int':
case 'int4':
case 'smallint':
case 'int2':
case 'serial':
case 'serial4':
case 'smallserial':
case 'serial2':
return 'number';
case 'double precision':
case 'float8':
case 'numeric':
case 'decimal':
case 'real':
case 'float4':
return 'float';
case 'money':
return 'currency';
case 'boolean':
return 'boolean';
case 'time':
case 'time with time zone':
case 'timetz':
case 'time without time zone':
case 'timestamp':
case 'timestamp with time zone':
case 'timestamptz':
case 'timestamp without time zone':
return 'datetime';
case 'date':
return 'date';
case 'json':
case 'jsonb':
return 'key-value';
case 'text':
case 'character varying':
case 'char':
case 'varchar':
default:
return 'string';
}
};

const getColumnInfo = (column: Record<string, number | string>): ColumnInfo => ({
name: column.column_name as string,
isId: column.key_type === 'PRIMARY KEY',
position: column.ordinal_position as number,
defaultValue: column.column_default,
isNullable: column.is_nullable === 'YES',
isEditable: column.is_updatable === 'YES',
type: column.referenced_table ? 'reference' : getColumnType(column.data_type as string),
referencedTable: (column.referenced_table ?? null) as string | null,
});

export class PostgresParser extends BaseDatabaseParser {
public static dialects = ['postgresql' as const];

Expand Down Expand Up @@ -177,7 +169,7 @@ export class PostgresParser extends BaseDatabaseParser {

const relations = await relQuery;

return columns.map((col) => {
return Promise.all(columns.map(async (col) => {
const rel = relations.rows.find((r) => {
const cols = pgArrayAggToArray(r.col);
if (cols.length > 1) return null; // AdminJS doesn't support multiple foreign keys
Expand All @@ -189,7 +181,35 @@ export class PostgresParser extends BaseDatabaseParser {
col.referenced_table = rel.referenced_table;
}

return new Property(getColumnInfo(col));
});
return new Property(await this.getColumnInfo(col));
}));
}


async getColumnInfo(column: Record<string, number | string>): Promise<ColumnInfo> {
return {
name: column.column_name as string,
isId: column.key_type === 'PRIMARY KEY',
position: column.ordinal_position as number,
defaultValue: column.column_default,
isNullable: column.is_nullable === 'YES',
isEditable: column.is_updatable === 'YES',
type: column.referenced_table ? ('reference' as PropertyType) : getColumnType(column.data_type as string),
referencedTable: (column.referenced_table ?? null) as string | null,
availableValues: await this.getAvailableValues(column),
}
}

async getAvailableValues(column: Record<string, number | string>): Promise<string[] | null> {
if (column.data_type !== 'USER-DEFINED' || !column.udt_name) {
return null;
}
const query = this.knex
.from('pg_catalog.pg_enum as e')
.select('e.enumlabel')
.leftJoin('pg_catalog.pg_type as t', (c) => c.on('e.enumtypid', 't.oid'))
.where('t.typname', column.udt_name);
const labels = await query;
return labels.map((l) => l.enumlabel as string)
}
}

0 comments on commit 097ef9e

Please sign in to comment.