refactor(cli): use dialect SQL in relationship workflows

This commit is contained in:
Andrey Avtomonov 2026-05-25 00:41:03 +02:00
parent 47f3206979
commit 33356d38da
7 changed files with 110 additions and 224 deletions

View file

@ -2,15 +2,11 @@ import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
import Database from 'better-sqlite3';
import { afterEach, describe, expect, it, vi } from 'vitest';
import { getDialectForDriver } from '../connections/dialects.js';
import type { KtxEnrichedColumn, KtxEnrichedSchema, KtxEnrichedTable } from './enrichment-types.js';
import { snapshotToKtxEnrichedSchema } from './local-enrichment.js';
import { loadKtxRelationshipBenchmarkFixture, maskKtxRelationshipBenchmarkSnapshot } from './relationship-benchmarks.js';
import {
createKtxRelationshipProfileCache,
formatKtxRelationshipTableRef,
profileKtxRelationshipSchema,
quoteKtxRelationshipIdentifier,
} from './relationship-profiling.js';
import { createKtxRelationshipProfileCache, profileKtxRelationshipSchema } from './relationship-profiling.js';
import type { KtxQueryResult, KtxReadOnlyQueryInput, KtxScanContext } from './types.js';
class InMemorySqliteExecutor {
@ -112,16 +108,6 @@ describe('relationship profiling', () => {
expect(source).toMatch(/UNION ALL/);
});
it('quotes identifiers and formats table refs for supported local SQL drivers', () => {
expect(quoteKtxRelationshipIdentifier('sqlite', 'odd"name')).toBe('"odd""name"');
expect(quoteKtxRelationshipIdentifier('mysql', 'odd`name')).toBe('`odd``name`');
expect(quoteKtxRelationshipIdentifier('sqlserver', 'odd]name')).toBe('[odd]]name]');
expect(formatKtxRelationshipTableRef('sqlite', { catalog: null, db: null, name: 'accounts' })).toBe('"accounts"');
expect(formatKtxRelationshipTableRef('postgres', { catalog: null, db: 'analytics', name: 'accounts' })).toBe(
'"analytics"."accounts"',
);
});
it('profiles row count, null rate, uniqueness, sample values, and text lengths', async () => {
executor = new InMemorySqliteExecutor();
executor.db.exec(`
@ -135,7 +121,7 @@ describe('relationship profiling', () => {
const result = await profileKtxRelationshipSchema({
connectionId: 'warehouse',
driver: 'sqlite',
dialect: getDialectForDriver('sqlite'),
schema: schema([
table('accounts', [
column('accounts', 'id', { primaryKey: false, nullable: false }),
@ -197,7 +183,7 @@ describe('relationship profiling', () => {
const result = await profileKtxRelationshipSchema({
connectionId: 'warehouse',
driver: 'sqlite',
dialect: getDialectForDriver('sqlite'),
schema: schema([
table('accounts', [
column('accounts', 'id', { nullable: false }),
@ -240,7 +226,7 @@ describe('relationship profiling', () => {
const profiles = await profileKtxRelationshipSchema({
connectionId: 'warehouse',
driver: 'sqlite',
dialect: getDialectForDriver('sqlite'),
schema: schema([
table('accounts', [
column('accounts', 'id', { nullable: false }),
@ -291,7 +277,7 @@ describe('relationship profiling', () => {
const first = await profileKtxRelationshipSchema({
connectionId: 'warehouse',
driver: 'sqlite',
dialect: getDialectForDriver('sqlite'),
schema: relationshipSchema,
executor,
ctx: { runId: 'profile-cache-run' },
@ -299,7 +285,7 @@ describe('relationship profiling', () => {
});
const second = await profileKtxRelationshipSchema({
connectionId: 'warehouse',
driver: 'sqlite',
dialect: getDialectForDriver('sqlite'),
schema: relationshipSchema,
executor,
ctx: { runId: 'profile-cache-run' },
@ -307,7 +293,7 @@ describe('relationship profiling', () => {
});
const third = await profileKtxRelationshipSchema({
connectionId: 'warehouse',
driver: 'sqlite',
dialect: getDialectForDriver('sqlite'),
schema: relationshipSchema,
executor,
ctx: { runId: 'profile-cache-fresh-run' },
@ -336,7 +322,7 @@ describe('relationship profiling', () => {
try {
const result = await profileKtxRelationshipSchema({
connectionId: fixture.snapshot.connectionId,
driver: fixture.snapshot.driver,
dialect: getDialectForDriver(fixture.snapshot.driver),
schema: snapshotToKtxEnrichedSchema(maskedSnapshot, new Map()),
executor: scaleExecutor,
ctx: { runId: 'scale-stress-profile-query-count' },
@ -381,7 +367,7 @@ describe('relationship profiling', () => {
await profileKtxRelationshipSchema({
connectionId: 'warehouse',
driver: 'sqlite',
dialect: getDialectForDriver('sqlite'),
schema: schemaWithTables(['accounts', 'orders', 'payments', 'refunds']),
executor,
ctx: { runId: 'profile-concurrency' },
@ -417,7 +403,7 @@ describe('relationship profiling', () => {
const result = await profileKtxRelationshipSchema({
connectionId: 'warehouse',
driver: 'sqlite',
dialect: getDialectForDriver('sqlite'),
schema: schemaWithTables(['accounts', 'orders']),
executor,
ctx: { runId: 'profile-error-isolated' },