FireDac Cached updates stops updating - sqlite

I am using SQLite databases (Delphi Seattle) FireDac components.
I have more than two applications writing into tables of the same database.
I was getting lock issues therefore started using CachedUpdates and all was fine.
Problem:
At times when the Application is running for more than few hours the Application stops Updating (Edit, Delete) my database tables, Read (Select) works fine.
No error comes up in OnReconcileError. This issue takes place in one of the applications and at the same time the other application using the same database works fine.
If problematic application is restarted, all is well again.
This is how I open my databases
LockingMode=Normal
StringFormat=Unicode
JournalMode=WAL
DriverID=SQLite
SharedCache=False
Synchronous=Full
BusyTimeout=20000
ForeignKeys=Off
Typical pattern of writing
try
wQry:=TFDQuery.Create(Nil);
wQry.Connection:=form_DatabaseWork.FDConnection1 ;
wQry.CachedUpdates:=True ;
wQry.Active:=false;
wQry.sql.text:='Select * from Setups';
wQry.Active:=True;
wQry.Edit ;
wQry.FieldByName('DisplayTitles').AsString:=wMsg ;
ssPost(wQry) ;
ssApplyUpdates(wQry);
finally
wQry.Active:=false;
FreeAndNil(wQry);
end;
Called functions
procedure ssApplyUpdates(pQry:TFDQuery);
var
nErr:Integer ;
begin
nErr:=pQry.ApplyUpdates ;
if nErr>0 then
begin
pQry.OnReconcileError:=form_Tools.Qry_DummyReconcileError ;
pQry.Reconcile ;
pQry.OnReconcileError:=Nil ;
end
else
pQry.CommitUpdates ;
end;
function ssPost(pQry:TFDQuery):Boolean ;
begin
result:=false;
try
pQry.Post;
result:=true;
except
on E: Exception do
WriteSomewhere(E.Message) ;
end;
end;
procedure Tform_Tools.Qry_DummyReconcileError(DataSet: TFDDataSet; E: EFDException; UpdateKind: TFDDatSRowState; var Action: TFDDAptReconcileAction);
begin
Action:=raCorrect ;
end;
I have not added FDconnection.transaction ... Hope that will help. Thanks.

Related

How to exec MariaDB Store Proc from Visual Foxpro?

I have a function/store proc in Maria DB
CREATE DEFINER=`root`#`localhost` PROCEDURE `test1`(var1 varchar(100))
BEGIN
select * from ttype where kode=var1;
END
I need to get a cursor from store proc, Howto get a cursor in vfp application, database in MariaDb/MySQL StoreProc?
I try with this in my Visual Foxpro :
Sqlexec(kon,"call test1 ('ABC')","test") --> not running
But when I use common select like this :
sqlexec(kon,"select * from ttype where kode='ABC'","test") --it's running well..
"Can you show me how to use aerror() in my case?"
You would use the AError() function always when any ODBC Remote action would fail, i.e. any of Vfp's SQL*() functions, like SqlStringConnect() for example or your proposed
sqlexec(kon,"select * from ttype where kode='ABC'","test") --it's running well
&& Actually you cannot know whether "it's running well" unless you are evaluating its return value like this:
Local lnResult, laSqlErrors[1], lcErrorMessage
lnResult = SqlExec(kon,"select * from ttype where kode='ABC'","test")
If m.lnResult = –1 && as documented in the F1 Help
AERROR(laSqlErrors)
lcErrorMessage = ;
TRANSFORM(laSqlErrors[1]) + ", " + ;
TRANSFORM(laSqlErrors[2])
&& now write a log and/or inform the user
ENDIF
&& to be continued

Print multiple reports on business central

I need to use multiples Report.Print() in a code, but business central only prints the last requested print.
Using a dialog.confirm(), a page.runmodal() or a message() between the prints works, but I need the code to run automatically without user input.
Any ideas?
Ex.: Not working, only last one prints
codeunit 90101 Test
{
trigger OnRun()
var
salesInvoice: Record "Sales Invoice Header";
RecRef: RecordRef;
begin
salesInvoice.setfilter("No.", '103021');
RecRef.GetTable(salesInvoice);
Report.Print(1306, '', '', RecRef);
salesInvoice.Reset();
salesInvoice.setfilter("No.", '103022'); //only this one prints
RecRef.GetTable(salesInvoice);
Report.Print(1306, '', '', RecRef);
end;
}
Ex2.: working, prints both
codeunit 90101 Test
{
trigger OnRun()
var
salesInvoice: Record "Sales Invoice Header";
RecRef: RecordRef;
begin
salesInvoice.setfilter("No.", '103021');
RecRef.GetTable(salesInvoice);
Report.Print(1306, '', '', RecRef);
salesInvoice.Reset();
salesInvoice.setfilter("No.", '103022');
RecRef.GetTable(salesInvoice);
if Dialog.Confirm('hello') then;
Report.Print(1306, '', '', RecRef);
end;
}
I'm having the same issue.
I was just as confused as I kept thinking "but how does report selection work then?" but realized it always opens the request page.
I'm considering these 2 options:
Save as pdf and store it to a blob and print it using a .net service running on the application server. See this article for printing pdf's.
Create a non-recurring job queue entry to print each report.
This is worked out quite well for me:
...
CreatePrintingJob(Report::"Warehouse Shipment", WarehouseShipmentHeader.RecordId);
...
procedure CreatePrintingJob(_ReportID: Integer; _RecordToPrint: RecordId)
begin
CreatePrintingJob(_ReportID, '', _RecordToPrint);
end;
procedure CreatePrintingJob(_ReportID: Integer; _ReportParameters: Text; _RecordToPrint: RecordId)
var
jobQueueEntry: Record "Job Queue Entry";
begin
jobQueueEntry.Init();
jobQueueEntry."Object Type to Run" := jobQueueEntry."Object Type to Run"::Report;
jobQueueEntry."Object ID to Run" := _ReportID;
jobQueueEntry."Record ID to Process" := _RecordToPrint;
jobQueueEntry."Starting Time" := 000000T;
jobQueueEntry."Maximum No. of Attempts to Run" := 3;
jobQueueEntry."Report Output Type" := jobQueueEntry."Report Output Type"::Print;
jobQueueEntry.Insert(true);
jobQueueEntry.SetReportParameters(_ReportParameters);
jobQueueEntry.ScheduleTask();
end;

dbgrid looping to update data not working

so I have a DBGRID that has this infos :
I wanted to edit values inside that DBGRID. I provide a button with codes :
var ptlok, idp, tgl, after, kode, jlh, sql, sqla:string;
begin
while not dbgrid2.DataSource.DataSet.Eof do
begin
ptlok:=dbgrid2.DataSource.DataSet.Fields[0].AsString;
tgl:=dbgrid2.DataSource.DataSet.Fields[1].AsString;
after := stringreplace(tgl, '/', '-', [rfReplaceAll, rfIgnoreCase]);
kode:=dbgrid2.DataSource.DataSet.Fields[2].AsString;
jlh:=dbgrid2.DataSource.DataSet.Fields[3].AsString;
idp:=dbgrid2.DataSource.DataSet.Fields[4].AsString;
sql:='update kasir_opname_detail set kode='+quotedstr(kode)+',
jumlah='+quotedstr(jlh)+' where ptlokasi='+quotedstr(ptlok)+' and
tanggal=to_date('+quotedstr(after)+','+quotedstr('dd-mm-yyyy')+')'+' and
idpay='+quotedstr(idp)+'';
sqla:=sql;
zquery13.close;
zquery13.sql.clear;
zquery13.sql.add(sqla);
zquery13.execsql;
dbgrid2.DataSource.dataset.Next;
showmessage(sqla);
//end;
label19.Caption:=sqla;
end;
showmessage('Data Berhasil Disimpan!');
end;
However the data aren't saved as expected. it will only read last line of DBGRID then updates all data with values from last line of DBGRID.
is there something wrong with the code?
(prev it works with different dbgrid)
I am using delphi 7 and oracle as database. Thanks in advance.

How to search for slow queries on Android SQLite

I am developping and Android application and want to find the slowest/more expansive sqlite queries running on my device to fine tune them.
Which query can I use and how can I run it on my device database ?
There is no built-in mechanism that already times your queries.
You have to add your own logging:
long t1 = System.currentTimeMillis();
Cursor c = db.query(...);
try {
while (c.moveToNext()) {
...
}
} finally {
c.close();
}
long t2 = System.currentTimeMillis();
Log.d(TAG, "query time: " + (t2 - t1));
And please note that SQLite computes result rows on demand, so you cannot easily isolate the query execution time from the time that your own code needs to handle the result rows.

Recovering from ComPort drop-out

D5-pro:
Using TurboPower APro and the ComPort and Terminal Components with USB Arduino Nano for a very basic Comms-Terminal. All works fine until I unplug the USB to simulate losing the Port. It all just hangs and will not restart without closing and restarting.
I cannot find an Event or process that is monitoring the Port status so I can gracefully shut the Port. I am able to prevent the Port being opened if it doesn't exist, but once opened and data streaming in, I seem to lose all access to it.
I also tried TComPort and Terminal by Dejan Crnila and it also does not stop gracefully either. It actually crashes and I have to use TaskManager to shut it all down.
Can someone please guide me with some code snippets that might give an indication that the port has gone missing. Or is there a better free Component for doing this.
Some modifications in the AwUser unit are required.
Add a new event for I/O errors.
TPortIOErrorEvent = procedure(CP : TObject; Error : Cardinal) of object;
property OnPortIOError: TPortIOErrorEvent read FOnPortIOError write FOnPortIOError;
Modify the TComThread.Execute method in the AwUser unit.
{Release time slice until we get a communications event}
if not WaitComEvent(CurrentEvent, #ComOL) then begin
if GetLastError = ERROR_IO_PENDING then begin
if GetOverLappedResult(CidEx,
ComOL,
Junk,
True) then begin
{WIN32 bug workaround: Apro gets the modem status bits
with a call (later) to GetCommModemStatus. Unfortunately,
that routine never seems to return either RI or TERI.
So, we note either EV_RING or EV_RINGTE here and later
manually merge the TERI bit into ModemStatus.}
if ((CurrentEvent and EV_RINGTE) <> 0) or
((CurrentEvent and EV_RING) <> 0) then
RingFlag := True;
{Read complete, reset event}
ResetEvent(ComOL.hEvent);
end else begin
{Port closed or other fatal condition, just exit the thread}
SetEvent(GeneralEvent);
CloseHandle(ComOL.hEvent);
H.ThreadGone(Self);
Exit;
end;
end else begin
Err := GetLastError; {!!! added code}
{ If we get an ERROR_INVALID_PARAMETER, we assume it's our }
{ use of ev_RingTe -- clear the flag and try again }
if (GetLastError = ERROR_INVALID_PARAMETER) and
(LastMask and EV_RINGTE <> 0) then begin
LastMask := DefEventMask and not EV_RINGTE;
SetCommMask(CidEx, LastMask);
end;
{!!! added code begin}
if (Err <> ERROR_INVALID_PARAMETER) and (Err>0) and Assigned(FOnPortIOError) then
FOnPortIOError(H.fOwner, Err)
{!!! added code end}
end;
end;
Add the similar code to "ProcessOutputEvent".
In the new event handler analyze the I/O error and close/re-open the port.

Resources