Skip to content

如何根据SQL语句上下文得知别名与实体的关系 #151

Closed
@resetsix

Description

@resetsix

Issue 区分

自动补全方式

实现自动补全的方式有两种:

  1. 前端静态补全:如使用 monaco-sql-languages
  2. 后端动态补全:如使用 LSPLanguage Server Protocol,语言服务器协议)。

核心原理

通过预测用户意图并提供可能的输入选项,基于已输入的内容和上下文信息,推断用户可能想要输入的内容。

实现步骤

  1. 词法分析(Lexical Analysis)

    • 操作:将输入的文本分解为标记(tokens)。
    • 目标:识别出关键字、标识符、运算符等。
  2. 语法分析(Syntactic Analysis)

    • 操作:基于词法分析结果,理解代码结构,构建语法树。
    • 目标:确定当前输入在语法树中的位置。
  3. 语义分析(Semantic Analysis)

    • 操作:理解代码的语义,分析变量作用域、类型信息等。
    • 目标:推断出当前光标位置应该提示什么类型的数据。
  4. 上下文感知(Context Awareness)

    • 操作:结合当前光标位置,分析上下文代码结构及之前的输入。
    • 目标:理解当前环境,确保提示项符合上下文。
  5. 候选项生成(Candidate Generation)

    • 操作:根据词法、语法、语义分析生成可能的补全选项。
    • 目标:生成如关键字、变量名、函数名等补全内容。
  6. 排序和过滤(Sorting & Filtering)

    • 操作:根据上下文的相关性和历史使用频率,对候选项进行排序。
    • 目标:过滤掉不符合当前上下文的无关项,并优化排序。

实现方法

  • 静态分析:基于预定义的语言规则和规范生成补全项。
  • 动态分析:考虑运行时信息和项目特定的上下文(如自定义函数、表别名等)。

数据来源

  • 语言规范:关键字、内置函数等基础补全内容。
  • 项目代码:如自定义别名、函数、变量等。
  • 上下文:用户已输入的代码内容,如库、表等。

AST 与动态编辑的局限

AST(抽象语法树)虽然可以帮助解析 SQL 语句的结构,但它只适合静态分析的场景。

在动态编辑环境中,SQL 语句往往不完整或存在语法错误,此时生成 AST 可能会影响性能。因此AST并不适用于实时编辑器的输入场景。

LSP 的优势

LSP更加适合动态编辑环境,它能够持续分析不完整或有语法错误的代码,并提供自动补全、跳转到定义等功能。通过增量更新可以提高性能,适合实时代码编辑和补全需求。

前端实现表别名与表名映射(重点)

虽然使用LSP有颇多好处,但十分依赖后端服务。

如果站在前端角度来看待自动补全别名处理(这也是monaco-sql-languages正在实现的愿景),可能需要如下步骤:

  1. 使用正则表达式识别 AS 语句或类似别名定义的语句。(无法精准匹配,因为 AS 关键字可以省略)
  2. 维护一个表别名与表名的映射表,记录所有别名和其对应的表名。
  3. 实时更新这个映射表,在用户输入 SQL 语句时,结合光标位置和上下文分析表别名。
  4. Select u. from user AS u语句中假设用户正在输入u.,那么通过查询映射表找到对应的表名(如 user),并提供列的自动补全。

别名处理会更加相对复杂,因为除了表可以作为别名还有字段、计算函数、子查询等等。

目前在前端处理别名映射我并没有想到一个完美解决方案和思路,例如AS关键字省略怎么办?

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionFurther information is requested

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions