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.
- package/README.md +140 -3
- package/dist/lib/flink/FlinkSqlParser.d.ts +221 -114
- package/dist/lib/flink/FlinkSqlParser.js +3608 -2907
- package/dist/lib/flink/FlinkSqlParserListener.d.ts +99 -0
- package/dist/lib/flink/FlinkSqlParserVisitor.d.ts +63 -0
- package/dist/lib/hive/HiveSqlParser.d.ts +169 -116
- package/dist/lib/hive/HiveSqlParser.js +5708 -5428
- package/dist/lib/hive/HiveSqlParserListener.d.ts +55 -0
- package/dist/lib/hive/HiveSqlParserVisitor.d.ts +35 -0
- package/dist/lib/impala/ImpalaSqlParser.d.ts +150 -81
- package/dist/lib/impala/ImpalaSqlParser.js +3730 -3323
- package/dist/lib/impala/ImpalaSqlParserListener.d.ts +76 -14
- package/dist/lib/impala/ImpalaSqlParserVisitor.d.ts +48 -8
- package/dist/lib/mysql/MySqlParser.d.ts +346 -316
- package/dist/lib/mysql/MySqlParser.js +10224 -10020
- package/dist/lib/mysql/MySqlParserListener.d.ts +55 -26
- package/dist/lib/mysql/MySqlParserVisitor.d.ts +33 -14
- package/dist/lib/postgresql/PostgreSqlParser.d.ts +215 -169
- package/dist/lib/postgresql/PostgreSqlParser.js +10333 -10051
- package/dist/lib/postgresql/PostgreSqlParserListener.d.ts +51 -7
- package/dist/lib/postgresql/PostgreSqlParserVisitor.d.ts +32 -4
- package/dist/lib/spark/SparkSqlParser.d.ts +215 -90
- package/dist/lib/spark/SparkSqlParser.js +5143 -4496
- package/dist/lib/spark/SparkSqlParserListener.d.ts +147 -5
- package/dist/lib/spark/SparkSqlParserVisitor.d.ts +92 -3
- package/dist/lib/trino/TrinoSqlListener.d.ts +90 -37
- package/dist/lib/trino/TrinoSqlParser.d.ts +219 -165
- package/dist/lib/trino/TrinoSqlParser.js +4942 -4615
- package/dist/lib/trino/TrinoSqlVisitor.d.ts +55 -21
- package/dist/parser/common/basicSQL.js +2 -0
- package/dist/parser/common/entityCollector.d.ts +91 -4
- package/dist/parser/common/entityCollector.js +215 -11
- package/dist/parser/common/textAndWord.d.ts +9 -1
- package/dist/parser/common/textAndWord.js +2 -0
- package/dist/parser/common/types.d.ts +2 -0
- package/dist/parser/common/types.js +2 -0
- package/dist/parser/flink/flinkEntityCollector.d.ts +10 -2
- package/dist/parser/flink/flinkEntityCollector.js +76 -14
- package/dist/parser/hive/hiveEntityCollector.d.ts +13 -1
- package/dist/parser/hive/hiveEntityCollector.js +85 -12
- package/dist/parser/impala/impalaEntityCollector.d.ts +7 -1
- package/dist/parser/impala/impalaEntityCollector.js +63 -12
- package/dist/parser/impala/index.js +2 -1
- package/dist/parser/mysql/mysqlEntityCollector.d.ts +9 -1
- package/dist/parser/mysql/mysqlEntityCollector.js +55 -12
- package/dist/parser/postgresql/postgreEntityCollector.d.ts +10 -1
- package/dist/parser/postgresql/postgreEntityCollector.js +86 -22
- package/dist/parser/spark/sparkEntityCollector.d.ts +13 -1
- package/dist/parser/spark/sparkEntityCollector.js +88 -12
- package/dist/parser/trino/index.js +2 -1
- package/dist/parser/trino/trinoEntityCollector.d.ts +7 -1
- package/dist/parser/trino/trinoEntityCollector.js +53 -12
- 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 {
|
|
132
|
-
import {
|
|
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
|
|
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
|
-
|
|
1271
|
+
visitSelectItem?: (ctx: SelectItemContext) => Result;
|
|
1262
1272
|
/**
|
|
1263
|
-
* Visit a parse tree produced by
|
|
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
|
-
|
|
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 `
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
|
85
|
+
return !isFuncEntityContext(entity) && !isColumnEntityContext(entity);
|
|
61
86
|
}
|
|
62
87
|
export function isFuncEntityContext(entity) {
|
|
63
88
|
if (!entity)
|
|
64
89
|
return false;
|
|
65
|
-
return
|
|
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
|
|
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
|
|
240
|
-
|
|
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
|
-
|
|
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;
|