Selaa lähdekoodia

Patch from Luiz Americo:
* Publish previously missing events
* Remove not necessary fields
* Add CheckBrowseMode for Locate, Lookup, ApplyUpdates
* General cleanup

git-svn-id: trunk@6792 -

joost 18 vuotta sitten
vanhempi
commit
de59f58291
1 muutettua tiedostoa jossa 64 lisäystä ja 69 poistoa
  1. 64 69
      packages/fcl-db/src/sqlite/customsqliteds.pas

+ 64 - 69
packages/fcl-db/src/sqlite/customsqliteds.pas

@@ -23,8 +23,8 @@ unit customsqliteds;
 
 {$Mode ObjFpc}
 {$H+}
-{ $Define DEBUG}
-{ $Define DEBUGACTIVEBUFFER}
+{.$Define DEBUG_SQLITEDS}
+{.$Define DEBUGACTIVEBUFFER}
 
 interface
 
@@ -81,7 +81,6 @@ type
     {$endif}
     FInternalActiveBuffer: PDataRecord;
     FInsertBookmark: PDataRecord;
-    FBufferSize: Integer;
     FExpectedAppends: Integer;
     FExpectedDeletes: Integer;
     FExpectedUpdates: Integer;
@@ -109,7 +108,6 @@ type
     FUpdatedItems: TFPList;
     FAddedItems: TFPList;
     FDeletedItems: TFPList;
-    FOrphanItems: TFPList;
     FReturnCode: Integer;
     FSqliteHandle: Pointer;
     FDataAllocated: Boolean;
@@ -126,6 +124,7 @@ type
     procedure GetSqliteHandle;
     function GetSqliteVersion: String; virtual; abstract;
     procedure BuildLinkedList; virtual; abstract;
+    procedure FreeItem(AItem: PDataRecord);
     procedure DisposeLinkedList;
     procedure SetDetailFilter;
     procedure MasterChanged(Sender: TObject);
@@ -176,9 +175,9 @@ type
     function CompareBookmarks(Bookmark1, Bookmark2: TBookmark): Longint; override;
     function GetFieldData(Field: TField; Buffer: Pointer): Boolean; override;
     function GetFieldData(Field: TField; Buffer: Pointer; NativeFormat: Boolean): Boolean; override;
-    function Locate(const KeyFields: string; const KeyValues: Variant; Options: TLocateOptions) : boolean; override;   
-    function LocateNext(const KeyFields: string; const KeyValues: Variant; Options: TLocateOptions) : boolean;
-    function Lookup(const KeyFields: string; const KeyValues: Variant; const ResultFields: string): Variant;{$ifndef ver2_0_0}override;{$endif}
+    function Locate(const KeyFields: string; const KeyValues: Variant; Options: TLocateOptions) : Boolean; override;
+    function LocateNext(const KeyFields: string; const KeyValues: Variant; Options: TLocateOptions) : Boolean;
+    function Lookup(const KeyFields: string; const KeyValues: Variant; const ResultFields: string): Variant;override;
     // Additional procedures
     function ApplyUpdates: Boolean;
     function CreateTable: Boolean;
@@ -242,8 +241,12 @@ type
     property AfterDelete;
     property BeforeScroll;
     property AfterScroll;
+    property BeforeRefresh;
+    property AfterRefresh;
     property OnDeleteError;
     property OnEditError;
+    property OnNewRecord;
+    property OnPostError;
   end;
   
   function Num2SqlStr(APChar: PChar): String;
@@ -334,7 +337,7 @@ begin
   Move(Buffer,(NewRow+FRowSize)^,Count);
   FActiveItem^.Row[FFieldIndex]:=NewRow;    
   StrDispose(FFieldRow);
-  {$ifdef DEBUG}
+  {$ifdef DEBUG_SQLITEDS}
   WriteLn('##TDSStream.Write##');
   WriteLn('  FPosition(Before): ',FPosition);
   WriteLn('  FRowSize(Before): ',FRowSize);
@@ -358,7 +361,7 @@ begin
   Move((FFieldRow+FPosition)^,Buffer,BytesToMove);
   Inc(FPosition,BytesToMove);
   Result:=BytesToMove;  
-  {$ifdef DEBUG}
+  {$ifdef DEBUG_SQLITEDS}
   WriteLn('##TDSStream.Read##');
   WriteLn('  Bytes requested: ',Count);
   WriteLn('  Bytes moved: ',BytesToMove);
@@ -370,12 +373,9 @@ end;
 // TCustomSqliteDataset override methods
 
 function TCustomSqliteDataset.AllocRecordBuffer: PChar;
-var
-  APointer:Pointer;
 begin
-  APointer := AllocMem(FBufferSize);
-  PDataRecord(APointer^):=FBeginItem;
-  Result:=APointer;
+  Result := AllocMem(SizeOf(PPDataRecord));
+  PDataRecord(Pointer(Result)^):=FBeginItem;
 end;
 
 constructor TCustomSqliteDataset.Create(AOwner: TComponent);
@@ -396,10 +396,8 @@ begin
   FMasterLink.OnMasterDisable:=@MasterDisabled;
   FIndexFieldList:=TList.Create;
   BookmarkSize := SizeOf(Pointer);
-  FBufferSize := SizeOf(PPDataRecord);
   FUpdatedItems:= TFPList.Create;
   FAddedItems:= TFPList.Create;
-  FOrphanItems:= TFPList.Create;
   FDeletedItems:= TFPList.Create;
   FSqlList:=TStringList.Create;
   inherited Create(AOwner);
@@ -444,7 +442,6 @@ begin
   FUpdatedItems.Destroy;
   FAddedItems.Destroy;
   FDeletedItems.Destroy;
-  FOrphanItems.Destroy;
   FMasterLink.Destroy;
   FIndexFieldList.Destroy;
   FSqlList.Destroy;
@@ -519,41 +516,30 @@ end;
 procedure TCustomSqliteDataset.DisposeLinkedList;
 var
   TempItem:PDataRecord;
-  Counter,I:Integer;
+  i:Integer;
 begin
   //Todo: insert debug info
   //Todo: see if FDataAllocated is still necessary
   FDataAllocated:=False;
   TempItem:=FBeginItem^.Next;
-  //Todo: see if is necessary to check if TempItem is nil (aparently is not)
-  if TempItem <> nil then
-    while TempItem^.Next <> nil do
-    begin
-      //Todo: Add procedure to Dispose and Free a Row ?
-      for Counter:= 0 to FRowCount - 1 do
-        StrDispose(TempItem^.Row[Counter]);  
-      FreeMem(TempItem^.Row,FRowBufferSize);
-      TempItem:=TempItem^.Next;
-      Dispose(TempItem^.Previous);
-    end; 
-  
+  while TempItem^.Next <> nil do
+  begin
+    TempItem:=TempItem^.Next;
+    FreeItem(TempItem^.Previous);
+  end; 
+
+  //Dispose Deleted Items
+  //Directly access list pointer since the index check is already done in the loop
+  for i:= 0 to FDeletedItems.Count - 1 do
+    FreeItem(PDataRecord(FDeletedItems.List^[i]));
+
   //Dispose FBeginItem.Row
   FreeMem(FBeginItem^.Row,FRowBufferSize);
     
-  //Dispose cache item
-  for Counter:= 0 to FRowCount - 1 do
-    StrDispose(FCacheItem^.Row[Counter]);
+  //Dispose cache item row
+  for i:= 0 to FRowCount - 1 do
+    StrDispose(FCacheItem^.Row[i]);
   FreeMem(FCacheItem^.Row,FRowBufferSize);
-
-  //Dispose OrphanItems
-  for Counter:= 0 to FOrphanItems.Count - 1 do
-  begin
-    TempItem:=PDataRecord(FOrphanItems[Counter]);
-    for I:= 0 to FRowCount - 1 do
-      StrDispose(TempItem^.Row[I]);  
-    FreeMem(TempItem^.Row,FRowBufferSize);
-    Dispose(TempItem);  
-  end;     
 end;
 
 procedure TCustomSqliteDataset.FreeRecordBuffer(var Buffer: PChar);
@@ -683,14 +669,14 @@ end;
 
 function TCustomSqliteDataset.GetRecordSize: Word;
 begin
-  Result := FBufferSize; //??
+  Result := SizeOf(PPDataRecord); //??
 end;
 
 procedure TCustomSqliteDataset.InternalAddRecord(Buffer: Pointer; DoAppend: Boolean);
 var
   NewItem: PDataRecord;
 begin
-  {$ifdef DEBUG}
+  {$ifdef DEBUG_SQLITEDS}
   if PPDataRecord(Buffer)^ <> FCacheItem then
     DatabaseError('PPDataRecord(Buffer) <> FCacheItem - Problem',Self);
   {$endif}
@@ -727,7 +713,6 @@ begin
   FAddedItems.Clear;
   FUpdatedItems.Clear;
   FDeletedItems.Clear;
-  FOrphanItems.Clear;
   FRecordCount:=0;
 end;
 
@@ -749,18 +734,10 @@ var
   TempItem:PDataRecord;
   ValError,TempInteger:Integer;
 begin
-  If FRecordCount = 0 then
+  if FRecordCount = 0 then
     Exit;
   Dec(FRecordCount);
   TempItem:=PPDataRecord(ActiveBuffer)^;
-  // Remove from changed list
-  FUpdatedItems.Remove(TempItem);
-  if FAddedItems.Remove(TempItem) = -1 then
-    FDeletedItems.Add(TempItem);
-  //Todo: see if FOrphanItems is necessary:
-  //  in ApplyUpdates a check could be done
-  //  to avoid "delete" the AddedItems
-  FOrphanItems.Add(TempItem);
   TempItem^.Next^.Previous:=TempItem^.Previous;
   TempItem^.Previous^.Next:=TempItem^.Next;
   if FCurrentItem = TempItem then
@@ -777,6 +754,12 @@ begin
     if (ValError = 0) and (TempInteger = (FNextAutoInc - 1)) then
       Dec(FNextAutoInc);
   end;    
+  // Update item lists
+  FUpdatedItems.Remove(TempItem);
+  if FAddedItems.Remove(TempItem) = -1 then
+    FDeletedItems.Add(TempItem)
+  else
+    FreeItem(TempItem);
 end;
 
 procedure TCustomSqliteDataset.InternalEdit;
@@ -909,6 +892,7 @@ var
   TempItem:PDataRecord;
 begin
   Result:=nil;
+  CheckBrowseMode;
   // Currently ignore options
   AFieldList:=TList.Create;
   try
@@ -953,7 +937,7 @@ begin
   finally
     AFieldList.Destroy;
   end;
-  {$ifdef DEBUG}
+  {$ifdef DEBUG_SQLITEDS}
   writeln('##TCustomSqliteDataset.FindRecordItem##');
   writeln('  KeyFields: ',keyfields);
   writeln('  KeyValues: ',keyvalues);
@@ -996,12 +980,22 @@ begin
   FSqliteHandle:=InternalGetHandle;
 end;
 
-function TCustomSqliteDataset.Locate(const KeyFields: string; const KeyValues: Variant; Options: TLocateOptions) : boolean;
+procedure TCustomSqliteDataset.FreeItem(AItem: PDataRecord);
+var
+  i: Integer;
+begin
+  for i:= 0 to FRowCount - 1 do
+    StrDispose(AItem^.Row[i]);
+  FreeMem(AItem^.Row,FRowBufferSize);
+  Dispose(AItem);
+end;
+
+function TCustomSqliteDataset.Locate(const KeyFields: string; const KeyValues: Variant; Options: TLocateOptions) : Boolean;
 begin
   Result:=FindRecordItem(FBeginItem^.Next,KeyFields,KeyValues,Options,True) <> nil;  
 end;
   
-function TCustomSqliteDataset.LocateNext(const KeyFields: string; const KeyValues: Variant; Options: TLocateOptions) : boolean;
+function TCustomSqliteDataset.LocateNext(const KeyFields: string; const KeyValues: Variant; Options: TLocateOptions) : Boolean;
 begin
   Result:=FindRecordItem(PPDataRecord(ActiveBuffer)^^.Next,KeyFields,KeyValues,Options,True) <> nil;
 end;
@@ -1040,7 +1034,6 @@ end;
 procedure TCustomSqliteDataset.SetExpectedDeletes(AValue:Integer);
 begin
   FDeletedItems.Capacity:=AValue;
-  FOrphanItems.Capacity:=AValue;  
 end;  
 
 procedure TCustomSqliteDataset.SetFieldData(Field: TField; Buffer: Pointer;
@@ -1155,7 +1148,7 @@ end;
 procedure TCustomSqliteDataset.MasterChanged(Sender: TObject);
 begin
   SetDetailFilter;
-  {$ifdef DEBUG}
+  {$ifdef DEBUG_SQLITEDS}
   writeln('##TCustomSqliteDataset.MasterChanged##');
   writeln('  SQL used to filter detail dataset:');
   writeln('  ',FSql);
@@ -1244,7 +1237,9 @@ function TCustomSqliteDataset.ApplyUpdates:Boolean;
 var
   iFields,iItems,StatementsCounter:Integer;
   SqlTemp,WhereKeyNameEqual,ASqlLine,TemplateStr:String;
+  TempItem: PDataRecord;
 begin
+  CheckBrowseMode;
   if not UpdatesPending then
   begin
     Result:=True;
@@ -1255,7 +1250,7 @@ begin
   begin
     StatementsCounter:=0;
     WhereKeyNameEqual:=' WHERE '+Fields[FPrimaryKeyNo].FieldName+' = ';
-    {$ifdef DEBUG}
+    {$ifdef DEBUG_SQLITEDS}
     WriteLn('##TCustomSqliteDataset.ApplyUpdates##');
     if FPrimaryKeyNo = FAutoIncFieldNo then
       WriteLn('  Using an AutoInc field as primary key');
@@ -1268,8 +1263,10 @@ begin
       TemplateStr:='DELETE FROM '+FTableName+WhereKeyNameEqual;
     for iItems:= 0 to FDeletedItems.Count - 1 do
     begin
+      TempItem:=PDataRecord(FDeletedItems.List^[iItems]);
       SqlTemp:=SqlTemp+(TemplateStr+
-        StrPas(PDataRecord(FDeletedItems[iItems])^.Row[FPrimaryKeyNo])+';');
+        StrPas(TempItem^.Row[FPrimaryKeyNo])+';');
+      FreeItem(TempItem);
       inc(StatementsCounter);
       //ApplyUpdates each 400 statements
       if StatementsCounter = 400 then
@@ -1312,9 +1309,7 @@ begin
     begin
       TemplateStr:='INSERT INTO '+FTableName+ ' (';
       for iFields:= 0 to Fields.Count - 2 do
-      begin
         TemplateStr:=TemplateStr + Fields[iFields].FieldName+',';
-      end; 
       TemplateStr:= TemplateStr+Fields[Fields.Count - 1].FieldName+') VALUES (';
     end;  
     for iItems:= 0 to FAddedItems.Count - 1 do
@@ -1339,7 +1334,7 @@ begin
       end;  
     end;  
     SqlTemp:=SqlTemp+'COMMIT;';
-    {$ifdef DEBUG}
+    {$ifdef DEBUG_SQLITEDS}
     writeln('  SQL: ',SqlTemp);
     {$endif}  
    FAddedItems.Clear;
@@ -1348,7 +1343,7 @@ begin
    FReturnCode:=SqliteExec(PChar(SqlTemp),nil,nil);
    Result:= FReturnCode = SQLITE_OK;
   end;  
-  {$ifdef DEBUG}
+  {$ifdef DEBUG_SQLITEDS}
     writeln('  Result: ',Result);
   {$endif}   
 end;    
@@ -1363,7 +1358,7 @@ var
   SqlTemp:String;
   i:Integer;
 begin
-  {$ifdef DEBUG}
+  {$ifdef DEBUG_SQLITEDS}
   writeln('##TCustomSqliteDataset.CreateTable##');
   if ATableName = '' then
     WriteLn('  TableName Not Set');
@@ -1411,7 +1406,7 @@ begin
         SqlTemp:=SqlTemp+ ' , ';
     end;
     SqlTemp:=SqlTemp+');';
-    {$ifdef DEBUG}
+    {$ifdef DEBUG_SQLITEDS}
     writeln('  SQL: ',SqlTemp);
     {$endif}
     ExecSQL(SqlTemp);
@@ -1443,6 +1438,7 @@ var
 begin
   if not Assigned(Callback) then
     DatabaseError('Callback parameter not set',Self);
+  CheckBrowseMode;
   if rsDeleted in RecordStates then
     with FDeletedItems do
     for i:= 0 to Count - 1 do
@@ -1476,7 +1472,6 @@ begin
   FAddedItems.Clear;
   FUpdatedItems.Clear;
   FDeletedItems.Clear;
-  FOrphanItems.Clear;
   //Reopen
   BuildLinkedList;               
   FCurrentItem:=FBeginItem;