[yunqa.de] Re: DiSqlite - Intransaction bug?

  • From: Delphi Inspiration <delphi@xxxxxxxx>
  • To: yunqa@xxxxxxxxxxxxx
  • Date: Tue, 05 Jan 2010 17:59:27 +0100

At 17:08 05.01.2010, Clyde England wrote:

>I had removed all uses of TDISQLite3Database.Execute("BEGIN") and replaced 
>with TDISQLite3Database.StartTransaction. However I still ran into the problem 
>(with the original "before fix" code)

Correct. But we did not have a reproducable test case.

>I think I have tracked down the cause and it would appear that the transaction 
>counter is not reset on a close of the database.

Of course. Why did I not think about this back then? Now it all makes sense!

>Shouldn't the counter be reset when you close a database (even though the 
>transaction has not been committed)?
>
>Take for example the following code:
>
>database.open;
>database.starttransaction;
>database.close;
>database.open;
>
>At this point database.intransaction returns true, and if you try to execute 
>database.commit you get my original error. 

Newly opened databases do not have active transaction. So the 
TDISQLite3Database transaction counter should be reset whenever an existing 
instance connects to a database, be it the same one or a new one.

The place to do this is in procedure TDISQLite3Database.DoConnect which 
completely lapsed my attention. With the modified TDISQLite3Database.DoConnect 
below, all your test cases pass. I have updated my test suite accordingly.

procedure TDISQLite3Database.DoConnect;
var
  h: sqlite3_ptr;
  s8: Utf8String;
begin
  if not Assigned(FHandle) then
    begin
      CheckDatabaseName(FDatabaseName);
      s8 := sqlite3_encode_utf8(FDatabaseName);
      try
        Check(sqlite3_open_v2(PUtf8Char(s8), @FHandle, 
          SQLITE_OPEN_READWRITE, nil));
      except
        { On error, close DB and reset handle. }
        on e: ESQLite3 do
          begin
            h := FHandle; FHandle := nil; sqlite3_close(h);
            if e.ErrorCode and $FF = SQLITE_CANTOPEN then
              raise EFOpenError.CreateFmt(SFOpenError,
                [WideExpandFileName(FDatabaseName)])
            else
              raise;
          end;
      else
        h := FHandle; FHandle := nil; sqlite3_close(h);
        raise;
      end;

      FTransactionCount := 0; // Add this line!!!

      {$IFDEF SQLITE_HAS_CODEC}
      if FPassword <> '' then
        Check(sqlite3_key(FHandle, Pointer(FPassword), 
                          Length(FPassword)));
      {$ENDIF SQLITE_HAS_CODEC}
    end;
end;

Ralf  

_______________________________________________
Delphi Inspiration mailing list
yunqa@xxxxxxxxxxxxx
//www.freelists.org/list/yunqa



Other related posts: