Fli*_*mzy 8 postgresql stored-procedures unit-test
我有一个简单的存储过程,其返回值取决于inet_client_addr()
. inet_client_addr()
在测试我的存储过程时,如何为了单元测试的目的而覆盖?
到目前为止,我想出的唯一解决方案是围绕inet_client_addr()
以下内容创建一个包装函数:
CREATE FUNCTION my_inet_client_addr() RETURNS INET AS $$
SELECT inet_client_addr();
$$ LANGUAGE sql;
Run Code Online (Sandbox Code Playgroud)
然后在我的函数中使用它:
CREATE local_connection() RETURNS BOOLEAN AS $$
SELECT my_inet_client_addr() = '127.0.0.1';
$$ LANGUAGE sql;
Run Code Online (Sandbox Code Playgroud)
然后在我的单元测试中,我可以重新定义my_inet_client_addr()
:
BEGIN;
SELECT PLAN(2);
REPLACE FUNCTION my_inet_client_addr() RETURNS INET AS $$
SELECT '127.0.0.1'::INET;
$$ LANGUAGE sql;
is(local_connection(),TRUE,'Connection from 127.0.0.1 is local');
REPLACE FUNCTION my_inet_client_addr() RETURNS INET AS $$
SELECT '192.168.1.1'::INET;
$$ LANGUAGE sql;
is(local_connection(),FALSE,'Connection from 192.168.1.1. is not local');
ROLLBACK;
Run Code Online (Sandbox Code Playgroud)
有没有办法在没有包装功能的情况下完成相同的任务my_inet_client_addr()
?
inet_client_addr()
是系统信息函数。
它pg_catalog
像其他内置函数一样位于模式中(附加模块除外)。
pg_catalog
是自动的一部分search_path
。根据文档:
此外
public
用户创建的模式之外,每个数据库还包含一个pg_catalog
模式,其中包含系统表和所有内置数据类型、函数和运算符。pg_catalog
始终是搜索路径的有效组成部分。如果它没有在路径中显式命名,那么在搜索路径的模式之前会隐式搜索它。这可确保始终可以找到内置名称。但是,如果您希望用户定义的名称覆盖内置名称,则可以明确地将其放置pg_catalog
在搜索路径的末尾。
大胆强调我的。
所以我们创建了一个专门的模式,并将其放置之前 pg_catalog
在search_path
:
CREATE SCHEMA override;
CREATE OR REPLACE FUNCTION override.inet_client_addr()
RETURNS inet AS
$func$
SELECT '127.0.0.1'::inet
$func$ language sql STABLE;
Run Code Online (Sandbox Code Playgroud)
SET search_path = override, pg_catalog, public;
Run Code Online (Sandbox Code Playgroud)
然后您的调用首先找到您的自定义覆盖函数:
SELECT inet_client_addr();
Run Code Online (Sandbox Code Playgroud)
确保非特权用户不能在 override
模式中,否则他们可以对你玩各种把戏。默认情况下并非如此。根据文档:
默认情况下,未向 PUBLIC 授予对表、列、模式的任何权限或表空间的。
大胆强调我的。
如果允许同一用户在数据库中创建对象,则需要小心。
根据文档:
搜索路径中命名的第一个模式称为当前模式。除了作为搜索的第一个模式之外,如果
CREATE TABLE
命令未指定模式名称,它也是将在其中创建新表的模式。
始终为CREATE
命令指定模式名称,并在默认情况下禁止所有对象创建以排除错误。
归档时间: |
|
查看次数: |
689 次 |
最近记录: |