写点什么

AntDB 基于 Oracle 兼容下的 DECODE 函数适配

  • 2022 年 9 月 14 日
    浙江
  • 本文字数:2323 字

    阅读完需:约 8 分钟

在去'O'大背景下,为了减轻用户去'O'成本以及加快去'O'速度,很多国产数据库厂商都会在数据库产品上做 Oracle 兼容性适配。AntDB 作为一款成熟、稳定的国产数据库,自然也兼容 Oracle,并且兼容程度高达 95%以上。本文将从 Oracle 的 DECODE 函数着手,分析一下 AntDB 的适配方案。

01

Oracle 的 DECODE 函数简介


  • 语法

图1-1 Oracle的DECODE函数语法


  • 功能

DECODE 将 expr 依次与 search 比较,如果 expr 与某个 search 相等,则返回对应的 result,如果没有找到相等的 search 则返回 default。如果没有指定 default,则返回 NULL。


函数含义相当于:


图1-2 Oracle的DECODE函数语义


  • 示例

示例如下

图1-3  Oracle的DECODE函数使用例


02

AntDB 适配方案


Oracle 的 DECODE 函数功能和 AntDB 的 CASE 表达式的功能非常相似,而 AntDB 也确实利用 CASE 表达式适配了 DECODE 函数的功能。


AntDB 的 CASE 表达式


  • 语法 1

图2-1 AntDB的CASE表达式语法1


  • 功能 1

CASE 子句可以用于任何表达式可以出现的地方。每一个 condition 是一个返回 boolean 结果的表达式。如果结果为真,那么 CASE 表达式的结果就是符合条件的 result,并且剩下的 CASE 表达式不会被处理。如果条件的结果不为真,那么以相同方式搜寻任何随后的 WHEN 子句。如果没有 WHEN condition 为真,那么 CASE 表达式的结果就是 ELSE 子句里的 result。如果省略了 ELSE 子句而且没有条件为真,则 CASE 表达式结果为空。


  • 示例 1


图2-2 AntDB的CASE表达式使用例1


  • 语法 2

图2-3 AntDB的CASE表达式语法2


  • 功能 2


第一个 expression 会被计算,然后与所有在 WHEN 子句中的每一个 value 对比,直到找到一个相等的。如果没有找到匹配的,则返回在 ELSE 子句中的 result(或者空值)。这类似于 C 里的 switch 语句。


  • 示例 2

图2-4 AntDB的CASE表达式使用例2


AntDB 利用 CASE 表达式的语法 2,对 DECODE 函数进行了适配。


03

DECODE 函数适配概要


3.1 语法分析阶段


AntDB 利用 CASE 表达式的语法 2,对 DECODE 函数进行了适配,在语法分析时将 DECODE 函数转换成了 CASE 表达式。


转换前:


图3-1 语法转换前的DECODE语法


转换后:


图3-2 语法转换后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



图4-1 语法规则中的适配


在函数的语法规则里追加了对 decode 函数的特殊处理(参考上述代码中的第一个 if 块):


  • 对 decode 函数的参数个数进行检查

由于 decode 函数的最后一个参数可以省略,则参数个数至少为 3。少于 3 个参数则报语法错误。


  • 通过 reparsedecodefunc 函数将 decode 函数转成 CaseExpr

在说明 reparsedecodefunc 函数的转换处理之前,先了解下 CASE 表达式相关的结构体。


CASE 表达式结构体 CaseExpr


图4-2 CaseExpr结构体


CaseExpr 结构体成员的说明如下。


- casetype

CASE 表达式结果类型,在语义解析时才能知道,语法分析时赋值为 InvalidOid。

- casecollid

排序规则的 OID,语法层不做处理。

- arg

CASE 关键字后面的参数,即 DECODE 函数的第一个参数 expr。

- args

WHEN 语句列表。

每个 WHEN 语句包含对应的 search 和 result 参数。

WHEN 语句对应的结构体参考如下。


图4-3 CaseWhen结构体


CaseWhen 结构体的成员说明如下。


  • expr

条件表达式。

CASE 关键字后的参数(expr)与 WHEN 关键字后的参数(search)是否相等的表达式。

  • result

WHEN 语句中 search 对应的 result。

  • location

token 的位置信息

- defresult

ELSE 关键字后参数,即 CASE 表达式的默认结果。

- isdecode

标记是否是 ORACLE 的 DECODE 函数。

- location

token 的位置信息


reparse_decode_func 函数的转换处理

先看下该函数的代码:




图4-4 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。


图4-5  语义解析阶段的处理流程


如图所示,语义解析时,为了与 ORACLE 的行为一致,AntDB 为 DECODE 函数做了一些细节上的处理。


05

DECODE 函数适配详细

经过 AntDB 适配后的 DECODE 函数,演示结果如下





图5-1 适配后的结果演示


06

总结

Oracle 功能适配时,利用 AntDB 既有的功能,可能起到事半功倍的效果。当然,熟悉和理解 AntDB 既有的功能,也是必不可少的技能。

DECODE 函数的适配只是 Oracle 兼容性开发的冰山一角,AntDB 在 Oracle 兼容上有着深厚的积累和独特的优势,想要去'O'的同学,可以试试 AntDB。


关于 AntDB 数据库

AntDB 数据库始于 2008 年,在运营商的核心系统上,为全国 24 个省份的 10 亿多用户提供在线服务,具备高性能、弹性扩展、高可靠等产品特性,峰值每秒可处理百万笔通信核心交易,保障系统持续稳定运行近十年,并在通信、金融、交通、能源、物联网等行业成功商用落地。


AntDB电信级核心交易数据库-服务全国24个省份超10亿用户


发布于: 刚刚阅读数: 3
用户头像

企业数据库创新实践者 2021.07.26 加入

AntDB数据库始于2008年,服务于全国20多个省份的10亿多用户提供在线服务;具备高性能、弹性扩展、高可靠等产品特性,峰值每秒可处理百万笔电信核心交易,并保障系统持续0故障运行近十年。 官网:asiainfoah.com

评论

发布
暂无评论
AntDB基于Oracle兼容下的DECODE函数适配_数据库_亚信AntDB数据库_InfoQ写作社区