rawsql-ts 0.1.0-beta.10 → 0.1.0-beta.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +165 -174
- package/dist/esm/index.js +17 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/models/BinarySelectQuery.js +137 -0
- package/dist/esm/models/BinarySelectQuery.js.map +1 -0
- package/dist/esm/models/Clause.js +289 -0
- package/dist/esm/models/Clause.js.map +1 -0
- package/dist/esm/models/KeywordTrie.js +48 -0
- package/dist/esm/models/KeywordTrie.js.map +1 -0
- package/dist/esm/models/Lexeme.js +18 -0
- package/dist/esm/models/Lexeme.js.map +1 -0
- package/dist/esm/models/SelectQuery.js +5 -0
- package/dist/esm/models/SelectQuery.js.map +1 -0
- package/dist/esm/models/SimpleSelectQuery.js +288 -0
- package/dist/esm/models/SimpleSelectQuery.js.map +1 -0
- package/dist/esm/models/SqlComponent.js +22 -0
- package/dist/esm/models/SqlComponent.js.map +1 -0
- package/dist/esm/models/ValueComponent.js +223 -0
- package/dist/esm/models/ValueComponent.js.map +1 -0
- package/dist/esm/models/ValuesQuery.js +12 -0
- package/dist/esm/models/ValuesQuery.js.map +1 -0
- package/dist/esm/parsers/CommandExpressionParser.js +120 -0
- package/dist/esm/parsers/CommandExpressionParser.js.map +1 -0
- package/dist/esm/parsers/CommonTableParser.js +58 -0
- package/dist/esm/parsers/CommonTableParser.js.map +1 -0
- package/dist/esm/parsers/ForClauseParser.js +54 -0
- package/dist/esm/parsers/ForClauseParser.js.map +1 -0
- package/dist/esm/parsers/FromClauseParser.js +43 -0
- package/dist/esm/parsers/FromClauseParser.js.map +1 -0
- package/dist/esm/parsers/FunctionExpressionParser.js +174 -0
- package/dist/esm/parsers/FunctionExpressionParser.js.map +1 -0
- package/dist/esm/parsers/GroupByParser.js +54 -0
- package/dist/esm/parsers/GroupByParser.js.map +1 -0
- package/dist/esm/parsers/HavingParser.js +32 -0
- package/dist/esm/parsers/HavingParser.js.map +1 -0
- package/dist/esm/parsers/IdentifierParser.js +35 -0
- package/dist/esm/parsers/IdentifierParser.js.map +1 -0
- package/dist/esm/parsers/JoinClauseParser.js +101 -0
- package/dist/esm/parsers/JoinClauseParser.js.map +1 -0
- package/dist/esm/parsers/KeywordParser.js +87 -0
- package/dist/esm/parsers/KeywordParser.js.map +1 -0
- package/dist/esm/parsers/LimitClauseParser.js +46 -0
- package/dist/esm/parsers/LimitClauseParser.js.map +1 -0
- package/dist/esm/parsers/LiteralParser.js +34 -0
- package/dist/esm/parsers/LiteralParser.js.map +1 -0
- package/dist/esm/parsers/OrderByClauseParser.js +73 -0
- package/dist/esm/parsers/OrderByClauseParser.js.map +1 -0
- package/dist/esm/parsers/OverExpressionParser.js +40 -0
- package/dist/esm/parsers/OverExpressionParser.js.map +1 -0
- package/dist/esm/parsers/ParameterExpressionParser.js +11 -0
- package/dist/esm/parsers/ParameterExpressionParser.js.map +1 -0
- package/dist/esm/parsers/ParenExpressionParser.js +29 -0
- package/dist/esm/parsers/ParenExpressionParser.js.map +1 -0
- package/dist/esm/parsers/PartitionByParser.js +49 -0
- package/dist/esm/parsers/PartitionByParser.js.map +1 -0
- package/dist/esm/parsers/SelectClauseParser.js +80 -0
- package/dist/esm/parsers/SelectClauseParser.js.map +1 -0
- package/dist/esm/parsers/SelectQueryParser.js +149 -0
- package/dist/esm/parsers/SelectQueryParser.js.map +1 -0
- package/dist/esm/parsers/SourceAliasExpressionParser.js +45 -0
- package/dist/esm/parsers/SourceAliasExpressionParser.js.map +1 -0
- package/dist/esm/parsers/SourceExpressionParser.js +31 -0
- package/dist/esm/parsers/SourceExpressionParser.js.map +1 -0
- package/dist/esm/parsers/SourceParser.js +115 -0
- package/dist/esm/parsers/SourceParser.js.map +1 -0
- package/dist/esm/parsers/SqlTokenizer.js +170 -0
- package/dist/esm/parsers/SqlTokenizer.js.map +1 -0
- package/dist/esm/parsers/StringSpecifierExpressionParser.js +18 -0
- package/dist/esm/parsers/StringSpecifierExpressionParser.js.map +1 -0
- package/dist/esm/parsers/UnaryExpressionParser.js +26 -0
- package/dist/esm/parsers/UnaryExpressionParser.js.map +1 -0
- package/dist/esm/parsers/ValueParser.js +132 -0
- package/dist/esm/parsers/ValueParser.js.map +1 -0
- package/dist/esm/parsers/ValuesQueryParser.js +82 -0
- package/dist/esm/parsers/ValuesQueryParser.js.map +1 -0
- package/dist/esm/parsers/WhereClauseParser.js +32 -0
- package/dist/esm/parsers/WhereClauseParser.js.map +1 -0
- package/dist/esm/parsers/WindowClauseParser.js +41 -0
- package/dist/esm/parsers/WindowClauseParser.js.map +1 -0
- package/dist/esm/parsers/WindowExpressionParser.js +159 -0
- package/dist/esm/parsers/WindowExpressionParser.js.map +1 -0
- package/dist/esm/parsers/WithClauseParser.js +53 -0
- package/dist/esm/parsers/WithClauseParser.js.map +1 -0
- package/dist/esm/tokenReaders/BaseTokenReader.js +78 -0
- package/dist/esm/tokenReaders/BaseTokenReader.js.map +1 -0
- package/dist/esm/tokenReaders/CommandTokenReader.js +141 -0
- package/dist/esm/tokenReaders/CommandTokenReader.js.map +1 -0
- package/dist/esm/tokenReaders/FunctionTokenReader.js +41 -0
- package/dist/esm/tokenReaders/FunctionTokenReader.js.map +1 -0
- package/dist/esm/tokenReaders/IdentifierTokenReader.js +66 -0
- package/dist/esm/tokenReaders/IdentifierTokenReader.js.map +1 -0
- package/dist/esm/tokenReaders/LiteralTokenReader.js +185 -0
- package/dist/esm/tokenReaders/LiteralTokenReader.js.map +1 -0
- package/dist/esm/tokenReaders/OperatorTokenReader.js +94 -0
- package/dist/esm/tokenReaders/OperatorTokenReader.js.map +1 -0
- package/dist/esm/tokenReaders/ParameterTokenReader.js +40 -0
- package/dist/esm/tokenReaders/ParameterTokenReader.js.map +1 -0
- package/dist/esm/tokenReaders/StringSpecifierTokenReader.js +27 -0
- package/dist/esm/tokenReaders/StringSpecifierTokenReader.js.map +1 -0
- package/dist/esm/tokenReaders/SymbolTokenReader.js +31 -0
- package/dist/esm/tokenReaders/SymbolTokenReader.js.map +1 -0
- package/dist/esm/tokenReaders/TokenReaderManager.js +106 -0
- package/dist/esm/tokenReaders/TokenReaderManager.js.map +1 -0
- package/dist/esm/tokenReaders/TypeTokenReader.js +55 -0
- package/dist/esm/tokenReaders/TypeTokenReader.js.map +1 -0
- package/dist/esm/transformers/CTEBuilder.js +184 -0
- package/dist/esm/transformers/CTEBuilder.js.map +1 -0
- package/dist/esm/transformers/CTECollector.js +380 -0
- package/dist/esm/transformers/CTECollector.js.map +1 -0
- package/dist/esm/transformers/CTEDisabler.js +321 -0
- package/dist/esm/transformers/CTEDisabler.js.map +1 -0
- package/dist/esm/transformers/CTEInjector.js +79 -0
- package/dist/esm/transformers/CTEInjector.js.map +1 -0
- package/dist/esm/transformers/CTENormalizer.js +42 -0
- package/dist/esm/transformers/CTENormalizer.js.map +1 -0
- package/dist/esm/transformers/Formatter.js +463 -0
- package/dist/esm/transformers/Formatter.js.map +1 -0
- package/dist/esm/transformers/QueryConverter.js +115 -0
- package/dist/esm/transformers/QueryConverter.js.map +1 -0
- package/dist/esm/transformers/SelectValueCollector.js +245 -0
- package/dist/esm/transformers/SelectValueCollector.js.map +1 -0
- package/dist/esm/transformers/SelectableColumnCollector.js +304 -0
- package/dist/esm/transformers/SelectableColumnCollector.js.map +1 -0
- package/dist/esm/transformers/TableColumnResolver.js +2 -0
- package/dist/esm/transformers/TableColumnResolver.js.map +1 -0
- package/dist/esm/transformers/TableSourceCollector.js +380 -0
- package/dist/esm/transformers/TableSourceCollector.js.map +1 -0
- package/dist/esm/transformers/UpstreamSelectQueryFinder.js +125 -0
- package/dist/esm/transformers/UpstreamSelectQueryFinder.js.map +1 -0
- package/dist/esm/types/index.d.ts +14 -0
- package/dist/esm/types/models/BinarySelectQuery.d.ts +91 -0
- package/dist/esm/types/models/Clause.d.ts +189 -0
- package/dist/esm/types/models/KeywordTrie.d.ts +11 -0
- package/dist/esm/types/models/Lexeme.d.ts +25 -0
- package/dist/esm/types/models/SelectQuery.d.ts +5 -0
- package/dist/esm/types/models/SimpleSelectQuery.d.ts +167 -0
- package/dist/esm/types/models/SqlComponent.d.ts +18 -0
- package/dist/esm/types/models/ValueComponent.d.ts +158 -0
- package/dist/esm/types/models/ValuesQuery.d.ts +10 -0
- package/dist/esm/types/parsers/CommandExpressionParser.d.ts +15 -0
- package/dist/esm/types/parsers/CommonTableParser.d.ts +9 -0
- package/dist/esm/types/parsers/ForClauseParser.d.ts +9 -0
- package/dist/esm/types/parsers/FromClauseParser.d.ts +9 -0
- package/dist/esm/types/parsers/FunctionExpressionParser.d.ts +22 -0
- package/dist/esm/types/parsers/GroupByParser.d.ts +10 -0
- package/dist/esm/types/parsers/HavingParser.d.ts +9 -0
- package/dist/esm/types/parsers/IdentifierParser.d.ts +8 -0
- package/dist/esm/types/parsers/JoinClauseParser.d.ts +14 -0
- package/dist/esm/types/parsers/KeywordParser.d.ts +17 -0
- package/dist/esm/types/parsers/LimitClauseParser.d.ts +9 -0
- package/dist/esm/types/parsers/LiteralParser.d.ts +8 -0
- package/dist/esm/types/parsers/OrderByClauseParser.d.ts +10 -0
- package/dist/esm/types/parsers/OverExpressionParser.d.ts +9 -0
- package/dist/esm/types/parsers/ParameterExpressionParser.d.ts +8 -0
- package/dist/esm/types/parsers/ParenExpressionParser.d.ts +8 -0
- package/dist/esm/types/parsers/PartitionByParser.d.ts +9 -0
- package/dist/esm/types/parsers/SelectClauseParser.d.ts +10 -0
- package/dist/esm/types/parsers/SelectQueryParser.d.ts +13 -0
- package/dist/esm/types/parsers/SourceAliasExpressionParser.d.ts +8 -0
- package/dist/esm/types/parsers/SourceExpressionParser.d.ts +8 -0
- package/dist/esm/types/parsers/SourceParser.d.ts +13 -0
- package/dist/esm/types/parsers/SqlTokenizer.d.ts +64 -0
- package/dist/esm/types/parsers/StringSpecifierExpressionParser.d.ts +8 -0
- package/dist/esm/types/parsers/UnaryExpressionParser.d.ts +8 -0
- package/dist/esm/types/parsers/ValueParser.d.ts +14 -0
- package/dist/esm/types/parsers/ValuesQueryParser.d.ts +10 -0
- package/dist/esm/types/parsers/WhereClauseParser.d.ts +9 -0
- package/dist/esm/types/parsers/WindowClauseParser.d.ts +9 -0
- package/dist/esm/types/parsers/WindowExpressionParser.d.ts +12 -0
- package/dist/esm/types/parsers/WithClauseParser.d.ts +9 -0
- package/dist/esm/types/tokenReaders/BaseTokenReader.d.ts +43 -0
- package/dist/esm/types/tokenReaders/CommandTokenReader.d.ts +7 -0
- package/dist/esm/types/tokenReaders/FunctionTokenReader.d.ts +11 -0
- package/dist/esm/types/tokenReaders/IdentifierTokenReader.d.ts +15 -0
- package/dist/esm/types/tokenReaders/LiteralTokenReader.d.ts +23 -0
- package/dist/esm/types/tokenReaders/OperatorTokenReader.d.ts +5 -0
- package/dist/esm/types/tokenReaders/ParameterTokenReader.d.ts +11 -0
- package/dist/esm/types/tokenReaders/StringSpecifierTokenReader.d.ts +8 -0
- package/dist/esm/types/tokenReaders/SymbolTokenReader.d.ts +12 -0
- package/dist/esm/types/tokenReaders/TokenReaderManager.d.ts +53 -0
- package/dist/esm/types/tokenReaders/TypeTokenReader.d.ts +11 -0
- package/dist/esm/types/transformers/CTEBuilder.d.ts +52 -0
- package/dist/esm/types/transformers/CTECollector.d.ts +81 -0
- package/dist/esm/types/transformers/CTEDisabler.d.ts +77 -0
- package/dist/esm/types/transformers/CTEInjector.d.ts +40 -0
- package/dist/esm/types/transformers/CTENormalizer.d.ts +25 -0
- package/dist/esm/types/transformers/Formatter.d.ts +82 -0
- package/dist/esm/types/transformers/QueryConverter.d.ts +41 -0
- package/dist/esm/types/transformers/SelectValueCollector.d.ts +60 -0
- package/dist/esm/types/transformers/SelectableColumnCollector.d.ts +70 -0
- package/dist/esm/types/transformers/TableColumnResolver.d.ts +10 -0
- package/dist/esm/types/transformers/TableSourceCollector.d.ts +92 -0
- package/dist/esm/types/transformers/UpstreamSelectQueryFinder.d.ts +27 -0
- package/dist/esm/types/utils/charLookupTable.d.ts +11 -0
- package/dist/esm/types/utils/stringUtils.d.ts +43 -0
- package/dist/esm/utils/charLookupTable.js +69 -0
- package/dist/esm/utils/charLookupTable.js.map +1 -0
- package/dist/esm/utils/stringUtils.js +164 -0
- package/dist/esm/utils/stringUtils.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/transformers/SelectValueCollector.d.ts +2 -4
- package/dist/transformers/SelectValueCollector.js.map +1 -1
- package/dist/transformers/TableColumnResolver.d.ts +10 -0
- package/dist/transformers/TableColumnResolver.js +3 -0
- package/dist/transformers/TableColumnResolver.js.map +1 -0
- package/package.json +17 -1
@@ -0,0 +1,41 @@
|
|
1
|
+
import { WindowFrameClause } from "../models/Clause";
|
2
|
+
import { TokenType } from "../models/Lexeme";
|
3
|
+
import { SqlTokenizer } from "./SqlTokenizer";
|
4
|
+
import { WindowExpressionParser } from "./WindowExpressionParser";
|
5
|
+
export class WindowClauseParser {
|
6
|
+
// Parse SQL string to AST (was: parse)
|
7
|
+
static parse(query) {
|
8
|
+
const tokenizer = new SqlTokenizer(query);
|
9
|
+
const lexemes = tokenizer.readLexmes();
|
10
|
+
// Parse
|
11
|
+
const result = this.parseFromLexeme(lexemes, 0);
|
12
|
+
// Error if there are remaining tokens
|
13
|
+
if (result.newIndex < lexemes.length) {
|
14
|
+
throw new Error(`Syntax error: Unexpected token "${lexemes[result.newIndex].value}" at position ${result.newIndex}. The WINDOW clause is complete but there are additional tokens.`);
|
15
|
+
}
|
16
|
+
return result.value;
|
17
|
+
}
|
18
|
+
// Parse from lexeme array (was: parse)
|
19
|
+
static parseFromLexeme(lexemes, index) {
|
20
|
+
let idx = index;
|
21
|
+
if (lexemes[idx].value !== 'window') {
|
22
|
+
throw new Error(`Syntax error at position ${idx}: Expected 'WINDOW' keyword but found "${lexemes[idx].value}". WINDOW clauses must start with the WINDOW keyword.`);
|
23
|
+
}
|
24
|
+
idx++;
|
25
|
+
if (idx >= lexemes.length || lexemes[idx].type !== TokenType.Identifier) {
|
26
|
+
throw new Error(`Syntax error: Expected window name after 'WINDOW' keyword.`);
|
27
|
+
}
|
28
|
+
// Get the window name
|
29
|
+
const name = lexemes[idx].value;
|
30
|
+
idx++;
|
31
|
+
if (idx >= lexemes.length || lexemes[idx].value !== 'as') {
|
32
|
+
throw new Error(`Syntax error at position ${idx}: Expected 'AS' keyword after window name.`);
|
33
|
+
}
|
34
|
+
idx++;
|
35
|
+
const expr = WindowExpressionParser.parseFromLexeme(lexemes, idx);
|
36
|
+
idx = expr.newIndex;
|
37
|
+
const windowFrame = new WindowFrameClause(name, expr.value);
|
38
|
+
return { value: windowFrame, newIndex: idx };
|
39
|
+
}
|
40
|
+
}
|
41
|
+
//# sourceMappingURL=WindowClauseParser.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"WindowClauseParser.js","sourceRoot":"","sources":["../../../src/parsers/WindowClauseParser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAU,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAElE,MAAM,OAAO,kBAAkB;IAC3B,uCAAuC;IAChC,MAAM,CAAC,KAAK,CAAC,KAAa;QAC7B,MAAM,SAAS,GAAG,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC;QAC1C,MAAM,OAAO,GAAG,SAAS,CAAC,UAAU,EAAE,CAAC;QAEvC,QAAQ;QACR,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAEhD,sCAAsC;QACtC,IAAI,MAAM,CAAC,QAAQ,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,mCAAmC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,iBAAiB,MAAM,CAAC,QAAQ,kEAAkE,CAAC,CAAC;QACzL,CAAC;QAED,OAAO,MAAM,CAAC,KAAK,CAAC;IACxB,CAAC;IAED,uCAAuC;IAChC,MAAM,CAAC,eAAe,CAAC,OAAiB,EAAE,KAAa;QAC1D,IAAI,GAAG,GAAG,KAAK,CAAC;QAEhB,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,4BAA4B,GAAG,0CAA0C,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,uDAAuD,CAAC,CAAC;QACxK,CAAC;QACD,GAAG,EAAE,CAAC;QAEN,IAAI,GAAG,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,UAAU,EAAE,CAAC;YACtE,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;QAClF,CAAC;QAED,sBAAsB;QACtB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;QAChC,GAAG,EAAE,CAAC;QAEN,IAAI,GAAG,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;YACvD,MAAM,IAAI,KAAK,CAAC,4BAA4B,GAAG,4CAA4C,CAAC,CAAC;QACjG,CAAC;QACD,GAAG,EAAE,CAAC;QAEN,MAAM,IAAI,GAAG,sBAAsB,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAClE,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC;QAEpB,MAAM,WAAW,GAAG,IAAI,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5D,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;IACjD,CAAC;CACJ"}
|
@@ -0,0 +1,159 @@
|
|
1
|
+
import { TokenType } from "../models/Lexeme";
|
2
|
+
import { WindowFrameBound, WindowFrameBoundaryValue, WindowFrameExpression, WindowFrameSpec, WindowFrameType, WindowFrameBoundStatic } from "../models/ValueComponent";
|
3
|
+
import { OrderByClauseParser } from "./OrderByClauseParser";
|
4
|
+
import { PartitionByParser } from "./PartitionByParser";
|
5
|
+
import { SqlTokenizer } from "./SqlTokenizer";
|
6
|
+
import { ValueParser } from "./ValueParser";
|
7
|
+
export class WindowExpressionParser {
|
8
|
+
// Parse SQL string to AST (was: parse)
|
9
|
+
static parse(query) {
|
10
|
+
const tokenizer = new SqlTokenizer(query); // Initialize tokenizer
|
11
|
+
const lexemes = tokenizer.readLexmes(); // Get tokens
|
12
|
+
// Parse
|
13
|
+
const result = this.parseFromLexeme(lexemes, 0);
|
14
|
+
// Error if there are remaining tokens
|
15
|
+
if (result.newIndex < lexemes.length) {
|
16
|
+
throw new Error(`Syntax error: Unexpected token "${lexemes[result.newIndex].value}" at position ${result.newIndex}. The window frame expression is complete but there are additional tokens.`);
|
17
|
+
}
|
18
|
+
return result.value;
|
19
|
+
}
|
20
|
+
// Parse from lexeme array (was: parse)
|
21
|
+
static parseFromLexeme(lexemes, index) {
|
22
|
+
let idx = index;
|
23
|
+
if (lexemes[idx].type !== TokenType.OpenParen) {
|
24
|
+
throw new Error(`Syntax error at position ${idx}: Expected opening parenthesis '(' but found "${lexemes[idx].value}".`);
|
25
|
+
}
|
26
|
+
idx++;
|
27
|
+
let partition = null;
|
28
|
+
let order = null;
|
29
|
+
let frameSpec = null;
|
30
|
+
if (idx < lexemes.length && lexemes[idx].value === 'partition by') {
|
31
|
+
const partitionResult = PartitionByParser.parseFromLexeme(lexemes, idx);
|
32
|
+
partition = partitionResult.value;
|
33
|
+
idx = partitionResult.newIndex;
|
34
|
+
}
|
35
|
+
if (idx < lexemes.length && lexemes[idx].value === 'order by') {
|
36
|
+
const orderResult = OrderByClauseParser.parseFromLexeme(lexemes, idx);
|
37
|
+
order = orderResult.value;
|
38
|
+
idx = orderResult.newIndex;
|
39
|
+
}
|
40
|
+
// Parse frame clause (ROWS/RANGE/GROUPS)
|
41
|
+
if (idx < lexemes.length && this.isFrameTypeKeyword(lexemes[idx].value)) {
|
42
|
+
const frameSpecResult = this.parseFrameSpec(lexemes, idx);
|
43
|
+
frameSpec = frameSpecResult.value;
|
44
|
+
idx = frameSpecResult.newIndex;
|
45
|
+
}
|
46
|
+
if (idx >= lexemes.length || lexemes[idx].type !== TokenType.CloseParen) {
|
47
|
+
throw new Error(`Syntax error at position ${idx}: Missing closing parenthesis ')' for window frame. Each opening parenthesis must have a matching closing parenthesis.`);
|
48
|
+
}
|
49
|
+
// Read close paren
|
50
|
+
idx++;
|
51
|
+
return { value: new WindowFrameExpression(partition, order, frameSpec), newIndex: idx };
|
52
|
+
}
|
53
|
+
static isFrameTypeKeyword(value) {
|
54
|
+
const lowerValue = value;
|
55
|
+
return lowerValue === 'rows' || lowerValue === 'range' || lowerValue === 'groups';
|
56
|
+
}
|
57
|
+
static parseFrameSpec(lexemes, index) {
|
58
|
+
let idx = index;
|
59
|
+
// Determine frame type (ROWS/RANGE/GROUPS)
|
60
|
+
const frameTypeStr = lexemes[idx].value;
|
61
|
+
let frameType;
|
62
|
+
switch (frameTypeStr) {
|
63
|
+
case 'rows':
|
64
|
+
frameType = WindowFrameType.Rows;
|
65
|
+
break;
|
66
|
+
case 'range':
|
67
|
+
frameType = WindowFrameType.Range;
|
68
|
+
break;
|
69
|
+
case 'groups':
|
70
|
+
frameType = WindowFrameType.Groups;
|
71
|
+
break;
|
72
|
+
default:
|
73
|
+
throw new Error(`Syntax error at position ${idx}: Invalid frame type "${lexemes[idx].value}". Expected one of: ROWS, RANGE, GROUPS.`);
|
74
|
+
}
|
75
|
+
idx++;
|
76
|
+
// Check for BETWEEN ... AND ... syntax
|
77
|
+
if (idx < lexemes.length && lexemes[idx].value === 'between') {
|
78
|
+
// BETWEEN ... AND ... syntax
|
79
|
+
idx++;
|
80
|
+
// Parse start boundary
|
81
|
+
const startBoundResult = this.parseFrameBoundary(lexemes, idx);
|
82
|
+
const startBound = startBoundResult.value;
|
83
|
+
idx = startBoundResult.newIndex;
|
84
|
+
// Check for AND keyword - may be recognized as a separate token or part of a compound token
|
85
|
+
if (idx >= lexemes.length || (lexemes[idx].value !== 'and')) {
|
86
|
+
throw new Error(`Syntax error at position ${idx}: Expected 'AND' keyword in BETWEEN clause.`);
|
87
|
+
}
|
88
|
+
idx++; // Skip AND
|
89
|
+
// Parse end boundary
|
90
|
+
const endBoundResult = this.parseFrameBoundary(lexemes, idx);
|
91
|
+
const endBound = endBoundResult.value;
|
92
|
+
idx = endBoundResult.newIndex;
|
93
|
+
return {
|
94
|
+
value: new WindowFrameSpec(frameType, startBound, endBound),
|
95
|
+
newIndex: idx
|
96
|
+
};
|
97
|
+
}
|
98
|
+
else {
|
99
|
+
// Single boundary specification
|
100
|
+
const boundaryResult = this.parseFrameBoundary(lexemes, idx);
|
101
|
+
const startBound = boundaryResult.value;
|
102
|
+
idx = boundaryResult.newIndex;
|
103
|
+
return {
|
104
|
+
value: new WindowFrameSpec(frameType, startBound, null),
|
105
|
+
newIndex: idx
|
106
|
+
};
|
107
|
+
}
|
108
|
+
}
|
109
|
+
static parseFrameBoundary(lexemes, index) {
|
110
|
+
let idx = index;
|
111
|
+
// Check for predefined boundaries
|
112
|
+
if (idx < lexemes.length && lexemes[idx].type === TokenType.Command) {
|
113
|
+
const currentValue = lexemes[idx].value;
|
114
|
+
let frameBound;
|
115
|
+
switch (currentValue) {
|
116
|
+
case 'current row':
|
117
|
+
frameBound = WindowFrameBound.CurrentRow;
|
118
|
+
break;
|
119
|
+
case 'unbounded preceding':
|
120
|
+
frameBound = WindowFrameBound.UnboundedPreceding;
|
121
|
+
break;
|
122
|
+
case 'unbounded following':
|
123
|
+
frameBound = WindowFrameBound.UnboundedFollowing;
|
124
|
+
break;
|
125
|
+
default:
|
126
|
+
throw new Error(`Syntax error at position ${idx}: Invalid frame type "${lexemes[idx].value}". Expected one of: ROWS, RANGE, GROUPS.`);
|
127
|
+
}
|
128
|
+
const bound = new WindowFrameBoundStatic(frameBound);
|
129
|
+
return { value: bound, newIndex: idx + 1 };
|
130
|
+
}
|
131
|
+
else if (idx < lexemes.length && lexemes[idx].type === TokenType.Literal) {
|
132
|
+
// Parse the numeric/literal value
|
133
|
+
const valueResult = ValueParser.parseFromLexeme(lexemes, idx);
|
134
|
+
idx = valueResult.newIndex;
|
135
|
+
// Next token must be 'preceding' or 'following'
|
136
|
+
if (idx < lexemes.length && lexemes[idx].type === TokenType.Command) {
|
137
|
+
const direction = lexemes[idx].value;
|
138
|
+
let isFollowing;
|
139
|
+
if (direction === 'preceding') {
|
140
|
+
isFollowing = false;
|
141
|
+
}
|
142
|
+
else if (direction === 'following') {
|
143
|
+
isFollowing = true;
|
144
|
+
}
|
145
|
+
else {
|
146
|
+
throw new Error(`Syntax error at position ${idx}: Expected 'preceding' or 'following' after numeric value in window frame boundary.`);
|
147
|
+
}
|
148
|
+
idx++;
|
149
|
+
const bound = new WindowFrameBoundaryValue(valueResult.value, isFollowing);
|
150
|
+
return { value: bound, newIndex: idx };
|
151
|
+
}
|
152
|
+
else {
|
153
|
+
throw new Error(`Syntax error at position ${idx}: Expected 'preceding' or 'following' after numeric value in window frame boundary.`);
|
154
|
+
}
|
155
|
+
}
|
156
|
+
throw new Error(`Syntax error at position ${idx}: Expected a valid frame boundary component.`);
|
157
|
+
}
|
158
|
+
}
|
159
|
+
//# sourceMappingURL=WindowExpressionParser.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"WindowExpressionParser.js","sourceRoot":"","sources":["../../../src/parsers/WindowExpressionParser.ts"],"names":[],"mappings":"AACA,OAAO,EAAU,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,wBAAwB,EAA0B,qBAAqB,EAAE,eAAe,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAC/L,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,OAAO,sBAAsB;IAC/B,uCAAuC;IAChC,MAAM,CAAC,KAAK,CAAC,KAAa;QAC7B,MAAM,SAAS,GAAG,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,uBAAuB;QAClE,MAAM,OAAO,GAAG,SAAS,CAAC,UAAU,EAAE,CAAC,CAAC,aAAa;QAErD,QAAQ;QACR,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAEhD,sCAAsC;QACtC,IAAI,MAAM,CAAC,QAAQ,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,mCAAmC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,iBAAiB,MAAM,CAAC,QAAQ,4EAA4E,CAAC,CAAC;QACnM,CAAC;QAED,OAAO,MAAM,CAAC,KAAK,CAAC;IACxB,CAAC;IAED,uCAAuC;IAChC,MAAM,CAAC,eAAe,CAAC,OAAiB,EAAE,KAAa;QAC1D,IAAI,GAAG,GAAG,KAAK,CAAC;QAChB,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,SAAS,EAAE,CAAC;YAC5C,MAAM,IAAI,KAAK,CAAC,4BAA4B,GAAG,iDAAiD,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;QAC5H,CAAC;QACD,GAAG,EAAE,CAAC;QACN,IAAI,SAAS,GAA6B,IAAI,CAAC;QAC/C,IAAI,KAAK,GAAyB,IAAI,CAAC;QACvC,IAAI,SAAS,GAA2B,IAAI,CAAC;QAC7C,IAAI,GAAG,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,cAAc,EAAE,CAAC;YAChE,MAAM,eAAe,GAAG,iBAAiB,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YACxE,SAAS,GAAG,eAAe,CAAC,KAAK,CAAC;YAClC,GAAG,GAAG,eAAe,CAAC,QAAQ,CAAC;QACnC,CAAC;QACD,IAAI,GAAG,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;YAC5D,MAAM,WAAW,GAAG,mBAAmB,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YACtE,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC;YAC1B,GAAG,GAAG,WAAW,CAAC,QAAQ,CAAC;QAC/B,CAAC;QACD,yCAAyC;QACzC,IAAI,GAAG,GAAG,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;YACtE,MAAM,eAAe,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YAC1D,SAAS,GAAG,eAAe,CAAC,KAAK,CAAC;YAClC,GAAG,GAAG,eAAe,CAAC,QAAQ,CAAC;QACnC,CAAC;QACD,IAAI,GAAG,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,UAAU,EAAE,CAAC;YACtE,MAAM,IAAI,KAAK,CAAC,4BAA4B,GAAG,wHAAwH,CAAC,CAAC;QAC7K,CAAC;QACD,mBAAmB;QACnB,GAAG,EAAE,CAAC;QAEN,OAAO,EAAE,KAAK,EAAE,IAAI,qBAAqB,CAAC,SAAS,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;IAC5F,CAAC;IAEO,MAAM,CAAC,kBAAkB,CAAC,KAAa;QAC3C,MAAM,UAAU,GAAG,KAAK,CAAC;QACzB,OAAO,UAAU,KAAK,MAAM,IAAI,UAAU,KAAK,OAAO,IAAI,UAAU,KAAK,QAAQ,CAAC;IACtF,CAAC;IAEO,MAAM,CAAC,cAAc,CAAC,OAAiB,EAAE,KAAa;QAC1D,IAAI,GAAG,GAAG,KAAK,CAAC;QAEhB,2CAA2C;QAC3C,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;QACxC,IAAI,SAA0B,CAAC;QAE/B,QAAQ,YAAY,EAAE,CAAC;YACnB,KAAK,MAAM;gBACP,SAAS,GAAG,eAAe,CAAC,IAAI,CAAC;gBACjC,MAAM;YACV,KAAK,OAAO;gBACR,SAAS,GAAG,eAAe,CAAC,KAAK,CAAC;gBAClC,MAAM;YACV,KAAK,QAAQ;gBACT,SAAS,GAAG,eAAe,CAAC,MAAM,CAAC;gBACnC,MAAM;YACV;gBACI,MAAM,IAAI,KAAK,CAAC,4BAA4B,GAAG,yBAAyB,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,0CAA0C,CAAC,CAAC;QAC9I,CAAC;QACD,GAAG,EAAE,CAAC;QAEN,uCAAuC;QACvC,IAAI,GAAG,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAC3D,6BAA6B;YAC7B,GAAG,EAAE,CAAC;YAEN,uBAAuB;YACvB,MAAM,gBAAgB,GAAG,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YAC/D,MAAM,UAAU,GAAG,gBAAgB,CAAC,KAAK,CAAC;YAC1C,GAAG,GAAG,gBAAgB,CAAC,QAAQ,CAAC;YAEhC,4FAA4F;YAC5F,IAAI,GAAG,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,EAAE,CAAC;gBAC1D,MAAM,IAAI,KAAK,CAAC,4BAA4B,GAAG,6CAA6C,CAAC,CAAC;YAClG,CAAC;YACD,GAAG,EAAE,CAAC,CAAC,WAAW;YAElB,qBAAqB;YACrB,MAAM,cAAc,GAAG,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YAC7D,MAAM,QAAQ,GAAG,cAAc,CAAC,KAAK,CAAC;YACtC,GAAG,GAAG,cAAc,CAAC,QAAQ,CAAC;YAE9B,OAAO;gBACH,KAAK,EAAE,IAAI,eAAe,CAAC,SAAS,EAAE,UAAU,EAAE,QAAQ,CAAC;gBAC3D,QAAQ,EAAE,GAAG;aAChB,CAAC;QACN,CAAC;aAAM,CAAC;YACJ,gCAAgC;YAChC,MAAM,cAAc,GAAG,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YAC7D,MAAM,UAAU,GAAG,cAAc,CAAC,KAAK,CAAC;YACxC,GAAG,GAAG,cAAc,CAAC,QAAQ,CAAC;YAE9B,OAAO;gBACH,KAAK,EAAE,IAAI,eAAe,CAAC,SAAS,EAAE,UAAU,EAAE,IAAI,CAAC;gBACvD,QAAQ,EAAE,GAAG;aAChB,CAAC;QACN,CAAC;IACL,CAAC;IAEO,MAAM,CAAC,kBAAkB,CAAC,OAAiB,EAAE,KAAa;QAC9D,IAAI,GAAG,GAAG,KAAK,CAAC;QAChB,kCAAkC;QAClC,IAAI,GAAG,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,OAAO,EAAE,CAAC;YAClE,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;YACxC,IAAI,UAA4B,CAAC;YACjC,QAAQ,YAAY,EAAE,CAAC;gBACnB,KAAK,aAAa;oBACd,UAAU,GAAG,gBAAgB,CAAC,UAAU,CAAC;oBACzC,MAAM;gBACV,KAAK,qBAAqB;oBACtB,UAAU,GAAG,gBAAgB,CAAC,kBAAkB,CAAC;oBACjD,MAAM;gBACV,KAAK,qBAAqB;oBACtB,UAAU,GAAG,gBAAgB,CAAC,kBAAkB,CAAC;oBACjD,MAAM;gBACV;oBACI,MAAM,IAAI,KAAK,CAAC,4BAA4B,GAAG,yBAAyB,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,0CAA0C,CAAC,CAAC;YAC9I,CAAC;YACD,MAAM,KAAK,GAAG,IAAI,sBAAsB,CAAC,UAAU,CAAC,CAAC;YACrD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC,EAAE,CAAC;QAC/C,CAAC;aAAM,IAAI,GAAG,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,OAAO,EAAE,CAAC;YACzE,kCAAkC;YAClC,MAAM,WAAW,GAAG,WAAW,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YAC9D,GAAG,GAAG,WAAW,CAAC,QAAQ,CAAC;YAC3B,gDAAgD;YAChD,IAAI,GAAG,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,OAAO,EAAE,CAAC;gBAClE,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;gBACrC,IAAI,WAAoB,CAAC;gBACzB,IAAI,SAAS,KAAK,WAAW,EAAE,CAAC;oBAC5B,WAAW,GAAG,KAAK,CAAC;gBACxB,CAAC;qBAAM,IAAI,SAAS,KAAK,WAAW,EAAE,CAAC;oBACnC,WAAW,GAAG,IAAI,CAAC;gBACvB,CAAC;qBAAM,CAAC;oBACJ,MAAM,IAAI,KAAK,CAAC,4BAA4B,GAAG,qFAAqF,CAAC,CAAC;gBAC1I,CAAC;gBACD,GAAG,EAAE,CAAC;gBACN,MAAM,KAAK,GAAG,IAAI,wBAAwB,CAAC,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;gBAC3E,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;YAC3C,CAAC;iBAAM,CAAC;gBACJ,MAAM,IAAI,KAAK,CAAC,4BAA4B,GAAG,qFAAqF,CAAC,CAAC;YAC1I,CAAC;QACL,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,4BAA4B,GAAG,8CAA8C,CAAC,CAAC;IACnG,CAAC;CACJ"}
|
@@ -0,0 +1,53 @@
|
|
1
|
+
import { WithClause } from "../models/Clause";
|
2
|
+
import { TokenType } from "../models/Lexeme";
|
3
|
+
import { SqlTokenizer } from "./SqlTokenizer";
|
4
|
+
import { CommonTableParser } from "./CommonTableParser";
|
5
|
+
export class WithClauseParser {
|
6
|
+
// Parse SQL string to AST (was: parse)
|
7
|
+
static parse(query) {
|
8
|
+
const tokenizer = new SqlTokenizer(query); // Initialize tokenizer
|
9
|
+
const lexemes = tokenizer.readLexmes(); // Get tokens
|
10
|
+
// Parse
|
11
|
+
const result = this.parseFromLexeme(lexemes, 0);
|
12
|
+
// Error if there are remaining tokens
|
13
|
+
if (result.newIndex < lexemes.length) {
|
14
|
+
throw new Error(`Syntax error: Unexpected token "${lexemes[result.newIndex].value}" at position ${result.newIndex}. The WITH clause is complete but there are additional tokens.`);
|
15
|
+
}
|
16
|
+
return result.value;
|
17
|
+
}
|
18
|
+
// Parse from lexeme array (was: parse)
|
19
|
+
static parseFromLexeme(lexemes, index) {
|
20
|
+
let idx = index;
|
21
|
+
// Expect WITH keyword
|
22
|
+
if (idx < lexemes.length && lexemes[idx].value.toLowerCase() === "with") {
|
23
|
+
idx++;
|
24
|
+
}
|
25
|
+
else {
|
26
|
+
throw new Error(`Syntax error at position ${idx}: Expected WITH keyword.`);
|
27
|
+
}
|
28
|
+
// Check for RECURSIVE keyword
|
29
|
+
const recursive = idx < lexemes.length && lexemes[idx].value.toLowerCase() === "recursive";
|
30
|
+
if (recursive) {
|
31
|
+
idx++;
|
32
|
+
}
|
33
|
+
// Parse CTEs
|
34
|
+
const tables = [];
|
35
|
+
// Parse first CTE (required)
|
36
|
+
const firstCte = CommonTableParser.parseFromLexeme(lexemes, idx);
|
37
|
+
tables.push(firstCte.value);
|
38
|
+
idx = firstCte.newIndex;
|
39
|
+
// Parse additional CTEs (optional)
|
40
|
+
while (idx < lexemes.length && lexemes[idx].type === TokenType.Comma) {
|
41
|
+
idx++; // Skip comma
|
42
|
+
const cteResult = CommonTableParser.parseFromLexeme(lexemes, idx);
|
43
|
+
tables.push(cteResult.value);
|
44
|
+
idx = cteResult.newIndex;
|
45
|
+
}
|
46
|
+
// Create WITH clause
|
47
|
+
return {
|
48
|
+
value: new WithClause(recursive, tables),
|
49
|
+
newIndex: idx
|
50
|
+
};
|
51
|
+
}
|
52
|
+
}
|
53
|
+
//# sourceMappingURL=WithClauseParser.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"WithClauseParser.js","sourceRoot":"","sources":["../../../src/parsers/WithClauseParser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAU,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,OAAO,gBAAgB;IACzB,uCAAuC;IAChC,MAAM,CAAC,KAAK,CAAC,KAAa;QAC7B,MAAM,SAAS,GAAG,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,uBAAuB;QAClE,MAAM,OAAO,GAAG,SAAS,CAAC,UAAU,EAAE,CAAC,CAAC,aAAa;QAErD,QAAQ;QACR,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAEhD,sCAAsC;QACtC,IAAI,MAAM,CAAC,QAAQ,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,mCAAmC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,iBAAiB,MAAM,CAAC,QAAQ,gEAAgE,CAAC,CAAC;QACvL,CAAC;QAED,OAAO,MAAM,CAAC,KAAK,CAAC;IACxB,CAAC;IAED,uCAAuC;IAChC,MAAM,CAAC,eAAe,CAAC,OAAiB,EAAE,KAAa;QAC1D,IAAI,GAAG,GAAG,KAAK,CAAC;QAEhB,sBAAsB;QACtB,IAAI,GAAG,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,MAAM,EAAE,CAAC;YACtE,GAAG,EAAE,CAAC;QACV,CAAC;aAAM,CAAC;YACJ,MAAM,IAAI,KAAK,CAAC,4BAA4B,GAAG,0BAA0B,CAAC,CAAC;QAC/E,CAAC;QAED,8BAA8B;QAC9B,MAAM,SAAS,GAAG,GAAG,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,WAAW,CAAC;QAC3F,IAAI,SAAS,EAAE,CAAC;YACZ,GAAG,EAAE,CAAC;QACV,CAAC;QAED,aAAa;QACb,MAAM,MAAM,GAAkB,EAAE,CAAC;QAEjC,6BAA6B;QAC7B,MAAM,QAAQ,GAAG,iBAAiB,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QACjE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC5B,GAAG,GAAG,QAAQ,CAAC,QAAQ,CAAC;QAExB,mCAAmC;QACnC,OAAO,GAAG,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,KAAK,EAAE,CAAC;YACnE,GAAG,EAAE,CAAC,CAAC,aAAa;YACpB,MAAM,SAAS,GAAG,iBAAiB,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YAClE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YAC7B,GAAG,GAAG,SAAS,CAAC,QAAQ,CAAC;QAC7B,CAAC;QAED,qBAAqB;QACrB,OAAO;YACH,KAAK,EAAE,IAAI,UAAU,CAAC,SAAS,EAAE,MAAM,CAAC;YACxC,QAAQ,EAAE,GAAG;SAChB,CAAC;IACN,CAAC;CACJ"}
|
@@ -0,0 +1,78 @@
|
|
1
|
+
import { TokenType } from '../models/Lexeme';
|
2
|
+
import { StringUtils } from '../utils/stringUtils';
|
3
|
+
/**
|
4
|
+
* Base class for token readers
|
5
|
+
*/
|
6
|
+
export class BaseTokenReader {
|
7
|
+
constructor(input, position = 0) {
|
8
|
+
this.input = input;
|
9
|
+
this.position = position;
|
10
|
+
}
|
11
|
+
/**
|
12
|
+
* Get the current position in the input
|
13
|
+
*/
|
14
|
+
getPosition() {
|
15
|
+
return this.position;
|
16
|
+
}
|
17
|
+
/**
|
18
|
+
* Set the position in the input
|
19
|
+
*/
|
20
|
+
setPosition(position) {
|
21
|
+
this.position = position;
|
22
|
+
}
|
23
|
+
/**
|
24
|
+
* Check if we've reached the end of input
|
25
|
+
*/
|
26
|
+
isEndOfInput(shift = 0) {
|
27
|
+
return this.position + shift >= this.input.length;
|
28
|
+
}
|
29
|
+
/**
|
30
|
+
* Check if we can read more characters
|
31
|
+
*/
|
32
|
+
canRead(shift = 0) {
|
33
|
+
return !this.isEndOfInput(shift);
|
34
|
+
}
|
35
|
+
/**
|
36
|
+
* Read an expected character
|
37
|
+
*/
|
38
|
+
read(expectChar) {
|
39
|
+
if (this.isEndOfInput()) {
|
40
|
+
throw new Error(`Unexpected character. expect: ${expectChar}, actual: EndOfInput, position: ${this.position}`);
|
41
|
+
}
|
42
|
+
if (this.input[this.position] !== expectChar) {
|
43
|
+
throw new Error(`Unexpected character. expect: ${expectChar}, actual: ${this.input[this.position]}, position: ${this.position}`);
|
44
|
+
}
|
45
|
+
const char = this.input[this.position];
|
46
|
+
this.position++;
|
47
|
+
return char;
|
48
|
+
}
|
49
|
+
/**
|
50
|
+
* Create a lexeme with the specified type and value
|
51
|
+
*/
|
52
|
+
createLexeme(type, value, maybeType = null, comments = null) {
|
53
|
+
if (type === TokenType.Command || type === TokenType.Operator || type === TokenType.Function) {
|
54
|
+
// Benchmark tests showed that directly calling toLowerCase() is ~5x faster
|
55
|
+
// than first checking if the string is already lowercase.
|
56
|
+
// See benchmarks/lowercase-benchmark.js for detailed performance analysis.
|
57
|
+
return {
|
58
|
+
type,
|
59
|
+
value: value.toLowerCase(),
|
60
|
+
comments: comments,
|
61
|
+
maybeType: maybeType,
|
62
|
+
};
|
63
|
+
}
|
64
|
+
return {
|
65
|
+
type,
|
66
|
+
value,
|
67
|
+
comments: comments,
|
68
|
+
maybeType: maybeType,
|
69
|
+
};
|
70
|
+
}
|
71
|
+
/**
|
72
|
+
* Get debug info for error reporting
|
73
|
+
*/
|
74
|
+
getDebugPositionInfo(errPosition) {
|
75
|
+
return StringUtils.getDebugPositionInfo(this.input, errPosition);
|
76
|
+
}
|
77
|
+
}
|
78
|
+
//# sourceMappingURL=BaseTokenReader.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"BaseTokenReader.js","sourceRoot":"","sources":["../../../src/tokenReaders/BaseTokenReader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD;;GAEG;AACH,MAAM,OAAgB,eAAe;IAIjC,YAAY,KAAa,EAAE,WAAmB,CAAC;QAC3C,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC7B,CAAC;IAED;;OAEG;IACI,WAAW;QACd,OAAO,IAAI,CAAC,QAAQ,CAAC;IACzB,CAAC;IAED;;OAEG;IACI,WAAW,CAAC,QAAgB;QAC/B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC7B,CAAC;IAED;;OAEG;IACO,YAAY,CAAC,QAAgB,CAAC;QACpC,OAAO,IAAI,CAAC,QAAQ,GAAG,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;IACtD,CAAC;IAED;;OAEG;IACO,OAAO,CAAC,QAAgB,CAAC;QAC/B,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC;IAED;;OAEG;IACO,IAAI,CAAC,UAAkB;QAC7B,IAAI,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,iCAAiC,UAAU,mCAAmC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QACnH,CAAC;QAED,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,UAAU,EAAE,CAAC;YAC3C,MAAM,IAAI,KAAK,CAAC,iCAAiC,UAAU,aAAa,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,eAAe,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QACrI,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvC,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC;IAChB,CAAC;IAED;;OAEG;IACO,YAAY,CAAC,IAAe,EAAE,KAAa,EAAE,YAA4B,IAAI,EAAE,WAA4B,IAAI;QACrH,IAAI,IAAI,KAAK,SAAS,CAAC,OAAO,IAAI,IAAI,KAAK,SAAS,CAAC,QAAQ,IAAI,IAAI,KAAK,SAAS,CAAC,QAAQ,EAAE,CAAC;YAC3F,2EAA2E;YAC3E,0DAA0D;YAC1D,2EAA2E;YAC3E,OAAO;gBACH,IAAI;gBACJ,KAAK,EAAE,KAAK,CAAC,WAAW,EAAE;gBAC1B,QAAQ,EAAE,QAAQ;gBAClB,SAAS,EAAE,SAAS;aACvB,CAAC;QACN,CAAC;QACD,OAAO;YACH,IAAI;YACJ,KAAK;YACL,QAAQ,EAAE,QAAQ;YAClB,SAAS,EAAE,SAAS;SACvB,CAAC;IACN,CAAC;IAED;;OAEG;IACO,oBAAoB,CAAC,WAAmB;QAC9C,OAAO,WAAW,CAAC,oBAAoB,CAAC,IAAI,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IACrE,CAAC;CAQJ"}
|
@@ -0,0 +1,141 @@
|
|
1
|
+
import { BaseTokenReader } from "./BaseTokenReader";
|
2
|
+
import { TokenType } from '../models/Lexeme';
|
3
|
+
import { KeywordTrie } from "../models/KeywordTrie";
|
4
|
+
import { KeywordParser } from "../parsers/KeywordParser";
|
5
|
+
// Commands are those that require a dedicated parser.
|
6
|
+
// Keywords composed of multiple words are also considered commands.
|
7
|
+
// The exception is "type". Since types can be user-defined and cannot be accurately identified, they are treated as Identifiers.
|
8
|
+
const joinTrie = new KeywordTrie([
|
9
|
+
["join"],
|
10
|
+
["inner", "join"],
|
11
|
+
["cross", "join"],
|
12
|
+
["left", "join"],
|
13
|
+
["left", "outer", "join"],
|
14
|
+
["right", "join"],
|
15
|
+
["right", "outer", "join"],
|
16
|
+
["full", "join"],
|
17
|
+
["full", "outer", "join"],
|
18
|
+
["natural", "join"],
|
19
|
+
["natural", "inner", "join"],
|
20
|
+
["natural", "left", "join"],
|
21
|
+
["natural", "left", "outer", "join"],
|
22
|
+
["natural", "right", "join"],
|
23
|
+
["natural", "right", "outer", "join"],
|
24
|
+
["natural", "full", "join"],
|
25
|
+
["natural", "full", "outer", "join"],
|
26
|
+
]);
|
27
|
+
const keywordTrie = new KeywordTrie([
|
28
|
+
["with"],
|
29
|
+
["recursive"],
|
30
|
+
["materialized"],
|
31
|
+
["not", "materialized"],
|
32
|
+
["select"],
|
33
|
+
["from"],
|
34
|
+
["distinct"],
|
35
|
+
["distinct", "on"],
|
36
|
+
["where"],
|
37
|
+
["group", "by"],
|
38
|
+
["having"],
|
39
|
+
["order", "by"],
|
40
|
+
["limit"],
|
41
|
+
["offset"],
|
42
|
+
// for
|
43
|
+
["for"],
|
44
|
+
["update"],
|
45
|
+
["share"],
|
46
|
+
["key", "share"],
|
47
|
+
["no", "key", "update"],
|
48
|
+
// set operations
|
49
|
+
["union"],
|
50
|
+
["union", "all"],
|
51
|
+
["intersect"],
|
52
|
+
["intersect", "all"],
|
53
|
+
["except"],
|
54
|
+
["except", "all"],
|
55
|
+
// between and
|
56
|
+
["beteen"],
|
57
|
+
// window functions
|
58
|
+
["window"],
|
59
|
+
["over"],
|
60
|
+
["partition", "by"],
|
61
|
+
["range"],
|
62
|
+
["range"],
|
63
|
+
["rows"],
|
64
|
+
["groups"],
|
65
|
+
["groups"],
|
66
|
+
// window frame
|
67
|
+
["current", "row"],
|
68
|
+
["unbounded", "preceding"],
|
69
|
+
["unbounded", "following"],
|
70
|
+
["preceding"],
|
71
|
+
["following"],
|
72
|
+
// table join commands
|
73
|
+
["on"],
|
74
|
+
["using"],
|
75
|
+
["lateral"],
|
76
|
+
// case
|
77
|
+
["case"],
|
78
|
+
["case", "when"],
|
79
|
+
["when"],
|
80
|
+
["then"],
|
81
|
+
["else"],
|
82
|
+
["end"],
|
83
|
+
// others
|
84
|
+
["insert", "into"],
|
85
|
+
["update"],
|
86
|
+
["delete", "from"],
|
87
|
+
["merge", "into"],
|
88
|
+
["matched"],
|
89
|
+
["not", "matched"],
|
90
|
+
["update", "set"],
|
91
|
+
["do", "nothing"],
|
92
|
+
["values"],
|
93
|
+
["set"],
|
94
|
+
["returning"],
|
95
|
+
["create", "table"],
|
96
|
+
["create", "temporary", "table"],
|
97
|
+
["tablesample"],
|
98
|
+
["array"],
|
99
|
+
// cast
|
100
|
+
["as"],
|
101
|
+
// odrder
|
102
|
+
["asc"],
|
103
|
+
["desc"],
|
104
|
+
["nulls", "first"],
|
105
|
+
["nulls", "last"],
|
106
|
+
]);
|
107
|
+
const keywordParser = new KeywordParser(keywordTrie);
|
108
|
+
export const joinkeywordParser = new KeywordParser(joinTrie);
|
109
|
+
export class CommandTokenReader extends BaseTokenReader {
|
110
|
+
tryRead(previous) {
|
111
|
+
if (this.isEndOfInput()) {
|
112
|
+
return null;
|
113
|
+
}
|
114
|
+
const keywordJoin = joinkeywordParser.parse(this.input, this.position);
|
115
|
+
if (keywordJoin !== null) {
|
116
|
+
this.position = keywordJoin.newPosition;
|
117
|
+
return this.createLexeme(TokenType.Command, keywordJoin.keyword);
|
118
|
+
}
|
119
|
+
// Check for keyword identifiers
|
120
|
+
const keyword = keywordParser.parse(this.input, this.position);
|
121
|
+
if (keyword !== null) {
|
122
|
+
this.position = keyword.newPosition;
|
123
|
+
return this.createLexeme(TokenType.Command, keyword.keyword);
|
124
|
+
}
|
125
|
+
// check hint clause
|
126
|
+
if (this.canRead(2) && this.input[this.position] === '/' && this.input[this.position + 1] === '*' && this.input[this.position + 2] === '+') {
|
127
|
+
this.position += 3;
|
128
|
+
const start = this.position;
|
129
|
+
while (this.position + 1 < this.input.length) {
|
130
|
+
if (this.input[this.position] === '*' && this.input[this.position + 1] === '/') {
|
131
|
+
this.position += 2;
|
132
|
+
return this.createLexeme(TokenType.Command, '/*+ ' + this.input.slice(start, this.position - 2).trim() + ' */');
|
133
|
+
}
|
134
|
+
this.position++;
|
135
|
+
}
|
136
|
+
throw new Error(`Block comment is not closed. position: ${this.position}`);
|
137
|
+
}
|
138
|
+
return null;
|
139
|
+
}
|
140
|
+
}
|
141
|
+
//# sourceMappingURL=CommandTokenReader.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"CommandTokenReader.js","sourceRoot":"","sources":["../../../src/tokenReaders/CommandTokenReader.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1,41 @@
|
|
1
|
+
import { BaseTokenReader } from './BaseTokenReader';
|
2
|
+
import { TokenType } from '../models/Lexeme';
|
3
|
+
import { StringUtils } from '../utils/stringUtils';
|
4
|
+
import { KeywordTrie } from '../models/KeywordTrie';
|
5
|
+
import { KeywordParser } from '../parsers/KeywordParser';
|
6
|
+
const trie = new KeywordTrie([
|
7
|
+
["grouping", "sets"],
|
8
|
+
]);
|
9
|
+
const keywordParser = new KeywordParser(trie);
|
10
|
+
/**
|
11
|
+
* Reads SQL identifier tokens
|
12
|
+
*/
|
13
|
+
export class FunctionTokenReader extends BaseTokenReader {
|
14
|
+
/**
|
15
|
+
* Try to read an identifier token
|
16
|
+
*/
|
17
|
+
tryRead(previous) {
|
18
|
+
if (this.isEndOfInput()) {
|
19
|
+
return null;
|
20
|
+
}
|
21
|
+
// Check for keyword identifiers
|
22
|
+
const keyword = keywordParser.parse(this.input, this.position);
|
23
|
+
if (keyword !== null) {
|
24
|
+
this.position = keyword.newPosition;
|
25
|
+
return this.createLexeme(TokenType.Function, keyword.keyword);
|
26
|
+
}
|
27
|
+
// Regular identifier
|
28
|
+
const result = StringUtils.tryReadRegularIdentifier(this.input, this.position);
|
29
|
+
if (!result) {
|
30
|
+
return null;
|
31
|
+
}
|
32
|
+
this.position = result.newPosition;
|
33
|
+
// peek next token
|
34
|
+
var shift = StringUtils.readWhiteSpaceAndComment(this.input, this.position).position - this.position;
|
35
|
+
if (this.canRead(shift) && this.input[this.position + shift] === '(') {
|
36
|
+
return this.createLexeme(TokenType.Function, result.identifier);
|
37
|
+
}
|
38
|
+
return null;
|
39
|
+
}
|
40
|
+
}
|
41
|
+
//# sourceMappingURL=FunctionTokenReader.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"FunctionTokenReader.js","sourceRoot":"","sources":["../../../src/tokenReaders/FunctionTokenReader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAU,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEzD,MAAM,IAAI,GAAG,IAAI,WAAW,CAAC;IACzB,CAAC,UAAU,EAAE,MAAM,CAAC;CACvB,CAAC,CAAC;AACH,MAAM,aAAa,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC;AAE9C;;GAEG;AACH,MAAM,OAAO,mBAAoB,SAAQ,eAAe;IACpD;;OAEG;IACI,OAAO,CAAC,QAAuB;QAClC,IAAI,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC;YACtB,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,gCAAgC;QAChC,MAAM,OAAO,GAAG,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC/D,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACnB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,WAAW,CAAC;YACpC,OAAO,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QAClE,CAAC;QAED,qBAAqB;QACrB,MAAM,MAAM,GAAG,WAAW,CAAC,wBAAwB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC/E,IAAI,CAAC,MAAM,EAAE,CAAC;YACV,OAAO,IAAI,CAAC;QAChB,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC;QAEnC,mBAAmB;QACnB,IAAI,KAAK,GAAG,WAAW,CAAC,wBAAwB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAErG,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC;YACnE,OAAO,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;QACpE,CAAC;QACD,OAAO,IAAI,CAAC;IAChB,CAAC;CACJ"}
|
@@ -0,0 +1,66 @@
|
|
1
|
+
import { BaseTokenReader } from './BaseTokenReader';
|
2
|
+
import { TokenType } from '../models/Lexeme';
|
3
|
+
import { StringUtils } from '../utils/stringUtils';
|
4
|
+
/**
|
5
|
+
* Reads SQL identifier tokens
|
6
|
+
*/
|
7
|
+
export class IdentifierTokenReader extends BaseTokenReader {
|
8
|
+
/**
|
9
|
+
* Try to read an identifier token
|
10
|
+
*/
|
11
|
+
tryRead(previous) {
|
12
|
+
if (this.isEndOfInput()) {
|
13
|
+
return null;
|
14
|
+
}
|
15
|
+
const char = this.input[this.position];
|
16
|
+
// wildcard identifier
|
17
|
+
if (char === '*') {
|
18
|
+
// Assume that the OperatorTokenReader is executed before the IdentifierTokenReader.
|
19
|
+
// Since we have determined that the OperatorTokenReader is not an Operator,
|
20
|
+
// we treat '*' here as a wildcard identifier.
|
21
|
+
this.position++;
|
22
|
+
return this.createLexeme(TokenType.Identifier, char);
|
23
|
+
}
|
24
|
+
// MySQL escaped identifier (escape character is backtick)
|
25
|
+
if (char === '`') {
|
26
|
+
const identifier = this.readEscapedIdentifier('`');
|
27
|
+
return this.createLexeme(TokenType.Identifier, identifier);
|
28
|
+
}
|
29
|
+
// Postgres escaped identifier (escape character is double quote)
|
30
|
+
if (char === '"') {
|
31
|
+
const identifier = this.readEscapedIdentifier('"');
|
32
|
+
return this.createLexeme(TokenType.Identifier, identifier);
|
33
|
+
}
|
34
|
+
// SQLServer escaped identifier (escape character is square bracket)
|
35
|
+
if (char === '[' && (previous === null || previous.value !== "array")) {
|
36
|
+
const identifier = this.readEscapedIdentifier(']');
|
37
|
+
return this.createLexeme(TokenType.Identifier, identifier);
|
38
|
+
}
|
39
|
+
// Regular identifier
|
40
|
+
const result = StringUtils.readRegularIdentifier(this.input, this.position);
|
41
|
+
this.position = result.newPosition;
|
42
|
+
return this.createLexeme(TokenType.Identifier, result.identifier);
|
43
|
+
}
|
44
|
+
/**
|
45
|
+
* Read an escaped identifier (surrounded by delimiters)
|
46
|
+
*/
|
47
|
+
readEscapedIdentifier(delimiter) {
|
48
|
+
const start = this.position;
|
49
|
+
// Skip the opening delimiter
|
50
|
+
this.position++;
|
51
|
+
while (this.canRead()) {
|
52
|
+
if (this.input[this.position] === delimiter) {
|
53
|
+
break;
|
54
|
+
}
|
55
|
+
this.position++;
|
56
|
+
}
|
57
|
+
if (start === this.position) {
|
58
|
+
throw new Error(`Closing delimiter is not found. position: ${start}, delimiter: ${delimiter}\n${this.getDebugPositionInfo(start)}}`);
|
59
|
+
}
|
60
|
+
// Skip the closing delimiter
|
61
|
+
this.position++;
|
62
|
+
// exclude the delimiter
|
63
|
+
return this.input.slice(start + 1, this.position - 1);
|
64
|
+
}
|
65
|
+
}
|
66
|
+
//# sourceMappingURL=IdentifierTokenReader.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"IdentifierTokenReader.js","sourceRoot":"","sources":["../../../src/tokenReaders/IdentifierTokenReader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAU,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD;;GAEG;AACH,MAAM,OAAO,qBAAsB,SAAQ,eAAe;IACtD;;OAEG;IACI,OAAO,CAAC,QAAuB;QAClC,IAAI,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC;YACtB,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAEvC,sBAAsB;QACtB,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACf,oFAAoF;YACpF,4EAA4E;YAC5E,8CAA8C;YAC9C,IAAI,CAAC,QAAQ,EAAE,CAAC;YAChB,OAAO,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACzD,CAAC;QAED,0DAA0D;QAC1D,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACf,MAAM,UAAU,GAAG,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC;YACnD,OAAO,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QAC/D,CAAC;QAED,iEAAiE;QACjE,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACf,MAAM,UAAU,GAAG,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC;YACnD,OAAO,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QAC/D,CAAC;QAED,oEAAoE;QACpE,IAAI,IAAI,KAAK,GAAG,IAAI,CAAC,QAAQ,KAAK,IAAI,IAAI,QAAQ,CAAC,KAAK,KAAK,OAAO,CAAC,EAAE,CAAC;YACpE,MAAM,UAAU,GAAG,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC;YACnD,OAAO,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QAC/D,CAAC;QAED,qBAAqB;QACrB,MAAM,MAAM,GAAG,WAAW,CAAC,qBAAqB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5E,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC;QACnC,OAAO,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IACtE,CAAC;IAED;;OAEG;IACK,qBAAqB,CAAC,SAAiB;QAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC;QAE5B,6BAA6B;QAC7B,IAAI,CAAC,QAAQ,EAAE,CAAC;QAEhB,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;YACpB,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,SAAS,EAAE,CAAC;gBAC1C,MAAM;YACV,CAAC;YACD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACpB,CAAC;QAED,IAAI,KAAK,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,6CAA6C,KAAK,gBAAgB,SAAS,KAAK,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACzI,CAAC;QAED,6BAA6B;QAC7B,IAAI,CAAC,QAAQ,EAAE,CAAC;QAEhB,wBAAwB;QACxB,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,EAAE,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;IAC1D,CAAC;CACJ"}
|