fix(cli): rename sql connection flag

This commit is contained in:
Andrey Avtomonov 2026-05-17 10:21:56 +02:00
parent 03ec7b1989
commit d3767152e9
5 changed files with 29 additions and 14 deletions

View file

@ -70,7 +70,7 @@ Agent integration ready: yes (codex:project)
| `ktx sl search "revenue"` | Search semantic-layer sources |
| `ktx sl validate <source> --connection-id <id>` | Validate a semantic source |
| `ktx sl query --measure <measure> --format sql` | Compile semantic-layer SQL |
| `ktx sql --connection-id <id> "select 1"` | Execute read-only SQL |
| `ktx sql --connection <id> "select 1"` | Execute read-only SQL |
| `ktx wiki search "revenue definition"` | Search local wiki context |
| `ktx mcp start` | Start the local MCP server for agent clients |

View file

@ -81,7 +81,7 @@ ktx sl search "revenue"
ktx wiki search "revenue recognition"
# Execute read-only SQL
ktx sql --connection-id warehouse "select count(*) from public.orders"
ktx sql --connection warehouse "select count(*) from public.orders"
# Start the local MCP server for agent clients
ktx mcp start

View file

@ -12,7 +12,7 @@ validates the statement before execution and only accepts a single `SELECT` or
Use `ktx sql` with a required connection id and positional SQL text.
```bash
ktx sql --connection-id <id> [options] <sql...>
ktx sql --connection <id> [options] <sql...>
```
## Options
@ -22,7 +22,7 @@ JSON.
| Flag | Description | Default |
|------|-------------|---------|
| `--connection-id <id>` | KTX database connection id. Required. | - |
| `-c`, `--connection <id>` | KTX database connection id. Required. | - |
| `--max-rows <n>` | Maximum rows to return. Must be between `1` and `10000`. | `1000` |
| `--output <mode>` | Output mode: `pretty`, `plain` (TSV), or `json`. | `pretty` |
| `--json` | Shortcut for `--output=json` (overrides `--output`). | `false` |
@ -33,23 +33,23 @@ Quote SQL in shell scripts and when the query contains spaces or punctuation.
```bash
# Count rows in a table
ktx sql --connection-id warehouse "select count(*) from public.orders"
ktx sql --connection warehouse "select count(*) from public.orders"
# Return a small result set
ktx sql \
--connection-id warehouse \
--connection warehouse \
--max-rows 25 \
"select id, status from public.orders order by created_at desc"
# Print JSON for agents or scripts
ktx sql \
--connection-id warehouse \
--connection warehouse \
--json \
"select status, count(*) from public.orders group by status"
# Print TSV rows
ktx sql \
--connection-id warehouse \
-c warehouse \
--output plain \
"select id, status from public.orders"
```

View file

@ -33,7 +33,7 @@ describe('registerSqlCommands', () => {
await expect(
program.parseAsync(
['--project-dir', '/tmp/ktx-sql', 'sql', '--connection-id', 'warehouse', 'select', '1'],
['--project-dir', '/tmp/ktx-sql', 'sql', '--connection', 'warehouse', 'select', '1'],
{ from: 'user' },
),
).resolves.toBe(program);
@ -53,13 +53,28 @@ describe('registerSqlCommands', () => {
);
});
it('supports the short connection flag', async () => {
const program = new Command().exitOverride().option('--project-dir <path>');
const sql = vi.fn(async () => 0);
const context = makeContext({ deps: { sql } });
registerSqlCommands(program, context);
await expect(
program.parseAsync(['--project-dir', '/tmp/ktx-sql', 'sql', '-c', 'warehouse', 'select 1'], {
from: 'user',
}),
).resolves.toBe(program);
expect(sql).toHaveBeenCalledWith(expect.objectContaining({ connectionId: 'warehouse', sql: 'select 1' }), context.io);
});
it('rejects missing SQL before invoking the runner', async () => {
const program = new Command().exitOverride().option('--project-dir <path>');
const sql = vi.fn(async () => 0);
registerSqlCommands(program, makeContext({ deps: { sql } }));
await expect(
program.parseAsync(['--project-dir', '/tmp/ktx-sql', 'sql', '--connection-id', 'warehouse'], {
program.parseAsync(['--project-dir', '/tmp/ktx-sql', 'sql', '--connection', 'warehouse'], {
from: 'user',
}),
).rejects.toThrow('missing required argument');
@ -74,7 +89,7 @@ describe('registerSqlCommands', () => {
await expect(
program.parseAsync(
['--project-dir', '/tmp/ktx-sql', 'sql', '--connection-id', 'warehouse', '--max-rows', '10001', 'select 1'],
['--project-dir', '/tmp/ktx-sql', 'sql', '--connection', 'warehouse', '--max-rows', '10001', 'select 1'],
{ from: 'user' },
),
).rejects.toThrow('must be an integer between 1 and 10000');

View file

@ -26,7 +26,7 @@ export function registerSqlCommands(program: Command, context: KtxCliCommandCont
.command('sql')
.description('Execute parser-validated read-only SQL against a configured connection')
.argument('<sql...>', 'SQL query to execute')
.requiredOption('--connection-id <id>', 'KTX connection id')
.requiredOption('-c, --connection <id>', 'KTX connection id')
.option('--max-rows <n>', 'Maximum rows to return', parseSqlMaxRowsOption, DEFAULT_MAX_ROWS)
.addOption(
new Option('--output <mode>', 'Output mode: pretty (default), plain (TSV), or json').choices([
@ -40,7 +40,7 @@ export function registerSqlCommands(program: Command, context: KtxCliCommandCont
async (
sqlParts: string[],
options: {
connectionId: string;
connection: string;
maxRows: number;
output?: 'pretty' | 'plain' | 'json';
json?: boolean;
@ -50,7 +50,7 @@ export function registerSqlCommands(program: Command, context: KtxCliCommandCont
await runSqlArgs(context, {
command: 'execute',
projectDir: resolveCommandProjectDir(command),
connectionId: options.connectionId,
connectionId: options.connection,
sql: sqlParts.join(' '),
maxRows: options.maxRows,
output: options.output,