AntDB 基于 Oracle 兼容下的 DECODE 函数适配
在去'O'大背景下,为了减轻用户去'O'成本以及加快去'O'速度,很多国产数据库厂商都会在数据库产品上做 Oracle 兼容性适配。AntDB 作为一款成熟、稳定的国产数据库,自然也兼容 Oracle,并且兼容程度高达 95%以上。本文将从 Oracle 的 DECODE 函数着手,分析一下 AntDB 的适配方案。
01
Oracle 的 DECODE 函数简介
语法
功能
DECODE 将 expr 依次与 search 比较,如果 expr 与某个 search 相等,则返回对应的 result,如果没有找到相等的 search 则返回 default。如果没有指定 default,则返回 NULL。
函数含义相当于:
示例
示例如下
02
AntDB 适配方案
Oracle 的 DECODE 函数功能和 AntDB 的 CASE 表达式的功能非常相似,而 AntDB 也确实利用 CASE 表达式适配了 DECODE 函数的功能。
AntDB 的 CASE 表达式
语法 1
功能 1
CASE 子句可以用于任何表达式可以出现的地方。每一个 condition 是一个返回 boolean 结果的表达式。如果结果为真,那么 CASE 表达式的结果就是符合条件的 result,并且剩下的 CASE 表达式不会被处理。如果条件的结果不为真,那么以相同方式搜寻任何随后的 WHEN 子句。如果没有 WHEN condition 为真,那么 CASE 表达式的结果就是 ELSE 子句里的 result。如果省略了 ELSE 子句而且没有条件为真,则 CASE 表达式结果为空。
示例 1
语法 2
功能 2
第一个 expression 会被计算,然后与所有在 WHEN 子句中的每一个 value 对比,直到找到一个相等的。如果没有找到匹配的,则返回在 ELSE 子句中的 result(或者空值)。这类似于 C 里的 switch 语句。
示例 2
AntDB 利用 CASE 表达式的语法 2,对 DECODE 函数进行了适配。
03
DECODE 函数适配概要
3.1 语法分析阶段
AntDB 利用 CASE 表达式的语法 2,对 DECODE 函数进行了适配,在语法分析时将 DECODE 函数转换成了 CASE 表达式。
转换前:
转换后:
3.2 语义解析阶段
AntDB 在对 CASE 表达式的语义解析阶段,添加了对 DECODE 函数的一些细节处理。
主要添加了以下 2 个处理:
1. DECODE 函数的 expr 参数与 search 参数比较时,选择合适的比较类型
AntDB 的 CASE 表达式选择了 expr 参数的类型作为与各个 search 参数比较时使用的类型。
为了与 ORACLE 的行为一致,AntDB 在适配 DECODE 函数时,选择了第一个 search 参数的类型作为比较时使用的类型。
2. search 参数为空字符串时作为 NULL 处理
这个是 ORACLE 的另一个兼容性适配,这里不做详细说明。
04
DECODE 函数适配详细
4.1 语法分析阶段
语法分析时,将 DECODE 函数转成 CASE 表达式。详细请参考以下代码。
代码文件:src/backend/parser/ora_gram.y
在函数的语法规则里追加了对 decode 函数的特殊处理(参考上述代码中的第一个 if 块):
对 decode 函数的参数个数进行检查
由于 decode 函数的最后一个参数可以省略,则参数个数至少为 3。少于 3 个参数则报语法错误。
通过 reparsedecodefunc 函数将 decode 函数转成 CaseExpr
在说明 reparsedecodefunc 函数的转换处理之前,先了解下 CASE 表达式相关的结构体。
CASE 表达式结构体 CaseExpr
CaseExpr 结构体成员的说明如下。
- casetype
CASE 表达式结果类型,在语义解析时才能知道,语法分析时赋值为 InvalidOid。
- casecollid
排序规则的 OID,语法层不做处理。
- arg
CASE 关键字后面的参数,即 DECODE 函数的第一个参数 expr。
- args
WHEN 语句列表。
每个 WHEN 语句包含对应的 search 和 result 参数。
WHEN 语句对应的结构体参考如下。
CaseWhen 结构体的成员说明如下。
expr
条件表达式。
CASE 关键字后的参数(expr)与 WHEN 关键字后的参数(search)是否相等的表达式。
result
WHEN 语句中 search 对应的 result。
location
token 的位置信息
- defresult
ELSE 关键字后参数,即 CASE 表达式的默认结果。
- isdecode
标记是否是 ORACLE 的 DECODE 函数。
- location
token 的位置信息
reparse_decode_func 函数的转换处理
先看下该函数的代码:
reparsedecodefunc()函数的参数 args 是 DECODE 函数的参数列表,该函数的主要处理逻辑如下:
1. 新作成一个 CaseExpr 节点
2. 利用 DECODE 函数的参数列表,设置 CaseExpr 的主要成员 casetype
语法层赋值为 InvalidOid。
isdecode
只有 ORACLE 的 DECODE 函数才会进 reparsedecodefunc(),因此设置为 true。
arg
设置为 DECODE 函数的第一个参数 expr。
args
1) 将 DECODE 函数的每一对 search/result 参数作成 CaseWhen 节点设置 CaseWhen 主要成员:
expr
设置为 DECODE 函数的 search 参数。
注意:
语法层并没有作成 DECODE 函数的第一个参数与 search 参数的等号表达式,后面的语义解析阶段会做这件事。
search 参数为 NULL 时,利用 DECODE 函数的第一个参数作成 IS_NULL 表达式,并赋值给 CaseWhen 的 expr 成员。
result
设置为 search 参数对应的 result 参数。
2) 将 CaseWhen 节点追加到 args 列表
defresult
设置为 DECODE 函数的最后一个参数。
3. 返回 CaseExpr 节点
4.2 语义解析阶段
AntDB 的 CASE 表达式是通过 transformCaseExpr()函数进行解析的。语法分析时 ORACLE 的 DECODE 函数被转换成了 CASE 表达式,因此 DECODE 函数的语义解析也将通过 transformCaseExpr()函数进行解析。
transformCaseExpr 函数的主要处理流程(红色部分为 DECODE 函数适配追加)请参考图 4-5。
如图所示,语义解析时,为了与 ORACLE 的行为一致,AntDB 为 DECODE 函数做了一些细节上的处理。
05
DECODE 函数适配详细
经过 AntDB 适配后的 DECODE 函数,演示结果如下
06
总结
Oracle 功能适配时,利用 AntDB 既有的功能,可能起到事半功倍的效果。当然,熟悉和理解 AntDB 既有的功能,也是必不可少的技能。
DECODE 函数的适配只是 Oracle 兼容性开发的冰山一角,AntDB 在 Oracle 兼容上有着深厚的积累和独特的优势,想要去'O'的同学,可以试试 AntDB。
关于 AntDB 数据库
AntDB 数据库始于 2008 年,在运营商的核心系统上,为全国 24 个省份的 10 亿多用户提供在线服务,具备高性能、弹性扩展、高可靠等产品特性,峰值每秒可处理百万笔通信核心交易,保障系统持续稳定运行近十年,并在通信、金融、交通、能源、物联网等行业成功商用落地。
AntDB电信级核心交易数据库-服务全国24个省份超10亿用户
版权声明: 本文为 InfoQ 作者【亚信AntDB数据库】的原创文章。
原文链接:【http://xie.infoq.cn/article/ed219707077c7024afa119697】。文章转载请联系作者。
评论