Here is the working code (for Debian users: just install the postgresql-pltcl-8.4 package and run 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();
However, I cannot get placeholders in the prepared message (it returns 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:
As a workaround, use the OLD entry (represented as an array in Tcl), enter the identifier column there, and use the replace function, replace $1 instead. Here you have two solutions: PL / pgSQL and 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;
Result:
java -classpath '.:postgresql-8.4-702.jdbc4.jar' DeleteUsingPreparedStmt TABLE log_table; id | query ----+--------------------------------- 1 | delete from floors where id = 1
(1 line)
source share