rawsql-ts 0.1.0-beta.11 → 0.1.0-beta.14
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 +78 -18
- 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/package.json +4 -1
@@ -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"}
|
@@ -0,0 +1,115 @@
|
|
1
|
+
import { FunctionSource, SubQuerySource, TableSource } from "../models/Clause";
|
2
|
+
import { TokenType } from "../models/Lexeme";
|
3
|
+
import { SelectQueryParser } from "./SelectQueryParser";
|
4
|
+
import { SqlTokenizer } from "./SqlTokenizer";
|
5
|
+
import { ValueParser } from "./ValueParser";
|
6
|
+
export class SourceParser {
|
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 source component 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
|
+
const idx = index;
|
22
|
+
// Handle subquery
|
23
|
+
if (idx < lexemes.length && lexemes[idx].type === TokenType.OpenParen) {
|
24
|
+
return this.parseParenSource(lexemes, idx);
|
25
|
+
}
|
26
|
+
// Handle function-based source
|
27
|
+
if (idx < lexemes.length && lexemes[idx].type === TokenType.Function) {
|
28
|
+
return this.parseFunctionSource(lexemes, idx);
|
29
|
+
}
|
30
|
+
// Handle table source (regular table, potentially schema-qualified)
|
31
|
+
return this.parseTableSource(lexemes, idx);
|
32
|
+
}
|
33
|
+
static parseTableSource(lexemes, index) {
|
34
|
+
// Check for column reference pattern ([identifier dot] * n + identifier)
|
35
|
+
let idx = index;
|
36
|
+
const identifiers = [];
|
37
|
+
// Add the first identifier
|
38
|
+
identifiers.push(lexemes[idx].value);
|
39
|
+
idx++;
|
40
|
+
// Look for dot and identifier pattern
|
41
|
+
while (idx < lexemes.length &&
|
42
|
+
idx + 1 < lexemes.length &&
|
43
|
+
lexemes[idx].type === TokenType.Dot &&
|
44
|
+
lexemes[idx + 1].type === TokenType.Identifier) {
|
45
|
+
// Skip the dot and add the next identifier
|
46
|
+
idx++;
|
47
|
+
identifiers.push(lexemes[idx].value);
|
48
|
+
idx++;
|
49
|
+
}
|
50
|
+
if (identifiers.length > 1) {
|
51
|
+
// If there are multiple identifiers, treat it as a column reference
|
52
|
+
const lastIdentifier = identifiers.pop() || '';
|
53
|
+
const value = new TableSource(identifiers, lastIdentifier);
|
54
|
+
return { value, newIndex: idx };
|
55
|
+
}
|
56
|
+
else {
|
57
|
+
// If there is a single identifier, treat it as a simple identifier
|
58
|
+
const value = new TableSource(null, identifiers[0]);
|
59
|
+
return { value, newIndex: idx };
|
60
|
+
}
|
61
|
+
}
|
62
|
+
static parseFunctionSource(lexemes, index) {
|
63
|
+
let idx = index;
|
64
|
+
const functionName = lexemes[idx].value;
|
65
|
+
idx++;
|
66
|
+
const argument = ValueParser.parseArgument(TokenType.OpenParen, TokenType.CloseParen, lexemes, idx);
|
67
|
+
idx = argument.newIndex;
|
68
|
+
const result = new FunctionSource(functionName, argument.value);
|
69
|
+
return { value: result, newIndex: idx };
|
70
|
+
}
|
71
|
+
static parseParenSource(lexemes, index) {
|
72
|
+
let idx = index;
|
73
|
+
// skip the open parenthesis
|
74
|
+
idx++;
|
75
|
+
if (idx >= lexemes.length) {
|
76
|
+
throw new Error(`Syntax error: Unexpected end of input at position ${idx}. Expected a subquery or nested expression after opening parenthesis.`);
|
77
|
+
}
|
78
|
+
// Support both SELECT and VALUES in subqueries
|
79
|
+
const keyword = lexemes[idx].value;
|
80
|
+
if (keyword === "select" || keyword === "values" || keyword === "with") {
|
81
|
+
const result = this.parseSubQuerySource(lexemes, idx);
|
82
|
+
idx = result.newIndex;
|
83
|
+
if (idx < lexemes.length && lexemes[idx].type == TokenType.CloseParen) {
|
84
|
+
// skip the closing parenthesis
|
85
|
+
idx++;
|
86
|
+
}
|
87
|
+
else {
|
88
|
+
throw new Error(`Syntax error at position ${idx}: Missing closing parenthesis. Each opening parenthesis must have a matching closing parenthesis.`);
|
89
|
+
}
|
90
|
+
return { value: result.value, newIndex: idx };
|
91
|
+
}
|
92
|
+
else if (lexemes[idx].type == TokenType.OpenParen) {
|
93
|
+
const result = this.parseParenSource(lexemes, idx);
|
94
|
+
idx = result.newIndex;
|
95
|
+
if (idx < lexemes.length && lexemes[idx].type == TokenType.CloseParen) {
|
96
|
+
// skip the closing parenthesis
|
97
|
+
idx++;
|
98
|
+
}
|
99
|
+
else {
|
100
|
+
throw new Error(`Syntax error at position ${idx}: Missing closing parenthesis. Each opening parenthesis must have a matching closing parenthesis.`);
|
101
|
+
}
|
102
|
+
return { value: result.value, newIndex: idx };
|
103
|
+
}
|
104
|
+
throw new Error(`Syntax error at position ${idx}: Expected 'SELECT' keyword, 'VALUES' keyword, or opening parenthesis '(' but found "${lexemes[idx].value}".`);
|
105
|
+
}
|
106
|
+
static parseSubQuerySource(lexemes, index) {
|
107
|
+
let idx = index;
|
108
|
+
// Use the new parseFromLexeme method and destructure the result
|
109
|
+
const { value: selectQuery, newIndex } = SelectQueryParser.parseFromLexeme(lexemes, idx);
|
110
|
+
idx = newIndex;
|
111
|
+
const subQuerySource = new SubQuerySource(selectQuery);
|
112
|
+
return { value: subQuerySource, newIndex: idx };
|
113
|
+
}
|
114
|
+
}
|
115
|
+
//# sourceMappingURL=SourceParser.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"SourceParser.js","sourceRoot":"","sources":["../../../src/parsers/SourceParser.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1,170 @@
|
|
1
|
+
import { TokenType } from '../models/Lexeme';
|
2
|
+
import { IdentifierTokenReader } from '../tokenReaders/IdentifierTokenReader';
|
3
|
+
import { LiteralTokenReader } from '../tokenReaders/LiteralTokenReader';
|
4
|
+
import { ParameterTokenReader } from '../tokenReaders/ParameterTokenReader';
|
5
|
+
import { SpecialSymbolTokenReader } from '../tokenReaders/SymbolTokenReader';
|
6
|
+
import { TokenReaderManager } from '../tokenReaders/TokenReaderManager';
|
7
|
+
import { OperatorTokenReader } from '../tokenReaders/OperatorTokenReader';
|
8
|
+
import { StringUtils } from '../utils/stringUtils';
|
9
|
+
import { CommandTokenReader } from '../tokenReaders/CommandTokenReader';
|
10
|
+
import { StringSpecifierTokenReader } from '../tokenReaders/StringSpecifierTokenReader';
|
11
|
+
import { FunctionTokenReader } from '../tokenReaders/FunctionTokenReader';
|
12
|
+
import { TypeTokenReader } from '../tokenReaders/TypeTokenReader';
|
13
|
+
/**
|
14
|
+
* Class responsible for tokenizing SQL input.
|
15
|
+
*/
|
16
|
+
export class SqlTokenizer {
|
17
|
+
/**
|
18
|
+
* Initializes a new instance of the SqlTokenizer.
|
19
|
+
*/
|
20
|
+
constructor(input) {
|
21
|
+
this.input = input;
|
22
|
+
this.position = 0;
|
23
|
+
// Initialize the token reader manager and register all readers
|
24
|
+
this.readerManager = new TokenReaderManager(input)
|
25
|
+
.register(new ParameterTokenReader(input))
|
26
|
+
.register(new StringSpecifierTokenReader(input))
|
27
|
+
// LiteralTokenReader should be registered before SpecialSymbolTokenReader and OperatorTokenReader
|
28
|
+
// Reason: To prevent numeric literals starting with a dot or sign from being misrecognized as operators
|
29
|
+
// e.g. `1.0` is a literal, not an operator
|
30
|
+
.register(new LiteralTokenReader(input))
|
31
|
+
.register(new SpecialSymbolTokenReader(input))
|
32
|
+
.register(new CommandTokenReader(input))
|
33
|
+
.register(new OperatorTokenReader(input))
|
34
|
+
// TypeTokenReader should be registered before FunctionTokenReader
|
35
|
+
// Reason: To prevent types containing parentheses from being misrecognized as functions
|
36
|
+
// e.g. `numeric(10, 2)` is a type, not a function
|
37
|
+
.register(new TypeTokenReader(input))
|
38
|
+
.register(new FunctionTokenReader(input))
|
39
|
+
.register(new IdentifierTokenReader(input)) // IdentifierTokenReader should be registered last
|
40
|
+
;
|
41
|
+
}
|
42
|
+
/**
|
43
|
+
* Checks if the end of input is reached.
|
44
|
+
*
|
45
|
+
* @param shift - The shift to consider beyond the current position.
|
46
|
+
* @returns True if the end of input is reached; otherwise, false.
|
47
|
+
*/
|
48
|
+
isEndOfInput(shift = 0) {
|
49
|
+
return this.position + shift >= this.input.length;
|
50
|
+
}
|
51
|
+
/**
|
52
|
+
* Checks if more input can be read.
|
53
|
+
*
|
54
|
+
* @param shift - The shift to consider beyond the current position.
|
55
|
+
* @returns True if more input can be read; otherwise, false.
|
56
|
+
*/
|
57
|
+
canRead(shift = 0) {
|
58
|
+
return !this.isEndOfInput(shift);
|
59
|
+
}
|
60
|
+
/**
|
61
|
+
* Reads the lexemes from the input string.
|
62
|
+
*
|
63
|
+
* @returns An array of lexemes extracted from the input string.
|
64
|
+
* @throws Error if an unexpected character is encountered.
|
65
|
+
*/
|
66
|
+
readLexmes() {
|
67
|
+
// Pre-allocate array with estimated capacity for better performance
|
68
|
+
const estimatedTokens = Math.ceil(this.input.length / 8); // Assuming average token length of 8 chars
|
69
|
+
const lexemes = new Array(estimatedTokens);
|
70
|
+
let lexemeCount = 0;
|
71
|
+
// Read initial prefix comments
|
72
|
+
const comment = this.readComment();
|
73
|
+
let pendingComments = comment.lines;
|
74
|
+
this.position = comment.position;
|
75
|
+
// Track the previous token
|
76
|
+
let previous = null;
|
77
|
+
// Read tokens until the end of input is reached
|
78
|
+
while (this.canRead()) {
|
79
|
+
// Semicolon is a delimiter, so stop reading
|
80
|
+
if (this.input[this.position] === ';') {
|
81
|
+
break;
|
82
|
+
}
|
83
|
+
// Read using the token reader manager
|
84
|
+
const lexeme = this.readerManager.tryRead(this.position, previous);
|
85
|
+
if (lexeme === null) {
|
86
|
+
throw new Error(`Unexpected character. actual: ${this.input[this.position]}, position: ${this.position}\n${this.getDebugPositionInfo(this.position)}`);
|
87
|
+
}
|
88
|
+
// Update position
|
89
|
+
this.position = this.readerManager.getMaxPosition();
|
90
|
+
// Read suffix comments
|
91
|
+
const currentComment = this.readComment();
|
92
|
+
this.position = currentComment.position;
|
93
|
+
if (lexeme.type === TokenType.Comma || lexeme.type === TokenType.Operator) {
|
94
|
+
// Carry over comments after commas or operators
|
95
|
+
if (currentComment.lines.length > 0) {
|
96
|
+
pendingComments.push(...currentComment.lines);
|
97
|
+
}
|
98
|
+
}
|
99
|
+
else {
|
100
|
+
// Add comments to the current token if any
|
101
|
+
const hasComments = pendingComments.length > 0 || currentComment.lines.length > 0;
|
102
|
+
if (hasComments) {
|
103
|
+
this.addCommentsToToken(lexeme, pendingComments, currentComment.lines);
|
104
|
+
}
|
105
|
+
pendingComments = []; // Clear as they are processed
|
106
|
+
}
|
107
|
+
lexemes[lexemeCount++] = lexeme;
|
108
|
+
previous = lexeme;
|
109
|
+
}
|
110
|
+
// Add any pending comments to the last token
|
111
|
+
if (pendingComments.length > 0 && lexemeCount > 0) {
|
112
|
+
const lastToken = lexemes[lexemeCount - 1];
|
113
|
+
if (lastToken.comments === null) {
|
114
|
+
lastToken.comments = [];
|
115
|
+
}
|
116
|
+
lastToken.comments.push(...pendingComments);
|
117
|
+
}
|
118
|
+
// Trim the array to actual size used
|
119
|
+
return lexemeCount === estimatedTokens ? lexemes : lexemes.slice(0, lexemeCount);
|
120
|
+
}
|
121
|
+
/**
|
122
|
+
* Adds pending comments to the last token.
|
123
|
+
*/
|
124
|
+
addPendingCommentsToLastToken(lexemes, pendingComments) {
|
125
|
+
if (pendingComments.length > 0 && lexemes.length > 0) {
|
126
|
+
const lastToken = lexemes[lexemes.length - 1];
|
127
|
+
if (lastToken.comments === null) {
|
128
|
+
lastToken.comments = [];
|
129
|
+
}
|
130
|
+
lastToken.comments.push(...pendingComments);
|
131
|
+
}
|
132
|
+
}
|
133
|
+
/**
|
134
|
+
* Adds comments to the token.
|
135
|
+
*/
|
136
|
+
addCommentsToToken(lexeme, prefixComments, suffixComments) {
|
137
|
+
const hasComments = prefixComments.length > 0 || suffixComments.length > 0;
|
138
|
+
if (hasComments) {
|
139
|
+
if (lexeme.comments === null) {
|
140
|
+
lexeme.comments = [];
|
141
|
+
}
|
142
|
+
// Add prefix comments to the beginning.
|
143
|
+
if (prefixComments.length > 0) {
|
144
|
+
lexeme.comments.unshift(...prefixComments);
|
145
|
+
}
|
146
|
+
// Add suffix comments to the end.
|
147
|
+
if (suffixComments.length > 0) {
|
148
|
+
lexeme.comments.push(...suffixComments);
|
149
|
+
}
|
150
|
+
}
|
151
|
+
}
|
152
|
+
/**
|
153
|
+
* Skips whitespace characters and SQL comments in the input.
|
154
|
+
*
|
155
|
+
* @remarks This method updates the position pointer.
|
156
|
+
*/
|
157
|
+
readComment() {
|
158
|
+
return StringUtils.readWhiteSpaceAndComment(this.input, this.position);
|
159
|
+
}
|
160
|
+
/**
|
161
|
+
* Gets debug information for error reporting.
|
162
|
+
*
|
163
|
+
* @param errPosition - The position where the error occurred.
|
164
|
+
* @returns A string containing the debug position information.
|
165
|
+
*/
|
166
|
+
getDebugPositionInfo(errPosition) {
|
167
|
+
return StringUtils.getDebugPositionInfo(this.input, errPosition);
|
168
|
+
}
|
169
|
+
}
|
170
|
+
//# sourceMappingURL=SqlTokenizer.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"SqlTokenizer.js","sourceRoot":"","sources":["../../../src/parsers/SqlTokenizer.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
import { TokenType } from "../models/Lexeme";
|
2
|
+
import { StringSpecifierExpression } from "../models/ValueComponent";
|
3
|
+
export class StringSpecifierExpressionParser {
|
4
|
+
static parseFromLexeme(lexemes, index) {
|
5
|
+
let idx = index;
|
6
|
+
const specifer = lexemes[idx].value;
|
7
|
+
idx++;
|
8
|
+
if (idx >= lexemes.length || lexemes[idx].type !== TokenType.Literal) {
|
9
|
+
throw new Error(`Expected string literal after string specifier at index ${idx}`);
|
10
|
+
}
|
11
|
+
const value = lexemes[idx].value;
|
12
|
+
idx++;
|
13
|
+
// Create StringSpecifierExpression
|
14
|
+
const result = new StringSpecifierExpression(specifer, value);
|
15
|
+
return { value: result, newIndex: idx };
|
16
|
+
}
|
17
|
+
}
|
18
|
+
//# sourceMappingURL=StringSpecifierExpressionParser.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"StringSpecifierExpressionParser.js","sourceRoot":"","sources":["../../../src/parsers/StringSpecifierExpressionParser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,yBAAyB,EAAkB,MAAM,0BAA0B,CAAC;AAErF,MAAM,OAAO,+BAA+B;IACjC,MAAM,CAAC,eAAe,CAAC,OAAiB,EAAE,KAAa;QAC1D,IAAI,GAAG,GAAG,KAAK,CAAC;QAChB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;QACpC,GAAG,EAAE,CAAC;QACN,IAAI,GAAG,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,OAAO,EAAE,CAAC;YACnE,MAAM,IAAI,KAAK,CAAC,2DAA2D,GAAG,EAAE,CAAC,CAAC;QACtF,CAAC;QACD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;QACjC,GAAG,EAAE,CAAC;QACN,mCAAmC;QACnC,MAAM,MAAM,GAAG,IAAI,yBAAyB,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAE9D,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;IAC5C,CAAC;CACJ"}
|
@@ -0,0 +1,26 @@
|
|
1
|
+
import { TokenType } from "../models/Lexeme";
|
2
|
+
import { ColumnReference, UnaryExpression } from "../models/ValueComponent";
|
3
|
+
import { ValueParser } from "./ValueParser";
|
4
|
+
export class UnaryExpressionParser {
|
5
|
+
static parseFromLexeme(lexemes, index) {
|
6
|
+
let idx = index;
|
7
|
+
// Process unary operator
|
8
|
+
if (idx < lexemes.length && lexemes[idx].type === TokenType.Operator) {
|
9
|
+
const operator = lexemes[idx].value;
|
10
|
+
idx++;
|
11
|
+
// Treat the asterisk as an Identifier, not as a unary operator
|
12
|
+
if (operator === '*') {
|
13
|
+
const v = new ColumnReference(null, '*');
|
14
|
+
return { value: v, newIndex: idx };
|
15
|
+
}
|
16
|
+
// Get the right-hand side value of the unary operator
|
17
|
+
const result = ValueParser.parseFromLexeme(lexemes, idx);
|
18
|
+
idx = result.newIndex;
|
19
|
+
// Create unary expression
|
20
|
+
const value = new UnaryExpression(operator, result.value);
|
21
|
+
return { value, newIndex: idx };
|
22
|
+
}
|
23
|
+
throw new Error(`Invalid unary expression at index ${index}: ${lexemes[index].value}`);
|
24
|
+
}
|
25
|
+
}
|
26
|
+
//# sourceMappingURL=UnaryExpressionParser.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"UnaryExpressionParser.js","sourceRoot":"","sources":["../../../src/parsers/UnaryExpressionParser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAoB,eAAe,EAAkB,MAAM,0BAA0B,CAAC;AAC9G,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,yBAAyB;QACzB,IAAI,GAAG,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,QAAQ,EAAE,CAAC;YACnE,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;YACpC,GAAG,EAAE,CAAC;YAEN,+DAA+D;YAC/D,IAAI,QAAQ,KAAK,GAAG,EAAE,CAAC;gBACnB,MAAM,CAAC,GAAG,IAAI,eAAe,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;gBACzC,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;YACvC,CAAC;YAED,sDAAsD;YACtD,MAAM,MAAM,GAAG,WAAW,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YACzD,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC;YAEtB,0BAA0B;YAC1B,MAAM,KAAK,GAAG,IAAI,eAAe,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;YAC1D,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;QACpC,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,qCAAqC,KAAK,KAAK,OAAO,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;IAC3F,CAAC;CACJ"}
|