2016-09-26 48 views
3

我最近写了一个blog post关于为PostgreSQL的JSONB类型创建一个自定义的minus操作符。Postgres自定义运算符优先级高于内置?

基本上,运营商创建这样的:

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的尝试铸造JSONB在默认的文本没有指定明确的类型时?我能避免这种情况吗?

回答

4

由于文档中描述的operator type resolution rules而导致定义运营商时出现问题。

在您给出的示例中,-运算符的参数的类型为jsonb(左参数)和unknown(右参数)。 PostgreSQL的类型unknown是分配给string literals的类型。

现在,如果你的运营商定制的定义,操作型的分辨率选择你的操作步骤2.A:

  1. Check for an operator accepting exactly the input argument types. If one exists (there can be only one exact match in the set of operators considered), use it.

    a. If one argument of a binary operator invocation is of the unknown type, then assume it is the same type as the other argument for this check. Invocations involving two unknown inputs, or a unary operator with an unknown input, will never find a match at this step.

因此,unknown参数'a'将转换为jsonb,这会导致你错误观摩。

+0

啊,打我几秒钟:-) 另一件要注意的是,你不能改变自定义运算符的优先顺序(你可以看到在某些语言中使用的解决方案)。 https://www.postgresql.org/docs/current/static/sql-syntax-lexical.html#SQL-PRECEDENCE –