9.3 9.4 9.5 9.6 10 11 12 13 14 Current(15)
阿里云PostgreSQL 问题报告 纠错本页面

63.3. B-树支持函数

表 37.8中所示,btree定义了一种必需的和两种可选的支持函数。

对于btree操作符族为其提供了比较操作符的每一种数据类型组合,操作符族必须提供一个比较支持函数,在pg_amproc中注册:支持函数编号为1,amproclefttype/amprocrighttype等于比较的左右数据类型(即匹配的操作符注册在pg_amop中的数据类型)。比较函数必须接收两个非空值AB并且返回一个int32值,返回值在A < BA = B以及A > B时分别为< 00> 0。不允许空值结果:该数据类型的所有值必须是可比较的。例子请见src/backend/access/nbtree/nbtcompare.c

如果被比较的值是一种可排序的数据类型,合适的排序规则OID将使用标准的PG_GET_COLLATION()机制被传递给比较支持函数。

可选地,btree操作符族可以提供排序支持函数,它们以支持函数编号2注册。这些函数允许以一种比单纯调用比较支持函数更加高效的方式实现排序比较。涉及的API在src/include/utils/sortsupport.h中定义。

可选地,btree操作符族可以提供in_range支持函数,它们以支持函数编号3注册。在btree索引操作期间不会用到这些函数,它们扩展了操作符族的语义,这样就能支持包含RANGE offset PRECEDING以及RANGE offset FOLLOWING窗口帧界类型(见第 4.2.8 节)的窗口子句。归根到底,这些函数所提供的额外信息是如何以一种与该操作符族的数据排序相兼容的方式加上或者减去一个offset值。

一个in_range函数必须具有这样的签名

in_range(val type1, base type1, offset type2, sub bool, less bool)
returns bool

valbase必须是同一种类型,该类型也是操作符族所支持的类型之一(即它提供排序的一种类型)。不过,offset可以是一种不同的类型,该类型有可能不被该操作符族所支持。例如内建的time_ops族提供了一个in_range函数,其offset是类型interval。一个操作符族可以为其所支持的任意类型提供in_range函数以及一个或者更多种offset类型。每一个in_range函数在进入到pg_amproc时,需要有amproclefttype等于type1以及amprocrighttype等于type2

in_range函数的本质语义取决于两个布尔标志参数。它应该将baseoffset相加或者相减,然后用val与其结果比较:

在这样做之前,该函数应该检查offset的符号:如果它小于零,则抛出错误ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE (22013)外加invalid preceding or following size in window function这样的错误文本(这是SQL标准所要求的,不过非标准操作符族可能会选择忽视这一限制,因为似乎其语义必要性很小)。这种要求被委托给了in_range函数,这样核心代码不需要理解对一种特定数据类型less than zero表示什么。

一个额外的期望是,如果可行,in_range函数应当在base + offset或者base - offset溢出时避免抛出错误。即便值超过了该数据类型的范围,也可以确定正确的比较结果。注意,如果数据类型包括诸如infinity或者NaN之类的概念,就需要额外的注意确保in_range的结果符合该操作符族的正常排序顺序。

in_range函数的结果必须与操作符族施加的排序顺序保持一致。准确的来说,给定任意固定的offset值以及sub值,那么:

less = false时,类似的具有相逆条件的语句成立。

如果被排序的类型(type1)是可排序的,合适的排序规则OID将使用标准的PG_GET_COLLATION()机制被传递给in_range函数。

in_range函数不需要处理NULL输入,并且通常将被标记为strict。