postgresql是对oracle兼容很好的数据库,在很应用多场景下,能够把平滑把oracle上的应用迁移到postgresql中 ,大大降低费用。在接下来的博文中,将不定期更新一些postgresql内核中针对Oracle兼容的功能开发。
在Oracle中,sysdate是一个常见的用法,取到当前日期时间,postgresql中虽然没有相同的sysdate,但有功能几乎一样的函数now(), 那么我们如何基于now()用最小的改动实现一个sysdate用法呢?
在postgresql中,parser模块(代码在src/backend/parser/)负责语法解析,我们要做的事就是将sysdate和now()对应起来。
修改步骤:
1. 增加一个关键字sysdate,postgresql关键字声明在 \src\include\parser\kwlist.h中,增加一行SYSDATE的关键字声明:
PG_KEYWORD("sysdate", SYSDATE, RESERVED_KEYWORD)
注意增加位置要严格按字符串排序,加到 sysid 和symmetric之间,否则检查将不能通过。这里的第一个(sysdate)是关键字,第二个值(SYSDATE)是枚举值,由gram.y中token定,第三个值(RESERVED_KEYWORD)是声名是否为保留字。
2. 在src/backend/parser/gram.y中增加语法逻辑。先声名关键字对应的token, 最终会转化成上面对应的枚举值,在 %token <keyword> 中增加SYSDATE,这个可以不排序,但最好放到S开头的地方,如下图:
3. 接下来增加将sysdate和now()对应的关键代码。在 c_expr:中增加如下代码,
| SYSDATE
{
$$ = (Node *) makeFuncCall(list_make1(makeString("now")), NIL, @1);
}
如下图:
4.最后在 reserved_keyword: 增加 | SYSDATE,注意,这个必须严格排序,加在 SYMMETRIC 和 TABLE之间
OK,代码增加完毕,编译安装运行,实测效果图如下:
整个原理很简单,就是在表达式解析中,增加一个SYSDATE分支,对应now()函数。函数应该解析成什么则看 func_expr的解析方法,照着构造一个出来即可,这里的关键点在于sysdate是没有括号的函数调用,要支持这种用法。
parser模块后续计划会写几个博文详细介绍,有兴趣的朋友可以先看看flex bison,了解一些基础。