Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / record implode / 6 сообщений из 6, страница 1 из 1
04.10.2005, 07:26
    #33302648
Erlan
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
record implode
Есть в триггере запись OLD.
как покрасивше превратить ее в строку?
например:

Дано:
OLD.id=1
OLD.name='Вася'
OLD.drunk=true

На выходе:
str = 'id=1;name=Вася;drunk=true';
либо просто
str = '1;Вася;true';
...
Рейтинг: 0 / 0
04.10.2005, 10:08
    #33302898
Andrey Daeron
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
record implode
ErlanЕсть в триггере запись OLD.
как покрасивше превратить ее в строку?
например:

Дано:
OLD.id=1
OLD.name='Вася'
OLD.drunk=true

На выходе:
str = 'id=1;name=Вася;drunk=true';
либо просто
str = '1;Вася;true';
Наверно интерисует более красивый вариант чем "ручками"?
Код: plaintext
1.
 str:=old.id||';'||old.name||';'||old.drunk;
...
Рейтинг: 0 / 0
04.10.2005, 11:51
    #33303239
Erlan
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
record implode
Не только.
Что если количество полей и их названия неизвестны?
...
Рейтинг: 0 / 0
04.10.2005, 13:38
    #33303665
domanix
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
record implode
Вот тебе тест - из которого нагладно видно что и как
PG8.03

--===========
CREATE TABLE test(ID SMALLINT,history_records TEXT);
--===========
CREATE OR REPLACE FUNCTION TEST_TRIG ()
RETURNS trigger AS $body$
BEGIN
/*неявный каст из типа рекорд в текст*/
new.history_records=OLD;
return new;
END; $body$ LANGUAGE 'plpgsql';
--=============
CREATE TRIGGER test_tr BEFORE UPDATE ON test
FOR EACH ROW EXECUTE PROCEDURE TEST_TRIG();
--=============
...
Рейтинг: 0 / 0
12.10.2005, 09:29
    #33318888
glebofff
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
record implode
domanixВот тебе тест - из которого нагладно видно что и как
PG8.03

--===========
CREATE TABLE test(ID SMALLINT,history_records TEXT);
--===========
CREATE OR REPLACE FUNCTION TEST_TRIG ()
RETURNS trigger AS $body$
BEGIN
/*неявный каст из типа рекорд в текст*/
new.history_records=OLD;
return new;
END; $body$ LANGUAGE 'plpgsql';
--=============
CREATE TRIGGER test_tr BEFORE UPDATE ON test
FOR EACH ROW EXECUTE PROCEDURE TEST_TRIG();
--=============

Ну да, тип RECORD можно привести к TEXT. И получим мы строку вида "(value,value,...,value)". А имена полей - как извлечь? Кажется, в pl/pgsql это не-ре-аль-но, я, по крайней мере, не нашёл. :-) Но их возможно извлечь в других процедурных языках, pl/perl, pl/tcl:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
CREATE TABLE "public"."tcl_test" (
  "first" INTEGER, 
  "second" INTEGER, 
  "third" INTEGER
) WITHOUT OIDS;

CREATE OR REPLACE FUNCTION "public"."testttt" () RETURNS trigger AS
$body$
foreach {nm val} [array get NEW] {
  elog NOTICE "$nm=$val";
}
return OK;
$body$
LANGUAGE 'pltcl';

CREATE TRIGGER "tcl_test_tr" BEFORE INSERT 
ON "public"."tcl_test" FOR EACH ROW  EXECUTE PROCEDURE "public"."testttt"();

Не знаю, что там у tcl с производительностью, он у меня почту отправляет (и только), но на некритичных табличках можно, думаю, задействовать. Например, для "маршрутизации" данных в соответствующие классы-потомки, если заведомо неизвестно количество полей (т.е., возможны NULL-значения).
...
Рейтинг: 0 / 0
15.10.2005, 07:57
    #33326311
фффф
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
record implode
2 glebofff: в TCL судя по документации $NEW и $OLD поля идут в алфавитном порядке?
В pl/perl тоже ключи хеша $_TD->{new} не упорядочены, значит чтобы получить порядок столбцов как в родной таблице, нужно лезть в pg_attibute - это на каждую изменяемую строку будет накладно. Плюс, для вставки в таблицу строки её нужно дополнительно обрабатывать - кавычки, бэкслеши... Короче тормозить будет.

Если ещё актуально, вот такая функция получилась, на перле:
Код: 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.
create table anytable_log (
  ts      timestamp not null default now(),
  relname text not null,
  action  char( 1 ) not null check (action in ('I', 'U', 'D')),
  tvalues text
);

CREATE OR REPLACE FUNCTION anytable_log_trigfn() RETURNS trigger AS $_$
#  use Data::Dumper; elog INFO, Dumper($_TD);
  my $tuple = 'new';
  $tuple = 'old' if $_TD->{event} eq 'DELETE';
  my @val;
  for my $f (sort keys %{$_TD->{$tuple}}) { #поля в алфавитном порядке!
    my $v = $_TD->{$tuple}->{$f};
    if (defined $v) {
      $v =~ s{'}{''''}g; #'
      $v =~ s{\\}{\\\\\\\\}g;
      push @val, "$f=''$v''";
    } else {
      push @val, "$f=NULL";
    }
  }
  my $q = sprintf("INSERT INTO anytable_log (relname, action, tvalues) VALUES ('%s', '%s', '%s')",
    $_TD->{relname}, substr($_TD->{event}, 0 , 1 ), join(',', @val));
#  elog INFO, $q;
  spi_exec_query($q);

  return;
$_$ LANGUAGE plperl VOLATILE;
Применять для логирования больших рабочих таблиц смысла нет, а вот для мелких вспомогательных - для которых лень параллельные таблицы аудита создавать - пойдет.
...
Рейтинг: 0 / 0
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / record implode / 6 сообщений из 6, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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