0

您好我正在使用 postgresql 8.1.22,我正在尝试使用以下函数设置 postgresql 审计。

CREATE OR REPLACE FUNCTION audit.if_modified_func() RETURNS TRIGGER AS $body$
DECLARE
    v_old_data TEXT;
    v_new_data TEXT;
BEGIN
    /*  If this actually for real auditing (where you need to log EVERY action),
        then you would need to use something like dblink or plperl that could log outside the transaction,
        regardless of whether the transaction committed or rolled back.
    */

    /* This dance with casting the NEW and OLD values to a ROW is not necessary in pg 9.0+ */

    IF (TG_OP = 'UPDATE') THEN
        v_old_data := ROW(OLD.*);
        v_new_data := ROW(NEW.*);
        INSERT INTO audit.logged_actions (schema_name,table_name,user_name,action,original_data,new_data,query) 
        VALUES (TG_TABLE_SCHEMA::TEXT,TG_TABLE_NAME::TEXT,session_user::TEXT,substring(TG_OP,1,1),v_old_data,v_new_data, current_query());
        RETURN NEW;
    ELSIF (TG_OP = 'DELETE') THEN
        v_old_data := ROW(OLD.*);
        INSERT INTO audit.logged_actions (schema_name,table_name,user_name,action,original_data,query)
        VALUES (TG_TABLE_SCHEMA::TEXT,TG_TABLE_NAME::TEXT,session_user::TEXT,substring(TG_OP,1,1),v_old_data, current_query());
        RETURN OLD;
    ELSIF (TG_OP = 'INSERT') THEN
        v_new_data := ROW(NEW.*);
        INSERT INTO audit.logged_actions (schema_name,table_name,user_name,action,new_data,query)
        VALUES (TG_TABLE_SCHEMA::TEXT,TG_TABLE_NAME::TEXT,session_user::TEXT,substring(TG_OP,1,1),v_new_data, current_query());
        RETURN NEW;
    ELSE
        RAISE WARNING '[AUDIT.IF_MODIFIED_FUNC] - Other action occurred: %, at %',TG_OP,now();
        RETURN NULL;
    END IF;

EXCEPTION
    WHEN data_exception THEN
        RAISE WARNING '[AUDIT.IF_MODIFIED_FUNC] - UDF ERROR [DATA EXCEPTION] - SQLSTATE: %, SQLERRM: %',SQLSTATE,SQLERRM;
        RETURN NULL;
    WHEN unique_violation THEN
        RAISE WARNING '[AUDIT.IF_MODIFIED_FUNC] - UDF ERROR [UNIQUE] - SQLSTATE: %, SQLERRM: %',SQLSTATE,SQLERRM;
        RETURN NULL;
    WHEN OTHERS THEN
        RAISE WARNING '[AUDIT.IF_MODIFIED_FUNC] - UDF ERROR [OTHER] - SQLSTATE: %, SQLERRM: %',SQLSTATE,SQLERRM;
        RETURN NULL;
END;
$body$
LANGUAGE plpgsql
SECURITY DEFINER

但是,如果您在上述函数中观察到 current_query() 并没有附带提到的语言 plpgsql。它会引发一些错误。当我用谷歌搜索时,我发现为了使用 current_query() 函数,必须安装 PL/CTL 语言。我尝试如下安装。它抛出一个错误。所以请帮助我如何将 PL/CTL 语言安装到我的数据库中,以便 current_query() 函数可以工作

-bash-3.2$ createlang -d dbname pltcl
createlang: language installation failed: ERROR:  could not access file "$libdir/pltcl": No such file or directory

好的,正如你建议的那样,我创建了 current_query() 函数,但是这次我得到了这样的东西,我所做的是,

CREATE TABLE phonebook(phone VARCHAR(32), firstname VARCHAR(32), lastname VARCHAR(32), address VARCHAR(64));


CREATE TRIGGER phonebook_auditt AFTER INSERT OR UPDATE OR DELETE ON phonebook 
    FOR EACH ROW EXECUTE PROCEDURE audit.if_modified_func();



INSERT INTO phonebook(phone, firstname, lastname, address) VALUES('9966888200', 'John', 'Doe', 'North America'); 

为了测试该功能,我创建了一个名为 phonebook 的表并创建了一个触发器,以便在任何插入或更新或删除之后执行上述功能 audit.if_modified_func()。该行被插入但我收到一个错误注册审计.if_modified_func()函数。错误如下

WARNING:  [AUDIT.IF_MODIFIED_FUNC] - UDF ERROR [OTHER] - SQLSTATE: 42703, SQLERRM: column "*" not found in data type phonebook

Query returned successfully: 1 rows affected, 10 ms execution time.

请告诉我我该怎么做才能摆脱上述错误。

4

1 回答 1

1

不确定您在哪里找到有关 current_query 和 pltcl 的信息。这些是无关的。您找不到 pltcl 的原因仅仅是因为您使用的是太旧的 PostgreSQL。current_query() 已在 8.4 版中添加到 Pg 中。

您使用这么旧的版本有什么特别的原因吗?它不再受支持,并且缺少将近 8 年的新增功能!

如果您必须使用 8.1,您可能需要定义:

create function current_query() returns text as '
select current_query from pg_stat_activity where procpid = pg_backend_pid();
' language sql;

但最好只是升级。

至于编辑和添加的第二个问题 - Pg 8.1 很可能不能使用“row.*”构造。用“舞蹈评论”找到谁写的原始代码,并询问它。也许它是为了在较新的 Pgs 中工作。

于 2013-07-03T10:26:23.863 回答