Closed
Description
Issue 区分
- 本 Issue:讨论如何通过手动获取上下文来处理 SQL 别名。
- How do I get the mapping of an alias in an SQL context? #150 :讨论借助
monaco-sql-languages
实现 SQL 别名的处理。
自动补全方式
实现自动补全的方式有两种:
- 前端静态补全:如使用
monaco-sql-languages
。 - 后端动态补全:如使用
LSP
(Language Server Protocol
,语言服务器协议)。
核心原理
通过预测用户意图并提供可能的输入选项,基于已输入的内容和上下文信息,推断用户可能想要输入的内容。
实现步骤
-
词法分析(Lexical Analysis)
- 操作:将输入的文本分解为标记(tokens)。
- 目标:识别出关键字、标识符、运算符等。
-
语法分析(Syntactic Analysis)
- 操作:基于词法分析结果,理解代码结构,构建语法树。
- 目标:确定当前输入在语法树中的位置。
-
语义分析(Semantic Analysis)
- 操作:理解代码的语义,分析变量作用域、类型信息等。
- 目标:推断出当前光标位置应该提示什么类型的数据。
-
上下文感知(Context Awareness)
- 操作:结合当前光标位置,分析上下文代码结构及之前的输入。
- 目标:理解当前环境,确保提示项符合上下文。
-
候选项生成(Candidate Generation)
- 操作:根据词法、语法、语义分析生成可能的补全选项。
- 目标:生成如关键字、变量名、函数名等补全内容。
-
排序和过滤(Sorting & Filtering)
- 操作:根据上下文的相关性和历史使用频率,对候选项进行排序。
- 目标:过滤掉不符合当前上下文的无关项,并优化排序。
实现方法
- 静态分析:基于预定义的语言规则和规范生成补全项。
- 动态分析:考虑运行时信息和项目特定的上下文(如自定义函数、表别名等)。
数据来源
- 语言规范:关键字、内置函数等基础补全内容。
- 项目代码:如自定义别名、函数、变量等。
- 上下文:用户已输入的代码内容,如库、表等。
AST 与动态编辑的局限
AST
(抽象语法树)虽然可以帮助解析 SQL 语句的结构,但它只适合静态分析的场景。
在动态编辑环境中,SQL 语句往往不完整或存在语法错误,此时生成 AST 可能会影响性能。因此AST并不适用于实时编辑器的输入场景。
LSP 的优势
LSP
更加适合动态编辑环境,它能够持续分析不完整或有语法错误的代码,并提供自动补全、跳转到定义等功能。通过增量更新可以提高性能,适合实时代码编辑和补全需求。
前端实现表别名与表名映射(重点)
虽然使用LSP
有颇多好处,但十分依赖后端服务。
如果站在前端角度来看待自动补全
和别名处理
(这也是monaco-sql-languages
正在实现的愿景),可能需要如下步骤:
- 使用正则表达式识别
AS
语句或类似别名定义的语句。(无法精准匹配,因为 AS 关键字可以省略) - 维护一个表别名与表名的映射表,记录所有别名和其对应的表名。
- 实时更新这个映射表,在用户输入 SQL 语句时,结合光标位置和上下文分析表别名。
- 在
Select u. from user AS u
语句中假设用户正在输入u.
,那么通过查询映射表找到对应的表名(如user
),并提供列的自动补全。
别名处理会更加相对复杂,因为除了表可以作为别名还有字段、计算函数、子查询等等。
目前在前端处理别名映射我并没有想到一个完美解决方案和思路,例如AS关键字省略怎么办?