Как получить значение параметра $ 1 из выполненного подготовленного оператора (внутри триггера с использованием current_query ()) - PullRequest
6 голосов
/ 18 августа 2011

В триггере я хочу посмотреть, какой SQL-запрос вызвал этот триггер.Я использовал current_query () функцию postgresql (8.4).

Все хорошо, но если триггер выполняется подготовленным оператором, я получаю заполнители ($ 1) вместо правильных значений.например (зарегистрированный запрос):

delete from some_table where id=$1

Есть ли способ получить / иметь эти значения / параметры?

Отредактировано (пример добавлен):

--table for saving query
create table log_table (
query text
)

--table for trigger
create table some_table (
id text
)
--function itself
CREATE FUNCTION save_query() RETURNS trigger AS $$
    switch $TG_op {
    DELETE {
            spi_exec "INSERT INTO log_table (query) VALUES (current_query())"
        }
    default {
            return OK
        }
    }
    return OK
$$ LANGUAGE pltcl;

Создание триггера:

create trigger test_trigger before delete on some_table for each row execute procedure save_query();

Подготовленный оператор выполняется из спящего режима.

Повторное редактирование (добавлена ​​часть Java)

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

public class DeleteUsingPreparedStmt {

    public static void main(String[] args) {
        try {
            String deleteString = "delete from floors where id = ? ";
            final int idToDelte = 1;

            Class.forName("org.postgresql.Driver");
            String url = "jdbc:postgresql://127.0.0.1:5432/YOUR_DATABASE";
            Connection conn = DriverManager.getConnection(url, "user", "password");

            PreparedStatement deleteStmt = conn.prepareStatement(deleteString);
            deleteStmt.setInt(1, idToDelte);
            deleteStmt.executeUpdate();
        } catch (Exception e) {
            //hide me :)
        }
    }
}

Вам нужен драйвер jdbc - нажмите .

1 Ответ

5 голосов
/ 18 августа 2011

Вот некоторый рабочий код (для пользователей Debian: просто установите postgresql-pltcl-8.4 пакет и запустите CREATE LANGUAGE pltcl;)

CREATE TABLE log_table (
    id serial,
    query text
);

CREATE TABLE floors (
    id serial,
    value text
);

INSERT INTO floors(value) VALUES ('aaa'), ('bbb');

CREATE OR REPLACE FUNCTION save_query() RETURNS trigger AS $$
    switch $TG_op {
        DELETE {
            spi_exec "INSERT INTO log_table (query) VALUES (current_query())"
        }
        default {
            return OK
        }
    }
    return OK
$$ LANGUAGE pltcl;

CREATE TRIGGER test_trigger
    BEFORE DELETE ON floors
    FOR EACH ROW
    EXECUTE PROCEDURE save_query();

Однако я не могу получить заполнители в подготовленном утверждении (возвращается EXECUTE deleteFromFloors(2);):

TABLE log_table;
 id | query 
----+-------
(0 rows)
DELETE FROM floors WHERE id = 1;
DELETE 1
TABLE log_table;
 id |              query               
----+----------------------------------
  1 | DELETE FROM floors WHERE id = 1;
(1 row)
PREPARE deleteFromFloors(integer) AS
    DELETE FROM floors WHERE id = $1;
PREPARE
EXECUTE deleteFromFloors(2);
DELETE 1
TABLE log_table;
 id |              query               
----+----------------------------------
  1 | DELETE FROM floors WHERE id = 1;
  2 | EXECUTE deleteFromFloors(2);
(2 rows)

EDIT:

В качестве обходного пути используйте запись OLD (представленную как массив в Tcl), извлеките оттуда столбец id и используйте функцию replace, чтобы поместить ее вместо $1. Здесь у вас есть два решения: PL / pgSQL и PL / Tcl:

CREATE OR REPLACE FUNCTION save_query() RETURNS TRIGGER AS $$
BEGIN
    INSERT INTO log_table (query)
        VALUES (replace(current_query(), '$1', OLD.id::text));
    RETURN OLD;
END;
$$ LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION save_query() RETURNS trigger AS $$
    switch $TG_op {
        DELETE {
            spi_exec "INSERT INTO log_table (query)
                VALUES (replace(current_query(), '\$1', '$OLD(id)'))"
        }
        default {
            return OK
        }
    }
    return OK
$$ LANGUAGE pltcl;

Результат:

java -classpath '.:postgresql-8.4-702.jdbc4.jar' DeleteUsingPreparedStmt

TABLE log_table;
 id |              query              
----+---------------------------------
  1 | delete from floors where id = 1

(1 строка)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...