sql:= 'SELECT movimgg.IdMovvgg AS FROM movimgg ORDER BY IdMovvgg DESC LIMIT 1';
Form1.ZQuery1.SQL.Text:= sql;
Form1.ZQuery1.Open;
Form1.ZQuery1.First;
movimggNumId:= StrToInt(Form1.ZQuery1.FieldByName('IdMovvgg').AsString);
sql:= 'SELECT IdPartGlob FROM partmovv ORDER BY IdPartGlob DESC LIMIT 1';
Form1.ZQuery1.SQL.Text:= sql;
Form1.ZQuery1.ExecSQL;
Form1.ZQuery1.First;
partmovNumId:= StrToInt(Form1.ZQuery1.FieldByName('IdPartGlob').AsString);
sql := 'SELECT IdPrestMom FROM prestmom ORDER BY IdPrestMom DESC LIMIT 1';
Form1.ZQuery1.SQL.Text := sql;
Form1.ZQuery1.ExecSQL;
Form1.ZQuery1.First;
prestmomNumId:= StrToInt(Form1.ZQuery1.FieldByName('IdPrestMom').AsString);
sql := 'SELECT IdResCasgg FROM restacassagg ORDER BY IdResCasgg DESC LIMIT 1';
Form1.ZQuery1.SQL.Text := sql;
Form1.ZQuery1.ExecSQL;
Form1.ZQuery1.First;
restaCassaNumId:= StrToInt(Form1.ZQuery1.FieldByName('IdResCasgg').AsString);
sql:= 'SELECT movimgg.IdMovvgg AS FROM movimgg ORDER BY IdMovvgg DESC LIMIT 1';
Form1.ZQuery1.SQL.Text:= sql;
Form1.ZQuery1.Open;
Form1.ZQuery1.First;
movimggNumId:= StrToInt(Form1.ZQuery1.FieldByName('IdMovvgg').AsString);
Form1.ZQuery1.Close;
sql:= 'SELECT IdPartGlob FROM partmovv ORDER BY IdPartGlob DESC LIMIT 1';
Form1.ZQuery1.SQL.Text:= sql;
Form1.ZQuery1.Open;
Form1.ZQuery1.First;
partmovNumId:= StrToInt(Form1.ZQuery1.FieldByName('IdPartGlob').AsString);
Form1.ZQuery1.Close;
sql := 'SELECT IdPrestMom FROM prestmom ORDER BY IdPrestMom DESC LIMIT 1';
Form1.ZQuery1.SQL.Text := sql;
Form1.ZQuery1.Open;
Form1.ZQuery1.First;
prestmomNumId:= StrToInt(Form1.ZQuery1.FieldByName('IdPrestMom').AsString);
Form1.ZQuery1.Close;
sql := 'SELECT IdResCasgg FROM restacassagg ORDER BY IdResCasgg DESC LIMIT 1';
Form1.ZQuery1.SQL.Text := sql;
Form1.ZQuery1.Open;
Form1.ZQuery1.First;
restaCassaNumId:= StrToInt(Form1.ZQuery1.FieldByName('IdResCasgg').AsString);
Form1.ZQuery1.Close;
Quando apri un recordset, per poterlo riutilizzare devi chiudere quello precedente.Non lo sapevo di certo, ma l'avevo immaginato. Secondo me, Gambas lavora meglio coi DB.
Poi EXECSQL si usa per eseguire una sql che non ritorna valori, se devi recuperare valori devi usare la open (e quindi la close di conseguenza).Questo non lo sapevo proprio. Grazie.
è interessante la necessità riguardante la validazione di una serie di "commit" di un insieme di transazioni singole.Molto appetibile questa tua indicazione, ma dove potrei trovare la spiegazione sull'argomento?
Varie scritture su varie tabelle sono molte volte necessarie per completare un sessione di aggiornamento.
Ma effettivamente c'è uno "strumento" che consente di effettuare un rollback di tutte le transazioni interessate nel caso qualcosa non vada a buon fine?
In tutti questi anni a me non è mai servito, o meglio non è mai successo alcunchè per cui fosse necessario effettuare un rollback, ma effettivamente se ci fosse lo implementerei sicuramente.Personalmente, non mi trovi d'accordo sull'aspettare che l'evento negativo si manifesti per gestirlo. Occorre, secondo me, prevederlo sin dalla progettazione ed inserirne il relativo codice, alfine di non doverci tornare sopra a distanza di tempo, dopo avere, magari, dimenticato la logica dei dettagli del codice scritto.
Molto appetibile questa tua indicazione, ma dove potrei trovare la spiegazione sull'argomento?Non lo sò, era la mia appunto una domanda rivolta alla community.
Personalmente, non mi trovi d'accordo sull'aspettare che l'evento negativo si manifesti per gestirlo. Occorre, secondo me, prevederlo sin dalla progettazione ed inserirne il relativo codice, alfine di non doverci tornare sopra a distanza di tempo, dopo avere, magari, dimenticato la logica dei dettagli del codice scritto.Assolutamente d'accordo con te. Per ovviare a ciò, in tutte gli eventi di scrittura (tipo beforepost), ho sempre "super controllato" tutti i dati. E in tutti questi anni non è mai successo niente sui database dei miei clienti. Certo l'interruzione di corrente è sempre in agguato, lo spegnimento inopportuno del PC (foss'anche un server) anche, come pure un blocco anomalo.
Type
IZConnection = interface [....] procedure Commit; procedure Rollback; procedure PrepareTransaction(const transactionid: string);
procedure CommitPrepared(const transactionid: string);
procedure RollbackPrepared(const transactionid: string); procedure Commit;
[....]
function Execute(const SQL: ZAnsiString): Boolean; overload;
Vedendo i frammenti di codice, mi verrebbe da suggerirti http://www.lazaruspascal.it/index.php?page=111 (http://www.lazaruspascal.it/index.php?page=111).Devo dire che non mi trovo con la terminologia ivi contenuta, perchè non vi sono abituato, Non capisco infatti quando dici:
Per "accendere" il motore di ZEOS Low Level, basta una semplice chiamata:La riga "var Connection: IZConnection;" dovrebbe corrispondere alla " ZConnection1: TZConnection;" contenuta nella sezione Interface del mio programma:
var Connection : IZConnection;
..
Connection := DriverManager.GetConnection(connectionURL);
interface
uses
Classes, SysUtils, DB, Forms, Controls, Graphics, Dialogs, StdCtrls, ComCtrls,
ExtCtrls, fpspreadsheet, laz_fpspreadsheet, Process, ZConnection, ZDataset, utilmie,
fpstypes; // , flcDynArrays; dovrebbe permettere di riordinare la seuenza degli elementi di un vettore
type
{ TForm1 }
TForm1 = class(TForm)
DataSource1: TDataSource;
. . .
ZConnection1: TZConnection;
ZQuery1: TZQuery;
. . .
var Connection: IZConnection;
....
Connection := ZConnection1.DbcConnection;
...
Quando indico "accendere" il motore, intendo dire attivare la connessione al database con tutto quello che ne consegue. (Caricamento della dll del driver vendor per l'accesso e altre cosine che fa internamente per garantirti l'accesso al database)Mi dispiace deluderti, ma non ho la preparazione che forse immagini.
Ho cercato di non essere pesante ed entrare troppo nei dettagli ma dare un taglio più informare giusto per arrivare a come utilizzare le cose. Gli sviluppatori Java non hanno problemi di sorta con quelle interfacce, essendo simili a quelle di JDBC.
Zeos è costruito a strati.
Quello che hai visto fino ad adesso è quello più esterno.
Il DriverManager è proprio una classe per i fatti suoi.
Nel tuo codice devi "adattare" il codice utilizzando:
[/size]Codice: [Seleziona]var Connection: IZConnection;
....
Connection := ZConnection1.DbcConnection;
...
A me non funziona:
Ho modificato la parte implementation del programma inserendovi la var Connection:Codice: [Seleziona]Il compilatore accende il seguente messaggio d'Errore:unit frmmain;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, DB, Forms, Controls, Graphics, Dialogs, StdCtrls, ComCtrls,
ExtCtrls, fpspreadsheet, laz_fpspreadsheet, Process, ZConnection, ZDataset, utilmie,
fpstypes; // , flcDynArrays; dovrebbe permettere di riordinare la seuenza degli elementi di un vettore
type
{ TForm1 }
{
--- bla --- bla ---
TForm1 = class(TForm)
DataSource1: TDataSource;
leInfoMov: TLabeledEdit;
PulsFine: TButton;
PulsAvvia: TButton;
Label1: TLabel;
lsDir: TListBox;
ZConnection1: TZConnection;
ZQuery1: TZQuery;
procedure PulsFineClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure PulsAvviaClick(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
uses
frm2;
type
TsSpreadsheetFormat = (sfExcel2, sfExcel5, sfExcel8, sfExcelXML, sfOOXML,
sfOpenDocument, sfCSV, sfHTML, sfWikiTable_Pipes, sfWikiTable_WikiMedia, sfUser); // sfOpenDocument è il tipo di formato valido per OpenOffice/LibreOffice.ods
const
dirFogli: string = '/media/dirdati/dativari/ContDom/';
var
Connection: IZConnection;
{ TForm1 }
--- bla --- bla ---Citazionefrmmain.pas(75,15) Error: Identifier not found "IZConnection"
frmmain.pas(75,27) Error: Error in type definition
La "IZConnection" è definita nell'unità "ZDbcIntfs" che devi inserire nelle Uses nella sezione Interface.Hai ragione, era scritto nella guida che mi ha suggerito di leggere Stilgar. Ora il compilatore l'ha riconosciuto.
In genere i componenti hanno una controparte di "design" che consente di essere configurati a designtime ed evitando tutte quelle operazioni che si dovrebbero invece effettuare a codice.
. . .
procedure TForm1.FormCreate(Sender: TObject);
const
dbCopia: String = '/media/dirdati/dativari/contabfam/ContabFamdb_prove';
dbOrig: String = '/media/dirdati/dativari/contabfam/ContabFamdb';
var
dbConn: IZConnection;
stmt: IZStatement;
rs: IZResultSet;
swAster: Boolean = False;
lun, totRecQry: Integer;
annata, dtIni, dtFin, sql, striMia: String;
dbDati: String = 'zdbc:sqlite-3:';
[...]
begin
[...]
dbDati:= dbDati + dbCopia;
dbConn := DriverManager.GetConnection(dbDati);
[...]
stmt:= FConnection.CreateStatement;
sql:= 'SELECT DtCoMovg,StaDtMovg FROM riepmovg WHERE DtCoMovg >= ' + dtIni + ' AND DtCoMovg <= ' + dtFin;
rs:= stmt.ExecuteQuery(sql);
totRecQry:= rs.GetRow;
[...]
frmmain.pas(155,17) Error: Identifier not found "FConnection"Ho guardato e riguardato la guida di Stilgar tante volte, ma non ho trovato niente che mi illuminasse.
:)
Stai dichiarando dbConn: IZConnection; e usi [/size]stmt:= FConnection.CreateStatement;.
"F" prima delle variabili, se applichiamo le convenzioni, indica che è una variabile d'istanza.
dbConn va benissimo come nome locale.
procedure TForm1.FormCreate(Sender: TObject);
const
dbCopia: String = '/media/dirdati/dativari/contabfam/ContabFamdb_prove';
dbOrig: String = '/media/dirdati/dativari/contabfam/ContabFamdb';
var
dbConn: IZConnection;
stmt: IZStatement;
rs: IZResultSet;
lun, totRecQry: Integer;
annata, dtIni, dtFin, sql, striMia: String;
dbDati: String = 'zdbc:sqlite-3:';
begin
[...]
dbDati:= dbDati + dbCopia;
dbConn:= DriverManager.GetConnection(dbDati);
[...]
stmt:= dbConn.CreateStatement;
sql:= 'SELECT DtCoMovg,StaDtMovg FROM riepmovg WHERE DtCoMovg >= ' + dtIni + ' AND DtCoMovg <= ' + dtFin;
rs:= stmt.ExecuteQuery(sql);
totRecQry:= rs.GetRow;
[...]
const
dbCopia: String = '/media/dirdati/dativari/contabfam/ContabFamdb_prove';
stmt:= dbConn.CreateStatement;
sql:= 'SELECT DtCoMovg,StaDtMovg FROM riepmovg WHERE DtCoMovg >= ' + dtIni + ' AND DtCoMovg <= ' + dtFin;
rs:= stmt.ExecuteQuery(sql);
totRecQry:= rs.GetRow;
hai controllato i permessi di tutto il percorso?No, l'unico utente sono io. Comunque, per prova ho attivato i permessi a tutti e l'errore è sempre lo stesso
il tuo utente deve avere i permessi di lettura/scrittura sulle varie cartelle
SQL Error: unable to open database file".al momento del "dbConn.CreateStatement".
namei -m /media/dirdati/dativari/contabfam/ContabFamdb_prove
[petrus@localhost ~]$ namei -m /media/dirdati/dativari/contabfam/ContabFamdb_prove
f: /media/dirdati/dativari/contabfam/ContabFamdb_prove
dr-xr-xr-x /
drwxr-xr-x media
drwxr-xr-x dirdati
drwxrwxrwx dativari
drwxrwxrwx contabfam
-rwxr-xr-x ContabFamdb_prove
[petrus@localhost ~]$
dbCopia: String = '/media/dirdati/dativari/contabfam/ContabFamdb_prove';
dbOrig: String = '/media/dirdati/dativari/contabfam/ContabFamdb';
var
AProcess: TProcess;
Esito: TSearchRec;
dbConn: IZConnection;
stmt: IZStatement;
rs: IZResultSet;
lun, totRecQry: Integer;
annata, dtIni, dtFin, sql, striMia: String;
dbDati: String = 'zdbc:sqlite-3:';
begin
AProcess := TProcess.Create(nil); // creo l'oggetto TProcess e lo assegno alla variabile AProcess.
striMia:='rm -f ' + dbCopia; // *** NON necessasria ***
AProcess.CommandLine:= striMia; // rimuovo, se esiste, la copia vecchia del DB
AProcess.Options := AProcess.Options + [poWaitOnExit]; // Questa opzione permette il complitamento del comando affidato ad AProcess prima di
// restituire il controllo al programma corrente
AProcess.Execute; // esegue la linea di comando col comando creata prima
striMia:= 'cp ' + dbOrig + ' ' + dbCopia;
AProcess.CommandLine:= striMia;
AProcess.Options := AProcess.Options + [poWaitOnExit];
AProcess.Execute;
AProcess.Free;
ShowMessage('"ContabFamdb" copiato in "ContabFamdb_prove"');
try
stmt:= dbConn.CreateStatement;
except
on E: Exception do
WriteLn('ERRORE nel "dbConn.CreateStatement", dove dbConn contiene "DriverManager.GetConnection(' + dbDati + ')"' + IntToStr(E.HelpContext) + ': ' + E.Message);
end;
Il contenuto di dbDati è corretto. :o
ERRORE nel "dbConn.CreateStatement", dove dbConn contiene "DriverManager.GetConnection(zdbc:sqlite-3:/media/dirdati/dativari/contabfam/ContabFamdb_prove)"0: SQL Error: unable to open database file
const
CurrentProtocol = 'sqlite';
DriverManager.GetConnection(DriverManager.ConstructURL(CurrentProtocol, '', fileName, '', '', 0, nil));
Il progetto ContDomInDomusRatio ha sollevato una eccezione di classe 'External: SIGSEGV'.riporto il codice modificato:
Nel file 'frmmain.pas' alla riga 158:
stmt := dbConn.CreateStatement;
const
CurrentProtocol = 'sqlite';
dbCopia: String = '/media/dirdati/dativari/contabfam/ContabFamdb_prove';
dbOrig: String = '/media/dirdati/dativari/contabfam/ContabFamdb';
var
AProcess: TProcess;
dbConn: IZConnection;
stmt :IZStatement;
rs :IZResultSet;
[...]
dbDati: String = 'zdbc:sqlite:';
begin
[...]
dbDati:= dbDati + dbCopia;
DriverManager.GetConnection(DriverManager.ConstructURL(CurrentProtocol, '', dbDati, '', '', 0, nil));
// DriverManager.GetConnection(DriverManager.ConstructURL(CurrentProtocol, '', dbCopia, '', '', 0, nil));
If FindFirst(dirFogli + 'ContDom*.*', faAnyFile, Esito)=0 then
begin
Label1.Caption:= 'Directory corrente:' + chr(10) + dirFogli;
repeat
begin
lun:= Length(Esito.Name);
annata:= Copy(Esito.Name,(lun-7),4);
WriteLn('nomeFoglio= "' + Esito.Name + '" / annata: -' + annata + '-');
dtIni:= annata + '0101';
dtFin:= annata + '1231';
stmt := dbConn.CreateStatement;
Temo che dovrò abbandonare IZConnetion per ritornare a TZConnection, oppure, drasticamente, dovrò abbandonare addirittura ZEOS.
A mio parere, ritorna dal componente TZConnection. Poi pian piano, quando avrai voglia, nuovo entusiamo e tempo puoi ripartire a vedere come il componente funziona e come si interfaccia con l'IZConnection.
Io purtroppo non posso aiutarti perchè Lazarus l'ho preso in mano da poco.
... usare 5 query non è un problema.
dbDati:= dbDati + dbCopia;
DriverManager.GetConnection(DriverManager.ConstructURL(CurrentProtocol, '', dbDati, '', '', 0, nil));
// dbDati('zdbc:sqlite:')+dbCopia('/media/dirdati/dativari/contabfam/ContabFamdb_prove')
procedure TDatabaseModule.createStructures(fileName: TFileName);
begin
try
FUpdateConnection := DriverManager.GetConnection(DriverManager.ConstructURL(CurrentProtocol, '', fileName, '', '', 0, nil));
try
if not tablePresent(FUpdateConnection, 'Subject') then
begin
FUpdateConnection.CreateStatement.Execute('CREATE TABLE Subject (id VARCHAR(37) primary key, title varchar(50))');
end;
if not tablePresent(FUpdateConnection, 'Note') then
begin
FUpdateConnection.CreateStatement.Execute('CREATE TABLE Note (id VARCHAR(37) primary key, subjectId VARCHAR(37), title varchar(100), [text] text, password varchar(200), FOREIGN KEY(subjectId) REFERENCES Subject(id))');
end;
if not tablePresent(FUpdateConnection, 'Attach') then
begin
FUpdateConnection.CreateStatement.Execute('CREATE TABLE Attach (id VARCHAR(37) primary key, noteId VARCHAR(37), comment varchar(2000))');
end;
if not tablePresent(FUpdateConnection, 'ToDo') then
begin
FUpdateConnection.CreateStatement.Execute('CREATE TABLE ToDo (id VARCHAR(37) primary key, noteId VARCHAR(37), comment varchar(2000), done int default 0)');
end;
if not tablePresent(FUpdateConnection, 'Info') then
begin
FUpdateConnection.CreateStatement.Execute('CREATE TABLE Info (key varchar(30) primary key, value varchar(100));');
FUpdateConnection.CreateStatement.Execute('INSERT INTO Info (key,value)values(''format-version'',''2.0'')');
end;
FUpdateConnection.CreateStatement.Execute('VACUUM');
finally
FUpdateConnection.Close;
end;
except
on e: Exception do
begin
writeln(e.Message);
end;
end;
FUpdateConnection := nil;
end;
function TDatabaseModule.tablePresent(datasource: IZConnection; tableName: string): boolean;
var
rs: IZResultSet;
begin
Result := False;
rs := datasource.GetMetadata.GetTables('', '', '%' + tableName + '%', ['TABLE']);
while rs.Next do
begin
tableName := rs.GetStringByName('TABLE_NAME');
if tableName = tableName then
begin
Result := True;
break;
end;
end;
end;
Il debugger lo usi?Il debugger lo uso, ma per constatare insieme il contenuto dell'URL faccio così
[...]
Perchè ho l'impressione che tu stia mandando 2 volte il protocollo da usare (quindi il driver).
[...]
Carica l'url in una variabile e controlla col debugger il suo contenuto. O stampa a console il valore, come ti trovi meglio.
dbDati:= dbDati + dbCopia;
striMia:= DriverManager.ConstructURL(CurrentProtocol, '', dbDati, '', '', 0, nil);
Writeln('DriverManager.URL= "' + striMia + '"');
DriverManager.GetConnection(DriverManager.ConstructURL(CurrentProtocol, '', dbDati, '', '', 0, nil));
DriverManager.URL= "zdbc:sqlite:///zdbc:sqlite:/media/dirdati/dativari/contabfam/ContabFamdb_prove"
DriverManager.URL= "zdbc:sqlite:////media/dirdati/dativari/contabfam/ContabFamdb_prove"Non capisco la presenza delle "///" precedenti il percorso contenuto nella variabile dbCopia (dalla finestra del debugger: "dbCopia = '/media/dirdati/dativari/contabfam/ContabFamdb_prove'
Cmq, ora ti si apre quel benedetto file?Si, finalmente si apre.
const
CurrentProtocol = 'sqlite';
dbCopia: String = '/media/dirdati/dativari/contabfam/ContabFamdb_prove';
dbOrig: String = '/media/dirdati/dativari/contabfam/ContabFamdb';
var
FConn: IZConnection;
stmt :IZStatement;
rs :IZResultSet;
[...]
begin
striMia:= DriverManager.ConstructURL(CurrentProtocol, '', dbCopia, '', '', 0, nil);
Writeln('DriverManager.URL= "' + striMia + '"');
FConn:= DriverManager.GetConnection(striMia);
[...]
stmt := FConn.CreateStatement;
sql:= 'SELECT DtCoMovg,StaDtMovg FROM riepmovg WHERE DtCoMovg >= ' + dtIni + ' AND DtCoMovg <= ' + dtFin;
rs := stmt.ExecuteQuery(sql);
totRecQry:= rs.GetRow; // totRecQry contiene sempre 0, anche quando il range di ricerca non è nullo
[...]
GetRow dovrebbe (ma non ricordo bene) a che posizione sei nel cursore.Non capisco bene cosa vuoi dire. Vuoi sapere dove si trova la "G" di GetRow ? La risposta è: posiz.26 ::)
Quindi senza while rs.next do dovrebbe restare sempre a zero.Hai ragione a fare quella riflessione, il codice è sparuto, ma ho riportato solo l'essenziale. Prima di questo momento riportarlo tutto non aveva senso.
procedure TForm1.FormCreate(Sender: TObject);
const
dirFogli: string = '/media/dirdati/dativari/ContDom/';
CurrentProtocol = 'sqlite';
dbCopia: String = '/media/dirdati/dativari/contabfam/ContabFamdb_prove';
dbOrig: String = '/media/dirdati/dativari/contabfam/ContabFamdb';
var
Esito: TSearchRec;
FConn: IZConnection;
stmt :IZStatement;
rs :IZResultSet;
swAster: Boolean = False;
lun, totRecQry: Integer;
annata, dtIni, dtFin, sql, striMia: String;
begin
//---------------------------------------------------- Salvataggio prudenziale del DB "ContabFamdb" -------------------------------------------------
CopyFile(dbOrig, dbCopia);
ShowMessage('"ContabFamdb" copiato in "ContabFamdb_prove"');
//---------------------------------------------------- FINE salvataggoio ---------------------------------------------------------------------------------
striMia:= DriverManager.ConstructURL(CurrentProtocol, '', dbCopia, '', '', 0, nil);
Writeln('DriverManager.URL= "' + striMia + '"');
FConn:= DriverManager.GetConnection(striMia);
stmt:= FConn.CreateStatement;
If FindFirst(dirFogli + 'ContDom*.*', faAnyFile, Esito)=0 then
begin
Label1.Caption:= 'Directory corrente:' + chr(10) + dirFogli;
repeat
begin
lun:= Length(Esito.Name);
annata:= Copy(Esito.Name,(lun-7),4);
WriteLn('nomeFoglio= "' + Esito.Name + '" / annata: -' + annata + '-');
// dtIni:= annata + '0101';
// dtFin:= annata + '1231';
dtIni:= '20020101'; // istruzione di prova di inizio periodo con 352 record
dtFin:= '20021231'; // istruzione di prova di fine periodo con 352 record
sql:= 'SELECT DtCoMovg,StaDtMovg FROM riepmovg WHERE DtCoMovg >= ' + dtIni + ' AND DtCoMovg <= ' + dtFin;
try
rs:= stmt.ExecuteQuery(sql);
totRecQry:= rs.GetRow;
except
on e: Exception do
begin
writeln(e.Message);
end;
end;
FConn.Close;
FConn:= nil;
case totRecQry of
0:
begin
striMia:= '-' + Esito.Name;
lsDir.Items.Add(striMia);
end
else
begin;
WriteLn('*** TROVATI in riepmovg, per l''annata -'+ annata + '- n.' + IntToStr(totRecQry) + '***');
striMia:= '*' + Esito.Name;
swAster:= True;
lsDir.Items.Add(striMia);
end;
end;
end;
Until FindnNext(Esito) <> 0;
FindClose(Esito);
// Writeln('Lettura directory -> TERMINATA' );
PulsAvvia.Caption:='AVVIO' + chr(10) + 'LAVORO';
case
swAster of
True:
begin
leInfoMov.Visible:= True;
end;
end;
end;
end;
Getrow dovrebbe restituire la posizione del cursore.Ah! Avevo capito male. Secondo me "rs.GetRow" era l'istruzione corrispondente alla "Form1.ZQuery1.RecordCount" di TZConnection.
Non spostando il cursore sei alla riga zero.
Come scrivevo nella miniguida, serve un rs.next
Se restituisce false vuol dire che non c'è più nulla nel cursore.
Come si accede alle colonne?
cursor.get[xxxxx](indice).
function LeggiUltimoID(nmTabDB: String):Integer;
const
CurrentProtocol = 'sqlite';
var
FConn: IZConnection;
stmt: IZStatement;
rs: IZResultSet;
numID, sql, striMia: String;
begin
striMia:= DriverManager.ConstructURL(CurrentProtocol, '', dbCorr, '', '', 0, nil);
FConn:= DriverManager.GetConnection(striMia);
stmt:= FConn.CreateStatement;
sql:= 'SELECT fields[1] as col1 FROM ' + nmTabDB + 'ORDER BY col1 DESC LIMIT 1';
rs:= stmt.ExecuteQuery(sql);
numID:= LoadCursorFromLazarusResource(col1); // dovrebbe leggere il contenuto della colonna 1 della tabella corrente del DB
end;
numID = 0
var
numID: Integer = longint
/media/dirdati/dativari/lazarus_progetti/lazarus_progetti_miei/daContDom_aDomusRatio/frmmain.pas(1216,3)
Codice: [Seleziona]numID:= LoadCursorFromLazarusResource(col1); // dovrebbe leggere il contenuto della colonna 1 della tabella corrente del DB
rs.getRow
Convengo con te che "LoadCursorFromLazarusResource(col1)" non dia il risultato desiderato, ma il comando "cursor.get[xxxxx](indice)", che ho trovato nella miniguida di Stilgar non viene riconosciuto, perciò non ho potuto portare a termine la prova. Quel Load... li, effettivamente non nha funzionato, ma mi ha permesso di terminare la prova. Il mio problema è che non riesco a trovare la sintassi corretta per il mio scopo, nè riesco ad immaginarmela.Codice: [Seleziona]numID:= LoadCursorFromLazarusResource(col1); // dovrebbe leggere il contenuto della colonna 1 della tabella corrente del DB
Non penso che quello ti ritorni il valore contenuto nel campo 'col1', ha a che fare con tuttaltro.
Tramite Interfaccia non conosco la funzione da chiamare, ma penso che sia tramiteCodice: [Seleziona]rs.getRow
function IsNull(ColumnIndex: Integer): Boolean;
function GetPChar(ColumnIndex: Integer): PChar;
function GetPAnsiChar(ColumnIndex: Integer): PAnsiChar; overload;
function GetPAnsiChar(ColumnIndex: Integer; out Len: NativeUInt): PAnsiChar; overload;
function GetString(ColumnIndex: Integer): String;
{$IFNDEF NO_ANSISTRING}
function GetAnsiString(ColumnIndex: Integer): AnsiString;
{$ENDIF}
{$IFNDEF NO_UTF8STRING}
function GetUTF8String(ColumnIndex: Integer): UTF8String;
{$ENDIF}
function GetRawByteString(ColumnIndex: Integer): RawByteString;
function GetBinaryString(ColumnIndex: Integer): RawByteString; deprecated;
function GetUnicodeString(ColumnIndex: Integer): ZWideString;
function GetPWideChar(ColumnIndex: Integer): PWideChar; overload;
function GetPWideChar(ColumnIndex: Integer; out Len: NativeUInt): PWideChar; overload;
function GetBoolean(ColumnIndex: Integer): Boolean;
function GetByte(ColumnIndex: Integer): Byte;
function GetShort(ColumnIndex: Integer): ShortInt;
function GetWord(ColumnIndex: Integer): Word;
function GetSmall(ColumnIndex: Integer): SmallInt;
function GetUInt(ColumnIndex: Integer): Cardinal;
function GetInt(ColumnIndex: Integer): Integer;
function GetULong(ColumnIndex: Integer): UInt64;
function GetLong(ColumnIndex: Integer): Int64;
function GetFloat(ColumnIndex: Integer): Single;
function GetDouble(ColumnIndex: Integer): Double;
function GetCurrency(ColumnIndex: Integer): Currency;
function GetBigDecimal(ColumnIndex: Integer): Extended;
function GetBytes(ColumnIndex: Integer): TBytes;
function GetDate(ColumnIndex: Integer): TDateTime;
function GetTime(ColumnIndex: Integer): TDateTime;
function GetTimestamp(ColumnIndex: Integer): TDateTime;
function GetAsciiStream(ColumnIndex: Integer): TStream;
function GetUnicodeStream(ColumnIndex: Integer): TStream;
function GetBinaryStream(ColumnIndex: Integer): TStream;
function GetBlob(ColumnIndex: Integer): IZBlob;
function GetDataSet(ColumnIndex: Integer): IZDataSet;
function GetValue(ColumnIndex: Integer): TZVariant;
function GetDefaultExpression(ColumnIndex: Integer): string;
//======================================================================
// Methods for accessing results by column name
//======================================================================
function IsNullByName(const ColumnName: string): Boolean;
function GetPCharByName(const ColumnName: string): PChar;
function GetPAnsiCharByName(const ColumnName: string): PAnsiChar; overload;
function GetPAnsiCharByName(const ColumnName: string; out Len: NativeUInt): PAnsiChar; overload;
function GetStringByName(const ColumnName: string): String;
{$IFNDEF NO_ANSISTRING}
function GetAnsiStringByName(const ColumnName: string): AnsiString;
{$ENDIF}
{$IFNDEF NO_UTF8STRING}
function GetUTF8StringByName(const ColumnName: string): UTF8String;
{$ENDIF}
function GetRawByteStringByName(const ColumnName: string): RawByteString;
function GetBinaryStringByName(const ColumnName: string): RawByteString; deprecated;
function GetUnicodeStringByName(const ColumnName: string): ZWideString;
function GetPWideCharByName(const ColumnName: string): PWideChar; overload;
function GetPWideCharByName(const ColumnName: string; out Len: NativeUInt): PWideChar; overload;
function GetBooleanByName(const ColumnName: string): Boolean;
function GetByteByName(const ColumnName: string): Byte;
function GetShortByName(const ColumnName: string): ShortInt;
function GetWordByName(const ColumnName: string): Word;
function GetSmallByName(const ColumnName: string): SmallInt;
function GetUIntByName(const ColumnName: string): Cardinal;
function GetIntByName(const ColumnName: string): Integer;
function GetULongByName(const ColumnName: string): UInt64;
function GetLongByName(const ColumnName: string): Int64;
function GetFloatByName(const ColumnName: string): Single;
function GetDoubleByName(const ColumnName: string): Double;
function GetCurrencyByName(const ColumnName: string): Currency;
function GetBigDecimalByName(const ColumnName: string): Extended;
function GetBytesByName(const ColumnName: string): TBytes;
function GetDateByName(const ColumnName: string): TDateTime;
function GetTimeByName(const ColumnName: string): TDateTime;
function GetTimestampByName(const ColumnName: string): TDateTime;
function GetAsciiStreamByName(const ColumnName: string): TStream;
function GetUnicodeStreamByName(const ColumnName: string): TStream;
function GetBinaryStreamByName(const ColumnName: string): TStream;
function GetBlobByName(const ColumnName: string): IZBlob;
function GetDataSetByName(const ColumnName: String): IZDataSet;
function GetValueByName(const ColumnName: string): TZVariant;
//=====================================================================
// Advanced features:
//=====================================================================
function GetWarnings: EZSQLWarning;
procedure ClearWarnings;
function GetCursorName: String;
function GetMetadata: IZResultSetMetadata;
function FindColumn(const ColumnName: string): Integer;
20/04/2021 20:45:25: SQL Error: near "as": syntax error <SELECT fields[1] as col1 FROM Note ORDER BY col1 DESC LIMIT 1>
20/04/2021 20:45:33: SQL Error: no such column: fields <SELECT fields[1] FROM Note ORDER BY col1 DESC LIMIT 1>
SELECT max(RowId) FROM laTuaTabella
rs.getLong(1);
o
rs.getInt(1);
sql:= 'SELECT max(RowId) FROM ' + nmTabDB;
rs:= stmt.ExecuteQuery(sql);
numID:= rs.GetInt(1); // legge il contenuto della colonna ID(col.1) dell'ultima riga della tabella corrente del DB
Result:= numID;
numID = 59936L'ho verificato col DB Browser: --> ("SELECT max(RowId) FROM movimgg" = 59936)
var
numID: Integer = longint
/media/dirdati/dativari/lazarus_progetti/lazarus_progetti_miei/daContDom_aDomusRatio/frmmain.pas(1187,3)
...
var
FConn: IZConnection;
stmt :IZStatement;
rs :IZResultSet;
...
striMia:= DriverManager.ConstructURL(CurrentProtocol, '', '/media/dirdati/dativari/contabfam/Fragola', '', '', 0, nil); // Il DB Fragola non esiste ma vorrei che me lo dicesse il programma
FConn:= DriverManager.GetConnection(striMia); // prepara l’accesso al DB, cercandolo
try
stmt:= FConn.CreateStatement; // eseguela Open del DB
except
on e: Exception do
begin
ShowMessage('DB NON trovato');
end;
end;
Non ha ancora usato ZeosDB in maniera completa.Si, è così. Ho provato in debug ed ho visto chiaramente che l'eccezione non viene generata.
Però penso che l'apertura di una connessione non generi eccezioni:
striMia:= DriverManager.ConstructURL(CurrentProtocol, '', '/media/dirdati/dativari/contabfam/Fragola', '', '', 0, nil);
try
FConn:= DriverManager.GetConnection(striMia); // prepara l’accesso al DB, cercandolo
except
on e: Exception do
begin
ShowMessage('DB NON trovato');
end;
end;
stmt:= FConn.CreateStatement; // eseguela Open del DB
//-----------
sql:= 'SELECT DtCoMovg FROM riepmovg';
try
rs:= stmt.ExecuteQuery(sql);
totRecQry:= rs.GetRow; // "totquery" viene impostato a 0(puntamento primo record della query contenuta in sql)
while rs.next do
begin
totRecQry:= totRecQry + 1;
end;
except
on e: Exception do
begin
writeln(e.Message);
end;
end;
ShowMessage('record letti in "riepmovg"= ' + IntToStr(totRecQry));
striMia:= DriverManager.ConstructURL(CurrentProtocol, '', '/media/dirdati/dativari/contabfam/Fragola', '', '', 0, nil);
try
FConn:= DriverManager.GetConnection(striMia); // prepara l’accesso al DB, cercandolo
except
on e: Exception do
begin
ShowMessage('DB NON trovato');
end;
end;
stmt:= FConn.CreateStatement; // eseguela Open del DB
//-----------
sql:= 'SELECT DtCoMovg FROM riepmovg';
try
rs:= stmt.ExecuteQuery(sql);
except
on e: Exception do
begin
writeln(e.Message);
end;
end;
totRecQry:= rs.GetRow; // "totquery" viene impostato a 0(puntamento primo record della query contenuta in sql)
try
while rs.next do
begin
totRecQry:= totRecQry + 1;
end;
except
on e: Exception do
begin
writeln(e.Message);
end;
end;
ShowMessage('record letti in "riepmovg"= ' + IntToStr(totRecQry));
puoi sempre fare un controllo preventivo ed emettere un errore se il DB non esiste, usando la FileExist, in caso contrario, procedi con la connessione.Ho accolto piacevolmente il tuo consiglio, perchè era proprio quello che avevo pensato di fare stamani, prima d' accendere il pc.
function TFProgVision.DB_Check(const sNomeDB: WideString; var sErrore: WideString): LongWord;
var tempelenco: TStringList;
tempflag: boolean;
VersioneDB: string;
tempstr: string;
i: Integer;
tempResult: integer;
const
tempDBList: array [0..6] of string = ('VisSubPassi', 'VisVerificaColore', 'VisMediaBinaria', 'VisConteggioFronti', 'VisFeltrini', 'VisSequenze', 'VisOCV');
tempDBStepList: array [0..17] of string = ('DataOraUTC', 'Prg', 'SX', 'SubPasso', 'EsitoPasso', 'TipoControllo', 'ColoreControllo', 'ColoreLimiteLow', 'ColoreLimiteHigh', 'ScattaFoto', 'Exp1', 'Exp2', 'Exp3', 'Exp4', 'Exp5', 'Exp6', 'Exp7', 'Exp8');
zero: integer = 0;
type
tempDBtipo = (VisSubPassi=0, VisVerificaColore=1, VisMediaBinaria=2, VisConteggioFronti=3, VisFeltrini=4, VisSequenze=5, VisOCV=6);
begin
result := ord(App_NoErrore);
sErrore := ErroreDesc[ord(App_NoErrore)];
//Questa funzione, quando viene chiamata attiva il sistema di reportistica tramite DB.
//Inoltre effettua tutti i controlli e aggiorna automaticamente le tabelle della visione con la nuova struttura ove necessario.
//Test della presenza del database
try
ForceDirectories(ExtractFilePath(sNomeDB));
//Crea il buffer per gli Step (1 SubPasso solo di lunghezza fissa)
//(DataOraUTC, Prg, SX, SubPasso, EsitoPasso, TipoControllo, ColoreControllo, "ColoreLimite(intensita)", ScattaFoto, Exp1, Exp2, Exp3, Exp4, Exp5, Exp6, Exp7, Exp8)
if FDConnection1.Connected then
begin
FDConnection1.Close;
end;
VersioneDB := '50';
tempelenco := TStringList.Create;
//Non serve specificare in realtà la creazione, in quanto se non esiste il database viene creato qualunque modo si imposti.
if FileExists(sNomeDB) then
begin
FDConnection1.Params.Values['OpenMode'] := 'omReadWrite';
end
else
begin
FDConnection1.Params.Values['OpenMode'] := 'omCreateUTF16';
end;
FDConnection1.Params.Database := sNomeDB;
FDConnection1.Open;
//Se siamo arrivati sino a qui, vuole dire che il database comunqueè stato creato.
//Controlliamo ogni singola tabella della visione
//*
//Qui viene creata la tabella Versione. Con la seguente istruzione andiamo a cearla se non esiste:
FDConnection1.ExecSQL('create table if not exists Versione (Visione varchar(16))');
//Ora controlliamo se c'è il campo "Visione", se non c'è lo creiamo.
//Questo è il metodo fornito da SQLITE ('PRAGMA table_info(Versione)') per elencare i campi di una tabella;
//quello applicato è invece più generico e funziona con tutti i database
tempelenco.Clear;
tempflag := false;
i := 0;
FDConnection1.GetFieldNames('', '', 'Versione', '', tempelenco);
while i < tempelenco.Count do
begin
if UpperCase(tempelenco[i]) = 'VISIONE' then
begin
tempflag := true;
break;
end;
inc(i);
end;
if not tempflag then
begin
//Eseguiamo la AlterTable per aggiungere la colonna "Visione";
FDConnection1.ExecSQL('alter table Versione ADD COLUMN Visione varchar(16)');
end;
//Leggiamo il valore della versione, e se differisce allora è necessario modificare il database (o tabelle o campi).
//Se è Nullo lo aggiorniamo noi.
FDQuery1.Active := false;
FDQuery1.SQL.Clear;
FDQuery1.SQL.Add('select Visione from Versione');
FDQuery1.Active := true;
FDQuery1.First;
if FDQuery1.FieldByName('Visione').Value <> NULL then
begin
tempstr := FDQuery1.FieldByName('Visione').Value;
end
else
begin
tempstr := '50'; //per default viene inserito un valore di versione minore alla prima versione con il DB
FDQuery1.Edit;
FDQuery1.FieldByName('Visione').Value := tempstr;
FDQuery1.Post;
end;
//Verifichiamo la versione del database (prime due cifre della versione del programma)
if VersioneDB.ToInteger > tempstr.ToInteger then
begin
//Dobbiamo aggiornare il database, ricreando le tabelle e trasferendo i vecchi dati
//Vengono aggiornate tutte le tabelle, onde evitare qualsiasi problema
//La procedura è identica a quella usata dai vari SQLITE Manager
tempelenco.Clear;
tempflag := false;
i := 0;
FDConnection1.GetTableNames( '', '', '', tempelenco);
for i := Low(tempDBList) to High(tempDBList) do
begin
case tempDBtipo(i) of
VisSubPassi:
begin
//Per ogni tabella elencata, cerchiamose esiste già nel database
if tempelenco.IndexOf(tempDBList[i]) >=0 then
begin
//Trasferiamo i dati della tabella esistente e creiamo quella nuova, ritrasferendo tutti i dati.
FDConnection1.ExecSQL('PRAGMA foreign_keys = 0');
FDConnection1.ExecSQL('CREATE TABLE temp_'+tempDBList[i]+' AS SELECT * FROM '+tempDBList[i]);
FDConnection1.ExecSQL('DROP TABLE '+tempDBList[i]);
//Creiamo la nuova tabella
tempstr := 'CREATE TABLE if not exists '+tempDBList[i]+' (DataOraUTC DATETIME NOT NULL, Prg INTEGER NOT NULL, SX BOOLEAN NOT NULL, SubPasso INTEGER NOT NULL, EsitoPasso BOOLEAN NOT NULL, ';
tempstr := tempstr + 'TipoControllo varchar(16) NOT NULL, ColoreControllo varchar(16) NOT NULL, ColoreLimiteLow INTEGER NOT NULL, ColoreLimiteHigh INTEGER NOT NULL, ScattaFoto BOOLEAN NOT NULL, Exp1 INTEGER NOT NULL DEFAULT (0), Exp2 INTEGER NOT NULL DEFAULT (0), ';
tempstr := tempstr + 'Exp3 INTEGER NOT NULL DEFAULT (0), Exp4 INTEGER NOT NULL DEFAULT (0), Exp5 INTEGER NOT NULL DEFAULT (0), Exp6 INTEGER NOT NULL DEFAULT (0), Exp7 INTEGER NOT NULL DEFAULT (0), Exp8 INTEGER NOT NULL DEFAULT (0))';
FDConnection1.ExecSQL(tempstr);
//Reinseriamo i dati nella nuova tabella
//nei nuovi campi
tempstr := 'INSERT INTO '+tempDBList[i]+' (DataOraUTC, Prg, SX, SubPasso, EsitoPasso, TipoControllo, ColoreControllo, "ColoreLimite(intensita)", ScattaFoto, Exp1, Exp2, Exp3, Exp4, Exp5, Exp6, Exp7, Exp8) ';
//dai vecchi campi
tempstr := tempstr + 'SELECT DataOraUTC, Prg, SX, SubPasso, EsitoPasso, TipoControllo, ColoreControllo, "ColoreLimite(intensita)", ScattaFoto, Exp1, Exp2, Exp3, Exp4, Exp5, Exp6, Exp7, Exp8 FROM temp_'+tempDBList[i];
FDConnection1.ExecSQL(tempstr);
//Eliminiamo la vecchia tabella
FDConnection1.ExecSQL('DROP TABLE temp_'+tempDBList[i]);
//Creiamo gli eventuali indici
// 'CREATE UNIQUE INDEX IDX_IndiceSubPasso ON VisSubPassi (DataOraUTCs, Prg, SubPasso);
FDConnection1.ExecSQL('PRAGMA foreign_keys = 0');
end
else
begin
//Creiamo la nuova tabella
tempstr := 'CREATE TABLE if not exists '+tempDBList[i]+' (DataOraUTC DATETIME NOT NULL, Prg INTEGER NOT NULL, SX BOOLEAN NOT NULL, SubPasso INTEGER NOT NULL, EsitoPasso BOOLEAN NOT NULL, ';
tempstr := tempstr + 'TipoControllo varchar(16) NOT NULL, ColoreControllo varchar(16) NOT NULL, ColoreLimiteLow INTEGER NOT NULL, ColoreLimiteHigh INTEGER NOT NULL, ScattaFoto BOOLEAN NOT NULL, Exp1 INTEGER NOT NULL DEFAULT (0), Exp2 INTEGER NOT NULL DEFAULT (0), ';
tempstr := tempstr + 'Exp3 INTEGER NOT NULL DEFAULT (0), Exp4 INTEGER NOT NULL DEFAULT (0), Exp5 INTEGER NOT NULL DEFAULT (0), Exp6 INTEGER NOT NULL DEFAULT (0), Exp7 INTEGER NOT NULL DEFAULT (0), Exp8 INTEGER NOT NULL DEFAULT (0))';
FDConnection1.ExecSQL(tempstr);
end;
end;
VisVerificaColore:
begin
//Per ogni tabella elencata, cerchiamose esiste già nel database
if tempelenco.IndexOf(tempDBList[i]) >=0 then
begin
//Trasferiamo i dati della tabella esistente e creiamo quella nuova, ritrasferendo tutti i dati.
FDConnection1.ExecSQL('PRAGMA foreign_keys = 0');
FDConnection1.ExecSQL('CREATE TABLE temp_'+tempDBList[i]+' AS SELECT * FROM '+tempDBList[i]);
FDConnection1.ExecSQL('DROP TABLE '+tempDBList[i]);
//Creiamo la nuova tabella
//tempstr := 'CREATE TABLE if not exists '+tempDBList[i]+' (DataOraUTC DATETIME NOT NULL REFERENCES VisSubPassi (DataOraUTC), Prg INTEGER NOT NULL REFERENCES VisSubPassi (Prg), SX BOOLEAN NOT NULL REFERENCES VisSubPassi (SX), ';
//tempstr := tempstr + 'SubPasso INTEGER NOT NULL REFERENCES VisSubPassi (SubPasso), NumRoi INTEGER NOT NULL, EsitoRoi BOOLEAN NOT NULL, TipoRoi VARCHAR (16) NOT NULL, ';
tempstr := 'CREATE TABLE if not exists '+tempDBList[i]+' (DataOraUTC DATETIME NOT NULL, Prg INTEGER NOT NULL, SX BOOLEAN NOT NULL, ';
tempstr := tempstr + 'SubPasso INTEGER NOT NULL, NumRoi INTEGER NOT NULL, EsitoRoi BOOLEAN NOT NULL, TipoRoi VARCHAR (16) NOT NULL, ';
tempstr := tempstr + 'MinNumPixel INTEGER NOT NULL, MaxNumPixel INTEGER NOT NULL, ConteggioPixel INTEGER NOT NULL)';
FDConnection1.ExecSQL(tempstr);
//Reinseriamo i dati nella nuova tabella
//nei nuovi campi
tempstr := 'INSERT INTO '+tempDBList[i]+' (DataOraUTC, Prg, SX, SubPasso, NumRoi, EsitoRoi, TipoRoi, MinNumPixel, MaxNumPixel, ConteggioPixel) ';
//dai vecchi campi
tempstr := tempstr + 'SELECT DataOraUTC, Prg, SX, SubPasso, NumRoi, EsitoRoi, TipoRoi, MinNumPixel, MaxNumPixel, ConteggioPixel FROM temp_'+tempDBList[i];
FDConnection1.ExecSQL(tempstr);
//Eliminiamo la vecchia tabella
FDConnection1.ExecSQL('DROP TABLE temp_'+tempDBList[i]);
//Creiamo gli eventuali indici
// 'CREATE UNIQUE INDEX IDX_IndiceSubPasso ON VisSubPassi (DataOraUTCs, Prg, SubPasso);
FDConnection1.ExecSQL('PRAGMA foreign_keys = 0');
end
else
begin
//Creiamo la nuova tabella
tempstr := 'CREATE TABLE if not exists '+tempDBList[i]+' (DataOraUTC DATETIME NOT NULL, Prg INTEGER NOT NULL, SX BOOLEAN NOT NULL, ';
tempstr := tempstr + 'SubPasso INTEGER NOT NULL, NumRoi INTEGER NOT NULL, EsitoRoi BOOLEAN NOT NULL, TipoRoi VARCHAR (16) NOT NULL, ';
tempstr := tempstr + 'MinNumPixel INTEGER NOT NULL, MaxNumPixel INTEGER NOT NULL, ConteggioPixel INTEGER NOT NULL)';
FDConnection1.ExecSQL(tempstr);
end;
end;
//OMISSIS ............QUI SI CONTINUA CON LE ALTRE TABELLE
end;
end;
//Andiamo ad aggiornare il campo versione se siamo arrivati sino a qui
FDQuery1.Active := false;
FDQuery1.SQL.Clear;
FDQuery1.SQL.Add('select Visione from Versione');
FDQuery1.Active := true;
FDQuery1.First;
FDQuery1.Edit;
FDQuery1.FieldByName('Visione').Value := VersioneDB;
FDQuery1.Post;
end;
fUsaDBforTrace := true; //Se tutto OK allora settiamo il flag per l'uso del database.
except on e:exception do
begin
if not trystrtoint(e.ClassName, tempresult) then
begin
tempresult := BaseError_SW+$FFFF;
end;
Result := tempResult;
sErrore := '$'+inttohex(tempresult,8)+': '+e.Message;
end;
end;
tempelenco.Free;
end.;