如何为基本类型(int、real...)重载相等运算符?
How to overload the equality operator for primitive types (int, real...)?
是否可以重载 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 ( - ) < 0,2 ;
$$ LANGUAGE PL/PGSQL
但是当我在查询中使用相等运算符时,我没有得到任何结果。
我还尝试将 new_equality()
函数参数定义为我的属性类型,如下所示:
CREATE OR REPLACE FUNCTION new_equality (Student.age%TYPE, Student.age%TYPE) RETURNS BOOLEAN
AS
$$
SELECT abs ( - ) < 0,2;
$$ lANGUAGE PL/PGSQL
但我收到一条通知,说 Postgres 将它们转换为 real
,当我在查询中使用相等运算符时,我仍然没有得到任何结果。
您的代码无效(应该是 LANGUAGE sql
),但是您的运算符不会被使用,因为 pg_catalog
在 search_path
.[=17= 上隐含地排在第一位]
您可以将 search_path
更改为将 pg_catalog
放在其他地方:
SET search_path = public, pg_catalog;
或者您可以显式引用运算符:
SELECT 1::real OPERATOR(public.=) 1.1::real;
Laurenz 指出了眼前的问题 search_path
。还有更多。
假设 Postgres 14,这会起作用:
CREATE OR REPLACE FUNCTION public.new_equality (real, real) -- be explicit about the schema!
RETURNS bool
LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE COST 10
BEGIN ATOMIC
SELECT abs( - ) < 0.2;
END;
CREATE OR REPLACE FUNCTION public.new_inequality (real, real) -- be explicit about the schema!
RETURNS bool
LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE COST 10
BEGIN ATOMIC
SELECT abs( - ) >= 0.2;
END;
CREATE OPERATOR public.= ( -- be explicit about the schema!
LEFTARG = real
, RIGHTARG = real
, FUNCTION = public.new_equality
, COMMUTATOR = OPERATOR(public.=) -- be explicit about the 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';
db<>fiddle here - 更多示例
注意 higher operator precedence,可能会在普通运算符不会强制使用括号!
您还必须定义您在声明中提到的NEGATOR
。使用 built-in !=
将是自相矛盾的废话。创建一个匹配运算符,您必须使用 schema-qualified 语法引用它。 The manual:
To give a schema-qualified operator name in com_op
or the other optional arguments, use the OPERATOR()
syntax [...]
相关:
- How to use % operator from the extension pg_trgm?
注意 <>
是 !=
的自动别名,<>
是 SQL.
中的默认不等式运算符
不合格的 =
将是标准的相等运算符 (OPERATOR(pg_catalog.=)
),而您不会乱用 search_path
来降级 pg_catalog
- 您应该吨!降级 pg_catalog
为各种严重问题打开了大门,因为系统对象现在隐藏在一个或多个其他模式之后。 不要 这样做,除非您确切地知道自己在做什么。关于 search_path
:
- How does the search_path influence identifier resolution and the "current schema"
这假设至少是 Postgres 14。关于 BEGIN ATOMIC
:
- How to implement `BEGIN ATOMIC` in PostgreSQL
使用关键字 FUNCTION
而不是误导性的 PROCEDURE
,这对于向后兼容仍然有效。参见:
与一样,使用与现有运算符不同的运算符符号可能更方便,以避免冲突。仍将具有比默认比较运算符标准(= 更高)的运算符优先级,并且不能轻易更改。
是否可以重载 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 ( - ) < 0,2 ;
$$ LANGUAGE PL/PGSQL
但是当我在查询中使用相等运算符时,我没有得到任何结果。
我还尝试将 new_equality()
函数参数定义为我的属性类型,如下所示:
CREATE OR REPLACE FUNCTION new_equality (Student.age%TYPE, Student.age%TYPE) RETURNS BOOLEAN
AS
$$
SELECT abs ( - ) < 0,2;
$$ lANGUAGE PL/PGSQL
但我收到一条通知,说 Postgres 将它们转换为 real
,当我在查询中使用相等运算符时,我仍然没有得到任何结果。
您的代码无效(应该是 LANGUAGE sql
),但是您的运算符不会被使用,因为 pg_catalog
在 search_path
.[=17= 上隐含地排在第一位]
您可以将 search_path
更改为将 pg_catalog
放在其他地方:
SET search_path = public, pg_catalog;
或者您可以显式引用运算符:
SELECT 1::real OPERATOR(public.=) 1.1::real;
Laurenz 指出了眼前的问题 search_path
。还有更多。
假设 Postgres 14,这会起作用:
CREATE OR REPLACE FUNCTION public.new_equality (real, real) -- be explicit about the schema!
RETURNS bool
LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE COST 10
BEGIN ATOMIC
SELECT abs( - ) < 0.2;
END;
CREATE OR REPLACE FUNCTION public.new_inequality (real, real) -- be explicit about the schema!
RETURNS bool
LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE COST 10
BEGIN ATOMIC
SELECT abs( - ) >= 0.2;
END;
CREATE OPERATOR public.= ( -- be explicit about the schema!
LEFTARG = real
, RIGHTARG = real
, FUNCTION = public.new_equality
, COMMUTATOR = OPERATOR(public.=) -- be explicit about the 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';
db<>fiddle here - 更多示例
注意 higher operator precedence,可能会在普通运算符不会强制使用括号!
您还必须定义您在声明中提到的NEGATOR
。使用 built-in !=
将是自相矛盾的废话。创建一个匹配运算符,您必须使用 schema-qualified 语法引用它。 The manual:
To give a schema-qualified operator name in
com_op
or the other optional arguments, use theOPERATOR()
syntax [...]
相关:
- How to use % operator from the extension pg_trgm?
注意 <>
是 !=
的自动别名,<>
是 SQL.
不合格的 =
将是标准的相等运算符 (OPERATOR(pg_catalog.=)
),而您不会乱用 search_path
来降级 pg_catalog
- 您应该吨!降级 pg_catalog
为各种严重问题打开了大门,因为系统对象现在隐藏在一个或多个其他模式之后。 不要 这样做,除非您确切地知道自己在做什么。关于 search_path
:
- How does the search_path influence identifier resolution and the "current schema"
这假设至少是 Postgres 14。关于 BEGIN ATOMIC
:
- How to implement `BEGIN ATOMIC` in PostgreSQL
使用关键字 FUNCTION
而不是误导性的 PROCEDURE
,这对于向后兼容仍然有效。参见:
与