Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 92 additions & 63 deletions README-zh_CN.md
Original file line number Diff line number Diff line change
@@ -1,42 +1,48 @@
# dt-sql-parser

[![NPM version][npm-image]][npm-url]
[![NPM version][npm-image]][npm-url] [![NPM downloads][download-img]][download-url] [![Chat][online-chat-img]][online-chat-url]

[npm-image]: https://img.shields.io/npm/v/dt-sql-parser.svg?style=flat-square
[npm-url]: https://www.npmjs.com/package/dt-sql-parser

[download-img]: https://img.shields.io/npm/dm/dt-sql-parser.svg?style=flat
[download-url]: https://www.npmjs.com/package/dt-sql-parser

[online-chat-img]: https://img.shields.io/discord/920616811261743104?logo=Molecule
[online-chat-url]: https://discord.gg/uVvq6mfPfa

[English](./README.md) | 简体中文

dt-sql-parser 是一个基于 [ANTLR4](https://github.com/antlr/antlr4) 开发的, 针对大数据领域的 **SQL Parser** 项目。通过[ANTLR4](https://github.com/antlr/antlr4) 默认生成的 Parser、Visitor 和 Listener 对象,我们可以轻松的做到对 SQL 语句的**语法检查**(Syntax Validation)、**词法分析**(Tokenizer)、 **遍历 AST** 节点等功能。此外,还提供了一些辅助方法, 例如 **SQL 切割(Split)**、**自动补全**等。
dt-sql-parser 是一个基于 [ANTLR4](https://github.com/antlr/antlr4) 开发的, 针对大数据领域的 **SQL Parser** 项目。通过[ANTLR4](https://github.com/antlr/antlr4) 生成的 Parser、Visitor 和 Listener,我们可以轻松的做到对 SQL 语句的**语法检查**(Syntax Validation)、**词法分析**(Tokenizer)、 **遍历 AST** 节点等功能。此外,还提供了一些辅助方法, 例如 **SQL 切割(Split)**、**自动补全**等。

**已支持的 SQL 类型:**

- Generic SQL (MySQL)
- MySQL
- Flink SQL
- Spark SQL
- Hive SQL
- PL/SQL
- PostgreSQL
- Trino SQL
- Impala SQL

**SQL 辅助方法支持**

| SQL 类型 | SQL 切割 | 自动补全 |
| SQL 类型 | SQL 切割 | 自动补全 |
| ----------- | -------- | -------- |
| Generic SQL | WIP | WIP |
| Flink SQL | ✅ | ✅ |
| Spark SQL | ✅ | ✅ |
| Hive SQL | ✅ | ✅ |
| PL/SQL | WIP | WIP |
| PostgreSQL | ✅ | ✅ |
| Trino SQL | ✅ | ✅ |
| MySQL | ✅ | ✅ |
| Flink SQL | ✅ | ✅ |
| Spark SQL | ✅ | ✅ |
| Hive SQL | ✅ | ✅ |
| PostgreSQL | ✅ | ✅ |
| Trino SQL | ✅ | ✅ |
| Impala SQL | ✅ | ✅ |

> 提示:当前的 Parser 是 `Javascript` 语言版本,如果有必要,可以尝试编译 Grammar 文件到其他目标语言
> 提示:当前的 Parser 是 `Javascript` 语言版本,如果有必要,可以尝试编译 Grammar 文件到其他目标语言

<br/>

## 与 MonacoEditor 集成
我们提供了一个[monaco-sql-languages](https://github.com/DTStack/monaco-sql-languages)包,你可以轻易的将`dt-sql-parser`与`monaco-editor`集成。
我们提供了[monaco-sql-languages](https://github.com/DTStack/monaco-sql-languages),通过它你可以轻易的将`dt-sql-parser`与`monaco-editor`集成。

<br/>

Expand All @@ -55,55 +61,55 @@ yarn add dt-sql-parser
## 使用
在开始使用前,需要先了解基本用法。`dt-sql-parser` 为不同类型的 SQL 分别提供相应的 SQL Parser 类:
```javascript
import { GenericSQL, FlinkSQL, SparkSQL, HiveSQL, PLSQL, PostgresSQL, TrinoSQL } from 'dt-sql-parser';
import { MySQL, FlinkSQL, SparkSQL, HiveSQL, PostgresSQL, TrinoSQL, ImpalaSQL } from 'dt-sql-parser';
```

在使用语法校验,自动补全等功能之前,需要先实例化对应 SQL 类型的 Parser,以 `GenericSQL` 为例:
在使用语法校验,自动补全等功能之前,需要先实例化对应 SQL 类型的 Parser,以 `MySQL` 为例:
```javascript
const parser = new GenericSQL();
const parser = new MySQL();
```

下文中的使用示例将使用 `GenericSQL`,其他 SQL 类型的 Parser 使用方式与`GenericSQL` 相同。
下文中的使用示例将使用 `MySQL`,其他 SQL 类型的 Parser 使用方式与`MySQL` 相同。

### 语法校验(Syntax Validation)
```javascript
import { GenericSQL } from 'dt-sql-parser';
import { MySQL } from 'dt-sql-parser';

const parser = new GenericSQL();
const parser = new MySQL();

const correctSql = 'select id,name from user1;';
const errors = parser.validate(correctSql);
console.log(errors);
```

输出:
*输出:*

```javascript
/*
[]
*/
```

校验失败示例:
**校验失败示例:**

```javascript
const incorrectSql = 'selec id,name from user1;'
const errors = parser.validate(incorrectSql);
console.log(errors);
```

输出:
*输出:*

```javascript
/*
[
{
endCol: 5,
endLine: 1,
startCol: 0,
startLine: 1,
message: "mismatched input 'SELEC' expecting {<EOF>, 'ALTER', 'ANALYZE', 'CALL', 'CHANGE', 'CHECK', 'CREATE', 'DELETE', 'DESC', 'DESCRIBE', 'DROP', 'EXPLAIN', 'GET', 'GRANT', 'INSERT', 'KILL', 'LOAD', 'LOCK', 'OPTIMIZE', 'PURGE', 'RELEASE', 'RENAME', 'REPLACE', 'RESIGNAL', 'REVOKE', 'SELECT', 'SET', 'SHOW', 'SIGNAL', 'UNLOCK', 'UPDATE', 'USE', 'BEGIN', 'BINLOG', 'CACHE', 'CHECKSUM', 'COMMIT', 'DEALLOCATE', 'DO', 'FLUSH', 'HANDLER', 'HELP', 'INSTALL', 'PREPARE', 'REPAIR', 'RESET', 'ROLLBACK', 'SAVEPOINT', 'START', 'STOP', 'TRUNCATE', 'UNINSTALL', 'XA', 'EXECUTE', 'SHUTDOWN', '--', '(', ';'}"
}
{
endCol: 5,
endLine: 1,
startCol: 0,
startLine: 1,
message: "mismatched input 'SELEC' expecting {<EOF>, 'ALTER', 'ANALYZE', 'CALL', 'CHANGE', 'CHECK', 'CREATE', 'DELETE', 'DESC', 'DESCRIBE', 'DROP', 'EXPLAIN', 'GET', 'GRANT', 'INSERT', 'KILL', 'LOAD', 'LOCK', 'OPTIMIZE', 'PURGE', 'RELEASE', 'RENAME', 'REPLACE', 'RESIGNAL', 'REVOKE', 'SELECT', 'SET', 'SHOW', 'SIGNAL', 'UNLOCK', 'UPDATE', 'USE', 'BEGIN', 'BINLOG', 'CACHE', 'CHECKSUM', 'COMMIT', 'DEALLOCATE', 'DO', 'FLUSH', 'HANDLER', 'HELP', 'INSTALL', 'PREPARE', 'REPAIR', 'RESET', 'ROLLBACK', 'SAVEPOINT', 'START', 'STOP', 'TRUNCATE', 'UNINSTALL', 'XA', 'EXECUTE', 'SHUTDOWN', '--', '(', ';'}"
}
]
*/
```
Expand All @@ -112,29 +118,34 @@ console.log(errors);

### 词法分析(Tokenizer)

必要场景下,可单独对 SQL 语句进行词法分析,获取所有的 Tokens 对象:
部分场景下,可以通过 `getAllTokens` 单独对 SQL 语句进行词法分析,获取所有的 Tokens 对象:

```javascript
import { GenericSQL } from 'dt-sql-parser';
import { MySQL } from 'dt-sql-parser';

const parser = new GenericSQL()
const parser = new MySQL()
const sql = 'select id,name,sex from user1;'
const tokens = parser.getAllTokens(sql)
console.log(tokens)
```

*输出:*

```javascript
/*
[
{
channel: 0
column: 0
line: 1
source: [SqlLexer, InputStream]
start: 0
stop: 5
tokenIndex: -1
type: 137
_text: null
},
...
{
channel: 0
column: 0
line: 1
source: [SqlLexer, InputStream]
start: 0
stop: 5
tokenIndex: -1
type: 137
_text: null
},
...
]
*/
```
Expand All @@ -144,13 +155,13 @@ console.log(tokens)
使用 Visitor 模式访问 AST 中的指定节点

```javascript
import { GenericSQL, SqlParserVisitor } from 'dt-sql-parser';
import { MySQL, MySqlParserVisitor } from 'dt-sql-parser';

const parser = new GenericSQL()
const parser = new MySQL()
const sql = `select id,name from user1;`
// parseTree
const tree = parser.parse(sql)
class MyVisitor extends SqlParserVisitor {
class MyVisitor extends MySqlParserVisitor {
// 重写 visitTableName 方法
visitTableName(ctx) {
let tableName = ctx.getText().toLowerCase()
Expand All @@ -164,12 +175,15 @@ class MyVisitor extends SqlParserVisitor {
}
const visitor = new MyVisitor()
visitor.visit(tree)
```

*输出:*

```javascript
/*
SelectElements id,name
TableName user1
*/

```

> 提示:使用 Visitor 模式时,节点的方法名称可以在对应 SQL 目录下的 Visitor 文件中查找
Expand All @@ -179,13 +193,13 @@ TableName user1
Listener 模式,利用 [ANTLR4](https://github.com/antlr/antlr4) 提供的 `ParseTreeWalker` 对象遍历 AST,进入各个节点时调用对应的方法。

```javascript
import { GenericSQL, SqlParserListener } from 'dt-sql-parser';
import { MySQL, MySqlParserListener } from 'dt-sql-parser';

const parser = new GenericSQL();
const parser = new MySQL();
const sql = 'select id,name from user1;'
// parseTree
const tree = parser.parse(sql)
class MyListener extends SqlParserListener {
class MyListener extends MySqlParserListener {
enterTableName(ctx) {
let tableName = ctx.getText().toLowerCase()
console.log('TableName', tableName)
Expand All @@ -197,12 +211,15 @@ class MyListener extends SqlParserListener {
}
const listenTableName = new MyListener();
parser.listen(listenTableName, tree);
```

*输出:*

```javascript
/*
SelectElements id,name
TableName user1
*/

```

> 提示:使用 Listener 模式时,节点的方法名称可以在对应 SQL 目录下的 Listener 文件中查找
Expand All @@ -215,37 +232,40 @@ const parser = new FlinkSQL();
const sql = 'SHOW TABLES;\nSELECT * FROM tb;';
const sqlSlices = parser.splitSQLByStatement(sql);
console.log(sqlSlices)
```

*输出:*

```javascript
/*
[
{
{
startIndex: 0,
endIndex: 11,
startLine: 1,
endLine: 1,
startColumn: 1,
endColumn: 12,
text: 'SHOW TABLES;'
},
{
},
{
startIndex: 13,
endIndex: 29,
startLine: 2,
endLine: 2,
startColumn: 1,
endColumn: 17,
text: 'SELECT * FROM tb;'
}
}
]
*/

```

### 自动补全(Code Completion)
在 sql 的指定位置上获取自动补全信息,以 `FlinkSQL` 为例:
在 sql 文本的指定位置上获取自动补全信息,以 `FlinkSQL` 为例:

调用 `getSuggestionAtCaretPosition` 方法,传入 sql 内容和需要自动补全的位置的行列号
+ 获取关键字候选项列表
调用 `getSuggestionAtCaretPosition` 方法,传入 sql 内容和指定位置的行列号
+ **获取关键字候选项列表**

```javascript
import { FlinkSQL } from 'dt-sql-parser';
Expand All @@ -254,19 +274,28 @@ console.log(sqlSlices)
const pos = { lineNumber: 1, column: 16 }; // 最后一个位置
const keywords = parser.getSuggestionAtCaretPosition(sql, pos)?.keywords;
console.log(keywords);
```
*输出:*

```javascript
/*
[ 'CATALOG', 'FUNCTION', 'TEMPORARY', 'VIEW', 'DATABASE', 'TABLE' ]
*/
```
+ 获取语法相关自动补全信息
+ **获取语法相关自动补全信息**
```javascript
const parser = new FlinkSQL();
const sql = 'SELECT * FROM tb';
const pos = { lineNumber: 1, column: 16 }; // tb 的后面
const syntaxSuggestions = parser.getSuggestionAtCaretPosition(sql, pos)?.syntax;
console.log(syntaxSuggestions);


```

*输出:*

```javascript
/*
[
{
Expand Down Expand Up @@ -298,7 +327,7 @@ console.log(sqlSlices)
]
*/
```
语法相关自动补全信息返回一个数组,数组中每一项代表该位置可以填写什么语法,比如上例中的输出结果代表该位置可以填写**表名**或者**视图名称**。其中 `syntaxContextType` 是可以补全的语法类型,`wordRanges` 则是已经填写的内容
语法相关自动补全信息返回一个数组,数组中每一项代表该位置可以填写什么语法,比如上例中的输出结果代表该位置可以填写**表名**或者**视图名称**。其中 `syntaxContextType` 是可以补全的语法类型,`wordRanges` 是已经填写的内容

### 其他 API

Expand Down
Loading