Как установить имя пользователя для триггера аудита Postgresql? - PullRequest
1 голос
/ 14 июля 2009

Я использую триггер в PostgreSQL 8.2 для аудита изменений в таблице:

CREATE OR REPLACE FUNCTION update_issue_history() RETURNS trigger as $trig$
BEGIN
        INSERT INTO issue_history (username, issueid)
               VALUES ('fixed-username', OLD.issueid);
        RETURN NULL;
END;
$trig$ LANGUAGE plpgsql;

CREATE TRIGGER update_issue_history_trigger
AFTER UPDATE ON issue
      FOR EACH ROW EXECUTE PROCEDURE update_issue_history();

То, что я хочу сделать, - это каким-то образом предоставить значение fixed-username во время выполнения обновления. Это возможно? Если да, то как мне это сделать?

Ответы [ 2 ]

0 голосов
/ 02 октября 2012

Я не вижу другого способа сделать это, кроме как создать временные таблицы и использовать EXECUTE в вашем триггере. Это будет иметь последствия для производительности, хотя. Лучшим вариантом может быть привязка к другой таблице где-нибудь и вход в систему, кто выполняет вход / выход по идентификатору сеанса и внутреннему PID, и ссылается на это?

Обратите внимание, у вас нет другого способа получить информацию в операторе обновления. Имейте в виду, что триггер может видеть только то, что доступно в API или в базе данных. Если вы хотите, чтобы триггер работал прозрачно, вы не можете ожидать передачи ему во время выполнения информации, к которой у него не было бы доступа в противном случае.

Основной вопрос, который вам нужно задать, это "Как БД узнает, что там поставить?" Как только вы определитесь с методом, ответ должен быть прямым, но бесплатных обедов нет.

Обновление

В прошлом, когда мне приходилось делать что-то подобное, когда вход в БД осуществлялся с ролью приложения, я делал это, создавая временную таблицу, а затем обращался к ней из хранимых процедур. В настоящее время хранимые процедуры могут обрабатывать временные таблицы таким образом, но в прошлом нам приходилось использовать EXECUTE.

У этого подхода есть два огромных ограничения. Во-первых, он создает много таблиц, и это в конечном итоге приводит к возможности обхода oid.

В наши дни я предпочитаю, чтобы логины в БД были логинами пользователей. Это значительно упрощает управление, и вы можете просто получить доступ через значение SESSION_USER (ошибка новичка заключается в использовании CURRENT_USER, который показывает текущий контекст безопасности, а не логин пользователя.

Ни один из этих подходов не работает хорошо с пулами соединений. В первом случае вы не можете выполнять пул соединений, потому что ваши временные таблицы будут неправильно истолкованы или засорены. Во-вторых, вы не можете сделать это, потому что роли входа в систему разные.

0 голосов
/ 14 июля 2009

Попробуйте что-то вроде этого:

CREATE OR REPLACE FUNCTION update_issue_history() 
RETURNS trigger as $trig$
DECLARE
      arg_username varchar;
BEGIN
      arg_username := TG_ARGV[0];
      INSERT INTO issue_history (username, issueid)
             VALUES (arg_username, OLD.issueid);
      RETURN NULL;
END;
$trig$ LANGUAGE plpgsql;

CREATE TRIGGER update_issue_history_trigger
AFTER UPDATE ON issue
      FOR EACH ROW EXECUTE PROCEDURE update_issue_history('my username value');
...