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,73 @@
|
|
1
|
+
import { NullsSortDirection, OrderByClause, OrderByItem, SortDirection } from "../models/Clause";
|
2
|
+
import { TokenType } from "../models/Lexeme";
|
3
|
+
import { SqlTokenizer } from "./SqlTokenizer";
|
4
|
+
import { ValueParser } from "./ValueParser";
|
5
|
+
export class OrderByClauseParser {
|
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 ORDER BY 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 !== 'order by') {
|
22
|
+
throw new Error(`Syntax error at position ${idx}: Expected 'ORDER BY' keyword but found "${lexemes[idx].value}". ORDER BY clauses must start with the ORDER BY keywords.`);
|
23
|
+
}
|
24
|
+
idx++;
|
25
|
+
const items = [];
|
26
|
+
const item = this.parseItem(lexemes, idx);
|
27
|
+
items.push(item.value);
|
28
|
+
idx = item.newIndex;
|
29
|
+
while (idx < lexemes.length && lexemes[idx].type === TokenType.Comma) {
|
30
|
+
idx++;
|
31
|
+
const item = this.parseItem(lexemes, idx);
|
32
|
+
items.push(item.value);
|
33
|
+
idx = item.newIndex;
|
34
|
+
}
|
35
|
+
if (items.length === 0) {
|
36
|
+
throw new Error(`Syntax error at position ${index}: No ordering expressions found. The ORDER BY clause requires at least one expression to order by.`);
|
37
|
+
}
|
38
|
+
else {
|
39
|
+
const clause = new OrderByClause(items);
|
40
|
+
return { value: clause, newIndex: idx };
|
41
|
+
}
|
42
|
+
}
|
43
|
+
static parseItem(lexemes, index) {
|
44
|
+
let idx = index;
|
45
|
+
const parsedValue = ValueParser.parseFromLexeme(lexemes, idx);
|
46
|
+
const value = parsedValue.value;
|
47
|
+
idx = parsedValue.newIndex;
|
48
|
+
if (idx >= lexemes.length) {
|
49
|
+
return { value: value, newIndex: idx };
|
50
|
+
}
|
51
|
+
// asc, desc
|
52
|
+
const sortDirection = idx >= lexemes.length
|
53
|
+
? null
|
54
|
+
: lexemes[idx].value === 'asc'
|
55
|
+
? (idx++, SortDirection.Ascending)
|
56
|
+
: lexemes[idx].value === 'desc'
|
57
|
+
? (idx++, SortDirection.Descending)
|
58
|
+
: null;
|
59
|
+
// nulls first, nulls last
|
60
|
+
const nullsSortDirection = idx >= lexemes.length
|
61
|
+
? null
|
62
|
+
: lexemes[idx].value === 'nulls first'
|
63
|
+
? (idx++, NullsSortDirection.First)
|
64
|
+
: lexemes[idx].value === 'nulls last'
|
65
|
+
? (idx++, NullsSortDirection.Last)
|
66
|
+
: null;
|
67
|
+
if (sortDirection === null && nullsSortDirection === null) {
|
68
|
+
return { value: value, newIndex: idx };
|
69
|
+
}
|
70
|
+
return { value: new OrderByItem(value, sortDirection, nullsSortDirection), newIndex: idx };
|
71
|
+
}
|
72
|
+
}
|
73
|
+
//# sourceMappingURL=OrderByClauseParser.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"OrderByClauseParser.js","sourceRoot":"","sources":["../../../src/parsers/OrderByClauseParser.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1,40 @@
|
|
1
|
+
import { TokenType } from "../models/Lexeme";
|
2
|
+
import { IdentifierString } from "../models/ValueComponent";
|
3
|
+
import { SqlTokenizer } from "./SqlTokenizer";
|
4
|
+
import { WindowExpressionParser } from "./WindowExpressionParser";
|
5
|
+
export class OverExpressionParser {
|
6
|
+
static parse(query) {
|
7
|
+
const tokenizer = new SqlTokenizer(query); // Initialize tokenizer
|
8
|
+
const lexemes = tokenizer.readLexmes(); // Get tokens
|
9
|
+
// Parse
|
10
|
+
const result = this.parseFromLexeme(lexemes, 0);
|
11
|
+
// Error if there are remaining tokens
|
12
|
+
if (result.newIndex < lexemes.length) {
|
13
|
+
throw new Error(`Syntax error: Unexpected token "${lexemes[result.newIndex].value}" at position ${result.newIndex}. The OVER expression is complete but there are additional tokens.`);
|
14
|
+
}
|
15
|
+
return result.value;
|
16
|
+
}
|
17
|
+
static parseFromLexeme(lexemes, index) {
|
18
|
+
let idx = index;
|
19
|
+
if (lexemes[idx].value !== 'over') {
|
20
|
+
throw new Error(`Syntax error at position ${idx}: Expected 'OVER' keyword but found "${lexemes[idx].value}". OVER expressions must start with the OVER keyword.`);
|
21
|
+
}
|
22
|
+
idx++;
|
23
|
+
if (idx >= lexemes.length) {
|
24
|
+
throw new Error(`Syntax error: Unexpected end of input after 'OVER' keyword. Expected either a window name or an opening parenthesis '('.`);
|
25
|
+
}
|
26
|
+
if (lexemes[idx].type === TokenType.Identifier) {
|
27
|
+
// named window frame
|
28
|
+
const name = lexemes[idx].value;
|
29
|
+
idx++;
|
30
|
+
return { value: new IdentifierString(name), newIndex: idx };
|
31
|
+
}
|
32
|
+
if (lexemes[idx].type === TokenType.OpenParen) {
|
33
|
+
// Delegate processing to WindowFrameExpressionParser
|
34
|
+
const result = WindowExpressionParser.parseFromLexeme(lexemes, idx);
|
35
|
+
return result;
|
36
|
+
}
|
37
|
+
throw new Error(`Syntax error at position ${idx}: Expected a window name or opening parenthesis '(' after OVER keyword, but found "${lexemes[idx].value}".`);
|
38
|
+
}
|
39
|
+
}
|
40
|
+
//# sourceMappingURL=OverExpressionParser.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"OverExpressionParser.js","sourceRoot":"","sources":["../../../src/parsers/OverExpressionParser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAkB,MAAM,0BAA0B,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAElE,MAAM,OAAO,oBAAoB;IACtB,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,oEAAoE,CAAC,CAAC;QAC3L,CAAC;QAED,OAAO,MAAM,CAAC,KAAK,CAAC;IACxB,CAAC;IAEM,MAAM,CAAC,eAAe,CAAC,OAAiB,EAAE,KAAa;QAC1D,IAAI,GAAG,GAAG,KAAK,CAAC;QAEhB,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,MAAM,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,4BAA4B,GAAG,wCAAwC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,uDAAuD,CAAC,CAAC;QACtK,CAAC;QACD,GAAG,EAAE,CAAC;QAEN,IAAI,GAAG,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,0HAA0H,CAAC,CAAC;QAChJ,CAAC;QAED,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,UAAU,EAAE,CAAC;YAC7C,qBAAqB;YACrB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;YAChC,GAAG,EAAE,CAAC;YACN,OAAO,EAAE,KAAK,EAAE,IAAI,gBAAgB,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;QAChE,CAAC;QAED,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,SAAS,EAAE,CAAC;YAC5C,qDAAqD;YACrD,MAAM,MAAM,GAAG,sBAAsB,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YACpE,OAAO,MAAM,CAAC;QAClB,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,4BAA4B,GAAG,sFAAsF,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;IACjK,CAAC;CACJ"}
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import { ParameterExpression } from "../models/ValueComponent";
|
2
|
+
export class ParameterExpressionParser {
|
3
|
+
static parseFromLexeme(lexemes, index) {
|
4
|
+
let idx = index;
|
5
|
+
// Exclude the parameter symbol (first character)
|
6
|
+
const value = new ParameterExpression(lexemes[idx].value.slice(1));
|
7
|
+
idx++;
|
8
|
+
return { value, newIndex: idx };
|
9
|
+
}
|
10
|
+
}
|
11
|
+
//# sourceMappingURL=ParameterExpressionParser.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"ParameterExpressionParser.js","sourceRoot":"","sources":["../../../src/parsers/ParameterExpressionParser.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAkB,MAAM,0BAA0B,CAAC;AAE/E,MAAM,OAAO,yBAAyB;IAC3B,MAAM,CAAC,eAAe,CAAC,OAAiB,EAAE,KAAa;QAC1D,IAAI,GAAG,GAAG,KAAK,CAAC;QAChB,iDAAiD;QACjD,MAAM,KAAK,GAAG,IAAI,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACnE,GAAG,EAAE,CAAC;QACN,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;IACpC,CAAC;CACJ"}
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import { TokenType } from "../models/Lexeme";
|
2
|
+
import { InlineQuery, ParenExpression } from "../models/ValueComponent";
|
3
|
+
import { SelectQueryParser } from "./SelectQueryParser";
|
4
|
+
import { ValueParser } from "./ValueParser";
|
5
|
+
export class ParenExpressionParser {
|
6
|
+
static parseFromLexeme(lexemes, index) {
|
7
|
+
let idx = index;
|
8
|
+
// check inline query
|
9
|
+
if (idx + 1 < lexemes.length && lexemes[idx].type === TokenType.OpenParen && (lexemes[idx + 1].value === "select" || lexemes[idx + 1].value === "values" || lexemes[idx + 1].value === "with")) {
|
10
|
+
idx += 1; // Skip the '(' token
|
11
|
+
const result = SelectQueryParser.parseFromLexeme(lexemes, idx);
|
12
|
+
idx = result.newIndex;
|
13
|
+
// Check for closing parenthesis
|
14
|
+
if (idx >= lexemes.length || lexemes[idx].type !== TokenType.CloseParen) {
|
15
|
+
throw new Error(`Expected ')' at index ${idx}, but found ${lexemes[idx].value}`);
|
16
|
+
}
|
17
|
+
idx++; // Skip the ')' token
|
18
|
+
const value = new InlineQuery(result.value);
|
19
|
+
return { value, newIndex: idx };
|
20
|
+
}
|
21
|
+
else {
|
22
|
+
const result = ValueParser.parseArgument(TokenType.OpenParen, TokenType.CloseParen, lexemes, index);
|
23
|
+
idx = result.newIndex;
|
24
|
+
const value = new ParenExpression(result.value);
|
25
|
+
return { value, newIndex: idx };
|
26
|
+
}
|
27
|
+
}
|
28
|
+
}
|
29
|
+
//# sourceMappingURL=ParenExpressionParser.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"ParenExpressionParser.js","sourceRoot":"","sources":["../../../src/parsers/ParenExpressionParser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,eAAe,EAAkB,MAAM,0BAA0B,CAAC;AACxF,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,OAAO,qBAAqB;IACvB,MAAM,CAAC,eAAe,CAAC,OAAiB,EAAE,KAAa;QAC1D,IAAI,GAAG,GAAG,KAAK,CAAC;QAEhB,qBAAqB;QACrB,IAAI,GAAG,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,SAAS,IAAI,CACzE,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,KAAK,QAAQ,IAAI,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,KAAK,QAAQ,IAAI,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,KAAK,MAAM,CAClH,EAAE,CAAC;YACA,GAAG,IAAI,CAAC,CAAC,CAAC,qBAAqB;YAC/B,MAAM,MAAM,GAAG,iBAAiB,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YAC/D,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC;YAEtB,gCAAgC;YAChC,IAAI,GAAG,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,UAAU,EAAE,CAAC;gBACtE,MAAM,IAAI,KAAK,CAAC,yBAAyB,GAAG,eAAe,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;YACrF,CAAC;YACD,GAAG,EAAE,CAAC,CAAC,qBAAqB;YAE5B,MAAM,KAAK,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC5C,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;QACpC,CAAC;aAAM,CAAC;YACJ,MAAM,MAAM,GAAG,WAAW,CAAC,aAAa,CAAC,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC,UAAU,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;YACpG,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC;YAEtB,MAAM,KAAK,GAAG,IAAI,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAChD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;QACpC,CAAC;IACL,CAAC;CACJ"}
|
@@ -0,0 +1,49 @@
|
|
1
|
+
import { PartitionByClause } from "../models/Clause";
|
2
|
+
import { TokenType } from "../models/Lexeme";
|
3
|
+
import { ValueList } from "../models/ValueComponent";
|
4
|
+
import { SqlTokenizer } from "./SqlTokenizer";
|
5
|
+
import { ValueParser } from "./ValueParser";
|
6
|
+
export class PartitionByParser {
|
7
|
+
// Parse SQL string to AST (was: parse)
|
8
|
+
static parse(query) {
|
9
|
+
const tokenizer = new SqlTokenizer(query); // Initialize tokenizer
|
10
|
+
const lexemes = tokenizer.readLexmes(); // Get tokens
|
11
|
+
// Parse
|
12
|
+
const result = this.parseFromLexeme(lexemes, 0);
|
13
|
+
// Error if there are remaining tokens
|
14
|
+
if (result.newIndex < lexemes.length) {
|
15
|
+
throw new Error(`Syntax error: Unexpected token "${lexemes[result.newIndex].value}" at position ${result.newIndex}. The PARTITION BY clause is complete but there are additional tokens.`);
|
16
|
+
}
|
17
|
+
return result.value;
|
18
|
+
}
|
19
|
+
// Parse from lexeme array (was: parse)
|
20
|
+
static parseFromLexeme(lexemes, index) {
|
21
|
+
let idx = index;
|
22
|
+
if (lexemes[idx].value !== 'partition by') {
|
23
|
+
throw new Error(`Syntax error at position ${idx}: Expected 'PARTITION BY' keyword but found "${lexemes[idx].value}". PARTITION BY clauses must start with the PARTITION BY keywords.`);
|
24
|
+
}
|
25
|
+
idx++;
|
26
|
+
const items = [];
|
27
|
+
const item = ValueParser.parseFromLexeme(lexemes, idx);
|
28
|
+
items.push(item.value);
|
29
|
+
idx = item.newIndex;
|
30
|
+
while (idx < lexemes.length && lexemes[idx].type === TokenType.Comma) {
|
31
|
+
idx++;
|
32
|
+
const item = ValueParser.parseFromLexeme(lexemes, idx);
|
33
|
+
items.push(item.value);
|
34
|
+
idx = item.newIndex;
|
35
|
+
}
|
36
|
+
if (items.length === 0) {
|
37
|
+
throw new Error(`Syntax error at position ${index}: No partition expressions found. The PARTITION BY clause requires at least one expression to partition by.`);
|
38
|
+
}
|
39
|
+
else if (items.length === 1) {
|
40
|
+
const clause = new PartitionByClause(items[0]);
|
41
|
+
return { value: clause, newIndex: idx };
|
42
|
+
}
|
43
|
+
else {
|
44
|
+
const clause = new PartitionByClause(new ValueList(items));
|
45
|
+
return { value: clause, newIndex: idx };
|
46
|
+
}
|
47
|
+
}
|
48
|
+
}
|
49
|
+
//# sourceMappingURL=PartitionByParser.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"PartitionByParser.js","sourceRoot":"","sources":["../../../src/parsers/PartitionByParser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAU,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAkB,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,OAAO,iBAAiB;IAC1B,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,wEAAwE,CAAC,CAAC;QAC/L,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,KAAK,KAAK,cAAc,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CAAC,4BAA4B,GAAG,gDAAgD,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,oEAAoE,CAAC,CAAC;QAC3L,CAAC;QACD,GAAG,EAAE,CAAC;QACN,MAAM,KAAK,GAAqB,EAAE,CAAC;QACnC,MAAM,IAAI,GAAG,WAAW,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QACvD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvB,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC;QACpB,OAAO,GAAG,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,KAAK,EAAE,CAAC;YACnE,GAAG,EAAE,CAAC;YACN,MAAM,IAAI,GAAG,WAAW,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YACvD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACvB,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC;QACxB,CAAC;QACD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,4BAA4B,KAAK,6GAA6G,CAAC,CAAC;QACpK,CAAC;aAAM,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5B,MAAM,MAAM,GAAG,IAAI,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YAC/C,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;QAC5C,CAAC;aAAM,CAAC;YACJ,MAAM,MAAM,GAAG,IAAI,iBAAiB,CAAC,IAAI,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;YAC3D,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;QAC5C,CAAC;IACL,CAAC;CACJ"}
|
@@ -0,0 +1,80 @@
|
|
1
|
+
import { Distinct, DistinctOn, SelectClause, SelectItem } from "../models/Clause";
|
2
|
+
import { TokenType } from "../models/Lexeme";
|
3
|
+
import { SqlTokenizer } from "./SqlTokenizer";
|
4
|
+
import { ValueParser } from "./ValueParser";
|
5
|
+
export class SelectClauseParser {
|
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 SELECT 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
|
+
let distinct = null;
|
22
|
+
if (lexemes[idx].value !== 'select') {
|
23
|
+
throw new Error(`Syntax error at position ${idx}: Expected 'SELECT' keyword but found "${lexemes[idx].value}". SELECT clauses must start with the SELECT keyword.`);
|
24
|
+
}
|
25
|
+
idx++;
|
26
|
+
if (idx < lexemes.length && lexemes[idx].value === 'distinct') {
|
27
|
+
idx++;
|
28
|
+
distinct = new Distinct();
|
29
|
+
}
|
30
|
+
else if (idx < lexemes.length && lexemes[idx].value === 'distinct on') {
|
31
|
+
idx++;
|
32
|
+
const argument = ValueParser.parseArgument(TokenType.OpenParen, TokenType.CloseParen, lexemes, idx);
|
33
|
+
distinct = new DistinctOn(argument.value);
|
34
|
+
idx = argument.newIndex;
|
35
|
+
}
|
36
|
+
const items = [];
|
37
|
+
const item = this.parseItem(lexemes, idx);
|
38
|
+
items.push(item.value);
|
39
|
+
idx = item.newIndex;
|
40
|
+
while (idx < lexemes.length && lexemes[idx].type === TokenType.Comma) {
|
41
|
+
idx++;
|
42
|
+
const item = this.parseItem(lexemes, idx);
|
43
|
+
items.push(item.value);
|
44
|
+
idx = item.newIndex;
|
45
|
+
}
|
46
|
+
if (items.length === 0) {
|
47
|
+
throw new Error(`Syntax error at position ${index}: No select items found. The SELECT clause requires at least one expression to select.`);
|
48
|
+
}
|
49
|
+
else {
|
50
|
+
const clause = new SelectClause(items, distinct);
|
51
|
+
return { value: clause, newIndex: idx };
|
52
|
+
}
|
53
|
+
}
|
54
|
+
static parseItem(lexemes, index) {
|
55
|
+
let idx = index;
|
56
|
+
const parsedValue = ValueParser.parseFromLexeme(lexemes, idx);
|
57
|
+
const value = parsedValue.value;
|
58
|
+
idx = parsedValue.newIndex;
|
59
|
+
if (idx < lexemes.length && lexemes[idx].value === 'as') {
|
60
|
+
// Skip 'AS' keyword
|
61
|
+
idx++;
|
62
|
+
}
|
63
|
+
if (idx < lexemes.length && lexemes[idx].type === TokenType.Identifier) {
|
64
|
+
const alias = lexemes[idx].value;
|
65
|
+
idx++;
|
66
|
+
return {
|
67
|
+
value: new SelectItem(value, alias),
|
68
|
+
newIndex: idx,
|
69
|
+
};
|
70
|
+
}
|
71
|
+
else {
|
72
|
+
// alias nameless
|
73
|
+
return {
|
74
|
+
value,
|
75
|
+
newIndex: idx,
|
76
|
+
};
|
77
|
+
}
|
78
|
+
}
|
79
|
+
}
|
80
|
+
//# sourceMappingURL=SelectClauseParser.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"SelectClauseParser.js","sourceRoot":"","sources":["../../../src/parsers/SelectClauseParser.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1,149 @@
|
|
1
|
+
import { BinarySelectQuery, SimpleSelectQuery } from "../models/SelectQuery";
|
2
|
+
import { SelectClauseParser } from "./SelectClauseParser";
|
3
|
+
import { FromClauseParser } from "./FromClauseParser";
|
4
|
+
import { WhereClauseParser } from "./WhereClauseParser";
|
5
|
+
import { GroupByClauseParser } from "./GroupByParser";
|
6
|
+
import { HavingClauseParser } from "./HavingParser";
|
7
|
+
import { OrderByClauseParser } from "./OrderByClauseParser";
|
8
|
+
import { WindowClauseParser } from "./WindowClauseParser";
|
9
|
+
import { LimitClauseParser } from "./LimitClauseParser";
|
10
|
+
import { ForClauseParser } from "./ForClauseParser";
|
11
|
+
import { SqlTokenizer } from "./SqlTokenizer";
|
12
|
+
import { WithClauseParser } from "./WithClauseParser";
|
13
|
+
import { ValuesQueryParser } from "./ValuesQueryParser";
|
14
|
+
export class SelectQueryParser {
|
15
|
+
// Parse SQL string to AST (was: parse)
|
16
|
+
static parse(query) {
|
17
|
+
const tokenizer = new SqlTokenizer(query);
|
18
|
+
const lexemes = tokenizer.readLexmes();
|
19
|
+
// Parse
|
20
|
+
const result = this.parseFromLexeme(lexemes, 0);
|
21
|
+
// Error if there are remaining tokens
|
22
|
+
if (result.newIndex < lexemes.length) {
|
23
|
+
throw new Error(`Syntax error: Unexpected token "${lexemes[result.newIndex].value}" at position ${result.newIndex}. The SELECT query is complete but there are additional tokens.`);
|
24
|
+
}
|
25
|
+
return result.value;
|
26
|
+
}
|
27
|
+
// Parse from lexeme array (was: parse)
|
28
|
+
static parseFromLexeme(lexemes, index) {
|
29
|
+
let idx = index;
|
30
|
+
if (idx >= lexemes.length) {
|
31
|
+
throw new Error(`Syntax error: Unexpected end of input at position ${index}.`);
|
32
|
+
}
|
33
|
+
// Check if the first token is a SELECT keyword or VALUES
|
34
|
+
const firstToken = lexemes[idx].value;
|
35
|
+
if (!this.selectCommandSet.has(firstToken) && firstToken !== 'values') {
|
36
|
+
throw new Error(`Syntax error at position ${idx}: Expected 'SELECT' or 'VALUES' keyword but found "${lexemes[idx].value}".`);
|
37
|
+
}
|
38
|
+
let firstResult = this.selectCommandSet.has(firstToken)
|
39
|
+
? this.parseSimpleSelectQuery(lexemes, idx)
|
40
|
+
: this.parseValuesQuery(lexemes, idx);
|
41
|
+
let query = firstResult.value;
|
42
|
+
idx = firstResult.newIndex;
|
43
|
+
// check 'union'
|
44
|
+
while (idx < lexemes.length && this.unionCommandSet.has(lexemes[idx].value.toLowerCase())) {
|
45
|
+
const operator = lexemes[idx].value.toLowerCase();
|
46
|
+
idx++;
|
47
|
+
if (idx >= lexemes.length) {
|
48
|
+
throw new Error(`Syntax error at position ${idx}: Expected a query after '${operator.toUpperCase()}' but found end of input.`);
|
49
|
+
}
|
50
|
+
const nextToken = lexemes[idx].value.toLowerCase();
|
51
|
+
if (this.selectCommandSet.has(nextToken)) {
|
52
|
+
const result = this.parseSimpleSelectQuery(lexemes, idx);
|
53
|
+
query = new BinarySelectQuery(query, operator, result.value);
|
54
|
+
idx = result.newIndex;
|
55
|
+
}
|
56
|
+
else if (nextToken === 'values') {
|
57
|
+
const result = this.parseValuesQuery(lexemes, idx);
|
58
|
+
query = new BinarySelectQuery(query, operator, result.value);
|
59
|
+
idx = result.newIndex;
|
60
|
+
}
|
61
|
+
else {
|
62
|
+
throw new Error(`Syntax error at position ${idx}: Expected 'SELECT' or 'VALUES' after '${operator.toUpperCase()}' but found "${lexemes[idx].value}".`);
|
63
|
+
}
|
64
|
+
}
|
65
|
+
return { value: query, newIndex: idx };
|
66
|
+
}
|
67
|
+
static parseSimpleSelectQuery(lexemes, index) {
|
68
|
+
let idx = index;
|
69
|
+
let withClauseResult = null;
|
70
|
+
// Parse optional WITH clause
|
71
|
+
if (idx < lexemes.length && lexemes[idx].value.toLowerCase() === 'with') {
|
72
|
+
withClauseResult = WithClauseParser.parseFromLexeme(lexemes, idx);
|
73
|
+
idx = withClauseResult.newIndex;
|
74
|
+
}
|
75
|
+
// Parse SELECT clause (required)
|
76
|
+
if (idx >= lexemes.length || lexemes[idx].value.toLowerCase() !== 'select') {
|
77
|
+
throw new Error(`Syntax error at position ${idx}: Expected 'SELECT' keyword but found "${idx < lexemes.length ? lexemes[idx].value : 'end of input'}". SELECT queries must start with the SELECT keyword.`);
|
78
|
+
}
|
79
|
+
const selectClauseResult = SelectClauseParser.parseFromLexeme(lexemes, idx);
|
80
|
+
idx = selectClauseResult.newIndex;
|
81
|
+
// Parse FROM clause (optional)
|
82
|
+
let fromClauseResult = null;
|
83
|
+
if (idx < lexemes.length && lexemes[idx].value.toLowerCase() === 'from') {
|
84
|
+
fromClauseResult = FromClauseParser.parseFromLexeme(lexemes, idx);
|
85
|
+
idx = fromClauseResult.newIndex;
|
86
|
+
}
|
87
|
+
// Parse WHERE clause (optional)
|
88
|
+
let whereClauseResult = null;
|
89
|
+
if (idx < lexemes.length && lexemes[idx].value.toLowerCase() === 'where') {
|
90
|
+
whereClauseResult = WhereClauseParser.parseFromLexeme(lexemes, idx);
|
91
|
+
idx = whereClauseResult.newIndex;
|
92
|
+
}
|
93
|
+
// Parse GROUP BY clause (optional)
|
94
|
+
let groupByClauseResult = null;
|
95
|
+
if (idx < lexemes.length && lexemes[idx].value.toLowerCase() === 'group by') {
|
96
|
+
groupByClauseResult = GroupByClauseParser.parseFromLexeme(lexemes, idx);
|
97
|
+
idx = groupByClauseResult.newIndex;
|
98
|
+
}
|
99
|
+
// Parse HAVING clause (optional)
|
100
|
+
let havingClauseResult = null;
|
101
|
+
if (idx < lexemes.length && lexemes[idx].value.toLowerCase() === 'having') {
|
102
|
+
havingClauseResult = HavingClauseParser.parseFromLexeme(lexemes, idx);
|
103
|
+
idx = havingClauseResult.newIndex;
|
104
|
+
}
|
105
|
+
// Parse WINDOW clause (optional)
|
106
|
+
let windowFrameClauseResult = null;
|
107
|
+
if (idx < lexemes.length && lexemes[idx].value.toLowerCase() === 'window') {
|
108
|
+
windowFrameClauseResult = WindowClauseParser.parseFromLexeme(lexemes, idx);
|
109
|
+
idx = windowFrameClauseResult.newIndex;
|
110
|
+
}
|
111
|
+
// Parse ORDER BY clause (optional)
|
112
|
+
let orderByClauseResult = null;
|
113
|
+
if (idx < lexemes.length && lexemes[idx].value.toLowerCase() === 'order by') {
|
114
|
+
orderByClauseResult = OrderByClauseParser.parseFromLexeme(lexemes, idx);
|
115
|
+
idx = orderByClauseResult.newIndex;
|
116
|
+
}
|
117
|
+
// Parse LIMIT clause (optional)
|
118
|
+
let limitClauseResult = null;
|
119
|
+
if (idx < lexemes.length && lexemes[idx].value.toLowerCase() === 'limit') {
|
120
|
+
limitClauseResult = LimitClauseParser.parseFromLexeme(lexemes, idx);
|
121
|
+
idx = limitClauseResult.newIndex;
|
122
|
+
}
|
123
|
+
// Parse FOR clause (optional)
|
124
|
+
let forClauseResult = null;
|
125
|
+
if (idx < lexemes.length && lexemes[idx].value.toLowerCase() === 'for') {
|
126
|
+
forClauseResult = ForClauseParser.parseFromLexeme(lexemes, idx);
|
127
|
+
idx = forClauseResult.newIndex;
|
128
|
+
}
|
129
|
+
// Create and return the SelectQuery object
|
130
|
+
const selectQuery = new SimpleSelectQuery(withClauseResult ? withClauseResult.value : null, selectClauseResult.value, fromClauseResult ? fromClauseResult.value : null, whereClauseResult ? whereClauseResult.value : null, groupByClauseResult ? groupByClauseResult.value : null, havingClauseResult ? havingClauseResult.value : null, orderByClauseResult ? orderByClauseResult.value : null, windowFrameClauseResult ? windowFrameClauseResult.value : null, limitClauseResult ? limitClauseResult.value : null, forClauseResult ? forClauseResult.value : null);
|
131
|
+
return { value: selectQuery, newIndex: idx };
|
132
|
+
}
|
133
|
+
static parseValuesQuery(lexemes, index) {
|
134
|
+
// Use ValuesQueryParser to parse VALUES clause
|
135
|
+
const result = ValuesQueryParser.parseFromLexeme(lexemes, index);
|
136
|
+
// Return the result from ValuesQueryParser directly
|
137
|
+
return { value: result.value, newIndex: result.newIndex };
|
138
|
+
}
|
139
|
+
}
|
140
|
+
SelectQueryParser.unionCommandSet = new Set([
|
141
|
+
"union",
|
142
|
+
"union all",
|
143
|
+
"intersect",
|
144
|
+
"intersect all",
|
145
|
+
"except",
|
146
|
+
"except all",
|
147
|
+
]);
|
148
|
+
SelectQueryParser.selectCommandSet = new Set(["with", "select"]);
|
149
|
+
//# sourceMappingURL=SelectQueryParser.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"SelectQueryParser.js","sourceRoot":"","sources":["../../../src/parsers/SelectQueryParser.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1,45 @@
|
|
1
|
+
import { SourceAliasExpression } from "../models/Clause";
|
2
|
+
import { TokenType } from "../models/Lexeme";
|
3
|
+
export class SourceAliasExpressionParser {
|
4
|
+
// Parse from lexeme array (was: parse)
|
5
|
+
static parseFromLexeme(lexemes, index) {
|
6
|
+
var _a;
|
7
|
+
let idx = index;
|
8
|
+
// If there is a column alias, it may be detected as a function, so functions are also processed.
|
9
|
+
if (idx < lexemes.length && (lexemes[idx].type === TokenType.Identifier || lexemes[idx].type === TokenType.Function)) {
|
10
|
+
// Check for alias
|
11
|
+
const table = lexemes[idx].value;
|
12
|
+
idx++;
|
13
|
+
if (idx < lexemes.length && lexemes[idx].type === TokenType.OpenParen) {
|
14
|
+
// Check for column alias
|
15
|
+
const columns = [];
|
16
|
+
// Skip the open parenthesis
|
17
|
+
idx++;
|
18
|
+
while (idx < lexemes.length && lexemes[idx].type === TokenType.Identifier) {
|
19
|
+
columns.push(lexemes[idx].value);
|
20
|
+
idx++;
|
21
|
+
if (idx < lexemes.length && lexemes[idx].type === TokenType.Comma) {
|
22
|
+
idx++;
|
23
|
+
}
|
24
|
+
else {
|
25
|
+
break; // Exit loop if not a comma
|
26
|
+
}
|
27
|
+
}
|
28
|
+
if (lexemes[idx].type === TokenType.CloseParen) {
|
29
|
+
// Skip the closing parenthesis
|
30
|
+
idx++;
|
31
|
+
}
|
32
|
+
else {
|
33
|
+
throw new Error(`Syntax error at position ${idx}: Missing closing parenthesis ')' for column alias list. Each opening parenthesis must have a matching closing parenthesis.`);
|
34
|
+
}
|
35
|
+
if (columns.length === 0) {
|
36
|
+
throw new Error(`Syntax error at position ${index}: No column aliases found. Column alias declarations must contain at least one column name.`);
|
37
|
+
}
|
38
|
+
return { value: new SourceAliasExpression(table, columns), newIndex: idx };
|
39
|
+
}
|
40
|
+
return { value: new SourceAliasExpression(table, null), newIndex: idx };
|
41
|
+
}
|
42
|
+
throw new Error(`Syntax error at position ${index}: Expected an identifier for table alias but found "${((_a = lexemes[index]) === null || _a === void 0 ? void 0 : _a.value) || 'end of input'}".`);
|
43
|
+
}
|
44
|
+
}
|
45
|
+
//# sourceMappingURL=SourceAliasExpressionParser.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"SourceAliasExpressionParser.js","sourceRoot":"","sources":["../../../src/parsers/SourceAliasExpressionParser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAU,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAGrD,MAAM,OAAO,2BAA2B;IACpC,uCAAuC;IAChC,MAAM,CAAC,eAAe,CAAC,OAAiB,EAAE,KAAa;;QAC1D,IAAI,GAAG,GAAG,KAAK,CAAC;QAEhB,iGAAiG;QACjG,IAAI,GAAG,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;YACnH,kBAAkB;YAClB,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;YACjC,GAAG,EAAE,CAAC;YAEN,IAAI,GAAG,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,SAAS,EAAE,CAAC;gBACpE,yBAAyB;gBACzB,MAAM,OAAO,GAAa,EAAE,CAAC;gBAE7B,4BAA4B;gBAC5B,GAAG,EAAE,CAAC;gBAEN,OAAO,GAAG,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,UAAU,EAAE,CAAC;oBACxE,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;oBACjC,GAAG,EAAE,CAAC;oBACN,IAAI,GAAG,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,KAAK,EAAE,CAAC;wBAChE,GAAG,EAAE,CAAC;oBACV,CAAC;yBAAM,CAAC;wBACJ,MAAM,CAAC,2BAA2B;oBACtC,CAAC;gBACL,CAAC;gBAED,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,UAAU,EAAE,CAAC;oBAC7C,+BAA+B;oBAC/B,GAAG,EAAE,CAAC;gBACV,CAAC;qBAAM,CAAC;oBACJ,MAAM,IAAI,KAAK,CAAC,4BAA4B,GAAG,6HAA6H,CAAC,CAAC;gBAClL,CAAC;gBACD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACvB,MAAM,IAAI,KAAK,CAAC,4BAA4B,KAAK,6FAA6F,CAAC,CAAC;gBACpJ,CAAC;gBAED,OAAO,EAAE,KAAK,EAAE,IAAI,qBAAqB,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;YAC/E,CAAC;YAED,OAAO,EAAE,KAAK,EAAE,IAAI,qBAAqB,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;QAC5E,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,4BAA4B,KAAK,uDAAuD,CAAA,MAAA,OAAO,CAAC,KAAK,CAAC,0CAAE,KAAK,KAAI,cAAc,IAAI,CAAC,CAAC;IACzJ,CAAC;CACJ"}
|
@@ -0,0 +1,31 @@
|
|
1
|
+
import { SourceExpression } from "../models/Clause";
|
2
|
+
import { TokenType } from "../models/Lexeme";
|
3
|
+
import { SourceParser } from "./SourceParser";
|
4
|
+
import { SourceAliasExpressionParser } from "./SourceAliasExpressionParser";
|
5
|
+
export class SourceExpressionParser {
|
6
|
+
// Parse from lexeme array (was: parse)
|
7
|
+
static parseFromLexeme(lexemes, index) {
|
8
|
+
let idx = index;
|
9
|
+
const sourceResult = SourceParser.parseFromLexeme(lexemes, idx);
|
10
|
+
idx = sourceResult.newIndex;
|
11
|
+
if (idx < lexemes.length) {
|
12
|
+
if (lexemes[idx].value === "as") {
|
13
|
+
idx++;
|
14
|
+
const aliasResult = SourceAliasExpressionParser.parseFromLexeme(lexemes, idx);
|
15
|
+
idx = aliasResult.newIndex;
|
16
|
+
const sourceExpr = new SourceExpression(sourceResult.value, aliasResult.value);
|
17
|
+
return { value: sourceExpr, newIndex: idx };
|
18
|
+
}
|
19
|
+
if (lexemes[idx].type === TokenType.Identifier) {
|
20
|
+
const aliasResult = SourceAliasExpressionParser.parseFromLexeme(lexemes, idx);
|
21
|
+
idx = aliasResult.newIndex;
|
22
|
+
const sourceExpr = new SourceExpression(sourceResult.value, aliasResult.value);
|
23
|
+
return { value: sourceExpr, newIndex: idx };
|
24
|
+
}
|
25
|
+
}
|
26
|
+
// no alias
|
27
|
+
const expr = new SourceExpression(sourceResult.value, null);
|
28
|
+
return { value: expr, newIndex: idx };
|
29
|
+
}
|
30
|
+
}
|
31
|
+
//# sourceMappingURL=SourceExpressionParser.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"SourceExpressionParser.js","sourceRoot":"","sources":["../../../src/parsers/SourceExpressionParser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,gBAAgB,EAAe,MAAM,kBAAkB,CAAC;AACxF,OAAO,EAAU,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAE5E,MAAM,OAAO,sBAAsB;IAC/B,uCAAuC;IAChC,MAAM,CAAC,eAAe,CAAC,OAAiB,EAAE,KAAa;QAC1D,IAAI,GAAG,GAAG,KAAK,CAAC;QAEhB,MAAM,YAAY,GAAG,YAAY,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAChE,GAAG,GAAG,YAAY,CAAC,QAAQ,CAAC;QAE5B,IAAI,GAAG,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;YACvB,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;gBAC9B,GAAG,EAAE,CAAC;gBACN,MAAM,WAAW,GAAG,2BAA2B,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;gBAC9E,GAAG,GAAG,WAAW,CAAC,QAAQ,CAAC;gBAC3B,MAAM,UAAU,GAAG,IAAI,gBAAgB,CAAC,YAAY,CAAC,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC;gBAC/E,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;YAChD,CAAC;YAED,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,UAAU,EAAE,CAAC;gBAC7C,MAAM,WAAW,GAAG,2BAA2B,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;gBAC9E,GAAG,GAAG,WAAW,CAAC,QAAQ,CAAC;gBAC3B,MAAM,UAAU,GAAG,IAAI,gBAAgB,CAAC,YAAY,CAAC,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC;gBAC/E,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;YAChD,CAAC;QACL,CAAC;QAED,WAAW;QACX,MAAM,IAAI,GAAG,IAAI,gBAAgB,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAC5D,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;IAC1C,CAAC;CACJ"}
|