Skip to content

Commit

Permalink
Add dataTypeCase & functionCase (#689)
Browse files Browse the repository at this point in the history
  • Loading branch information
nene committed Dec 7, 2023
2 parents 59fe667 + d0a7406 commit 7e3db7f
Show file tree
Hide file tree
Showing 83 changed files with 804 additions and 583 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ All fields are optional and all fields that are not specified will be filled wit
- [**`useTabs`**](docs/useTabs.md) to use tabs for indentation.
- [**`keywordCase`**](docs/keywordCase.md) uppercases or lowercases keywords.
- [**`identifierCase`**](docs/identifierCase.md) uppercases or lowercases identifiers. (**experimental!**)
- [**`dataTypeCase`**](docs/dataTypeCase.md) uppercases or lowercases data types. (**experimental!**)
- [**`functionCase`**](docs/functionCase.md) uppercases or lowercases function names. (**experimental!**)
- [**`indentStyle`**](docs/indentStyle.md) defines overall indentation style.
- [**`logicalOperatorNewline`**](docs/logicalOperatorNewline.md) newline before or after boolean operator (AND, OR, XOR).
- [**`expressionWidth`**](docs/expressionWidth.md) maximum number of characters in parenthesized expressions to be kept on single line.
Expand Down
45 changes: 45 additions & 0 deletions docs/dataTypeCase.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# dataTypeCase (experimental)

Converts data types to upper- or lowercase.

## Options

- `"preserve"` (default) preserves the original case.
- `"upper"` converts to uppercase.
- `"lower"` converts to lowercase.

### preserve

```sql
CREATE TABLE user (
id InTeGeR PRIMARY KEY,
first_name VarChaR(30) NOT NULL,
bio teXT,
is_email_verified BooL,
created_timestamp timestamP
);
```

### upper

```sql
CREATE TABLE user (
id INTEGER PRIMARY KEY,
first_name VARCHAR(30) NOT NULL,
bio TEXT,
is_email_verified BOOL,
created_timestamp TIMESTAMP
);
```

### lower

```sql
CREATE TABLE user (
id integer PRIMARY KEY,
first_name varchar(30) NOT NULL,
bio text,
is_email_verified bool,
created_timestamp timestamp
);
```
48 changes: 48 additions & 0 deletions docs/functionCase.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# functionCase (experimental)

Converts function names to upper- or lowercase.

## Options

- `"preserve"` (default) preserves the original case.
- `"upper"` converts to uppercase.
- `"lower"` converts to lowercase.

### preserve

```sql
SELECT
Concat(Trim(first_name), ' ', Trim(last_name)) AS name,
Max(salary) AS max_pay,
Cast(ssid AS INT)
FROM
employee
WHERE
expires_at > Now()
```

### upper

```sql
SELECT
CONCAT(TRIM(first_name), ' ', TRIM(last_name)) AS name,
MAX(salary) AS max_pay,
CAST(ssid AS INT)
FROM
employee
WHERE
expires_at > NOW()
```

### lower

```sql
SELECT
concat(trim(first_name), ' ', trim(last_name)) AS name,
max(salary) AS max_pay,
cast(ssid AS INT)
FROM
employee
WHERE
expires_at > now()
```
10 changes: 6 additions & 4 deletions docs/identifierCase.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ This option doesn't yet support all types of identifiers:

- prefixed variables like `@my_var` are not converted.
- parameter placeholders like `:param` are not converted.
- function names like `count(*)` are not converted (this are currently governed by `keywordCase` option instead.)

## Options

Expand All @@ -26,7 +25,8 @@ from
where
Column6
and Column7
group by Column4
group by
Column4
```

### upper
Expand All @@ -41,7 +41,8 @@ from
where
COLUMN6
and COLUMN7
group by COLUMN4
group by
COLUMN4
```

### lower
Expand All @@ -56,5 +57,6 @@ from
where
column6
and column7
group by column4
group by
column4
```
6 changes: 6 additions & 0 deletions src/FormatOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,19 @@ export type KeywordCase = 'preserve' | 'upper' | 'lower';

export type IdentifierCase = 'preserve' | 'upper' | 'lower';

export type DataTypeCase = 'preserve' | 'upper' | 'lower';

export type FunctionCase = 'preserve' | 'upper' | 'lower';

export type LogicalOperatorNewline = 'before' | 'after';

export interface FormatOptions {
tabWidth: number;
useTabs: boolean;
keywordCase: KeywordCase;
identifierCase: IdentifierCase;
dataTypeCase: DataTypeCase;
functionCase: FunctionCase;
indentStyle: IndentStyle;
logicalOperatorNewline: LogicalOperatorNewline;
expressionWidth: number;
Expand Down
71 changes: 65 additions & 6 deletions src/formatter/ExpressionFormatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import {
CaseExpressionNode,
CaseWhenNode,
CaseElseNode,
DataTypeNode,
ParameterizedDataTypeNode,
} from '../parser/ast.js';

import Layout, { WS } from './Layout.js';
Expand Down Expand Up @@ -94,6 +96,8 @@ export default class ExpressionFormatter {
switch (node.type) {
case NodeType.function_call:
return this.formatFunctionCall(node);
case NodeType.parameterized_data_type:
return this.formatParameterizedDataType(node);
case NodeType.array_subscript:
return this.formatArraySubscript(node);
case NodeType.property_access:
Expand Down Expand Up @@ -130,26 +134,46 @@ export default class ExpressionFormatter {
return this.formatLineComment(node);
case NodeType.block_comment:
return this.formatBlockComment(node);
case NodeType.data_type:
return this.formatDataType(node);
case NodeType.keyword:
return this.formatKeywordNode(node);
}
}

private formatFunctionCall(node: FunctionCallNode) {
this.withComments(node.nameKw, () => {
this.layout.add(this.showKw(node.nameKw));
this.layout.add(this.showFunctionKw(node.nameKw));
});
this.formatNode(node.parenthesis);
}

private formatParameterizedDataType(node: ParameterizedDataTypeNode) {
this.withComments(node.dataType, () => {
this.layout.add(this.showDataType(node.dataType));
});
this.formatNode(node.parenthesis);
}

private formatArraySubscript(node: ArraySubscriptNode) {
let formattedArray: string;

switch (node.array.type) {
case NodeType.data_type:
formattedArray = this.showDataType(node.array);
break;
case NodeType.keyword:
formattedArray = this.showKw(node.array);
break;
default:
formattedArray = this.showIdentifier(node.array);
break;
}

this.withComments(node.array, () => {
this.layout.add(
node.array.type === NodeType.keyword
? this.showKw(node.array)
: this.showIdentifier(node.array)
);
this.layout.add(formattedArray);
});

this.formatNode(node.parenthesis);
}

Expand Down Expand Up @@ -489,6 +513,10 @@ export default class ExpressionFormatter {
}
}

private formatDataType(node: DataTypeNode) {
this.layout.add(this.showDataType(node), WS.SPACE);
}

private showKw(node: KeywordNode): string {
if (isTabularToken(node.tokenType)) {
return toTabularFormat(this.showNonTabularKw(node), this.cfg.indentStyle);
Expand All @@ -509,6 +537,26 @@ export default class ExpressionFormatter {
}
}

private showFunctionKw(node: KeywordNode): string {
if (isTabularToken(node.tokenType)) {
return toTabularFormat(this.showNonTabularFunctionKw(node), this.cfg.indentStyle);
} else {
return this.showNonTabularFunctionKw(node);
}
}

// Like showFunctionKw(), but skips tabular formatting
private showNonTabularFunctionKw(node: KeywordNode): string {
switch (this.cfg.functionCase) {
case 'preserve':
return equalizeWhitespace(node.raw);
case 'upper':
return node.text;
case 'lower':
return node.text.toLowerCase();
}
}

private showIdentifier(node: IdentifierNode): string {
if (node.quoted) {
return node.text;
Expand All @@ -523,4 +571,15 @@ export default class ExpressionFormatter {
}
}
}

private showDataType(node: DataTypeNode): string {
switch (this.cfg.dataTypeCase) {
case 'preserve':
return equalizeWhitespace(node.raw);
case 'upper':
return node.text;
case 'lower':
return node.text.toLowerCase();
}
}
}
5 changes: 2 additions & 3 deletions src/languages/bigquery/bigquery.formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,8 @@ export const bigquery: DialectOptions = {
reservedSetOperations,
reservedJoins,
reservedPhrases,
reservedKeywords:
// Temporary, will be replaced by reservedDataTypes
[...new Set(keywords.concat(dataTypes))],
reservedKeywords: keywords,
reservedDataTypes: dataTypes,
reservedFunctionNames: functions,
extraParens: ['[]'],
stringTypes: [
Expand Down
9 changes: 0 additions & 9 deletions src/languages/bigquery/bigquery.functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -585,13 +585,4 @@ export const functions: string[] = [
// pivot
'PIVOT',
'UNPIVOT',

// Data types with parameters like VARCHAR(100)
// https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#parameterized_data_types
'BYTES',
'NUMERIC',
'DECIMAL',
'BIGNUMERIC',
'BIGDECIMAL',
'STRING',
];
9 changes: 1 addition & 8 deletions src/languages/bigquery/bigquery.keywords.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ export const keywords: string[] = [
];

export const dataTypes: string[] = [
// https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types
'ARRAY', // parametric, ARRAY<T>
'BOOL',
'BYTES', // parameterised, BYTES(Length)
Expand All @@ -134,12 +135,4 @@ export const dataTypes: string[] = [
'STRUCT', // parametric, STRUCT<T>
'TIME',
'TIMEZONE',

// https://cloud.google.com/bigquery/docs/reference/standard-sql/conversion_functions#formatting_syntax
'HEX',
'BASEX',
'BASE64M',
'ASCII',
'UTF-8',
'UTF8',
];
5 changes: 2 additions & 3 deletions src/languages/db2/db2.formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,9 +266,8 @@ export const db2: DialectOptions = {
reservedSetOperations,
reservedJoins,
reservedPhrases,
reservedKeywords:
// Temporary, will be replaced by reservedDataTypes
[...new Set(keywords.concat(dataTypes))],
reservedKeywords: keywords,
reservedDataTypes: dataTypes,
reservedFunctionNames: functions,
extraParens: ['[]'],
stringTypes: [
Expand Down
Loading

0 comments on commit 7e3db7f

Please sign in to comment.