DTStack / dt-sql-parser

SQL Parsers for BigData, built with antlr4.
https://dtstack.github.io/monaco-sql-languages/
MIT License
297 stars 94 forks source link

[Bug]: getAllEntities的isContainCaret判断异常 #288

Open ouzhou opened 7 months ago

ouzhou commented 7 months ago

Version

4.0.0

Which SQL?

MySQL

SQL content

SELECT * FROM tb where    ;

JavaScript/TypeScript code

import { FlinkSQL } from "dt-sql-parser";
const flink = new FlinkSQL();
const sql = "SELECT * FROM tb where    ;";
console.log(sql.length);// 27
const pos = { lineNumber: 1, column: 25 }; // tb 的后面
const entities = flink.getAllEntities(sql, pos);

console.log(entities);// [0].belongStmt.isContainCaret 为false

What happened?

sql语句长27个字符,当光标在第25个字符,也就是where后面2个空格的位置 期望打印的isContainCaret为true

Relevant log output

No response

ouzhou commented 7 months ago

想使用光标位置获取当语句内出现的表名,去做字段推荐。 经过测试发现除了where其他的比如order by这样的后面都无法判断在同一个语句内

Kijin-Seija commented 5 months ago

猜测是因为在语法规则src/grammar/mysql/MySqlParser.g4里,whereClause必须带后面的表达式才能被作为一个token。单纯的where不被作为一个token:

image

所以实际上解析时上下文丢弃了where之后的内容,又因为光标位也在where之后,所以根据iisContainCaret的逻辑:

image

不满足结束tokenIndex大于光标位置,所以就返回false了。

这个可以暂时通过在where后面添加一个占位符来workaround,其他有类似情况的语句同。

SELECT * FROM tb WHERE CARET;

彻底解决估计还得看官方如何处理这块的语法。