* * * *

Privacy Policy

Blog italiano

Clicca qui se vuoi andare al blog italiano su Lazarus e il pascal.

Forum ufficiale

Se non siete riusciti a reperire l'informazione che cercavate nei nostri articoli o sul nostro forum vi consiglio di visitare il
Forum ufficiale di Lazarus in lingua inglese.

Lazarus 1.0

Trascinare un file nel programma
DB concetti fondamentali e ZeosLib
Recuperare codice HTML da pagina web
Mandare mail con Lazarus
Stabilire il sistema operativo
Esempio lista in pascal
File INI
Codice di attivazione
Realizzare programmi multilingua
Lavorare con le directory
Utilizzare Unità esterne
TTreeView
TTreeview e Menu
Generare controlli RUN-TIME
LazReport, PDF ed immagini
Intercettare tasti premuti
Ampliare Lazarus
Lazarus e la crittografia
System Tray con Lazarus
UIB: Unified Interbase
Il file: questo sconosciuto
Conferma di chiusura di un applicazione
Liste e puntatori
Overload di funzioni
Funzioni a parametri variabili
Proprietà
Conversione numerica
TImage su Form e Panel
Indy gestiore server FTP lato Client
PopUpMenu sotto Pulsante (TSpeedButton)
Direttiva $macro
Toolbar
Evidenziare voci TreeView
Visualizzare un file Html esterno
StatusBar - aggirare l'errore variabile duplicata
Da DataSource a Excel
Le permutazioni
Brute force
Indy 10 - Invio email con allegati
La gestione degli errori in Lazarus
Pascal Script
Linux + Zeos + Firebird
Dataset virtuale
Overload di operatori
Lavorare con file in formato JSON con Lazarus
Zeos ... dietro le quinte (prima parte)
Disporre le finestre in un blocco unico (come Delphi)
Aspetto retrò (Cmd Line)
Lazarus 1.0
Come interfacciare periferica twain
Ubuntu - aggiornare free pascal e lazarus
fpcup: installazioni parallele di lazarus e fpc
Free Pascal e Lazarus sul Raspberry Pi
Cifratura: breve guida all'uso dell'algoritmo BlowFish con lazarus e free pascal.
Creare un server multithread
guida all'installazione di fpc trunk da subversion in linux gentoo
Indice
DB concetti fondamentali e connessioni standard
Advanced Record Syntax
DB concetti fondamentali e DBGrid
DB concetti fondamentali e TDBEdit, TDBMemo e TDBText
Advanced Record Syntax: un esempio pratico
Superclasse form base per programmi gestionali (e non)
Superclasse form base per programmi gestionali (e non) #2 - log, exception call stack, application toolbox
Superclasse form base per programmi gestionali (e non) #3 - traduzione delle form
Superclasse form base per programmi gestionali (e non) #4 - wait animation
Un dialog per la connessione al database:TfmSimpleDbConnectionDialog
Installare lazarus su mac osx sierra
immagine docker per lavorare con lazarus e free pascal
TDD o Test-Driven Development
Benvenuto! Effettua l'accesso oppure registrati.
Aprile 19, 2024, 04:20:05 pm

Inserisci il nome utente, la password e la durata della sessione.

385 Visitatori, 1 Utente

Autore Topic: Log  (Letto 1367 volte)

cappe

  • Newbie
  • *
  • Post: 28
  • Karma: +0/-0
Log
« il: Gennaio 03, 2023, 10:30:19 am »
Dovrei fare un log delle modifiche fatte ai database dagli utenti, secondo voi è meglio scriverlo a livello di trigger o di codice pascal. Qualche idea su come o qualche spunto?
Sono orientato di scriverlo in Pascal, ma ci sto pensando ...

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2870
  • Karma: +20/-4
Re:Log
« Risposta #1 il: Gennaio 03, 2023, 11:26:00 am »
ciao
per farlo a livello di trigger dovresti avere gli utenti che accedono al DB ognuno col loro codice (intendo la connessione al DB)

in uno scenario dove l'applicazione si connette al DB sempre con lo stesso utente e poi l'utente è gestito dall'applicazione è meglio  farlo da codice pascal
Imagination is more important than knowledge (A.Einstein)

Stilgar

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2382
  • Karma: +10/-0
Re:Log
« Risposta #2 il: Gennaio 03, 2023, 02:06:03 pm »
Ciao Cappe.

La risposta, come spesso capita in informatica, non è univoca.
Dipende dallo scenario che ti interessa (tanto per cambiare).

Se a te non serve salvare l'utente che opera la modifica, potrebbe essere il trigger che opera la storicizzazione del record modificato, una storicizzazione acefale, per capirsi.
Se devi mettere in piedi una sorta di audit, forse l'utente che opera la modifica ti serve e quindi le strategie devono cambiare (come suggerito da nomore potrebbe non essere lo stesso utente di connessione al db)
Se il DB che utilizzi permette di mettere in sessione dei valori custom, il trigger potrebbe essere ancora una strada praticabile: carici il nome dell'utente che modifica in sessione e il trigger lo legge.

Se a te serve una soluzione che non sia legata mani e piedi ad un engine specifico, la strada dell'applicazione esterna che gestisce l'utenza (come parametro nell'insert, per banalizzare l'operazione) sicuramente è più "portabile" tra i vari engine. Essendo 2 operazioni di modifica (storicizzazione + update) ricordati che devi gestire la transazione.
Storicizzare un record che poi si schianta nella modifica potrebbe portare a delle difficoltà e casini nel caso in cui l'ufficio audit volesse un report delle modifiche.

Spero di averti dato qualche spunto di riflessione.

Stilgar
« Ultima modifica: Gennaio 03, 2023, 05:14:13 pm da Stilgar »
Al mondo ci sono 10 tipi di persone ... chi capisce il binario e chi no.

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1266
  • Karma: +43/-0
  • Prima ascoltare, poi decidere
Re:Log
« Risposta #3 il: Gennaio 03, 2023, 04:20:44 pm »
Eseguire un Audit delle transazioni di un DB non è cosa semplice. Alcuni DB, anzi dire molti DB, dovrebbero già avere internamente la funzionalità richiesta (tra cui FIREBIRD e MSSQL se non vado errato).

SQLite invece presenta i normali Trigger che possono essere usati per fare creare un log. Però ti leghi specificatamente allo stato del DB e se fai variazioni delle tabelle ad esempio tramite update del tuo applicativo (cosa che ad esempio io faccio) bisogna ricordarsi di aggiornare anche i trigger con delle DDL.

Eseguendo tu a livello di codice i post, commit, etc ... io lo farei con gli eventi propri del componente (ZEOS ad esempio) tipo AfterPOST, AfterCommit, ......

Più flessibile ....

Ciao
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2870
  • Karma: +20/-4
Re:Log
« Risposta #4 il: Gennaio 03, 2023, 04:36:12 pm »
cmq su vuoi passare per i trigger, ti dico come ho fatto io in qualche occasione

  • se possibile, nelle tabelle da "loggare", aggiungi una colonna dove memorizzi l'utente (dell'applicazione) che ha effettuato la modifica e/o l'inserimento
  • creati una stored procedure apposita per inserire i log  (questo ti faciliterà il porting e la manutenzione), così puoi fare il log sia da trigger che da codice pascal
  • nei trigger metti il richiamo alla stored procedure di cui sopra, mantieni il trigger più semplice possibile
  • nella stored procedure, metti l'utente come parametro e leggilo dal campo aggiunto sopra
  • ti rimane fuori l'eliminazione: nel trigger "before update" non c'è un campo utente in quanto il record viene eliminato (quindi non sai chi ha eliminato il record)... ma a questo puoi ovviare richiamando la stored procedure dall'applicazione pascal...
Imagination is more important than knowledge (A.Einstein)

cappe

  • Newbie
  • *
  • Post: 28
  • Karma: +0/-0
Re:Log
« Risposta #5 il: Gennaio 03, 2023, 04:49:01 pm »
Il DB è firebird. Grazie per il suggerimento.

Penso di farlo in pascal, Dovrei fare un log delle  modifiche degli utenti. Ma ci sto ancora pensando.
A me serve una cosa semplice.
Tabelle transazione e modifiche. Ci provo.

P.S. Non avevo visto l'altro post sui log anche se sembra essere diverso il contesto,


Stilgar

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2382
  • Karma: +10/-0
Re:Log
« Risposta #6 il: Gennaio 03, 2023, 05:33:58 pm »
Allora si può ragione su FB.


https://firebirdsql.org/file/documentation/html/en/refdocs/fblangref30/firebird-30-language-reference.html#fblangref30-ddl-trigger


Utilizzando 2 funzioni FB puoi "personalizzare" la sessione di lavoro dell'utente.
Codice: [Seleziona]

SELECT RDB$SET_CONTEXT ('USER_SESSION', 'OS_USER','UTENTE OS') FROM RDB$DATABASE;
Codice: [Seleziona]
SELECT RDB$GET_CONTEXT ('USER_SESSION', 'OS_USER') FROM RDB$DATABASE;


In questo modo puoi customizzare le sessioni e lavorare con i trigger, generalizzare le tue query (da pascal), adattare la "stored procedure" senza dover sempre pescare l'utente dal sistema operativo.


(Salvi e riusi in altre parole)


Stilgar


Al mondo ci sono 10 tipi di persone ... chi capisce il binario e chi no.

Stilgar

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2382
  • Karma: +10/-0
Re:Log
« Risposta #7 il: Gennaio 03, 2023, 06:20:51 pm »
Per migliorare il suggerimento di nomore.
Se duplichi la struttura che devi mettere sotto audit, e aggiungi la colonna utente + operazione, puoi utilizzare 3 valori (quindi aggiungi anche il tipo di manipolazione del record che viene operato).
0=Insert
1=Update
2=Delete
(o una cosa similie).
Così puoi tracciare anche le cancellazioni, oltre che le versioni del record con tutte le modifiche operate sulla singola riga.


Poi, se aggiungi la data inizio validità e fine validità, puoi tenere traccia anche quando è stato modificato il record sotto audit.


Quindi la logica dovrebbe essere:
1) Chiudere la validità del record storicizzato precedente, con il codice di modifica che hai utilizzato + utente, se presente (l'update può lavorare anche se il record no è presente, senza far scattare errori)
Codice: [Seleziona]
update {tabella}_storico set data_validita_fine = CURRENT_TIMESTAMP, mod_code={codice_modifica} where data_validita_fine  is null
una cosa del tipo
2) Modificare/Inserire/Eliminare il record d'interesse.


3) Copiare il record attuale in quello storico

Codice: [Seleziona]
insert {tabella}_storico select *, CURRENT_TIMESTAMP, null, null from {tabella}


Le query sono di esempio, non so se funzionano così come le ho messe (non maledirmi)


Stilgar

Stilgar.
Al mondo ci sono 10 tipi di persone ... chi capisce il binario e chi no.

cappe

  • Newbie
  • *
  • Post: 28
  • Karma: +0/-0
Re:Log
« Risposta #8 il: Gennaio 03, 2023, 06:35:22 pm »
Ok. Domani provo a farlo.

cappe

  • Newbie
  • *
  • Post: 28
  • Karma: +0/-0
Re:Log
« Risposta #9 il: Gennaio 04, 2023, 11:32:06 am »
Per migliorare il suggerimento di nomore.
Se duplichi la struttura che devi mettere sotto audit, e aggiungi la colonna utente + operazione, puoi utilizzare 3 valori (quindi aggiungi anche il tipo di manipolazione del record che viene operato).
0=Insert
1=Update
2=Delete
(o una cosa similie).
Così puoi tracciare anche le cancellazioni, oltre che le versioni del record con tutte le modifiche operate sulla singola riga.
Poi, se aggiungi la data inizio validità e fine validità, puoi tenere traccia anche quando è stato modificato il record sotto audit.

Quindi la logica dovrebbe essere:
1) Chiudere la validità del record storicizzato precedente, con il codice di modifica che hai utilizzato + utente, se presente (l'update può lavorare anche se il record no è presente, senza far scattare errori)
Codice: [Seleziona]
update {tabella}_storico set data_validita_fine = CURRENT_TIMESTAMP, mod_code={codice_modifica} where data_validita_fine  is null
una cosa del tipo
2) Modificare/Inserire/Eliminare il record d'interesse.


3) Copiare il record attuale in quello storico

Codice: [Seleziona]
insert {tabella}_storico select *, CURRENT_TIMESTAMP, null, null from {tabella}


Le query sono di esempio, non so se funzionano così come le ho messe (non maledirmi)


Stilgar

Stilgar.

Grazie.
Fatto e funziona. La cosa interessante è che hai la fotografia della tabella, però come contro ricopia ogni volta tutti i dati. La cosa carina è che è semplice e sembra funzionare e molto probabilmente lo utilizzerò.

Ora provo con solo le modifiche.
« Ultima modifica: Gennaio 04, 2023, 11:56:19 am da cappe »

Stilgar

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2382
  • Karma: +10/-0
Re:Log
« Risposta #10 il: Gennaio 04, 2023, 02:17:06 pm »
Son contento che l'idea ti piaccia.
Tieni conto che ho preso l'approccio più ignorante (o agnostico se vogliamo parlare erudito) possibile.


Un problema di questo approccio è lo spazio.
Ricordati di mettere gli indici anche sulle date validità. Altrimenti con il tempo cercare nello storico diventa un massacro a livello di tempi.


Per le ottimizzazioni del db cedo il passo a Nomore che ha più esperienza di me.


Stilgar.
Al mondo ci sono 10 tipi di persone ... chi capisce il binario e chi no.

cappe

  • Newbie
  • *
  • Post: 28
  • Karma: +0/-0
Re:Log
« Risposta #11 il: Gennaio 04, 2023, 02:49:06 pm »
ad ogni modo, grazie e una buona idea

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2870
  • Karma: +20/-4
Re:Log
« Risposta #12 il: Gennaio 04, 2023, 03:30:32 pm »
per ora farei una riflessione sulla PK della tabella dello storico

se storicizziamo ad esempio un cliente, questo comparirà N volte nella tabella storico_clienti
per questo se impostiamo la PK come chiave composta con i campi:
  • codice cliente
  • data inizio validità (potrebbe essere "fine_validità" poi uno ragiona come vuole)

avremo il doppio vantaggio di (1) avere la possibilità di memorizzare N volte lo stesso cliente con la data di validità come discriminante e (2) una PK è anche un indice....

resta da capire come fare se la storicizzazione viene lanciata più volte  per lo stesso cliente nello stesso giorno
però la soluzione è semplice: basta che la data di validità sia un timestamp


Imagination is more important than knowledge (A.Einstein)

Stilgar

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2382
  • Karma: +10/-0
Re:Log
« Risposta #13 il: Gennaio 04, 2023, 03:50:57 pm »
Infatti nelle query suggerite ho messo current_timestamp().
Solo DATE mi ha creato grosse rogne in passato nella storicizzazione con operazioni parallele.


Stilgar.




Al mondo ci sono 10 tipi di persone ... chi capisce il binario e chi no.

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2870
  • Karma: +20/-4
Re:Log
« Risposta #14 il: Gennaio 04, 2023, 04:20:41 pm »
ops... a forza di parlare di "data" avevo dimenticato lo script  ::)
Imagination is more important than knowledge (A.Einstein)

 

Recenti

How To

Utenti
  • Utenti in totale: 785
  • Latest: gmax
Stats
  • Post in totale: 18772
  • Topic in totale: 2233
  • Online Today: 578
  • Online Ever: 900
  • (Gennaio 21, 2020, 08:17:49 pm)
Utenti Online
Users: 1
Guests: 385
Total: 386

Disclaimer:

Questo blog non rappresenta una testata giornalistica poiché viene aggiornato senza alcuna periodicità. Non può pertanto considerarsi un prodotto editoriale ai sensi della legge n. 62/2001.