Skip to content

Commit 8d81244

Browse files
committed
Add tests for dataTypeCase and functionCase
1 parent 66d596e commit 8d81244

26 files changed

+218
-11
lines changed

src/languages/db2/db2.keywords.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,12 +404,16 @@ export const keywords: string[] = [
404404
export const dataTypes: string[] = [
405405
// https://www.ibm.com/docs/en/db2-for-zos/12?topic=columns-data-types
406406
'ARRAY',
407+
'BIGINT',
407408
'CCSID',
408409
'CHAR',
409410
'CHARACTER',
410411
'DATE',
411412
'DOUBLE',
413+
'INT',
414+
'INTEGER',
412415
'LONG',
416+
'SMALLINT',
413417
'TIME',
414418
'TIMESTAMP',
415419
];

src/languages/db2i/db2i.keywords.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,7 @@ export const dataTypes: string[] = [
517517
'DOUBLE',
518518
'FLOAT',
519519
'GRAPHIC',
520+
'INT',
520521
'INTEGER',
521522
'LONG',
522523
'NUMERIC',

src/languages/mysql/mysql.keywords.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,12 @@ export const dataTypes: string[] = [
235235
'BIGINT', // (R)
236236
'BINARY', // (R)
237237
'BLOB', // (R)
238+
'BOOL', // (R)
239+
'BOOLEAN', // (R)
238240
'CHAR', // (R)
239241
'CHARACTER', // (R)
242+
'DATE', // (R)
243+
'DATETIME', // (R)
240244
'DEC', // (R)
241245
'DECIMAL', // (R)
242246
'DOUBLE', // (R)
@@ -260,6 +264,7 @@ export const dataTypes: string[] = [
260264
'PRECISION', // (R)
261265
'REAL', // (R)
262266
'SMALLINT', // (R)
267+
'TIMESTAMP', // (R)
263268
'TINYBLOB', // (R)
264269
'TINYINT', // (R)
265270
'TINYTEXT', // (R)

src/languages/redshift/redshift.keywords.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,13 @@ export const keywords: string[] = [
201201
export const dataTypes: string[] = [
202202
// https://docs.aws.amazon.com/redshift/latest/dg/r_Character_types.html#r_Character_types-text-and-bpchar-types
203203
'ARRAY',
204+
'BIGINT',
204205
'BPCHAR',
206+
'INT',
207+
'INT2',
208+
'INT4',
209+
'INT8',
210+
'INTEGER',
211+
'SMALLINT',
205212
'TEXT',
206213
];

src/lexer/disambiguateTokens.ts

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,39 @@ const funcNameToKeyword = (token: Token, i: number, tokens: Token[]): Token => {
3535
if (token.type === TokenType.RESERVED_FUNCTION_NAME) {
3636
const nextToken = nextNonCommentToken(tokens, i);
3737
if (!nextToken || !isOpenParen(nextToken)) {
38-
return { ...token, type: TokenType.RESERVED_KEYWORD };
38+
return {
39+
...token,
40+
type:
41+
// Function names which are also data types
42+
[
43+
'BIGINT',
44+
'BINARY',
45+
'BIT',
46+
'BLOB',
47+
'BOOLEAN',
48+
'CHAR',
49+
'DATE',
50+
'DECIMAL',
51+
'DOUBLE',
52+
'FLOAT',
53+
'INT',
54+
'INTEGER',
55+
'JSON',
56+
'NCHAR',
57+
'NUMBER',
58+
'NVARCHAR',
59+
'REAL',
60+
'SMALLINT',
61+
'TEXT',
62+
'TIME',
63+
'TIMESTAMP',
64+
'TINYINT',
65+
'VARCHAR',
66+
'XML',
67+
].includes(token.text)
68+
? TokenType.RESERVED_DATA_TYPE
69+
: TokenType.RESERVED_KEYWORD,
70+
};
3971
}
4072
}
4173
return token;

test/behavesLikeMariaDbFormatter.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,10 @@ export default function behavesLikeMariaDbFormatter(format: FormatFn) {
163163
`create table account (id int comment 'the most important column');
164164
select * from mysql.user;
165165
insert into user (id, name) values (1, 'Blah');`,
166-
{ keywordCase: 'upper' }
166+
{
167+
keywordCase: 'upper',
168+
dataTypeCase: 'upper',
169+
}
167170
)
168171
).toBe(dedent`
169172
CREATE TABLE

test/behavesLikeSqlFormatter.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import supportsNewlineBeforeSemicolon from './options/newlineBeforeSemicolon.js'
1616
import supportsLogicalOperatorNewline from './options/logicalOperatorNewline.js';
1717
import supportsParamTypes from './options/paramTypes.js';
1818
import supportsWindowFunctions from './features/windowFunctions.js';
19+
import supportsFunctionCase from './options/functionCase.js';
1920

2021
/**
2122
* Core tests for all SQL formatters
@@ -29,6 +30,7 @@ export default function behavesLikeSqlFormatter(format: FormatFn) {
2930
supportsUseTabs(format);
3031
supportsKeywordCase(format);
3132
supportsIdentifierCase(format);
33+
supportsFunctionCase(format);
3234
supportsIndentStyle(format);
3335
supportsLinesBetweenQueries(format);
3436
supportsExpressionWidth(format);

test/bigquery.test.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import supportsMergeInto from './features/mergeInto.js';
2424
import supportsCreateView from './features/createView.js';
2525
import supportsAlterTable from './features/alterTable.js';
2626
import supportsIsDistinctFrom from './features/isDistinctFrom.js';
27+
import supportsDataTypeCase from './options/dataTypeCase.js';
2728

2829
describe('BigQueryFormatter', () => {
2930
const language = 'bigquery';
@@ -32,7 +33,11 @@ describe('BigQueryFormatter', () => {
3233
behavesLikeSqlFormatter(format);
3334
supportsComments(format, { hashComments: true });
3435
supportsCreateView(format, { orReplace: true, materialized: true, ifNotExists: true });
35-
supportsCreateTable(format, { orReplace: true, ifNotExists: true });
36+
supportsCreateTable(format, {
37+
orReplace: true,
38+
ifNotExists: true,
39+
dialectDoesntHaveVarchar: true,
40+
});
3641
supportsDropTable(format, { ifExists: true });
3742
supportsAlterTable(format, {
3843
addColumn: true,
@@ -60,6 +65,7 @@ describe('BigQueryFormatter', () => {
6065
supportsParams(format, { positional: true, named: ['@'], quoted: ['@``'] });
6166
supportsWindow(format);
6267
supportsLimiting(format, { limit: true, offset: true });
68+
supportsDataTypeCase(format);
6369

6470
// Note: BigQuery supports single dashes inside identifiers, so my-ident would be
6571
// detected as identifier, while other SQL dialects would detect it as

test/db2.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import supportsStrings from './features/strings.js';
1111
import supportsComments from './features/comments.js';
1212
import supportsOperators from './features/operators.js';
1313
import supportsLimiting from './features/limiting.js';
14+
import supportsDataTypeCase from './options/dataTypeCase.js';
1415

1516
describe('Db2Formatter', () => {
1617
const language = 'db2';
@@ -49,6 +50,7 @@ describe('Db2Formatter', () => {
4950
]);
5051
// Additional U& string type in addition to others shared by all DB2 implementations
5152
supportsStrings(format, ["U&''"]);
53+
supportsDataTypeCase(format);
5254

5355
it('supports non-standard FOR clause', () => {
5456
expect(format('SELECT * FROM tbl FOR UPDATE OF other_tbl FOR RS USE AND KEEP EXCLUSIVE LOCKS'))

test/db2i.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import supportsDropTable from './features/dropTable.js';
88
import supportsJoin from './features/join.js';
99
import supportsOperators from './features/operators.js';
1010
import supportsLimiting from './features/limiting.js';
11+
import supportsDataTypeCase from './options/dataTypeCase.js';
1112

1213
describe('Db2iFormatter', () => {
1314
const language = 'db2i';
@@ -28,4 +29,5 @@ describe('Db2iFormatter', () => {
2829
additionally: ['EXCEPTION JOIN', 'LEFT EXCEPTION JOIN', 'RIGHT EXCEPTION JOIN'],
2930
});
3031
supportsOperators(format, ['**', '¬=', '¬>', '¬<', '!>', '!<', '||', '=>']);
32+
supportsDataTypeCase(format);
3133
});

test/features/createTable.ts

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,30 @@ interface CreateTableConfig {
77
ifNotExists?: boolean;
88
columnComment?: boolean;
99
tableComment?: boolean;
10+
dialectDoesntHaveVarchar?: boolean;
1011
}
1112

12-
export default function supportsCreateTable(
13-
format: FormatFn,
14-
{ orReplace, ifNotExists, columnComment, tableComment }: CreateTableConfig = {}
15-
) {
13+
export default function supportsCreateTable(format: FormatFn, cfg: CreateTableConfig = {}) {
1614
it('formats short CREATE TABLE', () => {
1715
expect(format('CREATE TABLE tbl (a INT PRIMARY KEY, b TEXT);')).toBe(dedent`
1816
CREATE TABLE
1917
tbl (a INT PRIMARY KEY, b TEXT);
2018
`);
2119
});
2220

21+
if (!cfg.dialectDoesntHaveVarchar) {
22+
it('formats short CREATE TABLE with lowercase data types', () => {
23+
expect(
24+
format('CREATE TABLE tbl (a INT PRIMARY KEY, b VARCHAR);', {
25+
dataTypeCase: 'lower',
26+
})
27+
).toBe(dedent`
28+
CREATE TABLE
29+
tbl (a int PRIMARY KEY, b varchar);
30+
`);
31+
});
32+
}
33+
2334
// The decision to place it to multiple lines is made based on the length of text inside braces
2435
// ignoring the whitespace. (Which is not quite right :P)
2536
it('formats long CREATE TABLE', () => {
@@ -36,7 +47,7 @@ export default function supportsCreateTable(
3647
`);
3748
});
3849

39-
if (orReplace) {
50+
if (cfg.orReplace) {
4051
it('formats short CREATE OR REPLACE TABLE', () => {
4152
expect(format('CREATE OR REPLACE TABLE tbl (a INT PRIMARY KEY, b TEXT);')).toBe(dedent`
4253
CREATE OR REPLACE TABLE
@@ -45,7 +56,7 @@ export default function supportsCreateTable(
4556
});
4657
}
4758

48-
if (ifNotExists) {
59+
if (cfg.ifNotExists) {
4960
it('formats short CREATE TABLE IF NOT EXISTS', () => {
5061
expect(format('CREATE TABLE IF NOT EXISTS tbl (a INT PRIMARY KEY, b TEXT);')).toBe(dedent`
5162
CREATE TABLE IF NOT EXISTS
@@ -54,7 +65,7 @@ export default function supportsCreateTable(
5465
});
5566
}
5667

57-
if (columnComment) {
68+
if (cfg.columnComment) {
5869
it('formats short CREATE TABLE with column comments', () => {
5970
expect(
6071
format(`CREATE TABLE tbl (a INT COMMENT 'Hello world!', b TEXT COMMENT 'Here we are!');`)
@@ -68,7 +79,7 @@ export default function supportsCreateTable(
6879
});
6980
}
7081

71-
if (tableComment) {
82+
if (cfg.tableComment) {
7283
it('formats short CREATE TABLE with comment', () => {
7384
expect(format(`CREATE TABLE tbl (a INT, b TEXT) COMMENT = 'Hello, world!';`)).toBe(dedent`
7485
CREATE TABLE

test/hive.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import supportsDeleteFrom from './features/deleteFrom.js';
2222
import supportsTruncateTable from './features/truncateTable.js';
2323
import supportsMergeInto from './features/mergeInto.js';
2424
import supportsCreateView from './features/createView.js';
25+
import supportsDataTypeCase from './options/dataTypeCase.js';
2526

2627
describe('HiveFormatter', () => {
2728
const language = 'hive';
@@ -50,6 +51,7 @@ describe('HiveFormatter', () => {
5051
supportsArrayAndMapAccessors(format);
5152
supportsWindow(format);
5253
supportsLimiting(format, { limit: true });
54+
supportsDataTypeCase(format);
5355

5456
// eslint-disable-next-line no-template-curly-in-string
5557
it('recognizes ${hivevar:name} substitution variables', () => {

test/mariadb.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import supportsCreateView from './features/createView.js';
1414
import supportsAlterTable from './features/alterTable.js';
1515
import supportsStrings from './features/strings.js';
1616
import supportsConstraints from './features/constraints.js';
17+
import supportsDataTypeCase from './options/dataTypeCase.js';
1718

1819
describe('MariaDbFormatter', () => {
1920
const language = 'mariadb';
@@ -52,6 +53,7 @@ describe('MariaDbFormatter', () => {
5253
renameTo: true,
5354
renameColumn: true,
5455
});
56+
supportsDataTypeCase(format);
5557

5658
it(`supports @"name" variables`, () => {
5759
expect(format(`SELECT @"foo fo", @"foo\\"x", @"foo""y" FROM tbl;`)).toBe(dedent`

test/mysql.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import supportsCreateView from './features/createView.js';
1414
import supportsAlterTable from './features/alterTable.js';
1515
import supportsStrings from './features/strings.js';
1616
import supportsConstraints from './features/constraints.js';
17+
import supportsDataTypeCase from './options/dataTypeCase.js';
1718

1819
describe('MySqlFormatter', () => {
1920
const language = 'mysql';
@@ -54,6 +55,7 @@ describe('MySqlFormatter', () => {
5455
renameTo: true,
5556
renameColumn: true,
5657
});
58+
supportsDataTypeCase(format);
5759

5860
it(`supports @"name" variables`, () => {
5961
expect(format(`SELECT @"foo fo", @"foo\\"x", @"foo""y" FROM tbl;`)).toBe(dedent`

test/options/dataTypeCase.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import dedent from 'dedent-js';
2+
3+
import { FormatFn } from '../../src/sqlFormatter.js';
4+
5+
export default function supportsDataTypeCase(format: FormatFn) {
6+
it('preserves data type keyword case by default', () => {
7+
const result = format('CREATE TABLE users ( id iNt PRIMARY KEY )');
8+
expect(result).toBe(dedent`
9+
CREATE TABLE
10+
users (id iNt PRIMARY KEY)
11+
`);
12+
});
13+
14+
it('converts data type keyword case to uppercase', () => {
15+
const result = format('CREATE TABLE users ( id iNt PRIMARY KEY )', {
16+
dataTypeCase: 'upper',
17+
});
18+
expect(result).toBe(dedent`
19+
CREATE TABLE
20+
users (id INT PRIMARY KEY)
21+
`);
22+
});
23+
24+
it('converts data type keyword case to lowercase', () => {
25+
const result = format('CREATE TABLE users ( id iNt PRIMARY KEY )', {
26+
dataTypeCase: 'lower',
27+
});
28+
expect(result).toBe(dedent`
29+
CREATE TABLE
30+
users (id int PRIMARY KEY)
31+
`);
32+
});
33+
34+
it('preserves data type keyword case in cast by default', () => {
35+
const result = format('SELECT CAST(quantity AS InT) FROM orders');
36+
expect(result).toBe(dedent`
37+
SELECT
38+
CAST(quantity AS InT)
39+
FROM
40+
orders
41+
`);
42+
});
43+
44+
it('converts data type keyword case in cast to uppercase', () => {
45+
const result = format('SELECT CAST(quantity AS InT) FROM orders', {
46+
dataTypeCase: 'upper',
47+
});
48+
expect(result).toBe(dedent`
49+
SELECT
50+
CAST(quantity AS INT)
51+
FROM
52+
orders
53+
`);
54+
});
55+
56+
it('converts data type keyword case in cast to lowercase', () => {
57+
const result = format('SELECT CAST(quantity AS InT) FROM orders', {
58+
dataTypeCase: 'lower',
59+
});
60+
expect(result).toBe(dedent`
61+
SELECT
62+
CAST(quantity AS int)
63+
FROM
64+
orders
65+
`);
66+
});
67+
}

0 commit comments

Comments
 (0)