[关闭]
@Rays 2022-06-30T09:18:13.000000Z 字数 1368 阅读 341

PostgreSQL 14会破坏其官方的.NET和Java驱动


摘要: PostgreSQL 14中的新语法,尤其是使用BEGIN ATOMIC ... END创建SQL函数,在某些情况下会破坏其官方的.NET和Java数据库驱动。但只要不通过Npgsql或PgJDBC修改数据库模式,就不会出现问题。

作者: Jonathan Allen

正文:

PostgreSQL 14中的新语法,尤其是使用BEGIN ATOMIC ... END创建SQL函数,在某些情况下会破坏其官方的.NET和Java数据库驱动。但只要不通过NpgsqlPgJDBC修改数据库模式,就不会出现问题。

对于Java的JDBC和.NET的ADO.NET数据库驱动框架,它们存在一个共同点,那就是都支持使用分号实现SQL语句批处理。批处理对提高性能是十分必要的。如果客户端一次只发送一个命令,那么每个命令就必须要付出通信延迟代价。但如果使用批处理一次执行一批语句,那么只需付出一次通信代价。

事实上,SQL Server等数据库将批处理语句作为一个庞大的SQL字符串整体发送。但PostgreSQL的wire通信协议工作机制有别如此。虽然批处理语句依然整体发送,但客户端需将语句拆分为各条独立的命令。

原始实现可简单地假设每个分号标识一条语句的终止处。当然,分号也可能是一条语句字符串中的内容,而非一条语句的结尾。Npgsql和PgJDBC解析器对此做了考虑。

这曾经工作得很好。但现在新建SQL函数体中可以定义多条语句,那么应如何处理?当然这也不是问题,因为函数体使用“$...$”标记做转义。在“$...$”标记对内的分号,与其它字符串文字的处理方式无异。

进而PostgreSQL 14添加了称为“SQL标准语法”的“BEGIN ATOMIC ... END”语句。对此发行说明中给出如下解释,

使用SQL标准语法编写的函数或过程能快速解析,并存储为解析树形式。这可更好地追踪函数的依赖关系,并具有更好的安全性。

由于分号可能并非出现在引号引起的字符串中,而是会出现在BEGIN ATOMIC ... END语句块内的任何位置,如果解析器使用当前的方法,就无法确定批处理中语句的拆分位置。完全支持语句拆分或是要去更改API,或是要去新建一个更复杂的解析器。

Npgsql已关注当前解析器的开销问题,决定更改API。在Npgsql的库中增加了一种称为“原始SQL(raw SQL mode)”的模式。此模式没有使用命名参数,需要使用位置(positional)参数。

而PgJDBC团队尚未决定采用何种方法。其进展可关注软件缺陷报告“新的PG14 SQL标准函数破坏了PgJDBC解析器(New PG14 SQL-standard function bodies break our SQL parser)”。

作者简介

Jonathan Allen在上世纪90年代后期为一家健康诊所实施MIS项目,实现从Access和Excel逐步升级为企业解决方案。在金融部门编写五年自动交易系统后,他成为多个项目的顾问,其中包括机器人仓库UI、癌症研究软件中间层,以及解决一家大型房地产保险公司的大数据需求。在空闲时间,他喜欢研习16世纪的武术。

原文链接: PostgreSQL 14 Breaks the .NET and Java Drivers for PostgreSQL

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注