mirror of
https://github.com/Kaelio/ktx.git
synced 2026-06-16 08:25:14 +02:00
refactor: remove legacy ktx compatibility shims (#211)
* refactor: remove legacy ktx compatibility shims * fix: restore overlay collision guidance
This commit is contained in:
parent
a954a29a76
commit
96952fb43c
59 changed files with 294 additions and 342 deletions
|
|
@ -8,12 +8,8 @@ import type { KtxTableRef } from './types.js';
|
|||
*
|
||||
* Accepted entry forms:
|
||||
* "catalog.db.name" — fully qualified
|
||||
* "db.name" — schema-qualified (catalog = null; legacy / Postgres-shape)
|
||||
* "db.name" — schema-qualified (catalog = null)
|
||||
* "name" — bare (catalog = db = null; SQLite-shape)
|
||||
* { catalog?, db?, name } — escape hatch for identifiers containing dots
|
||||
*
|
||||
* The setup wizard writes the fully-qualified form going forward; the lenient
|
||||
* parser keeps existing project configs working.
|
||||
*/
|
||||
export function resolveEnabledTables(
|
||||
connection: Record<string, unknown> | undefined,
|
||||
|
|
@ -33,16 +29,6 @@ function parseEnabledTableEntry(value: unknown): KtxTableRef | null {
|
|||
if (typeof value === 'string') {
|
||||
return parseDottedEntry(value);
|
||||
}
|
||||
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
||||
const entry = value as { catalog?: unknown; db?: unknown; name?: unknown };
|
||||
const name = typeof entry.name === 'string' ? entry.name : null;
|
||||
if (!name) return null;
|
||||
return {
|
||||
catalog: typeof entry.catalog === 'string' ? entry.catalog : null,
|
||||
db: typeof entry.db === 'string' ? entry.db : null,
|
||||
name,
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1878,6 +1878,15 @@ describe('resolveEnabledTables', () => {
|
|||
expect(result!.has(tableRefKey({ catalog: null, db: 'public', name: 'orders' }))).toBe(true);
|
||||
});
|
||||
|
||||
it('ignores legacy enabled_tables object entries', () => {
|
||||
expect(
|
||||
resolveEnabledTables({
|
||||
driver: 'postgres',
|
||||
enabled_tables: [{ catalog: null, db: 'public', name: 'orders' }],
|
||||
}),
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it('returns null for undefined connection', () => {
|
||||
expect(resolveEnabledTables(undefined)).toBeNull();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -126,19 +126,17 @@ function normalizeDriver(driver: string | undefined): KtxConnectionDriver {
|
|||
const normalized = (driver ?? '').toLowerCase();
|
||||
if (
|
||||
normalized === 'postgres' ||
|
||||
normalized === 'postgresql' ||
|
||||
normalized === 'sqlite' ||
|
||||
normalized === 'sqlite3' ||
|
||||
normalized === 'mysql' ||
|
||||
normalized === 'clickhouse' ||
|
||||
normalized === 'sqlserver' ||
|
||||
normalized === 'bigquery' ||
|
||||
normalized === 'snowflake'
|
||||
) {
|
||||
return normalized === 'sqlite3' ? 'sqlite' : normalized;
|
||||
return normalized;
|
||||
}
|
||||
throw new Error(
|
||||
`Standalone ktx scan supports postgres/postgresql/sqlite/mysql/clickhouse/sqlserver/bigquery/snowflake in this phase, received "${driver ?? 'unknown'}"`,
|
||||
`Standalone ktx scan supports postgres/sqlite/mysql/clickhouse/sqlserver/bigquery/snowflake in this phase, received "${driver ?? 'unknown'}"`,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,9 +47,9 @@ describe('scopedTableNames', () => {
|
|||
expect(scopedTableNames(scope, { catalog: 'ANALYTICS', db: 'STAGING' })).toEqual(['LISTINGS']);
|
||||
});
|
||||
|
||||
it('treats null in the scope entry as a wildcard for that segment', () => {
|
||||
it('requires non-null scope segments to match the namespace', () => {
|
||||
const scope = tableRefSet([{ catalog: null, db: 'public', name: 'users' }]);
|
||||
expect(scopedTableNames(scope, { catalog: 'any-catalog', db: 'public' })).toEqual(['users']);
|
||||
expect(scopedTableNames(scope, { catalog: 'any-catalog', db: 'public' })).toEqual([]);
|
||||
});
|
||||
|
||||
it('returns empty when no scope entry matches the namespace', () => {
|
||||
|
|
@ -57,7 +57,7 @@ describe('scopedTableNames', () => {
|
|||
expect(scopedTableNames(scope, { catalog: 'X', db: 'Y' })).toEqual([]);
|
||||
});
|
||||
|
||||
it('dedupes when the same name appears under different catalog projections', () => {
|
||||
it('dedupes exact namespace matches only', () => {
|
||||
const scope: ReadonlySet<KtxTableRefKey> = tableRefSet([
|
||||
{ catalog: null, db: 'public', name: 'users' },
|
||||
{ catalog: 'A', db: 'public', name: 'users' },
|
||||
|
|
|
|||
|
|
@ -33,8 +33,7 @@ export function tableRefSet(refs: readonly KtxTableRef[]): ReadonlySet<KtxTableR
|
|||
|
||||
/**
|
||||
* Return the bare table names from a scope that fall within the given
|
||||
* (catalog, db) namespace. `catalog: null` is treated as a wildcard so that
|
||||
* legacy 2-part `"db.name"` entries continue to match. Same for `db: null`.
|
||||
* (catalog, db) namespace.
|
||||
*/
|
||||
export function scopedTableNames(
|
||||
scope: ReadonlySet<KtxTableRefKey>,
|
||||
|
|
@ -45,8 +44,8 @@ export function scopedTableNames(
|
|||
const wantDb = namespace.db ?? null;
|
||||
for (const key of scope) {
|
||||
const ref = tableRefFromKey(key);
|
||||
if (wantCatalog !== null && ref.catalog !== null && ref.catalog !== wantCatalog) continue;
|
||||
if (wantDb !== null && ref.db !== null && ref.db !== wantDb) continue;
|
||||
if (ref.catalog !== wantCatalog) continue;
|
||||
if (ref.db !== wantDb) continue;
|
||||
names.add(ref.name);
|
||||
}
|
||||
return [...names];
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import type { KtxTableRefKey } from './table-ref.js';
|
|||
export type KtxConnectionDriver =
|
||||
| 'sqlite'
|
||||
| 'postgres'
|
||||
| 'postgresql'
|
||||
| 'sqlserver'
|
||||
| 'bigquery'
|
||||
| 'snowflake'
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import type {
|
|||
KtxTableRef,
|
||||
} from './types.js';
|
||||
|
||||
type CatalogDriver = KtxConnectionDriver | 'sqlite3';
|
||||
type CatalogDriver = KtxConnectionDriver;
|
||||
|
||||
export interface WarehouseCatalogServiceDeps {
|
||||
fileStore: KtxFileStorePort;
|
||||
|
|
@ -129,7 +129,7 @@ function splitDisplay(display: string): string[] {
|
|||
}
|
||||
|
||||
function formatDisplay(driver: CatalogDriver, table: KtxTableRef): string {
|
||||
if (driver === 'sqlite' || driver === 'sqlite3') {
|
||||
if (driver === 'sqlite') {
|
||||
return table.name;
|
||||
}
|
||||
return [table.catalog, table.db, table.name].filter((part): part is string => Boolean(part)).join('.');
|
||||
|
|
@ -137,7 +137,7 @@ function formatDisplay(driver: CatalogDriver, table: KtxTableRef): string {
|
|||
|
||||
function parseDisplay(driver: CatalogDriver, display: string): KtxTableRef | null {
|
||||
const parts = splitDisplay(display);
|
||||
if (driver === 'sqlite' || driver === 'sqlite3') {
|
||||
if (driver === 'sqlite') {
|
||||
return parts.length === 1 ? { catalog: null, db: null, name: parts[0]! } : null;
|
||||
}
|
||||
if (driver === 'bigquery' || driver === 'snowflake' || driver === 'sqlserver') {
|
||||
|
|
@ -156,7 +156,7 @@ function parseDisplay(driver: CatalogDriver, display: string): KtxTableRef | nul
|
|||
}
|
||||
|
||||
function expectedDisplayPartCount(driver: CatalogDriver): number {
|
||||
if (driver === 'sqlite' || driver === 'sqlite3') {
|
||||
if (driver === 'sqlite') {
|
||||
return 1;
|
||||
}
|
||||
if (driver === 'bigquery' || driver === 'snowflake' || driver === 'sqlserver') {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue