Fixed Access Violation when setting Sort Fields in SQLite3 DB

Code samples and contributions from users for ZeosLib's DBOs of version 6.x

Moderators: gto, cipto_kh, EgonHugeist, mdaems

Post Reply
BytePlayer
Fresh Boarder
Fresh Boarder
Posts: 24
Joined: 21.09.2012, 10:13

Fixed Access Violation when setting Sort Fields in SQLite3 DB

Post by BytePlayer »

unit ZDbcCache;

I was getting an access violation when I set the SortIndexFields value to two fields in a table. I tracked it down to the function CompareUnicodeCLob_Asc and discovered it was happening only when it was trying to compare a field with itself. I added an extra check to verify if the two pointers being passed were the same (shown bracketed in {KJS Added} through {KJS END ADD} which seems to solve the problem.

However, it does imply that the sort is not as efficient as it could be as it really shouldn't be comparing two copies of the same field.

Code: Select all

function CompareUnicodeCLob_Asc(const Null1, Null2: Boolean; const V1, V2): Integer;
var
  Blob1, Blob2: IZBlob;
  {$IFDEF MSWINDOWS}
  ValuePtr1, ValuePtr2: Pointer;
  {$ENDIF}
begin
{KJS ADDED}
if (PPointer(V1)^=PPointer(V2)^) then
   begin
      result:=0;
      exit;
   end;
{KJS END ADD}
  Result := NullsCompareMatrix[Null1, Null2];
  if Result = BothNotNull then
  begin
    // Both values not null
    Blob1 := IZBlob(PPointer(V1)^);
    Blob2 := IZBlob(PPointer(V2)^);
    Result := NullsCompareMatrix[(Blob1 = nil) or (Blob1.IsEmpty), (Blob2 = nil) or (Blob2.IsEmpty)];
    if Result <> BothNotNull then Exit;
    if Blob1.IsClob and Blob2.IsClob then
    begin
      {$IFDEF MSWINDOWS}
      ValuePtr1 := Blob1.GetPWideChar;
      ValuePtr2 := Blob2.GetPWideChar;
      SetLastError(0);
        Result := CompareStringW(LOCALE_USER_DEFAULT, 0,
          ValuePtr1, Blob1.Length, ValuePtr2, Blob2.Length) - 2{CSTR_EQUAL};
      end;
      if GetLastError <> 0 then RaiseLastOSError;
      {$ELSE}
        {$IFDEF UNICODE}
        Result := AnsiCompareStr(Blob1.GetUnicodeString, Blob2.GetUnicodeString);
        {$ELSE}
        Result := WideCompareStr(Blob1.GetUnicodeString, Blob2.GetUnicodeString);
        {$ENDIF}
      {$ENDIF}
    end
    else
      Result := ZMemLComp(Blob1.GetBuffer, Blob2.GetBuffer, Max(Blob1.Length, Blob2.Length));
  end;
end;
marsupilami
Platinum Boarder
Platinum Boarder
Posts: 1918
Joined: 17.01.2011, 14:17

Re: Fixed Access Violation when setting Sort Fields in SQLite3 DB

Post by marsupilami »

Hello BytePlayer,

I am not 100% sure what to make of this.... I don't see immediately where an access violation should happen in the old code. Could you maybe provide a working example? This also helps me in adding a test to the test suites, so we can make sure we don't get that problem again.

Regarding the code:
using "if Blob1.IsClob and Blob2.IsClob then" seems kinda redundant to me because "CompareUnicodeCLob_Asc" should never be used on binary data. Even though SQLite disagrees with us about how to use fields...

Best regards,

Jan
Post Reply