我最近写了一篇关于为PostgreSQL的JSONB类型创建自定义减号运算符的blog post。
基本上,运算符是这样创建的:
CREATE OPERATOR - (
PROCEDURE = jsonb_minus,
LEFTARG = jsonb,
RIGHTARG = jsonb )
但是,正如评论者正确指出的那样,在创建此运算符之后,默认的JSONB - TEXT不再起作用。此查询会导致错误:
SELECT '{"a":1, "b":{"c":123, "d":"test"}}'::jsonb - 'a'
结果为invalid input syntax for type json
。您必须将第二个参数显式地转换为TEXT才能使其正常工作。
删除自定义运算符后,将恢复正常行为,上面的查询会显示所需的结果:{"b": {"c": 123, "d": "test"}}
为什么Postgres会在未指定显式类型时尝试通过默认TEXT转换为JSONB?我可以避免这个吗?
答案 0 :(得分:4)
由于文档中描述的operator type resolution rules而定义运算符时会出现问题。
在您给出的示例中,-
运算符的参数具有类型jsonb
(左参数)和unknown
(右参数)。 PostgreSQL的类型unknown
是分配给string literals的类型。
现在,如果定义了自定义运算符,则运算符类型解析在步骤2.a。中选择运算符:
- 醇>
检查操作员是否完全接受输入参数类型。如果存在(在所考虑的运算符集中只能有一个完全匹配),请使用它。
一个。如果二元运算符调用的一个参数是
unknown
类型,则假设它与此检查的另一个参数类型相同。涉及两个unknown
输入或带有unknown
输入的一元运算符的调用在此步骤中永远不会找到匹配项。
因此,unknown
参数'a'
将转换为jsonb
,这会导致您发现错误。