feat: allow generic historic sql readers locally

This commit is contained in:
Andrey Avtomonov 2026-05-11 19:25:29 +02:00
parent 1b1b32d717
commit 5d72c1f240
2 changed files with 49 additions and 3 deletions

View file

@ -4,6 +4,7 @@ import { join } from 'node:path';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { initKtxProject, type KtxLocalProject, loadKtxProject } from '../project/index.js';
import type { SqlAnalysisPort } from '../sql-analysis/index.js';
import type { HistoricSqlReader } from './adapters/historic-sql/types.js';
import { LocalLookerRuntimeStore } from './adapters/looker/local-runtime-store.js';
import { createDefaultLocalIngestAdapters, localPullConfigForAdapter } from './local-adapters.js';
@ -110,6 +111,44 @@ describe('local ingest adapters', () => {
expect(adapters.map((adapter) => adapter.source)).toContain('historic-sql');
expect(adapters.find((adapter) => adapter.source === 'historic-sql')?.fetch).toBeTypeOf('function');
expect(adapters.find((adapter) => adapter.source === 'historic-sql')?.skillNames).toEqual([
'historic_sql_table_digest',
'historic_sql_patterns',
]);
});
it('registers historic-sql with an injected non-Postgres reader and query client', () => {
const reader: HistoricSqlReader = {
async probe() {
return { warnings: [], info: [] };
},
async *fetchAggregated() {},
};
const queryClient = { executeQuery: async () => ({ headers: [], rows: [], totalRows: 0 }) };
const adapters = createDefaultLocalIngestAdapters(project, {
historicSql: {
sqlAnalysis: {
async analyzeForFingerprint(sql) {
return {
fingerprint: 'fp',
normalizedSql: sql,
tablesTouched: [],
literalSlots: [],
};
},
async analyzeBatch() {
return new Map();
},
},
reader,
queryClient,
},
});
const adapter = adapters.find((candidate) => candidate.source === 'historic-sql');
expect(adapter).toBeDefined();
expect(adapter?.fetch).toBeTypeOf('function');
});
it('builds Postgres historic-sql pull config from a local connection', async () => {

View file

@ -10,6 +10,7 @@ import { PostgresPgssReader } from './adapters/historic-sql/postgres-pgss-reader
import {
HISTORIC_SQL_SOURCE_KEY,
historicSqlUnifiedPullConfigSchema,
type HistoricSqlReader,
type KtxPostgresQueryClient,
} from './adapters/historic-sql/types.js';
import {
@ -42,7 +43,9 @@ export interface DefaultLocalIngestAdaptersOptions {
databaseIntrospection?: Omit<DaemonLiveDatabaseIntrospectionOptions, 'connections' | 'baseUrl'>;
historicSql?: {
sqlAnalysis: SqlAnalysisPort;
postgresQueryClient: KtxPostgresQueryClient;
reader?: HistoricSqlReader;
queryClient?: unknown;
postgresQueryClient?: KtxPostgresQueryClient;
postgresBaselineRootDir?: string;
now?: () => Date;
};
@ -90,11 +93,15 @@ export function createDefaultLocalIngestAdapters(
];
if (options.historicSql) {
const queryClient = options.historicSql.queryClient ?? options.historicSql.postgresQueryClient;
if (!queryClient) {
throw new Error('Historic SQL local adapter requires queryClient or postgresQueryClient');
}
adapters.push(
new HistoricSqlSourceAdapter({
sqlAnalysis: options.historicSql.sqlAnalysis,
reader: new PostgresPgssReader(),
queryClient: options.historicSql.postgresQueryClient,
reader: options.historicSql.reader ?? new PostgresPgssReader(),
queryClient,
legacyPostgresBaselineRootDir: options.historicSql.postgresBaselineRootDir,
now: options.historicSql.now,
}),