令我惊讶的是,我注意到简单的文本搜索 API 不利用属于 RLS 策略一部分的表上的索引。例如,mytable 有一个策略,而我正在使用名为 text_vector 的列 搜索:
WITH subq AS (
SELECT inst_id, text_vector, ts_rank(text_vector, q) AS rank, q
FROM mytable, plainto_tsquery('apple & orange') q
WHERE text_vector @@ q
)
SELECT inst_id, rank, ts_headline(text_content, q) AS markup
FROM subq
ORDER BY rank DESC;
我猜这与它们不防漏有关。是否有任何类型的解决方法而不更改系统表(例如,我在 RDS 中无法做到这一点)?
是的,那一定是RLS引起的。 PostgreSQL 必须防止在行级安全策略施加的条件之前调用非
LEAKPROOF
函数。现在@@
操作器不防漏。因此,即使相同的索引扫描(例如,多列 GiST 索引)可以满足 RLS 策略,该运算符也永远不会在索引扫描条件下使用。唯一的补救措施是免除用户在该表上的 RLS。抱歉,安全不是免费的。
您可能想知道为什么像
@@
这样无害的运算符不防漏。 PostgreSQL 在这里采取了非常严格的政策:只有当你能够证明你可以提供的任何可能参数都不会触发错误,从而允许你猜测有关其他参数的任何信息时,函数才会被标记为
LEAKPROOF
。例如,+
代表 integer
不是防漏的,因为溢出错误会泄漏有关其他参数的信息。