View Issue Details

IDProjectCategoryView StatusLast Update
0004230JEDI VCL00 JVCL Componentspublic2008-10-14 02:29
ReporterNazgulAssigned Toobones 
PrioritynormalSeverityfeatureReproducibilityN/A
Status resolvedResolutionfixed 
Product Version3.32 
Target VersionFixed in Version3.36 
Summary0004230: Sort on non-data fields in TJvMemoryData
DescriptionThis patch allows TJvMemoryData to sort data on fields that are not of type fkData.
Additional InformationCheck out the attached patch file.
TagsNo tags attached.

Activities

2007-09-13 06:44

 

JvMemoryDataSet.pas.patch (3,924 bytes)
--- E:/bds4/Imports/jvcl/run/__history/JvMemoryDataset.pas.~1~	Wed Nov 29 19:13:00 2006
+++ E:/bds4/Imports/jvcl/run/JvMemoryDataset.pas	Thu Sep 13 13:50:32 2007
@@ -130,7 +130,7 @@
     function AddRecord: TJvMemoryRecord;
     function InsertRecord(Index: Integer): TJvMemoryRecord;
     function FindRecordID(ID: Integer): TJvMemoryRecord;
-    procedure CreateIndexList(const FieldNames: string);
+    procedure CreateIndexList(const FieldNames: WideString); 
     procedure FreeIndexList;
     procedure QuickSort(L, R: Integer; Compare: TCompareRecords);
     procedure Sort;
@@ -1960,6 +1960,10 @@
 procedure TJvMemoryData.SortOnFields(const FieldNames: string = '';
   CaseInsensitive: Boolean = True; Descending: Boolean = False);
 begin 
+  // Post the table before sorting
+  if State in dsEditModes then
+    Post;
+
   if FieldNames <> '' then
   	CreateIndexList(FieldNames)
   else
@@ -2032,6 +2036,7 @@
 function TJvMemoryData.CompareRecords(Item1, Item2: TJvMemoryRecord): Integer;
 var
   Data1, Data2: PChar;
+  CData1, CData2, Buffer1, Buffer2: array[0..dsMaxStringSize] of Char;
   F: TField;
   I: Integer;
 begin
@@ -2041,24 +2046,50 @@
     for I := 0 to FIndexList.Count - 1 do
     begin
       F := TField(FIndexList[I]);
+      if F.FieldKind = fkData then
+      begin
       Data1 := FindFieldData(Item1.Data, F);
       if Data1 <> nil then
       begin
         Data2 := FindFieldData(Item2.Data, F);
         if Data2 <> nil then
         begin
-          if (Data1[0] <> #0) and (Data2[0] <> #0) then
+            if Boolean(Data1[0]) and Boolean(Data2[0]) then
           begin
             Inc(Data1);
             Inc(Data2);
             Result := CompareFields(Data1, Data2, F.DataType,
               FCaseInsensitiveSort);
           end
-          else
-          if Data1[0] <> #0 then
+            else if Boolean(Data1[0]) then
             Result := 1
+            else if Boolean(Data2[0]) then
+              Result := -1;
+            if FDescendingSort then
+              Result := -Result;
+          end;
+        end;
+        if Result <> 0 then
+          Exit;
+      end
           else
-          if Data2[0] <> #0 then
+      begin
+        FillChar(Buffer1, dsMaxStringSize, #0);
+        FillChar(Buffer2, dsMaxStringSize, #0);
+        RecordToBuffer(Item1, Buffer1);
+        RecordToBuffer(Item2, Buffer2);
+        Move(Buffer1[1 + FRecordSize + F.Offset], CData1, F.DataSize);
+        if CData1 <> nil then
+        begin
+          Move(Buffer2[1 + FRecordSize + F.Offset], CData2, F.DataSize);
+          if CData2 <> nil then
+          begin
+            if Boolean(CData1[0]) and Boolean(CData2[0]) then
+              Result := CompareFields(@CData1, @CData2, F.DataType,
+                FCaseInsensitiveSort)
+            else if Boolean(CData1[0]) then
+              Result := 1
+            else if Boolean(CData2[0]) then
             Result := -1;
           if FDescendingSort then
             Result := -Result;
@@ -2068,12 +2099,12 @@
         Exit;
     end;
   end;
+  end;
   if Result = 0 then
   begin
     if Item1.ID > Item2.ID then
       Result := 1
-    else
-    if Item1.ID < Item2.ID then
+    else if Item1.ID < Item2.ID then
       Result := -1;
     if FDescendingSort then
       Result := -Result;
@@ -2088,7 +2119,7 @@
     Result := False;
 end;
 
-procedure TJvMemoryData.CreateIndexList(const FieldNames: string);
+procedure CreateIndexList(const FieldNames: WideString);
 var
   Pos: Integer;
   F: TField;
@@ -2101,7 +2132,7 @@
   while Pos <= Length(FieldNames) do
   begin
     F := FieldByName(ExtractFieldNameEx(FieldNames, Pos));
-    if (F.FieldKind = fkData) and
+    if {(F.FieldKind = fkData) and} 
       (F.DataType in ftSupported - ftBlobTypes) then
       FIndexList.Add(F)
     else

obones

2007-10-12 08:39

administrator   ~0013937

In which conditions can an user need to sort on "non fkData" fields?

Nazgul

2007-10-16 08:59

reporter   ~0013976

I found my patch quite useful. I think an user may need to sort on fkLookup or fkCalculated fields.

For example, in my application I have a TJvMemoryData that represents invoices. It contains two fkData fields: Amount w/o VAT, and VAT. I also have one fkCalculated field, Amount w/ VAT, which is sum of Amount w/o VAT and VAT. And the users need to sort the dataset on Amount w/ VAT field.

obones

2008-02-21 07:36

administrator   ~0014260

Please send us a patch in a format that TortoiseSVN can understand, based on the current SVN version. The two codes are right now too different for us to integrate this patch.
Thanks in advance

obones

2008-07-23 07:16

administrator   ~0014431

Hello, any news?

Nazgul

2008-07-23 07:42

reporter   ~0014447

How can I check out JvMemoryDataSet.pas? I checked out the entire JVCL repository, but JvMemoryDataSet.pas is not there...

obones

2008-07-23 13:07

administrator   ~0014449

It is in the "run" directory, except that it is spelled this way:

JvMemoryDataset.pas

There is not capital s.

Nazgul

2008-07-24 01:52

reporter   ~0014453

I can't find the "run" directory.

It is probably created during the installation. But I don't want to overwrite my my current installation of jvcl with the svn version. I need to use the stable version.

obones

2008-07-24 02:04

administrator   ~0014454

No, it is not created during installation. It is right there, at the root of the directory where you installed the JVCL.

obones

2008-07-24 02:06

administrator   ~0014455

https://jvcl.svn.sourceforge.net/svnroot/jvcl/trunk/jvcl/run/

Nazgul

2008-07-24 02:45

reporter   ~0014456

Oh, I've just found out that I've accidentaly checked out jcl instead of jvcl ;-)

Stupid, stupid me. I am sorry for the confusion.

The link to "Web SVN" on the main JVCL page is broken. On the downloads page two more links to the svn repository are broken, too.

Nevertheless, now I have the head revision of JvMemoryDataset.pas, so I will merge my update, test it and create a patch for svn.

Nazgul

2008-10-05 12:03

reporter   ~0014752

Here is the patch for the latest version of Jvcl. I have tested it and it worked fine for me.

2008-10-05 12:03

 

JvMemoryDataSet2.pas.patch (4,545 bytes)
Index: JvMemoryDataset.pas
===================================================================
--- JvMemoryDataset.pas	(revision 11937)
+++ JvMemoryDataset.pas	(working copy)
@@ -137,7 +137,7 @@
     function AddRecord: TJvMemoryRecord;
     function InsertRecord(Index: Integer): TJvMemoryRecord;
     function FindRecordID(ID: Integer): TJvMemoryRecord;
-    procedure CreateIndexList(const FieldNames: string);
+    procedure CreateIndexList(const FieldNames: WideString);
     procedure FreeIndexList;
     procedure QuickSort(L, R: Integer; Compare: TCompareRecords);
     procedure Sort;
@@ -2006,6 +2006,10 @@
 procedure TJvMemoryData.SortOnFields(const FieldNames: string = '';
   CaseInsensitive: Boolean = True; Descending: Boolean = False);
 begin
+  // Post the table before sorting
+  if State in dsEditModes then
+    Post;
+
   if FieldNames <> '' then
     CreateIndexList(FieldNames)
   else
@@ -2078,6 +2082,7 @@
 function TJvMemoryData.CompareRecords(Item1, Item2: TJvMemoryRecord): Integer;
 var
   Data1, Data2: {$IFDEF COMPILER12_UP}PByte{$ELSE}PChar{$ENDIF COMPILER12_UP};
+  CData1, CData2, Buffer1, Buffer2: array[0..dsMaxStringSize] of Char;
   F: TField;
   I: Integer;
 begin
@@ -2087,31 +2092,58 @@
     for I := 0 to FIndexList.Count - 1 do
     begin
       F := TField(FIndexList[I]);
-      Data1 := FindFieldData(Item1.Data, F);
-      if Data1 <> nil then
+      if F.FieldKind = fkData then
       begin
-        Data2 := FindFieldData(Item2.Data, F);
-        if Data2 <> nil then
+        Data1 := FindFieldData(Item1.Data, F);
+        if Data1 <> nil then
         begin
-          if (Data1[0] <> {$IFDEF COMPILER12_UP}0{$ELSE}#0{$ENDIF COMPILER12_UP}) and (Data2[0] <> {$IFDEF COMPILER12_UP}0{$ELSE}#0{$ENDIF COMPILER12_UP}) then
+          Data2 := FindFieldData(Item2.Data, F);
+          if Data2 <> nil then
           begin
-            Inc(Data1);
-            Inc(Data2);
-            Result := CompareFields(Data1, Data2, F.DataType,
-              FCaseInsensitiveSort);
-          end
-          else
-          if Data1[0] <> {$IFDEF COMPILER12_UP}0{$ELSE}#0{$ENDIF COMPILER12_UP} then
-            Result := 1
-          else
-          if Data2[0] <> {$IFDEF COMPILER12_UP}0{$ELSE}#0{$ENDIF COMPILER12_UP} then
-            Result := -1;
-          if FDescendingSort then
-            Result := -Result;
+            if Boolean(Data1[0]) and Boolean(Data2[0]) then
+            begin
+              Inc(Data1);
+              Inc(Data2);
+              Result := CompareFields(Data1, Data2, F.DataType,
+                FCaseInsensitiveSort);
+            end
+            else if Boolean(Data1[0]) then
+              Result := 1
+            else if Boolean(Data2[0]) then
+              Result := -1;
+            if FDescendingSort then
+              Result := -Result;
+          end;
         end;
+        if Result <> 0 then
+          Exit;
+      end
+      else
+      begin
+        FillChar(Buffer1, dsMaxStringSize, #0);
+        FillChar(Buffer2, dsMaxStringSize, #0);
+        RecordToBuffer(Item1, Buffer1);
+        RecordToBuffer(Item2, Buffer2);
+        Move(Buffer1[1 + FRecordSize + F.Offset], CData1, F.DataSize);
+        if CData1 <> nil then
+        begin
+          Move(Buffer2[1 + FRecordSize + F.Offset], CData2, F.DataSize);
+          if CData2 <> nil then
+          begin
+            if Boolean(CData1[0]) and Boolean(CData2[0]) then
+              Result := CompareFields(@CData1, @CData2, F.DataType,
+                FCaseInsensitiveSort)
+            else if Boolean(CData1[0]) then
+              Result := 1
+            else if Boolean(CData2[0]) then
+              Result := -1;
+            if FDescendingSort then
+              Result := -Result;
+          end;
+        end;
+        if Result <> 0 then
+          Exit;
       end;
-      if Result <> 0 then
-        Exit;
     end;
   end;
   if Result = 0 then
@@ -2134,7 +2166,7 @@
     Result := False;
 end;
 
-procedure TJvMemoryData.CreateIndexList(const FieldNames: string);
+procedure TJvMemoryData.CreateIndexList(const FieldNames: WideString);
 var
   Pos: Integer;
   F: TField;
@@ -2147,7 +2179,7 @@
   while Pos <= Length(FieldNames) do
   begin
     F := FieldByName(ExtractFieldNameEx(FieldNames, Pos));
-    if (F.FieldKind = fkData) and (F.DataType in ftSupported - ftBlobTypes) then
+    if {(F.FieldKind = fkData) and }(F.DataType in ftSupported - ftBlobTypes) then
       FIndexList.Add(F)
     else
       ErrorFmt(SFieldTypeMismatch, [F.DisplayName]);

obones

2008-10-14 02:28

administrator   ~0014857

Thanks, this is now in SVN

Issue History

Date Modified Username Field Change
2007-09-13 06:44 Nazgul New Issue
2007-09-13 06:44 Nazgul File Added: JvMemoryDataSet.pas.patch
2007-10-12 08:39 obones Note Added: 0013937
2007-10-12 08:39 obones Status new => feedback
2007-10-16 08:59 Nazgul Note Added: 0013976
2008-02-21 07:36 obones Note Added: 0014260
2008-07-23 07:16 obones Note Added: 0014431
2008-07-23 07:42 Nazgul Note Added: 0014447
2008-07-23 13:07 obones Note Added: 0014449
2008-07-24 01:52 Nazgul Note Added: 0014453
2008-07-24 02:04 obones Note Added: 0014454
2008-07-24 02:06 obones Note Added: 0014455
2008-07-24 02:45 Nazgul Note Added: 0014456
2008-10-05 12:03 Nazgul Note Added: 0014752
2008-10-05 12:03 Nazgul File Added: JvMemoryDataSet2.pas.patch
2008-10-14 02:28 obones Status feedback => resolved
2008-10-14 02:28 obones Fixed in Version => Daily / SVN
2008-10-14 02:28 obones Resolution open => fixed
2008-10-14 02:28 obones Assigned To => obones
2008-10-14 02:28 obones Note Added: 0014857