Pg_trigger_depth () è male da usare per prevenire il trigger a cascata (ricorsione)?


8

Perché è pg_trigger_depth() = 0male usare (per qualsiasi cosa diversa dal debug) quando si impedisce il trigger a cascata (ricorsione)?

Qualcuno può fornire il codice per dimostrare perché è male?

Immagino perché se più trigger funzionano contemporaneamente sugli stessi dati, una condizione che interrompe l'utilizzo di un trigger pg_trigger_depth() = 0interromperà qualsiasi trigger che è il secondo in linea per funzionare.

Ho pensato che sarebbe stata una buona soluzione a questa (mia) domanda qui, ma mi è stato detto diversamente:

Ho pensato che sarebbe stata una buona domanda.

Viene offerto qui come soluzione:

Documentazione di Postgres 9.3:

https://www.postgresql.org/docs/9.3/static/functions-info.html

Risposte:


1

Sì, è sempre male rendere dipendente il comportamento pg_trigger_depth()

Forse sono un po 'meno contrario alle affermazioni generali, ma a che serve? Non vi è alcun argomento che posso vedere sul motivo per cui si vorrebbe una tale funzione. Lo scopo principale di un database è garantire l'integrità dei dati. E per quanto posso vedere, e potrei sbagliarmi, un tale uso è sempre una potenziale violazione dell'integrità dei dati. Nella risposta di @ Erwin dice "se dimentichi" . Il punto di garantire l'integrità è eliminare questa possibilità. Se un agente riesce a ricordare tutto e a comprendere le conseguenze e il codice che lo circonda, puoi ottenere l'integrità dei dati da qualsiasi cosa .

Introduciamo alcuni termini, nella programmazione, abbiamo

  • "stato" che include tutto ciò a cui un programmatore ha accesso.
  • "contesto di esecuzione" che include l'ambiente per l'esecuzione.

Abbiamo inoltre un termine per una funzione, che non ha uno stato che chiamiamo funzione pura ,

La funzione valuta sempre lo stesso valore di risultato dati gli stessi valori di argomento. Il valore del risultato della funzione non può dipendere da alcuna informazione o stato nascosto che può cambiare mentre procede l'esecuzione del programma o tra diverse esecuzioni del programma, né può dipendere da alcun input esterno dai dispositivi I / O (di solito, vedere di seguito).

La distinzione per purezza è utile perché elimina qualsiasi onere di ricordare qualcosa per conto del computer o del programmatore: f(x) = yè sempre vero. Qui stai violando la purezza nel punto peggiore: il database. E lo stai facendo in modo complesso e soggetto a errori - rendendo il contesto di esecuzione interno una cosa palpabile nello stato della tua applicazione DB.

Non lo vorrei. Considera solo le complessità che devi tamponare mentalmente.

  • Table A's Trigger Aincendi
    • Trigger Arilascia sempre DML a Table B, sparando Trigger B.
      • Trigger Brilascia condizionalmente DML a Table A, sparando Trigger A.
      • Trigger Brilascia sempre DML a Table A, sparando Trigger A.
    • Trigger Arilascia condizionalmente DML a Table B, sparando Trigger B.
      • Trigger Brilascia condizionalmente DML a Table A, sparando Trigger A.
      • Trigger Brilascia sempre DML a Table A, sparando Trigger A.

Se questo sembra complesso, tieni presente che "condizionatamente" può essere ulteriormente esteso a "è successo, ma potrebbe non accadere sempre" e "non è successo, ma può accadere altrove".

Per pg_trigger_depth()essere utile, devi avere una serie di eventi allo stesso modo complessi. E, ora, vuoi che l'esecuzione dipenda dal contenuto dell'esecuzione in quella catena?

Lo eviterei. Se il tuo sistema di innesco è così complesso, stai giocando a patate calde con una bomba a mano in un armadio tutto da solo e non sembra che finisca bene.


10

E ' non è male usare per sé (IMHO). Devi solo essere consapevole delle implicazioni.

Preferirei farlo pg_trigger_depth() < 1invece di pg_trigger_depth() = 0, in linea di principio, ma non è importante qui. Stiamo parlando di trigger come:

CREATE TRIGGER my_trigger
AFTER INSERT ON my_tbl
FOR EACH ROW
WHEN (pg_trigger_depth() < 1)
EXECUTE PROCEDURE my_trigger_func();

Se successivamente si aggiungono trigger che a loro volta attivano il trigger, non accadrà nulla. Il trigger reagisce solo agli eventi non trigger. A seconda della tua configurazione, questo potrebbe essere esattamente quello che vuoi - o tipo di trappola, se ti dimentichi di questo e in seguito aggiungi altri trigger che dovrebbero a loro volta (anche) attivare questo trigger. Stai cambiando il comportamento predefinito. Assicurati di documentarlo chiaramente.

Tenere presente che pg_trigger_depth()conta qualsiasi trigger , non solo lo stesso trigger per impedire la ricorsione, quindi la condizione impedisce al trigger di attivarsi se chiamato anche da qualsiasi altro trigger.
Il manuale:

livello di annidamento corrente dei trigger PostgreSQL (0 se non chiamato, direttamente o indirettamente, dall'interno di un trigger)

Relazionato:

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.