dt-sql-parser 4.0.2 → 4.1.0-beta.1

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.
Files changed (88) hide show
  1. package/README.md +6 -1
  2. package/dist/lib/flink/FlinkSqlLexer.js +1 -2
  3. package/dist/lib/flink/FlinkSqlParser.d.ts +175 -174
  4. package/dist/lib/flink/FlinkSqlParser.js +2315 -2388
  5. package/dist/lib/flink/FlinkSqlParserListener.d.ts +5 -16
  6. package/dist/lib/flink/FlinkSqlParserVisitor.d.ts +3 -10
  7. package/dist/lib/hive/HiveSqlLexer.js +1 -2
  8. package/dist/lib/hive/HiveSqlParser.d.ts +3 -1
  9. package/dist/lib/hive/HiveSqlParser.js +8 -9
  10. package/dist/lib/impala/ImpalaSqlLexer.js +1 -2
  11. package/dist/lib/impala/ImpalaSqlParser.d.ts +123 -107
  12. package/dist/lib/impala/ImpalaSqlParser.js +3223 -3155
  13. package/dist/lib/impala/ImpalaSqlParserListener.d.ts +22 -0
  14. package/dist/lib/impala/ImpalaSqlParserVisitor.d.ts +14 -0
  15. package/dist/lib/mysql/MySqlLexer.js +1 -2
  16. package/dist/lib/mysql/MySqlParser.d.ts +469 -422
  17. package/dist/lib/mysql/MySqlParser.js +11460 -10509
  18. package/dist/lib/mysql/MySqlParserListener.d.ts +33 -11
  19. package/dist/lib/mysql/MySqlParserVisitor.d.ts +21 -7
  20. package/dist/lib/postgresql/PostgreSqlLexer.js +1 -2
  21. package/dist/lib/postgresql/PostgreSqlParser.d.ts +2025 -6265
  22. package/dist/lib/postgresql/PostgreSqlParser.js +60092 -88368
  23. package/dist/lib/postgresql/PostgreSqlParserListener.d.ts +1688 -6083
  24. package/dist/lib/postgresql/PostgreSqlParserVisitor.d.ts +712 -3511
  25. package/dist/lib/spark/SparkSqlLexer.js +1 -2
  26. package/dist/lib/spark/SparkSqlParser.d.ts +16 -13
  27. package/dist/lib/spark/SparkSqlParser.js +50 -51
  28. package/dist/lib/spark/SparkSqlParserListener.d.ts +10 -10
  29. package/dist/lib/spark/SparkSqlParserVisitor.d.ts +6 -6
  30. package/dist/lib/trino/TrinoSqlLexer.d.ts +323 -260
  31. package/dist/lib/trino/TrinoSqlLexer.js +1610 -1264
  32. package/dist/lib/trino/TrinoSqlListener.d.ts +1311 -200
  33. package/dist/lib/trino/TrinoSqlParser.d.ts +1908 -562
  34. package/dist/lib/trino/TrinoSqlParser.js +22629 -13412
  35. package/dist/lib/trino/TrinoSqlVisitor.d.ts +761 -69
  36. package/dist/locale/locale.d.ts +41 -0
  37. package/dist/locale/locale.js +43 -0
  38. package/dist/parser/common/basicSQL.d.ts +9 -4
  39. package/dist/parser/common/basicSQL.js +64 -21
  40. package/dist/parser/common/entityCollector.d.ts +60 -12
  41. package/dist/parser/common/entityCollector.js +141 -17
  42. package/dist/parser/common/parseErrorListener.d.ts +6 -3
  43. package/dist/parser/common/parseErrorListener.js +83 -2
  44. package/dist/parser/common/textAndWord.d.ts +6 -9
  45. package/dist/parser/common/textAndWord.js +9 -20
  46. package/dist/parser/common/transform.d.ts +8 -0
  47. package/dist/parser/common/transform.js +11 -0
  48. package/dist/parser/common/types.d.ts +1 -0
  49. package/dist/parser/flink/flinkEntityCollector.js +40 -6
  50. package/dist/parser/flink/flinkErrorListener.d.ts +9 -0
  51. package/dist/parser/flink/flinkErrorListener.js +67 -0
  52. package/dist/parser/flink/index.d.ts +4 -1
  53. package/dist/parser/flink/index.js +16 -12
  54. package/dist/parser/hive/hiveEntityCollector.js +40 -6
  55. package/dist/parser/hive/hiveErrorListener.d.ts +9 -0
  56. package/dist/parser/hive/hiveErrorListener.js +65 -0
  57. package/dist/parser/hive/index.d.ts +4 -1
  58. package/dist/parser/hive/index.js +16 -12
  59. package/dist/parser/impala/ImpalaErrorListener.d.ts +9 -0
  60. package/dist/parser/impala/ImpalaErrorListener.js +63 -0
  61. package/dist/parser/impala/impalaEntityCollector.js +51 -6
  62. package/dist/parser/impala/index.d.ts +4 -1
  63. package/dist/parser/impala/index.js +7 -3
  64. package/dist/parser/mysql/index.d.ts +4 -1
  65. package/dist/parser/mysql/index.js +7 -3
  66. package/dist/parser/mysql/mysqlEntityCollector.d.ts +3 -1
  67. package/dist/parser/mysql/mysqlEntityCollector.js +40 -5
  68. package/dist/parser/mysql/mysqlErrorListener.d.ts +9 -0
  69. package/dist/parser/mysql/mysqlErrorListener.js +63 -0
  70. package/dist/parser/postgresql/index.d.ts +4 -1
  71. package/dist/parser/postgresql/index.js +20 -16
  72. package/dist/parser/postgresql/postgreEntityCollector.d.ts +5 -1
  73. package/dist/parser/postgresql/postgreEntityCollector.js +44 -4
  74. package/dist/parser/postgresql/postgreErrorListener.d.ts +9 -0
  75. package/dist/parser/postgresql/postgreErrorListener.js +71 -0
  76. package/dist/parser/spark/index.d.ts +4 -1
  77. package/dist/parser/spark/index.js +7 -3
  78. package/dist/parser/spark/sparkEntityCollector.d.ts +1 -1
  79. package/dist/parser/spark/sparkEntityCollector.js +43 -6
  80. package/dist/parser/spark/sparkErrorListener.d.ts +9 -0
  81. package/dist/parser/spark/sparkErrorListener.js +63 -0
  82. package/dist/parser/trino/index.d.ts +4 -1
  83. package/dist/parser/trino/index.js +26 -13
  84. package/dist/parser/trino/trinoEntityCollector.d.ts +6 -4
  85. package/dist/parser/trino/trinoEntityCollector.js +44 -9
  86. package/dist/parser/trino/trinoErrorListener.d.ts +9 -0
  87. package/dist/parser/trino/trinoErrorListener.js +65 -0
  88. package/package.json +35 -11
@@ -0,0 +1,41 @@
1
+ declare const i18n: {
2
+ zh_CN: {
3
+ stmtInComplete: string;
4
+ noValidPosition: string;
5
+ expecting: string;
6
+ unfinishedMultilineComment: string;
7
+ unfinishedDoubleQuoted: string;
8
+ unfinishedSingleQuoted: string;
9
+ unfinishedTickQuoted: string;
10
+ noValidInput: string;
11
+ newObj: string;
12
+ existingObj: string;
13
+ new: string;
14
+ existing: string;
15
+ orKeyword: string;
16
+ keyword: string;
17
+ missing: string;
18
+ at: string;
19
+ or: string;
20
+ };
21
+ en_US: {
22
+ stmtInComplete: string;
23
+ noValidPosition: string;
24
+ expecting: string;
25
+ unfinishedMultilineComment: string;
26
+ unfinishedDoubleQuoted: string;
27
+ unfinishedSingleQuoted: string;
28
+ unfinishedTickQuoted: string;
29
+ noValidInput: string;
30
+ newObj: string;
31
+ existingObj: string;
32
+ new: string;
33
+ existing: string;
34
+ orKeyword: string;
35
+ keyword: string;
36
+ missing: string;
37
+ at: string;
38
+ or: string;
39
+ };
40
+ };
41
+ export { i18n };
@@ -0,0 +1,43 @@
1
+ const zh_CN = {
2
+ stmtInComplete: '语句不完整',
3
+ noValidPosition: '在此位置无效',
4
+ expecting: ',期望',
5
+ unfinishedMultilineComment: '未完成的多行注释',
6
+ unfinishedDoubleQuoted: '未完成的双引号字符串字变量',
7
+ unfinishedSingleQuoted: '未完成的单引号字符串字变量',
8
+ unfinishedTickQuoted: '未完成的反引号引用字符串字变量',
9
+ noValidInput: '没有有效的输入',
10
+ newObj: '一个新的对象',
11
+ existingObj: '一个存在的对象',
12
+ new: '一个新的',
13
+ existing: '一个存在的',
14
+ orKeyword: '或者一个关键字',
15
+ keyword: '一个关键字',
16
+ missing: '缺少',
17
+ at: '在',
18
+ or: '或者',
19
+ };
20
+ const en_US = {
21
+ stmtInComplete: 'Statement is incomplete',
22
+ noValidPosition: 'is not valid at this position',
23
+ expecting: ', expecting ',
24
+ unfinishedMultilineComment: 'Unfinished multiline comment',
25
+ unfinishedDoubleQuoted: 'Unfinished double quoted string literal',
26
+ unfinishedSingleQuoted: 'Unfinished single quoted string literal',
27
+ unfinishedTickQuoted: 'Unfinished back tick quoted string literal',
28
+ noValidInput: 'is no valid input at all',
29
+ newObj: 'a new object',
30
+ existingObj: 'an existing object',
31
+ new: 'a new ',
32
+ existing: 'an existing ',
33
+ orKeyword: ' or a keyword',
34
+ keyword: 'a keyword',
35
+ missing: 'missing ',
36
+ at: ' at ',
37
+ or: ' or ',
38
+ };
39
+ const i18n = {
40
+ zh_CN,
41
+ en_US,
42
+ };
43
+ export { i18n };
@@ -1,8 +1,8 @@
1
- import { Lexer, Token, CommonTokenStream, CharStream, ParserRuleContext, ParseTreeListener } from 'antlr4ng';
1
+ import { Lexer, Token, CommonTokenStream, CharStream, ParserRuleContext, ParseTreeListener, ANTLRErrorListener } from 'antlr4ng';
2
2
  import { CandidatesCollection } from 'antlr4-c3';
3
3
  import { SQLParserBase } from '../../lib/SQLParserBase';
4
4
  import { TextSlice } from './textAndWord';
5
- import { CaretPosition, Suggestions } from './types';
5
+ import { CaretPosition, LOCALE_TYPE, Suggestions } from './types';
6
6
  import { ParseError, ErrorListener } from './parseErrorListener';
7
7
  import type { SplitListener } from './splitListener';
8
8
  import type { EntityCollector } from './entityCollector';
@@ -40,17 +40,21 @@ export declare abstract class BasicSQL<L extends Lexer = Lexer, PRC extends Pars
40
40
  * @param candidates candidate list
41
41
  * @param allTokens all tokens from input
42
42
  * @param caretTokenIndex tokenIndex of caretPosition
43
- * @param tokenIndexOffset offset of the tokenIndex in the candidates compared to the tokenIndex in allTokens
44
43
  */
45
- protected abstract processCandidates(candidates: CandidatesCollection, allTokens: Token[], caretTokenIndex: number, tokenIndexOffset: number): Suggestions<Token>;
44
+ protected abstract processCandidates(candidates: CandidatesCollection, allTokens: Token[], caretTokenIndex: number): Suggestions<Token>;
46
45
  /**
47
46
  * Get a new splitListener instance.
48
47
  */
49
48
  protected abstract get splitListener(): SplitListener<ParserRuleContext>;
49
+ /**
50
+ * Get a new errorListener instance.
51
+ */
52
+ protected abstract createErrorListener(errorListener: ErrorListener): ANTLRErrorListener;
50
53
  /**
51
54
  * Get a new entityCollector instance.
52
55
  */
53
56
  protected abstract createEntityCollector(input: string, caretTokenIndex?: number): EntityCollector;
57
+ locale: LOCALE_TYPE;
54
58
  /**
55
59
  * Create an antlr4 lexer from input.
56
60
  * @param input string
@@ -106,6 +110,7 @@ export declare abstract class BasicSQL<L extends Lexer = Lexer, PRC extends Pars
106
110
  * @param input source string
107
111
  */
108
112
  splitSQLByStatement(input: string): TextSlice[] | null;
113
+ private splitInputBySeparator;
109
114
  /**
110
115
  * Get suggestions of syntax and token at caretPosition
111
116
  * @param input source string
@@ -2,8 +2,8 @@ import { CharStreams, CommonTokenStream, ParseTreeWalker, PredictionMode, } from
2
2
  import { CodeCompletionCore } from 'antlr4-c3';
3
3
  import { findCaretTokenIndex } from './findCaretTokenIndex';
4
4
  import { ctxToText, tokenToWord } from './textAndWord';
5
- import { ParseErrorListener } from './parseErrorListener';
6
5
  import { ErrorStrategy } from './errorStrategy';
6
+ const SEPARATOR = ';';
7
7
  /**
8
8
  * Basic SQL class, every sql needs extends it.
9
9
  */
@@ -14,6 +14,7 @@ export class BasicSQL {
14
14
  this._errorListener = (error) => {
15
15
  this._parseErrors.push(error);
16
16
  };
17
+ this.locale = 'en_US';
17
18
  }
18
19
  /**
19
20
  * Create an antlr4 lexer from input.
@@ -24,7 +25,7 @@ export class BasicSQL {
24
25
  const lexer = this.createLexerFromCharStream(charStreams);
25
26
  if (errorListener) {
26
27
  lexer.removeErrorListeners();
27
- lexer.addErrorListener(new ParseErrorListener(errorListener));
28
+ lexer.addErrorListener(this.createErrorListener(errorListener));
28
29
  }
29
30
  return lexer;
30
31
  }
@@ -39,7 +40,7 @@ export class BasicSQL {
39
40
  parser.interpreter.predictionMode = PredictionMode.SLL;
40
41
  if (errorListener) {
41
42
  parser.removeErrorListeners();
42
- parser.addErrorListener(new ParseErrorListener(errorListener));
43
+ parser.addErrorListener(this.createErrorListener(errorListener));
43
44
  }
44
45
  return parser;
45
46
  }
@@ -65,7 +66,7 @@ export class BasicSQL {
65
66
  this._charStreams = CharStreams.fromString(input);
66
67
  this._lexer = this.createLexerFromCharStream(this._charStreams);
67
68
  this._lexer.removeErrorListeners();
68
- this._lexer.addErrorListener(new ParseErrorListener(this._errorListener));
69
+ this._lexer.addErrorListener(this.createErrorListener(this._errorListener));
69
70
  this._tokenStream = new CommonTokenStream(this._lexer);
70
71
  /**
71
72
  * All tokens are generated in advance.
@@ -96,7 +97,7 @@ export class BasicSQL {
96
97
  const parser = this.createParserWithCache(input);
97
98
  this._parsedInput = input;
98
99
  parser.removeErrorListeners();
99
- parser.addErrorListener(new ParseErrorListener(this._errorListener));
100
+ parser.addErrorListener(this.createErrorListener(this._errorListener));
100
101
  this._parseTree = parser.program();
101
102
  return this._parseTree;
102
103
  }
@@ -140,9 +141,6 @@ export class BasicSQL {
140
141
  return null;
141
142
  }
142
143
  const splitListener = this.splitListener;
143
- // TODO: add splitListener to all sqlParser implements and remove following if
144
- if (!splitListener)
145
- return null;
146
144
  this.listen(splitListener, this._parseTree);
147
145
  const res = splitListener.statementsContext
148
146
  .map((context) => {
@@ -151,6 +149,39 @@ export class BasicSQL {
151
149
  .filter(Boolean);
152
150
  return res;
153
151
  }
152
+ // 通过分隔符进一步切分语句
153
+ splitInputBySeparator(inputSlice, caretTokenIndex) {
154
+ const allTokens = this.getAllTokens(inputSlice);
155
+ /**
156
+ * set startToken
157
+ */
158
+ let startToken = null;
159
+ for (let tokenIndex = caretTokenIndex; tokenIndex >= 0; tokenIndex--) {
160
+ const token = allTokens[tokenIndex];
161
+ if ((token === null || token === void 0 ? void 0 : token.text) === SEPARATOR) {
162
+ startToken = allTokens[tokenIndex + 1];
163
+ break;
164
+ }
165
+ }
166
+ if (startToken === null) {
167
+ startToken = allTokens[0];
168
+ }
169
+ /**
170
+ * set stopToken
171
+ */
172
+ let stopToken = null;
173
+ for (let tokenIndex = caretTokenIndex; tokenIndex < allTokens.length; tokenIndex++) {
174
+ const token = allTokens[tokenIndex];
175
+ if ((token === null || token === void 0 ? void 0 : token.text) === SEPARATOR) {
176
+ stopToken = token;
177
+ break;
178
+ }
179
+ }
180
+ if (stopToken === null) {
181
+ stopToken = allTokens[allTokens.length - 1];
182
+ }
183
+ return { startToken, stopToken };
184
+ }
154
185
  /**
155
186
  * Get suggestions of syntax and token at caretPosition
156
187
  * @param input source string
@@ -158,16 +189,13 @@ export class BasicSQL {
158
189
  * @returns suggestion
159
190
  */
160
191
  getSuggestionAtCaretPosition(input, caretPosition) {
161
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
192
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
162
193
  const splitListener = this.splitListener;
163
- // TODO: add splitListener to all sqlParser implements and remove following if
164
- if (!splitListener)
165
- return null;
166
194
  this.parseWithCache(input);
167
195
  if (!this._parseTree)
168
196
  return null;
169
197
  let sqlParserIns = this._parser;
170
- const allTokens = this.getAllTokens(input);
198
+ let allTokens = this.getAllTokens(input);
171
199
  let caretTokenIndex = findCaretTokenIndex(caretPosition, allTokens);
172
200
  let c3Context = this._parseTree;
173
201
  let tokenIndexOffset = 0;
@@ -212,8 +240,8 @@ export class BasicSQL {
212
240
  }
213
241
  }
214
242
  // A boundary consisting of the index of the input.
215
- const startIndex = (_e = (_d = startStatement === null || startStatement === void 0 ? void 0 : startStatement.start) === null || _d === void 0 ? void 0 : _d.start) !== null && _e !== void 0 ? _e : 0;
216
- const stopIndex = (_g = (_f = stopStatement === null || stopStatement === void 0 ? void 0 : stopStatement.stop) === null || _f === void 0 ? void 0 : _f.stop) !== null && _g !== void 0 ? _g : input.length - 1;
243
+ let startIndex = (_e = (_d = startStatement === null || startStatement === void 0 ? void 0 : startStatement.start) === null || _d === void 0 ? void 0 : _d.start) !== null && _e !== void 0 ? _e : 0;
244
+ let stopIndex = (_g = (_f = stopStatement === null || stopStatement === void 0 ? void 0 : stopStatement.stop) === null || _f === void 0 ? void 0 : _f.stop) !== null && _g !== void 0 ? _g : input.length - 1;
217
245
  /**
218
246
  * Save offset of the tokenIndex in the range of input
219
247
  * compared to the tokenIndex in the whole input
@@ -224,7 +252,26 @@ export class BasicSQL {
224
252
  * Reparse the input fragment,
225
253
  * and c3 will collect candidates in the newly generated parseTree.
226
254
  */
227
- const inputSlice = input.slice(startIndex, stopIndex);
255
+ let inputSlice = input.slice(startIndex, stopIndex);
256
+ /**
257
+ * Split the inputSlice by separator.
258
+ */
259
+ if (inputSlice.includes(SEPARATOR)) {
260
+ const { startToken, stopToken } = this.splitInputBySeparator(inputSlice, caretTokenIndex);
261
+ startIndex = (_k = startToken === null || startToken === void 0 ? void 0 : startToken.start) !== null && _k !== void 0 ? _k : 0;
262
+ stopIndex = (_l = (stopToken === null || stopToken === void 0 ? void 0 : stopToken.stop) + 1) !== null && _l !== void 0 ? _l : input.length;
263
+ /**
264
+ * Save offset of the tokenIndex in the range of input
265
+ * compared to the tokenIndex in the whole input
266
+ */
267
+ tokenIndexOffset = (_m = startToken === null || startToken === void 0 ? void 0 : startToken.tokenIndex) !== null && _m !== void 0 ? _m : 0;
268
+ caretTokenIndex = caretTokenIndex - tokenIndexOffset;
269
+ /**
270
+ * Get the smaller range of inputSlice
271
+ */
272
+ inputSlice = inputSlice.slice(startIndex, stopIndex);
273
+ allTokens = this.getAllTokens(inputSlice);
274
+ }
228
275
  const lexer = this.createLexer(inputSlice);
229
276
  lexer.removeErrorListeners();
230
277
  const tokenStream = new CommonTokenStream(lexer);
@@ -240,7 +287,7 @@ export class BasicSQL {
240
287
  const core = new CodeCompletionCore(sqlParserIns);
241
288
  core.preferredRules = this.preferredRules;
242
289
  const candidates = core.collectCandidates(caretTokenIndex, c3Context);
243
- const originalSuggestions = this.processCandidates(candidates, allTokens, caretTokenIndex, tokenIndexOffset);
290
+ const originalSuggestions = this.processCandidates(candidates, allTokens, caretTokenIndex);
244
291
  const syntaxSuggestions = originalSuggestions.syntax.map((syntaxCtx) => {
245
292
  const wordRanges = syntaxCtx.wordRanges.map((token) => {
246
293
  return tokenToWord(token, this._parsedInput);
@@ -261,10 +308,6 @@ export class BasicSQL {
261
308
  ? findCaretTokenIndex(caretPosition, allTokens)
262
309
  : void 0;
263
310
  const collectListener = this.createEntityCollector(input, caretTokenIndex);
264
- // TODO: add entityCollector to all sqlParser implements and remove following if
265
- if (!collectListener) {
266
- return null;
267
- }
268
311
  // const parser = this.createParserWithCache(input);
269
312
  // parser.entityCollecting = true;
270
313
  // if(caretPosition) {
@@ -1,6 +1,6 @@
1
- import { ParserRuleContext } from 'antlr4ng';
1
+ import { ParserRuleContext, Token } from 'antlr4ng';
2
+ import { TextPosition, WordPosition, WordRange } from './textAndWord';
2
3
  import { EntityContextType } from './types';
3
- import { WordPosition, TextPosition } from './textAndWord';
4
4
  /**
5
5
  * TODO: more stmt type should be supported.
6
6
  */
@@ -13,7 +13,8 @@ export declare enum StmtContextType {
13
13
  CREATE_VIEW_STMT = "createViewStmt",
14
14
  SELECT_STMT = "selectStmt",
15
15
  INSERT_STMT = "insertStmt",
16
- CREATE_FUNCTION_STMT = "createFunctionStmt"
16
+ CREATE_FUNCTION_STMT = "createFunctionStmt",
17
+ ALTER_TABLE_STMT = "alterTableStmt"
17
18
  }
18
19
  export interface StmtContext {
19
20
  readonly stmtContextType: StmtContextType;
@@ -23,20 +24,65 @@ export interface StmtContext {
23
24
  readonly isContainCaret?: boolean;
24
25
  }
25
26
  export declare function toStmtContext(ctx: ParserRuleContext, type: StmtContextType, input: string, rootStmt: StmtContext | null, parentStmt: StmtContext | null, isContainCaret?: boolean): StmtContext | null;
26
- export interface BaseAliasContext {
27
- readonly isAlias: boolean;
28
- alias?: string | EntityContext | null;
29
- origin?: string | EntityContext | StmtContext | null;
27
+ /**
28
+ * entity's attribute
29
+ * @key comment: entity's comment attribute
30
+ * @key colType: column entity's type attribute
31
+ * @key alias: entity's alias attribute
32
+ * */
33
+ export declare enum AttrName {
34
+ comment = "_comment",
35
+ colType = "_colType",
36
+ alias = "_alias"
30
37
  }
31
- export interface EntityContext extends BaseAliasContext {
38
+ /**
39
+ * ParserRuleContext with custom attributes
40
+ * */
41
+ type ParserRuleContextWithAttr = ParserRuleContext & {
42
+ [K in AttrName]?: Token;
43
+ };
44
+ /**
45
+ * Function's arguments
46
+ * */
47
+ export interface Argument {
48
+ argMode?: WordRange;
49
+ argName?: WordRange;
50
+ argType: WordRange;
51
+ }
52
+ export interface BaseEntityContext {
32
53
  readonly entityContextType: EntityContextType;
33
54
  readonly text: string;
34
55
  readonly position: WordPosition;
35
56
  readonly belongStmt: StmtContext;
36
- relatedEntities: EntityContext[] | null;
37
- columns: EntityContext[] | null;
57
+ reference?: string | EntityContext;
58
+ [AttrName.comment]: WordRange | null;
59
+ [AttrName.alias]?: WordRange | null;
60
+ }
61
+ export interface CommonEntityContext extends BaseEntityContext {
62
+ relatedEntities: CommonEntityContext[] | null;
63
+ columns?: ColumnEntityContext[];
64
+ }
65
+ export interface ColumnEntityContext extends BaseEntityContext {
66
+ [AttrName.colType]: WordRange | null;
67
+ }
68
+ export interface FuncEntityContext extends BaseEntityContext {
69
+ relatedEntities: CommonEntityContext[] | null;
70
+ arguments: Argument[] | null;
71
+ returns?: Argument;
72
+ }
73
+ export type EntityContext = CommonEntityContext | FuncEntityContext | ColumnEntityContext;
74
+ export declare function isCommonEntityContext(entity: EntityContext): entity is CommonEntityContext;
75
+ export declare function isFuncEntityContext(entity: EntityContext): entity is FuncEntityContext;
76
+ export declare function isColumnEntityContext(entity: EntityContext): entity is ColumnEntityContext;
77
+ /**
78
+ * what we need when collect attribute information
79
+ * */
80
+ interface AttrInfo {
81
+ attrName: AttrName;
82
+ endContextList: string[];
38
83
  }
39
- export declare function toEntityContext(ctx: ParserRuleContext, type: EntityContextType, input: string, belongStmt: StmtContext, alias?: BaseAliasContext): EntityContext | null;
84
+ export declare function toEntityContext(ctx: ParserRuleContext, type: EntityContextType, input: string, belongStmt: StmtContext, attrInfo?: AttrInfo[]): EntityContext | null;
85
+ export declare function findAttribute(ctx: ParserRuleContextWithAttr | null, keyName: AttrName, endContextNameList: string[]): Token | null;
40
86
  /**
41
87
  * @todo: Handle alias, includes column alias, table alias, query as alias and so on.
42
88
  * @todo: [may be need] Combine the entities in each clause.
@@ -59,11 +105,12 @@ export declare abstract class EntityCollector {
59
105
  visitErrorNode(): void;
60
106
  enterEveryRule(): void;
61
107
  exitEveryRule(): void;
108
+ getRootStmt(): StmtContext | null;
62
109
  getEntities(): EntityContext[];
63
110
  enterProgram(): void;
64
111
  protected pushStmt(ctx: ParserRuleContext, type: StmtContextType): StmtContext | null;
65
112
  protected popStmt(): StmtContext;
66
- protected pushEntity(ctx: ParserRuleContext, type: EntityContextType, alias?: BaseAliasContext): EntityContext | null;
113
+ protected pushEntity(ctx: ParserRuleContext, type: EntityContextType, attrInfo?: AttrInfo[]): EntityContext | null;
67
114
  /**
68
115
  * Combine entities that inside a single statement.
69
116
  * e.g. combine tableName and column if they are inside a same createTableStatement.
@@ -76,3 +123,4 @@ export declare abstract class EntityCollector {
76
123
  protected combineRootStmtEntities(stmtContext: StmtContext, entitiesInsideStmt: EntityContext[]): EntityContext[];
77
124
  protected combineCreateTableOrViewStmtEntities(stmtContext: StmtContext, entitiesInsideStmt: EntityContext[]): EntityContext[];
78
125
  }
126
+ export {};
@@ -9,9 +9,10 @@ var __rest = (this && this.__rest) || function (s, e) {
9
9
  }
10
10
  return t;
11
11
  };
12
- import { EntityContextType } from './types';
13
- import { ctxToText, ctxToWord } from './textAndWord';
12
+ import { isToken } from 'antlr4ng';
14
13
  import { SimpleStack } from './simpleStack';
14
+ import { ctxToText, isWordRange, tokenToWord, } from './textAndWord';
15
+ import { EntityContextType } from './types';
15
16
  /**
16
17
  * TODO: more stmt type should be supported.
17
18
  */
@@ -26,6 +27,7 @@ export var StmtContextType;
26
27
  StmtContextType["SELECT_STMT"] = "selectStmt";
27
28
  StmtContextType["INSERT_STMT"] = "insertStmt";
28
29
  StmtContextType["CREATE_FUNCTION_STMT"] = "createFunctionStmt";
30
+ StmtContextType["ALTER_TABLE_STMT"] = "alterTableStmt";
29
31
  })(StmtContextType || (StmtContextType = {}));
30
32
  export function toStmtContext(ctx, type, input, rootStmt, parentStmt, isContainCaret) {
31
33
  const text = ctxToText(ctx, input);
@@ -40,20 +42,131 @@ export function toStmtContext(ctx, type, input, rootStmt, parentStmt, isContainC
40
42
  isContainCaret,
41
43
  };
42
44
  }
43
- const baseAlias = {
44
- isAlias: false,
45
- origin: null,
46
- alias: null,
47
- };
48
- export function toEntityContext(ctx, type, input, belongStmt, alias) {
49
- const word = ctxToWord(ctx, input);
45
+ /**
46
+ * entity's attribute
47
+ * @key comment: entity's comment attribute
48
+ * @key colType: column entity's type attribute
49
+ * @key alias: entity's alias attribute
50
+ * */
51
+ export var AttrName;
52
+ (function (AttrName) {
53
+ AttrName["comment"] = "_comment";
54
+ AttrName["colType"] = "_colType";
55
+ AttrName["alias"] = "_alias";
56
+ })(AttrName || (AttrName = {}));
57
+ export function isCommonEntityContext(entity) {
58
+ if (!entity)
59
+ return false;
60
+ return 'relatedEntities' in entity && !('arguments' in entity);
61
+ }
62
+ export function isFuncEntityContext(entity) {
63
+ if (!entity)
64
+ return false;
65
+ return 'arguments' in entity;
66
+ }
67
+ export function isColumnEntityContext(entity) {
68
+ if (!entity)
69
+ return false;
70
+ return AttrName.colType in entity;
71
+ }
72
+ export function toEntityContext(ctx, type, input, belongStmt, attrInfo) {
73
+ var _a, _b;
74
+ const word = ctxToText(ctx, input);
50
75
  if (!word)
51
76
  return null;
52
- const { text } = word, position = __rest(word, ["text"]);
53
- const finalAlias = Object.assign({}, baseAlias, alias !== null && alias !== void 0 ? alias : {});
54
- return Object.assign({ entityContextType: type, text,
77
+ const { text, startLine, endLine } = word, rest = __rest(word, ["text", "startLine", "endLine"]);
78
+ const position = Object.assign(Object.assign({}, rest), { line: startLine });
79
+ let entityInfo = {
80
+ entityContextType: type,
81
+ text,
55
82
  position,
56
- belongStmt, relatedEntities: null, columns: null }, finalAlias);
83
+ belongStmt,
84
+ [AttrName.comment]: null,
85
+ };
86
+ switch (entityInfo.entityContextType) {
87
+ case EntityContextType.FUNCTION:
88
+ case EntityContextType.FUNCTION_CREATE: {
89
+ entityInfo.relatedEntities = null;
90
+ entityInfo.arguments = null;
91
+ break;
92
+ }
93
+ case EntityContextType.COLUMN:
94
+ case EntityContextType.COLUMN_CREATE:
95
+ entityInfo[AttrName.colType] = null;
96
+ break;
97
+ default:
98
+ entityInfo.relatedEntities = null;
99
+ break;
100
+ }
101
+ if (attrInfo) {
102
+ for (let k = 0; k < attrInfo.length; k++) {
103
+ const attributeName = (_a = attrInfo[k]) === null || _a === void 0 ? void 0 : _a.attrName;
104
+ const attrToken = findAttribute(ctx, attributeName, (_b = attrInfo[k]) === null || _b === void 0 ? void 0 : _b.endContextList);
105
+ if (attrToken) {
106
+ const attrVal = isToken(attrToken)
107
+ ? tokenToWord(attrToken, input)
108
+ : ctxToText(attrToken, input);
109
+ if (attrVal) {
110
+ if (isWordRange(attrVal)) {
111
+ entityInfo = Object.assign(entityInfo, {
112
+ [attributeName]: attrVal,
113
+ });
114
+ }
115
+ else {
116
+ const { startIndex, endIndex, startColumn, endColumn, text } = attrVal, rest = __rest(attrVal, ["startIndex", "endIndex", "startColumn", "endColumn", "text"]);
117
+ entityInfo = Object.assign(entityInfo, {
118
+ [attributeName]: {
119
+ startIndex,
120
+ endIndex,
121
+ startColumn,
122
+ endColumn,
123
+ text,
124
+ line: rest === null || rest === void 0 ? void 0 : rest.startLine,
125
+ },
126
+ });
127
+ }
128
+ }
129
+ }
130
+ }
131
+ }
132
+ return entityInfo;
133
+ }
134
+ export function findAttribute(ctx, keyName, endContextNameList) {
135
+ var _a, _b;
136
+ const parent = (ctx === null || ctx === void 0 ? void 0 : ctx.parent) || null;
137
+ let attrVal = null;
138
+ if (parent === null || parent === void 0 ? void 0 : parent[keyName]) {
139
+ attrVal = (parent === null || parent === void 0 ? void 0 : parent[keyName]) || null;
140
+ return attrVal;
141
+ }
142
+ else {
143
+ if (((_a = parent === null || parent === void 0 ? void 0 : parent.constructor) === null || _a === void 0 ? void 0 : _a.name) && !endContextNameList.includes((_b = parent === null || parent === void 0 ? void 0 : parent.constructor) === null || _b === void 0 ? void 0 : _b.name)) {
144
+ attrVal = findAttribute(parent, keyName, endContextNameList);
145
+ }
146
+ if (!attrVal) {
147
+ if (parent === null || parent === void 0 ? void 0 : parent.children) {
148
+ attrVal = findAttributeChildren(parent, keyName);
149
+ }
150
+ }
151
+ }
152
+ return attrVal;
153
+ }
154
+ function findAttributeChildren(ctx, keyName) {
155
+ const visitChildren = (ctx === null || ctx === void 0 ? void 0 : ctx.children) || [];
156
+ let attrVal = null;
157
+ if (visitChildren.length) {
158
+ for (let i = 0; i < visitChildren.length; i++) {
159
+ const child = visitChildren[i] || null;
160
+ if (child === null || child === void 0 ? void 0 : child[keyName]) {
161
+ attrVal = (child === null || child === void 0 ? void 0 : child[keyName]) || null;
162
+ return attrVal;
163
+ }
164
+ else {
165
+ attrVal = findAttributeChildren(child, keyName);
166
+ }
167
+ }
168
+ }
169
+ return attrVal;
57
170
  }
58
171
  /**
59
172
  * @todo: Handle alias, includes column alias, table alias, query as alias and so on.
@@ -72,6 +185,9 @@ export class EntityCollector {
72
185
  visitErrorNode() { }
73
186
  enterEveryRule() { }
74
187
  exitEveryRule() { }
188
+ getRootStmt() {
189
+ return this._rootStmt;
190
+ }
75
191
  getEntities() {
76
192
  return Array.from(this._entitiesSet);
77
193
  }
@@ -111,8 +227,8 @@ export class EntityCollector {
111
227
  }
112
228
  return stmtContext;
113
229
  }
114
- pushEntity(ctx, type, alias) {
115
- const entityContext = toEntityContext(ctx, type, this._input, this._stmtStack.peek(), alias);
230
+ pushEntity(ctx, type, attrInfo) {
231
+ const entityContext = toEntityContext(ctx, type, this._input, this._stmtStack.peek(), attrInfo);
116
232
  if (entityContext) {
117
233
  if (this._stmtStack.isEmpty()) {
118
234
  this._entitiesSet.add(entityContext);
@@ -181,10 +297,18 @@ export class EntityCollector {
181
297
  return result;
182
298
  }, []);
183
299
  if (mainEntity && columns.length) {
184
- mainEntity.columns = columns;
300
+ if (isCommonEntityContext(mainEntity)) {
301
+ mainEntity = Object.assign(mainEntity, {
302
+ columns,
303
+ });
304
+ }
185
305
  }
186
306
  if (mainEntity && relatedEntities.length) {
187
- mainEntity.relatedEntities = relatedEntities;
307
+ if (isCommonEntityContext(mainEntity) || isFuncEntityContext(mainEntity)) {
308
+ mainEntity = Object.assign(mainEntity, {
309
+ relatedEntities,
310
+ });
311
+ }
188
312
  }
189
313
  return finalEntities;
190
314
  }
@@ -1,4 +1,5 @@
1
- import { Token, Recognizer, ANTLRErrorListener, RecognitionException, ATNSimulator } from 'antlr4ng';
1
+ import { Token, Recognizer, ANTLRErrorListener, RecognitionException, ATNSimulator, Parser } from 'antlr4ng';
2
+ import { LOCALE_TYPE } from './types';
2
3
  /**
3
4
  * Converted from {@link SyntaxError}.
4
5
  */
@@ -29,11 +30,13 @@ export interface SyntaxError {
29
30
  * Includes lexical errors and parsing errors.
30
31
  */
31
32
  export type ErrorListener = (parseError: ParseError, originalError: SyntaxError) => void;
32
- export declare class ParseErrorListener implements ANTLRErrorListener {
33
+ export declare abstract class ParseErrorListener implements ANTLRErrorListener {
33
34
  private _errorListener;
34
- constructor(errorListener: ErrorListener);
35
+ private locale;
36
+ constructor(errorListener: ErrorListener, locale?: LOCALE_TYPE);
35
37
  reportAmbiguity(): void;
36
38
  reportAttemptingFullContext(): void;
37
39
  reportContextSensitivity(): void;
40
+ protected abstract getExpectedText(parser: Parser, token: Token): string;
38
41
  syntaxError(recognizer: Recognizer<ATNSimulator>, offendingSymbol: Token | null, line: number, charPositionInLine: number, msg: string, e: RecognitionException): void;
39
42
  }