powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Триггер. Что я делаю не так?
6 сообщений из 6, страница 1 из 1
Триггер. Что я делаю не так?
    #34415350
olden69
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
С Постгри работаю недавно. Помогите, плиз, с триггером. Вроде бы все правильно написано, но не срабатывает. И запись, обрабатываемую, не вставляет, хотя определен как AFTER INSERT.
Может я просто по незнанию какому, что называется - "гляжу в книгу - вижу фигу"? Может нельзя в Постгри в триггере одной таблицы делать вставку в другую таблицу?

есть две таблицы:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
CREATE TABLE acc
(
  sip_from character varying( 128 ) NOT NULL DEFAULT ''::character varying,
  sip_to character varying( 128 ) NOT NULL DEFAULT ''::character varying,
  sip_status character varying( 128 ) NOT NULL DEFAULT ''::character varying,
  sip_method character varying( 16 ) NOT NULL DEFAULT ''::character varying,
  i_uri character varying( 128 ) NOT NULL DEFAULT ''::character varying,
  o_uri character varying( 128 ) NOT NULL DEFAULT ''::character varying,
  from_uri character varying( 128 ) NOT NULL DEFAULT ''::character varying,
  to_uri character varying( 128 ) NOT NULL DEFAULT ''::character varying,
  sip_callid character varying( 128 ) NOT NULL DEFAULT ''::character varying,
  username character varying( 64 ) NOT NULL DEFAULT ''::character varying,
  "domain" character varying( 128 ) NOT NULL DEFAULT ''::character varying,
  fromtag character varying( 128 ) NOT NULL DEFAULT ''::character varying,
  totag character varying( 128 ) NOT NULL DEFAULT ''::character varying,
  "time" timestamp without time zone NOT NULL DEFAULT '1900-01-01 00:00:01'::timestamp without time zone,
  "timestamp" timestamp without time zone NOT NULL DEFAULT now(),
  src_leg character varying( 128 ),
  dst_leg character varying( 128 )
) 
WITH OIDS;
ALTER TABLE acc OWNER TO postgres;
GRANT ALL ON TABLE acc TO postgres WITH GRANT OPTION;
GRANT ALL ON TABLE acc TO public;

и
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
CREATE TABLE cdr
(
  id serial NOT NULL,
  call_id character varying( 128 ),
  account_id integer,
  user_name character varying( 64 ),
  time_begin timestamp without time zone,
  time_end timestamp without time zone,
  uri_from character varying( 128 ),
  uri_to character varying( 128 ),
  duration integer NOT NULL DEFAULT  0 ,
  CONSTRAINT pk_cdr PRIMARY KEY (id)
) 
WITHOUT OIDS;
ALTER TABLE cdr OWNER TO postgres;
GRANT ALL ON TABLE cdr TO postgres WITH GRANT OPTION;
GRANT ALL ON TABLE cdr TO public;

первой таблице создаю триггер
Код: plaintext
1.
2.
3.
4.
5.
CREATE TRIGGER acc_insert
  AFTER INSERT
  ON acc
  FOR EACH ROW
  EXECUTE PROCEDURE acc_insert();

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
CREATE OR REPLACE FUNCTION acc_insert()
  RETURNS "trigger" AS
'
DECLARE
  _time_begin timestamp without time zone;
  _duration integer;
  _duration_raw interval;
  _account_id integer;

BEGIN

  IF NEW.sip_method = ''ACK'' THEN 
    
    SELECT account_id INTO _account_id FROM subscriber WHERE phone = _user_name;

    INSERT INTO cdr (call_id, account_id, user_name, time_begin, uri_from, uri_to)
      VALUES(NEW.sip_callid, _account_id, NEW.username, NEW."timestamp", NEW.from_uri, NEW.to_uri);

  ELSIF NEW.sip_method = ''BYE'' THEN

    SELECT "timestamp" INTO _time_begin FROM acc WHERE sip_callid = NEW.sip_callid AND NEW.sip_method = ''ACK'';

    _duration_raw := NEW."timestamp" - _time_begin;

    _duration := ( (EXTRACT(day FROM _duration_raw) * 24 + EXTRACT(hour FROM _duration_raw)) * 3600 + 
                   EXTRACT(minute FROM _duration_raw) * 60 + EXTRACT(second FROM _duration_raw) )::integer;
    
    UPDATE cdr SET time_end = NEW."timestamp", duration = _duration WHERE call_id = NEW.sip_callid;

  END IF;


  RETURN NULL;
END;
'
  LANGUAGE 'plpgsql' VOLATILE;

в итоге запись с полем sip_method = 'ACK' вообще не появляется в таблице acc
и в таблицу cdr ничего не вставляется.
А вот запись с полем sip_method = 'BYE' в acc появляется.
Но как проверить? С типом вставляемых полей роде бы никаких конфликтов.
Вообще, любая работа по другим таблицам (SELECT, INSERT, etc.) в ветке обработки условия sip_method = 'ACK' приводит к отмене вставки этой записи в таблицу acc даже если эти таблицы ВСЕ позволяют public .

Что не так? Ткните носом.
...
Рейтинг: 0 / 0
Триггер. Что я делаю не так?
    #34415363
olden69
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
сорри
Код: plaintext
 PostgreSQL 7.4.11 on i386-redhat-linux-gnu, compiled by GCC i386-redhat-linux-gcc (GCC) 3.4.4 20050721 (Red Hat 3.4.4-2) 
...
Рейтинг: 0 / 0
Триггер. Что я делаю не так?
    #34415464
Serik Akhmetov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Выполните запросы вручную, откуда берутся значения первичного ключа ?
Все ли ограничения выполняются ? Похоже срабатывает какой-то exception, и вся транзакция откатывается.
...
Рейтинг: 0 / 0
Триггер. Что я делаю не так?
    #34415789
olden69
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
да вручную я все это делал
оформил работу с другими таблицами отдельной функцией и передавал ей call_id
все проходило успешно при вызове вручную с консоли
но вызов той функции из триггерной функции (передавая ей NEW.sip_callid) заканчивался крахом

Тут видимо какая-то тонкость работы с полями вставляемой записи внутри триггерной функции.
Кстати там у меня небольшая ошибка,
Код: plaintext
SELECT account_id::integer INTO _account_id FROM subscriber WHERE phone = NEW.username;
но результат тот же и после ее исправления

вот лог сеанса
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
LOG:  statement: BEGIN

LOG:  statement: insert into acc
 (from_uri,to_uri,sip_method,i_uri,o_uri,sip_from,sip_callid,sip_to,sip_status,username,totag,fromtag,domain,time ) values
 ('from','to','ACK','from','to','7ICq4MHV7RveL2Hy','jaYickbldqKulTkw','as173b545b','200','00004','as173b545b','7ICq4MHV7RveL2Hy',
 'domain','2007-03-26 10:14:10')

LOG:  statement: SELECT  ( $ 1   = 'ACK')
CONTEXT:  PL/pgSQL function "acc_insert" line  12  at if
LOG:  statement: SELECT  account_id::integer FROM subscriber WHERE phone = $ 1 
CONTEXT:  PL/pgSQL function "acc_insert" line  14  at select into variables
LOG:  statement: ROLLBACK


LOG:  statement: BEGIN
LOG:  statement: insert into acc
 (from_uri,to_uri,sip_method,i_uri,o_uri,sip_from,sip_callid,sip_to,sip_status,username,totag,fromtag,domain,time ) values
 ('from','to','BYE','from','to','7ICq4MHV7RveL2Hy','jaYickbldqKulTkw','as173b545b','200','00004','as173b545b','7ICq4MHV7RveL2Hy',
 'domain','2007-03-26 10:14:14')

LOG:  statement: SELECT  ( $ 1   = 'BYE')

CONTEXT:  PL/pgSQL function "acc_insert" line  22  at if
LOG:  statement: SELECT  "timestamp" FROM acc WHERE sip_callid =  $ 1   AND  $ 2   = 'ACK'

CONTEXT:  PL/pgSQL function "acc_insert" line  24  at select into variables
LOG:  statement: SELECT   $ 1   -  $ 2 

CONTEXT:  PL/pgSQL function "acc_insert" line  26  at assignment
LOG:  statement: SELECT  ( (EXTRACT(day FROM  $ 1  ) *  24  + EXTRACT(hour FROM  $ 2  )) *  3600  + EXTRACT(minute FROM  $ 3  ) *  60  +
 EXTRACT(second FROM  $ 4  ) )::integer
 
CONTEXT:  PL/pgSQL function "acc_insert" line  28  at assignment
LOG:  statement: UPDATE cdr SET time_end =  $ 1  , duration =  $ 2   WHERE call_id =  $ 3 

CONTEXT:  PL/pgSQL function "acc_insert" line  31  at SQL statement
LOG:  statement: COMMIT

Явно видно, что после селекта транзакция откатилась. НО ПОЧЕМУ?
Смущают эти алиасы полей ($1 $2 $3), которые используются с совершенно разными полями вставляемой записи.

Где-то я недопонимаю работу Постгри...
...
Рейтинг: 0 / 0
Триггер. Что я делаю не так?
    #34416120
olden69
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
все, в какой-то мере разобрался
включил на сервере более подробный лог и обнаружил отсутствие прав на генератор (sequence) для сериального поля в таблице cdr .
Осталось непонятным почему даже при закомментированном инсерте, только при селекте по другой таблице транзакция все равно откатывалась, но уже все работает.
Отнесу пока сие "божественное воскрешение" к разряду "ЧУДО". :)
...
Рейтинг: 0 / 0
Триггер. Что я делаю не так?
    #34423625
Funny_Falcon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
SELECT account_id INTO _account_id FROM subscriber WHERE phone = _user_name;
А что такое _user_name? Оно нигде не объявляется и в логе выглядит как $1:
Код: plaintext
1.
2.
LOG:  statement: SELECT  account_id::integer FROM subscriber WHERE phone = $ 1 
CONTEXT:  PL/pgSQL function "acc_insert" line  14  at select into variables
LOG:  statement: ROLLBACK
...
Рейтинг: 0 / 0
6 сообщений из 6, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Триггер. Что я делаю не так?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]