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