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 -
This commit is contained in:
joost 2007-03-11 20:06:37 +00:00
parent 9054139d26
commit de59f58291

View File

@ -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;