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

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

На выходе:
str = 'id=1;name=Вася;drunk=true';
либо просто
str = '1;Вася;true';
...
Рейтинг: 0 / 0
record implode
    #33302898
Andrey Daeron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
record implode
    #33303239
Erlan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Не только.
Что если количество полей и их названия неизвестны?
...
Рейтинг: 0 / 0
record implode
    #33303665
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();
--=============
...
Рейтинг: 0 / 0
record implode
    #33318888
glebofff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
record implode
    #33326311
фффф
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
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
6 сообщений из 6, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / record implode
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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