2008-11-20 18 views
19

Mam tego wyzwalacza w Postgresql, że nie mogę po prostu dostać się do pracy (nie robi nic). Aby zrozumieć, jak to zdefiniowałem:debugowanie wyzwalacza postgresql

CREATE TABLE documents (
    ... 
    modification_time timestamp with time zone DEFAULT now() 
); 

CREATE FUNCTION documents_update_mod_time() RETURNS trigger 
AS $$ 
    begin 
    new.modification_time := now(); 
    return new; 
    end 
$$ 
    LANGUAGE plpgsql; 

CREATE TRIGGER documents_modification_time 
    BEFORE INSERT OR UPDATE ON documents 
    FOR EACH ROW 
    EXECUTE PROCEDURE documents_update_mod_time(); 

Teraz, aby uczynić go bardziej interesującym ... Jak debugować wyzwalacze?

+0

To nie jest ściśle powiązane, ale można go znaleźć przydatne w swoich przygodach i tak pgsql: http://stackoverflow.com/questions/430123/how-do-i-enable-the-postgresql-function -profiler – Kev

Odpowiedz

41
  1. Użyj następujący kod wewnątrz funkcji wyzwalania, a następnie oglądać zakładkę „Wiadomości” w pgAdmin3 lub wyjście w psql:

    RAISE NOTICE 'myplpgsqlval is currently %', myplpgsqlval;  -- either this 
    RAISE EXCEPTION 'failed'; -- or that 
    
  2. aby zobaczyć, które wyzwala rzeczywiście sprawdzony, ile czasy itp, następujące stwierdzenie jest life-saver wyboru:

    EXPLAIN ANALYZE UPDATE table SET foo='bar'; -- shows the called triggers 
    

    Zauważ, że jeśli spust nie jest uzyskiwanie nazywa i użyć dziedziczenia może być th w momencie zdefiniowania wyzwalacza tylko w tabeli nadrzędnej, podczas gdy wyzwalacze nie są automatycznie dziedziczone przez tabele potomne.

  3. Aby przejść przez funkcję, można użyć debugera wbudowanego w pgAdmin3, która w systemie Windows jest domyślnie włączona; wszystko co musisz zrobić, to wykonać kod znajdujący się w ... \ 8.3 \ share \ contrib \ pldbgapi.sql przeciwko bazie jesteś diagnostycznych, uruchom pgAdmin3 prawym przyciskiem myszy swoją funkcję wyzwalania, hit „Ustaw Breakpoint”, a następnie wykonaj instrukcję, która spowodowałaby uruchomienie wyzwalacza, na przykład powyższą instrukcję UPDATE.

+0

Nie wiem, czy tak można to zrobić na innych platformach. Również wcześniej udostępniłbym trzecią metodę (jest to * naprawdę * pod ręką!), Ale odkryłem to tydzień po tym, jak pierwotnie opublikowano to pytanie. – Kev

+1

Próbowałem z Postgresem 9.2 i towarzyszącym mu pgAdmin. Nie ma menu Set Breakpoint w dowolnym miejscu, nawet po wykonaniu instrukcji wymienionych powyżej. Również plik znajduje się w ... \ 9.2 \ share \ extension \ pldbgapi-1.0.sql. System operacyjny: Windows Server 2008 – Dojo

3

Możesz użyć poleceń "powiadomienie o zwiększeniu" wewnątrz swojej funkcji wyzwalacza, aby je zdebugować. Aby debugowanie wyzwalacza nie było w ogóle wywoływane, to inna historia.

Jeśli dodasz wyjątek "podniesienia" w funkcji wyzwalacza, czy nadal możesz wstawiać/aktualizować?

Ponadto, jeśli test aktualizacji wystąpi w tej samej transakcji, co test wstawiania, teraz() będzie takie samo (ponieważ jest obliczane tylko raz dla każdej transakcji) i dlatego aktualizacja nie będzie działać. W takim przypadku wykonaj je w oddzielnych transakcjach lub jeśli jest to test jednostkowy i nie możesz tego zrobić, użyj funkcji clock_timestamp().

mam badanej jednostki, która zależy od pewnego czasu dzieje przez między transakcjami, więc na początku testów jednostkowych mam coś takiego:

ALTER TABLE documents 
    ALTER COLUMN modification_time SET DEFAULT clock_timestamp(); 

następnie w spuście, użyj „set MODIFICATION_TIME = default ".

Zwykle nie robi to dodatkowych obliczeń, ale podczas testu jednostkowego pozwala mi to na wstawianie wstawek z pg_sleep pomiędzy, aby symulować upływ czasu i faktycznie to ma odzwierciedlenie w danych.

+0

Dobra podpowiedź ... więc wygląda na to, że funkcja nie jest wywoływana .. jakikolwiek pomysł, dlaczego? –

+0

Czy masz uprawnienia do wykonywania dla funkcji wyzwalacza? – Kev

+0

Możesz chcieć w pełni zakwalifikować (poprzedzić nazwę schematu) nazwy różnych obiektów, aby być po bezpiecznej stronie. także prawdopodobnie mogło zabraknąć „Wstaw” część swojej definicji wyzwalacza, wartość domyślna dba o tej sprawie. –

2

Okazuje się, że używałem dziedziczenia w powyższym problemie i zapomniałem o nim wspomnieć. Teraz dla każdego, kto może uruchamiać się to za dobrze, oto kilka wskazówek debugowania:

użyć następującego kodu do debugowania, co spust robi:

RAISE NOTICE 'test';  -- either this 
RAISE EXCEPTION 'failed'; -- or that 

Aby zobaczyć, który wyzwala rzeczywiście się nazywa, ile razy itp, następujące stwierdzenie jest life-saver wyboru:

EXPLAIN ANALYZE UPDATE table SET foo='bar'; -- shows the called triggers 

Potem jest jedna rzecz, nie wiedziałem wcześniej: wyzwala tylko ogień podczas aktualizowania dokładną tabelę one zdefiniowane dalej. Jeśli korzystasz z dziedziczenia, MUSISZ zdefiniować je również na tabelach podrzędnych!

+0

należy cross-post, że smakołyk na http://www.postgresql.org/docs /8.3/interactive/ddl-inherit.html – Kev