暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

OceanBase 源码解读(十一):表达式和函数

作者简介:竹翁,毕业于北京大学, OceanBase 内核研发总监。
原名杨志丰,花名竹翁。近十年来一直在阿里巴巴/蚂蚁金服自主研发分布式系统和数据库的从事研发工作。
致力于设计出先进的 HTAP 数据库系统,打造技术业内标杆、商业取得成功的核心基础设施。在 OceanBase 系统中,他先后负责 OceanBase 的 SQL 引擎,分布式主控模块,多模数据库方向等,负责过 OceanBase 的数据库平台产品研发,近期在负责内核创新研发工作。且竹翁对 C++ 、分布式系统原理、 SQL 查询处理、事务处理、编译技术、工程效率等方面也有着浓厚的兴趣。

表达式是 SQL 语句的一部分。例如,where employee = lcase('Chang') or id = 1001 中,where 后是一个值类型为 bool 的表达式,其中 lcase 是一个(系统)函数。

在前面《 OceanBase 源码解读(三)SQL 的一生》中讲过,SQL 语句在生成抽象语法树后,经过 resolver 转换解析为 stmt 逻辑执行计划,其中的一个关键部分是表达式的解析。表达式解析类是位于sql/resolver/expr 的ObRawExprResolver,它输入ObParseNode 树,输出表达式树 ObRawExpr 。这个 ObRawExpr 仅用于优化器阶段的语义分析优化,在生成物理执行计划后会被转换为为执行效率优化的 ObExpr 。

上图是表达式解析的主函数。可以看到,抽象语法树结点中用 T_XXX 这样的枚举值表示结点类型。这里有一个比较特别的设计,所有形式为 func(arg1, arg2) 的表达式在 parser 里都被解析为 T_FUN_SYS 类型,函数名存在子结点里,待 resolver 阶段处理。这样,新增一个普通内建函数的时候,我们不需要修改语法文件。不过,这也是为什么有时候相关 SQL 函数不存在的报错与 MySQL , Oracle 的行为不完全一致。从上面代码可以看到,如果内建函数中没找到,还会从用户自定义函数(UDF)中查找。

上图是 process_fun_sys_node() 片段,可以看到,在做了几个特殊的函数别名处理之后,最后通过查找ObExprOperatorFactory 类决定一个函数是否存在。(看这个类还能发现外部没有公开文档的一些隐藏函数,比如研发查问题时常用的 usec_to_time:)

所有内建函数的实现位于 sql/engine/expr 下,类的接口比较清晰,可以照猫画虎。写好实现类后,如上图,用REG_OP 宏把这个类注册一下,表达式解析和代码生成就能自动识别这个新函数。

好了,本期内容到这里就结束了。

那么本系列第二个练习题来了:请你给 OceanBase 社区版实现一个 MySQL 5.7 新增的系统内建函数吧!(这也是 OceanBase SQL 组很多新人入职第一题:)

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论