要理解规则系统是如何工作的,有必要知道它何时被调用,以及它的输入和结果是什么。
规则系统位于解析器和规划器之间。它接收解析器的输出,一个查询树,以及用户定义的重写规则,这些重写规则也是带有额外信息的查询树,并生成零个或多个查询树作为结果。因此,它的输入和输出总是解析器本身可以产生的,因此,它看到的任何东西基本上都可以表示为一个SQL语句。
那么,什么是查询树?它是一个内部表示,用于表示一个SQL语句,其中构建它的单个部分被单独存储。这些查询树可以在服务器日志中显示,如果您设置了配置参数 debug_print_parse
、debug_print_rewritten
或 debug_print_plan
。规则动作也作为查询树存储在系统目录 pg_rewrite
中。它们不像日志输出那样格式化,但包含完全相同的信息。
读取原始查询树需要一些经验。但是,由于SQL查询树的表示形式足以理解规则系统,因此本章将不教授如何读取它们。
在阅读本章中的SQL查询树表示时,需要能够识别语句在查询树结构中被分解成的部分。查询树的组成部分是
这是一个简单的值,指示哪个命令(SELECT
、INSERT
、UPDATE
、DELETE
)生成了查询树。
范围表是查询中使用的关系的列表。在 SELECT
语句中,这些是 FROM
关键字后面的关系。
每个范围表条目标识一个表或视图,并说明它在查询的其他部分中是如何被称呼的。在查询树中,范围表条目是通过编号而不是名称来引用的,因此这里即使有重复的名称也不会像在 SELECT
SQL语句中那样存在问题。当规则的范围表被合并后,这种情况就可能发生。本章中的示例不会出现这种情况。
这是一个指向范围表的索引,用于标识查询结果要写入的关系。
SELECT
查询没有结果关系。(SELECT INTO
的特殊情况几乎与 CREATE TABLE
后跟 INSERT ... SELECT
相同,此处不单独讨论。)
对于 INSERT
、UPDATE
和 DELETE
命令,结果关系是更改要生效的表(或视图!)。
目标列表是定义查询结果的表达式列表。对于 SELECT
,这些表达式是构成查询最终输出的表达式。它们对应于 SELECT
和 FROM
关键字之间的表达式。(*
只是关系的所有列名的缩写。它会被解析器展开成单独的列,因此规则系统永远不会看到它。)
DELETE
命令不需要普通的目标列表,因为它们不产生任何结果。相反,规划器会在空目标列表中添加一个特殊的CTID条目,以便执行器能够找到要删除的行。(当结果关系是普通表时,会添加CTID。如果它是视图,则如 第 39.2.4 节中所述,规则系统会添加一个整行变量。)
对于 INSERT
命令,目标列表描述了应该插入到结果关系中的新行。它由 VALUES
子句中的表达式或 INSERT ... SELECT
中的 SELECT
子句中的表达式组成。重写过程的第一步会为任何未被原始命令赋值但有默认值的列添加目标列表条目。任何剩余的列(既没有指定值也没有默认值)将被规划器填充为常量 NULL 表达式。
对于 UPDATE
命令,目标列表描述了应该替换旧行的新行。在规则系统中,它只包含命令的 SET column = expression
部分中的表达式。规划器将通过插入复制旧行值到新行的表达式来处理缺失的列。与 DELETE
一样,也会添加一个CTID或整行变量,以便执行器能够识别要更新的旧行。
目标列表中的每个条目都包含一个表达式,该表达式可以是常量值、指向范围表中某个关系的列的变量、参数,或者由函数调用、常量、变量、运算符等组成的表达式树。
查询的限定条件是一个表达式,与目标列表条目中包含的表达式类似。此表达式的结果值是一个布尔值,指示是否应执行最终结果行的操作(INSERT
、UPDATE
、DELETE
或 SELECT
)。它对应于 SELECT
的 WHERE
子句。SQL语句。
查询的连接树显示了 FROM
子句的结构。对于像 SELECT ... FROM a, b, c
这样的简单查询,连接树只是 FROM
项的列表,因为我们可以按任何顺序连接它们。但当使用 JOIN
表达式,特别是外连接时,我们必须按照连接显示的顺序进行连接。在这种情况下,连接树显示了 JOIN
表达式的结构。与特定 JOIN
子句相关联的限制(来自 ON
或 USING
表达式)作为限定表达式存储在那些连接树节点上。将顶层 WHERE
表达式也作为限定表达式附加到顶层连接树项上也可能很方便。因此,连接树实际上代表了 SELECT
的 FROM
和 WHERE
子句。
查询树的其他部分,如 ORDER BY
子句,在此处不予关注。规则系统在应用规则时会替换其中的某些条目,但这与规则系统的基本原理关系不大。
如果您在文档中发现任何不正确、与您对特定功能的体验不符或需要进一步澄清的内容,请使用 此表格 报告文档问题。