You are not logged in.
Hi ab!
Recently we had upgraded from mORMot 2.0.5027 to the latest stable 2.2.6584. Since then, we've encountered an exception in some parts of our code "x.AddSorted() is not allowed with loCreateUniqueIndex: use Add()". This occurs when using generic lists with AddSorted and a custom compare function.
Here is an example, how to reproduce the exception:
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
System.Math,
Mormot.core.collections;
type
TTestRecord = record
Test: Integer;
end;
function SomeComparer(const Item1, Item2): Integer;
begin
Result:=CompareValue(TTestRecord(Item1).Test,TTestRecord(Item2).Test);
end;
var
ListUnderTest: IList<TTestRecord>;
begin
try
ListUnderTest:=Collections.NewPlainList<TTestRecord>([]);
ListUnderTest.Comparer:=SomeComparer;
var RecA:=Default(TTestRecord);
RecA.Test:=321;
var RecB:=Default(TTestRecord);
RecB.Test:=123;
ListUnderTest.AddSorted(RecA);
ListUnderTest.AddSorted(RecB);
for var LoopRec in ListUnderTest do
begin
Writeln(LoopRec.Test);
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
readln;
end.
The output of this console example is:
EIList: TIList<Project1.TTestRecord>.AddSorted() is not allowed with loCreateUniqueIndex: use Add()
We analyzed the cause and believe the check in mormot.core.collections (specifically in TIListParent.DoAddSorted) is incomplete:
function TIListParent.DoAddSorted(const value; wasadded: PBoolean): integer;
begin
if fHasher = nil then // << this check don't consider the compare function
raise EIList.CreateUtf8('%.AddSorted() is not allowed with ' +
'loCreateUniqueIndex: use Add()', [self]);
result := fDynArray.FastLocateOrAddSorted(value, wasadded);
end;
Instead, the check should be:
function TIListParent.DoAddSorted(const value; wasadded: PBoolean): integer;
begin
if (fHasher = nil) and (@fDynArray.compare = nil) then // << consider also the compare function
raise EIList.CreateUtf8('%.AddSorted() is not allowed with ' +
'loCreateUniqueIndex: use Add()', [self]);
result := fDynArray.FastLocateOrAddSorted(value, wasadded);
end;
Many thanks for your time and consideration!
Best regards from Germany
Offline
Notice:
Previously the check was if fHasher<>nil and changed to if fHasher = nil in
commit 51627ba2a2d2b70c9604115cf36cd367c59e1b29.
Maybe it was correct previously?
Last edited by WladiD (2024-09-30 12:49:56)
Offline
You are right: this was a regression.
Please try with
https://github.com/synopse/mORMot2/commit/03c3434d
Thanks a lot Wladi for the detailed report and investigation!
Offline
This works for us.
Thank you so much for your consistently fast and reliable support!
Offline