Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2010-06

Firebird stored procedure exceptions generate access violation

16 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Jim

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
Michael Van Canneyt
to Jim
Jim wrote 143 lines
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)

It might be worth putting all parameters in a record definition and pass the record to your function. That makes the procedure declaration somewhat more manageable and understandable. (and definitely more efficent as well).

Then, there is an access violation in your code:
Try to get a stack trace, we can then tell where the access violation occured, maybe it will tell us a little more.

Michael.

Jim
to Michael Van Canneyt
Michael Van Canneyt wrote
On Sat, 5 Jun 2010, Jim wrote:

<snip>

Show quoted text 20 lines
> 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) It might be worth putting all parameters in a record definition and pass the record to your function. That makes the procedure declaration somewhat more manageable and understandable. (and definitely more efficent as well). Then, there is an access violation in your code: Try to get a stack trace, we can then tell where the access violation occured, maybe it will tell us a little more. Michael.

Ok, I'll have a go at doing that... I'll get back to the list.

Regards, jb
Jim
to Michael Van Canneyt: It might be worth putting all parameters in a record definition and pass the record to…
Michael Van Canneyt wrote
On Sat, 5 Jun 2010, Jim wrote:

<snip>

Show quoted text 18 lines
> 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) It might be worth putting all parameters in a record definition and pass the record to your function. That makes the procedure declaration somewhat more manageable and understandable. (and definitely more efficent as well). Then, there is an access violation in your code: Try to get a stack trace, we can then tell where the access violation occured, maybe it will tell us a little more.

I've not yet looked into converting the procedure call parameters into a record.
However, using gdb I got the following backtrace:
gdb flocate
break fpc_raiseexception
=>gives Cannot access memory at address 0xc800
run c:\windows\system32 => passing the directory for flocate to search in. ... snip a lot of my program's debug output...
Debug: 5-6-2010 11:54:30: SaveDirectoryEntry: going to add parameters for insert query (nmwcdclsx64.dll)
Debug: 5-6-2010 11:54:30: SaveDirectoryEntry: insert query code done. (nmwcdclsx64.dll)
Debug: 5-6-2010 11:54:30: SaveDirectoryEntry: going to add parameters for insert query (NOISE.CHS)

Program received signal SIGSEGV, Segmentation fault. 0x000000010000ad7d in FINALIZE$_DATEUTILS ()
(gdb) backtrace
#0 0x000000010000ad7d in FINALIZE$_DATEUTILS ()
#1 0x0000000005d73f80 in ?? ()
#2 0x00000000012baf10 in ?? ()
#3 0x00000000012baf10 in ?? ()
#4 0x000000010000715c in FINALIZE$_DATEUTILS ()
#5 0x0000000000010a70 in ?? ()
#6 0x0000000077c38f15 in ?? ()
#7 0x0000000000010000 in ?? ()
#8 0x0000000005d73f80 in ?? ()
#9 0x000000000102ef00 in ?? ()
#10 0x00000001000531b0 in FINALIZE$_DATEUTILS ()
#11 0x0000000000000000 in ?? ()

Hope this is what you're looking for...

regards,
jb

Michael Van Canneyt
to Jim
Jim wrote 54 lines
On 5-6-2010 10:47, Michael Van Canneyt wrote: > On Sat, 5 Jun 2010, Jim wrote: <snip> >> 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) > > It might be worth putting all parameters in a record definition and pass > the > record to your function. That makes the procedure declaration somewhat more > manageable and understandable. (and definitely more efficent as well). > > Then, there is an access violation in your code: > Try to get a stack trace, we can then tell where the access violation > occured, maybe it will tell us a little more. I've not yet looked into converting the procedure call parameters into a record. However, using gdb I got the following backtrace: gdb flocate break fpc_raiseexception =>gives Cannot access memory at address 0xc800 run c:\windows\system32 => passing the directory for flocate to search in. ... snip a lot of my program's debug output... Debug: 5-6-2010 11:54:30: SaveDirectoryEntry: going to add parameters for insert query (nmwcdclsx64.dll) Debug: 5-6-2010 11:54:30: SaveDirectoryEntry: insert query code done. (nmwcdclsx64.dll) Debug: 5-6-2010 11:54:30: SaveDirectoryEntry: going to add parameters for insert query (NOISE.CHS) Program received signal SIGSEGV, Segmentation fault. 0x000000010000ad7d in FINALIZE$_DATEUTILS () (gdb) backtrace #0 0x000000010000ad7d in FINALIZE$_DATEUTILS () #1 0x0000000005d73f80 in ?? () #2 0x00000000012baf10 in ?? () #3 0x00000000012baf10 in ?? () #4 0x000000010000715c in FINALIZE$_DATEUTILS () #5 0x0000000000010a70 in ?? () #6 0x0000000077c38f15 in ?? () #7 0x0000000000010000 in ?? () #8 0x0000000005d73f80 in ?? () #9 0x000000000102ef00 in ?? () #10 0x00000001000531b0 in FINALIZE$_DATEUTILS () #11 0x0000000000000000 in ?? () Hope this is what you're looking for...

It is, but it doesn't give the expected output.
Are you using a UDF ?

Michael.

Jim
to Michael Van Canneyt
Michael Van Canneyt wrote 25 lines
On Sat, 5 Jun 2010, Jim wrote: > On 5-6-2010 10:47, Michael Van Canneyt wrote: >> On Sat, 5 Jun 2010, Jim wrote: > <snip> > Program received signal SIGSEGV, Segmentation fault. > 0x000000010000ad7d in FINALIZE$_DATEUTILS () > (gdb) backtrace > #0 0x000000010000ad7d in FINALIZE$_DATEUTILS () > #1 0x0000000005d73f80 in ?? () > #2 0x00000000012baf10 in ?? () > #3 0x00000000012baf10 in ?? () > #4 0x000000010000715c in FINALIZE$_DATEUTILS () > #5 0x0000000000010a70 in ?? () > #6 0x0000000077c38f15 in ?? () > #7 0x0000000000010000 in ?? () > #8 0x0000000005d73f80 in ?? () > #9 0x000000000102ef00 in ?? () > #10 0x00000001000531b0 in FINALIZE$_DATEUTILS () > #11 0x0000000000000000 in ?? () > > Hope this is what you're looking for... It is, but it doesn't give the expected output. Are you using a UDF ? Michael.

Yes, I am using a Firebird UDF for debugging, but it's on a different machine (Linux server). I just got rid of it in the newest revision on bitbucket (which probably also fixes database creation using Flamerobin
- seems FlameRobin has a bug in generating metadata DDL for views).

I'll get the newest 32 and 64 bit Lazarus snapshots with FPC 2.4.1.

Then change the function call to use records, compile and test.

By the way, I also get a ton of memory leaks while running the code.

I'd really love to build an embedded Firebird version of the tool, but I don't seem to manage that. Well, I'll get to that later...

Thanks for the help so far; if you need more details, let me know...

Regards, jb
Michael Van Canneyt
to Jim
Jim wrote 31 lines
On 5-6-2010 12:23, Michael Van Canneyt wrote: > On Sat, 5 Jun 2010, Jim wrote: >> On 5-6-2010 10:47, Michael Van Canneyt wrote: >>> On Sat, 5 Jun 2010, Jim wrote: >> <snip> >> Program received signal SIGSEGV, Segmentation fault. >> 0x000000010000ad7d in FINALIZE$_DATEUTILS () >> (gdb) backtrace >> #0 0x000000010000ad7d in FINALIZE$_DATEUTILS () >> #1 0x0000000005d73f80 in ?? () >> #2 0x00000000012baf10 in ?? () >> #3 0x00000000012baf10 in ?? () >> #4 0x000000010000715c in FINALIZE$_DATEUTILS () >> #5 0x0000000000010a70 in ?? () >> #6 0x0000000077c38f15 in ?? () >> #7 0x0000000000010000 in ?? () >> #8 0x0000000005d73f80 in ?? () >> #9 0x000000000102ef00 in ?? () >> #10 0x00000001000531b0 in FINALIZE$_DATEUTILS () >> #11 0x0000000000000000 in ?? () >> >> Hope this is what you're looking for... > > It is, but it doesn't give the expected output. Are you using a UDF ? > > Michael. Yes, I am using a Firebird UDF for debugging, but it's on a different machine (Linux server). I just got rid of it in the newest revision on bitbucket (which probably also fixes database creation using Flamerobin - seems FlameRobin has a bug in generating metadata DDL for views).

Is the firebird UDF written in fpc ?

Show quoted text 9 lines
I'll get the newest 32 and 64 bit Lazarus snapshots with FPC 2.4.1. Then change the function call to use records, compile and test. By the way, I also get a ton of memory leaks while running the code. I'd really love to build an embedded Firebird version of the tool, but I don't seem to manage that. Well, I'll get to that later...

Well, I've succesfully used embedded firebird with FPC, so that part should work. But I didn't use exceptions in Firebird, and also no UDF, so these are 2 unknowns for me.

Maybe there is some special handling required for firebird exceptions, although that would surprise me. Normally I'd simply expect this to be a special error code, and the message of the exception as the error message...

Michael.

Jim
to Michael Van Canneyt
Michael Van Canneyt wrote 8 lines
On Sun, 6 Jun 2010, Jim wrote: > On 5-6-2010 12:23, Michael Van Canneyt wrote: >> On Sat, 5 Jun 2010, Jim wrote: >>> On 5-6-2010 10:47, Michael Van Canneyt wrote: >>>> On Sat, 5 Jun 2010, Jim wrote: >>> <snip> Is the firebird UDF written in fpc ?
Yep, but the error still happens even if I strip out the UDF - which
I've done now.
Here's the source code for the debug UDF anyway - without some comments:
{$IFDEF FPC}
// Compiler constants for the FreePascal compiler.
  {$MODE OBJFPC}// Needed for the Result := construct
  {$SMARTLINK ON}// Try to slim down resulting binary. Seems to work
only on Windows at the moment. Apparently doesn't work on dlls
  {$PACKRECORDS C} // Try packrecords c to pack bytes just the way c
does it. Doesn't seem to have any effect, but let's leave it in.
  {$IFDEF WINDOWS}
  {$VERSION 1.0} // DLL version number
  {$ENDIF}
{$ENDIF}
library fbdebug;
{$IFDEF FPC}
uses
  Classes,
  SysUtils;
{$ENDIF}
  function ib_util_malloc(Bytes: integer): pointer; cdecl; external
'ib_util';
  function debug(Message, DestinationFile: PChar): longint; cdecl; export;
    // Appends Message to File. Returns 0 if succesful.
    // 73 if file system error (todo: lookup FreeBSD EX_CANTCREAT
sysexits exit code)
    // longint=4 bytes, signed. We don't use unsigned, because
    // Firebird can't handle that at the moment.
  var
    OutputFile: TFileStream;
    RightNow: String;
  const
    LineFeed = #13#10;
  begin
    RightNow:=DateTimeToStr(Now)+':';
    Result := 73; //Default failure code
    if DestinationFile  '' then
    begin
      if FileExists(DestinationFile) then
      begin
        OutputFile := TFileStream.Create(DestinationFile,
fmOpenReadWrite or fmShareDenyWrite);
        OutputFile.Seek(0, soFromEnd);
      end
      else
      begin
        OutputFile :=
          TFileStream.Create(DestinationFile, fmCreate or fmOpenWrite or
fmShareDenyWrite);
      end;
      try
        OutputFile.Write(RightNow[1], Length(RightNow));
        OutputFile.Write(Message^, Length(Message));
        OutputFile.Write(LineFeed[1], Length(Linefeed));
        Result := 0;
      finally
        OutputFile.Free;
      end; //try
    end //if outputfile
    else //No outputfile given
    begin
      Result := 65; //equivalent to EX_DATAERR in FreeBSD
    end;
   {$IFDEF DEBUG}
    writeln('debug: message: ', Message, ' to file: ', OutputFile);
    writeln('Result code: ', Result);
   {$ENDIF}
  end;
exports
  debug Name 'debug';
begin
end.
Well, I've succesfully used embedded firebird with FPC, so that part should work. But I didn't use exceptions in Firebird, and also no UDF, so these are 2 unknowns for me.

Well, as long as you're there and willing to help ;) - for embedded I have to copy over the dlls etc. Tried it for win 64; was able to connect to the database using isql.exe so assume I've got the proper dlls set.

Next, my db access unit uses these database units: sqldb {queries, db access}
ibconnection {Firebird access};
and in the implementation section it uses:
ibase60dyn {for embedded firebird declaration}
DB {for parameter types};

In my db setup code, I tried to do this:
  FUseEmbedded := true;
  UseEmbeddedFirebird := FUseEmbedded; //know this option is deprecated,
but can't get embedded to work
  FDBHost := ''; //empty for embedded;
  FDBPort := 3050; //Default port for Firebird is 3050; maybe 0 for
embedded?
  FDBDatabase := 'flocate'; //for embedded, specify database filename
  //for normal db: 'flocate'; //use an alias on firebird server for easy
management
  FDBUser := 'SYSDBA';
  FDBPassword := 'masterkey';
  if false = false then
  begin
    DBParams := TStringList.Create;
    DBParams.Add('port=' + IntToStr(FDBPort));
  end;

If I set the port to either 3050 or 0, I get an error: EControlC/Control-C hit
If I don't add the port to the DBParams when using embedded:

  if FUseEmbedded = false then

I get an access violation.
I'm using the 64 bit Firebird client version 2.1.2.18118 (also tried with a 2.5 release candidate)

What am I doing wrong?

Show quoted text 5 lines
Maybe there is some special handling required for firebird exceptions, although that would surprise me. Normally I'd simply expect this to be a special error code, and the message of the exception as the error message...

True, I have some docs regarding Delphi and Firebird exception handling somewhere, I'll look them up...

Jim
to Michael Van Canneyt: Is the firebird UDF written in fpc ? Well, I've succesfully used embedded firebird with…
Michael Van Canneyt wrote 6 lines
Maybe there is some special handling required for firebird exceptions, although that would surprise me. Normally I'd simply expect this to be a special error code, and the message of the exception as the error message... Michael.

Found a pdf detailing exception handling in Firebird and Delphi/IBO here: http://www.ibobjects.com/docs/ti_ErrorHandling.pdf page 20 implies custom exceptions are treated like normal database errors: they generate an SQLCODE (Firebird SQL error code), and an SQLMessage (the message I defined in my custom exception), as well as the ERRCODE/ISC error code (IIRC, internal or more detailed Firebird error code)

Page 22 and further describe Firebird exceptions; page 23 deals with custom/user-defined Firebird exceptions, which I'm using. Apparently the IBO code deals with these kinds of exceptions the same as with normal database exceptions.

Regards, jb
Jim
to Michael Van Canneyt: It might be worth putting all parameters in a record definition and pass the record to…
Michael Van Canneyt wrote
It might be worth putting all parameters in a record definition and pass the record to your function. That makes the procedure declaration somewhat more manageable and understandable. (and definitely more efficent as well).

Progress!

As you suggested, I've converted the code to use a record when passing parameters (fields) to the procedure that calls the insert stored procedure on Firebird.

See http://bitbucket.org/jb/flocate/changesets
commit 60: 9f6694fd910f
(To download: click on the commit message; you get a new page; top right of screen: get source)

(The UDF that used to be on the firebird server has also been gone since revision 59).

Now running
Free Pascal Compiler version 2.4.1 [2010/06/06] for x86_64

1. Compiling for 32 bit:
ppc386.exe flocate.lpr -b -FUoutput\i386-win32\ -FEoutput\i386-win32\ -g -gh -gl -O- -vewnh -TWIN32

2. Compiling for 64 bit:
fpc flocate.lpr -b -FUoutput\x86_64-win64\ -FEoutput\x86_64-win64\ -g -gh -gl -O- -vewnh

3. Running the 32 bit code:
output\i386-win32\flocate c:\windows\system32 1>test32.txt 2>test32err.txt

(In between: delete all table data using a stored procedure: EXECUTE
PROCEDURE CLEARALLDATA; COMMIT; )

4. Running the 64 bit code:
output\x86_64-win64\flocate c:\windows\system32 1>test64.txt 2>test64err.txt

Results:
32 bit:
Debug output shows no memory leaks:
Heap dump by heaptrc unit
392010 memory blocks allocated : 24734813/25968016 392010 memory blocks freed : 24734813/25968016 0 unfreed memory blocks : 0
True heap size : 2457600 (160 used in System startup) True free heap : 2457440

The insert code does bomb on a file:
Debug: 6-6-2010 14:56:03: Database error running insert query (filename: <a filename>). Database error message: : Execute : -Malformed string; Database error code: 335544849
... and it rolls back the transaction as expected. Probably some character set issue as I had set the database character set to UTF8; will set it to none next time...

64 bit:
Debut output shows lots of memory leaks:
Heap dump by heaptrc unit
2282244 memory blocks allocated : 700848239/714843280 2178376 memory blocks freed : 687897476/701626320 103868 unfreed memory blocks : 12950763
True heap size : 31457280 (224 used in System startup) True free heap : 1506976
Should be : 4944992
Call trace for block $00000000060BCF60 size 31
$0000000100045146 TDIRECTORYENTRY__GETEXEINFO, line 403 of directoryentry.pp
$0000000100046150 TDIRECTORYENTRY__READINFO, line 544 of directoryentry.pp
$0000000100046D68 TDIRECTORYENTRY__CREATE, line 781 of directoryentry.pp $000000010003E117 TFILESEARCH__ADDFILETORESULT, line 210 of search.pp $000000010003ECFE TFILESEARCH__SEARCHPERFILTER, line 321 of search.pp $000000010003F003 TFILESEARCH__SEARCH, line 356 of search.pp $0000000100001FBF FLOCATE__DORUN, line 245 of flocate.lpr $000000010003C938
Call trace for block $00000000060C0E70 size 53
$00000001000450D7 TDIRECTORYENTRY__GETEXEINFO, line 401 of directoryentry.pp
$0000000100046150 TDIRECTORYENTRY__READINFO, line 544 of directoryentry.pp
$0000000100046D68 TDIRECTORYENTRY__CREATE, line 781 of directoryentry.pp $000000010003E117 TFILESEARCH__ADDFILETORESULT, line 210 of search.pp $000000010003ECFE TFILESEARCH__SEARCHPERFILTER, line 321 of search.pp $000000010003F003 TFILESEARCH__SEARCH, line 356 of search.pp $0000000100001FBF FLOCATE__DORUN, line 245 of flocate.lpr $000000010003C938

The 64 bit code does return a lot of files from the database (though it's missing e.g. cmd.exe which I'll have to look into). It doesn't crash on the file it crashed on in my original post, possibly because of cleaning the database?

Test run conclusion: same code, different amount of bits=> different results.
I suspect the EXIF code I used may be sensitive to variable type sizes etc. But I'm too much of a newbie to tell.

In any case, the access violation that used to be there doesn't happen any more.

To find out how fpc deals with custom Firebird exceptions, I modified my stored procedure to always call a custom exception regardless of input. And there we go again:
Debug: 6-6-2010 15:21:14: Error running insert query (filename: directoryentry.pp.i). Technical details: Access violation

Debugging in 64 bit:
GNU gdb 6.7.50.20080109-cvs
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
<http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-pc-mingw32"...

warning: A handler for the OS ABI "Cygwin" is not built into this configuration
of GDB. Attempting to continue with the default i386:x86-64 settings. (gdb) break fpc_raiseexception
Cannot access memory at address 0xc800
(gdb) run
...... debug output....
Program received signal SIGSEGV, Segmentation fault. 0x000000010000ad7d in FINALIZE$_DATEUTILS ()
(gdb) backtrace
#0 0x000000010000ad7d in FINALIZE$_DATEUTILS ()
#1 0x0000000001153640 in ?? ()
#2 0x000000000110b950 in ?? ()
#3 0x000000000110b950 in ?? ()
#4 0x000000010000715c in FINALIZE$_DATEUTILS ()
#5 0x0000000000010a70 in ?? ()
#6 0x0000000077488f15 in ?? ()
#7 0x0000000000010000 in ?? ()
#8 0x0000000001153640 in ?? ()
#9 0x000000000102ef10 in ?? ()
#10 0x0000000100052f80 in FINALIZE$_DATEUTILS ()
#11 0x0000000000000000 in ?? ()

Debugging in 32 bit:
GNU gdb 6.8
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
<http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details.
This GDB was configured as "i686-pc-mingw32"...
(gdb) break fpc_raiseexception
Breakpoint 1 at 0x40a9c6
...... debug output....
Breakpoint 1, 0x0040a9c6 in fpc_raiseexception ()
(gdb) backtrace
#0 0x0040a9c6 in fpc_raiseexception ()
#1 0x0043d284 in
IBCONNECTION_TIBCONNECTION_$__CHECKERROR$ANSISTRING$PISC_STATUS () #2 0x0043e9ca in
IBCONNECTION_TIBCONNECTION_$__EXECUTE$TSQLCURSOR$TSQLTRANSACTION$TPARAMS () #3 0x0043ac1a in SQLDB_TCUSTOMSQLQUERY_$__EXECUTE () #4 0x0043b7d9 in SQLDB_TCUSTOMSQLQUERY_$__EXECSQL () #5 0x00437e51 in TFLOCATEDB__SAVEDIRECTORYENTRY (INSERTFIELDS= {COMPUTERNAME = 0x1649fb8 "MARVIN", DATEACCESSED = 40335.475694444445, DATECREATED = 40335.475694444445, DATEMODIFIED = 39282.142569444448, EXECOMPANY = 0x0, EXECOPYRIGHT = 0x0, EXEDESCRIPTION = 0x0, EXEFILEVERSION = 0x0, EXEINTERNALNAME = 0x0, EXEORIGINALFILENAME = 0x0, EXEPRODUCTNAME = 0x0, EXEPRODUCTVERSION =
0x0, EXIFAPERTURE = 0x0, EXIFARTIST = 0x0, EXIFCOMPRESSEDBPP = 0x0, EXIFCOPYRIGHT = 0x0, EXIFDATETIME = -693593, EXIFDATETIMEDIGITIZED = -693593, EXIFDATETIMEORIGINAL = -693593, EXIFEXPOSURE = 0x0, EXIFEXPOSUREPROGRAM = 0x0, EXIFFLASH = 0x0, EXIFFSTOPS = 0x0, EXIFIMAGEDESCRIPTION = 0x0, EXIFISO = 0, EXIFLIGHTSOURCE = 0x0, EXIFMAKE = 0x0, EXIFMAXAPERTURE = 0x0, EXIFMETERINGMETHOD = 0x0, EXIFMETERINGMODE = 0x0, EXIFMODEL = 0x0, EXIFORIENTATION = 0x0, EXIFPIXELXDIMENSION = 0, EXIFPIXELYDIMENSION = 0, EXIFSHUTTERSPEED = 0x0, EXIFSOFTWARE = 0x0, EXIFUSERCOMMENTS = 0x0, EXIFXRESOLUTION = 0, EXIFYRESOLUTION = 0, FILEDESCRIPTION = 0x0, FILENAME = 0x164a078 "fbintl.conf", FILEPATH = 0x16d11e8 "C:\\Users\\jimbeam\\My
Documents\\Lazarus\\flocate\\output\\i386-win32\\intl\\", FILESIZE = 6656, FILETYPE = 0x164d198 "other", MD5HASH = 0x16acbf0 "0304b1526d4db539276853d987159277", MP3ALBUM = 0x0, MP3ARTIST = 0x0, MP3COMMENT = 0x0, MP3GENRE = 0x0, MP3TITLE = 0x0, MP3TRACK = 0, MP3YEAR = 0}, this=0x1651f98)
at flocatedb.pp:484
#6 0x00432cd7 in TDIRECTORYENTRYLIST__SAVETODATABASE (this=0x1649ef0) at directoryentrylist.pp:236
#7 0x0042f359 in TFILESEARCH__SAVETODATABASE (this=0x1649e90) at search.pp:245
#8 0x00401e62 in TFLOCATE__DORUN (this=0x1660fd8) at flocate.lpr:246 #9 0x0042dd54 in CUSTAPP_TCUSTOMAPPLICATION_$__RUN () #10 0x004025ec in main () at flocate.lpr:329

Seems like fpc simply doesn't know how to deal with those exceptions???

Regards, jb
Michael Van Canneyt
to Jim
Jim wrote 8 lines
(gdb) break fpc_raiseexception Breakpoint 1 at 0x40a9c6 ...... debug output.... Breakpoint 1, 0x0040a9c6 in fpc_raiseexception () (gdb) backtrace #0 0x0040a9c6 in fpc_raiseexception () #1 0x0043d284 in IBCONNECTION_TIBCONNECTION_$__CHECKERROR$ANSISTRING$PISC_STATUS ()

OK, this means you've found an error in the error handling code of TIBConnection. Unfortunately, there is not enough info to pinpoint the exact location.

Do you think you can recompile the ibconnection unit with debug info ? (copying to to your project's directory should do the trick)

Michael.

Jim
to Michael Van Canneyt
Michael Van Canneyt wrote 21 lines
On Sun, 6 Jun 2010, Jim wrote: > (gdb) break fpc_raiseexception > Breakpoint 1 at 0x40a9c6 > ...... debug output.... > Breakpoint 1, 0x0040a9c6 in fpc_raiseexception () > (gdb) backtrace > #0 0x0040a9c6 in fpc_raiseexception () > #1 0x0043d284 in > IBCONNECTION_TIBCONNECTION_$__CHECKERROR$ANSISTRING$PISC_STATUS () OK, this means you've found an error in the error handling code of TIBConnection. Unfortunately, there is not enough info to pinpoint the exact location. Do you think you can recompile the ibconnection unit with debug info ? (copying to to your project's directory should do the trick) Michael.

On win32, I get this using a ibconnection unit compiled with -g -gl: (gdb) backtrace
#0 0x0040a9c6 in fpc_raiseexception ()
#1 0x0043d29e in TIBCONNECTION__CHECKERROR (PROCNAME=0x483320 "Execute", STATUS=0x388338, this=0x3a0568) at ibconnection.pp:156 #2 0x0043ec3d in TIBCONNECTION__EXECUTE (CURSOR=0x388320, ATRANSACTION=0x3cf5c28, APARAMS=0x3df0140, this=0x3a0568) at ibconnection.pp:670
#3 0x0043ac1a in SQLDB_TCUSTOMSQLQUERY_$__EXECUTE () #4 0x0043b7d9 in SQLDB_TCUSTOMSQLQUERY_$__EXECSQL () #5 0x00437e51 in TFLOCATEDB__SAVEDIRECTORYENTRY (INSERTFIELDS= {COMPUTERNAME = 0x3196b0 "MARVIN", DATEACCESSED =
40080.684351851851, DATE
... and the rest of the parameters...
#6 0x00432cd7 in TDIRECTORYENTRYLIST__SAVETODATABASE (this=0x3195e8) at directoryentrylist.pp:236
#7 0x0042f359 in TFILESEARCH__SAVETODATABASE (this=0x319588) at search.pp:245
#8 0x00401e62 in TFLOCATE__DORUN (this=0x3383f8) at flocate.lpr:247 #9 0x0042dd54 in CUSTAPP_TCUSTOMAPPLICATION_$__RUN () #10 0x004025ec in main () at flocate.lpr:330

Regards, jb
Jim
to Jim
Jim wrote 45 lines
On 6-6-2010 16:06, Michael Van Canneyt wrote: > > > On Sun, 6 Jun 2010, Jim wrote: >> (gdb) break fpc_raiseexception >> Breakpoint 1 at 0x40a9c6 >> ...... debug output.... >> Breakpoint 1, 0x0040a9c6 in fpc_raiseexception () >> (gdb) backtrace >> #0 0x0040a9c6 in fpc_raiseexception () >> #1 0x0043d284 in >> IBCONNECTION_TIBCONNECTION_$__CHECKERROR$ANSISTRING$PISC_STATUS () > > OK, this means you've found an error in the error handling code of > TIBConnection. Unfortunately, there is not enough info to pinpoint the > exact > location. > > Do you think you can recompile the ibconnection unit with debug info ? > (copying to to your project's directory should do the trick) > > Michael. On win32, I get this using a ibconnection unit compiled with -g -gl: (gdb) backtrace #0 0x0040a9c6 in fpc_raiseexception () #1 0x0043d29e in TIBCONNECTION__CHECKERROR (PROCNAME=0x483320 "Execute", STATUS=0x388338, this=0x3a0568) at ibconnection.pp:156 #2 0x0043ec3d in TIBCONNECTION__EXECUTE (CURSOR=0x388320, ATRANSACTION=0x3cf5c28, APARAMS=0x3df0140, this=0x3a0568) at ibconnection.pp:670 #3 0x0043ac1a in SQLDB_TCUSTOMSQLQUERY_$__EXECUTE () #4 0x0043b7d9 in SQLDB_TCUSTOMSQLQUERY_$__EXECSQL () #5 0x00437e51 in TFLOCATEDB__SAVEDIRECTORYENTRY (INSERTFIELDS= {COMPUTERNAME = 0x3196b0 "MARVIN", DATEACCESSED = 40080.684351851851, DATE ... and the rest of the parameters... #6 0x00432cd7 in TDIRECTORYENTRYLIST__SAVETODATABASE (this=0x3195e8) at directoryentrylist.pp:236 #7 0x0042f359 in TFILESEARCH__SAVETODATABASE (this=0x319588) at search.pp:245 #8 0x00401e62 in TFLOCATE__DORUN (this=0x3383f8) at flocate.lpr:247 #9 0x0042dd54 in CUSTAPP_TCUSTOMAPPLICATION_$__RUN () #10 0x004025ec in main () at flocate.lpr:330

Oops, let me check, I might've traced the wrong database error. Let me set up my fake Firebird custom exception again & get back to you...

Regards, jb
Jim
to Michael Van Canneyt: OK, this means you've found an error in the error handling code of TIBConnection.…
Michael Van Canneyt wrote 18 lines
> (gdb) break fpc_raiseexception > Breakpoint 1 at 0x40a9c6 > ...... debug output.... > Breakpoint 1, 0x0040a9c6 in fpc_raiseexception () > (gdb) backtrace > #0 0x0040a9c6 in fpc_raiseexception () > #1 0x0043d284 in > IBCONNECTION_TIBCONNECTION_$__CHECKERROR$ANSISTRING$PISC_STATUS () OK, this means you've found an error in the error handling code of TIBConnection. Unfortunately, there is not enough info to pinpoint the exact location. Do you think you can recompile the ibconnection unit with debug info ? (copying to to your project's directory should do the trick) Michael.

Hi all,

Recap: accessing Firebird database with custom (Firebird) exceptions, it seems the FPC code crashes on hitting the exception.

Michael Van Canneyt helped me to debug the issues, but I got lost in the complexity, so decided to write a simple Windows32 test program with embedded Firebird test program with custom Firebird exceptions.

I've attempted to compile the ibconnection, sqldb etc units with debugging (-g -gl -gh) and added them to the directory.

Also added the entire Firebird 2.1 embedded environment, and a test database; you can test it with the included isql.exe.

Details in fbembedtest_readme.txt

Compile/test script in compileandtest.bat

I've uploaded it to:
http://bitbucket.org/jb/flocate/issue/5/cant-get-embedded-firebird-to-work the latest attachment is
fbembedtest16June_10.52.zip

Possibly due to my newbie-ness, I can't get embedded Firebird to work;
the connection attempt crashes with another access violation.

Could some kind soul look at it and:
1. Tell me what I'm doing wrong
2. Tell me if there's any documentation on embedded Firebird, and where I can find it.
3. Help me in testing out these custom Firebird exceptions - what I was trying to do in the first place...

Thanks!

jb

Jim
to Jim

On 16-6-2010 11:09, Jim wrote:
<snip>

Show quoted text 10 lines
I've uploaded it to: http://bitbucket.org/jb/flocate/issue/5/cant-get-embedded-firebird-to-work the latest attachment is fbembedtest16June_10.52.zip Possibly due to my newbie-ness, I can't get embedded Firebird to work; the connection attempt crashes with another access violation. Could some kind soul look at it and: 1. Tell me what I'm doing wrong

Sorry all:

Solved: PEBKAC/PICNIC problem as usual.

I assigned a variable that hadn't been initialised as a stringlist to the connection's Params property.

On with the next problem...

thanks,
jb

Jim
to Jim
Show quoted text 12 lines
Sorry all: Solved: PEBKAC/PICNIC problem as usual. I assigned a variable that hadn't been initialised as a stringlist to the connection's Params property. On with the next problem... thanks, jb

Progress & help requested from the experts.

32 bit works, 64 bit doesn't:

32 bit:
The custom Firebird exception stuff as well as embedded Firebird works well on my version of fpc 2.4.1 32 bit on Windows: ...snip output...
*** Insert number 5 again. This shold fail because of the unique index. *** We should get a generic database error.
Debug: 16-6-2010 15:38:50: SaveNumber: going to add parameters for insert query
Debug: 16-6-2010 15:38:50: Database error running insert query. Database error message: : Execute :
-violation of PRIMARY or UNIQUE KEY constraint "NUMBERUNIQUE" on table "NUMBERS
"; Database error code: 335544665
...snip output...
*** Now test our custom Firebird exception by trying to insert 13: Debug: 16-6-2010 15:12:21: SaveNumber: going to add parameters for insert query
Debug: 16-6-2010 15:12:21: Database error running insert query. Database error message: : Execute :
-exception 1
-EXCNOT13
-No, not 13, I can't handle that!
-At trigger 'TRIGCHECK13' line: 7, col: 28; Database error code: 335544517 Debug: 16-6-2010 15:12:21: Parameters were:
BINGONUMBER: *13*
Debug: 16-6-2010 15:12:21: Rolling back transaction. ...snip output...

Uploaded this to bitbucket as fbembedtest16June_15.10.zip http://bitbucket.org/jb/flocate/issue/5/cant-get-embedded-firebird-to-work

64 bit:
1. The code seems to hang somewhere. Do I have to fiddle with integers or longints or whatever they're called?
2. The database error handling that was working in 32 bit is erroneous here (control-c hit - see output below - instead of Database error running insert query. )
Seems like the database layer isn't passing on error messages but something is just dumping a generic error. (My exception handling code distinguishes between database and other errors).

Compiled using 64 bit fpc:
Free Pascal Compiler version 2.4.1 [2010/06/06] for x86_64 Recompiled all .pp files.

Now the program seems to hang in the middle of adding parameters or when
executing the query, possibly somewhere in
    FInsertQuery.Params.ParamByName('BINGONUMBER').AsInteger := BingoNumber;
    try
      FInsertQuery.ExecSQL;

Output:
Debug: 16-6-2010 15:32:49: Starting database setup: Debug: 16-6-2010 15:32:49: SetUp: Connecting to database: Debug: 16-6-2010 15:32:49: DB/Setup/Going to start transaction. Debug: 16-6-2010 15:32:49: Getting query
=============================================================== fbembedtest: information.
Test program for firebird 2.1 embedded database and custom stored procedures.
Please see
fbembedtest_readme.TXT
for details on setting up database etc.
Freeware but no warranties, express or implied.
For full copyright and license, please see the source code. =============================================================== Debug: 16-6-2010 15:32:49: Application started.

*** First, clear any existing numbers out of database: Debug: 16-6-2010 15:32:49: ClearData: going to run query DELETE FROM NUMBERS;

*** Insert number 5. This should work:
Debug: 16-6-2010 15:32:49: SaveNumber: going to add parameters for insert query
Debug: 16-6-2010 15:32:49: SaveNumber: insert query code done.

*** Insert number 5 again. This should fail because of the unique index. *** We should get a generic database error.
Debug: 16-6-2010 15:32:49: SaveNumber: going to add parameters for insert query
Debug: 16-6-2010 15:32:49: Error running insert query. Technical details: Control-C hit
Debug: 16-6-2010 15:32:49: Parameters were:
BINGONUMBER: *5*
Debug: 16-6-2010 15:32:49: SaveNumber: insert query code done.

*** Now test our custom Firebird exception by trying to insert 13: Debug: 16-6-2010 15:32:49: SaveNumber: going to add parameters for insert query

Uploaded to bitbucket as well.