I am new to db2 and got stuck in a problem which shouldn't be tricky.
I have a procedure try_a which calls another procedure try_b
in both the procedures i have declared exit handler for sql exception.
Suppose in try_b divide by zero error is encountered then that is returned using SIGNAL.
When try_a (exit handler written)calls try_b then on case of divide by zero error in try_b ,sql exception of inner block is not shown.
Can you please help how can this be achieved.
I don't have a sample code now. Will try to put that tomorrow.
When you use SIGNAL in the inner stored procedure, the condition that is raised is the user-defined type, not the original condition that cause the inner condition handler to be invoked. It has its own SQLCODE, SQLSTATE, and message. You could use the RESIGNAL statement to raise the same condition.
Alternatively, you could log error messages to a temporary table or a file in each condition handler.
Related
I am using Delphi 2009 Unicode and Firebird 3.x UTF8/dialect 3 database with IBX components. And now I see that all the exceptions raised from the Firebird SQL procedure and trigger code (e.g. using exception my_exception; statement) are handled by IBX as special Firebird exceptions:
Attempt to execute an unprepared dynamic SQL statement
Error Code: 335544711 SQL Code: -901
IBX does not report the name/code/content of the original Firebird exception. It is quite strange, because Delphi 2009 IBX can handle Firebird 2.1 UTF8/Unicode exceptions without problems. It seems to me that IBX is trying to do some extra steps that are not allowed.
Of course, I know that all the advices to move to other frameworks from the IBX, but we are not living in the ideal world, so, the question is as it is.
Question extended:
After initialization code in the project file (this is IB routine http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/IB_SetIBDataBaseErrorMessages.html):
SetIBDataBaseErrorMessages([ShowSQLCode,ShowIBMessage,ShowSQLMessage]);
I am getting normal error messages from the exceptions that are raised from the triggers, but I am still getting generic 'Attempt to execute...' error message in the case when exception is raised from the SQL procedure.
Question updated:
The generic exception about attempt appears when the procedure is called from the IBX TIBStoredProc, but if stored procedure is called (via select from...) from the TIBDataSet, then the right error message appears. So - there should be problem how TIBStoredProc handles the error messages.
Debug shows, that Delphi IBX code IBSQL.pas contains code:
SQLExecProcedure:
begin
fetch_res := Call(FGDSLibrary.isc_dsql_execute2(StatusVector, TRHandle,
#FHandle, Database.SQLDialect, FSQLParams.AsXSQLDA,
FSQLRecord.AsXSQLDA), False);
if (fetch_res <> 0) then
begin
if (fetch_res <> isc_lock_conflict) then
begin
{ Sometimes a prepared stored procedure appears to get
off sync on the server ....This code is meant to try
to work around the problem simply by "retrying". This
need to be reproduced and fixed.
}
FGDSLibrary.isc_dsql_prepare(StatusVector, TRHandle, #FHandle, 0,
PByte(FProcessedSQL.Text), Database.SQLDialect, nil);
Call(FGDSLibrary.isc_dsql_execute2(StatusVector, TRHandle,
#FHandle, Database.SQLDialect, FSQLParams.AsXSQLDA,
FSQLRecord.AsXSQLDA), True);
end
else
IBDataBaseError; // go ahead and raise the lock conflict
end;
end
and the error message about unprepared statement is raised exactly upon the second execution isc_dsql_execute2(...), so - maybe such second try is not necessary and we can raise Exception IBDataBaseError whenever the fetch_res is not 0? Maybe someone knows why Jeff introduced such second call and what bugs this second call tried to solve?
It appears, that Delphi XE 10.2 code makes the second call only in the specific case:
if (fetch_res = isc_bad_stmt_handle) then
And that makes the erroneous second call rare enough to solve the problem in my question. So, the solution is to replace the initial general condition (fetch_res <> isc_lock_conflict) with the more specific condition (fetch_res = isc_bad_stmt_handle).
I am using Delphi (2009, never mind) with IBX and I am trying to execute simple code:
TestSQL.ExecQuery;
Before this code I have checked (and it can be seen in debugger watches as well) that TestSQL.Transaction.InTransaction is True. Nevertheless the exception is raised:
EIBInterBaseError with message 'invalid transaction handle (expecting explicit transaction start)'
So, there is no another solution than to execute the code:
TestSQL.Transaction.StartTransaction;
TestSQL.ExecQuery;
Now the other exception is raised:
EIBClientError with message 'Transaction is active'
Complete dead end? Delphi has code:
procedure TIBTransaction.CheckInTransaction;
begin
if FStreamedActive and (not InTransaction) then
Loaded;
if (FHandle = nil) then
IBError(ibxeNotInTransaction, [nil]);
end;
and it means that the transaction requirement is determined not only by InTransaction but by private variable FStreamedActive as well. So - the transaction control is way more complex? How can I impact FStreamedActive? What is the solution? My test code is part to lengthier code but I wonder how I can break down the inner status of transaction state?
I found the solution - TestSQL.Database was unintentionally different from TestSQL.Transaction.DefaultDatabase. And that manifested in such a strange error message. It is quite strange that IBX allow at all those databases to be different.
I'm facing difficulty to find a correct way to get errors on ApplyUpdates method, using FireDAC in memory (CachedUpdates).
Here is my scenario, a master-detail relationship, compounded by:
1 TFDConnection
2 TFDQuery
2 TDataSource
1 TFDSchemaAdapter
Both queries are setted as CachedUpdates and are linked to FDSchemaAdapter.
The FDQuery2 (detail) is linked with the master by MasterSource property. MasterFields and IndexFieldNames are setted as "idMaster". The property FetchOptions.DetailCascade is also checked.
I also have a button to perform the apply:
try
FDConnection1.StartTransaction;
FDSchemaAdapter1.ApplyUpdates(0);
FDQuery1.CommitUpdates;
FDQuery2.CommitUpdates;
FDConnection1.Commit;
except on E: Exception do
begin
FDConnection1.Rollback;
raise Exception.CreateFmt('Something went wrong. Error: %s', [E.Message]);
end;
end;
Everything is working fine so far.
The problem occurs when my database throw an exception, such a constraint violation. The exception is not raising. Consequently, my transaction is not 'rollbacked'.
ps: I'm using Delphi XE7 and Firebird 2.5
As the documentation states:
ApplyUpdates returns the number of errors it encountered. Based on
this return value and the setting of AMaxErrors successfully, applied
updates are removed from the centralized change log. If the update
process is aborted before all updates are applied, any unapplied
updates remain in the change log.
ApplyUpdates does not raise an
exception. Instead, the application should review erroneous records
using Reconcile and the OnReconcileRow event handler or the
FilterChanges and RowError properties for each dataset. For more
details, read "Reviewing errors" at Caching Updates.
So... you should not be expecting an exception but you should be checking the value returned by ApplyUpdates to decide if you can commit or handle errors.
I am getting the following error:
2013-11-14 11:57:33,994 [TestScheduler_QuartzSchedulerThread] ERROR Common.Loggi
ng.Factory.AbstractLogger.Error(:0) - An error occurred while scanning for the n
ext trigger to fire.
Quartz.JobPersistenceException: Couldn't acquire next trigger: Cannot insert the
value NULL into column 'SCHED_TIME', table 'quartz.dbo.QRTZ_FIRED_TRIGGERS'; co
lumn does not allow nulls. INSERT fails.
The statement has been terminated. ---> System.Data.SqlClient.SqlException: Cann
ot insert the value NULL into column 'SCHED_TIME', table 'quartz.dbo.QRTZ_FIRED_
TRIGGERS'; column does not allow nulls. INSERT fails.
The statement has been terminated.
I am using the example from HERE and I think I need to understand how jobs work with ADO.Net Jobstore better. My code works perfectly with RAMJobStore. Is there something else I have to do to get ADO to scan for triggers?
Turns out when I looked closer at the errors it was referencing the older version of Quartz.net.
I have used Inserts, selects, updates, deleted without problem all over the program but for some reason this specific section causes it to except and not run the SQL I send it.
I am trying to "UPDATE SectionTable(AreaID) VALUES ('+IntToStr(ActClient.AreaID)+') WHERE SectionID='+IntToStr(iCount)"
The section with the ID "iCount" exists deffinately. The ActClient.AreaID is "2" and its overwriting null data in the "SectionTable" table.
What is the problem here?
OpenDatabase(slDb);
sltb:=sldb.GetTable('SELECT * FROM SectionTable WHERE SectionID='+IntToStr(iCount));
OutputDebugString(PAnsiChar(sltb.FieldAsString(sltb.FieldIndex['SectionID'])+sltb.FieldAsString(sltb.FieldIndex['Gender'])+sltb.FieldAsString(sltb.FieldIndex['CompetitionID'])));
sSQL := 'UPDATE SectionTable(AreaID) VALUES ('+IntToStr(ActClient.AreaID)+') WHERE SectionID='+IntToStr(iCount);
sldb.ExecSQL(sSQL);
CloseDatabase(slDb);
I get this error message appear when this is ran.
---------------------------
Debugger Exception Notification
---------------------------
Project CompetitionServer.exe raised exception class ESQLiteException with message 'Error executing SQL.
Error [1]: SQL error or missing database.
"UPDATE SectionTable(AreaID) VALUES (2) WHERE SectionID=2": near "(": syntax error'. Process stopped. Use Step or Run to continue.
---------------------------
OK Help
---------------------------
UPDATE table SET column = expression, column = expression WHERE predicates