Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions modules/module-postgres/src/api/PostgresRouteAPIAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -275,14 +275,14 @@ GROUP BY schemaname, tablename, quoted_name`
);
const rows = pgwire.pgwireRows(results);

let schemas: Record<string, any> = {};
let schemas: Record<string, service_types.DatabaseSchema> = {};

for (let row of rows) {
const schema = (schemas[row.schemaname] ??= {
name: row.schemaname,
tables: []
});
const table = {
const table: service_types.DatabaseSchema['tables'][0] = {
name: row.tablename,
columns: [] as any[]
};
Expand All @@ -296,7 +296,9 @@ GROUP BY schemaname, tablename, quoted_name`
}
table.columns.push({
name: column.attname,
sqlite_type: sync_rules.expressionTypeFromPostgresType(pg_type).typeFlags,
type: column.data_type,
internal_type: column.data_type,
pg_type: pg_type
});
}
Expand Down
29 changes: 27 additions & 2 deletions packages/sync-rules/src/ExpressionType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export const TYPE_TEXT = 2;
export const TYPE_INTEGER = 4;
export const TYPE_REAL = 8;

export type SqliteType = 'null' | 'blob' | 'text' | 'integer' | 'real';
export type SqliteType = 'null' | 'blob' | 'text' | 'integer' | 'real' | 'numeric';

export interface ColumnDefinition {
name: string;
Expand Down Expand Up @@ -34,7 +34,7 @@ export class ExpressionType {
return new ExpressionType(typeFlags);
}

static fromTypeText(type: SqliteType | 'numeric') {
static fromTypeText(type: SqliteType) {
if (type == 'null') {
return ExpressionType.NONE;
} else if (type == 'blob') {
Expand Down Expand Up @@ -72,3 +72,28 @@ export class ExpressionType {
return this.typeFlags == TYPE_NONE;
}
}

/**
* Here only for backwards-compatibility only.
*/
export function expressionTypeFromPostgresType(type: string | undefined): ExpressionType {
if (type?.endsWith('[]')) {
return ExpressionType.TEXT;
}
switch (type) {
case 'bool':
return ExpressionType.INTEGER;
case 'bytea':
return ExpressionType.BLOB;
case 'int2':
case 'int4':
case 'int8':
case 'oid':
return ExpressionType.INTEGER;
case 'float4':
case 'float8':
return ExpressionType.REAL;
default:
return ExpressionType.TEXT;
}
}
54 changes: 31 additions & 23 deletions packages/sync-rules/src/StaticSchema.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnDefinition, ExpressionType } from './ExpressionType.js';
import { ColumnDefinition, ExpressionType, expressionTypeFromPostgresType, SqliteType } from './ExpressionType.js';
import { SourceTableInterface } from './SourceTableInterface.js';
import { TablePattern } from './TablePattern.js';
import { SourceSchema, SourceSchemaTable } from './types.js';
Expand All @@ -14,11 +14,28 @@ export interface SourceTableDefinition {
}

export interface SourceColumnDefinition {
/**
* Column name.
*/
name: string;

/**
* Option 1: SQLite type flags - see ExpressionType.typeFlags.
* Option 2: SQLite type name in lowercase - 'text' | 'integer' | 'real' | 'numeric' | 'blob' | 'null'
*/
sqlite_type?: number | SqliteType;

/**
* Postgres type.
* Type name from the source database, e.g. "character varying(255)[]"
*/
pg_type: string;
internal_type?: string;

/**
* Postgres type, kept for backwards-compatibility.
*
* @deprecated - use internal_type instead
*/
pg_type?: string;
}

export interface SourceConnectionDefinition {
Expand Down Expand Up @@ -75,28 +92,19 @@ export class StaticSchema implements SourceSchema {
function mapColumn(column: SourceColumnDefinition): ColumnDefinition {
return {
name: column.name,
type: mapType(column.pg_type)
type: mapColumnType(column)
};
}

function mapType(type: string | undefined): ExpressionType {
if (type?.endsWith('[]')) {
return ExpressionType.TEXT;
}
switch (type) {
case 'bool':
return ExpressionType.INTEGER;
case 'bytea':
return ExpressionType.BLOB;
case 'int2':
case 'int4':
case 'int8':
case 'oid':
return ExpressionType.INTEGER;
case 'float4':
case 'float8':
return ExpressionType.REAL;
default:
return ExpressionType.TEXT;
function mapColumnType(column: SourceColumnDefinition): ExpressionType {
if (typeof column.sqlite_type == 'number') {
return ExpressionType.of(column.sqlite_type);
} else if (typeof column.sqlite_type == 'string') {
return ExpressionType.fromTypeText(column.sqlite_type);
} else if (column.pg_type != null) {
// We still handle these types for backwards-compatibility of old schemas
return expressionTypeFromPostgresType(column.pg_type);
} else {
throw new Error(`Cannot determine SQLite type of ${JSON.stringify(column)}`);
}
}
33 changes: 31 additions & 2 deletions packages/types/src/definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,15 @@ export const ConnectionStatusV2 = t.object({
});
export type ConnectionStatusV2 = t.Encoded<typeof ConnectionStatusV2>;

export enum SqliteSchemaTypeText {
null = 'null',
blob = 'blob',
text = 'text',
integer = 'integer',
real = 'real',
numeric = 'numeric'
}

export const DatabaseSchema = t.object({
name: t.string,
tables: t.array(
Expand All @@ -99,14 +108,34 @@ export const DatabaseSchema = t.object({
columns: t.array(
t.object({
name: t.string,

/**
* Option 1: SQLite type flags - see ExpressionType.typeFlags.
* Option 2: SQLite type name in lowercase - 'text' | 'integer' | 'real' | 'numeric' | 'blob' | 'null'
*/
sqlite_type: t.number.or(t.Enum(SqliteSchemaTypeText)),

/**
* Type name from the source database, e.g. "character varying(255)[]"
*/
internal_type: t.string,

/**
* Description for the field if available.
*/
description: t.string.optional(),

/**
* Full type name, e.g. "character varying(255)[]"
* @deprecated - use internal_type
*/
type: t.string,
type: t.string.optional(),

/**
* Internal postgres type, e.g. "varchar[]".
* @deprecated - use internal_type instead
*/
pg_type: t.string
pg_type: t.string.optional()
})
)
})
Expand Down
Loading