共计 3100 个字符,预计需要花费 8 分钟才能阅读完成。
Calcite 在大数据系统中有着宽泛的使用, 比方 Apache Flink, Apache Drill 等都大量应用了 Calcite,了解 Calcite 的原理能够说曾经成为了解大数据系统中 SQL 拜访层实现原理的必备条件之一。
然而不少人在学习 Calcite 的过程中都发现对于 Calcite 的实际案例其实很少,本文就将为大家具体介绍如何基于 Calcite 框架的 SQL 语法扩大摸索使之更合乎你的业务需要,以及扩大 SQL 在数栈产品的利用实际。
Calcite 介绍及用处
Calcite 介绍
Apache Calcite 是一个动静的数据管理框架,自身不波及任何物理存储信息,而是专一在 SQL 解析、基于关系代数的查问优化,通过扩大形式来对接底层存储。
目前 Apache Calcite 被利用在宽泛的数据开源零碎中,比方 Apache Hive、Apache Phoenix、Apache Flink 等。
Calcite 的用处
Calcite 提供了 ANSI 规范 SQL 的解析,以及各种 SQL 方言,针对来自于不同数据源的简单 SQL,在 Calcite 中会把 SQL 解析成 SqlNode 语法树结构,而后依据失去的语法树转换成自定义 Node,通过自定义 Node 解析获取到表的字段信息、以及表信息、血统等相干信息。
下图展现了一部分对外提供的接口信息:
sqlparser 解析模块次要提供了以下几种性能 :
• 解析 SQL 蕴含的所有表、字段信息
• 解析 SQL 的 udf 函数
• 解析 SQL 的血统信息,包含表级血统、字段血统
• 解析自定义 SqlNode
• api 服务变量解析替换
SQL 语法扩大
理解完 Calcite 是什么以及用处后,上面为大家分享 Calcite SQL 语法扩大的相干内容。
SQL 语法扩大背景
在 sqlparser 中进行 sql 解析的场景中,有两种状况须要应用到自定义扩大,一是 Calcite 不反对的一些语法;二是在一些场景中存在 sql 中带有 ${var} 自定义变量语法。
那么针对下面的这两种状况,Calcite 的自定义扩大是如何实现的呢?自定义扩大次要波及到以下三个文件:
• Parser.jj:Parser.jj 是一个 Calcite 外围的语法和词法文件,基于 Apache FreeMaker 模版,该模版蕴含着变量,这些变量在编译时能够被替换
• parserImpl.ftl:提供自定义 SQL 语句、literals、dataType 的实现办法
• config.fmpp:该文件是 FMPP 的配置文件,提供了 SQL 语句、literals、dataType 的接口扩大入口
Calcite 应用 javacc 作为语法解析器,freemaker 作为模版,把 parserImpls.ftl、config.fmpp、Parser.jj 模版合成最终的语法词法文件,最终通过 javacc 编译成自定义的解析器源码,整体流程如下图所示:
扩大 SQL 实现
● 工程目录
● 扩大 sql 实现案例
反对以下 limit 相干语法以及数字能够写成 ${var} 模式:
-> limit count,limit start count
-> limit count offset start
-> offset start limit count
在原生的 Calcite 解析是反对 limit count 语法的,然而因为返回 SqlOrderBy 对象外部类 Operator 的 unparse 办法在 SQL 输入过程中对原始 SQL 进行了改写,因而须要应用扩大 SQL 失去正确的 SQL。
上面介绍一个 limit offset 语法扩大样例,扩大 SQL 如下:
select id, name from test where id > 3 order by id desc limit 1 offset ${offset_val}
整体流程如下:
01
Parser.jj 定义 ${var} 变量的 token 词法 DOLLAR_VARIABLE:
02
Parser.jj 扩大的变量办法接入,上面办法会在解析到 limit、offset 关键字前面的一个词时进行调用:
03
Parser.jj limit offset 在 select 语法的外围解决逻辑:
-> 定义变量
次要定义了三个 boolean 类型的变量,isOffsetLimit 示意 offset limit 语法,isLimitOffset 示意 limit offset 语法,isOnlyLimit 示意 limit count、limit start count 语法。
-> 定义解决逻辑
-> 返回自定义 SqlNode
针对合乎下面的三个 boolean 条件时,应用自定义 ExtendSqlOrderBy 的扩大类。
04
parserImpl.ftl 定义扩大的 SqlNode ExtendDollarVariable:
05
config.fmpp 定义包以及扩大实现类的 import:
06
扩大 SqlNode 实现:
-> 变量实现 sqlNode
-> 扩大 limit 实现类 ExtendSqlOrderBy,该类实现了 SqlOrderBy,并在此基础扩大了 limit 的 SqlNode,以及 isOffsetLimit、isLimitOffset、isOnlyLimit 三个 boolean 标识 limit 的不同语法
通过下面的这些步骤后,最初解析生成的 SqlNode 语法树如下所示:
扩大 SQL 在数栈的利用
目前袋鼠云的底层 sqlparser sql 解析波及的子产品利用包含 API 数据服务、离线开发、客户数据洞察(标签)、实时开发等,尽管大部分针对 Calcite 的 SQL 语法扩大绝对于下层的产品利用感知不是很显著,然而扩大 SQL 还是解决了一些痛点,次要如下:
• 逐步替换底层采纳了多种解析工具解析的状况,使保护更简略,缩小 bug 的产生
• 解决一些不反对的语法,防止在下层业务层做解决或者在底层做一些非凡解决
以在 API 数据服务后续接入的 like 语法革新为例为大家进行分享,目前的 API 数据服务中反对 like ${var} 语法,在执行测试中通过传递 like 语法来确定执行的含糊匹配形式,例如 %xx、xx%、%xx%。
收到客户提出的优化 like 语法场景,袋鼠云本着客户第一的准则,这种正当的优化需要是驳回的。SQL 反对 like%${var}、${var}%、%${var}%,这样在执行测试中就不须要输出 % 了,目前扩大 SQL 语法曾经反对这种优化的 like 语法,预计在 2023 年上半年会接入进去,上面通过 API 数据服务展现以后 like SQL 和扩大后的 SQL 差别:
● 以后 like ${var} 解决
-> 生成 API
-> 测试执行,含糊匹配须要输出 %
● 扩大 like %${var}%
-> 生成 API
-> 测试执行, 因为在 SQL 阶段曾经写了含糊匹配形式,因而能够间接输出值
总结布局
置信通过下面的案例后,大家对于 Calcite 扩大 SQL 语法的流程应该有了大抵的理解,目前在袋鼠云的业务场景中曾经扩大了许多语法,在将来还有一些工作须要进行优化:
• 丰盛 SQL 语法,实现不同数据源扩大 SQL 语法的隔离
• 逐步通过 SQL 语法扩大替换掉底层 Calcite 和 druid 独特解析的场景,防止保护多套雷同的解析,缩小线上问题产生
最初如果是初步接触 Calcite SQL 语法扩大的同学们,倡议先相熟 javacc 语法。
地址:https://javacc.github.io/javacc/
想理解或征询更多无关袋鼠云大数据产品、行业解决方案、客户案例的敌人,浏览袋鼠云官网:https://www.dtstack.com/?src=…
同时,欢送对大数据开源我的项目有趣味的同学退出「袋鼠云开源框架钉钉技术 qun」,交换最新开源技术信息,qun 号码:30537511,我的项目地址:https://github.com/DTStack