如何重载基本类型(int、real...)的相等运算符?

问题描述 投票:0回答:2

是否可以重载 PostgreSQL 中现有的相等运算符,以给出

int
real
类型的两个值之间的相等性的新定义?我认为这违反了超载规则,但我想知道是否有办法做到这一点。我试过这个:

CREATE OPERATOR = ( LEFTARG = real ,
                    RIGHTARG = real,
                    PROCEDURE = new_equality,
                    COMMUTATOR = = ,
                    NEGATOR = !=
                  );

CREATE OR REPLACE FUNCTION new_equality (real, real) RETURNS BOOLEAN AS 
$$
SELECT abs ($1 - $2) < 0,2 ;
$$ LANGUAGE PL/PGSQL

但是当我在查询中使用相等运算符时,我没有得到任何结果。
我还尝试将

new_equality()
函数参数定义为我的属性类型,如下所示:

CREATE OR REPLACE FUNCTION new_equality (Student.age%TYPE, Student.age%TYPE) RETURNS BOOLEAN 
AS
$$
SELECT abs ($1 - $2) < 0,2;
$$ lANGUAGE PL/PGSQL

但是我收到一条通知,说 Postgres 将它们转换为

real
,当我在查询中使用相等运算符时,我仍然没有得到任何结果。

sql postgresql operator-overloading
2个回答
2
投票

Laurenz指出了

search_path
的直接问题。还有更多。

这会起作用:

CREATE OR REPLACE FUNCTION public.new_equality (real, real)  -- explicit schema!
  RETURNS bool
  LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE COST 10
RETURN abs($1 - $2) < 0.2;

CREATE OR REPLACE FUNCTION public.new_inequality (real, real)  -- explicit schema!
  RETURNS bool
  LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE COST 10
RETURN abs($1 - $2) >= 0.2;

CREATE OPERATOR public.= (             -- explicit schema!
  LEFTARG    = real
, RIGHTARG   = real
, FUNCTION   = public.new_equality
, COMMUTATOR = OPERATOR(public.=)      -- explicit schema!
, NEGATOR    = OPERATOR(public.!=)     -- must also exist
);

CREATE OPERATOR public.!= (
  LEFTARG    = real
, RIGHTARG   = real
, FUNCTION   = public.new_inequality
, COMMUTATOR = OPERATOR(public.!=)
, NEGATOR    = OPERATOR(public.=)
);

使用

OPERATOR()
构造来调用它:

SELECT id, real '0.1' OPERATOR(public.=) real '0.2';
SELECT id, real '0.1' OPERATOR(public.!=) real '0.2';
SELECT id, real '0.1' OPERATOR(public.<>) real '0.2';

小提琴 - 有更多示例

“标准 SQL”函数的语法至少需要 Postgres 14。参见:

注意更高的运算符优先级,可能会在普通运算符不会的情况下强制使用括号!

您还必须定义您在声明中提到的

NEGATOR
。使用内置的
!=
会是自相矛盾的废话。创建一个匹配运算符,使用模式限定语法引用它。 说明书:

要在

com_op
或其他可选参数中给出模式限定的运算符名称,请使用
OPERATOR()
语法 [...]

相关:

请注意,

<>
!=
的自动别名,
<>
是SQL中默认的不等运算符。

不合格的

=
将是标准的相等运算符 (
OPERATOR(pg_catalog.=)
),而您不会混淆
search_path
来降级
pg_catalog
- 你不应该这样做!降级
pg_catalog
为各种严重问题打开了大门,因为系统对象现在隐藏在一个或多个其他模式后面。 不要这样做,除非你确切地知道自己在做什么。关于
search_path

使用关键字

FUNCTION
代替误导性的
PROCEDURE
,这对于向后兼容仍然有效。参见:

就像评论中建议的一样,使用与现有符号不同的运算符符号以避免冲突可能会更方便。仍然比默认比较运算符具有标准(=更高)运算符优先级,并且不能轻易更改。


0
投票
您的代码无效(应该是

LANGUAGE sql

),但您的运算符不会被使用,因为 
pg_catalog
 隐式地位于 
search_path
 上。

您可以更改

search_path

pg_catalog
 放在其他地方:

SET search_path = public, pg_catalog;
或者您可以显式引用运算符:

SELECT 1::real OPERATOR(public.=) 1.1::real;
    
© www.soinside.com 2019 - 2024. All rights reserved.