一、前言
2021年12月23号到2021年12月24号的数据技术嘉年华直播中,不少国产数据库厂商都在说兼容oracle的语法到了百分之多少。我想着,既然都说兼容,那我能不能直接把我之前写的一些奇奇怪怪的功能给移植到这些数据库上去?
稍微研究了一下这些国产数据库,发现很多都是基于mysql或者postgresql。也就是说,理论上,只要某个基于postgresql的数据库做了兼容oracle的相关对象,那么理论上也应该能移植到另一个基于postgresql的数据库上去。
但一个人去对比这么多数据库扣那几百上千个对象的代码,工程量巨大,还不如自己针对某一个数据库,挑几个它缺的写写。
刚好近期有报道,openGauss进入了国家计算机等级考试
重磅消息,openGauss纳入全国计算机等级考试!
所以我开了这个新坑,打算给openGauss写写兼容oracle的sql的函数及过程。
另外,由于不清楚是否有人在做和我同样的事,如果有,为避免重复造轮子,请及时和我联系。
注意,本计划目的为个人学习,不涉及商业行为,可能最后无法100%完成。
二、分析
首先,openGauss官方有提供ORACLE语法的兼容包compat-tools,包含了oracle里有的静态视图及大部分函数,还有几个dbms包。
compat-tools开源地址https://gitee.com/enmotech/compat-tools
所以,我可以参考着这个项目的写法,补上一些我以前有用过但compat-tools里没有的东西。
但是要注意的是,这种兼容包的目的是sql兼容,原理只是使用plsql代码,利用现有pg数据库内自带的函数进行转换,在逻辑上符合oracle输出的结果,是没有底层的专用优化算法的,所以查询效率不一定会快。要效率快,不能仅仅是在plsql层面来模拟逻辑,而应该在数据库进行内置(即全局可用的那种函数,而非仅仅是一个模式下的对象)或者用C函数。刚刚才开始看pg的内容,我暂时还做不到那个层面。
我在本地docker里开了个openGauss,然后打上compat-tools,查询dba_objects中的所有function名称,导出成表格。然后从oracle官网的21c-sql参考文档,把function名称全部复制下来,放到xlsx表格里,用vlookup函数匹配oracle有但openGauss没有的函数。
在比较过程中发现,有些postgresql自带的函数,在dba_objects中查不到,比如cast、least、greast、nullif、nvl等,所以需要剔除了这些函数后再进行比较。一比,发现有两百个函数在openGauss中是缺少的。然后我逐个去看这些函数,
- 一堆json和xml的相关处理函数,这些需要统一分析,先排除,
- 一堆近似算法的函数,这个属于底层机制,不能在plsql层面上实现,所以也剔除
- 有很多oracle内部对象的专用处理函数,这些在openGauss里也用不上
- 有很多机器学习的函数,但openGauss里有另一套机制,所以也用不上
经过一系列排除后,得到以下清单
ANY_VALUE
ASCIISTR
BFILENAME
BIN_TO_NUM
COSH
KURTOSIS_POP
KURTOSIS_SAMP
LNNVL
NUMTOYMINTERVAL
RATIO_TO_REPORT
ROUND_TIES_TO_EVEN (number)
SINH
SKEWNESS_POP
SKEWNESS_SAMP
SOUNDEX
STANDARD_HASH
SYSTIMESTAMP
TANH
UNISTR
可以发现,这些函数里有不少是我的系列文章“收集一些较为少见但很有用的SQL函数及写法”中有提到的
这里面有不少函数要全新写逻辑会相当复杂,所以我会先从简单的开始写起。
另外,还有对dbms包的兼容,这个会更麻烦,之后会另起一篇文章进行介绍。
三、计划进度
如果本计划进度有更新,会优先在本文的原文地址先更新
函数名称 | 功能描述 | 进度 | 完成日期 |
---|---|---|---|
ANY_VALUE | 聚合函数,取任意值 | 完成 | 20220101 |
ASCIISTR | 获得字符串的ascii码 | 完成 | 20211229 |
BFILENAME | 获得操作系统上的一个文件作为对象 | ||
BIN_TO_NUM | 二进制转数字 | 完成 | 20211229 |
COSH | 双曲余弦 | 完成 | 20211230 |
KURTOSIS_POP | 总体峰态 | 完成 | 20220103 |
KURTOSIS_SAMP | 样本峰态 | 完成 | 20220103 |
LNNVL | 避免表达式中有空值导致统计遗漏的一个函数 | 完成 | 20220101 |
NUMTOYMINTERVAL | 将数字转换成年月INTERVAL | 完成 | 20211230 |
RATIO_TO_REPORT | 分析函数,取本值占分组的百分比 | ||
ROUND_TIES_TO_EVEN (number) | 区别于round的另一种四舍五入 | 完成 | 20211229 |
SINH | 双曲正弦 | 完成 | 20211230 |
SKEWNESS_POP | 总体偏度 | 完成 | 20220103 |
SKEWNESS_SAMP | 样本偏度 | 完成 | 20220103 |
SOUNDEX | 发音相似 | 完成 | 20211230 |
STANDARD_HASH | 标准哈希 | 完成 | 20211229 |
SYSTIMESTAMP | 当前时间戳 | 完成 | 20211229 |
TANH | 双曲正切 | 完成 | 20211230 |
UNISTR | 将unicode编码转换成文字字符串 | 完成 | 20211229 |
以下为相较于第一版的新增部分 | |||
BIT_AND_AGG | 位与聚合 | 完成 | 20211231 |
BIT_OR_AGG | 位或聚合 | 完成 | 20211231 |
BIT_XOR_AGG | 位异或聚合 | 完成 | 20211231 |
REMAINDER | 取任何数相除的余数(和mod不一样,不会进行floor) | 完成 | 20220102 |
BITOR | 位或 | 完成 | 20211231 |
BITXOR | 位异或 | 完成 | 20211231 |
待研究问题
- ratio_to_report不是常规的聚合函数,而是开窗函数,需要写c++函数,目前暂不确定是否需要重新编译数据库。2022-01-02,参考源码中avg的聚合及lag的默认值取法,修改最终函数为当前窗口当前值除以汇总但单独编译的时候一堆error,主要不清楚应该去掉哪些依赖,毕竟源码就像个蜘蛛网;如果编译整个数据库这动作又太大了,所以暂时放弃这个函数。
- 峰度和偏度,在网上找的公式和oracle计算出来的不一样,暂不清楚公式.2022-01-03凌晨睡不着,在国外网站上搜到一个用excel手动计算偏度的案例,已实测和oracle计算一致
- BFILENAME的两个参数,目录和文件名,其中目录这个对象在pg里没有,达不到100%复刻,可以使用pg_read_binary_file这个函数,传入文件全路径达到同样的效果。但需要使用初始化账号,这个可以通过由初始化账号建立使用本账号权限的函数,来实现访问
[SQLErrorCode : 10527][127.0.0.1:54611/ocalhost/127.0.0.1:5432] ERROR: must be initial account to read files