Skip to content

Commit 4e58639

Browse files
author
zth
committed
Add query diagnostics CLI
1 parent 71ca90b commit 4e58639

6 files changed

Lines changed: 685 additions & 11 deletions

File tree

package-lock.json

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/cli/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
"io-ts-reporters": "^2.0.1",
4949
"nunjucks": "3.2.4",
5050
"pascal-case": "^3.1.1",
51+
"pg": "^8.11.2",
5152
"pgtyped-rescript-query": "^3.0.1",
5253
"piscina": "^4.0.0",
5354
"tinypool": "^0.7.0",
@@ -58,6 +59,7 @@
5859
"@types/debug": "4.1.8",
5960
"@types/fs-extra": "11.0.1",
6061
"@types/nunjucks": "^3.1.3",
62+
"@types/pg": "^8.10.2",
6163
"@types/yargs": "17.0.24",
6264
"rescript": "12.2.0"
6365
},
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { jest } from '@jest/globals';
2+
import { parseSQLFile, queryASTToIR } from '@pgtyped/parser';
3+
import { getParameterLabels, runDiagnostics } from './diagnostics.js';
4+
5+
const sqlFile = '../example/src/books/books.sql';
6+
7+
describe('diagnostics', () => {
8+
let logSpy: ReturnType<typeof jest.spyOn>;
9+
10+
beforeEach(() => {
11+
logSpy = jest.spyOn(console, 'log').mockImplementation(() => undefined);
12+
});
13+
14+
afterEach(() => {
15+
logSpy.mockRestore();
16+
});
17+
18+
test('lists query names without config', async () => {
19+
await runDiagnostics(undefined, {
20+
file: sqlFile,
21+
list: true,
22+
mode: 'explain',
23+
format: 'text',
24+
});
25+
26+
expect(logSpy).toHaveBeenCalledWith('FindBookById');
27+
expect(logSpy).toHaveBeenCalledWith('InsertBooks');
28+
});
29+
30+
test('prints processed SQL without config', async () => {
31+
await runDiagnostics(undefined, {
32+
file: sqlFile,
33+
queryName: 'FindBookById',
34+
sql: true,
35+
mode: 'explain',
36+
format: 'text',
37+
});
38+
39+
expect(logSpy).toHaveBeenCalledWith('SELECT * FROM books WHERE id = $1');
40+
});
41+
42+
test('keeps scalar parameter labels when params are supplied', () => {
43+
const query = parseSQLFile(`
44+
/* @name FindBookById */
45+
SELECT * FROM books WHERE id = :id;
46+
`).queries[0];
47+
48+
const labels = getParameterLabels(queryASTToIR(query, null), { id: 1 });
49+
50+
expect(labels.get(1)).toBe('id');
51+
});
52+
53+
test('keeps spread-pick labels when params are supplied', () => {
54+
const query = parseSQLFile(`
55+
/*
56+
@name InsertBooks
57+
@param books -> ((rank!, name!)...)
58+
*/
59+
INSERT INTO books (rank, name)
60+
VALUES :books;
61+
`).queries[0];
62+
63+
const labels = getParameterLabels(queryASTToIR(query, null), {
64+
books: [
65+
{ rank: 1, name: 'one' },
66+
{ rank: 2, name: 'two' },
67+
],
68+
});
69+
70+
expect([...labels.values()]).toEqual([
71+
'books.rank',
72+
'books.name',
73+
'books.rank',
74+
'books.name',
75+
]);
76+
});
77+
});

0 commit comments

Comments
 (0)