dt-sql-parser 4.0.0-ng.2 → 4.0.0

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 (142) hide show
  1. package/README.md +119 -112
  2. package/dist/index.d.ts +14 -6
  3. package/dist/index.js +11 -4
  4. package/dist/lib/SQLParserBase.d.ts +8 -0
  5. package/dist/lib/SQLParserBase.js +14 -0
  6. package/dist/lib/{flinksql → flink}/FlinkSqlLexer.d.ts +2 -2
  7. package/dist/lib/{flinksql → flink}/FlinkSqlLexer.js +2 -1
  8. package/dist/lib/{flinksql → flink}/FlinkSqlParser.d.ts +5 -11
  9. package/dist/lib/{flinksql → flink}/FlinkSqlParser.js +2065 -2054
  10. package/dist/lib/{flinksql → flink}/FlinkSqlParserListener.d.ts +0 -13
  11. package/dist/lib/{flinksql → flink}/FlinkSqlParserListener.js +1 -1
  12. package/dist/lib/{flinksql → flink}/FlinkSqlParserVisitor.d.ts +0 -8
  13. package/dist/lib/{flinksql → flink}/FlinkSqlParserVisitor.js +2 -1
  14. package/dist/lib/hive/HiveSqlLexer.d.ts +258 -257
  15. package/dist/lib/hive/HiveSqlLexer.js +1794 -1786
  16. package/dist/lib/hive/HiveSqlParser.d.ts +1266 -3176
  17. package/dist/lib/hive/HiveSqlParser.js +23046 -33454
  18. package/dist/lib/hive/HiveSqlParserListener.d.ts +141 -2036
  19. package/dist/lib/hive/HiveSqlParserVisitor.d.ts +151 -1358
  20. package/dist/lib/hive/HiveSqlParserVisitor.js +1 -0
  21. package/dist/lib/impala/ImpalaSqlLexer.d.ts +170 -154
  22. package/dist/lib/impala/ImpalaSqlLexer.js +1179 -1099
  23. package/dist/lib/impala/ImpalaSqlParser.d.ts +282 -240
  24. package/dist/lib/impala/ImpalaSqlParser.js +3881 -3744
  25. package/dist/lib/impala/ImpalaSqlParserListener.d.ts +22 -11
  26. package/dist/lib/impala/ImpalaSqlParserVisitor.d.ts +14 -7
  27. package/dist/lib/impala/ImpalaSqlParserVisitor.js +1 -0
  28. package/dist/lib/index.d.ts +6 -6
  29. package/dist/lib/index.js +6 -6
  30. package/dist/lib/mysql/MySqlLexer.d.ts +2 -2
  31. package/dist/lib/mysql/MySqlLexer.js +1 -0
  32. package/dist/lib/mysql/MySqlParser.d.ts +347 -418
  33. package/dist/lib/mysql/MySqlParser.js +10484 -11099
  34. package/dist/lib/mysql/MySqlParserListener.d.ts +41 -126
  35. package/dist/lib/mysql/MySqlParserVisitor.d.ts +23 -76
  36. package/dist/lib/mysql/MySqlParserVisitor.js +1 -0
  37. package/dist/lib/plsql/PlSqlBaseLexer.d.ts +1 -2
  38. package/dist/lib/plsql/PlSqlBaseLexer.js +1 -1
  39. package/dist/lib/plsql/PlSqlBaseParser.d.ts +3 -2
  40. package/dist/lib/plsql/PlSqlBaseParser.js +2 -2
  41. package/dist/lib/plsql/PlSqlLexer.d.ts +3 -3
  42. package/dist/lib/plsql/PlSqlLexer.js +2 -1
  43. package/dist/lib/plsql/PlSqlParser.d.ts +3 -3
  44. package/dist/lib/plsql/PlSqlParser.js +2 -1
  45. package/dist/lib/plsql/PlSqlParserVisitor.js +1 -0
  46. package/dist/lib/{pgsql/PostgreSQLLexer.d.ts → postgresql/PostgreSqlLexer.d.ts} +3 -3
  47. package/dist/lib/{pgsql/PostgreSQLLexer.js → postgresql/PostgreSqlLexer.js} +618 -617
  48. package/dist/lib/{pgsql/PostgreSQLParser.d.ts → postgresql/PostgreSqlParser.d.ts} +3598 -3484
  49. package/dist/lib/{pgsql/PostgreSQLParser.js → postgresql/PostgreSqlParser.js} +41502 -42831
  50. package/dist/lib/{pgsql/PostgreSQLParserListener.d.ts → postgresql/PostgreSqlParserListener.d.ts} +2797 -2730
  51. package/dist/lib/{pgsql/PostgreSQLParserListener.js → postgresql/PostgreSqlParserListener.js} +3 -3
  52. package/dist/lib/{pgsql/PostgreSQLParserVisitor.d.ts → postgresql/PostgreSqlParserVisitor.d.ts} +1845 -1810
  53. package/dist/lib/{pgsql/PostgreSQLParserVisitor.js → postgresql/PostgreSqlParserVisitor.js} +4 -3
  54. package/dist/lib/spark/SparkSqlLexer.d.ts +305 -298
  55. package/dist/lib/spark/SparkSqlLexer.js +1777 -1735
  56. package/dist/lib/spark/SparkSqlParser.d.ts +1764 -669
  57. package/dist/lib/spark/SparkSqlParser.js +15460 -10769
  58. package/dist/lib/spark/SparkSqlParserListener.d.ts +1285 -35
  59. package/dist/lib/spark/SparkSqlParserVisitor.d.ts +790 -21
  60. package/dist/lib/spark/SparkSqlParserVisitor.js +1 -0
  61. package/dist/lib/{trinosql → trino}/TrinoSqlLexer.d.ts +2 -2
  62. package/dist/lib/{trinosql → trino}/TrinoSqlLexer.js +2 -1
  63. package/dist/lib/{trinosql → trino}/TrinoSqlListener.d.ts +7 -5
  64. package/dist/lib/{trinosql → trino}/TrinoSqlListener.js +1 -1
  65. package/dist/lib/{trinosql → trino}/TrinoSqlParser.d.ts +11 -5
  66. package/dist/lib/{trinosql → trino}/TrinoSqlParser.js +360 -320
  67. package/dist/lib/{trinosql → trino}/TrinoSqlVisitor.d.ts +4 -3
  68. package/dist/lib/{trinosql → trino}/TrinoSqlVisitor.js +2 -1
  69. package/dist/parser/common/{basicParser.d.ts → basicSQL.d.ts} +22 -19
  70. package/dist/parser/common/{basicParser.js → basicSQL.js} +52 -34
  71. package/dist/parser/common/entityCollector.d.ts +78 -0
  72. package/dist/parser/common/entityCollector.js +191 -0
  73. package/dist/parser/common/{utils/findCaretTokenIndex.d.ts → findCaretTokenIndex.d.ts} +2 -2
  74. package/dist/parser/common/{utils/findCaretTokenIndex.js → findCaretTokenIndex.js} +3 -2
  75. package/dist/parser/common/parseErrorListener.d.ts +6 -6
  76. package/dist/parser/common/parseErrorListener.js +1 -1
  77. package/dist/parser/common/simpleStack.d.ts +10 -0
  78. package/dist/parser/common/simpleStack.js +23 -0
  79. package/dist/parser/common/splitListener.d.ts +8 -0
  80. package/dist/parser/common/splitListener.js +12 -0
  81. package/dist/parser/common/textAndWord.d.ts +52 -0
  82. package/dist/parser/common/textAndWord.js +58 -0
  83. package/dist/parser/common/{basic-parser-types.d.ts → types.d.ts} +4 -31
  84. package/dist/parser/common/types.js +34 -0
  85. package/dist/parser/flink/flinkEntityCollector.d.ts +33 -0
  86. package/dist/parser/flink/flinkEntityCollector.js +84 -0
  87. package/dist/parser/flink/flinkSplitListener.d.ts +6 -0
  88. package/dist/parser/flink/flinkSplitListener.js +6 -0
  89. package/dist/parser/flink/index.d.ts +17 -0
  90. package/dist/parser/{flinksql.js → flink/index.js} +26 -37
  91. package/dist/parser/hive/hiveEntityCollector.d.ts +35 -0
  92. package/dist/parser/hive/hiveEntityCollector.js +90 -0
  93. package/dist/parser/hive/hiveSplitListener.d.ts +6 -0
  94. package/dist/parser/hive/hiveSplitListener.js +6 -0
  95. package/dist/parser/hive/index.d.ts +17 -0
  96. package/dist/parser/{hive.js → hive/index.js} +24 -34
  97. package/dist/parser/impala/impalaEntityCollector.d.ts +35 -0
  98. package/dist/parser/impala/impalaEntityCollector.js +90 -0
  99. package/dist/parser/impala/impalaSplitListener.d.ts +6 -0
  100. package/dist/parser/impala/impalaSplitListener.js +6 -0
  101. package/dist/parser/impala/index.d.ts +17 -0
  102. package/dist/parser/{impala.js → impala/index.js} +24 -34
  103. package/dist/parser/index.d.ts +8 -8
  104. package/dist/parser/index.js +8 -8
  105. package/dist/parser/mysql/index.d.ts +17 -0
  106. package/dist/parser/{mysql.js → mysql/index.js} +24 -34
  107. package/dist/parser/mysql/mysqlEntityCollector.d.ts +37 -0
  108. package/dist/parser/mysql/mysqlEntityCollector.js +96 -0
  109. package/dist/parser/mysql/mysqlSplitListener.d.ts +6 -0
  110. package/dist/parser/mysql/mysqlSplitListener.js +6 -0
  111. package/dist/parser/plsql.d.ts +7 -6
  112. package/dist/parser/plsql.js +6 -4
  113. package/dist/parser/postgresql/index.d.ts +17 -0
  114. package/dist/parser/postgresql/index.js +130 -0
  115. package/dist/parser/postgresql/postgreEntityCollector.d.ts +37 -0
  116. package/dist/parser/postgresql/postgreEntityCollector.js +96 -0
  117. package/dist/parser/postgresql/postgreSplitListener.d.ts +6 -0
  118. package/dist/parser/postgresql/postgreSplitListener.js +6 -0
  119. package/dist/parser/spark/index.d.ts +17 -0
  120. package/dist/parser/{spark.js → spark/index.js} +29 -40
  121. package/dist/parser/spark/sparkEntityCollector.d.ts +37 -0
  122. package/dist/parser/spark/sparkEntityCollector.js +96 -0
  123. package/dist/parser/spark/sparkSplitListener.d.ts +6 -0
  124. package/dist/parser/spark/sparkSplitListener.js +6 -0
  125. package/dist/parser/trino/index.d.ts +17 -0
  126. package/dist/parser/{trinosql.js → trino/index.js} +25 -36
  127. package/dist/parser/trino/trinoEntityCollector.d.ts +30 -0
  128. package/dist/parser/trino/trinoEntityCollector.js +75 -0
  129. package/dist/parser/trino/trinoSplitListener.d.ts +6 -0
  130. package/dist/parser/trino/trinoSplitListener.js +6 -0
  131. package/dist/utils/index.d.ts +1 -1
  132. package/dist/utils/token.d.ts +1 -1
  133. package/package.json +1 -1
  134. package/dist/parser/common/basic-parser-types.js +0 -34
  135. package/dist/parser/flinksql.d.ts +0 -23
  136. package/dist/parser/hive.d.ts +0 -23
  137. package/dist/parser/impala.d.ts +0 -23
  138. package/dist/parser/mysql.d.ts +0 -23
  139. package/dist/parser/pgsql.d.ts +0 -23
  140. package/dist/parser/pgsql.js +0 -140
  141. package/dist/parser/spark.d.ts +0 -23
  142. package/dist/parser/trinosql.d.ts +0 -23
@@ -79,7 +79,7 @@ import { UpdateContext } from "./TrinoSqlParser.js";
79
79
  import { MergeContext } from "./TrinoSqlParser.js";
80
80
  import { ShowTableCommentContext } from "./TrinoSqlParser.js";
81
81
  import { ShowColumnCommentContext } from "./TrinoSqlParser.js";
82
- import { QueryContext } from "./TrinoSqlParser.js";
82
+ import { QueryStatementContext } from "./TrinoSqlParser.js";
83
83
  import { WithContext } from "./TrinoSqlParser.js";
84
84
  import { TableElementContext } from "./TrinoSqlParser.js";
85
85
  import { ColumnDefinitionContext } from "./TrinoSqlParser.js";
@@ -838,11 +838,12 @@ export declare class TrinoSqlVisitor<Result> extends AbstractParseTreeVisitor<Re
838
838
  */
839
839
  visitShowColumnComment?: (ctx: ShowColumnCommentContext) => Result;
840
840
  /**
841
- * Visit a parse tree produced by `TrinoSqlParser.query`.
841
+ * Visit a parse tree produced by the `queryStatement`
842
+ * labeled alternative in `TrinoSqlParser.query`.
842
843
  * @param ctx the parse tree
843
844
  * @return the visitor result
844
845
  */
845
- visitQuery?: (ctx: QueryContext) => Result;
846
+ visitQueryStatement?: (ctx: QueryStatementContext) => Result;
846
847
  /**
847
848
  * Visit a parse tree produced by `TrinoSqlParser.with`.
848
849
  * @param ctx the parse tree
@@ -1,4 +1,5 @@
1
- // Generated from dt-sql-parser/src/grammar/trinosql/TrinoSql.g4 by ANTLR 4.13.1
1
+ // Generated from dt-sql-parser/src/grammar/trino/TrinoSql.g4 by ANTLR 4.13.1
2
+ // @ts-nocheck
2
3
  import { AbstractParseTreeVisitor } from "antlr4ng";
3
4
  /**
4
5
  * This interface defines a complete generic visitor for a parse tree produced
@@ -1,23 +1,22 @@
1
- import { Parser, Lexer, Token, CommonTokenStream, CharStream, ParserRuleContext, ParseTreeListener } from 'antlr4ng';
1
+ import { Lexer, Token, CommonTokenStream, CharStream, ParserRuleContext, ParseTreeListener } from 'antlr4ng';
2
2
  import { CandidatesCollection } from 'antlr4-c3';
3
- import { CaretPosition, Suggestions, TextSlice } from './basic-parser-types';
3
+ import { SQLParserBase } from '../../lib/SQLParserBase';
4
+ import { TextSlice } from './textAndWord';
5
+ import { CaretPosition, Suggestions } from './types';
4
6
  import { ParseError, ErrorListener } from './parseErrorListener';
5
- interface IParser<IParserRuleContext extends ParserRuleContext> extends Parser {
6
- program(): IParserRuleContext;
7
- }
8
- interface SplitListener extends ParseTreeListener {
9
- statementsContext: ParserRuleContext[];
10
- }
7
+ import type { SplitListener } from './splitListener';
8
+ import type { EntityCollector } from './entityCollector';
9
+ import { EntityContext } from './entityCollector';
11
10
  /**
12
- * Custom Parser class, subclass needs extends it.
11
+ * Basic SQL class, every sql needs extends it.
13
12
  */
14
- export default abstract class BasicParser<L extends Lexer = Lexer, PRC extends ParserRuleContext = ParserRuleContext, P extends IParser<PRC> = IParser<PRC>> {
13
+ export declare abstract class BasicSQL<L extends Lexer = Lexer, PRC extends ParserRuleContext = ParserRuleContext, P extends SQLParserBase<PRC> = SQLParserBase<PRC>> {
15
14
  /** members for cache start */
16
15
  protected _charStreams: CharStream;
17
16
  protected _lexer: L;
18
17
  protected _tokenStream: CommonTokenStream;
19
18
  protected _parser: P;
20
- protected _parseTree: PRC;
19
+ protected _parseTree: PRC | null;
21
20
  protected _parsedInput: string;
22
21
  protected _parseErrors: ParseError[];
23
22
  /** members for cache end */
@@ -45,26 +44,30 @@ export default abstract class BasicParser<L extends Lexer = Lexer, PRC extends P
45
44
  */
46
45
  protected abstract processCandidates(candidates: CandidatesCollection, allTokens: Token[], caretTokenIndex: number, tokenIndexOffset: number): Suggestions<Token>;
47
46
  /**
48
- * Get splitListener instance.
47
+ * Get a new splitListener instance.
48
+ */
49
+ protected abstract get splitListener(): SplitListener<ParserRuleContext>;
50
+ /**
51
+ * Get a new entityCollector instance.
49
52
  */
50
- protected abstract get splitListener(): SplitListener;
53
+ protected abstract createEntityCollector(input: string, caretTokenIndex?: number): EntityCollector;
51
54
  /**
52
55
  * Create an antlr4 lexer from input.
53
56
  * @param input string
54
57
  */
55
- createLexer(input: string, errorListener?: ErrorListener<any>): L;
58
+ createLexer(input: string, errorListener?: ErrorListener): L;
56
59
  /**
57
60
  * Create an antlr4 parser from input.
58
61
  * @param input string
59
62
  */
60
- createParser(input: string, errorListener?: ErrorListener<any>): P;
63
+ createParser(input: string, errorListener?: ErrorListener): P;
61
64
  /**
62
65
  * Parse input string and return parseTree.
63
66
  * @param input string
64
67
  * @param errorListener listen parse errors and lexer errors.
65
68
  * @returns parseTree
66
69
  */
67
- parse(input: string, errorListener?: ErrorListener<any>): PRC;
70
+ parse(input: string, errorListener?: ErrorListener): PRC;
68
71
  /**
69
72
  * Create an antlr4 parser from input.
70
73
  * And the instances will be cache.
@@ -96,13 +99,13 @@ export default abstract class BasicParser<L extends Lexer = Lexer, PRC extends P
96
99
  * @param listener Listener instance extends ParserListener
97
100
  * @param parseTree parser Tree
98
101
  */
99
- listen<PTL extends ParseTreeListener = ParseTreeListener>(listener: PTL, parseTree: PRC): void;
102
+ listen<PTL extends ParseTreeListener = ParseTreeListener>(listener: PTL, parseTree: ParserRuleContext): void;
100
103
  /**
101
104
  * Split input into statements.
102
105
  * If exist syntax error it will return null.
103
106
  * @param input source string
104
107
  */
105
- splitSQLByStatement(input: any): TextSlice[];
108
+ splitSQLByStatement(input: string): TextSlice[] | null;
106
109
  /**
107
110
  * Get suggestions of syntax and token at caretPosition
108
111
  * @param input source string
@@ -110,5 +113,5 @@ export default abstract class BasicParser<L extends Lexer = Lexer, PRC extends P
110
113
  * @returns suggestion
111
114
  */
112
115
  getSuggestionAtCaretPosition(input: string, caretPosition: CaretPosition): Suggestions | null;
116
+ getAllEntities(input: string, caretPosition?: CaretPosition): EntityContext[] | null;
113
117
  }
114
- export {};
@@ -1,14 +1,14 @@
1
- import { CharStreams, CommonTokenStream, ParseTreeWalker, } from 'antlr4ng';
1
+ import { CharStreams, CommonTokenStream, ParseTreeWalker, PredictionMode, } from 'antlr4ng';
2
2
  import { CodeCompletionCore } from 'antlr4-c3';
3
- import { findCaretTokenIndex } from './utils/findCaretTokenIndex';
4
- import ParseErrorListener from './parseErrorListener';
3
+ import { findCaretTokenIndex } from './findCaretTokenIndex';
4
+ import { ctxToText, tokenToWord } from './textAndWord';
5
+ import { ParseErrorListener } from './parseErrorListener';
5
6
  import { ErrorStrategy } from './errorStrategy';
6
7
  /**
7
- * Custom Parser class, subclass needs extends it.
8
+ * Basic SQL class, every sql needs extends it.
8
9
  */
9
- export default class BasicParser {
10
+ export class BasicSQL {
10
11
  constructor() {
11
- this._parsedInput = null;
12
12
  this._parseErrors = [];
13
13
  /** members for cache end */
14
14
  this._errorListener = (error) => {
@@ -36,6 +36,7 @@ export default class BasicParser {
36
36
  const lexer = this.createLexer(input, errorListener);
37
37
  const tokenStream = new CommonTokenStream(lexer);
38
38
  const parser = this.createParserFromTokenStream(tokenStream);
39
+ parser.interpreter.predictionMode = PredictionMode.SLL;
39
40
  if (errorListener) {
40
41
  parser.removeErrorListeners();
41
42
  parser.addErrorListener(new ParseErrorListener(errorListener));
@@ -73,6 +74,7 @@ export default class BasicParser {
73
74
  */
74
75
  this._tokenStream.fill();
75
76
  this._parser = this.createParserFromTokenStream(this._tokenStream);
77
+ this._parser.interpreter.predictionMode = PredictionMode.SLL;
76
78
  this._parser.buildParseTrees = true;
77
79
  this._parser.errorHandler = new ErrorStrategy();
78
80
  return this._parser;
@@ -87,7 +89,7 @@ export default class BasicParser {
87
89
  */
88
90
  parseWithCache(input, errorListener) {
89
91
  // Avoid parsing the same input repeatedly.
90
- if (this._parsedInput === input && !errorListener) {
92
+ if (this._parsedInput === input && !errorListener && this._parseTree) {
91
93
  return this._parseTree;
92
94
  }
93
95
  this._parseErrors = [];
@@ -134,26 +136,19 @@ export default class BasicParser {
134
136
  */
135
137
  splitSQLByStatement(input) {
136
138
  const errors = this.validate(input);
137
- if (errors.length) {
139
+ if (errors.length || !this._parseTree) {
138
140
  return null;
139
141
  }
140
142
  const splitListener = this.splitListener;
141
- // TODO: add splitListener to all sqlParser implements add remove following if
143
+ // TODO: add splitListener to all sqlParser implements and remove following if
142
144
  if (!splitListener)
143
145
  return null;
144
146
  this.listen(splitListener, this._parseTree);
145
- const res = splitListener.statementsContext.map((context) => {
146
- const { start, stop } = context;
147
- return {
148
- startIndex: start.start,
149
- endIndex: stop.stop,
150
- startLine: start.line,
151
- endLine: stop.line,
152
- startColumn: start.column + 1,
153
- endColumn: stop.column + 1 + stop.text.length,
154
- text: this._parsedInput.slice(start.start, stop.stop + 1),
155
- };
156
- });
147
+ const res = splitListener.statementsContext
148
+ .map((context) => {
149
+ return ctxToText(context, this._parsedInput);
150
+ })
151
+ .filter(Boolean);
157
152
  return res;
158
153
  }
159
154
  /**
@@ -165,10 +160,12 @@ export default class BasicParser {
165
160
  getSuggestionAtCaretPosition(input, caretPosition) {
166
161
  var _a, _b, _c, _d, _e, _f, _g, _h, _j;
167
162
  const splitListener = this.splitListener;
168
- // TODO: add splitListener to all sqlParser implements add remove following if
163
+ // TODO: add splitListener to all sqlParser implements and remove following if
169
164
  if (!splitListener)
170
165
  return null;
171
166
  this.parseWithCache(input);
167
+ if (!this._parseTree)
168
+ return null;
172
169
  let sqlParserIns = this._parser;
173
170
  const allTokens = this.getAllTokens(input);
174
171
  let caretTokenIndex = findCaretTokenIndex(caretPosition, allTokens);
@@ -190,8 +187,8 @@ export default class BasicParser {
190
187
  * The boundaries of this range must be statements with no syntax errors.
191
188
  * This can ensure the stable performance of the C3.
192
189
  */
193
- let startStatement;
194
- let stopStatement;
190
+ let startStatement = null;
191
+ let stopStatement = null;
195
192
  for (let index = 0; index < statementCount; index++) {
196
193
  const ctx = statementsContext[index];
197
194
  const isCurrentCtxValid = !ctx.exception;
@@ -203,10 +200,13 @@ export default class BasicParser {
203
200
  */
204
201
  const isPrevCtxValid = index === 0 || !((_b = statementsContext[index - 1]) === null || _b === void 0 ? void 0 : _b.exception);
205
202
  const isNextCtxValid = index === statementCount - 1 || !((_c = statementsContext[index + 1]) === null || _c === void 0 ? void 0 : _c.exception);
206
- if (ctx.stop.tokenIndex < caretTokenIndex && isPrevCtxValid) {
203
+ if (ctx.stop && ctx.stop.tokenIndex < caretTokenIndex && isPrevCtxValid) {
207
204
  startStatement = ctx;
208
205
  }
209
- if (!stopStatement && ctx.start.tokenIndex > caretTokenIndex && isNextCtxValid) {
206
+ if (ctx.start &&
207
+ !stopStatement &&
208
+ ctx.start.tokenIndex > caretTokenIndex &&
209
+ isNextCtxValid) {
210
210
  stopStatement = ctx;
211
211
  break;
212
212
  }
@@ -230,6 +230,7 @@ export default class BasicParser {
230
230
  const tokenStream = new CommonTokenStream(lexer);
231
231
  tokenStream.fill();
232
232
  const parser = this.createParserFromTokenStream(tokenStream);
233
+ parser.interpreter.predictionMode = PredictionMode.SLL;
233
234
  parser.removeErrorListeners();
234
235
  parser.buildParseTrees = true;
235
236
  parser.errorHandler = new ErrorStrategy();
@@ -242,14 +243,7 @@ export default class BasicParser {
242
243
  const originalSuggestions = this.processCandidates(candidates, allTokens, caretTokenIndex, tokenIndexOffset);
243
244
  const syntaxSuggestions = originalSuggestions.syntax.map((syntaxCtx) => {
244
245
  const wordRanges = syntaxCtx.wordRanges.map((token) => {
245
- return {
246
- text: this._parsedInput.slice(token.start, token.stop + 1),
247
- startIndex: token.start,
248
- endIndex: token.stop,
249
- line: token.line,
250
- startColumn: token.column + 1,
251
- stopColumn: token.column + 1 + token.text.length,
252
- };
246
+ return tokenToWord(token, this._parsedInput);
253
247
  });
254
248
  return {
255
249
  syntaxContextType: syntaxCtx.syntaxContextType,
@@ -261,4 +255,28 @@ export default class BasicParser {
261
255
  keywords: originalSuggestions.keywords,
262
256
  };
263
257
  }
258
+ getAllEntities(input, caretPosition) {
259
+ const allTokens = this.getAllTokens(input);
260
+ const caretTokenIndex = caretPosition
261
+ ? findCaretTokenIndex(caretPosition, allTokens)
262
+ : void 0;
263
+ 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
+ // const parser = this.createParserWithCache(input);
269
+ // parser.entityCollecting = true;
270
+ // if(caretPosition) {
271
+ // const allTokens = this.getAllTokens(input);
272
+ // const tokenIndex = findCaretTokenIndex(caretPosition, allTokens);
273
+ // parser.caretTokenIndex = tokenIndex;
274
+ // }
275
+ // const parseTree = parser.program();
276
+ const parseTree = this.parseWithCache(input);
277
+ this.listen(collectListener, parseTree);
278
+ // parser.caretTokenIndex = -1;
279
+ // parser.entityCollecting = false;
280
+ return collectListener.getEntities();
281
+ }
264
282
  }
@@ -0,0 +1,78 @@
1
+ import { ParserRuleContext } from 'antlr4ng';
2
+ import { EntityContextType } from './types';
3
+ import { WordPosition, TextPosition } from './textAndWord';
4
+ /**
5
+ * TODO: more stmt type should be supported.
6
+ */
7
+ export declare enum StmtContextType {
8
+ /** A self-contained and complete statement */
9
+ COMMON_STMT = "commonStmt",
10
+ CREATE_CATALOG_STMT = "createCatalogStmt",
11
+ CREATE_DATABASE_STMT = "createDatabaseStmt",
12
+ CREATE_TABLE_STMT = "createTableStmt",
13
+ CREATE_VIEW_STMT = "createViewStmt",
14
+ SELECT_STMT = "selectStmt",
15
+ INSERT_STMT = "insertStmt",
16
+ CREATE_FUNCTION_STMT = "createFunctionStmt"
17
+ }
18
+ export interface StmtContext {
19
+ readonly stmtContextType: StmtContextType;
20
+ readonly position: TextPosition;
21
+ readonly rootStmt: StmtContext | null;
22
+ readonly parentStmt: StmtContext | null;
23
+ readonly isContainCaret?: boolean;
24
+ }
25
+ 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;
30
+ }
31
+ export interface EntityContext extends BaseAliasContext {
32
+ readonly entityContextType: EntityContextType;
33
+ readonly text: string;
34
+ readonly position: WordPosition;
35
+ readonly belongStmt: StmtContext;
36
+ relatedEntities: EntityContext[] | null;
37
+ columns: EntityContext[] | null;
38
+ }
39
+ export declare function toEntityContext(ctx: ParserRuleContext, type: EntityContextType, input: string, belongStmt: StmtContext, alias?: BaseAliasContext): EntityContext | null;
40
+ /**
41
+ * @todo: Handle alias, includes column alias, table alias, query as alias and so on.
42
+ * @todo: [may be need] Combine the entities in each clause.
43
+ */
44
+ export declare abstract class EntityCollector {
45
+ constructor(input: string, caretTokenIndex?: number);
46
+ private readonly _input;
47
+ private readonly _caretTokenIndex;
48
+ private readonly _entitiesSet;
49
+ /** Staging statements that have already entered. */
50
+ private readonly _stmtStack;
51
+ /** Staging entities inside a single statement or clause. */
52
+ private readonly _entityStack;
53
+ /**
54
+ * Always point to the first non-commonStmt at the bottom of the _stmtStack,
55
+ * unless there are only commonStmts in the _stmtStack.
56
+ * */
57
+ private _rootStmt;
58
+ visitTerminal(): void;
59
+ visitErrorNode(): void;
60
+ enterEveryRule(): void;
61
+ exitEveryRule(): void;
62
+ getEntities(): EntityContext[];
63
+ enterProgram(): void;
64
+ protected pushStmt(ctx: ParserRuleContext, type: StmtContextType): StmtContext | null;
65
+ protected popStmt(): StmtContext;
66
+ protected pushEntity(ctx: ParserRuleContext, type: EntityContextType, alias?: BaseAliasContext): EntityContext | null;
67
+ /**
68
+ * Combine entities that inside a single statement.
69
+ * e.g. combine tableName and column if they are inside a same createTableStatement.
70
+ * Then add combined entities into result.
71
+ */
72
+ private combineEntitiesAndAdd;
73
+ /**
74
+ * Combined all entities under a rootStmt.
75
+ */
76
+ protected combineRootStmtEntities(stmtContext: StmtContext, entitiesInsideStmt: EntityContext[]): EntityContext[];
77
+ protected combineCreateTableOrViewStmtEntities(stmtContext: StmtContext, entitiesInsideStmt: EntityContext[]): EntityContext[];
78
+ }
@@ -0,0 +1,191 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import { EntityContextType } from './types';
13
+ import { ctxToText, ctxToWord } from './textAndWord';
14
+ import { SimpleStack } from './simpleStack';
15
+ /**
16
+ * TODO: more stmt type should be supported.
17
+ */
18
+ export var StmtContextType;
19
+ (function (StmtContextType) {
20
+ /** A self-contained and complete statement */
21
+ StmtContextType["COMMON_STMT"] = "commonStmt";
22
+ StmtContextType["CREATE_CATALOG_STMT"] = "createCatalogStmt";
23
+ StmtContextType["CREATE_DATABASE_STMT"] = "createDatabaseStmt";
24
+ StmtContextType["CREATE_TABLE_STMT"] = "createTableStmt";
25
+ StmtContextType["CREATE_VIEW_STMT"] = "createViewStmt";
26
+ StmtContextType["SELECT_STMT"] = "selectStmt";
27
+ StmtContextType["INSERT_STMT"] = "insertStmt";
28
+ StmtContextType["CREATE_FUNCTION_STMT"] = "createFunctionStmt";
29
+ })(StmtContextType || (StmtContextType = {}));
30
+ export function toStmtContext(ctx, type, input, rootStmt, parentStmt, isContainCaret) {
31
+ const text = ctxToText(ctx, input);
32
+ if (!text)
33
+ return null;
34
+ const { text: _ } = text, position = __rest(text, ["text"]);
35
+ return {
36
+ stmtContextType: type,
37
+ position,
38
+ rootStmt: rootStmt !== null && rootStmt !== void 0 ? rootStmt : null,
39
+ parentStmt: parentStmt !== null && parentStmt !== void 0 ? parentStmt : null,
40
+ isContainCaret,
41
+ };
42
+ }
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);
50
+ if (!word)
51
+ 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,
55
+ position,
56
+ belongStmt, relatedEntities: null, columns: null }, finalAlias);
57
+ }
58
+ /**
59
+ * @todo: Handle alias, includes column alias, table alias, query as alias and so on.
60
+ * @todo: [may be need] Combine the entities in each clause.
61
+ */
62
+ export class EntityCollector {
63
+ constructor(input, caretTokenIndex) {
64
+ this._input = input;
65
+ this._caretTokenIndex = caretTokenIndex !== null && caretTokenIndex !== void 0 ? caretTokenIndex : -1;
66
+ this._entitiesSet = new Set();
67
+ this._stmtStack = new SimpleStack();
68
+ this._entityStack = new SimpleStack();
69
+ this._rootStmt = null;
70
+ }
71
+ visitTerminal() { }
72
+ visitErrorNode() { }
73
+ enterEveryRule() { }
74
+ exitEveryRule() { }
75
+ getEntities() {
76
+ return Array.from(this._entitiesSet);
77
+ }
78
+ enterProgram() {
79
+ this._entitiesSet.clear();
80
+ this._stmtStack.clear();
81
+ this._entityStack.clear();
82
+ this._rootStmt = null;
83
+ }
84
+ pushStmt(ctx, type) {
85
+ var _a;
86
+ let isContainCaret;
87
+ if (this._caretTokenIndex >= 0) {
88
+ isContainCaret =
89
+ !!ctx.start &&
90
+ !!ctx.stop &&
91
+ ctx.start.tokenIndex <= this._caretTokenIndex &&
92
+ ctx.stop.tokenIndex >= this._caretTokenIndex;
93
+ }
94
+ const stmtContext = toStmtContext(ctx, type, this._input, this._rootStmt, this._stmtStack.peek(), isContainCaret);
95
+ if (stmtContext) {
96
+ if (this._stmtStack.isEmpty() ||
97
+ ((_a = this._stmtStack.peek()) === null || _a === void 0 ? void 0 : _a.stmtContextType) === StmtContextType.COMMON_STMT) {
98
+ this._rootStmt = stmtContext;
99
+ }
100
+ this._stmtStack.push(stmtContext);
101
+ }
102
+ return stmtContext;
103
+ }
104
+ popStmt() {
105
+ const stmtContext = this._stmtStack.pop();
106
+ if (stmtContext && this._rootStmt === stmtContext) {
107
+ this._rootStmt = this._stmtStack.peek();
108
+ if (!this._entityStack.isEmpty()) {
109
+ this.combineEntitiesAndAdd(stmtContext);
110
+ }
111
+ }
112
+ return stmtContext;
113
+ }
114
+ pushEntity(ctx, type, alias) {
115
+ const entityContext = toEntityContext(ctx, type, this._input, this._stmtStack.peek(), alias);
116
+ if (entityContext) {
117
+ if (this._stmtStack.isEmpty()) {
118
+ this._entitiesSet.add(entityContext);
119
+ }
120
+ else {
121
+ // If is inside a statement
122
+ this._entityStack.push(entityContext);
123
+ }
124
+ }
125
+ return entityContext;
126
+ }
127
+ /**
128
+ * Combine entities that inside a single statement.
129
+ * e.g. combine tableName and column if they are inside a same createTableStatement.
130
+ * Then add combined entities into result.
131
+ */
132
+ combineEntitiesAndAdd(stmtContext) {
133
+ const entitiesInsideStmt = [];
134
+ while (!this._entityStack.isEmpty() &&
135
+ (this._entityStack.peek().belongStmt === stmtContext ||
136
+ this._entityStack.peek().belongStmt.rootStmt === stmtContext)) {
137
+ entitiesInsideStmt.unshift(this._entityStack.pop());
138
+ }
139
+ const combinedEntities = this.combineRootStmtEntities(stmtContext, entitiesInsideStmt);
140
+ while (combinedEntities.length) {
141
+ const entity = combinedEntities.shift();
142
+ entity && this._entitiesSet.add(entity);
143
+ }
144
+ }
145
+ /**
146
+ * Combined all entities under a rootStmt.
147
+ */
148
+ combineRootStmtEntities(stmtContext, entitiesInsideStmt) {
149
+ if (stmtContext.stmtContextType === StmtContextType.CREATE_VIEW_STMT ||
150
+ stmtContext.stmtContextType === StmtContextType.CREATE_TABLE_STMT) {
151
+ return this.combineCreateTableOrViewStmtEntities(stmtContext, entitiesInsideStmt);
152
+ }
153
+ return entitiesInsideStmt;
154
+ }
155
+ combineCreateTableOrViewStmtEntities(stmtContext, entitiesInsideStmt) {
156
+ const columns = [];
157
+ const relatedEntities = [];
158
+ let mainEntity = null;
159
+ const finalEntities = entitiesInsideStmt.reduce((result, entity) => {
160
+ if (entity.belongStmt !== stmtContext) {
161
+ if (entity.entityContextType !== EntityContextType.COLUMN &&
162
+ entity.entityContextType !== EntityContextType.COLUMN_CREATE) {
163
+ relatedEntities.push(entity);
164
+ result.push(entity);
165
+ }
166
+ return result;
167
+ }
168
+ if (entity.entityContextType === EntityContextType.COLUMN_CREATE) {
169
+ columns.push(entity);
170
+ }
171
+ else if (entity.entityContextType === EntityContextType.TABLE_CREATE ||
172
+ entity.entityContextType === EntityContextType.VIEW_CREATE) {
173
+ mainEntity = entity;
174
+ result.push(entity);
175
+ return result;
176
+ }
177
+ else if (entity.entityContextType !== EntityContextType.COLUMN) {
178
+ relatedEntities.push(entity);
179
+ result.push(entity);
180
+ }
181
+ return result;
182
+ }, []);
183
+ if (mainEntity && columns.length) {
184
+ mainEntity.columns = columns;
185
+ }
186
+ if (mainEntity && relatedEntities.length) {
187
+ mainEntity.relatedEntities = relatedEntities;
188
+ }
189
+ return finalEntities;
190
+ }
191
+ }
@@ -1,9 +1,9 @@
1
1
  import { Token } from 'antlr4ng';
2
- import { CaretPosition } from '../basic-parser-types';
2
+ import { CaretPosition } from './types';
3
3
  /**
4
4
  * find token index via caret position (cursor position)
5
5
  * @param caretPosition
6
6
  * @param allTokens all the tokens
7
7
  * @returns caretTokenIndex
8
8
  */
9
- export declare function findCaretTokenIndex(caretPosition: CaretPosition, allTokens: Token[]): number;
9
+ export declare function findCaretTokenIndex(caretPosition: CaretPosition, allTokens: Token[]): number | undefined;
@@ -5,6 +5,7 @@
5
5
  * @returns caretTokenIndex
6
6
  */
7
7
  export function findCaretTokenIndex(caretPosition, allTokens) {
8
+ var _a, _b;
8
9
  const { lineNumber: caretLine, column: caretCol } = caretPosition;
9
10
  let left = 0;
10
11
  let right = allTokens.length - 1;
@@ -15,12 +16,12 @@ export function findCaretTokenIndex(caretPosition, allTokens) {
15
16
  right = mid - 1;
16
17
  }
17
18
  else if (token.line < caretLine ||
18
- (token.line === caretLine && token.column + token.text.length + 1 < caretCol)) {
19
+ (token.line === caretLine && token.column + ((_b = (_a = token.text) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) + 1 < caretCol)) {
19
20
  left = mid + 1;
20
21
  }
21
22
  else {
22
23
  return allTokens[mid].tokenIndex;
23
24
  }
24
25
  }
25
- return null;
26
+ return void 0;
26
27
  }
@@ -16,9 +16,9 @@ export interface ParseError {
16
16
  /**
17
17
  * The type of error resulting from lexical parsing and parsing.
18
18
  */
19
- export interface SyntaxError<T> {
19
+ export interface SyntaxError {
20
20
  readonly recognizer: Recognizer<ATNSimulator>;
21
- readonly offendingSymbol: Token;
21
+ readonly offendingSymbol: Token | null;
22
22
  readonly line: number;
23
23
  readonly charPositionInLine: number;
24
24
  readonly msg: string;
@@ -28,12 +28,12 @@ export interface SyntaxError<T> {
28
28
  * ErrorListener will be invoked when it encounters a parsing error.
29
29
  * Includes lexical errors and parsing errors.
30
30
  */
31
- export type ErrorListener<T> = (parseError: ParseError, originalError: SyntaxError<T>) => void;
32
- export default class ParseErrorListener implements ANTLRErrorListener {
31
+ export type ErrorListener = (parseError: ParseError, originalError: SyntaxError) => void;
32
+ export declare class ParseErrorListener implements ANTLRErrorListener {
33
33
  private _errorListener;
34
- constructor(errorListener: ErrorListener<Token>);
34
+ constructor(errorListener: ErrorListener);
35
35
  reportAmbiguity(): void;
36
36
  reportAttemptingFullContext(): void;
37
37
  reportContextSensitivity(): void;
38
- syntaxError(recognizer: Recognizer<ATNSimulator>, offendingSymbol: any, line: number, charPositionInLine: number, msg: string, e: RecognitionException): void;
38
+ syntaxError(recognizer: Recognizer<ATNSimulator>, offendingSymbol: Token | null, line: number, charPositionInLine: number, msg: string, e: RecognitionException): void;
39
39
  }
@@ -1,4 +1,4 @@
1
- export default class ParseErrorListener {
1
+ export class ParseErrorListener {
2
2
  constructor(errorListener) {
3
3
  this._errorListener = errorListener;
4
4
  }
@@ -0,0 +1,10 @@
1
+ export declare class SimpleStack<T> {
2
+ constructor();
3
+ private stack;
4
+ push(item: T): void;
5
+ pop(): T;
6
+ peek(): T;
7
+ clear(): void;
8
+ size(): number;
9
+ isEmpty(): boolean;
10
+ }