Redian新闻
>
一文走进SQL编译-语义解析

一文走进SQL编译-语义解析

公众号新闻






一、概述





SQL 引擎主要由三大部分构成:解析器、优化器和执行器。解析器的主要作用是将客户端传来的命令解析编译成数据库能识别运行的命令,其主要由词法解析、语法解析和语义解析三部分构成,如下图所示。


本文将重点介绍 KaiwuDB 语义解析部分,其输入为 AST 语法树,输出为可供优化器使用的 Expr 表达式。KaiwuDB 中的语义解析主要包括:
  • 检查数据库或表是否存在
  • 检查语句所需的特定权限
  • 对语句中的表达式进行语义解析
  • 检查 DDL 语句所请求的 schema change 的有效性



二、语义解析







KaiwuDB 中的语义解析主要包括以下流程:
  • 检查查询是否为 SQL 语言中的有效语句
  • 解析名称,例如表名或变量名的值
  • 消除不必要的中间计算,例如用 1.0 替换 0.6 + 0.4,这也被称为常数折
  • 确定用于中间结果的数据类型

其代码流程介于 parser 和 memo 构建之间,将 parser 输出的 AST 中的对象进行语义解析,语义解析的输出作为 memo 构建的输入。

接下来,将重点介绍查询语句的语义解析流程:
  • Source and target analysis (目标解析)   
  • Permission check (权限校验)
  • Semantic decomposition & validation (表达式拆分及其语义解析)


1. 目标解析及权限校验

1)接口路径:

buildStmt() -> buildSelectStmtWithoutParent() ->  buildSelectClause() -> builtFrom() -> buildDataSource()

2)核心接口为:


ResolveDataSource 通过 object name 解析出对象描述符(元数据),Privilege check 使用 current username 来校验当前用户对该对象是否有相应权限。

在完成目标解析和权限校验后,会为 select stmt 中的 from clause 构建 memo 表达式。这个行为看似不是语义解析应该做的,出现在这里的原因是 KaiwuDB 的语义解析和部分逻辑计划优化是相互融合的。

2. 表达式拆分及其语义解析

1)接口路径:

buildStmt() -> buildSelectStmtWithoutParent() -> buildSelectClause()

KaiwuDB 将 select stmt 中的各个部分拆分为表达式,并对其进行标量表达式的语义解析,从而完成 scalarExpr 的构建。例如:


2)标量表达式语义解析:

ROLE:检查表达式是否合法,为其做一些初步的优化,为其赋予类型。

INTERFACE
       in : Expr
       out : TypedExpr
       实质上是检查并赋予类型 + 简化表达式
       AnalyzeExpr()

HOW
       i. Name Resolution
       ii. TypeCheck
       iii. Normalize Expr

这些子任务实现几乎是纯粹的函数,唯一的缺陷是, TypeCheck 将 SQL 占位符($1、$2 等)的类型以一种对顺序敏感的方式,输出到通过递归传递的语义环境对象上。

注意:可以使用 EXPLAIN(EXPRS, TYPES) 来检查表达式,而不进行解构和简化。

i. Name Resolution



参数 sources 和 IndexedVars,如果都不是 nil,则表示 resolveNames 应该被执行。IndexedVars map 将被填充并且作为结果返回。
  • 用 parser.IndexedVar 实例替换列名
  • 用 parser.FuncDef 引用替换函数名

ii. TypeCheck

parser.TypeCheck() / parser.TypeCheckAndRequire():
  • 常数折叠
  • 类型推断
  • 类型检查
  • 在 ComparisonExpr 节点上记忆比较器函数
  • 用其类型来注释表达式和占位符

实现 Expr 接口的表达式有很多:AndExpr, OrExpr, CastExpr, CaseExpr 等。

每个表达式都实现了 TypeCheck 接口,在被调用时返回结果表达式的类型,包括 bool, string, int 等。

iii. Normalize

parser.NormalizeExpr():

注意:此处的 normalize 有点不太准确,因为他并没有进行标准的 normalize,这里只是将除变量名以外的东西都放到比较符号的右侧,从而达到简化的目的。

Normalize Example
  • (a+1) < 3 is transformed to a < 2
  • -(a - b) is transformed to (b - a)
  • a between c and d is transformed to a >= c and a <= d


Normalize 的实现主要依靠 WalkExpr 函数。WalkExpr 会横穿 Expr,其通过传入对应的 visitor 来定义 WalkExpr 的具体行为,前面讲到的 name resolution 也是通过传入 name resolution visitor 实现的。

往期推荐



微软Edge正在偷窥你

有奖问答 | 如何快速编写出高质量的Go应用程序?

PHP程序员薪资竟然垫底、PG取代MySQL成为最流行数据库



这里有最新开源资讯、软件更新、技术干货等内容

点这里 ↓↓↓ 记得 关注✔ 标星⭐ 哦



微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
有限算术知识的结构主义解释上古小说《朝歌》6:横祸又一个 SQL 神器,开源了!有种“美神降临”叫王子文走复古风,又A又飒全网都沦陷了…开源产品测评之SQL上线能力CCL2023-Eval | 汉语框架语义解析评测正式开启,诚邀您积极参与一条SQL如何被MySQL架构中的各个组件操作执行的?这将是一场灾难?37年历史的PostgreSQL数据库将进行重大架构变更FlinkSQL 数据权限之数据脱敏解决方案从MySQL到OBOracle:如何处理自增列?慢SQL是如何拖垮数据库的?在 MySQL 中处理时间 | Linux 中国MySQL高级进阶:索引优化PHP程序员薪资竟然垫底、PG取代MySQL成为最流行数据库MyBatis 动态 SQL 最全教程,这样写 SQL 太爽了!面试数据岗时,怎么把自己的SQL技能展现出来?PostgreSQL正面临抉择ClickHouse和PostgreSQL:“数据天堂”中的好搭档当LLM遇到Database:阿里达摩院联合HKU推出Text-to-SQL新基准​线上 MySQL 的自增 id 用尽怎么办?阿里一面:MySQL 单表数据最大不要超过多少行?为什么?MySQL 巨坑:永远不要在 MySQL 中使用 UTF-8!!硬核观察 #1037 PostgreSQL 超过 MySQL 成为开发者首选数据库16 年等待,再见 SQL Boy,这一次数据库交互形态彻底被颠覆了!《乍暖還寒》 “The Last Station”2/23/10 (為愛啟程)贺万全公陵园落成一文了解MySQL全新版本模型刘震云中国女性的见识/诚实、忠厚,对朋友讲信义奇怪的SQL问题+1MySQL 单表数据最大不要超过多少行?为什么?必囤好课|三周带你从0到1掌握Python, SQL, Excel等核心技能,课程免费无限次回放!【人来疯】高效方案:30万条数据插入 MySQL 仅需13秒大数据SQL数据倾斜与数据膨胀的优化与经验总结一文解读|Java编译期注解处理器AbstractProcessor
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。