mirror of
https://github.com/Kaelio/ktx.git
synced 2026-06-13 08:15:14 +02:00
fix(setup): use schema context and query history wording
This commit is contained in:
parent
9c7b4f9b84
commit
0b16578dd5
4 changed files with 129 additions and 136 deletions
|
|
@ -118,12 +118,12 @@ function shouldShowSetupEntryMenu(
|
|||
newDatabaseConnectionId?: string;
|
||||
databaseUrl?: string;
|
||||
databaseSchema?: string[];
|
||||
enableHistoricSql?: boolean;
|
||||
disableHistoricSql?: boolean;
|
||||
historicSqlWindowDays?: number;
|
||||
historicSqlMinExecutions?: number;
|
||||
historicSqlServiceAccountPattern?: string[];
|
||||
historicSqlRedactionPattern?: string[];
|
||||
enableQueryHistory?: boolean;
|
||||
disableQueryHistory?: boolean;
|
||||
queryHistoryWindowDays?: number;
|
||||
queryHistoryMinExecutions?: number;
|
||||
queryHistoryServiceAccountPattern?: string[];
|
||||
queryHistoryRedactionPattern?: string[];
|
||||
skipDatabases?: boolean;
|
||||
source?: KtxSetupSourceType;
|
||||
sourceConnectionId?: string;
|
||||
|
|
@ -157,10 +157,10 @@ function shouldShowSetupEntryMenu(
|
|||
if (options.databaseSchema && options.databaseSchema.length > 0) {
|
||||
return false;
|
||||
}
|
||||
if (options.historicSqlServiceAccountPattern && options.historicSqlServiceAccountPattern.length > 0) {
|
||||
if (options.queryHistoryServiceAccountPattern && options.queryHistoryServiceAccountPattern.length > 0) {
|
||||
return false;
|
||||
}
|
||||
if (options.historicSqlRedactionPattern && options.historicSqlRedactionPattern.length > 0) {
|
||||
if (options.queryHistoryRedactionPattern && options.queryHistoryRedactionPattern.length > 0) {
|
||||
return false;
|
||||
}
|
||||
if (options.notionRootPageId && options.notionRootPageId.length > 0) {
|
||||
|
|
@ -190,10 +190,10 @@ function shouldShowSetupEntryMenu(
|
|||
'skipEmbeddings',
|
||||
'newDatabaseConnectionId',
|
||||
'databaseUrl',
|
||||
'enableHistoricSql',
|
||||
'disableHistoricSql',
|
||||
'historicSqlWindowDays',
|
||||
'historicSqlMinExecutions',
|
||||
'enableQueryHistory',
|
||||
'disableQueryHistory',
|
||||
'queryHistoryWindowDays',
|
||||
'queryHistoryMinExecutions',
|
||||
'skipDatabases',
|
||||
'source',
|
||||
'sourceConnectionId',
|
||||
|
|
@ -282,19 +282,19 @@ export function registerSetupCommands(program: Command, context: KtxCliCommandCo
|
|||
(value, previous: string[]) => [...previous, value],
|
||||
[],
|
||||
)
|
||||
.option('--enable-historic-sql', 'Enable Historic SQL when the selected database supports it', false)
|
||||
.option('--disable-historic-sql', 'Disable Historic SQL for the selected database', false)
|
||||
.option('--historic-sql-window-days <number>', 'Historic SQL query-history window', positiveInteger)
|
||||
.option('--historic-sql-min-executions <number>', 'Minimum Historic SQL executions for a template', positiveInteger)
|
||||
.option('--enable-query-history', 'Enable query history when the selected database supports it', false)
|
||||
.option('--disable-query-history', 'Disable query history for the selected database', false)
|
||||
.option('--query-history-window-days <number>', 'Query-history lookback window', positiveInteger)
|
||||
.option('--query-history-min-executions <number>', 'Minimum executions for a query-history template', positiveInteger)
|
||||
.option(
|
||||
'--historic-sql-service-account-pattern <pattern>',
|
||||
'Historic SQL service-account regex; repeatable',
|
||||
'--query-history-service-account-pattern <pattern>',
|
||||
'Query-history service-account regex; repeatable',
|
||||
(value, previous: string[]) => [...previous, value],
|
||||
[],
|
||||
)
|
||||
.option(
|
||||
'--historic-sql-redaction-pattern <pattern>',
|
||||
'Historic SQL SQL-literal redaction regex; repeatable',
|
||||
'--query-history-redaction-pattern <pattern>',
|
||||
'Query-history SQL-literal redaction regex; repeatable',
|
||||
(value, previous: string[]) => [...previous, value],
|
||||
[],
|
||||
)
|
||||
|
|
@ -357,9 +357,9 @@ export function registerSetupCommands(program: Command, context: KtxCliCommandCo
|
|||
context.setExitCode(1);
|
||||
return;
|
||||
}
|
||||
if (options.enableHistoricSql && options.disableHistoricSql) {
|
||||
if (options.enableQueryHistory && options.disableQueryHistory) {
|
||||
context.io.stderr.write(
|
||||
'Choose only one Historic SQL action: --enable-historic-sql or --disable-historic-sql.\n',
|
||||
'Choose only one query-history action: --enable-query-history or --disable-query-history.\n',
|
||||
);
|
||||
context.setExitCode(1);
|
||||
return;
|
||||
|
|
@ -404,17 +404,17 @@ export function registerSetupCommands(program: Command, context: KtxCliCommandCo
|
|||
...(options.newDatabaseConnectionId ? { databaseConnectionId: options.newDatabaseConnectionId } : {}),
|
||||
...(options.databaseUrl ? { databaseUrl: options.databaseUrl } : {}),
|
||||
databaseSchemas: options.databaseSchema,
|
||||
...(options.enableHistoricSql ? { enableHistoricSql: true } : {}),
|
||||
...(options.disableHistoricSql ? { disableHistoricSql: true } : {}),
|
||||
...(options.historicSqlWindowDays !== undefined ? { historicSqlWindowDays: options.historicSqlWindowDays } : {}),
|
||||
...(options.historicSqlMinExecutions !== undefined
|
||||
? { historicSqlMinExecutions: options.historicSqlMinExecutions }
|
||||
...(options.enableQueryHistory ? { enableQueryHistory: true } : {}),
|
||||
...(options.disableQueryHistory ? { disableQueryHistory: true } : {}),
|
||||
...(options.queryHistoryWindowDays !== undefined ? { queryHistoryWindowDays: options.queryHistoryWindowDays } : {}),
|
||||
...(options.queryHistoryMinExecutions !== undefined
|
||||
? { queryHistoryMinExecutions: options.queryHistoryMinExecutions }
|
||||
: {}),
|
||||
...(options.historicSqlServiceAccountPattern.length > 0
|
||||
? { historicSqlServiceAccountPatterns: options.historicSqlServiceAccountPattern }
|
||||
...(options.queryHistoryServiceAccountPattern.length > 0
|
||||
? { queryHistoryServiceAccountPatterns: options.queryHistoryServiceAccountPattern }
|
||||
: {}),
|
||||
...(options.historicSqlRedactionPattern.length > 0
|
||||
? { historicSqlRedactionPatterns: options.historicSqlRedactionPattern }
|
||||
...(options.queryHistoryRedactionPattern.length > 0
|
||||
? { queryHistoryRedactionPatterns: options.queryHistoryRedactionPattern }
|
||||
: {}),
|
||||
skipDatabases: options.skipDatabases === true,
|
||||
...(options.source ? { source: options.source } : {}),
|
||||
|
|
|
|||
|
|
@ -443,6 +443,18 @@ describe('runKtxCli', () => {
|
|||
expect(testIo.stdout()).not.toContain('--embedding-model');
|
||||
expect(testIo.stdout()).not.toContain('--embedding-dimensions');
|
||||
expect(testIo.stdout()).not.toContain('--embedding-base-url');
|
||||
for (const expected of [
|
||||
'--enable-query-history',
|
||||
'--disable-query-history',
|
||||
'--query-history-window-days',
|
||||
'--query-history-min-executions',
|
||||
'--query-history-service-account-pattern',
|
||||
'--query-history-redaction-pattern',
|
||||
]) {
|
||||
expect(testIo.stdout()).toContain(expected);
|
||||
}
|
||||
expect(testIo.stdout()).not.toContain('--enable-historic-sql');
|
||||
expect(testIo.stdout()).not.toContain('--historic-sql-window-days');
|
||||
expect(testIo.stderr()).toBe('');
|
||||
});
|
||||
|
||||
|
|
@ -1142,10 +1154,10 @@ describe('runKtxCli', () => {
|
|||
'env:DATABASE_URL',
|
||||
'--database-schema',
|
||||
'public',
|
||||
'--enable-historic-sql',
|
||||
'--historic-sql-window-days',
|
||||
'--enable-query-history',
|
||||
'--query-history-window-days',
|
||||
'30',
|
||||
'--historic-sql-min-executions',
|
||||
'--query-history-min-executions',
|
||||
'12',
|
||||
],
|
||||
setupIo.io,
|
||||
|
|
@ -1166,9 +1178,9 @@ describe('runKtxCli', () => {
|
|||
databaseConnectionId: 'warehouse',
|
||||
databaseUrl: 'env:DATABASE_URL',
|
||||
databaseSchemas: ['public'],
|
||||
enableHistoricSql: true,
|
||||
historicSqlWindowDays: 30,
|
||||
historicSqlMinExecutions: 12,
|
||||
enableQueryHistory: true,
|
||||
queryHistoryWindowDays: 30,
|
||||
queryHistoryMinExecutions: 12,
|
||||
skipDatabases: false,
|
||||
}),
|
||||
setupIo.io,
|
||||
|
|
@ -1346,18 +1358,20 @@ describe('runKtxCli', () => {
|
|||
expect(setupIo.stderr()).toContain('Choose only one embedding credential source');
|
||||
});
|
||||
|
||||
it('rejects conflicting Historic SQL setup flags', async () => {
|
||||
it('rejects conflicting query-history setup flags', async () => {
|
||||
const setup = vi.fn(async () => 0);
|
||||
const setupIo = makeIo();
|
||||
|
||||
await expect(
|
||||
runKtxCli(['--project-dir', tempDir, 'setup', '--enable-historic-sql', '--disable-historic-sql'], setupIo.io, {
|
||||
runKtxCli(['--project-dir', tempDir, 'setup', '--enable-query-history', '--disable-query-history'], setupIo.io, {
|
||||
setup,
|
||||
}),
|
||||
).resolves.toBe(1);
|
||||
|
||||
expect(setup).not.toHaveBeenCalled();
|
||||
expect(setupIo.stderr()).toContain('Choose only one Historic SQL action');
|
||||
expect(setupIo.stderr()).toContain(
|
||||
'Choose only one query-history action: --enable-query-history or --disable-query-history.',
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects the removed hidden agent command', async () => {
|
||||
|
|
|
|||
|
|
@ -954,23 +954,17 @@ describe('setup databases step', () => {
|
|||
].join('\n'),
|
||||
);
|
||||
expect(io.stdout()).not.toContain('Tables: 2');
|
||||
expect(io.stdout()).toContain(
|
||||
[
|
||||
'◇ Scanning postgres-warehouse',
|
||||
'│ Running structural scan…',
|
||||
'│',
|
||||
].join('\n'),
|
||||
);
|
||||
expect(io.stdout()).toContain(
|
||||
[
|
||||
'◇ Scan complete for postgres-warehouse',
|
||||
'│ Changes: 2 new tables',
|
||||
'│ Report: raw-sources/postgres-warehouse/live-database/.../scan-report.json',
|
||||
'│',
|
||||
'◇ Primary source ready',
|
||||
'│ postgres-warehouse · PostgreSQL · structural scan complete',
|
||||
].join('\n'),
|
||||
);
|
||||
expect(io.stdout()).toContain('◇ Building schema context for postgres-warehouse');
|
||||
expect(io.stdout()).toContain('│ Running fast database ingest…');
|
||||
expect(io.stdout()).toContain('◇ Schema context complete for postgres-warehouse');
|
||||
expect(io.stdout()).toContain('│ Changes: 2 new tables');
|
||||
expect(io.stdout()).toContain('◇ Primary source ready');
|
||||
expect(io.stdout()).toContain('│ postgres-warehouse · PostgreSQL · schema context complete');
|
||||
expect(io.stdout()).not.toContain('Scanning postgres-warehouse');
|
||||
expect(io.stdout()).not.toContain('Scan complete for postgres-warehouse');
|
||||
expect(io.stdout()).not.toContain('structural scan complete');
|
||||
expect(io.stdout()).not.toContain('Report: raw-sources');
|
||||
expect(io.stdout()).not.toContain('live-database');
|
||||
expect(io.stdout()).not.toContain('[5%] Preparing scan');
|
||||
expect(io.stdout()).not.toContain('What changed');
|
||||
expect(io.stdout()).not.toContain('Next:');
|
||||
|
|
@ -1278,7 +1272,8 @@ describe('setup databases step', () => {
|
|||
expect(io.stderr()).toContain('Native SQLite is built for a different Node.js ABI.');
|
||||
expect(io.stderr()).toContain('│ Native SQLite is built for a different Node.js ABI.');
|
||||
expect(io.stderr()).toContain('Fix: pnpm run native:rebuild');
|
||||
expect(io.stderr()).toContain(`Retry: ktx scan --project-dir ${tempDir} warehouse`);
|
||||
expect(io.stderr()).toContain(`Retry: ktx ingest warehouse --project-dir ${tempDir} --fast`);
|
||||
expect(io.stderr()).not.toContain('ktx scan');
|
||||
expect(io.stderr()).not.toContain('npm rebuild');
|
||||
expect(io.stderr()).not.toMatch(/^Native SQLite is built for a different Node.js ABI\./m);
|
||||
});
|
||||
|
|
@ -1337,7 +1332,7 @@ describe('setup databases step', () => {
|
|||
expect(io.stdout()).toContain('◇ Scan complete for warehouse');
|
||||
});
|
||||
|
||||
it('writes Historic SQL config for supported Snowflake databases after validation succeeds', async () => {
|
||||
it('writes query history config for supported Snowflake databases after validation succeeds', async () => {
|
||||
const io = makeIo();
|
||||
const result = await runKtxSetupDatabasesStep(
|
||||
{
|
||||
|
|
@ -1346,10 +1341,10 @@ describe('setup databases step', () => {
|
|||
databaseDrivers: ['snowflake'],
|
||||
databaseConnectionId: 'snowflake',
|
||||
databaseSchemas: [],
|
||||
enableHistoricSql: true,
|
||||
historicSqlWindowDays: 30,
|
||||
historicSqlServiceAccountPatterns: ['^svc_'],
|
||||
historicSqlRedactionPatterns: ['(?i)secret'],
|
||||
enableQueryHistory: true,
|
||||
queryHistoryWindowDays: 30,
|
||||
queryHistoryServiceAccountPatterns: ['^svc_'],
|
||||
queryHistoryRedactionPatterns: ['(?i)secret'],
|
||||
skipDatabases: false,
|
||||
},
|
||||
io.io,
|
||||
|
|
@ -1391,7 +1386,7 @@ describe('setup databases step', () => {
|
|||
expect(config.ingest.adapters).toEqual([]);
|
||||
});
|
||||
|
||||
it('writes Postgres Historic SQL config with minExecutions and ignores window/redaction output', async () => {
|
||||
it('writes Postgres query history config with minExecutions and ignores window/redaction output', async () => {
|
||||
const io = makeIo();
|
||||
const result = await runKtxSetupDatabasesStep(
|
||||
{
|
||||
|
|
@ -1401,11 +1396,11 @@ describe('setup databases step', () => {
|
|||
databaseConnectionId: 'warehouse',
|
||||
databaseUrl: 'env:DATABASE_URL',
|
||||
databaseSchemas: ['public'],
|
||||
enableHistoricSql: true,
|
||||
historicSqlWindowDays: 30,
|
||||
historicSqlMinExecutions: 12,
|
||||
historicSqlServiceAccountPatterns: ['^svc_'],
|
||||
historicSqlRedactionPatterns: ['(?i)secret'],
|
||||
enableQueryHistory: true,
|
||||
queryHistoryWindowDays: 30,
|
||||
queryHistoryMinExecutions: 12,
|
||||
queryHistoryServiceAccountPatterns: ['^svc_'],
|
||||
queryHistoryRedactionPatterns: ['(?i)secret'],
|
||||
skipDatabases: false,
|
||||
},
|
||||
io.io,
|
||||
|
|
@ -1451,11 +1446,12 @@ describe('setup databases step', () => {
|
|||
expect(configText).not.toMatch(/^\s+adapters:/m);
|
||||
expect(config.ingest.adapters).toEqual([]);
|
||||
expect(config.ingest.workUnits.maxConcurrency).toBe(6);
|
||||
expect(io.stdout()).toContain('Historic SQL probe...');
|
||||
expect(io.stdout()).toContain('Query history probe...');
|
||||
expect(io.stdout()).not.toContain('Historic SQL probe...');
|
||||
expect(io.stdout()).toContain('pg_stat_statements ready');
|
||||
});
|
||||
|
||||
it('writes Historic SQL config for supported existing database connections', async () => {
|
||||
it('writes query history config for supported existing database connections', async () => {
|
||||
await writeFile(
|
||||
join(tempDir, 'ktx.yaml'),
|
||||
[
|
||||
|
|
@ -1478,8 +1474,8 @@ describe('setup databases step', () => {
|
|||
inputMode: 'disabled',
|
||||
databaseConnectionIds: ['analytics'],
|
||||
databaseSchemas: [],
|
||||
enableHistoricSql: true,
|
||||
historicSqlWindowDays: 45,
|
||||
enableQueryHistory: true,
|
||||
queryHistoryWindowDays: 45,
|
||||
skipDatabases: false,
|
||||
},
|
||||
io.io,
|
||||
|
|
@ -1511,7 +1507,7 @@ describe('setup databases step', () => {
|
|||
expect(config.ingest.adapters).toEqual([]);
|
||||
});
|
||||
|
||||
it('enables Historic SQL on an existing Postgres connection', async () => {
|
||||
it('enables query history on an existing Postgres connection', async () => {
|
||||
await writeFile(
|
||||
join(tempDir, 'ktx.yaml'),
|
||||
[
|
||||
|
|
@ -1533,8 +1529,8 @@ describe('setup databases step', () => {
|
|||
inputMode: 'disabled',
|
||||
databaseConnectionIds: ['warehouse'],
|
||||
databaseSchemas: [],
|
||||
enableHistoricSql: true,
|
||||
historicSqlMinExecutions: 8,
|
||||
enableQueryHistory: true,
|
||||
queryHistoryMinExecutions: 8,
|
||||
skipDatabases: false,
|
||||
},
|
||||
io.io,
|
||||
|
|
@ -1635,7 +1631,7 @@ describe('setup databases step', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('prints a non-blocking Postgres Historic SQL probe failure after connection test succeeds', async () => {
|
||||
it('prints a non-blocking Postgres query history probe failure after connection test succeeds', async () => {
|
||||
const io = makeIo();
|
||||
const historicSqlProbe = vi.fn(async () => ({
|
||||
ok: false,
|
||||
|
|
@ -1654,7 +1650,7 @@ describe('setup databases step', () => {
|
|||
databaseConnectionId: 'warehouse',
|
||||
databaseUrl: 'env:DATABASE_URL',
|
||||
databaseSchemas: [],
|
||||
enableHistoricSql: true,
|
||||
enableQueryHistory: true,
|
||||
skipDatabases: false,
|
||||
},
|
||||
io.io,
|
||||
|
|
@ -1673,12 +1669,13 @@ describe('setup databases step', () => {
|
|||
dialect: 'postgres',
|
||||
}),
|
||||
);
|
||||
expect(io.stdout()).toContain('Historic SQL probe...');
|
||||
expect(io.stdout()).toContain('Query history probe...');
|
||||
expect(io.stdout()).not.toContain('Historic SQL probe...');
|
||||
expect(io.stdout()).toContain('pg_stat_statements extension is not installed');
|
||||
expect(io.stdout()).toContain('Setup written; first ingest run will fail until fixed.');
|
||||
});
|
||||
|
||||
it('does not run the Historic SQL probe when the regular connection test fails', async () => {
|
||||
it('does not run the query history probe when the regular connection test fails', async () => {
|
||||
const io = makeIo();
|
||||
const historicSqlProbe = vi.fn(async () => ({ ok: true, lines: [] }));
|
||||
|
||||
|
|
@ -1690,7 +1687,7 @@ describe('setup databases step', () => {
|
|||
databaseConnectionId: 'warehouse',
|
||||
databaseUrl: 'env:DATABASE_URL',
|
||||
databaseSchemas: [],
|
||||
enableHistoricSql: true,
|
||||
enableQueryHistory: true,
|
||||
skipDatabases: false,
|
||||
},
|
||||
io.io,
|
||||
|
|
|
|||
|
|
@ -43,12 +43,12 @@ export interface KtxSetupDatabasesArgs {
|
|||
databaseConnectionId?: string;
|
||||
databaseUrl?: string;
|
||||
databaseSchemas: string[];
|
||||
enableHistoricSql?: boolean;
|
||||
disableHistoricSql?: boolean;
|
||||
historicSqlWindowDays?: number;
|
||||
historicSqlMinExecutions?: number;
|
||||
historicSqlServiceAccountPatterns?: string[];
|
||||
historicSqlRedactionPatterns?: string[];
|
||||
enableQueryHistory?: boolean;
|
||||
disableQueryHistory?: boolean;
|
||||
queryHistoryWindowDays?: number;
|
||||
queryHistoryMinExecutions?: number;
|
||||
queryHistoryServiceAccountPatterns?: string[];
|
||||
queryHistoryRedactionPatterns?: string[];
|
||||
skipDatabases: boolean;
|
||||
}
|
||||
|
||||
|
|
@ -301,7 +301,7 @@ function historicSqlProbeFailureLines(error: unknown): string[] {
|
|||
if (error instanceof Error && error.name === 'HistoricSqlVersionUnsupportedError') {
|
||||
return [` FAIL ${error.message}`];
|
||||
}
|
||||
return [` FAIL Historic SQL probe failed: ${error instanceof Error ? error.message : String(error)}`];
|
||||
return [` FAIL Query history probe failed: ${error instanceof Error ? error.message : String(error)}`];
|
||||
}
|
||||
|
||||
async function defaultHistoricSqlProbe(input: KtxSetupHistoricSqlProbeInput): Promise<KtxSetupHistoricSqlProbeResult> {
|
||||
|
|
@ -831,23 +831,23 @@ async function maybeApplyHistoricSqlConfig(input: {
|
|||
}): Promise<KtxProjectConnectionConfig | 'back'> {
|
||||
const dialect = HISTORIC_SQL_DIALECT_BY_DRIVER[input.driver];
|
||||
if (!dialect) {
|
||||
if (input.args.enableHistoricSql === true) {
|
||||
if (input.args.enableQueryHistory === true) {
|
||||
throw new Error(
|
||||
`Historic SQL setup is only supported for Snowflake, BigQuery, and Postgres, not ${driverLabel(input.driver)}.`,
|
||||
`Query history setup is only supported for Snowflake, BigQuery, and Postgres, not ${driverLabel(input.driver)}.`,
|
||||
);
|
||||
}
|
||||
return input.connection;
|
||||
}
|
||||
|
||||
let enabled = input.args.enableHistoricSql === true;
|
||||
if (input.args.disableHistoricSql === true) {
|
||||
let enabled = input.args.enableQueryHistory === true;
|
||||
if (input.args.disableQueryHistory === true) {
|
||||
enabled = false;
|
||||
} else if (input.args.inputMode !== 'disabled' && input.args.enableHistoricSql !== true && dialect !== 'postgres') {
|
||||
} else if (input.args.inputMode !== 'disabled' && input.args.enableQueryHistory !== true && dialect !== 'postgres') {
|
||||
const choice = await input.prompts.select({
|
||||
message: `Enable Historic SQL query-history ingest for this ${driverLabel(input.driver)} connection?`,
|
||||
message: `Enable query-history ingest for this ${driverLabel(input.driver)} connection?`,
|
||||
options: [
|
||||
{ value: 'yes', label: 'Enable Historic SQL' },
|
||||
{ value: 'no', label: 'Do not enable Historic SQL' },
|
||||
{ value: 'yes', label: 'Enable query history' },
|
||||
{ value: 'no', label: 'Do not enable query history' },
|
||||
{ value: 'back', label: 'Back' },
|
||||
],
|
||||
});
|
||||
|
|
@ -855,7 +855,7 @@ async function maybeApplyHistoricSqlConfig(input: {
|
|||
enabled = choice === 'yes';
|
||||
}
|
||||
|
||||
if (dialect === 'postgres' && input.args.enableHistoricSql !== true && input.args.disableHistoricSql !== true) {
|
||||
if (dialect === 'postgres' && input.args.enableQueryHistory !== true && input.args.disableQueryHistory !== true) {
|
||||
return input.connection;
|
||||
}
|
||||
|
||||
|
|
@ -869,20 +869,20 @@ async function maybeApplyHistoricSqlConfig(input: {
|
|||
const common: Record<string, unknown> = {
|
||||
...existing,
|
||||
enabled: true,
|
||||
filters: historicSqlFiltersForSetup(input.args.historicSqlServiceAccountPatterns),
|
||||
filters: historicSqlFiltersForSetup(input.args.queryHistoryServiceAccountPatterns),
|
||||
};
|
||||
|
||||
if (dialect === 'postgres') {
|
||||
return withQueryHistoryConfig(input.connection, {
|
||||
...common,
|
||||
minExecutions: input.args.historicSqlMinExecutions ?? 5,
|
||||
minExecutions: input.args.queryHistoryMinExecutions ?? 5,
|
||||
});
|
||||
}
|
||||
|
||||
return withQueryHistoryConfig(input.connection, {
|
||||
...common,
|
||||
windowDays: input.args.historicSqlWindowDays ?? 90,
|
||||
redactionPatterns: input.args.historicSqlRedactionPatterns ?? [],
|
||||
windowDays: input.args.queryHistoryWindowDays ?? 90,
|
||||
redactionPatterns: input.args.queryHistoryRedactionPatterns ?? [],
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -1097,20 +1097,6 @@ function summarizeScanChanges(output: string): string {
|
|||
return 'no table changes';
|
||||
}
|
||||
|
||||
function shortenScanReportPath(path: string): string {
|
||||
const normalized = path.trim();
|
||||
const liveDatabaseMarker = '/live-database/';
|
||||
const markerIndex = normalized.indexOf(liveDatabaseMarker);
|
||||
if (markerIndex === -1) {
|
||||
return normalized;
|
||||
}
|
||||
const filename = normalized.split('/').at(-1);
|
||||
if (!filename) {
|
||||
return normalized;
|
||||
}
|
||||
return `${normalized.slice(0, markerIndex + liveDatabaseMarker.length)}.../${filename}`;
|
||||
}
|
||||
|
||||
function writeSetupSection(io: KtxCliIo, title: string, lines: string[]): void {
|
||||
io.stdout.write(`◇ ${title}\n`);
|
||||
for (const line of lines) {
|
||||
|
|
@ -1467,7 +1453,7 @@ async function maybeRunHistoricSqlSetupProbe(input: {
|
|||
return;
|
||||
}
|
||||
|
||||
input.io.stdout.write('│ Historic SQL probe...\n');
|
||||
input.io.stdout.write('│ Query history probe...\n');
|
||||
const probe = input.deps.historicSqlProbe ?? defaultHistoricSqlProbe;
|
||||
const result = await probe({
|
||||
projectDir: input.projectDir,
|
||||
|
|
@ -1488,7 +1474,7 @@ async function applyHistoricSqlConfigToExistingConnection(input: {
|
|||
args: KtxSetupDatabasesArgs;
|
||||
prompts: KtxSetupDatabasesPromptAdapter;
|
||||
}): Promise<'back' | void> {
|
||||
if (input.args.enableHistoricSql !== true && input.args.disableHistoricSql !== true) {
|
||||
if (input.args.enableQueryHistory !== true && input.args.disableQueryHistory !== true) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1557,8 +1543,8 @@ async function validateAndScanConnection(input: {
|
|||
io: input.io,
|
||||
deps: input.deps,
|
||||
});
|
||||
writeSetupSection(input.io, `Scanning ${input.connectionId}`, [
|
||||
'Running structural scan…',
|
||||
writeSetupSection(input.io, `Building schema context for ${input.connectionId}`, [
|
||||
'Running fast database ingest…',
|
||||
]);
|
||||
let scanIo = createBufferedCommandIo();
|
||||
let scanCode = await scanConnection(input.projectDir, input.connectionId, scanIo);
|
||||
|
|
@ -1567,11 +1553,11 @@ async function validateAndScanConnection(input: {
|
|||
if (nativeSqliteDetail) {
|
||||
writePrefixedLines(
|
||||
(chunk) => input.io.stderr.write(chunk),
|
||||
[
|
||||
`Structural scan failed for ${input.connectionId}.`,
|
||||
'Native SQLite is built for a different Node.js ABI.',
|
||||
`Detail: ${nativeSqliteDetail}`,
|
||||
'Rebuilding Native SQLite with pnpm run native:rebuild…',
|
||||
[
|
||||
`Fast database ingest failed for ${input.connectionId}.`,
|
||||
'Native SQLite is built for a different Node.js ABI.',
|
||||
`Detail: ${nativeSqliteDetail}`,
|
||||
'Rebuilding Native SQLite with pnpm run native:rebuild…',
|
||||
].join('\n'),
|
||||
);
|
||||
const rebuildNativeSqlite = input.deps.rebuildNativeSqlite ?? defaultRebuildNativeSqlite;
|
||||
|
|
@ -1579,7 +1565,7 @@ async function validateAndScanConnection(input: {
|
|||
if (rebuildCode === 0) {
|
||||
writePrefixedLines(
|
||||
(chunk) => input.io.stderr.write(chunk),
|
||||
'Native SQLite rebuild complete. Retrying structural scan…',
|
||||
'Native SQLite rebuild complete. Retrying fast database ingest…',
|
||||
);
|
||||
const retryScanIo = createBufferedCommandIo();
|
||||
scanCode = await scanConnection(input.projectDir, input.connectionId, retryScanIo);
|
||||
|
|
@ -1590,10 +1576,10 @@ async function validateAndScanConnection(input: {
|
|||
(chunk) => input.io.stderr.write(chunk),
|
||||
[
|
||||
rebuildCode === 0
|
||||
? `Structural scan still failed for ${input.connectionId} after rebuilding Native SQLite.`
|
||||
? `Fast database ingest still failed for ${input.connectionId} after rebuilding Native SQLite.`
|
||||
: `Native SQLite rebuild failed for ${input.connectionId}.`,
|
||||
'Fix: pnpm run native:rebuild',
|
||||
`Retry: ktx scan --project-dir ${input.projectDir} ${input.connectionId}`,
|
||||
`Retry: ktx ingest ${input.connectionId} --project-dir ${input.projectDir} --fast`,
|
||||
].join('\n'),
|
||||
);
|
||||
}
|
||||
|
|
@ -1602,8 +1588,8 @@ async function validateAndScanConnection(input: {
|
|||
writePrefixedLines(
|
||||
(chunk) => input.io.stderr.write(chunk),
|
||||
[
|
||||
`Structural scan failed for ${input.connectionId}.`,
|
||||
`Debug command: ktx scan --project-dir ${input.projectDir} ${input.connectionId}`,
|
||||
`Fast database ingest failed for ${input.connectionId}.`,
|
||||
`Debug command: ktx ingest ${input.connectionId} --project-dir ${input.projectDir} --fast --debug`,
|
||||
].join('\n'),
|
||||
);
|
||||
}
|
||||
|
|
@ -1612,17 +1598,13 @@ async function validateAndScanConnection(input: {
|
|||
}
|
||||
}
|
||||
const scanOutput = scanIo.stdoutText();
|
||||
const reportPath = readOutputValue(scanOutput, 'Report');
|
||||
writeSetupSection(
|
||||
input.io,
|
||||
`Scan complete for ${input.connectionId}`,
|
||||
[
|
||||
`Changes: ${summarizeScanChanges(scanOutput)}`,
|
||||
...(reportPath ? [`Report: ${shortenScanReportPath(reportPath)}`] : []),
|
||||
],
|
||||
`Schema context complete for ${input.connectionId}`,
|
||||
[`Changes: ${summarizeScanChanges(scanOutput)}`],
|
||||
);
|
||||
writeSetupSection(input.io, 'Primary source ready', [
|
||||
`${input.connectionId} · ${driverDisplay} · structural scan complete`,
|
||||
`${input.connectionId} · ${driverDisplay} · schema context complete`,
|
||||
]);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue