[fpc-pascal] Firebird stored procedure exceptions generate access violation
Jim
hakkie42 at gmail.com
Sat Jun 5 10:26:47 CEST 2010
Hi all,
Still working on my locate clone at
http://bitbucket.org/jb/flocate/
- download at
http://bitbucket.org/jb/flocate/downloads
Running Free Pascal Compiler version 2.4.1 [2010/06/01] for x86_64 on
Windows.
I've cobbled together some Firebird database code.
If you want to have a more complete overview, I've posted the entire
database unit to
http://pastebin.com/rgpAK91Q
I have connection/transaction/query objects open. The query calls a
stored procedure on the database and has parameters defined... like this
EXECUTE PROCEDURE SPADDFILEDEFAULT ( ' + ':COMPUTERNAME, ' + .... and
a lot of others....
In a loop going through the files I've found on the computer (in
TDirectoryEntryList = class(TFPObjectList) ), I call a procedure
procedure TflocateDB.SaveDirectoryEntry(COMPUTERNAME: string; .... and a
lot of others....
that use the open query, first clear (for luck, I guess ;) then assign
parameters (e.g.
FInsertQuery.Params.ParamByName('COMPUTERNAME').AsString :=
COMPUTERNAME;
FInsertQuery.Params.ParamByName('DATEACCESSED').AsDateTime :=
DATEACCESSED;
Finally I execute the SQL within an try...except block
try
FInsertQuery.ExecSQL;
FTransaction.CommitRetaining;
//todo: this is for testing so we can see what didn't get inserted
//in production, we'd just have one big happy transaction I suppose
except
on E: EIBDatabaseError do
begin
// We would havee committed, so we should be rolling back.
{$IFDEF DEBUG}
Writeln(stderr, 'Debug: ', DateTimeToStr(Now),
': Database error running insert query (filename: ', FILENAME,
'). Database error message: ',
E.Message, '; Database error code: ', E.GDSErrorCode
);
Writeln(stderr, 'Debug: ', DateTimeToStr(Now),
': Parameters were: ');
for DebugCounter := 0 to FInsertQuery.Params.Count - 1 do
begin
Writeln(stderr, FInsertQuery.Params[DebugCounter].Name, ': *',
FInsertQuery.Params[DebugCounter].Value , '*');
end;
Writeln(stderr, 'Debug: ', DateTimeToStr(Now),
': Rolling back transaction.');
{$ENDIF DEBUG}
FTransaction.RollBack;
end;
on E: Exception do
begin
{$IFDEF DEBUG}
Writeln(stderr, 'Debug: ', DateTimeToStr(Now),
': Error running insert query (filename: ',
FILENAME, '). Technical details: ',
E.Message
);
Writeln(stderr, 'Debug: ', DateTimeToStr(Now),
': Parameters were: ');
for DebugCounter := 0 to FInsertQuery.Params.Count - 1 do
begin
Writeln(stderr, FInsertQuery.Params[DebugCounter].Name, ': *',
FInsertQuery.Params[DebugCounter].Value, '*');
end;
{$ENDIF DEBUG}
end; //E: Exception
end; //end of actual execsql block
The stored procedure in Firebird takes all the parameters, looks them up
in the respective tables (e.g. TBLCOMPUTERS), inserts new records if
required, gets the resulting primary keys for dependent tables and
finally inserts all these keys and some more data in a TBLFILES table.
This stored procedure is not faultless yet; sometimes it errors out.
I've implemented multiple custom Firebird exceptions in the stored
procedures like this:
CREATE EXCEPTION SPCOULDNOTFINDVERSIONINFO
'Could not add records: unable to add version information to database';
The SP calls these exceptions when something seriously goes wrong e.g.
SELECT EXEID FROM TBLEXES WHERE EXEFILEVERSION=:exefileversion
AND EXEPRODUCTVERSION=:exeproductversion
INTO :localEXEID;
IF (:localEXEID IS NULL) THEN
BEGIN
/* when we can't add the info */
/* in the related table, we should just abort */
localDUMMY = FBDEBUG('Exception for TBLEXES problems will be
called: SPCOULDNOTFINDVERSIONINFO', '/tmp/test.txt');
... some more debugging stuff...
EXCEPTION SPCOULDNOTFINDVERSIONINFO;
END
When I hit the stored procedure exception mentioned above, my code
doesn't complain, but on the next file and all subsequent files, the
error code in my code indicates I got an access violation.
E.g. my Firebird logging gives:
5-6-10 10:02:07:Exception for TBLEXES problems will be called:
SPCOULDNOTFINDVERSIONINFO
5-6-10 10:02:07:FILENAME :*nmwcdclsx64.dll*
5-6-10 10:02:07:FILEPATH :*C:\windows\system32\*
5-6-10 10:02:07:localEXEID :*<NULL>*
5-6-10 10:02:07:EXECOMPANY :*Nokia*
5-6-10 10:02:07:EXECOPYRIGHT :*Copyright (c)
2002,2003,2004,2005. Nokia. All rights reserved.*
5-6-10 10:02:07:EXEDESCRIPTION :*Wireless Communication
Device Class Installer*
5-6-10 10:02:07:EXEFILEVERSION may not be NULL :*7.1.18.34*
5-6-10 10:02:07:EXEINTERNALNAME :*NMWCDCLSX64*
5-6-10 10:02:07:EXEORIGINALFILENAME :*nmwcdclsx64.dll*
5-6-10 10:02:07:EXEPRODUCTNAME :*<NULL>*
5-6-10 10:02:07:EXEPRODUCTVERSION :*<NULL>*
While the debug output my code generates shows:
Debug: 5-6-2010 10:02:05: SaveDirectoryEntry: going to add parameters
for insert query (nmwcdclsx64.dll)
Debug: 5-6-2010 10:02:05: SaveDirectoryEntry: insert query code done.
(nmwcdclsx64.dll)
Debug: 5-6-2010 10:02:05: SaveDirectoryEntry: going to add parameters
for insert query (<the next file>)
Debug: 5-6-2010 10:02:05: Error running insert query (filename: <the
next file>). Technical details: Access violation
Debug: 5-6-2010 10:02:05: Parameters were:
... and it shows the parameters I've set
In the mean time, I think I know why the stored proc errors out, but I
still think there's something wrong with my FreePascal code ;)
Finally, the question:
What I really want is to get a Firebird SQLCODE error code or some other
details that allow me to figure out whether one of my custom exceptions
get called. Also, it seems something is wrong after the error; although
the objects still seem to exist, the database obviously won't insert
anymore.
How do I get proper error codes and/or fix this code? (Of course,
suggestions on code improvement etc are also welcome)
Thanks in advance,
--
Regards,
jb
More information about the fpc-pascal
mailing list