Skip to content

Separate multi-word keywords from the rest #363

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Aug 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/formatter/ExpressionFormatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ export default class ExpressionFormatter {
return this.formatLogicalOperator(token);
case TokenType.RESERVED_KEYWORD:
case TokenType.RESERVED_FUNCTION_NAME:
case TokenType.RESERVED_PHRASE:
return this.formatKeyword(token);
case TokenType.RESERVED_CASE_START:
return this.formatCaseStart(token);
Expand Down
10 changes: 10 additions & 0 deletions src/languages/bigquery/bigquery.formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,15 @@ const reservedJoins = expandPhrases([
'{INNER | CROSS} JOIN',
]);

const reservedPhrases = [
// https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#tablesample_operator
'TABLESAMPLE SYSTEM',
// From DDL: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language
'ANY TYPE',
'ALL COLUMNS',
'NOT DETERMINISTIC',
];

// https://cloud.google.com/bigquery/docs/reference/#standard-sql-reference
export default class BigQueryFormatter extends Formatter {
static operators = ['~', '>>', '<<', '||'];
Expand All @@ -127,6 +136,7 @@ export default class BigQueryFormatter extends Formatter {
reservedSetOperations,
reservedJoins,
reservedDependentClauses: ['WHEN', 'ELSE'],
reservedPhrases,
reservedKeywords: keywords,
reservedFunctionNames: functions,
openParens: ['(', '['],
Expand Down
5 changes: 1 addition & 4 deletions src/languages/bigquery/bigquery.keywords.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export const keywords = flatKeywordList({
'SOME',
'STRUCT',
'TABLE',
'TABLESAMPLE SYSTEM',
'TABLESAMPLE',
'THEN',
'TO',
'TREAT',
Expand Down Expand Up @@ -138,11 +138,8 @@ export const keywords = flatKeywordList({
'INOUT',
'RETURNS',
'LANGUAGE',
'ANY TYPE',
'ALL COLUMNS',
'CASCADE',
'RESTRICT',
'DETERMINISTIC',
'NOT DETERMINISTIC',
],
});
3 changes: 3 additions & 0 deletions src/languages/db2/db2.formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ const reservedJoins = expandPhrases([
'{INNER | CROSS} JOIN',
]);

const reservedPhrases = ['ON DELETE', 'ON UPDATE'];

// https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_72/db2/rbafzintro.htm
export default class Db2Formatter extends Formatter {
static operators = ['**', '¬=', '¬>', '¬<', '!>', '!<', '||'];
Expand All @@ -157,6 +159,7 @@ export default class Db2Formatter extends Formatter {
reservedSetOperations,
reservedJoins,
reservedDependentClauses: ['WHEN', 'ELSE', 'ELSEIF'],
reservedPhrases,
reservedKeywords: keywords,
reservedFunctionNames: functions,
stringTypes: [{ quote: "''", prefixes: ['G', 'N', 'X', 'BX', 'GX', 'UX', 'U&'] }],
Expand Down
1 change: 0 additions & 1 deletion src/languages/db2/db2.keywords.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,5 +236,4 @@ export const keywords = flatKeywordList({
'YEARS',
'ZONE',
],
constraints: ['ON DELETE', 'ON UPDATE'],
});
3 changes: 3 additions & 0 deletions src/languages/mariadb/mariadb.formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,8 @@ const reservedJoins = expandPhrases([
'STRAIGHT_JOIN',
]);

const reservedPhrases = ['ON DELETE', 'ON UPDATE', 'CHARACTER SET'];

// For reference: https://mariadb.com/kb/en/sql-statements-structure/
export default class MariaDbFormatter extends Formatter {
static operators = [':=', '<<', '>>', '<=>', '&&', '||'];
Expand All @@ -253,6 +255,7 @@ export default class MariaDbFormatter extends Formatter {
reservedSetOperations,
reservedJoins,
reservedDependentClauses: ['WHEN', 'ELSE', 'ELSEIF', 'ELSIF'],
reservedPhrases,
reservedLogicalOperators: ['AND', 'OR', 'XOR'],
reservedKeywords: keywords,
reservedFunctionNames: functions,
Expand Down
2 changes: 0 additions & 2 deletions src/languages/mariadb/mariadb.keywords.ts
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,4 @@ export const keywords = flatKeywordList({
'YEAR_MONTH',
'ZEROFILL',
],
constraints: ['ON DELETE', 'ON UPDATE'],
charset: ['CHARACTER SET'],
});
3 changes: 3 additions & 0 deletions src/languages/mysql/mysql.formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,8 @@ const reservedJoins = expandPhrases([
'STRAIGHT_JOIN',
]);

const reservedPhrases = ['ON DELETE', 'ON UPDATE', 'CHARACTER SET'];

// https://dev.mysql.com/doc/refman/8.0/en/
export default class MySqlFormatter extends Formatter {
static operators = ['~', ':=', '<<', '>>', '<=>', '&&', '||', '->', '->>'];
Expand All @@ -220,6 +222,7 @@ export default class MySqlFormatter extends Formatter {
reservedSetOperations,
reservedJoins,
reservedDependentClauses: ['WHEN', 'ELSE', 'ELSEIF'],
reservedPhrases,
reservedLogicalOperators: ['AND', 'OR', 'XOR'],
reservedKeywords: keywords,
reservedFunctionNames: functions,
Expand Down
2 changes: 0 additions & 2 deletions src/languages/mysql/mysql.keywords.ts
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,4 @@ export const keywords = flatKeywordList({
'ZEROFILL', // (R)
'ZONE',
],
constraints: ['ON DELETE', 'ON UPDATE'],
charset: ['CHARACTER SET'],
});
3 changes: 3 additions & 0 deletions src/languages/plsql/plsql.formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ const reservedJoins = expandPhrases([
'{CROSS | OUTER} APPLY',
]);

const reservedPhrases = ['ON DELETE', 'ON UPDATE', 'ON COMMIT'];

export default class PlSqlFormatter extends Formatter {
static operators = [
'||',
Expand All @@ -73,6 +75,7 @@ export default class PlSqlFormatter extends Formatter {
reservedSetOperations,
reservedJoins,
reservedDependentClauses: ['WHEN', 'ELSE'],
reservedPhrases,
reservedLogicalOperators: ['AND', 'OR', 'XOR'],
reservedKeywords: keywords,
reservedFunctionNames: functions,
Expand Down
1 change: 0 additions & 1 deletion src/languages/plsql/plsql.keywords.ts
Original file line number Diff line number Diff line change
Expand Up @@ -328,5 +328,4 @@ export const keywords = flatKeywordList({
'YEAR',
'ZONE',
],
constraints: ['ON DELETE', 'ON UPDATE'],
});
3 changes: 3 additions & 0 deletions src/languages/postgresql/postgresql.formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,8 @@ const reservedJoins = expandPhrases([
'NATURAL {LEFT | RIGHT | FULL} [OUTER] JOIN',
]);

const reservedPhrases = ['ON DELETE', 'ON UPDATE'];

const binaryOperators = [
// Math Operators
'<<',
Expand Down Expand Up @@ -306,6 +308,7 @@ export default class PostgreSqlFormatter extends Formatter {
reservedSetOperations,
reservedJoins,
reservedDependentClauses: ['WHEN', 'ELSE'],
reservedPhrases,
reservedKeywords: keywords,
reservedFunctionNames: functions,
openParens: ['(', '['],
Expand Down
1 change: 0 additions & 1 deletion src/languages/postgresql/postgresql.keywords.ts
Original file line number Diff line number Diff line change
Expand Up @@ -461,5 +461,4 @@ export const keywords = flatKeywordList({
'YES',
'ZONE',
],
constraints: ['ON DELETE', 'ON UPDATE', 'ON COMMIT'],
});
9 changes: 9 additions & 0 deletions src/languages/redshift/redshift.formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,14 @@ const reservedJoins = expandPhrases([
'NATURAL {LEFT | RIGHT | FULL} [OUTER] JOIN',
]);

const reservedPhrases = [
// https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-data-conversion.html
'NULL AS',
// https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_EXTERNAL_SCHEMA.html
'DATA CATALOG',
'HIVE METASTORE',
];

// https://docs.aws.amazon.com/redshift/latest/dg/cm_chap_SQLCommandRef.html
export default class RedshiftFormatter extends Formatter {
static operators = ['~', '|/', '||/', '<<', '>>', '||'];
Expand All @@ -127,6 +135,7 @@ export default class RedshiftFormatter extends Formatter {
reservedSetOperations,
reservedJoins,
reservedDependentClauses: ['WHEN', 'ELSE'],
reservedPhrases,
reservedKeywords: keywords,
reservedFunctionNames: functions,
stringTypes: ["''"],
Expand Down
15 changes: 2 additions & 13 deletions src/languages/redshift/redshift.keywords.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ export const keywords = flatKeywordList({
'FILLRECORD',
'IGNOREBLANKLINES',
'IGNOREHEADER',
'NULL AS',
'REMOVEQUOTES',
'ROUNDEC',
'TIMEFORMAT',
Expand Down Expand Up @@ -177,15 +176,13 @@ export const keywords = flatKeywordList({
'CATALOG_ROLE',
'SECRET_ARN',
'EXTERNAL',
'HIVE METASTORE', // https://docs.aws.amazon.com/redshift/latest/dg/c-spectrum-external-schemas.html
// https://docs.aws.amazon.com/redshift/latest/dg/c_choosing_dist_sort.html
'AUTO',
'EVEN',
'KEY',
'PREDICATE', // ANALYZE | ANALYSE (https://docs.aws.amazon.com/redshift/latest/dg/r_ANALYZE.html)
// unknown
'COMPRESSION',
'DATA CATALOG',
],
/**
* Other keywords not included:
Expand All @@ -194,14 +191,6 @@ export const keywords = flatKeywordList({
* SVL: https://docs.aws.amazon.com/redshift/latest/dg/svl_views.html
* SVV: https://docs.aws.amazon.com/redshift/latest/dg/svv_views.html
*/
dataTypes: [
'CHAR',
'CHARACTER',
'NCHAR',
'VARCHAR',
'CHARACTER VARYING',
'NVARCHAR',
'BPCHAR',
'TEXT',
],
// https://docs.aws.amazon.com/redshift/latest/dg/r_Character_types.html#r_Character_types-text-and-bpchar-types
dataTypes: ['BPCHAR', 'TEXT'],
});
3 changes: 3 additions & 0 deletions src/languages/spark/spark.formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ const reservedJoins = expandPhrases([
'NATURAL [LEFT] {ANTI | SEMI} JOIN',
]);

const reservedPhrases = ['ON DELETE', 'ON UPDATE', 'CURRENT ROW'];

// http://spark.apache.org/docs/latest/sql-programming-guide.html
export default class SparkFormatter extends Formatter {
static operators = ['~', '<=>', '&&', '||', '==', '->'];
Expand All @@ -108,6 +110,7 @@ export default class SparkFormatter extends Formatter {
reservedSetOperations,
reservedJoins,
reservedDependentClauses: ['WHEN', 'ELSE'],
reservedPhrases,
reservedLogicalOperators: ['AND', 'OR', 'XOR'],
reservedKeywords: keywords,
reservedFunctionNames: functions,
Expand Down
2 changes: 0 additions & 2 deletions src/languages/spark/spark.keywords.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,6 @@ export const keywords = flatKeywordList({
'COALESCE',
'CONTAINS',
'CONVERT',
'CURRENT ROW',
'DAYS',
'DAY_HOUR',
'DAY_MINUTE',
Expand Down Expand Up @@ -275,5 +274,4 @@ export const keywords = flatKeywordList({
'VARIABLES',
'YEAR_MONTH',
],
constraints: ['ON DELETE', 'ON UPDATE'],
});
3 changes: 3 additions & 0 deletions src/languages/sql/sql.formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ const reservedJoins = expandPhrases([
'NATURAL {LEFT | RIGHT | FULL} [OUTER] JOIN',
]);

const reservedPhrases = ['ON DELETE', 'ON UPDATE'];

export default class SqlFormatter extends Formatter {
static operators = [];

Expand All @@ -55,6 +57,7 @@ export default class SqlFormatter extends Formatter {
reservedSetOperations,
reservedJoins,
reservedDependentClauses: ['WHEN', 'ELSE'],
reservedPhrases,
reservedKeywords: keywords,
reservedFunctionNames: functions,
stringTypes: [{ quote: "''", prefixes: ['N', 'X', 'U&'] }],
Expand Down
1 change: 0 additions & 1 deletion src/languages/sql/sql.keywords.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,5 +225,4 @@ export const keywords = flatKeywordList({
'WITHOUT',
'YEAR',
],
constraints: ['ON DELETE', 'ON UPDATE'],
});
3 changes: 3 additions & 0 deletions src/languages/sqlite/sqlite.formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ const reservedJoins = expandPhrases([
'NATURAL {LEFT | RIGHT | FULL} [OUTER] JOIN',
]);

const reservedPhrases = ['ON DELETE', 'ON UPDATE'];

export default class SqliteFormatter extends Formatter {
// https://www.sqlite.org/lang_expr.html
static operators = ['~', '->', '->>', '||', '<<', '>>', '=='];
Expand All @@ -53,6 +55,7 @@ export default class SqliteFormatter extends Formatter {
reservedSetOperations,
reservedJoins,
reservedDependentClauses: ['WHEN', 'ELSE'],
reservedPhrases,
reservedKeywords: keywords,
reservedFunctionNames: functions,
stringTypes: [
Expand Down
1 change: 0 additions & 1 deletion src/languages/sqlite/sqlite.keywords.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,5 +156,4 @@ export const keywords = flatKeywordList({
'WITH',
'WITHOUT',
],
constraints: ['ON DELETE', 'ON UPDATE'],
});
3 changes: 3 additions & 0 deletions src/languages/tsql/tsql.formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ const reservedJoins = expandPhrases([
'{CROSS | OUTER} APPLY',
]);

const reservedPhrases = ['ON DELETE', 'ON UPDATE'];

// https://docs.microsoft.com/en-us/sql/t-sql/language-reference?view=sql-server-ver15
export default class TSqlFormatter extends Formatter {
static operators = ['~', '!<', '!>', '+=', '-=', '*=', '/=', '%=', '|=', '&=', '^=', '::'];
Expand All @@ -210,6 +212,7 @@ export default class TSqlFormatter extends Formatter {
reservedSetOperations,
reservedJoins,
reservedDependentClauses: ['WHEN', 'ELSE'],
reservedPhrases,
reservedKeywords: keywords,
reservedFunctionNames: functions,
stringTypes: [{ quote: "''", prefixes: ['N'] }],
Expand Down
1 change: 0 additions & 1 deletion src/languages/tsql/tsql.keywords.ts
Original file line number Diff line number Diff line change
Expand Up @@ -413,5 +413,4 @@ export const keywords = flatKeywordList({
'YEAR',
'ZONE',
],
constraints: ['ON DELETE', 'ON UPDATE'],
});
7 changes: 7 additions & 0 deletions src/lexer/Tokenizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ interface TokenizerOptions {
reservedSetOperations: string[];
// Various joins like LEFT OUTER JOIN
reservedJoins: string[];
// These are essentially multi-word sequences of keywords,
// that we prioritize over normal keywords
reservedPhrases?: string[];
// built in function names
reservedFunctionNames: string[];
// all other reserved words (not included to any of the above lists)
Expand Down Expand Up @@ -99,6 +102,10 @@ export default class Tokenizer {
regex: regex.reservedWord(cfg.reservedJoins, cfg.identChars),
value: v => equalizeWhitespace(v.toUpperCase()),
},
[TokenType.RESERVED_PHRASE]: {
regex: regex.reservedWord(cfg.reservedPhrases ?? [], cfg.identChars),
value: v => equalizeWhitespace(v.toUpperCase()),
},
[TokenType.RESERVED_LOGICAL_OPERATOR]: {
regex: regex.reservedWord(cfg.reservedLogicalOperators ?? ['AND', 'OR'], cfg.identChars),
value: v => equalizeWhitespace(v.toUpperCase()),
Expand Down
1 change: 1 addition & 0 deletions src/lexer/TokenizerEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ export default class TokenizerEngine {
this.matchToken(TokenType.RESERVED_SET_OPERATION) ||
this.matchToken(TokenType.RESERVED_DEPENDENT_CLAUSE) ||
this.matchToken(TokenType.RESERVED_JOIN) ||
this.matchToken(TokenType.RESERVED_PHRASE) ||
this.matchToken(TokenType.RESERVED_LOGICAL_OPERATOR) ||
this.matchToken(TokenType.RESERVED_FUNCTION_NAME) ||
this.matchToken(TokenType.RESERVED_KEYWORD)
Expand Down
2 changes: 2 additions & 0 deletions src/lexer/token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export enum TokenType {
RESERVED_KEYWORD = 'RESERVED_KEYWORD',
RESERVED_FUNCTION_NAME = 'RESERVED_FUNCTION_NAME',
RESERVED_LOGICAL_OPERATOR = 'RESERVED_LOGICAL_OPERATOR',
RESERVED_PHRASE = 'RESERVED_PHRASE',
RESERVED_DEPENDENT_CLAUSE = 'RESERVED_DEPENDENT_CLAUSE',
RESERVED_SET_OPERATION = 'RESERVED_SET_OPERATION',
RESERVED_COMMAND = 'RESERVED_COMMAND',
Expand Down Expand Up @@ -73,6 +74,7 @@ export const isReserved = (token: Token): boolean =>
token.type === TokenType.RESERVED_KEYWORD ||
token.type === TokenType.RESERVED_FUNCTION_NAME ||
token.type === TokenType.RESERVED_LOGICAL_OPERATOR ||
token.type === TokenType.RESERVED_PHRASE ||
token.type === TokenType.RESERVED_DEPENDENT_CLAUSE ||
token.type === TokenType.RESERVED_COMMAND ||
token.type === TokenType.RESERVED_SET_OPERATION ||
Expand Down