最初的目标:创建一个约束以确保特定 Postgres 表中只存在不重叠的子网。
通过仔细阅读文档,我可以做到这一点:
create table subnets (
subnet cidr,
exclude (subnet with &&)
);
但这不起作用。它产生了难以理解的信息:
ERROR: operator &&(inet,inet) is not a member of operator family "network_ops"
DETAIL: The exclusion operator must be related to the index operator class for the constraint.
尽管阅读了有关运算符类和索引以及索引类型的文档部分,但我仍然觉得我错过了一个被认为是理所当然的整个解释部分。我仍然不知道什么是操作员类,真的,也不是操作员家族。
我确实在邮件列表上找到了一个代码片段,该代码片段导致以下工作代码:
create table subnets (
subnet cidr,
exclude using gist (subnet inet_ops with &&)
);
但我无法真正理解“使用要点”的用途,也无法真正理解“inet_ops”的用途。
我知道“使用要点”与索引类型有关。我知道索引是为“唯一”约束自动创建的,我猜也可能为“排除”约束自动创建索引。 关于“操作员类”的唯一文档都与索引有关,而不是约束。
对于我想要排除约束的这个或未来的查询,我如何确定应该指定什么运算符类和访问方法才能使约束起作用?
请注意,即使手头有工作代码,我也无法找到为什么它是“gist”而不是其他东西,以及为什么它是“inet_ops”而不是“network_ops”或什么都没有。 \doS
并且操作员类文档中列出的查询令人费解。
我产生的另一个错误也令人费解:
vagrant=# create table subnets (
subnet cidr,
exclude using gist (subnet with &&)
);
ERROR: data type cidr has no default operator class for access method "gist"
HINT: You must specify an operator class for the index or define a default operator class for the data type.
(这个问题的前提是我不应该求助于复制和粘贴咒语;彻底审查文档并仔细阅读错误消息应该可以让我解决问题。对于 Postgres,这在以前一直是正确的。)
PostgreSQL 索引由两部分组成,从接口扩展到索引的文档
\dA+
在 psql 中看到这个。)GIST 是索引方法。为什么需要 GIST 或 SP-GIST,
EXCLUSION CONSTRAINTS
请参阅这篇文章。您需要的运算符类inet_ops
是. 您遇到的问题是 forcidr
并且inet
提供了两个 GIST 运算符类,而错误的是 default,gist_cidr_ops
是默认值。它是“附加提供的模块”的一部分,大多数发行版将其打包为-contrib
. 它由btree_gist
扩展提供(源)inet_ops
是核心,而不是默认值。你怎么会知道这个?你可能不会。至于访问类型,祝你好运。与 PostgreSQL 一起分发的文档本身在这里非常缺乏,尽管他们确实涉及到这一点,
您可以做的最好的事情是提交一个文档补丁到
btree_gist
可能也应该记录的地方。