BUG #11283: PostgreSQL bug? function's variable type cached not flushed within session when the type altered.
От | digoal@126.com |
---|---|
Тема | BUG #11283: PostgreSQL bug? function's variable type cached not flushed within session when the type altered. |
Дата | |
Msg-id | 20140828083929.2534.84054@wrigleys.postgresql.org обсуждение исходный текст |
Список | pgsql-bugs |
The following bug has been logged on the website: Bug reference: 11283 Logged by: digoal Email address: digoal@126.com PostgreSQL version: 9.3.4 Operating system: CentOS 6.5 x64 Description: PostgreSQL bug? function's variable type cached not flushed within session when the type altered. see my test : create table public.t ( c1 int primary key, c2 text, crt_time timestamp ); CREATE TABLE public.undo_t ( id serial8 primary key, xid int8, relid oid, table_schema text, table_name text, when_tg text, level text, op text, encoding name, old_rec public.t, new_rec public.t, crt_time timestamp without time zone DEFAULT now(), username text, client_addr inet, client_port int ); CREATE OR REPLACE FUNCTION public.undo_t_trace() RETURNS trigger LANGUAGE plpgsql AS $BODY$ DECLARE v_new_rec public.t; -- type cached in session, don't modified when table t altered. must reopen an session. v_old_rec public.t; -- type cached in session, don't modified when table t altered. must reopen an session. v_username text := session_user; v_client_addr inet := inet_client_addr(); v_client_port int := inet_client_port(); v_xid bigint := txid_current(); v_encoding name := pg_client_encoding(); BEGIN case TG_OP when 'DELETE' then v_old_rec := OLD; insert into public.undo_t (xid, relid, table_schema, table_name, when_tg, level, op, encoding, old_rec, username, client_addr, client_port) values (v_xid, tg_relid, tg_table_schema, tg_table_name, tg_when, tg_level, tg_op, v_encoding, v_old_rec, v_username, v_client_addr, v_client_port); when 'INSERT' then raise notice '%', NEW; -- OK v_new_rec := NEW; raise notice '%', v_new_rec; -- use cached type. not OK. insert into public.undo_t (xid, relid, table_schema, table_name, when_tg, level, op, encoding, new_rec, username, client_addr, client_port) values (v_xid, tg_relid, tg_table_schema, tg_table_name, tg_when, tg_level, tg_op, v_encoding, v_new_rec, v_username, v_client_addr, v_client_port); when 'UPDATE' then v_old_rec := OLD; v_new_rec := NEW; insert into public.undo_t (xid, relid, table_schema, table_name, when_tg, level, op, encoding, old_rec, new_rec, username, client_addr, client_port) values (v_xid, tg_relid, tg_table_schema, tg_table_name, tg_when, tg_level, tg_op, v_encoding, v_old_rec, v_new_rec, v_username, v_client_addr, v_client_port); when 'TRUNCATE' then insert into public.undo_t (xid, relid, table_schema, table_name, when_tg, level, op, encoding, old_rec, username, client_addr, client_port) select v_xid, tg_relid, tg_table_schema, tg_table_name, tg_when, tg_level, tg_op, v_encoding, t, v_username, v_client_addr, v_client_port from public.t; else return null; end case; RETURN null; END; $BODY$ strict volatile; CREATE TRIGGER tg1 AFTER DELETE or INSERT or UPDATE ON public.t FOR EACH ROW EXECUTE PROCEDURE undo_t_trace(); CREATE TRIGGER tg2 BEFORE TRUNCATE ON public.t FOR EACH STATEMENT EXECUTE PROCEDURE undo_t_trace(); insert into public.t values (1,'test',now()); insert into public.t values (2,'test',now()); postgres=# select * from public.t; c1 | c2 | crt_time ----+------+---------------------------- 1 | test | 2014-08-28 16:14:34.548555 2 | test | 2014-08-28 16:14:35.194634 (2 rows) postgres=# select new_rec from public.undo_t; new_rec --------------------------------------- (1,test,"2014-08-28 16:14:34.548555") (2,test,"2014-08-28 16:14:35.194634") (2 rows) postgres=# alter table public.t add column c3 int; ALTER TABLE postgres=# insert into public.t values (3,'test',now(),1); NOTICE: (3,test,"2014-08-28 16:15:58.394688",1) NOTICE: (3,test,"2014-08-28 16:15:58.394688",) INSERT 0 1 postgres=# select * from public.t; c1 | c2 | crt_time | c3 ----+------+----------------------------+---- 1 | test | 2014-08-28 16:14:34.548555 | 2 | test | 2014-08-28 16:14:35.194634 | 3 | test | 2014-08-28 16:15:58.394688 | 1 (3 rows) postgres=# select new_rec from public.undo_t; new_rec ---------------------------------------- (1,test,"2014-08-28 16:14:34.548555",) (2,test,"2014-08-28 16:14:35.194634",) (3,test,"2014-08-28 16:15:58.394688",) (3 rows) postgres=# \q postgres@192_168_173_203-> psql psql (9.3.4) Type "help" for help. postgres=# select new_rec from public.undo_t; new_rec ---------------------------------------- (1,test,"2014-08-28 16:14:34.548555",) (2,test,"2014-08-28 16:14:35.194634",) (3,test,"2014-08-28 16:15:58.394688",) (3 rows) postgres=# insert into public.t values (4,'test',now(),1); NOTICE: (4,test,"2014-08-28 16:16:45.857712",1) NOTICE: (4,test,"2014-08-28 16:16:45.857712",1) INSERT 0 1 postgres=# select new_rec from public.undo_t; new_rec ----------------------------------------- (1,test,"2014-08-28 16:14:34.548555",) (2,test,"2014-08-28 16:14:35.194634",) (3,test,"2014-08-28 16:15:58.394688",) (4,test,"2014-08-28 16:16:45.857712",1) (4 rows) postgres=# alter table t drop column c2; ALTER TABLE postgres=# \set VERBOSITY verbose postgres=# insert into public.t values (5,now(),1); NOTICE: 00000: (5,"2014-08-28 16:17:20.078688",1) LOCATION: exec_stmt_raise, pl_exec.c:3041 ERROR: 22007: invalid input syntax for type timestamp: "1" CONTEXT: PL/pgSQL function undo_t_trace() line 18 at assignment LOCATION: DateTimeParseError, datetime.c:3567
В списке pgsql-bugs по дате отправления:
Предыдущее
От: Tom LaneДата:
Сообщение: Re: Error with citext extension when upgrading from 9.0.3 to 9.3.5: 'cannot cast type oid[] to oidvector'
Следующее
От: Tom LaneДата:
Сообщение: Re: Error with citext extension when upgrading from 9.0.3 to 9.3.5: 'cannot cast type oid[] to oidvector'