Willino Blog

Sono un ingegnere informatico, appassionato di fotografia, chitarra acustica, micologia e Tennis Tavolo. In questo blog cercherò di raccontare eventi ed esperienze che in qualche modo potrebbero risultare utili a tutti.

martedì 21 aprile 2009

Esecuzione di comandi WSQL

Questa guida di riferimento è indirizzata agli sviluppatori WY

L'esecuzione di un comando SQL/WSQL compilato con il metodo discusso nella Guida di riferimento per la creazione di comandi SQL da codice Delphi, come da esempio seguente :

• Esempio Object Pascal
SqlCMD.BuildSQL('Descrizione comando sql');
Compilazione del comando SQL/WSQL

La richiesta di esecuzione del comando può avvenire in due metodi differenti. Il primo metodo di esecuzione non ritorna un cursore al comando ed è adatto per comando DML (manipolazione dei dati) e DDL (definizione dello schema), mentre il secondo metodo ritorna un cursore alle righe restituite dall'esecuzione del comando. questo fa comprendere che il metodo di esecuzione va scelto a priori in funzione del comando. Vedremo per primo il metodo di esecuzione che non ritorna cursori, come in questo caso :

• Esempio Object Pascal
  1.With WYDM, WYDM.SQLServices Do
2.Begin
3. TransactionStart;
4. Try
5. ExecuteSQL(SqlCMD.BuildSQL('Descrizione'), stWithSQL);
6. TransactionCommit;
7. Except
8. TransactionRollBack;
9. End;
10.End;
Esecuzione di un comando SQL/WSQL che non ritorna cursori (utile per INSERT,UPDATE,DELETE)

Il metodo che esegue il comando è ExecuteSQL appartenente a WYDM, il modulo dati dell'applicazione. In ingresso questo metodo si aspetta il comando SQL compilato (restituito da BuildSQL) e la modalità di gestione del comando che può essere :

  1. stWithSQL, per comandi DML
  2. stWithPSQL, per comandi DDL

Vediamo ora il caso più completo che, invece, esegue il comando ritornando un cursore molto semplice e potente da utilizzare.

• Esempio Object Pascal
  1.Var
2. lRow : TWYDataset;
3.Begin
4. lRow := WYDM.CreateFetchableDataset;
5. Try
6. With WYDM, WYDM.SQLServices Do
7. Begin
8. SqlCMD.Clear;
9. SqlCMD.Sql.Add('SELECT * FROM WY_ALIAS');
10. SqlCMD.Sql.Add(' WHERE IDALIAS=?1?');
11. SqlCMD.AV(aAlias);
12. If ExecuteSQL(SqlCMD.BuildSql('Recupero Alias'),'IDALIAS', lRow, flMultiTone) <> '' Then
13. Begin
14. While FetchRow(lRow, flMultiTone) Do
15. Begin
16. lRow.Row.FieldByName('TIPOLOGIA_ALIAS').AsInteger;
17. End;
18. End;
19. End;
20. Finally
21. WYDM.FreeFetchableDataset(lRow);
22. End;
23.End;
Esecuzione di un comando SQL/WSQL che ritorna un cursore al dataset (utile per SELECT)

Esaminiamo il codice.

Le righe da 8 a 11 dovrebbero ormai essere chiare, mentre sono di nostro interesse le righe 4,12,14,16 e 21.

La riga 4 inizializza il cursore lRow e lo predispone per ricevere il dataset. Uno dei punti forti di WY è la gestione completamente offline dei dataset pertanto, una volta eseguito il nostro comando, il cursore lRow conterrà il dataset in memoria e le risorse per l'esecuzione del comando SQL/WSQL saranno già tutte rilasciate. Vedremo quindi più avanti tutte le caratteristiche del cursore TWYDataset.

La riga 12 esegue il comando. Il metodo si aspetta il comando SQL compilato, il nome di una colonna chiave, il cursore e la modalita di gestione del cursore stesso. Concentriamoci sull'ultimo parametro, che può assumere due valori :

  1. flSingleTone
  2. flMultiTone

Nel primo caso ci si aspetta il ritorno di una sola riga (quindi per le query singletone), mentre nel secondo ci si aspetta un dataset. A prescindere dalle righe ritornate, il cursore lRow punterà alla prima riga del dataset in memoria.

Ciò che ora ci interessa è accedere ai valori della riga corrente nel dataset, e poter scorrere il dataset stesso.

L'accesso ai dati della riga corrente avviene come in un qualsiasi dataset derivato da TDataset che, nel nostro cursore, è puntato dall'attributo Row del cursore lRow, come descritto nella riga 16 dell'esempio precedente e qui di seguito generalizzato :

• Esempio Object Pascal
lRow.Row.FieldByName('COLONNA_INTERO').AsInteger;
Lettura di un valore di una riga del cursore

Per scorrere invece il dataset in memoria tramite il cursore consideriamo la riga 14 dell'esempio precedente, qui generalizzato :

• Esempio Object Pascal
While FetchRow(lRow, flMultiTone) Do
Ciclo di fetch per il cursore ottenuto dall'esecuzione del comando

Non è necessario aprire o chiudere i cursori lRow in quanto sarà compito dell'oggetto WYDM gestire il flusso. La differenza con l'approccio classico di gestione dei dataset sta proprio nel fatto che l'apertura e la chiusura, i controlli di esistenza e altro vengono svolti dall'oggetto WYDM in modo trasparente.

La riga 21 dell'esempio precedente rilascia le risorse di memoria allocate dal cursore lRow.

E' infine possibile eseguire il comando per leggere il valore di una sola colonna in una query singletone con il seguente metodo :

• Esempio Object Pascal
lString:=ExecuteSQL(SqlCMD.BuildSql('Descrizione'), 'NOME_COLONNA');
Esecuzione di un comando SQL/WSQL per leggere il valore di una sola colonna

domenica 19 aprile 2009

Preparazione di comandi WSQL

Questa guida di riferimento è indirizzata agli sviluppatori WY

Il modeler

WY dispone di un oggetto SQLCMD, attributo dell'oggetto WYDM (il modulo dati base per le applicazioni WY) progettato per la creazione di comandi SQL e WSQL.

La struttura essenziale della classe TWYSQLModeler (SQLCMD ne è un'istanza) è la seguente.

• Esempio Object Pascal
  1.  TWYSQLModeler = Class Sealed(TWYObject)
2. Public
3. SQL : TStringList;
4. Procedure Clear;
5. Function FAV(Const aValue : Variant;
6. AddQuotes : Boolean = True): TWYSQLModeler;
7. Function AV (Const aValue : Variant;
8. AddQuotes : Boolean = True): Boolean;
9. Function AN : Boolean;
10. Function AC (Const aCondition : String;
11. ConditionType : TConditionType;
12. DoItOnlyIf : Boolean) : Boolean;
13. Function BuildSQL (aOwner : String = '';
14. AutoClear : Boolean = False): String;
15. End;
Dichiarazione interfaccia TWSQLModeler

Della dichiarazione di cui sopra presteremo particolare attenzione all'oggetto SQL della riga 3, ai metodi FAV,AV,AC,AN e BuildSQL.

Per meglio comprendere l'utilizzo dell'oggetto, è bene proseguire con la descrizione del processo di creazione.


  1. Scrittura del comando tramite l'oggetto SQL;

  2. Definizione delle condizioni variabili;

  3. Passaggio dei parametri variabili;

  4. Compilazione del comando.

Scrittura del comando SQL/WSQL

La scrittura del comando è eseguita mediante l'oggetto SQL di SQLCMD.


• Esempio Object Pascal
  1.  // ...    
2. With WYDM.SqlServices, WYDM Do
3. Begin
4. SqlCMD.Clear;
5. SqlCMD.Sql.Add('SELECT * FROM TABELLA WHERE ...');
6. // ...
7. End;
Immissione del comando SQL da codice tramite la libreria WY

Definizione delle condizioni variabili

Le condizioni variabili aggiungono condizioni al comando SQL/WSQL in modo dinamico.


• Esempio Object Pascal
SqlCmd.AC('COLONNA1=?1?', ctAND, Condizione1);
Inserimento di una condizione variabile

La riga di questo esempio segue la scritta del comando, ovvero va inserita dopo la riga 6 dell'esempio precedente.

Il parametro in cui è inserito come esempio il valore 'COLONNA1=?1?' dovrà contenere la condizione da passare al comando.

Il parametro ctAND specifica che questa condizione va agginuta al comando con AND.

Il parametro Condizione1 è, infine, lo statement delphi che se vero cosentirà di aggiungere la condizione al comando.


• Esempio Object Pascal
SqlCmd.AC('TIPOLOGIA_ALIAS<>1',ctAND,(cb_AliasCheck.Checked = True));
Condizione variabile dipendente da un controllo della finestra attiva dell'applicazione

In questo esempio al comando viene aggiunta in AND la condizione TIPOLOGIA_ALIAS<>1 solo se il checkbox cb_AliasCheck ha la proprietà checked=true. La condizione dinamica prevede che il comaando SQL abbia al suo interno inserita una richiesta di condizione dinamica del tipo @n@.


Definizione dei parametri variabili

I parametri variabili aggiungono parametri al comando SQL/WSQL in modo dinamico.


• Esempio Object Pascal
  1.SqlCmd.AV(WYAM.GlobalManager.GlobalID);
2.SqlCmd.AV(Valore1);
3.SqlCMD.AN;
Passaggio di tre parametri variabili ad un comando SQL

In questo esempio alle righe 1 e 2 vengono passati due parametri di applicazione, sia globali (WYAM.GlobalManager.GlobalID) che locali (IDTabella). Alla riga 3, invece, viene passato NULL.I tre parametri passati in questo esempio prevedono che il comando SQL abbia al suo interno inserite 3 richieste di valori dinamici del tipo ?n?,ovvero che la corrispondente Query sia così composta :/p>

• Esempio SQL/WSQL
  1.SELECT A.ID_AZIENZA, A.DENOMINAZIONE_AZIENZA
2. FROM APP_AZIENDE A
3. WHERE A.ID_AZIENDA=?1? AND A,CODICE_FISCALE=?2? AND
4. COALESCE(A.AZIENDA_CHIUSA,?3?);
Comando WSQL con 3 richieste di parametri variabili

Un altro metodo per passare i valori ai parametri variabili è quello del Fluent Interfaces, ovvero :


• Esempio Object Pascal
SqlCmd.FAV(Valore1).FAV(Valore2).FAV(Valore3);
Utilizzo dei Fluent Interfaces per il passaggio di parametri variabili al comando

Vediamo ora un esempio di codice completo per la scrittura del comando.


• Esempio Object Pascal
  1.  With WYDM.SqlServices, WYDM Do
2. Begin
3. SqlCmd.Clear;
4. SqlCmd.Sql.Add('SELECT *');
5. SqlCmd.Sql.Add('FROM ');
6. SqlCmd.Sql.Add(' APP_AZIENDE A');
7. SqlCmd.Sql.Add('WHERE A.IDAZIENZA=?1? @1@');
8. SqlCmd.AC('A.DENOMINAZIONE_AZIENDA=?2?', ctAND, Condizione1);
9. SqlCmd.AV(WYAM.GlobalManager.GlobalID);
10. SqlCmd.AV(ValoreColonna2);
11. //...
12. End;
Comando WSQL integrato nel codice

Facciamo ora un esempio più chiaro e complesso in cui con una interogazione in WSQL vogliamo conoscere quali utenti sono stati attivati dopo una certa data. Per eseguire questo comando dobbiamo accertarci che l'utente connesso abbia i permessi di amministratore, altrimenti mostreremo solamente i dati relativi all'operatore connesso.


• Esempio Object Pascal
  1.Var
2. lData : TDateTime;
3.Begin
4. lData:=StrToDateTimeDef('01/01/2008',Date);
5. With WYDM,WYDM.SQLServices Do
6. Begin
7. SqlCMD.Clear;
8. SqlCMD.Sql.Add('SELECT');
9. SqlCMD.Sql.Add(' IDOPERATORE,NOMINATIVO_OPERATORE,');
10. SqlCMD.Sql.Add(' DATA_ATTIVAZIONE');
11. SqlCMD.Sql.Add('FROM');
12. SqlCMD.Sql.Add(' WY_OPERATORI O');
13. SqlCMD.Sql.Add('WHERE');
14. SqlCMD.Sql.Add(' O.IDAPPLICATIVO=?1? AND');
15. SqlCMD.Sql.Add(' O.DATA_ATTIVAZIONE>=?2?');
16. SqlCMD.Sql.Add(' @3@');
17. SqlCMD.AC('O.IDOPERATORE=?3?',ctAND,(Not WYAM.AppUserAdmin));
18. SqlCMD.AV(WYAM.ApplicationID);
19. SqlCMD.AV(lData);
20. SqlCMD.AV(WYAM.AppUserID);
21. SQLCMD.BuildSQL('Operatori nuovi');
22. End;
23.End;
Esempio completo di scrittura comando SQL/WSQL, inserimento di condizioni dinamiche e passaggio di parametri variabili

In questo esempio, la verifica della proprietà WYAM.AppUserAdmin è determinante per l'aggiunta della condizione variabile. Condizione che viene aggiunta (vincolando quindi a mostrare la sola riga dell'operatore connesso) solo se l'utente non è amministratore. E' importante prestare attenzione al fatto che l'ordine di aggiunta dei parametri variabili è strettamente connesso al numero di richiesta di valore dinamico ?n?. Questo significa che il valore lData deve essere aggiunto in seconda posizione, avendo nel comando SQL numero di richiesta pari a ?2?. Notare che il metodo AV ha per parametro in ingresso un Variant e pertanto, oltre al vantaggio di una semplice gestione dei dati passati ai comandi, viene semplificata anche la procedura di conversione dati per il DB.


Compilazione del comando

La compilazione del comando genera un comando SQL completo di parametri e condizioni.


• Esempio Object Pascal
SqlCMD.BuildSQL('Descrizione comando sql');
Compilazione del comando e preparazione all'esecuzione

Siamo ora pronti ad eseguire il comando.

ANSA.it - Top News