Skip to content

Commit 89fc28b

Browse files
committed
Extract behavesLikePostgresqlFormatter()
1 parent 595b3df commit 89fc28b

File tree

3 files changed

+144
-266
lines changed

3 files changed

+144
-266
lines changed
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
import dedent from 'dedent-js';
2+
import { FormatFn } from '../src/sqlFormatter.js';
3+
4+
/**
5+
* Shared tests for PostgreSQL and DuckDB
6+
*/
7+
export default function behavesLikePostgresqlFormatter(format: FormatFn) {
8+
it('allows $ character as part of identifiers', () => {
9+
expect(format('SELECT foo$, some$$ident')).toBe(dedent`
10+
SELECT
11+
foo$,
12+
some$$ident
13+
`);
14+
});
15+
16+
it('formats type-cast operator without spaces', () => {
17+
expect(format('SELECT 2 :: numeric AS foo;')).toBe(dedent`
18+
SELECT
19+
2::numeric AS foo;
20+
`);
21+
});
22+
23+
// issue #144 (unsolved)
24+
// This is currently far from ideal.
25+
it('formats SELECT DISTINCT ON () syntax', () => {
26+
expect(format('SELECT DISTINCT ON (c1, c2) c1, c2 FROM tbl;')).toBe(dedent`
27+
SELECT DISTINCT
28+
ON (c1, c2) c1,
29+
c2
30+
FROM
31+
tbl;
32+
`);
33+
});
34+
35+
// Regression test for issue #624
36+
it('supports array slice operator', () => {
37+
expect(format('SELECT foo[:5], bar[1:], baz[1:5], zap[:];')).toBe(dedent`
38+
SELECT
39+
foo[:5],
40+
bar[1:],
41+
baz[1:5],
42+
zap[:];
43+
`);
44+
});
45+
46+
it('formats ALTER TABLE ... ALTER COLUMN', () => {
47+
expect(
48+
format(
49+
`ALTER TABLE t ALTER COLUMN foo SET DATA TYPE VARCHAR;
50+
ALTER TABLE t ALTER COLUMN foo SET DEFAULT 5;
51+
ALTER TABLE t ALTER COLUMN foo DROP DEFAULT;
52+
ALTER TABLE t ALTER COLUMN foo SET NOT NULL;
53+
ALTER TABLE t ALTER COLUMN foo DROP NOT NULL;`
54+
)
55+
).toBe(dedent`
56+
ALTER TABLE t
57+
ALTER COLUMN foo
58+
SET DATA TYPE VARCHAR;
59+
60+
ALTER TABLE t
61+
ALTER COLUMN foo
62+
SET DEFAULT 5;
63+
64+
ALTER TABLE t
65+
ALTER COLUMN foo
66+
DROP DEFAULT;
67+
68+
ALTER TABLE t
69+
ALTER COLUMN foo
70+
SET NOT NULL;
71+
72+
ALTER TABLE t
73+
ALTER COLUMN foo
74+
DROP NOT NULL;
75+
`);
76+
});
77+
78+
// Issue #685
79+
it('allows TYPE to be used as an identifier', () => {
80+
expect(format(`SELECT type, modified_at FROM items;`)).toBe(dedent`
81+
SELECT
82+
type,
83+
modified_at
84+
FROM
85+
items;
86+
`);
87+
});
88+
89+
// Issue #156, #709
90+
it('does not recognize common fields names as keywords', () => {
91+
expect(
92+
format(`SELECT id, type, name, location, label, password FROM release;`, {
93+
keywordCase: 'upper',
94+
})
95+
).toBe(dedent`
96+
SELECT
97+
id,
98+
type,
99+
name,
100+
location,
101+
label,
102+
password
103+
FROM
104+
release;
105+
`);
106+
});
107+
108+
it('formats DEFAULT VALUES clause', () => {
109+
expect(
110+
format(`INSERT INTO items default values RETURNING id;`, {
111+
keywordCase: 'upper',
112+
})
113+
).toBe(dedent`
114+
INSERT INTO
115+
items
116+
DEFAULT VALUES
117+
RETURNING
118+
id;
119+
`);
120+
});
121+
122+
// Issue #726
123+
it('treats TEXT as data-type (not as plain keyword)', () => {
124+
expect(
125+
format(`CREATE TABLE foo (items text);`, {
126+
dataTypeCase: 'upper',
127+
})
128+
).toBe(dedent`
129+
CREATE TABLE foo (items TEXT);
130+
`);
131+
132+
expect(
133+
format(`CREATE TABLE foo (text VARCHAR(100));`, {
134+
keywordCase: 'upper',
135+
})
136+
).toBe(dedent`
137+
CREATE TABLE foo (text VARCHAR(100));
138+
`);
139+
});
140+
}

test/duckdb.test.ts

Lines changed: 2 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import dedent from 'dedent-js';
33
import { format as originalFormat, FormatFn } from '../src/sqlFormatter.js';
44

55
import behavesLikeSqlFormatter from './behavesLikeSqlFormatter.js';
6+
import behavesLikePostgresqlFormatter from './behavesLikePostgresqlFormatter.js';
67
import supportsAlterTable from './features/alterTable.js';
78
import supportsBetween from './features/between.js';
89
import supportsCreateTable from './features/createTable.js';
@@ -34,6 +35,7 @@ describe('DuckDBFormatter', () => {
3435
const format: FormatFn = (query, cfg = {}) => originalFormat(query, { ...cfg, language });
3536

3637
behavesLikeSqlFormatter(format);
38+
behavesLikePostgresqlFormatter(format);
3739
supportsComments(format, { nestedBlockComments: true });
3840
supportsCommentOn(format);
3941
supportsCreateView(format, { orReplace: true, ifNotExists: true });
@@ -130,33 +132,6 @@ describe('DuckDBFormatter', () => {
130132
supportsLimiting(format, { limit: true, offset: true });
131133
supportsDataTypeCase(format);
132134

133-
it('allows $ character as part of identifiers', () => {
134-
expect(format('SELECT foo$, some$$ident')).toBe(dedent`
135-
SELECT
136-
foo$,
137-
some$$ident
138-
`);
139-
});
140-
141-
it('formats type-cast operator without spaces', () => {
142-
expect(format('SELECT 2 :: numeric AS foo;')).toBe(dedent`
143-
SELECT
144-
2::numeric AS foo;
145-
`);
146-
});
147-
148-
// issue #144 (unsolved)
149-
// This is currently far from ideal.
150-
it('formats SELECT DISTINCT ON () syntax', () => {
151-
expect(format('SELECT DISTINCT ON (c1, c2) c1, c2 FROM tbl;')).toBe(dedent`
152-
SELECT DISTINCT
153-
ON (c1, c2) c1,
154-
c2
155-
FROM
156-
tbl;
157-
`);
158-
});
159-
160135
it('formats TIMESTAMP WITH TIME ZONE syntax', () => {
161136
expect(
162137
format(`
@@ -170,112 +145,6 @@ describe('DuckDBFormatter', () => {
170145
`);
171146
});
172147

173-
// Regression test for issue #624
174-
it('supports array slice operator', () => {
175-
expect(format('SELECT foo[:5], bar[1:], baz[1:5], zap[:];')).toBe(dedent`
176-
SELECT
177-
foo[:5],
178-
bar[1:],
179-
baz[1:5],
180-
zap[:];
181-
`);
182-
});
183-
184-
it('formats ALTER TABLE ... ALTER COLUMN', () => {
185-
expect(
186-
format(
187-
`ALTER TABLE t ALTER COLUMN foo SET DATA TYPE VARCHAR;
188-
ALTER TABLE t ALTER COLUMN foo SET DEFAULT 5;
189-
ALTER TABLE t ALTER COLUMN foo DROP DEFAULT;
190-
ALTER TABLE t ALTER COLUMN foo SET NOT NULL;
191-
ALTER TABLE t ALTER COLUMN foo DROP NOT NULL;`
192-
)
193-
).toBe(dedent`
194-
ALTER TABLE t
195-
ALTER COLUMN foo
196-
SET DATA TYPE VARCHAR;
197-
198-
ALTER TABLE t
199-
ALTER COLUMN foo
200-
SET DEFAULT 5;
201-
202-
ALTER TABLE t
203-
ALTER COLUMN foo
204-
DROP DEFAULT;
205-
206-
ALTER TABLE t
207-
ALTER COLUMN foo
208-
SET NOT NULL;
209-
210-
ALTER TABLE t
211-
ALTER COLUMN foo
212-
DROP NOT NULL;
213-
`);
214-
});
215-
216-
// Issue #685
217-
it('allows TYPE to be used as an identifier', () => {
218-
expect(format(`SELECT type, modified_at FROM items;`)).toBe(dedent`
219-
SELECT
220-
type,
221-
modified_at
222-
FROM
223-
items;
224-
`);
225-
});
226-
227-
// Issue #156, #709
228-
it('does not recognize common fields names as keywords', () => {
229-
expect(
230-
format(`SELECT id, type, name, location, label, password FROM release;`, {
231-
keywordCase: 'upper',
232-
})
233-
).toBe(dedent`
234-
SELECT
235-
id,
236-
type,
237-
name,
238-
location,
239-
label,
240-
password
241-
FROM
242-
release;
243-
`);
244-
});
245-
246-
it('formats DEFAULT VALUES clause', () => {
247-
expect(
248-
format(`INSERT INTO items default values RETURNING id;`, {
249-
keywordCase: 'upper',
250-
})
251-
).toBe(dedent`
252-
INSERT INTO
253-
items
254-
DEFAULT VALUES
255-
RETURNING
256-
id;
257-
`);
258-
});
259-
260-
// Issue #726
261-
it('treats TEXT as data-type (not as plain keyword)', () => {
262-
expect(
263-
format(`CREATE TABLE foo (items text);`, {
264-
dataTypeCase: 'upper',
265-
})
266-
).toBe(dedent`
267-
CREATE TABLE foo (items TEXT);
268-
`);
269-
270-
expect(
271-
format(`CREATE TABLE foo (text VARCHAR(100));`, {
272-
keywordCase: 'upper',
273-
})
274-
).toBe(dedent`
275-
CREATE TABLE foo (text VARCHAR(100));
276-
`);
277-
});
278-
279148
it('formats JSON data type', () => {
280149
expect(
281150
format(`CREATE TABLE foo (bar json, baz json);`, {

0 commit comments

Comments
 (0)