JDBC规范是否阻止'?'从被用作运营商(在报价之外)?

时间:2013-02-08 19:24:35

标签: sql postgresql jdbc specifications

来自Sam Macbeth's question

  

JDBC规范中有什么允许的吗?要转义并且不是参数占位符吗?

例如,Postgres允许您使用?作为运算符:

SELECT * FROM tbl WHERE tbl.data ? 'abc'

JDBC驱动程序可以让你使用吗?作为运营商仍然是符合JDBC的?

3 个答案:

答案 0 :(得分:9)

如果你有最新的postgresql驱动程序,你可以使用:

??

更改原始查询:

SELECT * FROM tbl WHERE tbl.data ?? 'abc'

此拉取请求中包含详细信息 - https://github.com/pgjdbc/pgjdbc/pull/227 这个改变是在原始问题之后很久才做出的,但值得注意的是,现在有一个简单的答案。

答案 1 :(得分:7)

我认为如果JDBC驱动程序允许?运算符不转义并按原样使用它将是完全可以接受的,但它可能会使您的解析器复杂化以实际识别此运算符的参数和2 )可能会混淆习惯?的人(也可能是工具)只是意味着参数占位符。

所以我的建议是提供某种逃避(或替代操作员)。但是,查看JDBC规范,驱动程序应该只使用JDBC转义语法来实现JDBC规范中定义的转义(13.4.2:“转义语法不用于调用用户定义的或供应商特定的标量函数。 “;虽然这是关于{fn ...}转义的具体内容。

所以要么你需要使用另一种逃避,要么“打破”规则(我认为没有人会介意)。如果您想要更具说明性的答案,可以将问题发送到jdbc-spec-discuss mailinglist。我相信Lance Andersen(JDBC规范负责人)将提供答案。

修改

另外有趣的是,JDBC规范第6.2节(指南和要求)说:

  

驱动程序应提供对底层数据源实现的每个功能的访问,包括扩展JDBC API的功能。目的是使用JDBC API的应用程序可以访问与本机应用程序相同的功能集。

所以基于你应该(不一定)支持? - 运算符,你只需要找到一种实用的方法来实现它。


基于discussion on jdbc-spec-discuss

进行更新

根据Lance Andersen的说法,JDBC规范遵循关于问号的SQL规范:它们只能用作查询文本中的参数占位符(当然除了注释和引用文本),因此使用{{1}就像在PostgreSQL中一样,hstore运算符是不允许的。 (见this message

可用选项是为操作员提供别名或转义,前提是这与未来的更改不相冲突(如果没有透视,则很难做到这一点)。最好的解决方案 - 防止未来JDBC更改出现问题 - 可能是一个自定义转义。

JDBC实际上并没有定义供应商转义,但Lance Andersen确实提出了类似于JDBC转义的转义:?;在此转义中使用vendorname或drivername将提供一种命名空间形式,以防止与规范冲突。 (见this message

为了与'普通'JDBC函数转义一致,我建议定义一个转义,允许你问题中的查询表示为:

{postgres <thing to be escaped>}

我根据hstore documentationSELECT * FROM tbl WHERE {postgres containskey(tbl.data, 'abc')} 的含义选择containskey。对??&)和containsallkeys?|的类似建议。为了保持一致性,您可以考虑为其他hstore运算符执行此操作。

你也可以决定只逃避问号本身。例如,使用containsanykey{postgres '?'}(问号为qm)进行转义。我认为可读性低于我的函数逃避建议:

{postgres qm}

根据JDBC v.Next(4.4?)

的新提案进行了更新

下一个JDBC规范(可能编号为4.4),可能会添加一个显式的JDBC转义来完全转义查询的片段,明确的意图是能够转义本身不使用问号的数据库系统的问号对于参数标记,需要支持问号的其他用途。

建议的语法是SELECT * FROM tbl WHERE tbl.data {postgres '?'} 'abc' (Oracle JDBC驱动程序已经将其作为非标准转义支持)。使用此语法,可以使用{\ <thing-to escape> \}(在字符串文字:{\?\})中转义参数标记,或者转义更大的片段以提高可读性。

另请参阅jdbc-spec-discuss邮件列表中的SQL 2016 MATCH RECOGNIZE JDBC parameter Marker / Escape Charactersearlier discussion

答案 2 :(得分:5)

我在JDBC specification中看不到允许?转义的任何内容。几乎所有关于?的说法都是:

  

参数标记(由SQL字符串中的“?”表示)用于指定语句的输入值,这些值可能在运行时发生变化。 [1]

以后......

  

参数序号,即传递给approriate setter方法的整数,在语句中引用参数标记(“?”),从1开始。 [2]

它只为一小组功能定义了转义语法,这些功能看起来都不适用于?

  

JDBC为以下内容定义了转义语法:

     
      
  • 标量函数
  •   
  • 日期和时间文字
  •   
  • 外部联接
  •   
  • 调用存储过程
  •   
  • LIKE子句的转义字符 [3]
  •   

总的来说,似乎JDBC规范没有非常“严格”的语言(例如,与使用必须 的某些W3C规范文档相比较很多),所以我不知道允许?转义的驱动程序是否在技术上不合规,但它可能不太兼容。

甚至连Postgres驱动程序都不允许它,因为驱动程序中的方法实际解析了? doesn't check for any escape characters的SQL语句。


1。 JDBC 4.1规范,第13.2节 - PreparedStatement接口
2。 JDBC 4.1规范,第13.3.2节 - 设置参数
3。 JDBC 4.1规范,第13.4节 - 转义语法