dt-sql-parser 4.0.1 → 4.1.0-beta.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 (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 +11463 -10512
  18. package/dist/lib/mysql/MySqlParserListener.d.ts +42 -20
  19. package/dist/lib/mysql/MySqlParserVisitor.d.ts +26 -12
  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 +7 -2
  39. package/dist/parser/common/basicSQL.js +5 -15
  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 +3 -0
  53. package/dist/parser/flink/index.js +13 -9
  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 +3 -0
  58. package/dist/parser/hive/index.js +13 -9
  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 +3 -0
  63. package/dist/parser/impala/index.js +4 -0
  64. package/dist/parser/mysql/index.d.ts +3 -0
  65. package/dist/parser/mysql/index.js +4 -0
  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 +3 -0
  71. package/dist/parser/postgresql/index.js +17 -13
  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 +3 -0
  77. package/dist/parser/spark/index.js +4 -0
  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 +3 -0
  83. package/dist/parser/trino/index.js +23 -10
  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 +40 -12
@@ -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';
@@ -47,10 +47,15 @@ export declare abstract class BasicSQL<L extends Lexer = Lexer, PRC extends Pars
47
47
  * Get a new splitListener instance.
48
48
  */
49
49
  protected abstract get splitListener(): SplitListener<ParserRuleContext>;
50
+ /**
51
+ * Get a new errorListener instance.
52
+ */
53
+ protected abstract createErrorListener(errorListener: ErrorListener): ANTLRErrorListener;
50
54
  /**
51
55
  * Get a new entityCollector instance.
52
56
  */
53
57
  protected abstract createEntityCollector(input: string, caretTokenIndex?: number): EntityCollector;
58
+ locale: LOCALE_TYPE;
54
59
  /**
55
60
  * Create an antlr4 lexer from input.
56
61
  * @param input string
@@ -2,7 +2,6 @@ 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';
7
6
  /**
8
7
  * Basic SQL class, every sql needs extends it.
@@ -14,6 +13,7 @@ export class BasicSQL {
14
13
  this._errorListener = (error) => {
15
14
  this._parseErrors.push(error);
16
15
  };
16
+ this.locale = 'en_US';
17
17
  }
18
18
  /**
19
19
  * Create an antlr4 lexer from input.
@@ -24,7 +24,7 @@ export class BasicSQL {
24
24
  const lexer = this.createLexerFromCharStream(charStreams);
25
25
  if (errorListener) {
26
26
  lexer.removeErrorListeners();
27
- lexer.addErrorListener(new ParseErrorListener(errorListener));
27
+ lexer.addErrorListener(this.createErrorListener(errorListener));
28
28
  }
29
29
  return lexer;
30
30
  }
@@ -39,7 +39,7 @@ export class BasicSQL {
39
39
  parser.interpreter.predictionMode = PredictionMode.SLL;
40
40
  if (errorListener) {
41
41
  parser.removeErrorListeners();
42
- parser.addErrorListener(new ParseErrorListener(errorListener));
42
+ parser.addErrorListener(this.createErrorListener(errorListener));
43
43
  }
44
44
  return parser;
45
45
  }
@@ -65,7 +65,7 @@ export class BasicSQL {
65
65
  this._charStreams = CharStreams.fromString(input);
66
66
  this._lexer = this.createLexerFromCharStream(this._charStreams);
67
67
  this._lexer.removeErrorListeners();
68
- this._lexer.addErrorListener(new ParseErrorListener(this._errorListener));
68
+ this._lexer.addErrorListener(this.createErrorListener(this._errorListener));
69
69
  this._tokenStream = new CommonTokenStream(this._lexer);
70
70
  /**
71
71
  * All tokens are generated in advance.
@@ -96,7 +96,7 @@ export class BasicSQL {
96
96
  const parser = this.createParserWithCache(input);
97
97
  this._parsedInput = input;
98
98
  parser.removeErrorListeners();
99
- parser.addErrorListener(new ParseErrorListener(this._errorListener));
99
+ parser.addErrorListener(this.createErrorListener(this._errorListener));
100
100
  this._parseTree = parser.program();
101
101
  return this._parseTree;
102
102
  }
@@ -140,9 +140,6 @@ export class BasicSQL {
140
140
  return null;
141
141
  }
142
142
  const splitListener = this.splitListener;
143
- // TODO: add splitListener to all sqlParser implements and remove following if
144
- if (!splitListener)
145
- return null;
146
143
  this.listen(splitListener, this._parseTree);
147
144
  const res = splitListener.statementsContext
148
145
  .map((context) => {
@@ -160,9 +157,6 @@ export class BasicSQL {
160
157
  getSuggestionAtCaretPosition(input, caretPosition) {
161
158
  var _a, _b, _c, _d, _e, _f, _g, _h, _j;
162
159
  const splitListener = this.splitListener;
163
- // TODO: add splitListener to all sqlParser implements and remove following if
164
- if (!splitListener)
165
- return null;
166
160
  this.parseWithCache(input);
167
161
  if (!this._parseTree)
168
162
  return null;
@@ -261,10 +255,6 @@ export class BasicSQL {
261
255
  ? findCaretTokenIndex(caretPosition, allTokens)
262
256
  : void 0;
263
257
  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
258
  // const parser = this.createParserWithCache(input);
269
259
  // parser.entityCollecting = true;
270
260
  // 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
  }
@@ -1,11 +1,92 @@
1
+ import { Token, LexerNoViableAltException, InputMismatchException, NoViableAltException, } from 'antlr4ng';
2
+ import { transform } from './transform';
1
3
  export class ParseErrorListener {
2
- constructor(errorListener) {
4
+ constructor(errorListener, locale = 'en_US') {
5
+ this.locale = locale;
3
6
  this._errorListener = errorListener;
4
7
  }
5
8
  reportAmbiguity() { }
6
9
  reportAttemptingFullContext() { }
7
10
  reportContextSensitivity() { }
8
11
  syntaxError(recognizer, offendingSymbol, line, charPositionInLine, msg, e) {
12
+ var _a;
13
+ let message = '';
14
+ // If not undefined then offendingSymbol is of type Token.
15
+ if (offendingSymbol) {
16
+ let token = offendingSymbol;
17
+ const parser = recognizer;
18
+ // judge token is EOF
19
+ const isEof = token.type === Token.EOF;
20
+ if (isEof) {
21
+ token = parser.tokenStream.get(token.tokenIndex - 1);
22
+ }
23
+ const wrongText = (_a = token.text) !== null && _a !== void 0 ? _a : '';
24
+ const isInComplete = isEof && wrongText !== ' ';
25
+ const expectedText = isInComplete ? '' : this.getExpectedText(parser, token);
26
+ if (!e) {
27
+ // handle missing or unwanted tokens.
28
+ message = msg;
29
+ if (msg.includes('extraneous')) {
30
+ message = `'${wrongText}' {noValidPosition}${expectedText.length ? `{expecting}${expectedText}` : ''}`;
31
+ }
32
+ if (msg.includes('missing')) {
33
+ const regex = /missing\s+'([^']+)'/;
34
+ const match = msg.match(regex);
35
+ message = `{missing}`;
36
+ if (match) {
37
+ const missKeyword = match[1];
38
+ message += `'${missKeyword}'`;
39
+ }
40
+ else {
41
+ message += `{keyword}`;
42
+ }
43
+ message += `{at}'${wrongText}'`;
44
+ }
45
+ }
46
+ else {
47
+ // handle mismatch exception or no viable alt exception
48
+ if (e instanceof InputMismatchException || e instanceof NoViableAltException) {
49
+ if (isEof) {
50
+ message = `{stmtInComplete}`;
51
+ }
52
+ else {
53
+ message = `'${wrongText}' {noValidPosition}`;
54
+ }
55
+ if (expectedText.length > 0) {
56
+ message += `{expecting}${expectedText}`;
57
+ }
58
+ }
59
+ else {
60
+ message = msg;
61
+ }
62
+ }
63
+ }
64
+ else {
65
+ // No offending symbol, which indicates this is a lexer error.
66
+ if (e instanceof LexerNoViableAltException) {
67
+ const lexer = recognizer;
68
+ const input = lexer.inputStream;
69
+ let text = lexer.getErrorDisplay(input.getText(lexer._tokenStartCharIndex, input.index));
70
+ switch (text[0]) {
71
+ case '/':
72
+ message = '{unfinishedMultilineComment}';
73
+ break;
74
+ case '"':
75
+ message = '{unfinishedDoubleQuoted}';
76
+ break;
77
+ case "'":
78
+ message = '{unfinishedSingleQuoted}';
79
+ break;
80
+ case '`':
81
+ message = '{unfinishedTickQuoted}';
82
+ break;
83
+ default:
84
+ message = '"' + text + '" {noValidInput}';
85
+ break;
86
+ }
87
+ }
88
+ }
89
+ message = transform(message, this.locale);
9
90
  let endCol = charPositionInLine + 1;
10
91
  if (offendingSymbol && offendingSymbol.text !== null) {
11
92
  endCol = charPositionInLine + offendingSymbol.text.length;
@@ -16,7 +97,7 @@ export class ParseErrorListener {
16
97
  endLine: line,
17
98
  startColumn: charPositionInLine + 1,
18
99
  endColumn: endCol + 1,
19
- message: msg,
100
+ message,
20
101
  }, {
21
102
  e,
22
103
  line,
@@ -35,18 +35,15 @@ export interface TextSlice extends TextPosition {
35
35
  /**
36
36
  * Convert Token to Word
37
37
  */
38
- export declare function tokenToWord(token: Token, input: string): WordPosition & {
39
- text: string;
40
- };
41
- /**
42
- * Convert ParserRuleContext to Word
43
- */
44
- export declare function ctxToWord(ctx: ParserRuleContext, input: string): (WordPosition & {
45
- text: string;
46
- }) | null;
38
+ export declare function tokenToWord(token: Token, input: string): WordRange;
47
39
  /**
48
40
  * Convert ParserRuleContext to Text
49
41
  */
50
42
  export declare function ctxToText(ctx: ParserRuleContext, input: string): (TextPosition & {
51
43
  text: string;
52
44
  }) | null;
45
+ /**
46
+ * judge whether the context is a WordRange
47
+ * @param textOrWord TextSlice or WordRange object
48
+ * */
49
+ export declare function isWordRange(textOrWord: TextSlice | WordRange): textOrWord is WordRange;