PostgreSQL7.0手册-程序员手册 -40. 扩展的 SQL: 操作符
第四十章. 扩展的 SQL: 操作符
Postgres 支持左目,右目和双目操作符.操作符可以重载,或以不同数目或类型的参数重新使用.如果有语义含混而系统无法决定使用哪个正确的操作符,它将返回一个错误。你可能必须转换左和/或右操作数的类型来帮助系统明白你想用的是哪个操作符.
每个操作符都是对真正干活的对应函数的"语义修饰";所以你在创建操作符之前必须先创建对应的函数。不过,一个操作符也并不仅仅是语义修饰,因为它还带着可以帮助查询规划器优化使用该操作符的查询的附加信息。本章的大部分将用于解释那些附加信息。
下面是一个创建用于两个复数相加的操作符的例子。我们假设已经创建了复数类型的定义。首先我们需要做(相加)工作的函数;然后我们就可以定义操作符:
CREATE FUNCTION complex_add(complex, complex)
RETURNS complex
AS '$PWD/obj/complex.so'
LANGUAGE 'c';
CREATE OPERATOR + (
leftarg = complex,
rightarg = complex,
procedure = complex_add,
commutator = +
);
现在我们可以:
SELECT (a + b) AS c FROM test_complex;
+----------------+
|c |
+----------------+
|(5.2,6.05) |
+----------------+
|(133.42,144.95) |
+----------------+
我们在这里已经演示了如何创建两目操作符。要创建单目操作符,只需要省略左操作数(对左目操作符)或者右操作数(对右操作符)即可。只有过程(procedure)子句和参数(argument)子句是 CREATE OPERATOR 里需要的条目。例子里演示的 COMMUTATOR 子句是一个给查询优化器的可选的暗示。关于 COMMUTATOR 和其它优化器暗示的详细信息在下面给出。
操作符优化信息
作者:由 Tom Lane 书写。
Postgres 的操作符定义可以包括几个可选的子句,这些子句告诉系统一些关于该操作符的特性的有用信息。在可能的情况下,我们都应该提供这些子句,因为它们可能为使用这个操作符的查询带来可观的速度提升。不过要注意如果你声明了这些子句,你必须确保它们是正确的!对优化子句的错误使用将导致后端的崩溃,精细的输出错误或者其他糟糕事情。如果你对这些事情不确定的话,你可以总是忽略优化子句;唯一的后果是查询可能比需要的运行的慢一些。
附加的优化子句可能在今后的 Postgres 版本里出现。这里描述的都是版本 6.5 可以理解的。
COMMUTATOR(换向器)
如果提供了 COMMUTATOR 子句,则命名一个操作符是被定义的操作符的换向器。如果有两个操作符 A,B,对于任何可能的输入 x,y 都有 (x A y) 等于 (y B x),那么我们就说 A 是 B 的换向器,同样 B 也是 A 的换向器。例如,操作符 '<' 和 '>' 对于所使用的一定的数据类型通常都是对方的换向器,而操作符 '+' 通常是它自身的换向器。但是操作符 '-' 通常没有换向器。
一个被换向的操作符的左操作符与它的换向器的右操作符相同,反之亦然。所以Postgres 所需要的只是一个换向器操作符的名称用以查找该换向器,那也是 COMMUTATOR 子句里所需要的唯一的东西。
当你定义一个自换向的操作符时,你定义它就是了。当你定义一对换向器操作符时,事情就有一点棘手:怎样定义一个操作符的换向器指向另一个你还没有定义的操作符呢?我们对这个问题有两个解决方法:
个方法是省略你定义的第一个操作符的 COMMUTATOR 子句,然后在第二个操作符的定义里提供一个( COMMUTATOR 子句)。因为 Postgres 知道换向操作符是成对出现的,所以当它看到第二个定义时它会自动返回并填充第一个定义里空缺的 COMMUTATOR 子句。
另一个更直接的方法是在两个定义里面都包含 COMMUTATOR 子句。当 Postgres 处理第一个定义并意识到 COMMUTAOTR 指向一个不存在的操作符,系统会在系统的 pg_operator 表里面为该操作符记录一个虚拟的记录。这个虚拟的记录只有操作符名,左和右参数类型以及结果类型是有效的,因为这些是到目前为止Postgres 可以推导出来的东西。第一个操作符表记录将和这个虚拟记录联接。稍后,当你定义第二个操作符时,系统将用来自第二个操作符的信息更新该虚拟记录。如果你试图在虚拟操作符被填充之前使用它,你将只能收到一条错误信息。(注意:这个过程在Postgres 6.5以前的版本不能可靠的工作,但是现在这种方法是我们推荐的方法。)
NEGATOR(否定符)
如果提供了 NEGATOR 子句,则命名一个操作符是被定义的操作符的否定符。如果有两个都返回布尔变量的操作符 A 和 B,对任何可能的输入 x 和 y,都有 (x A y) 等于 NOT (x B y),那么我们说 A 是 B 的否定符。当然 B 也是 A 的否定符。例如,'<' 和 '>=' 对大多数数据类型是一对否定符。一个操作符不可能是它自身的有效操作符。
不象 COMMUTATOR,一对单目操作符可以互为有效的否定符;那就意味着对于所有的 x,(A x) 等于 NOT (B x),或者类似的右目操作符的这种情况。
一个操作符的否定符必须有于该操作符本身一样的左和/或右参数,所以就象 COMMUTATOR 一样,只有操作符名需要在 NEGATOR 子句里面给出。
提供 NEGATOR 对查询优化器是非常有帮助的,因为这样就允许象 NOT (x = y) 这样的表达式简化成 x <> y。这样的情况比你想象的要频繁的多,因为 NOT 可能因为其他的重排列而被引入。
否定符对可以用上面换向符对中解释的相同的方法来定义。
RESTRICT(限制)
如果提供了 RESTRICT 子句,则为操作符命名一个选择性限制计算函数(注意这里是一个函数名,而不是一个操作符名)。RESTRICT 子句只是对返回布尔变量的双目操作符有意义。选择性限制计算符的概念是猜测一个表中所有行的哪一部分对于目前的操作符和特定的常量将满足一个象下面这样形式的 WHERE 条件子句
field OP constant
它可以给出这种类型的 WHERE 子句可以删除多少行的一个概念,这将帮助优化器进行优化。(你可能会说,如果该常量(constant)在左边怎么办?哦,那是 COMMUTATOR 干的事...)
书写新的选择性限制计算函数远远超
Postgres 支持左目,右目和双目操作符.操作符可以重载,或以不同数目或类型的参数重新使用.如果有语义含混而系统无法决定使用哪个正确的操作符,它将返回一个错误。你可能必须转换左和/或右操作数的类型来帮助系统明白你想用的是哪个操作符.
每个操作符都是对真正干活的对应函数的"语义修饰";所以你在创建操作符之前必须先创建对应的函数。不过,一个操作符也并不仅仅是语义修饰,因为它还带着可以帮助查询规划器优化使用该操作符的查询的附加信息。本章的大部分将用于解释那些附加信息。
下面是一个创建用于两个复数相加的操作符的例子。我们假设已经创建了复数类型的定义。首先我们需要做(相加)工作的函数;然后我们就可以定义操作符:
CREATE FUNCTION complex_add(complex, complex)
RETURNS complex
AS '$PWD/obj/complex.so'
LANGUAGE 'c';
CREATE OPERATOR + (
leftarg = complex,
rightarg = complex,
procedure = complex_add,
commutator = +
);
现在我们可以:
SELECT (a + b) AS c FROM test_complex;
+----------------+
|c |
+----------------+
|(5.2,6.05) |
+----------------+
|(133.42,144.95) |
+----------------+
我们在这里已经演示了如何创建两目操作符。要创建单目操作符,只需要省略左操作数(对左目操作符)或者右操作数(对右操作符)即可。只有过程(procedure)子句和参数(argument)子句是 CREATE OPERATOR 里需要的条目。例子里演示的 COMMUTATOR 子句是一个给查询优化器的可选的暗示。关于 COMMUTATOR 和其它优化器暗示的详细信息在下面给出。
操作符优化信息
作者:由 Tom Lane 书写。
Postgres 的操作符定义可以包括几个可选的子句,这些子句告诉系统一些关于该操作符的特性的有用信息。在可能的情况下,我们都应该提供这些子句,因为它们可能为使用这个操作符的查询带来可观的速度提升。不过要注意如果你声明了这些子句,你必须确保它们是正确的!对优化子句的错误使用将导致后端的崩溃,精细的输出错误或者其他糟糕事情。如果你对这些事情不确定的话,你可以总是忽略优化子句;唯一的后果是查询可能比需要的运行的慢一些。
附加的优化子句可能在今后的 Postgres 版本里出现。这里描述的都是版本 6.5 可以理解的。
COMMUTATOR(换向器)
如果提供了 COMMUTATOR 子句,则命名一个操作符是被定义的操作符的换向器。如果有两个操作符 A,B,对于任何可能的输入 x,y 都有 (x A y) 等于 (y B x),那么我们就说 A 是 B 的换向器,同样 B 也是 A 的换向器。例如,操作符 '<' 和 '>' 对于所使用的一定的数据类型通常都是对方的换向器,而操作符 '+' 通常是它自身的换向器。但是操作符 '-' 通常没有换向器。
一个被换向的操作符的左操作符与它的换向器的右操作符相同,反之亦然。所以Postgres 所需要的只是一个换向器操作符的名称用以查找该换向器,那也是 COMMUTATOR 子句里所需要的唯一的东西。
当你定义一个自换向的操作符时,你定义它就是了。当你定义一对换向器操作符时,事情就有一点棘手:怎样定义一个操作符的换向器指向另一个你还没有定义的操作符呢?我们对这个问题有两个解决方法:
个方法是省略你定义的第一个操作符的 COMMUTATOR 子句,然后在第二个操作符的定义里提供一个( COMMUTATOR 子句)。因为 Postgres 知道换向操作符是成对出现的,所以当它看到第二个定义时它会自动返回并填充第一个定义里空缺的 COMMUTATOR 子句。
另一个更直接的方法是在两个定义里面都包含 COMMUTATOR 子句。当 Postgres 处理第一个定义并意识到 COMMUTAOTR 指向一个不存在的操作符,系统会在系统的 pg_operator 表里面为该操作符记录一个虚拟的记录。这个虚拟的记录只有操作符名,左和右参数类型以及结果类型是有效的,因为这些是到目前为止Postgres 可以推导出来的东西。第一个操作符表记录将和这个虚拟记录联接。稍后,当你定义第二个操作符时,系统将用来自第二个操作符的信息更新该虚拟记录。如果你试图在虚拟操作符被填充之前使用它,你将只能收到一条错误信息。(注意:这个过程在Postgres 6.5以前的版本不能可靠的工作,但是现在这种方法是我们推荐的方法。)
NEGATOR(否定符)
如果提供了 NEGATOR 子句,则命名一个操作符是被定义的操作符的否定符。如果有两个都返回布尔变量的操作符 A 和 B,对任何可能的输入 x 和 y,都有 (x A y) 等于 NOT (x B y),那么我们说 A 是 B 的否定符。当然 B 也是 A 的否定符。例如,'<' 和 '>=' 对大多数数据类型是一对否定符。一个操作符不可能是它自身的有效操作符。
不象 COMMUTATOR,一对单目操作符可以互为有效的否定符;那就意味着对于所有的 x,(A x) 等于 NOT (B x),或者类似的右目操作符的这种情况。
一个操作符的否定符必须有于该操作符本身一样的左和/或右参数,所以就象 COMMUTATOR 一样,只有操作符名需要在 NEGATOR 子句里面给出。
提供 NEGATOR 对查询优化器是非常有帮助的,因为这样就允许象 NOT (x = y) 这样的表达式简化成 x <> y。这样的情况比你想象的要频繁的多,因为 NOT 可能因为其他的重排列而被引入。
否定符对可以用上面换向符对中解释的相同的方法来定义。
RESTRICT(限制)
如果提供了 RESTRICT 子句,则为操作符命名一个选择性限制计算函数(注意这里是一个函数名,而不是一个操作符名)。RESTRICT 子句只是对返回布尔变量的双目操作符有意义。选择性限制计算符的概念是猜测一个表中所有行的哪一部分对于目前的操作符和特定的常量将满足一个象下面这样形式的 WHERE 条件子句
field OP constant
它可以给出这种类型的 WHERE 子句可以删除多少行的一个概念,这将帮助优化器进行优化。(你可能会说,如果该常量(constant)在左边怎么办?哦,那是 COMMUTATOR 干的事...)
书写新的选择性限制计算函数远远超
Tags:PostgreSQL,手册,程序员,手册,扩展,SQL,操作符

