dt-sql-parser 4.4.0-beta.0 → 4.5.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 (53) hide show
  1. package/README.md +140 -3
  2. package/dist/lib/flink/FlinkSqlParser.d.ts +221 -114
  3. package/dist/lib/flink/FlinkSqlParser.js +3608 -2907
  4. package/dist/lib/flink/FlinkSqlParserListener.d.ts +99 -0
  5. package/dist/lib/flink/FlinkSqlParserVisitor.d.ts +63 -0
  6. package/dist/lib/hive/HiveSqlParser.d.ts +169 -116
  7. package/dist/lib/hive/HiveSqlParser.js +5708 -5428
  8. package/dist/lib/hive/HiveSqlParserListener.d.ts +55 -0
  9. package/dist/lib/hive/HiveSqlParserVisitor.d.ts +35 -0
  10. package/dist/lib/impala/ImpalaSqlParser.d.ts +150 -81
  11. package/dist/lib/impala/ImpalaSqlParser.js +3730 -3323
  12. package/dist/lib/impala/ImpalaSqlParserListener.d.ts +76 -14
  13. package/dist/lib/impala/ImpalaSqlParserVisitor.d.ts +48 -8
  14. package/dist/lib/mysql/MySqlParser.d.ts +346 -316
  15. package/dist/lib/mysql/MySqlParser.js +10224 -10020
  16. package/dist/lib/mysql/MySqlParserListener.d.ts +55 -26
  17. package/dist/lib/mysql/MySqlParserVisitor.d.ts +33 -14
  18. package/dist/lib/postgresql/PostgreSqlParser.d.ts +215 -169
  19. package/dist/lib/postgresql/PostgreSqlParser.js +10333 -10051
  20. package/dist/lib/postgresql/PostgreSqlParserListener.d.ts +51 -7
  21. package/dist/lib/postgresql/PostgreSqlParserVisitor.d.ts +32 -4
  22. package/dist/lib/spark/SparkSqlParser.d.ts +215 -90
  23. package/dist/lib/spark/SparkSqlParser.js +5143 -4496
  24. package/dist/lib/spark/SparkSqlParserListener.d.ts +147 -5
  25. package/dist/lib/spark/SparkSqlParserVisitor.d.ts +92 -3
  26. package/dist/lib/trino/TrinoSqlListener.d.ts +90 -37
  27. package/dist/lib/trino/TrinoSqlParser.d.ts +219 -165
  28. package/dist/lib/trino/TrinoSqlParser.js +4942 -4615
  29. package/dist/lib/trino/TrinoSqlVisitor.d.ts +55 -21
  30. package/dist/parser/common/basicSQL.js +2 -0
  31. package/dist/parser/common/entityCollector.d.ts +91 -4
  32. package/dist/parser/common/entityCollector.js +215 -11
  33. package/dist/parser/common/textAndWord.d.ts +9 -1
  34. package/dist/parser/common/textAndWord.js +2 -0
  35. package/dist/parser/common/types.d.ts +2 -0
  36. package/dist/parser/common/types.js +2 -0
  37. package/dist/parser/flink/flinkEntityCollector.d.ts +10 -2
  38. package/dist/parser/flink/flinkEntityCollector.js +76 -14
  39. package/dist/parser/hive/hiveEntityCollector.d.ts +13 -1
  40. package/dist/parser/hive/hiveEntityCollector.js +85 -12
  41. package/dist/parser/impala/impalaEntityCollector.d.ts +7 -1
  42. package/dist/parser/impala/impalaEntityCollector.js +63 -12
  43. package/dist/parser/impala/index.js +2 -1
  44. package/dist/parser/mysql/mysqlEntityCollector.d.ts +9 -1
  45. package/dist/parser/mysql/mysqlEntityCollector.js +55 -12
  46. package/dist/parser/postgresql/postgreEntityCollector.d.ts +10 -1
  47. package/dist/parser/postgresql/postgreEntityCollector.js +86 -22
  48. package/dist/parser/spark/sparkEntityCollector.d.ts +13 -1
  49. package/dist/parser/spark/sparkEntityCollector.js +88 -12
  50. package/dist/parser/trino/index.js +2 -1
  51. package/dist/parser/trino/trinoEntityCollector.d.ts +7 -1
  52. package/dist/parser/trino/trinoEntityCollector.js +53 -12
  53. package/package.json +1 -1
@@ -116,6 +116,7 @@ import { SortItemContext } from "./TrinoSqlParser.js";
116
116
  import { QuerySpecificationContext } from "./TrinoSqlParser.js";
117
117
  import { WhereClauseContext } from "./TrinoSqlParser.js";
118
118
  import { HavingClauseContext } from "./TrinoSqlParser.js";
119
+ import { SelectListContext } from "./TrinoSqlParser.js";
119
120
  import { GroupByContext } from "./TrinoSqlParser.js";
120
121
  import { PartitionByContext } from "./TrinoSqlParser.js";
121
122
  import { SingleGroupingSetContext } from "./TrinoSqlParser.js";
@@ -128,8 +129,11 @@ import { WindowDefinitionContext } from "./TrinoSqlParser.js";
128
129
  import { WindowSpecificationContext } from "./TrinoSqlParser.js";
129
130
  import { NamedQueryContext } from "./TrinoSqlParser.js";
130
131
  import { SetQuantifierContext } from "./TrinoSqlParser.js";
131
- import { SelectSingleContext } from "./TrinoSqlParser.js";
132
- import { SelectAllContext } from "./TrinoSqlParser.js";
132
+ import { SelectItemContext } from "./TrinoSqlParser.js";
133
+ import { SelectAllWithoutTableContext } from "./TrinoSqlParser.js";
134
+ import { TableAllColumnsContext } from "./TrinoSqlParser.js";
135
+ import { SelectLiteralColumnNameContext } from "./TrinoSqlParser.js";
136
+ import { SelectExpressionColumnNameContext } from "./TrinoSqlParser.js";
133
137
  import { RelationDefaultContext } from "./TrinoSqlParser.js";
134
138
  import { JoinRelationContext } from "./TrinoSqlParser.js";
135
139
  import { JoinTypeContext } from "./TrinoSqlParser.js";
@@ -151,11 +155,12 @@ import { ColumnListCreateContext } from "./TrinoSqlParser.js";
151
155
  import { ColumnListContext } from "./TrinoSqlParser.js";
152
156
  import { ColumnAliasesContext } from "./TrinoSqlParser.js";
153
157
  import { TableNameContext } from "./TrinoSqlParser.js";
158
+ import { ExpressionSourceTableContext } from "./TrinoSqlParser.js";
159
+ import { ParenthesizedRelationContext } from "./TrinoSqlParser.js";
154
160
  import { SubqueryRelationContext } from "./TrinoSqlParser.js";
155
161
  import { UnnestContext } from "./TrinoSqlParser.js";
156
162
  import { LateralContext } from "./TrinoSqlParser.js";
157
163
  import { TableFunctionInvocationContext } from "./TrinoSqlParser.js";
158
- import { ParenthesizedRelationContext } from "./TrinoSqlParser.js";
159
164
  import { JsonTableContext } from "./TrinoSqlParser.js";
160
165
  import { OrdinalityColumnContext } from "./TrinoSqlParser.js";
161
166
  import { ValueColumnContext } from "./TrinoSqlParser.js";
@@ -1176,6 +1181,12 @@ export declare class TrinoSqlVisitor<Result> extends AbstractParseTreeVisitor<Re
1176
1181
  * @return the visitor result
1177
1182
  */
1178
1183
  visitHavingClause?: (ctx: HavingClauseContext) => Result;
1184
+ /**
1185
+ * Visit a parse tree produced by `TrinoSqlParser.selectList`.
1186
+ * @param ctx the parse tree
1187
+ * @return the visitor result
1188
+ */
1189
+ visitSelectList?: (ctx: SelectListContext) => Result;
1179
1190
  /**
1180
1191
  * Visit a parse tree produced by `TrinoSqlParser.groupBy`.
1181
1192
  * @param ctx the parse tree
@@ -1253,19 +1264,35 @@ export declare class TrinoSqlVisitor<Result> extends AbstractParseTreeVisitor<Re
1253
1264
  */
1254
1265
  visitSetQuantifier?: (ctx: SetQuantifierContext) => Result;
1255
1266
  /**
1256
- * Visit a parse tree produced by the `selectSingle`
1257
- * labeled alternative in `TrinoSqlParser.selectItem`.
1267
+ * Visit a parse tree produced by `TrinoSqlParser.selectItem`.
1258
1268
  * @param ctx the parse tree
1259
1269
  * @return the visitor result
1260
1270
  */
1261
- visitSelectSingle?: (ctx: SelectSingleContext) => Result;
1271
+ visitSelectItem?: (ctx: SelectItemContext) => Result;
1262
1272
  /**
1263
- * Visit a parse tree produced by the `selectAll`
1264
- * labeled alternative in `TrinoSqlParser.selectItem`.
1273
+ * Visit a parse tree produced by `TrinoSqlParser.selectAllWithoutTable`.
1265
1274
  * @param ctx the parse tree
1266
1275
  * @return the visitor result
1267
1276
  */
1268
- visitSelectAll?: (ctx: SelectAllContext) => Result;
1277
+ visitSelectAllWithoutTable?: (ctx: SelectAllWithoutTableContext) => Result;
1278
+ /**
1279
+ * Visit a parse tree produced by `TrinoSqlParser.tableAllColumns`.
1280
+ * @param ctx the parse tree
1281
+ * @return the visitor result
1282
+ */
1283
+ visitTableAllColumns?: (ctx: TableAllColumnsContext) => Result;
1284
+ /**
1285
+ * Visit a parse tree produced by `TrinoSqlParser.selectLiteralColumnName`.
1286
+ * @param ctx the parse tree
1287
+ * @return the visitor result
1288
+ */
1289
+ visitSelectLiteralColumnName?: (ctx: SelectLiteralColumnNameContext) => Result;
1290
+ /**
1291
+ * Visit a parse tree produced by `TrinoSqlParser.selectExpressionColumnName`.
1292
+ * @param ctx the parse tree
1293
+ * @return the visitor result
1294
+ */
1295
+ visitSelectExpressionColumnName?: (ctx: SelectExpressionColumnNameContext) => Result;
1269
1296
  /**
1270
1297
  * Visit a parse tree produced by the `relationDefault`
1271
1298
  * labeled alternative in `TrinoSqlParser.relation`.
@@ -1396,43 +1423,50 @@ export declare class TrinoSqlVisitor<Result> extends AbstractParseTreeVisitor<Re
1396
1423
  */
1397
1424
  visitTableName?: (ctx: TableNameContext) => Result;
1398
1425
  /**
1399
- * Visit a parse tree produced by the `subqueryRelation`
1426
+ * Visit a parse tree produced by the `expressionSourceTable`
1427
+ * labeled alternative in `TrinoSqlParser.relationPrimary`.
1428
+ * @param ctx the parse tree
1429
+ * @return the visitor result
1430
+ */
1431
+ visitExpressionSourceTable?: (ctx: ExpressionSourceTableContext) => Result;
1432
+ /**
1433
+ * Visit a parse tree produced by the `parenthesizedRelation`
1400
1434
  * labeled alternative in `TrinoSqlParser.relationPrimary`.
1401
1435
  * @param ctx the parse tree
1402
1436
  * @return the visitor result
1403
1437
  */
1438
+ visitParenthesizedRelation?: (ctx: ParenthesizedRelationContext) => Result;
1439
+ /**
1440
+ * Visit a parse tree produced by the `subqueryRelation`
1441
+ * labeled alternative in `TrinoSqlParser.relationSourceTable`.
1442
+ * @param ctx the parse tree
1443
+ * @return the visitor result
1444
+ */
1404
1445
  visitSubqueryRelation?: (ctx: SubqueryRelationContext) => Result;
1405
1446
  /**
1406
1447
  * Visit a parse tree produced by the `unnest`
1407
- * labeled alternative in `TrinoSqlParser.relationPrimary`.
1448
+ * labeled alternative in `TrinoSqlParser.relationSourceTable`.
1408
1449
  * @param ctx the parse tree
1409
1450
  * @return the visitor result
1410
1451
  */
1411
1452
  visitUnnest?: (ctx: UnnestContext) => Result;
1412
1453
  /**
1413
1454
  * Visit a parse tree produced by the `lateral`
1414
- * labeled alternative in `TrinoSqlParser.relationPrimary`.
1455
+ * labeled alternative in `TrinoSqlParser.relationSourceTable`.
1415
1456
  * @param ctx the parse tree
1416
1457
  * @return the visitor result
1417
1458
  */
1418
1459
  visitLateral?: (ctx: LateralContext) => Result;
1419
1460
  /**
1420
1461
  * Visit a parse tree produced by the `tableFunctionInvocation`
1421
- * labeled alternative in `TrinoSqlParser.relationPrimary`.
1462
+ * labeled alternative in `TrinoSqlParser.relationSourceTable`.
1422
1463
  * @param ctx the parse tree
1423
1464
  * @return the visitor result
1424
1465
  */
1425
1466
  visitTableFunctionInvocation?: (ctx: TableFunctionInvocationContext) => Result;
1426
- /**
1427
- * Visit a parse tree produced by the `parenthesizedRelation`
1428
- * labeled alternative in `TrinoSqlParser.relationPrimary`.
1429
- * @param ctx the parse tree
1430
- * @return the visitor result
1431
- */
1432
- visitParenthesizedRelation?: (ctx: ParenthesizedRelationContext) => Result;
1433
1467
  /**
1434
1468
  * Visit a parse tree produced by the `jsonTable`
1435
- * labeled alternative in `TrinoSqlParser.relationPrimary`.
1469
+ * labeled alternative in `TrinoSqlParser.relationSourceTable`.
1436
1470
  * @param ctx the parse tree
1437
1471
  * @return the visitor result
1438
1472
  */
@@ -359,6 +359,8 @@ export class BasicSQL {
359
359
  }
360
360
  const core = new CodeCompletionCore(sqlParserIns);
361
361
  core.preferredRules = this.preferredRules;
362
+ // core.showRuleStack = true;
363
+ // core.showResult = true;
362
364
  const candidates = core.collectCandidates(caretTokenIndex, parseTree);
363
365
  const originalSuggestions = this.processCandidates(candidates, allTokens, caretTokenIndex);
364
366
  const syntaxSuggestions = originalSuggestions.syntax.map((syntaxCtx) => {
@@ -22,6 +22,8 @@ export interface StmtContext {
22
22
  readonly rootStmt: StmtContext | null;
23
23
  readonly parentStmt: StmtContext | null;
24
24
  readonly isContainCaret?: boolean;
25
+ readonly scopeDepth: number;
26
+ readonly text: string;
25
27
  }
26
28
  export declare function toStmtContext(ctx: ParserRuleContext, type: StmtContextType, input: string, rootStmt: StmtContext | null, parentStmt: StmtContext | null, isContainCaret?: boolean): StmtContext | null;
27
29
  /**
@@ -49,31 +51,77 @@ export interface Argument {
49
51
  argName?: WordRange;
50
52
  argType: WordRange;
51
53
  }
54
+ /**
55
+ * Base interface for all entity contexts in SQL parsing
56
+ */
52
57
  export interface BaseEntityContext {
58
+ /** The type of entity context */
53
59
  readonly entityContextType: EntityContextType;
60
+ /** The text representation of this entity */
54
61
  readonly text: string;
62
+ /** The position information for this entity */
55
63
  readonly position: WordPosition;
64
+ /** The statement this entity belongs to */
56
65
  readonly belongStmt: StmtContext;
66
+ /** Reference to another entity or string */
57
67
  reference?: string | EntityContext;
68
+ /** Whether the entity is accessible from the caret position, **ONLY** applicable to table entity */
69
+ isAccessible: boolean | null;
70
+ /** Entities related to this entity */
71
+ relatedEntities: EntityContext[] | null;
72
+ /** Comment attribute for this entity */
58
73
  [AttrName.comment]: WordRange | null;
74
+ /** Alias attribute for this entity */
59
75
  [AttrName.alias]?: WordRange | null;
60
76
  }
77
+ /**
78
+ * Types of column declarations
79
+ */
80
+ export declare enum ColumnDeclareType {
81
+ /** Literal column name */
82
+ LITERAL = 0,
83
+ /** Using asterisk syntax (tableName.*) */
84
+ ALL = 1,
85
+ /** Complex expressions like subqueries, case statements, function calls */
86
+ EXPRESSION = 2
87
+ }
88
+ /**
89
+ * Types of table declarations
90
+ */
91
+ export declare enum TableDeclareType {
92
+ /** Regular table reference */
93
+ LITERAL = 0,
94
+ /** Table defined by expression (e.g., subquery) */
95
+ EXPRESSION = 1
96
+ }
61
97
  export interface CommonEntityContext extends BaseEntityContext {
62
- relatedEntities: CommonEntityContext[] | null;
98
+ /** Columns associated with this entity */
63
99
  columns?: ColumnEntityContext[];
100
+ /** Type of table declaration */
101
+ declareType?: TableDeclareType;
64
102
  }
65
103
  export interface ColumnEntityContext extends BaseEntityContext {
104
+ /** Type of column declaration */
105
+ declareType?: ColumnDeclareType;
106
+ /** Column type information */
66
107
  [AttrName.colType]: WordRange | null;
108
+ /** Column alias */
109
+ [AttrName.alias]?: WordRange | null;
67
110
  }
68
111
  export interface FuncEntityContext extends BaseEntityContext {
69
- relatedEntities: CommonEntityContext[] | null;
112
+ /** Function arguments */
70
113
  arguments: Argument[] | null;
114
+ /** Function return value */
71
115
  returns?: Argument;
72
116
  }
73
117
  export type EntityContext = CommonEntityContext | FuncEntityContext | ColumnEntityContext;
74
118
  export declare function isCommonEntityContext(entity: EntityContext): entity is CommonEntityContext;
75
119
  export declare function isFuncEntityContext(entity: EntityContext): entity is FuncEntityContext;
76
120
  export declare function isColumnEntityContext(entity: EntityContext): entity is ColumnEntityContext;
121
+ /**
122
+ * Check if ctx is a child node of a specific rule type
123
+ */
124
+ export declare function isChildContextOf(ctx: ParserRuleContext, parentRuleIndex: number): boolean;
77
125
  /**
78
126
  * what we need when collect attribute information
79
127
  * */
@@ -81,7 +129,10 @@ interface AttrInfo {
81
129
  attrName: AttrName;
82
130
  endContextList: string[];
83
131
  }
84
- export declare function toEntityContext(ctx: ParserRuleContext, type: EntityContextType, input: string, belongStmt: StmtContext, attrInfo?: AttrInfo[]): EntityContext | null;
132
+ interface MetaInfo {
133
+ declareType: TableDeclareType | ColumnDeclareType;
134
+ }
135
+ export declare function toEntityContext(ctx: ParserRuleContext, type: EntityContextType, input: string, belongStmt: StmtContext, attrInfo?: AttrInfo[], metaInfo?: MetaInfo): EntityContext | null;
85
136
  export declare function findAttribute(ctx: ParserRuleContextWithAttr | null, keyName: AttrName, endContextNameList: string[]): Token | null;
86
137
  /**
87
138
  * @todo: Handle alias, includes column alias, table alias, query as alias and so on.
@@ -97,6 +148,16 @@ export declare abstract class EntityCollector {
97
148
  private readonly _stmtStack;
98
149
  /** Staging entities inside a single statement or clause. */
99
150
  private readonly _entityStack;
151
+ /**
152
+ * The scope depth of the statement containing the caret.
153
+ * This is used to determine the accessibility of entities.
154
+ */
155
+ private _caretStmtScopeDepth;
156
+ /**
157
+ * The nearest statement containing the caret,
158
+ * Not used for now.
159
+ */
160
+ private _caretStmt;
100
161
  /**
101
162
  * Always point to the first non-commonStmt at the bottom of the _stmtStack,
102
163
  * unless there are only commonStmts in the _stmtStack.
@@ -109,6 +170,30 @@ export declare abstract class EntityCollector {
109
170
  getRootStmt(): StmtContext | null;
110
171
  getEntities(): EntityContext[];
111
172
  enterProgram(): void;
173
+ exitProgram(): void;
174
+ /**
175
+ * Adds accessibility markers to entities
176
+ * @param entities The list of entities to process
177
+ */
178
+ protected attachAccessibleToEntities(entities: EntityContext[]): void;
179
+ /**
180
+ * Attach query result to column if the column is derived from expression.
181
+ */
182
+ protected attachQueryResultToColumn(column: ColumnEntityContext, queryResults: CommonEntityContext[]): void;
183
+ /**
184
+ * Attach related columns to query result
185
+ */
186
+ protected attachColumnsToQueryResult(queryResult: CommonEntityContext, columns: ColumnEntityContext[]): void;
187
+ /**
188
+ * Attach query result to table if the table is derived from expression.
189
+ */
190
+ protected attachQueryResultToTable(table: CommonEntityContext, queryResults: CommonEntityContext[]): void;
191
+ /**
192
+ * Gets query result entities inside a statement
193
+ * @param stmt The statement to search within
194
+ * @returns Array of query result entity contexts
195
+ */
196
+ protected getQueryResultEntitiesInsideStmt(stmt: StmtContext): CommonEntityContext[];
112
197
  /**
113
198
  * The antlr4 will ignore hidden tokens, if we type whitespace at the end of a statement,
114
199
  * the whitespace token will not as stop token, so we consider the whitespace token as a part of the nonhidden token in front of it
@@ -116,7 +201,7 @@ export declare abstract class EntityCollector {
116
201
  protected getPrevNonHiddenTokenIndex(caretTokenIndex: number): number;
117
202
  protected pushStmt(ctx: ParserRuleContext, type: StmtContextType): StmtContext | null;
118
203
  protected popStmt(): StmtContext;
119
- protected pushEntity(ctx: ParserRuleContext, type: EntityContextType, attrInfo?: AttrInfo[]): EntityContext | null;
204
+ protected pushEntity(ctx: ParserRuleContext, type: EntityContextType, attrInfo?: AttrInfo[], metaInfo?: MetaInfo): EntityContext | null;
120
205
  /**
121
206
  * Combine entities that inside a single statement.
122
207
  * e.g. combine tableName and column if they are inside a same createTableStatement.
@@ -127,6 +212,8 @@ export declare abstract class EntityCollector {
127
212
  * Combined all entities under a rootStmt.
128
213
  */
129
214
  protected combineRootStmtEntities(stmtContext: StmtContext, entitiesInsideStmt: EntityContext[]): EntityContext[];
215
+ protected combineQueryResultStmtEntities(stmtContext: StmtContext, entitiesInsideStmt: EntityContext[]): EntityContext[];
216
+ protected combineFromTableSource(stmtContext: StmtContext, entitiesInsideStmt: EntityContext[]): EntityContext[];
130
217
  protected combineCreateTableOrViewStmtEntities(stmtContext: StmtContext, entitiesInsideStmt: EntityContext[]): EntityContext[];
131
218
  }
132
219
  export {};
@@ -30,16 +30,19 @@ export var StmtContextType;
30
30
  StmtContextType["ALTER_TABLE_STMT"] = "alterTableStmt";
31
31
  })(StmtContextType || (StmtContextType = {}));
32
32
  export function toStmtContext(ctx, type, input, rootStmt, parentStmt, isContainCaret) {
33
+ var _a;
33
34
  const text = ctxToText(ctx, input);
34
35
  if (!text)
35
36
  return null;
36
- const { text: _ } = text, position = __rest(text, ["text"]);
37
+ const { text: stmtText } = text, position = __rest(text, ["text"]);
37
38
  return {
38
39
  stmtContextType: type,
39
40
  position,
40
41
  rootStmt: rootStmt !== null && rootStmt !== void 0 ? rootStmt : null,
41
42
  parentStmt: parentStmt !== null && parentStmt !== void 0 ? parentStmt : null,
42
43
  isContainCaret,
44
+ text: stmtText,
45
+ scopeDepth: type === StmtContextType.COMMON_STMT ? 0 : ((_a = parentStmt === null || parentStmt === void 0 ? void 0 : parentStmt.scopeDepth) !== null && _a !== void 0 ? _a : 0) + 1,
43
46
  };
44
47
  }
45
48
  /**
@@ -54,22 +57,56 @@ export var AttrName;
54
57
  AttrName["colType"] = "_colType";
55
58
  AttrName["alias"] = "_alias";
56
59
  })(AttrName || (AttrName = {}));
60
+ /**
61
+ * Types of column declarations
62
+ */
63
+ export var ColumnDeclareType;
64
+ (function (ColumnDeclareType) {
65
+ /** Literal column name */
66
+ ColumnDeclareType[ColumnDeclareType["LITERAL"] = 0] = "LITERAL";
67
+ /** Using asterisk syntax (tableName.*) */
68
+ ColumnDeclareType[ColumnDeclareType["ALL"] = 1] = "ALL";
69
+ /** Complex expressions like subqueries, case statements, function calls */
70
+ ColumnDeclareType[ColumnDeclareType["EXPRESSION"] = 2] = "EXPRESSION";
71
+ })(ColumnDeclareType || (ColumnDeclareType = {}));
72
+ /**
73
+ * Types of table declarations
74
+ */
75
+ export var TableDeclareType;
76
+ (function (TableDeclareType) {
77
+ /** Regular table reference */
78
+ TableDeclareType[TableDeclareType["LITERAL"] = 0] = "LITERAL";
79
+ /** Table defined by expression (e.g., subquery) */
80
+ TableDeclareType[TableDeclareType["EXPRESSION"] = 1] = "EXPRESSION";
81
+ })(TableDeclareType || (TableDeclareType = {}));
57
82
  export function isCommonEntityContext(entity) {
58
83
  if (!entity)
59
84
  return false;
60
- return 'relatedEntities' in entity && !('arguments' in entity);
85
+ return !isFuncEntityContext(entity) && !isColumnEntityContext(entity);
61
86
  }
62
87
  export function isFuncEntityContext(entity) {
63
88
  if (!entity)
64
89
  return false;
65
- return 'arguments' in entity;
90
+ return [EntityContextType.FUNCTION, EntityContextType.FUNCTION_CREATE].includes(entity.entityContextType);
66
91
  }
67
92
  export function isColumnEntityContext(entity) {
68
93
  if (!entity)
69
94
  return false;
70
- return AttrName.colType in entity;
95
+ return [EntityContextType.COLUMN, EntityContextType.COLUMN_CREATE].includes(entity.entityContextType);
96
+ }
97
+ /**
98
+ * Check if ctx is a child node of a specific rule type
99
+ */
100
+ export function isChildContextOf(ctx, parentRuleIndex) {
101
+ let parentCtx = ctx.parent;
102
+ while (parentCtx) {
103
+ if (parentCtx.ruleIndex === parentRuleIndex)
104
+ return true;
105
+ parentCtx = parentCtx.parent;
106
+ }
107
+ return false;
71
108
  }
72
- export function toEntityContext(ctx, type, input, belongStmt, attrInfo) {
109
+ export function toEntityContext(ctx, type, input, belongStmt, attrInfo, metaInfo) {
73
110
  var _a, _b;
74
111
  const word = ctxToText(ctx, input);
75
112
  if (!word)
@@ -81,6 +118,7 @@ export function toEntityContext(ctx, type, input, belongStmt, attrInfo) {
81
118
  text,
82
119
  position,
83
120
  belongStmt,
121
+ declareType: metaInfo === null || metaInfo === void 0 ? void 0 : metaInfo.declareType,
84
122
  [AttrName.comment]: null,
85
123
  };
86
124
  switch (entityInfo.entityContextType) {
@@ -168,6 +206,24 @@ function findAttributeChildren(ctx, keyName) {
168
206
  }
169
207
  return attrVal;
170
208
  }
209
+ /**
210
+ * Check if an entity is contained within the range entity's context
211
+ * @param entity - The entity to check if it's contained
212
+ * @param rangeEntity - The entity that defines the containing range
213
+ * @returns true if entity is contained within rangeEntity's range
214
+ */
215
+ function isEntityInScope(entity, rangeEntity) {
216
+ const entityStart = entity.position.startTokenIndex;
217
+ const entityStop = entity.position.endTokenIndex;
218
+ const rangeStart = rangeEntity.position.startTokenIndex;
219
+ const rangeStop = rangeEntity.position.endTokenIndex;
220
+ return (entityStart != null &&
221
+ entityStop != null &&
222
+ rangeStart != null &&
223
+ rangeStop != null &&
224
+ rangeStart <= entityStart &&
225
+ rangeStop >= entityStop);
226
+ }
171
227
  /**
172
228
  * @todo: Handle alias, includes column alias, table alias, query as alias and so on.
173
229
  * @todo: [may be need] Combine the entities in each clause.
@@ -181,6 +237,8 @@ export class EntityCollector {
181
237
  this._stmtStack = new SimpleStack();
182
238
  this._entityStack = new SimpleStack();
183
239
  this._rootStmt = null;
240
+ this._caretStmtScopeDepth = 0;
241
+ this._caretStmt = null;
184
242
  }
185
243
  visitTerminal() { }
186
244
  visitErrorNode() { }
@@ -198,6 +256,78 @@ export class EntityCollector {
198
256
  this._entityStack.clear();
199
257
  this._rootStmt = null;
200
258
  }
259
+ exitProgram() {
260
+ const entities = Array.from(this._entitiesSet);
261
+ if (this._caretTokenIndex !== -1) {
262
+ this.attachAccessibleToEntities(entities);
263
+ }
264
+ this._entityStack.clear();
265
+ }
266
+ /**
267
+ * Adds accessibility markers to entities
268
+ * @param entities The list of entities to process
269
+ */
270
+ attachAccessibleToEntities(entities) {
271
+ var _a;
272
+ if (!entities.length) {
273
+ return;
274
+ }
275
+ for (const entity of entities) {
276
+ if (entity.isAccessible !== undefined) {
277
+ continue;
278
+ }
279
+ const entityScopeDepth = (_a = entity.belongStmt.scopeDepth) !== null && _a !== void 0 ? _a : 0;
280
+ if (entity.entityContextType === EntityContextType.TABLE) {
281
+ entity.isAccessible =
282
+ !!entity.belongStmt.isContainCaret &&
283
+ entityScopeDepth === this._caretStmtScopeDepth;
284
+ }
285
+ else {
286
+ entity.isAccessible = null;
287
+ }
288
+ // Recursively process related entities
289
+ if (entity.relatedEntities) {
290
+ this.attachAccessibleToEntities(entity.relatedEntities);
291
+ }
292
+ // Process columns of the table
293
+ if (entity.columns) {
294
+ const columnEntities = entity.columns || [];
295
+ this.attachAccessibleToEntities(columnEntities);
296
+ }
297
+ }
298
+ }
299
+ /**
300
+ * Attach query result to column if the column is derived from expression.
301
+ */
302
+ attachQueryResultToColumn(column, queryResults) {
303
+ const relatedEntities = queryResults.filter((queryResult) => isEntityInScope(queryResult, column));
304
+ column.relatedEntities = relatedEntities;
305
+ }
306
+ /**
307
+ * Attach related columns to query result
308
+ */
309
+ attachColumnsToQueryResult(queryResult, columns) {
310
+ const relatedColumns = columns.filter((column) => column.belongStmt === queryResult.belongStmt);
311
+ queryResult.columns = relatedColumns;
312
+ }
313
+ /**
314
+ * Attach query result to table if the table is derived from expression.
315
+ */
316
+ attachQueryResultToTable(table, queryResults) {
317
+ const relatedQueryResults = queryResults.filter((queryResult) => isEntityInScope(queryResult, table));
318
+ table.relatedEntities = relatedQueryResults;
319
+ }
320
+ /**
321
+ * Gets query result entities inside a statement
322
+ * @param stmt The statement to search within
323
+ * @returns Array of query result entity contexts
324
+ */
325
+ getQueryResultEntitiesInsideStmt(stmt) {
326
+ return this.getEntities()
327
+ .filter((entity) => entity.entityContextType === EntityContextType.QUERY_RESULT &&
328
+ entity.belongStmt.parentStmt === stmt)
329
+ .filter(isCommonEntityContext);
330
+ }
201
331
  /**
202
332
  * The antlr4 will ignore hidden tokens, if we type whitespace at the end of a statement,
203
333
  * the whitespace token will not as stop token, so we consider the whitespace token as a part of the nonhidden token in front of it
@@ -223,6 +353,9 @@ export class EntityCollector {
223
353
  !!ctx.stop &&
224
354
  ctx.start.tokenIndex <= this._caretTokenIndex &&
225
355
  ctx.stop.tokenIndex >= this.getPrevNonHiddenTokenIndex(this._caretTokenIndex);
356
+ if (isContainCaret && type !== StmtContextType.COMMON_STMT) {
357
+ this._caretStmtScopeDepth++;
358
+ }
226
359
  }
227
360
  const stmtContext = toStmtContext(ctx, type, this._input, this._rootStmt, this._stmtStack.peek(), isContainCaret);
228
361
  if (stmtContext) {
@@ -236,16 +369,24 @@ export class EntityCollector {
236
369
  }
237
370
  popStmt() {
238
371
  const stmtContext = this._stmtStack.pop();
239
- if (stmtContext && this._rootStmt === stmtContext) {
240
- this._rootStmt = this._stmtStack.peek();
372
+ if (stmtContext) {
373
+ if (stmtContext.stmtContextType === StmtContextType.COMMON_STMT) {
374
+ this._rootStmt = this._stmtStack.peek();
375
+ }
241
376
  if (!this._entityStack.isEmpty()) {
242
377
  this.combineEntitiesAndAdd(stmtContext);
243
378
  }
379
+ // If the current statement contains the caret and its scope depth equals the caret statement's scope depth
380
+ // then set it as the nearest statement containing the caret
381
+ if (stmtContext.isContainCaret &&
382
+ stmtContext.scopeDepth === this._caretStmtScopeDepth) {
383
+ this._caretStmt = stmtContext;
384
+ }
244
385
  }
245
386
  return stmtContext;
246
387
  }
247
- pushEntity(ctx, type, attrInfo) {
248
- const entityContext = toEntityContext(ctx, type, this._input, this._stmtStack.peek(), attrInfo);
388
+ pushEntity(ctx, type, attrInfo, metaInfo) {
389
+ const entityContext = toEntityContext(ctx, type, this._input, this._stmtStack.peek(), attrInfo, metaInfo);
249
390
  if (entityContext) {
250
391
  if (this._stmtStack.isEmpty()) {
251
392
  this._entitiesSet.add(entityContext);
@@ -283,13 +424,76 @@ export class EntityCollector {
283
424
  stmtContext.stmtContextType === StmtContextType.CREATE_TABLE_STMT) {
284
425
  return this.combineCreateTableOrViewStmtEntities(stmtContext, entitiesInsideStmt);
285
426
  }
286
- return entitiesInsideStmt;
427
+ else if (stmtContext.stmtContextType === StmtContextType.SELECT_STMT) {
428
+ const tableSourceEntities = this.combineFromTableSource(stmtContext, entitiesInsideStmt);
429
+ const queryResultEntities = this.combineQueryResultStmtEntities(stmtContext, entitiesInsideStmt);
430
+ const otherEntities = entitiesInsideStmt.filter((entity) => ![
431
+ EntityContextType.QUERY_RESULT,
432
+ EntityContextType.TABLE,
433
+ EntityContextType.COLUMN,
434
+ ].includes(entity.entityContextType));
435
+ return Array.from(new Set([...tableSourceEntities, ...queryResultEntities, ...otherEntities]));
436
+ }
437
+ else {
438
+ // Do not collect column and queryResult entities if they are not inside a select statement
439
+ return entitiesInsideStmt.filter((entity) => entity.entityContextType !== EntityContextType.COLUMN &&
440
+ entity.entityContextType !== EntityContextType.QUERY_RESULT);
441
+ }
442
+ }
443
+ combineQueryResultStmtEntities(stmtContext, entitiesInsideStmt) {
444
+ if (!stmtContext || !(entitiesInsideStmt === null || entitiesInsideStmt === void 0 ? void 0 : entitiesInsideStmt.length)) {
445
+ return [];
446
+ }
447
+ const columnEntities = [];
448
+ const relatedTableEntities = [];
449
+ const finalEntities = [];
450
+ const queryResultEntitiesInsideStmt = this.getQueryResultEntitiesInsideStmt(stmtContext);
451
+ // Categorize and process entities
452
+ entitiesInsideStmt.forEach((entity) => {
453
+ if (entity.belongStmt !== stmtContext)
454
+ return;
455
+ if (entity.entityContextType === EntityContextType.QUERY_RESULT &&
456
+ isCommonEntityContext(entity)) {
457
+ finalEntities.push(entity);
458
+ }
459
+ else if (entity.entityContextType === EntityContextType.COLUMN &&
460
+ isColumnEntityContext(entity)) {
461
+ if (entity.declareType === ColumnDeclareType.EXPRESSION) {
462
+ this.attachQueryResultToColumn(entity, queryResultEntitiesInsideStmt);
463
+ }
464
+ columnEntities.push(entity);
465
+ }
466
+ else if (entity.entityContextType === EntityContextType.TABLE &&
467
+ isCommonEntityContext(entity)) {
468
+ relatedTableEntities.push(entity);
469
+ }
470
+ });
471
+ // combine collected entities to query result entity
472
+ finalEntities.forEach((queryResultEntity) => {
473
+ this.attachColumnsToQueryResult(queryResultEntity, columnEntities);
474
+ queryResultEntity.relatedEntities = relatedTableEntities;
475
+ });
476
+ return finalEntities;
477
+ }
478
+ combineFromTableSource(stmtContext, entitiesInsideStmt) {
479
+ const finalEntities = [];
480
+ const queryResultEntitiesInsideStmt = this.getQueryResultEntitiesInsideStmt(stmtContext);
481
+ const tableEntities = (entitiesInsideStmt.filter((entity) => entity.entityContextType === EntityContextType.TABLE));
482
+ tableEntities.forEach((table) => {
483
+ // If it's an EXPRESSION type (subquery), need to associate with QUERY_RESULT entities
484
+ if (table.declareType === TableDeclareType.EXPRESSION) {
485
+ this.attachQueryResultToTable(table, queryResultEntitiesInsideStmt);
486
+ }
487
+ finalEntities.push(table);
488
+ });
489
+ return finalEntities;
287
490
  }
288
491
  combineCreateTableOrViewStmtEntities(stmtContext, entitiesInsideStmt) {
289
492
  const columns = [];
290
493
  const relatedEntities = [];
494
+ const queryResultEntitiesInsideStmt = this.getQueryResultEntitiesInsideStmt(stmtContext);
291
495
  let mainEntity = null;
292
- const finalEntities = entitiesInsideStmt.reduce((result, entity) => {
496
+ const finalEntities = [...entitiesInsideStmt, ...queryResultEntitiesInsideStmt].reduce((result, entity) => {
293
497
  if (entity.belongStmt !== stmtContext) {
294
498
  if (entity.entityContextType !== EntityContextType.COLUMN &&
295
499
  entity.entityContextType !== EntityContextType.COLUMN_CREATE) {
@@ -10,8 +10,12 @@ export interface WordPosition {
10
10
  readonly startColumn: number;
11
11
  /** end at ..n + 1 */
12
12
  readonly endColumn: number;
13
+ /** start at 0 */
14
+ readonly startTokenIndex: number;
15
+ /** end at ..n-1 */
16
+ readonly endTokenIndex: number;
13
17
  }
14
- export interface WordRange extends WordPosition {
18
+ export interface WordRange extends Omit<WordPosition, 'startTokenIndex' | 'endTokenIndex'> {
15
19
  /** content of word */
16
20
  readonly text: string;
17
21
  }
@@ -28,6 +32,10 @@ export interface TextPosition {
28
32
  readonly startColumn: number;
29
33
  /** end at ..n + 1 */
30
34
  readonly endColumn: number;
35
+ /** start at 0 */
36
+ readonly startTokenIndex: number;
37
+ /** end at ..n-1 */
38
+ readonly endTokenIndex: number;
31
39
  }
32
40
  export interface TextSlice extends TextPosition {
33
41
  readonly text: string;