#1 2016-04-18 17:29:17

vaclav
Member
Registered: 2015-02-24
Posts: 4

Problem with WIN32CASE and WIN32NOCASE collations

Functions Utf16SQLCompCase and Utf16SQLCompNoCase provide incorrect result for {$ifdef MSWINDOWS} when one or both input strings are empty (s1Len = 0 and/or s2Len = 0):

  • Utf16SQLCompCase(nonempty, empty) = -2 (should be 1!!! (see WideCompareText))

  • Utf16SQLCompCase(empty, nonempty) = -2 (should be -1!!! (see WideCompareText); fortunately, for SQLite -1 or -2 makes no difference)

  • Utf16SQLCompCase(empty, empty) = -2 (should be 0!!! (see WideCompareText))

Therefore indexes do not reach their value, which is - simply fatal... hmm

  • select * from Table where IndexedField like 'value' => value normally found

  • select * from Table where IndexedField = 'value' => nothing found!!!

I propose the following fix:

function Utf16SQLCompCase(CollateParam: pointer; s1Len: integer; S1: pointer;
    s2Len: integer; S2: pointer) : integer; {$ifndef SQLITE3_FASTCALL}cdecl;{$endif}
{$ifndef MSWINDOWS}
var W1,W2: WideString;
{$endif}
begin
  if (s1Len<=0) and (s2Len<=0) then
    result:=0
  else if s1Len<=0 then
    result:=-1
  else if s2Len<=0 then
    result:=1
  else begin
    {$ifdef MSWINDOWS}
    result := CompareStringW(GetThreadLocale,0,S1,s1len shr 1,S2,s2Len shr 1)-2;
    {$else} // cross-platform but slower version using two temporary WideString
    SetString(W1,PWideChar(S1),s1len shr 1);
    SetString(W2,PWideChar(S2),s2len shr 1);
    result := WideCompareStr(W1,W2); // use OS string comparison API
    {$endif}
  end;
end;
function Utf16SQLCompNoCase(CollateParam: pointer; s1Len: integer; s1: pointer;
    s2Len: integer; s2: pointer) : integer; {$ifndef SQLITE3_FASTCALL}cdecl;{$endif}
{$ifndef MSWINDOWS}
var W1,W2: WideString;
{$endif}
begin
  if (s1Len<=0) and (s2Len<=0) then
    result:=0
  else if s1Len<=0 then
    result:=-1
  else if s2Len<=0 then
    result:=1
  else begin
    {$ifdef MSWINDOWS}
    result := CompareStringW(GetThreadLocale,NORM_IGNORECASE,S1,s1len shr 1,S2,s2Len shr 1)-2;
    {$else} // cross-platform but slower version using two temporary WideString
    SetString(W1,PWideChar(S1),s1len shr 1);
    SetString(W2,PWideChar(S2),s2len shr 1);
    result := WideCompareText(W1,W2); // use OS string comparison API
    {$endif}
  end;
end;

Tested on Delphi 2006 and Windows 10.

Offline

#2 2016-04-18 18:33:36

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,272
Website

Re: Problem with WIN32CASE and WIN32NOCASE collations

Please try http://synopse.info/fossil/info/831c26f0a7

Thanks for the feedback!

Offline

#3 2016-04-18 21:07:36

vaclav
Member
Registered: 2015-02-24
Posts: 4

Re: Problem with WIN32CASE and WIN32NOCASE collations

Thanks, works as expected!

Offline

Board footer

Powered by FluxBB