【StarRocks系列】 Trino 方言支持
我们在之前的文章中,介绍了 Doris 官方提供的两种方言转换工具,分别是 sql convertor 和方言 plugin。StarRocks 目前同样也提供了类似的方言转换功能。本文我们就一起来看一下这个功能的实现与 Doris 相比有何不同。
一、Trino 方言验证
我们可以通过如下 SQL 来验证 Trino 的方言转换在 SR 中的效果:
set enable_profile = true;
set sql_dialect = starrocks;
select BOROUGH, approx_count_distinct(ZIP_CODE) cnt from crashdata group by BOROUGH order by cnt desc;
set sql_dialect = trino;
select BOROUGH, approx_distinct("ZIP_CODE") cnt from crashdata group by BOROUGH order by cnt desc;
针对上述查询,我们在 SR 集群执行,结果如下所示:
可以看到,执行结果完全一致,说明方言转换已经生效,并且符合预期。通过 WebUI 查看提交的两条 SQL:
页面上显示的仍然是原始的 SQL 而不是改写之后的。如果在 SR 的方言下,执行 SQL2 的话,那么会直接报错,如下所示:
提示函数找不到,这也是符合预期的,因为 approx_distinct 这个函数在 SR 中是不存在的。下面我们就结合代码来看一下 SR 是如何实现这个方言转换功能的。
二、Trino AST 简介
由于 Trino 的方言支持,主要思路是将 Trino 的相关结构转换成 SR 的结构,因此这里先简单了解下 Trino 的 AST 相关结构:
后续提到的相关结构,就可以直接参考上述图片。
三、Trino Transformer 介绍
SR 在 FE 中实现了一套 transformer 可以将 Trino 的 function 转换为 SR 的 function,从而实现了方言转换的功能。
3.1 整体流程图
整个 parse 的相关流程如下所示:
上述流程可以分为如下几个步骤:
- FE 启动的时候,Trino2SRFunctionCallTransformer 会通过静态方法将所有 Trino 到 SR 的函数映射注册到 TRANSFORMER_MAP 这个 map 中;
- FE 调用 Trino 的 SqlParser 将 sql string 转换为 Trino 的 Statement 结构,可以参考上述的 AST 结构图;
- 在 trino/AstBuilder 中,将 Trino 的 Statement 转换为 SR 的 StatementBase,transformer 用于进行函数转换;
- 根据 sql 中的 Trino 函数名,在 Map 中进行匹配,找到对应的 FunctionCallTransformer;
- 在 FunctionCallTransformer 中构造 FunctionCallRewriter,最终返回至 trino/AstBuilder,完成函数的转换;
- 继续后续的其他操作,最终生成 SR 的 StatementBase结构,完成 parse 操作。
这里我们来一一看下对应的操作。
3.2 函数映射注册
Trino 到 SR 的函数映射注册代码位于 Trino2SRFunctionCallTransformer 中,这个类在加载的时候,会完成对应的函数映射注册,如下所示:
private static void registerAllFunctionTransformer() {registerAggregateFunctionTransformer();registerArrayFunctionTransformer();registerDateFunctionTransformer();registerStringFunctionTransformer();registerRegexpFunctionTransformer();registerJsonFunctionTransformer();registerURLFunctionTransformer();registerBitwiseFunctionTransformer();registerUnicodeFunctionTransformer();registerMapFunctionTransformer();registerBinaryFunctionTransformer();// todo: support more function transform
}
以 registerAggregateFunctionTransformer 为例,这里负责对聚合函数的映射进行注册,相关代码如下所示:
private static void registerAggregateFunctionTransformer() {// 1.approx_distinctregisterFunctionTransformer("approx_distinct", 1,"approx_count_distinct", ImmutableList.of(Expr.class));// 2. arbitraryregisterFunctionTransformer("arbitrary", 1,"any_value", ImmutableList.of(Expr.class));// 3. approx_percentileregisterFunctionTransformer("approx_percentile", 2,"percentile_approx", ImmutableList.of(Expr.class, Expr.class));
通过这个函数的映射,Trino 的 approx_distinct 函数就会被转换成 SR 的 approx_count_distinct,对应的结构体转换如下所示:
可以看到,最终在 map 中保存了 approx_distinct 这个 Trino 函数到 SR 的映射。需要注意的是,map 的 value 是一个 list,主要是为了处理参数不同的重载函数。通过 debug 可以直接查看已经注册的函数映射:
其中,PlaceholderExpr 就是用来保存 SR 函数的输入参数,主要就是 index 和 参数的类型,后续用于进行匹配,最终会被替换成实际的函数参数,位于 FunctionCallRewriter 的 sourceArguments 中。
3.3 Transformer 匹配
在 FE 启动之后,Trino 的函数映射已经全部注册完成。当我们通过设置方言为 trino 之后,首先需要根据 Trino 的函数名去 map 中进行匹配,由于重载函数的存在,因此还需要比较对应的参数类型。相关的函数调用如下所示:
parse(SqlParser.java):56
--parseWithTrinoDialect(SqlParser.java):68/74
---toStatement(TrinoParserUtils.java):42
----accept(io/trino/sql/tree/Statement.java)
// 省略部分函数调用栈
-visitFunctionCall(trino/AstBuilder.java):713
--convert(Trino2SRFunctionCallTransformer.java):47
---convertRegisterFn(Trino2SRFunctionCallTransformer.java):62
----match(FunctionCallTransformer.java)
其中,match函数的参数为 List<Expr>,对应的就是 2.1 中 List<Expression> 转换后的结果,即将 Trino 的 Expression 转换为 SR 中的 Expr 结构。匹配的过程主要分为两步:
- 比较参数个数是否一致;
- 比较每一个 PlaceholderExpr 的类型,是否是实际参数类型的超类。
两个条件都满足的话,则证明这个 transformer 是相符的,则继续进行后续的转换。
3.4 函数转换
转换操作主要就是生成一个 FunctionCallRewriter 对象,相关的函数调用如下所示:
visitFunctionCall(trino/AstBuilder.java):713
-convert(Trino2SRFunctionCallTransformer.java):47
--convertRegisterFn(Trino2SRFunctionCallTransformer.java):69
---transform(FunctionCallTransformer.java):113
----ctor(FunctionCallRewriter.java)
我们通过 debug 分别对比下 Trino 和 SR 中的function call 的结构,如下所示:
可以看到,最终生成的 FunctionCallRewriter 中,已经包含了具体的参数,即 ZIP_CODE 这个列,对应的类型是 SlotRef,而 2.2 中的 PlaceholderExpr 只有类型信息,即 Expr(SlotRef是其一个子类,所以类型可以匹配上)。
四、总结
4.1 与 Doris 方言功能比较
由于 Doris 的 sql convertor 工具是借助 SqlGlot 实现的,因此与 Doris 本身关系不大。这里我们主要比较下 Doris 的方言 plugin 与 SR 的 transformer 优缺点:
方言功能 | 优点 | 缺点 |
---|---|---|
SR Transformer | 实现比较完善,支持各种函数转换 | 与SR代码耦合紧,并且仅支持Trino,扩展性一般 |
Doris Plugin | 通过Plugin的方法与Doris代码进行了解耦,扩展性相对较好,目前支持Trino和Spark | 实现比较简单,函数转换未提供,并且存在一些问题,可用性较差 |
4.2 思考小结
由于目前 SR 官方只支持 Trino 的方言转换,并且与源码耦合比较紧,如下所示:
// SqlParser.java
public static List<StatementBase> parse(String sql, SessionVariable sessionVariable) {if (sessionVariable.getSqlDialect().equalsIgnoreCase("trino")) {return parseWithTrinoDialect(sql, sessionVariable);} else {return parseWithStarRocksDialect(sql, sessionVariable);}
}
如果想要完整的支持一种新的方言转换,需要实现对应的 FunctionCallTransformer 和 AstBuilder,并修改上述的 if-else,总体代码开发量比较大。此外,本文的所有内容是笔者基于 StarRocks-3.3 版本分析、总结而来,如有错误,欢迎指正。
五、参考文档
- sql_dialect;
- [Feature] Support Trino parser on StarRocks #14830;
相关文章:
【StarRocks系列】 Trino 方言支持
我们在之前的文章中,介绍了 Doris 官方提供的两种方言转换工具,分别是 sql convertor 和方言 plugin。StarRocks 目前同样也提供了类似的方言转换功能。本文我们就一起来看一下这个功能的实现与 Doris 相比有何不同。 一、Trino 方言验证 我们可以通过…...
【2024最新华为OD-C卷试题汇总】URL拼接 (100分) - 三语言AC题解(Python/Java/Cpp)
🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C卷的三语言AC题解 💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 文章目录 前…...
【ARM 嵌入式 C 字符串系列 23.7 -- C 实现函数 isdigit 和 isxdigit】
请阅读【嵌入式开发学习必备专栏 】 文章目录 isdigit 和 isxdigit C代码实现实现 isdigit实现 isxdigit使用示例 isdigit 和 isxdigit C代码实现 在C语言中,isdigit和isxdigit函数用于检查一个字符是否分别为十进制数字或十六进制数字。以下是这两个函数的简单实现…...
三分钟了解计算机网络核心概念-数据链路层和物理层
计算机网络数据链路层和物理层 节点:一般指链路层协议中的设备。 链路:一般把沿着通信路径连接相邻节点的通信信道称为链路。 MAC 协议:媒体访问控制协议,它规定了帧在链路上传输的规则。 奇偶校验位:一种差错检测方…...
数据结构===堆
文章目录 概要堆2条件大顶堆小顶堆 堆的实现插入元素删除堆顶元素 堆代码小结 概要 堆,有趣的数据结构。 那么,如何实现一个堆呢? 堆 堆,有哪些重点: 满足2条件大顶堆小顶堆 2条件 2条件: 堆是一个…...
AAA、RADIUS、TACACS、Diameter协议介绍
准备软考高级时碰到的一个概念,于是搜集网络资源整理得出此文。 概述 AAA是Authentication、Authorization、Accounting的缩写简称,即认证、授权、记帐。Cisco开发的一个提供网络安全的系统。AAA协议决定哪些用户能够访问服务,以及用户能够…...
Nacos高频面试题及参考答案(2万字长文)
目录 Nacos是什么?它的主要功能有哪些? Nacos在微服务架构中扮演什么角色?...
CMakeLists.txt语法规则:条件判断中表达式说明四
一. 简介 前面学习了 CMakeLists.txt语法中的 部分常用命令,常量变量,双引号的使用。 前面几篇文章也简单了解了 CMakeLists.txt语法中的条件判断,文章如下: CMakeLists.txt语法规则:条件判断说明一-CSDN博客 CMa…...
Hive概述
Hive简介 Hive是一个基于Hadoop的开源数据仓库工具,用于存储和处理海量结构化数据. 它是Facebook在2008年8月开源的一个数据仓库框架,提供了类似于SQL语法的HQL(HiveSQL)语句作为数据访问接口. Hive可以做复查统计分析之类的工作; 利用hdfs的存储空间,进行结构化数据的存储; 利…...
buuctf-misc-33.[BJDCTF2020]藏藏藏1
33.[BJDCTF2020]藏藏藏1 题目:藏了很多层,一层一层的剥开 常规思路,先使用010打开一下看看 binwalk不行用foremost 发现是pk文件也就是压缩包,并且包含了docx文件 这不binwalk分离一下文件?虽然可以看出有隐藏文件&…...
golang 基础知识细节回顾
之前学习golang的速度过于快,部分内容有点囫囵吞枣的感觉,写gorm过程中有很多违反我常识的地方,我通过复习去修正了我之前认知错误和遗漏的地方。 itoa itoa自增的作用在编辑error code时候作用很大,之前编辑springboot的error c…...
递归陷阱七例
目录 栈溢出 无限递归 大常数参数 递归深度过大 重复计算 函数调用开销 递归与迭代的选择 总结 递归是一种强大的编程技术,它允许函数调用自身。递归在很多情况下可以简化代码,使问题更容易理解和解决。然而,递归也容易导致一些常见的…...
【3D基础】坐标转换——地理坐标投影到平面
汤国安版GIS原理第二章重点 1.常见投影方式 https://download.csdn.net/blog/column/9283203/83387473 Web Mercator投影(Web Mercator Projection): 优点: 在 Web 地图中广泛使用,易于显示并与在线地图服务集成。在…...
颈椎锻炼方式
1. 颈部伸展运动:坐直,慢慢将头向前伸展,直到感到轻微的拉伸,保持数秒钟,然后缓慢放松。重复10次。 2. 颈部旋转运动:坐直,慢慢将头向一侧转动,直到感到轻微的拉伸,保持…...
测试环境搭建:JDK+Tomcat+Mysql+Redis
基础的测试环境搭建: LAMPLinux(CentOS、ubuntu、redhat)ApacheMysqlPHP LTMJLinux(CentOS、ubuntu、redhat)TomcatMysql(Oracle)RedisJava 真实的测试环境搭建:(企业真实的运维) 基于SpringBoot(SpringCloud分布式微…...
(delphi11最新学习资料) Object Pascal 学习笔记---第11章第1节(混合引用中的错误)
11.1.3 混合引用中的错误 在使用对象时,你通常应该只使用对象变量或接口变量来访问它们。混合使用这两种方法会破坏对象 Pascal 所提供的引用计数机制,并可能导致极难跟踪的内存错误。在实践中,如果你决定使用接口,你可能应该…...
代码随想录算法训练营第三天 | 链表理论基础,203.移除链表元素,707.设计链表,206.反转链表
对于链表完全陌生,但是看题目又觉得和数组一样的 链表理论基础 Q:什么是链表? A:链表是由一系列结点组成的。每一个结点由两部分组成:数据和指针。 203.移除链表元素 题目: 给你一个链表的头节点 head 和…...
如何利用仪表构造InfiniBand流量在数据中心测试中的应用
一、什么是Infiniband? 在当今数据爆炸的时代,数据中心作为信息处理的中心枢纽,面临着前所未有的挑战。传统的通信方式已经难以满足日益增长的数据传输需求,而InfiniBand技术的出现,为数据中心带来了全新的通信解决方…...
Kubernetes 文档 / 概念 / Kubernetes 架构 / 节点
Kubernetes 文档 / 概念 / Kubernetes 架构 / 节点 此文档从 Kubernetes 官网摘录 中文地址 英文地址 节点上的组件包括 kubelet、 容器运行时以及 kube-proxy。 管理 向 API 服务器添加节点的方式主要有两种: 节点上的 kubelet 向控制面执行自注册;…...
ICode国际青少年编程竞赛- Python-1级训练场-for循环练习
ICode国际青少年编程竞赛- Python-1级训练场-for循环练习 1、 for i in range(3):Dev.step(4)Dev.turnLeft()2、 for i in range(3):Dev.step(2)Dev.turnRight()Dev.step(2)Dev.turnLeft()3、 for i in range(3):Dev.step(2)Dev.turnRight()Dev.step(2)Dev.turnLeft()4、 for…...
Flutter分模块开发、模块可单独启动、包含Provider
前言 当前案例 Flutter SDK版本:3.13.2 目前Flutter都是在一个项目中,创建不同目录进行模块开发,我进行Android原生开发时,发现原生端,是可以将每个模块独立运行起来的,灵感来自这; 折腾了几…...
Element-UI快速入门:构建优雅的Vue.js应用界面
Element-UI是一套基于Vue.js的组件库,提供了丰富的UI组件和交互效果,帮助开发者快速构建出美观、功能丰富的Web应用界面。本文将介绍如何快速入门Element-UI,并搭建一个简单的示例界面。 步骤一:安装Element-UI 首先,…...
Flutter 中的 @immutable:深入解析与最佳实践
在 Flutter 开发中,immutable 注释扮演着至关重要的角色,用于标记不可变类。不可变类顾名思义,其状态一旦创建便不可更改,这与可变类截然不同。后者允许在创建后对实例进行修改。 immutable 的利好 引入不可变类可以带来诸多优势…...
Pandas数据可视化 - Matplotlib、Seaborn、Pandas Plot、Plotly
可视化工具介绍 让我们一起探讨Matplotlib、Seaborn、Pandas Plot和Plotly这四个数据可视化库的优缺点以及各自的适用场景。这有助于你根据不同的需求选择合适的工具。 1. Matplotlib 优点: 功能强大:几乎可以用于绘制任何静态、动画和交互式图表。高度可定制&a…...
人工智能的发展将如何重塑网络安全
微信搜索关注公众号网络研究观,获取更多信息。 人们很容易认为人工智能 (AI) 真正出现是在 2019 年,当时 OpenAI 推出了 ChatGPT 的前身 GPT-2。 但现实却有些不同。人工智能的基础可以追溯到 1950 年,当时数学家艾伦图灵发表了题为“计算机…...
Prometheus+Grafana多方位监控
PrometheusGrafana多方位监控 契机 ⚙ 最近发现火山引擎有托管的Prometheus,可是当前是邀测阶段。并且发现火山云的ECS是自带开机自启的exporter的。刚好需要搭建一套服务器监控,所以研究了一套Prometheus监控,包含linux主机监控nginx监控es监控rabbitM…...
使用Docker安装Redis
大家好,今天给大家分享一下如何使用docker安装Redis,关于docker的安装和常用命令,大家可以参考下面两篇文章,本文中不做过多描述。 Docker在Windows与CentOS上的安装 Docker常用命令 关于Redis的介绍与常用操作可以参考&#x…...
React 之 Effect与事件(event)(八)
Effect(useEffect Hook) 在React中,Effect(或者更具体地说,useEffect Hook)是一个特殊的函数,它允许你在函数组件中执行副作用操作。这些副作用操作可能包括数据获取、手动更改DOM、订阅或取消订…...
网卡的了解
什么是网卡_csdn网卡是什么-CSDN博客 MAC地址:48位串行号(独一无二) 2^48281 474 976 710 656 10位:10亿 5位:1万 15位:10万亿 网卡就是网络适配器 设置--->网络和Internet--->高级网络设置--->硬…...
SSM框架目录
ssm 知识相关目录主要参考尚硅谷 赵伟风老师的视屏,参考链接为 SSM视频_ SSM技术视频_SSM视频教程_尚硅谷 【注意】有些图片为了简便,所以就直接使用了视屏分析。 1、SSM框架相关知识 SpringFramework 基本概念 链接:SpringFramework 基本…...
国外网站做任务套利/北京疫情又严重了
看《致命连线》电影,学习RDP协议压缩思路<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />美国电影《致命连线》(Antitrust)(又名:反垄断),描述了世界巨头的软件公司(模拟微软)聘用天才青年&am…...
陕西手机网站建设/微信app小程序开发
文章目录 前言I 宏定义II 二进制文件修改III 静态分析防护小结see also前言 本人最终喜欢的马甲包混淆方案是用Hikari,具体的用法看这里:https://kunnan.blog.csdn.net/article/details/107957286 本文的重点是讲解最原始的方法:字符串替换 宏定义> [**ios-class-guard*…...
太原适合网站设计地址/网络推广方法有几种
对象的基础知识: 一个对象要真正地被使用,可采用以下几种方式获得: 引用JavaScript内部对象; 由浏览器环境中提供; 创建新对象。 有关对象操作语句: 1)、For...in语句 格式如下: F…...
淘宝内部优惠券网站怎样做的/seo网站分析
在并发时代,具有4、8和16个处理器内核的芯片变得越来越普遍,并且在不久的将来,我们将看到具有数百甚至数千个内核的芯片。 这种处理能力具有巨大的可能性,但是对于软件开发人员而言,这也带来了挑战。 最大限度地利用这…...
潍坊市建设局网站/企业管理培训课程视频
在使用虚拟机的过程中,虚拟机初始硬盘容量设置得过大,未免有点浪费,若初始设置得过小,后续可能会出现硬盘空间不够的情况,很多朋友在虚拟机容量不够时,显得束手无策,这里介绍一下我的一个扩展虚…...
网站的建设成本/百度网盘会员
Hibernate Validator 是 JSR 303 的一个参考实现,除支持 所有标准的校验注解外,它还支持以下的扩展注解...