Skip to content

Commit aded067

Browse files
committed
Merge branch 'sqlLiteralCase-option'
Refs #13
2 parents b6d7eb6 + b1816eb commit aded067

File tree

4 files changed

+83
-3
lines changed

4 files changed

+83
-3
lines changed

README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,8 @@ There are also some SQL-specific options:
121121

122122
| API Option | Default | Description |
123123
| ----------------------------- | :-----: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
124-
| `sqlKeywordCase` | `upper` | Converts SQL keywords to `upper` or `lower` case, or `preserve` existing. Note that for now `preserve` is somewhat incompatible with `sqlCanonicalSyntax: true` (e.g. the added `AS` keywords will always be in uppercase). |
124+
| `sqlKeywordCase` | `upper` | Convert SQL keywords to `upper` or `lower` case, or `preserve` existing. Note that for now `preserve` is somewhat incompatible with `sqlCanonicalSyntax: true` (e.g. the added `AS` keywords will always be in uppercase). |
125+
| `sqlLiteralCase` | `upper` | Convert SQL literals TRUE, FALSE and NULL to `upper` or `lower` case, or `preserve` existing. |
125126
| `sqlParamTypes` | `[]` | Array of bound parameter types: `?`, `?nr`, `$nr`, `:name`, `@name`, `$name`. |
126127
| `sqlCanonicalSyntax` | `true` | When enabled, performs some opinionated changes of keywords and operators, like enforcing the use of `AS` in aliases and replacing `<>` comparisons with `!=`. See [STYLE_GUIDE][] for more details. (Since 0.11.0) |
127128
| `sqlFinalSemicolon` | `true` | When enabled, enforces a semicolon at the end of last statement. When disabled leaves it up to the author whether to add a final semicolon or not. (Since 0.13.0) |

src/options.ts

+25
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Node, ParserOptions as CstParserOptions } from "sql-parser-cst";
33

44
export interface SqlPluginOptions {
55
sqlKeywordCase: "preserve" | "upper" | "lower";
6+
sqlLiteralCase: "preserve" | "upper" | "lower";
67
sqlParamTypes: NonNullable<CstParserOptions["paramTypes"]>;
78
sqlCanonicalSyntax: boolean;
89
sqlFinalSemicolon: boolean;
@@ -36,6 +37,30 @@ export const options: SupportOptions = {
3637
},
3738
],
3839
},
40+
sqlLiteralCase: {
41+
type: "choice",
42+
category: "SQL",
43+
default: "upper",
44+
description:
45+
"Enforces upper/lower case for SQL literals (TRUE, FALSE, NULL)",
46+
choices: [
47+
{
48+
value: "preserve",
49+
description: "preserves the existing case",
50+
since: "0.14.0",
51+
},
52+
{
53+
value: "upper",
54+
description: "forces all keywords to uppercase",
55+
since: "0.14.0",
56+
},
57+
{
58+
value: "lower",
59+
description: "forces all keywords to lowercase",
60+
since: "0.14.0",
61+
},
62+
],
63+
},
3964
sqlParamTypes: {
4065
type: "string",
4166
array: true,

src/syntax/expr.ts

+16-2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
isCompoundSelectStmt,
2424
} from "../node_utils";
2525
import { isString, last } from "../utils";
26+
import { AllPrettierOptions } from "src/options";
2627

2728
export const exprMap: CstToDocMap<AllExprNodes> = {
2829
list_expr: (print, node, path) => {
@@ -169,13 +170,15 @@ export const exprMap: CstToDocMap<AllExprNodes> = {
169170
/** cst-ignore: value */
170171
number_literal: (print) => print("text"),
171172
/** cst-ignore: value */
172-
boolean_literal: (print) => print("valueKw"),
173+
boolean_literal: (print, node, path, options) =>
174+
printLiteral(node.valueKw, options),
173175
/** cst-ignore: value */
174176
string_literal: (print) => print("text"),
175177
/** cst-ignore: value */
176178
blob_literal: (print) => print("text"),
177179
/** cst-ignore: value */
178-
null_literal: (print) => print("nullKw"),
180+
null_literal: (print, node, path, options) =>
181+
printLiteral(node.nullKw, options),
179182
numeric_literal: (print) => print.spaced(["numericKw", "string"]),
180183
bignumeric_literal: (print) => print.spaced(["bignumericKw", "string"]),
181184
date_literal: (print) => print.spaced(["dateKw", "string"]),
@@ -191,4 +194,15 @@ export const exprMap: CstToDocMap<AllExprNodes> = {
191194
parameter: (print) => print("text"),
192195
};
193196

197+
const printLiteral = <T>(node: Keyword, options: AllPrettierOptions<T>) => {
198+
switch (options.sqlLiteralCase) {
199+
case "preserve":
200+
return node.text;
201+
case "upper":
202+
return node.text.toUpperCase();
203+
case "lower":
204+
return node.text.toLowerCase();
205+
}
206+
};
207+
194208
const isBooleanOp = ({ name }: Keyword) => name === "AND" || name === "OR";

test/options/literalCase.test.ts

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import dedent from "dedent-js";
2+
import { pretty } from "../test_utils";
3+
4+
describe("sqlLiteralCase option", () => {
5+
it(`defaults to uppercasing of all literals`, async () => {
6+
expect(await pretty(`SELECT true, false, null`)).toBe(dedent`
7+
SELECT TRUE, FALSE, NULL
8+
`);
9+
});
10+
11+
it(`sqlKeywordCase: "preserve" keeps keywords case as-is`, async () => {
12+
expect(
13+
await pretty(`SELECT true, False, NULL`, {
14+
sqlLiteralCase: "preserve",
15+
}),
16+
).toBe(dedent`
17+
SELECT true, False, NULL
18+
`);
19+
});
20+
21+
it(`sqlLiteralCase: "upper" converts keywords to uppercase`, async () => {
22+
expect(
23+
await pretty(`SELECT true, False, NULL`, {
24+
sqlLiteralCase: "upper",
25+
}),
26+
).toBe(dedent`
27+
SELECT TRUE, FALSE, NULL
28+
`);
29+
});
30+
31+
it(`sqlLiteralCase: "lower" converts keywords to lowercase`, async () => {
32+
expect(
33+
await pretty(`SELECT true, False, NULL`, {
34+
sqlLiteralCase: "lower",
35+
}),
36+
).toBe(dedent`
37+
SELECT true, false, null
38+
`);
39+
});
40+
});

0 commit comments

Comments
 (0)