mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-22 08:29:29 +02:00
* Patch fom Luiz Americo
- Add support to TMemoField - Add RefetchData, TableExists, UpdatesPending methods - Optimize ApplyUpdates when using/creating big datasets - Other fixes/improvements
This commit is contained in:
parent
df057f7550
commit
7b3db009fc
@ -28,7 +28,11 @@ unit sqliteds;
|
||||
|
||||
interface
|
||||
|
||||
uses Classes, SysUtils, Db;
|
||||
uses Classes, SysUtils, Db
|
||||
{$ifdef DEBUG}
|
||||
,Crt
|
||||
{$endif}
|
||||
;
|
||||
|
||||
type
|
||||
PDataRecord = ^DataRecord;
|
||||
@ -40,7 +44,24 @@ type
|
||||
Next: PDataRecord;
|
||||
Previous: PDataRecord;
|
||||
end;
|
||||
|
||||
|
||||
TDSStream = class(TStream)
|
||||
private
|
||||
FActiveItem:PDataRecord;
|
||||
FFieldRow:PChar;
|
||||
FFieldIndex:Integer;
|
||||
FRowSize: Integer;
|
||||
FPosition: Longint;
|
||||
public
|
||||
constructor Create(const ActiveItem: PDataRecord; FieldIndex:Integer);
|
||||
function Write(const Buffer; Count: Longint): Longint; override;
|
||||
function Read(var Buffer; Count: Longint): Longint; override;
|
||||
function Seek(Offset: Longint; Origin: Word): Longint; override;
|
||||
// function Seek(Offset: Int64; Origin: TSeekOrigin): Int64; override;
|
||||
end;
|
||||
|
||||
{ TSqliteDataset }
|
||||
|
||||
TSqliteDataset = class(TDataSet)
|
||||
private
|
||||
FFileName: String;
|
||||
@ -64,8 +85,9 @@ type
|
||||
FSqliteReturnId: Integer;
|
||||
FDataAllocated: Boolean;
|
||||
FSaveOnClose: Boolean;
|
||||
FSaveOnRefetch: Boolean;
|
||||
FComplexSql: Boolean;
|
||||
FSqliteHandle: Pointer;
|
||||
FDBError: PPChar;
|
||||
FUpdatedItems: TList;
|
||||
FAddedItems: TList;
|
||||
FDeletedItems: TList;
|
||||
@ -74,6 +96,7 @@ type
|
||||
procedure DisposeLinkedList;
|
||||
protected
|
||||
function AllocRecordBuffer: PChar; override;
|
||||
function CreateBlobStream(Field: TField; Mode: TBlobStreamMode): TStream; override;
|
||||
procedure FreeRecordBuffer(var Buffer: PChar); override;
|
||||
procedure GetBookmarkData(Buffer: PChar; Data: Pointer); override;
|
||||
function GetBookmarkFlag(Buffer: PChar): TBookmarkFlag; override;
|
||||
@ -110,7 +133,10 @@ type
|
||||
function CreateTable: Boolean;
|
||||
function ExecSQL:Integer;
|
||||
function ExecSQL(ASql:String):Integer;
|
||||
function TableExists: Boolean;
|
||||
procedure RefetchData;
|
||||
function SqliteReturnString: String;
|
||||
function UpdatesPending: Boolean;
|
||||
{$ifdef USE_SQLITEDS_INTERNALS}
|
||||
property BeginItem: PDataRecord read FBeginItem;
|
||||
property EndItem: PDataRecord read FEndItem;
|
||||
@ -118,6 +144,7 @@ type
|
||||
property AddedItems: TList read FAddedItems;
|
||||
property DeletedItems: TList read FDeletedItems;
|
||||
{$endif}
|
||||
property ComplexSql: Boolean read FComplexSql write FComplexSql;
|
||||
property ExpectedAppends: Integer read FExpectedAppends write SetExpectedAppends;
|
||||
property ExpectedUpdates: Integer read FExpectedUpdates write SetExpectedUpdates;
|
||||
property ExpectedDeletes: Integer read FExpectedDeletes write SetExpectedDeletes;
|
||||
@ -126,6 +153,7 @@ type
|
||||
property FileName: String read FFileName write FFileName;
|
||||
property IndexFieldName: String read FIndexFieldName write FIndexFieldName;
|
||||
property SaveOnClose: Boolean read FSaveOnClose write FSaveOnClose;
|
||||
property SaveOnRefetch: Boolean read FSaveOnRefetch write FSaveOnRefetch;
|
||||
property SQL: String read FSql write FSql;
|
||||
property TableName: String read FTableName write FTableName;
|
||||
//property Active;
|
||||
@ -156,7 +184,7 @@ type
|
||||
|
||||
implementation
|
||||
|
||||
uses SQLite;
|
||||
uses SQLite,strutils;
|
||||
|
||||
function GetAutoIncValue(NextValue: Pointer; Columns: Integer; ColumnValues: PPChar; ColumnNames: PPChar): integer; cdecl;
|
||||
var
|
||||
@ -216,11 +244,12 @@ begin
|
||||
begin
|
||||
AType:= ftTime;
|
||||
FieldSize:=SizeOf(TDateTime);
|
||||
end else if (ColumnStr = 'MEMO') then
|
||||
begin
|
||||
AType:= ftMemo;
|
||||
FieldSize:=10;//??
|
||||
end else if (ColumnStr = 'AUTOINC') then
|
||||
begin
|
||||
//Todo: remove this check. do it in open
|
||||
if TSqliteDataset(TheDataset).Tablename = '' then
|
||||
DatabaseError('Sqliteds - AutoInc fields requires Tablename to be set');
|
||||
AType:= ftAutoInc;
|
||||
FieldSize:=SizeOf(Integer);
|
||||
if TSqliteDataset(TheDataset).FAutoIncFieldNo = -1 then
|
||||
@ -234,6 +263,95 @@ begin
|
||||
end;
|
||||
result:=-1;
|
||||
end;
|
||||
|
||||
// TDSStream
|
||||
|
||||
constructor TDSStream.Create(const ActiveItem: PDataRecord; FieldIndex:Integer);
|
||||
begin
|
||||
inherited Create;
|
||||
FPosition:=0;
|
||||
FActiveItem:=ActiveItem;
|
||||
FFieldIndex:=FieldIndex;
|
||||
FFieldRow:=ActiveItem^.Row[FieldIndex];
|
||||
if FFieldRow <> nil then
|
||||
FRowSize:=StrLen(FFieldRow)
|
||||
else
|
||||
FRowSize:=0;
|
||||
end;
|
||||
{
|
||||
function TDSMemoryStream.Seek(Offset: Int64; Origin: TSeekOrigin): Int64;
|
||||
begin
|
||||
Case Origin of
|
||||
soBeginning : FPosition:=Offset;
|
||||
soEnd : FPosition:=FRowSize+Offset;
|
||||
soCurrent : FPosition:=FPosition+Offset;
|
||||
end;
|
||||
Result:=FPosition;
|
||||
end;
|
||||
}
|
||||
function TDSStream.Seek(Offset: Longint; Origin: Word): Longint;
|
||||
begin
|
||||
Case Origin of
|
||||
soFromBeginning : FPosition:=Offset;
|
||||
soFromEnd : FPosition:=FRowSize+Offset;
|
||||
soFromCurrent : FPosition:=FPosition+Offset;
|
||||
end;
|
||||
Result:=FPosition;
|
||||
end;
|
||||
|
||||
function TDSStream.Write(const Buffer; Count: Longint): Longint;
|
||||
var
|
||||
NewRow:PChar;
|
||||
begin
|
||||
Result:=Count;
|
||||
if Count = 0 then
|
||||
Exit;
|
||||
//Todo: see how TDbMemo read/write to field and choose best if order
|
||||
if FPosition = 0 then
|
||||
begin
|
||||
NewRow:=StrAlloc(Count+1);
|
||||
(NewRow+Count)^:=#0;
|
||||
Move(Buffer,NewRow^,Count);
|
||||
end
|
||||
else
|
||||
begin
|
||||
NewRow:=StrAlloc(FRowSize+Count+1);
|
||||
(NewRow+Count+FRowSize)^:=#0;
|
||||
Move(FFieldRow^,NewRow^,FRowSize);
|
||||
Move(Buffer,(NewRow+FRowSize)^,Count);
|
||||
end;
|
||||
FActiveItem^.Row[FFieldIndex]:=NewRow;
|
||||
StrDispose(FFieldRow);
|
||||
FFieldRow:=NewRow;
|
||||
FRowSize:=StrLen(NewRow);
|
||||
Inc(FPosition,Count);
|
||||
{$ifdef DEBUG}
|
||||
WriteLn('Writing a BlobStream');
|
||||
WriteLn('Stream.Size: ',StrLen(NewRow));
|
||||
WriteLn('Stream Value: ',NewRow);
|
||||
WriteLn('FPosition:',FPosition);
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
function TDSStream.Read(var Buffer; Count: Longint): Longint;
|
||||
var
|
||||
BytesToMove:Integer;
|
||||
begin
|
||||
if (FRowSize - FPosition) >= Count then
|
||||
BytesToMove:=Count
|
||||
else
|
||||
BytesToMove:=FRowSize - FPosition;
|
||||
Move((FFieldRow+FPosition)^,Buffer,BytesToMove);
|
||||
Inc(FPosition,BytesToMove);
|
||||
Result:=BytesToMove;
|
||||
{$ifdef DEBUG}
|
||||
WriteLn('Reading a BlobStream');
|
||||
WriteLn('Bytes requested: ',Count);
|
||||
WriteLn('Bytes Moved: ',BytesToMove);
|
||||
WriteLn('Stream.Size: ',FRowSize);
|
||||
WriteLn('Stream Value: ',FFieldRow);
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
// TSqliteDataset override methods
|
||||
|
||||
@ -310,6 +428,7 @@ end;
|
||||
|
||||
constructor TSqliteDataset.Create(AOwner: TComponent);
|
||||
begin
|
||||
//FComplexSql:=False;
|
||||
BookmarkSize := SizeOf(Pointer);
|
||||
FBufferSize := SizeOf(PPDataRecord);
|
||||
FUpdatedItems:= TList.Create;
|
||||
@ -320,10 +439,14 @@ begin
|
||||
FOrphanItems.Capacity:=20;
|
||||
FDeletedItems:= TList.Create;
|
||||
FDeletedItems.Capacity:=20;
|
||||
FSaveOnClose:=False;
|
||||
inherited Create(AOwner);
|
||||
end;
|
||||
|
||||
function TSqliteDataset.CreateBlobStream(Field: TField; Mode: TBlobStreamMode): TStream;
|
||||
begin
|
||||
Result:= TDSStream.Create(PPDataRecord(ActiveBuffer)^,Field.FieldNo - 1);
|
||||
end;
|
||||
|
||||
destructor TSqliteDataset.Destroy;
|
||||
begin
|
||||
inherited Destroy;
|
||||
@ -338,7 +461,7 @@ var
|
||||
TempItem:PDataRecord;
|
||||
Counter,I:Integer;
|
||||
begin
|
||||
//Todo insert debug info
|
||||
//Todo: insert debug info
|
||||
FDataAllocated:=False;
|
||||
//Dispose cache item
|
||||
for Counter:= 0 to FRowCount - 1 do
|
||||
@ -541,6 +664,7 @@ end;
|
||||
procedure TSqliteDataset.InternalDelete;
|
||||
var
|
||||
TempItem:PDataRecord;
|
||||
ValError,TempInteger:Integer;
|
||||
begin
|
||||
If FRecordCount = 0 then
|
||||
Exit;
|
||||
@ -560,10 +684,13 @@ begin
|
||||
else
|
||||
FCurrentItem:= FCurrentItem^.Next;
|
||||
end;
|
||||
// Dec FNextAutoInc
|
||||
// Dec FNextAutoInc (only if deleted item is the last record)
|
||||
if FAutoIncFieldNo <> -1 then
|
||||
if StrToInt(StrPas(TempItem^.Row[FAutoIncFieldNo])) = (FNextAutoInc - 1) then
|
||||
begin
|
||||
Val(StrPas(TempItem^.Row[FAutoIncFieldNo]),TempInteger,ValError);
|
||||
if (ValError = 0) and (TempInteger = (FNextAutoInc - 1)) then
|
||||
Dec(FNextAutoInc);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSqliteDataset.InternalFirst;
|
||||
@ -622,8 +749,12 @@ procedure TSqliteDataset.InternalOpen;
|
||||
begin
|
||||
FAutoIncFieldNo:=-1;
|
||||
if not FileExists(FFileName) then
|
||||
DatabaseError('File '+FFileName+' not found',Self);
|
||||
DatabaseError('TSqliteDataset - File '+FFileName+' not found');
|
||||
if (FTablename = '') and not (FComplexSql) then
|
||||
DatabaseError('TSqliteDataset - Tablename not set');
|
||||
FSqliteHandle:=sqlite_open(PChar(FFileName),0,nil);
|
||||
if FSql = '' then
|
||||
FSql := 'Select * from '+FTableName+';';
|
||||
InternalInitFieldDefs;
|
||||
if DefaultFields then
|
||||
CreateFields;
|
||||
@ -748,77 +879,116 @@ end;
|
||||
|
||||
function TSqliteDataset.ApplyUpdates:Boolean;
|
||||
var
|
||||
CounterFields,CounterItems:Integer;
|
||||
SqlTemp,KeyName:String;
|
||||
Quote:Char;
|
||||
CounterFields,CounterItems,StatementsCounter:Integer;
|
||||
SqlTemp,KeyName,ASqlLine,TemplateStr:String;
|
||||
begin
|
||||
Result:=False;
|
||||
if (FTableName <> '') and (FIndexFieldNo <> -1) then
|
||||
if (FIndexFieldNo <> -1) and not FComplexSql then
|
||||
begin
|
||||
StatementsCounter:=0;
|
||||
KeyName:=Fields[FIndexFieldNo].FieldName;
|
||||
{$ifdef DEBUG}
|
||||
WriteLn('ApplyUpdates called');
|
||||
if FIndexFieldNo = FAutoIncFieldNo then
|
||||
WriteLn('Using an AutoInc field as primary key');
|
||||
WriteLn('IndexFieldName: ',KeyName);
|
||||
WriteLn('IndexFieldNo: ',FIndexFieldNo);
|
||||
{$endif}
|
||||
SqlTemp:='BEGIN TRANSACTION; ';
|
||||
SqlTemp:='BEGIN TRANSACTION;';
|
||||
// Update changed records
|
||||
For CounterItems:= 0 to FUpdatedItems.Count - 1 do
|
||||
if FUpdatedItems.Count > 0 then
|
||||
TemplateStr:='UPDATE '+FTableName+' SET ';
|
||||
for CounterItems:= 0 to FUpdatedItems.Count - 1 do
|
||||
begin
|
||||
SqlTemp:=SqlTemp+'UPDATE '+FTableName+' SET ';
|
||||
ASqlLine:=TemplateStr;
|
||||
for CounterFields:= 0 to Fields.Count - 1 do
|
||||
begin
|
||||
if PDataRecord(FUpdatedItems[CounterItems])^.Row[CounterFields] <> nil then
|
||||
begin
|
||||
if Fields[CounterFields].DataType = ftString then
|
||||
Quote:='"'
|
||||
ASqlLine:=ASqlLine + Fields[CounterFields].FieldName +' = ';
|
||||
if not (Fields[CounterFields].DataType in [ftString,ftMemo]) then
|
||||
ASqlLine:=ASqlLine+StrPas(PDataRecord(FUpdatedItems[CounterItems])^.Row[CounterFields])+ ','
|
||||
else
|
||||
Quote:=' ';
|
||||
SqlTemp:=SqlTemp + Fields[CounterFields].FieldName +' = '+Quote+
|
||||
StrPas(PDataRecord(FUpdatedItems[CounterItems])^.Row[CounterFields])+Quote+' , ';
|
||||
ASqlLine:=ASqlLine+''''+
|
||||
AnsiReplaceStr(StrPas(PDataRecord(FUpdatedItems[CounterItems])^.Row[CounterFields]),'''','''''')+''',';
|
||||
end
|
||||
else
|
||||
SqlTemp:=SqlTemp + Fields[CounterFields].FieldName +' = NULL , ';
|
||||
ASqlLine:=ASqlLine + Fields[CounterFields].FieldName +' = NULL,';
|
||||
end;
|
||||
system.delete(SqlTemp,Length(SqlTemp)-2,2);
|
||||
SqlTemp:=SqlTemp+'WHERE '+KeyName+' = '+StrPas(PDataRecord(FUpdatedItems[CounterItems])^.Row[FIndexFieldNo])+';';
|
||||
//Todo: see if system.delete trunks AnsiString
|
||||
system.delete(ASqlLine,Length(ASqlLine),1);
|
||||
SqlTemp:=SqlTemp + ASqlLine+' WHERE '+KeyName+' = '+StrPas(PDataRecord(FUpdatedItems[CounterItems])^.Row[FIndexFieldNo])+';';
|
||||
inc(StatementsCounter);
|
||||
//ApplyUpdates each 400 statements
|
||||
if StatementsCounter = 400 then
|
||||
begin
|
||||
SqlTemp:=SqlTemp+'END TRANSACTION;';
|
||||
FSqliteReturnId:=sqlite_exec(FSqliteHandle,PChar(SqlTemp),nil,nil,nil);
|
||||
StatementsCounter:=0;
|
||||
SqlTemp:='BEGIN TRANSACTION;';
|
||||
end;
|
||||
end;
|
||||
// Add new records
|
||||
For CounterItems:= 0 to FAddedItems.Count - 1 do
|
||||
// Build TemplateStr
|
||||
if FAddedItems.Count > 0 then
|
||||
begin
|
||||
SqlTemp:=SqlTemp+'INSERT INTO '+FTableName+ ' ( ';
|
||||
TemplateStr:='INSERT INTO '+FTableName+ ' (';
|
||||
for CounterFields:= 0 to Fields.Count - 1 do
|
||||
begin
|
||||
SqlTemp:=SqlTemp + Fields[CounterFields].FieldName;
|
||||
TemplateStr:=TemplateStr + Fields[CounterFields].FieldName;
|
||||
if CounterFields <> Fields.Count - 1 then
|
||||
SqlTemp:=SqlTemp+' , ';
|
||||
TemplateStr:=TemplateStr+',';
|
||||
end;
|
||||
SqlTemp:=SqlTemp+') VALUES ( ';
|
||||
TemplateStr:=TemplateStr+') VALUES (';
|
||||
end;
|
||||
for CounterItems:= 0 to FAddedItems.Count - 1 do
|
||||
begin
|
||||
ASqlLine:=TemplateStr;
|
||||
for CounterFields:= 0 to Fields.Count - 1 do
|
||||
begin
|
||||
if PDataRecord(FAddedItems[CounterItems])^.Row[CounterFields] <> nil then
|
||||
begin
|
||||
if Fields[CounterFields].DataType = ftString then
|
||||
Quote:='"'
|
||||
if not (Fields[CounterFields].DataType in [ftString,ftMemo]) then
|
||||
ASqlLine:=ASqlLine+StrPas(PDataRecord(FAddedItems[CounterItems])^.Row[CounterFields])
|
||||
else
|
||||
Quote:=' ';
|
||||
SqlTemp:=SqlTemp + Quote+ StrPas(PDataRecord(FAddedItems[CounterItems])^.Row[CounterFields])+Quote;
|
||||
ASqlLine:=ASqlLine+''''+
|
||||
AnsiReplaceStr(StrPas(PDataRecord(FAddedItems[CounterItems])^.Row[CounterFields]),'''','''''')+'''';
|
||||
end
|
||||
else
|
||||
SqlTemp:=SqlTemp + 'NULL';
|
||||
ASqlLine:=ASqlLine + 'NULL';
|
||||
//Todo: see if delete ASqline is faster
|
||||
if CounterFields <> Fields.Count - 1 then
|
||||
SqlTemp:=SqlTemp+' , ';
|
||||
ASqlLine:=ASqlLine+',';
|
||||
end;
|
||||
SqlTemp:=SqlTemp+') ;';
|
||||
SqlTemp:=SqlTemp+ASqlLine+');';
|
||||
inc(StatementsCounter);
|
||||
//ApplyUpdates each 400 statements
|
||||
if StatementsCounter = 400 then
|
||||
begin
|
||||
SqlTemp:=SqlTemp+'END TRANSACTION;';
|
||||
FSqliteReturnId:=sqlite_exec(FSqliteHandle,PChar(SqlTemp),nil,nil,nil);
|
||||
StatementsCounter:=0;
|
||||
SqlTemp:='BEGIN TRANSACTION;';
|
||||
end;
|
||||
end;
|
||||
// Delete Items
|
||||
For CounterItems:= 0 to FDeletedItems.Count - 1 do
|
||||
if FDeletedItems.Count > 0 then
|
||||
TemplateStr:='DELETE FROM '+FTableName+ ' WHERE '+KeyName+' = ';
|
||||
for CounterItems:= 0 to FDeletedItems.Count - 1 do
|
||||
begin
|
||||
SqlTemp:=SqlTemp+'DELETE FROM '+FTableName+ ' WHERE '+KeyName+' = '+
|
||||
SqlTemp:=SqlTemp+TemplateStr+
|
||||
StrPas(PDataRecord(FDeletedItems[CounterItems])^.Row[FIndexFieldNo])+';';
|
||||
inc(StatementsCounter);
|
||||
//ApplyUpdates each 400 statements
|
||||
if StatementsCounter = 400 then
|
||||
begin
|
||||
SqlTemp:=SqlTemp+'END TRANSACTION;';
|
||||
FSqliteReturnId:=sqlite_exec(FSqliteHandle,PChar(SqlTemp),nil,nil,nil);
|
||||
StatementsCounter:=0;
|
||||
SqlTemp:='BEGIN TRANSACTION;';
|
||||
end;
|
||||
end;
|
||||
SqlTemp:=SqlTemp+'END TRANSACTION; ';
|
||||
SqlTemp:=SqlTemp+'END TRANSACTION;';
|
||||
{$ifdef DEBUG}
|
||||
writeln('ApplyUpdates Sql: ',SqlTemp);
|
||||
{$endif}
|
||||
@ -846,7 +1016,7 @@ begin
|
||||
{$endif}
|
||||
if (FTableName <> '') and (FieldDefs.Count > 0) then
|
||||
begin
|
||||
FSqliteHandle:= sqlite_open(PChar(FFileName),0,FDBError);
|
||||
FSqliteHandle:= sqlite_open(PChar(FFileName),0,nil);
|
||||
SqlTemp:='CREATE TABLE '+FTableName+' (';
|
||||
for Counter := 0 to FieldDefs.Count-1 do
|
||||
begin
|
||||
@ -870,6 +1040,8 @@ begin
|
||||
SqlTemp:=SqlTemp + ' TIME';
|
||||
ftAutoInc:
|
||||
SqlTemp:=SqlTemp + ' AUTOINC';
|
||||
ftMemo:
|
||||
SqlTemp:=SqlTemp + ' MEMO';
|
||||
else
|
||||
SqlTemp:=SqlTemp + ' VARCHAR';
|
||||
end;
|
||||
@ -888,6 +1060,67 @@ begin
|
||||
Result:=False;
|
||||
end;
|
||||
|
||||
function TSqliteDataset.TableExists: Boolean;
|
||||
var
|
||||
AHandle,vm:Pointer;
|
||||
ColumnNames,ColumnValues:PPChar;
|
||||
AInt:Integer;
|
||||
begin
|
||||
Result:=False;
|
||||
if not (FTableName = '') and FileExists(FFileName) then
|
||||
begin
|
||||
if FSqliteHandle = nil then
|
||||
begin
|
||||
{$ifdef DEBUG}
|
||||
writeln('TableExists - FSqliteHandle=nil : Opening a file');
|
||||
{$endif}
|
||||
AHandle:=sqlite_open(PChar(FFileName),0,nil);
|
||||
end
|
||||
else
|
||||
begin
|
||||
{$ifdef DEBUG}
|
||||
writeln('TableExists - FSqliteHandle<>nil : Using FSqliteHandle');
|
||||
{$endif}
|
||||
AHandle:=FSqliteHandle;
|
||||
end;
|
||||
FSqliteReturnId:=sqlite_compile(AHandle,
|
||||
Pchar('SELECT name FROM SQLITE_MASTER WHERE type = ''table'' AND name LIKE '''+ FTableName+ ''';'),
|
||||
nil,@vm,nil);
|
||||
{$ifdef DEBUG}
|
||||
WriteLn('TableExists.sqlite_compile - SqliteReturnString:',SqliteReturnString);
|
||||
{$endif}
|
||||
FSqliteReturnId:=sqlite_step(vm,@AInt,@ColumnValues,@ColumnNames);
|
||||
{$ifdef DEBUG}
|
||||
WriteLn('TableExists.sqlite_step - SqliteReturnString:',SqliteReturnString);
|
||||
{$endif}
|
||||
Result:=FSqliteReturnId = SQLITE_ROW;
|
||||
sqlite_finalize(vm, nil);
|
||||
if (FSqliteHandle = nil) then
|
||||
sqlite_close(AHandle);
|
||||
end;
|
||||
{$ifdef DEBUG}
|
||||
WriteLn('TableExists ('+FTableName+') Result:',Result);
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
procedure TSqliteDataset.RefetchData;
|
||||
begin
|
||||
//Close
|
||||
if FSaveOnRefetch then
|
||||
ApplyUpdates;
|
||||
if FDataAllocated then
|
||||
DisposeLinkedList;
|
||||
FAddedItems.Clear;
|
||||
FUpdatedItems.Clear;
|
||||
FDeletedItems.Clear;
|
||||
FOrphanItems.Clear;
|
||||
FRecordCount:=0;
|
||||
//Reopen
|
||||
BuildLinkedList;
|
||||
FCurrentItem:=FBeginItem;
|
||||
Resync([]);
|
||||
end;
|
||||
|
||||
function TSqliteDataset.SqliteReturnString: String;
|
||||
begin
|
||||
case FSqliteReturnId of
|
||||
@ -922,11 +1155,17 @@ begin
|
||||
else
|
||||
Result:='Unknow Return Value';
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TSqliteDataset.UpdatesPending: Boolean;
|
||||
begin
|
||||
Result:= (FDeletedItems.Count > 0) or
|
||||
(FAddedItems.Count > 0) or (FUpdatedItems.Count > 0);
|
||||
end;
|
||||
|
||||
procedure Register;
|
||||
begin
|
||||
RegisterComponents('Data Access', [TSqliteDataset]);
|
||||
end;
|
||||
|
||||
end.
|
||||
end.
|
||||
|
Loading…
Reference in New Issue
Block a user