Trigger PostgreSQL для общего обрезания полей записи INSERT / UPDATE - PullRequest
0 голосов
/ 17 октября 2019

Я пытаюсь обрезать общие записи INSERT / UPDATE для каждой таблицы в БД, чтобы удалить любые пробелы до и после каждого текстового значения (т. Е. Изменить «значение» на «значение»).

Я взялвзгляните на Общий триггер обрезки строк для Postgresql , но это работает только на записях INSERT, поскольку ARGV существует только во время этого события.

Я подумал, что нужно конвертировать NEW в jsonb,что теперь я предполагаю, что имеет вид {"key1": "value1", "key2": "value2"}, но я не знаю, как циклически проходить по его полям, чтобы обрезать его значения.

Iпланирую использовать

SELECT 
    column_name
FROM
    information_schema.columns
WHERE
    table_name = TG_TABLE_NAME AND table_schema = TG_TABLE_SCHEMA AND (data_type = 'text' OR data_type = 'character varying' )

, чтобы получить только «ключ1» (столбцы), имеющий строку типа, поэтому сценарий выглядит как

CREATE OR REPLACE FUNCTION a_trigger() RETURNS trigger AS $trim_trigger$ 
DECLARE
    j jsonb = to_jsonb(NEW);
    current_column text;
BEGIN
    FOR current_column IN 
      SELECT 
        column_name
      FROM
        information_schema.columns
      WHERE
        table_name = TG_TABLE_NAME AND table_schema = TG_TABLE_SCHEMA AND (data_type = 'text' OR data_type = 'character varying' )
    LOOP
      IF j ->> current_column IS NOT NULL THEN
        j = jsonb_set(j, j ->> current_column, to_jsonb(regexp_replace(j ->> current_column, '^\s*|\s*$', '', 'g')),false);
      END IF;
    END LOOP;

    NEW = jsonb_populate_record(NEW, j);
    RETURN NEW;
END;
$trim_trigger$ LANGUAGE plpgsql;

У меня проблемыиспользуя jsonb_set;его подпись "jsonb, text [], jsonb, bool", но j - >> current_column - текст, и, возможно, я не до конца понял параметр 'path'.

Что мне здесь не хватает?


В конце концов я справился с

j = jsonb_set(j, concat('{',current_column,'}')::text[], to_jsonb(regexp_replace(j ->> current_column, '^\s*|\s*$', '', 'g')),false);

(я добавил приведение к тексту [])

Но мне это кажется немного грязным

1 Ответ

0 голосов
/ 18 октября 2019

Ваше утверждение "работает только с записями INSERT, поскольку ARGV существует только во время этого события" - false . TG_ARGV [] существует для всех инициируемых событий, включая события вставки, обновления, удаления и даже усечения и другие. Смотрите следующую демонстрацию:

create or replace function argv_test_trigger_function()
 returns trigger
 language plpgsql
 as $$
 declare 
     l_action_msg text;
 begin 
     case tg_op 
          when 'INSERT' then l_action_msg = 'Adding '   || new.description;
          when 'DELETE' then l_action_msg = 'Removing ' || old.description;
          when 'UPDATE' then l_action_msg = 'Updating ' || old.description || ' to ' || new.description;
          else l_action_msg = 'Trunacting???';
     end case;  

     raise notice E'Trigger % fired on % of %, with % parameters value(S) %\n ... Taking action %',
                  tg_name, tg_op, tg_table_name, tg_nargs::text, tg_argv::text,l_action_msg;

     if tg_op = 'DELETE' 
     then 
         return old;
     else 
         return new;
     end if; 
end ; 
$$; 

drop table if exists argv_test cascade;
create table argv_test (id serial, description text);  

drop trigger if exists argv_test_bir on argv_test; 
create trigger argv_test_bir
       before insert on argv_test
       for each row execute procedure  argv_test_trigger_function('adding row.' );  

drop trigger if exists argv_test_bur on argv_test; 
create trigger argv_test_bur
       before update on argv_test
       for each row execute procedure  argv_test_trigger_function('Updating row.' );    

drop trigger if exists argv_test_bdr on argv_test;        
create trigger argv_test_bdr
       before delete on argv_test
       for each row execute procedure  argv_test_trigger_function('Deleting row.', 'That'' All folks');  



insert into argv_test(description) values( 'Initial insert'); 
update argv_test set description = description || ', and now it''s updated';
delete from argv_test;
...