From 9aa6ea2255307b0492c684e498c867ccafa3b141 Mon Sep 17 00:00:00 2001
From: blikblum <blikblum@idefix.freepascal.org>
Date: Sun, 18 Oct 2015 18:53:47 +0000
Subject: [PATCH] Implement OnFilterRecord

git-svn-id: trunk@32093 -
---
 packages/fcl-db/src/sqlite/customsqliteds.pas | 92 ++++++++++++-------
 1 file changed, 61 insertions(+), 31 deletions(-)

diff --git a/packages/fcl-db/src/sqlite/customsqliteds.pas b/packages/fcl-db/src/sqlite/customsqliteds.pas
index 33fe54725c..7acdc98c36 100644
--- a/packages/fcl-db/src/sqlite/customsqliteds.pas
+++ b/packages/fcl-db/src/sqlite/customsqliteds.pas
@@ -109,6 +109,7 @@ type
     {$endif}
     FInternalActiveBuffer: PDataRecord;
     FInsertBookmark: PDataRecord;
+    FFilterBuffer: TRecordBuffer;
     FOnCallback: TSqliteCallback;
     FMasterLink: TMasterDataLink;
     FIndexFieldNames: String;
@@ -176,6 +177,7 @@ type
     procedure DoBeforeClose; override;
     procedure DoAfterInsert; override;
     procedure DoBeforeInsert; override;
+    procedure DoFilterRecord(var Acceptable: Boolean); virtual;
     procedure FreeRecordBuffer(var Buffer: TRecordBuffer); override;
     procedure GetBookmarkData(Buffer: TRecordBuffer; Data: Pointer); override;
     function GetBookmarkFlag(Buffer: TRecordBuffer): TBookmarkFlag; override;
@@ -578,6 +580,13 @@ begin
   inherited DoBeforeInsert;
 end;
 
+procedure TCustomSqliteDataset.DoFilterRecord(var Acceptable: Boolean);
+begin
+  Acceptable := True;
+  if Assigned(OnFilterRecord) then
+    OnFilterRecord(Self, Acceptable);
+end;
+
 destructor TCustomSqliteDataset.Destroy;
 begin
   inherited Destroy;
@@ -746,10 +755,14 @@ begin
   else
     FieldOffset := FieldDefs.Count + FCalcFieldList.IndexOf(Field);
 
-  if not (State in [dsCalcFields, dsInternalCalc]) then
-    FieldRow := PPDataRecord(ActiveBuffer)^^.Row[FieldOffset]
-  else
-    FieldRow := PPDataRecord(CalcBuffer)^^.Row[FieldOffset];
+  case State of
+    dsCalcFields, dsInternalCalc:
+      FieldRow := PPDataRecord(CalcBuffer)^^.Row[FieldOffset];
+    dsFilter:
+      FieldRow := PPDataRecord(FFilterBuffer)^^.Row[FieldOffset];
+    else
+      FieldRow := PPDataRecord(ActiveBuffer)^^.Row[FieldOffset];
+  end;
 
   Result := FieldRow <> nil;  
   if Result and (Buffer <> nil) then //supports GetIsNull
@@ -789,31 +802,46 @@ begin
 end;
 
 function TCustomSqliteDataset.GetRecord(Buffer: TRecordBuffer; GetMode: TGetMode; DoCheck: Boolean): TGetResult;
+var
+  Acceptable: Boolean;
+  SaveState: TDataSetState;
 begin
   Result := grOk;
-  case GetMode of
-    gmPrior:
-      if (FCurrentItem^.Previous = FBeginItem) or (FCurrentItem = FBeginItem) then
-        Result := grBOF
-      else
-        FCurrentItem:=FCurrentItem^.Previous;
-    gmCurrent:
-      if (FCurrentItem = FBeginItem) or (FCurrentItem = FEndItem) then
-         Result := grError;
-    gmNext:
-      if (FCurrentItem = FEndItem) or (FCurrentItem^.Next = FEndItem) then
-        Result := grEOF
-      else
-        FCurrentItem := FCurrentItem^.Next;
-  end; //case
-  if Result = grOk then
-  begin
-    PDataRecord(Pointer(Buffer)^) := FCurrentItem;
-    FCurrentItem^.BookmarkFlag := bfCurrent;
-    GetCalcFields(Buffer);
-  end
-    else if (Result = grError) and DoCheck then
-      DatabaseError('No records found', Self);
+  repeat
+    Acceptable := True;
+    case GetMode of
+      gmPrior:
+        if (FCurrentItem^.Previous = FBeginItem) or (FCurrentItem = FBeginItem) then
+          Result := grBOF
+        else
+          FCurrentItem:=FCurrentItem^.Previous;
+      gmCurrent:
+        if (FCurrentItem = FBeginItem) or (FCurrentItem = FEndItem) then
+           Result := grError;
+      gmNext:
+        if (FCurrentItem = FEndItem) or (FCurrentItem^.Next = FEndItem) then
+          Result := grEOF
+        else
+          FCurrentItem := FCurrentItem^.Next;
+    end; //case
+    if Result = grOk then
+    begin
+      PDataRecord(Pointer(Buffer)^) := FCurrentItem;
+      FCurrentItem^.BookmarkFlag := bfCurrent;
+      GetCalcFields(Buffer);
+      if Filtered then
+      begin
+        FFilterBuffer := Buffer;
+        SaveState := SetTempState(dsFilter);
+        DoFilterRecord(Acceptable);
+        if (GetMode = gmCurrent) and not Acceptable then
+          Result := grError;
+        RestoreState(SaveState);
+      end;
+    end
+      else if (Result = grError) and DoCheck then
+        DatabaseError('No records found', Self);
+  until (Result <> grOK) or Acceptable;
 end;
 
 function TCustomSqliteDataset.GetRecordCount: Integer;
@@ -1573,7 +1601,7 @@ begin
   FMasterLink.DataSource := Value;
 end;
 
-procedure TCustomSqliteDataset.ExecSQL(const ASQL: String);
+procedure TCustomSqliteDataset.ExecSQL(const ASql: String);
 begin
   if FSqliteHandle = nil then
     GetSqliteHandle;
@@ -1831,7 +1859,8 @@ begin
     Result := False;
 end;
 
-procedure TCustomSqliteDataset.ExecCallback(const ASQL: String; UserData: Pointer = nil);
+procedure TCustomSqliteDataset.ExecCallback(const ASql: String;
+  UserData: Pointer);
 var
   CallbackInfo: TCallbackInfo;
 begin
@@ -1913,12 +1942,13 @@ begin
     (FAddedItems.Count > 0) or (FDeletedItems.Count > 0);
 end;
 
-function TCustomSqliteDataset.QuickQuery(const ASQL: String): String;
+function TCustomSqliteDataset.QuickQuery(const ASql: String): String;
 begin
   Result := QuickQuery(ASQL, nil, False);
 end;
 
-function TCustomSqliteDataset.QuickQuery(const ASQL: String; const AStrList: TStrings): String;
+function TCustomSqliteDataset.QuickQuery(const ASql: String;
+  const AStrList: TStrings): String;
 begin
   Result := QuickQuery(ASQL, AStrList, False)
 end;