* Patch from Luiz Americo:

- Allow more than one field to be used in Locate (fix bug #7843)
- Properly implement Edit, Insert, Cancel
- Simplified TableExists
- Make RecNo follows Delphi/sqldb (1 based count)

git-svn-id: trunk@5711 -
This commit is contained in:
michael 2006-12-25 15:56:48 +00:00
parent b0bc5d92fd
commit edc1015a49
3 changed files with 200 additions and 295 deletions

View File

@ -69,11 +69,11 @@ type
{$else}
FCurrentItem: PDataRecord;
{$endif}
FInternalActiveBuffer: PDataRecord;
FBufferSize: Integer;
FExpectedAppends: Integer;
FExpectedDeletes: Integer;
FExpectedUpdates: Integer;
//FPersistentHandle: Boolean;
FSaveOnClose: Boolean;
FSaveOnRefetch: Boolean;
FAutoIncrementKey: Boolean;
@ -81,6 +81,7 @@ type
FIndexFieldNames: String;
FIndexFieldList: TList;
FSqlList:TStrings;
procedure CopyCacheToItem(AItem: PDataRecord);
function GetIndexFields(Value: Integer): TField;
procedure UpdateIndexFields;
function FindRecordItem(StartItem: PDataRecord; const KeyFields: string; const KeyValues: Variant; Options: TLocateOptions; DoResync:Boolean):PDataRecord;
@ -135,7 +136,9 @@ type
function GetRecordSize: Word; override;
procedure InternalAddRecord(Buffer: Pointer; DoAppend: Boolean); override;
procedure InternalClose; override;
procedure InternalCancel; override;
procedure InternalDelete; override;
procedure InternalEdit; override;
procedure InternalFirst; override;
procedure InternalGotoBookmark(ABookmark: Pointer); override;
procedure InternalInitRecord(Buffer: PChar); override;
@ -173,8 +176,8 @@ type
function QuickQuery(const ASql:String;const AStrList: TStrings;FillObjects:Boolean):String;virtual;abstract;overload;
procedure RefetchData;
function SqliteReturnString: String; virtual;abstract;
function TableExists: Boolean;overload;
function TableExists(const ATableName:String):Boolean;virtual;abstract;overload;
function TableExists: Boolean;
function TableExists(const ATableName:String):Boolean;
function UpdatesPending: Boolean;
{$ifdef DEBUGACTIVEBUFFER}
procedure SetCurrentItem(Value:PDataRecord);
@ -192,7 +195,6 @@ type
property ExpectedDeletes: Integer read FExpectedDeletes write SetExpectedDeletes;
property IndexFields[Value: Integer]: TField read GetIndexFields;
property RowsAffected: Integer read GetRowsAffected;
//property PersistentHandle: boolean read FPersistentHandle write FPersistentHandle;
property SqliteReturnId: Integer read FSqliteReturnId;
property SqliteHandle: Pointer read FSqliteHandle;
property SqliteVersion: String read GetSqliteVersion;
@ -239,11 +241,13 @@ type
implementation
uses
strutils, variants;
strutils, variants, dbconst;
const
SQLITE_OK = 0;//sqlite2.x.x and sqlite3.x.x defines this equal
//sqlite2.x.x and sqlite3.x.x define these constants equally
SQLITE_OK = 0;
SQLITE_ROW = 100;
function Num2SqlStr(APChar: PChar): String;
begin
if APChar = nil then
@ -364,7 +368,6 @@ begin
FEndItem^.Next:=nil;
FBeginItem^.BookMarkFlag:=bfBOF;
FCacheItem^.BookMarkFlag:=bfEOF;
FEndItem^.BookMarkFlag:=bfEOF;
FMasterLink:=TMasterDataLink.Create(Self);
@ -382,19 +385,19 @@ begin
end;
function TCustomSqliteDataset.CreateBlobStream(Field: TField; Mode: TBlobStreamMode): TStream;
var
ActiveItem:PDataRecord;
begin
if Mode = bmWrite then
begin
ActiveItem:=PPDataRecord(ActiveBuffer)^;
if (ActiveItem <> FCacheItem) and (FUpdatedItems.IndexOf(ActiveItem) = -1) and (FAddedItems.IndexOf(ActiveItem) = -1) then
FUpdatedItems.Add(ActiveItem);
StrDispose(ActiveItem^.Row[Field.FieldNo - 1]);
ActiveItem^.Row[Field.FieldNo - 1]:=nil;
if not (State in [dsEdit, dsInsert]) then
begin
DatabaseErrorFmt(SNotInEditState,[Name],Self);
Exit;
end;
StrDispose(FCacheItem^.Row[Field.FieldNo - 1]);
FCacheItem^.Row[Field.FieldNo - 1]:=nil;
end;
Result:= TDSStream.Create(PPDataRecord(ActiveBuffer)^,Field.FieldNo - 1);
end;
end;
destructor TCustomSqliteDataset.Destroy;
begin
@ -414,6 +417,19 @@ begin
Dispose(FEndItem);
end;
procedure TCustomSqliteDataset.CopyCacheToItem(AItem: PDataRecord);
var
i:Integer;
begin
for i := 0 to FRowCount - 1 do
begin
StrDispose(AItem^.Row[i]);
AItem^.Row[i]:=FCacheItem^.Row[i];
FCacheItem^.Row[i]:=nil;
end;
AItem^.BookmarkFlag:=FCacheItem^.BookmarkFlag;
end;
function TCustomSqliteDataset.GetIndexFields(Value: Integer): TField;
begin
if (Value < 0) or (Value > FIndexFieldList.Count - 1) then
@ -560,27 +576,30 @@ var
TempItem,TempActive:PDataRecord;
begin
Result:= -1;
if FRecordCount = 0 then
if (FRecordCount = 0) or (State = dsInsert) then
Exit;
TempItem:=FBeginItem;
TempActive:=PPDataRecord(ActiveBuffer)^;
if TempActive = FCacheItem then // Record not posted yet
Result:=FRecordCount
else
while TempActive <> TempItem do
if TempActive = FCacheItem then // Record is being edited
begin
TempActive:=FInternalActiveBuffer;
end;
//RecNo is 1 based
inc(Result);
while TempActive <> TempItem do
begin
if TempItem^.Next <> nil then
begin
if TempItem^.Next <> nil then
begin
inc(Result);
TempItem:=TempItem^.Next;
end
else
begin
Result:=-1;
DatabaseError('Sqliteds.GetRecNo - ActiveItem Not Found',Self);
break;
end;
end;
inc(Result);
TempItem:=TempItem^.Next;
end
else
begin
Result:=-1;
DatabaseError('GetRecNo - ActiveItem Not Found',Self);
break;
end;
end;
end;
function TCustomSqliteDataset.GetRecordSize: Word;
@ -591,7 +610,6 @@ end;
procedure TCustomSqliteDataset.InternalAddRecord(Buffer: Pointer; DoAppend: Boolean);
var
NewItem: PDataRecord;
Counter:Integer;
begin
{$ifdef DEBUG}
if PPDataRecord(Buffer)^ <> FCacheItem then
@ -599,12 +617,20 @@ begin
{$endif}
New(NewItem);
GetMem(NewItem^.Row,FRowBufferSize);
for Counter := 0 to FRowCount - 1 do
NewItem^.Row[Counter]:=StrNew(FCacheItem^.Row[Counter]);
FEndItem^.Previous^.Next:=NewItem;
NewItem^.Previous:=FEndItem^.Previous;
NewItem^.Next:=FEndItem;
FEndItem^.Previous:=NewItem;
//necessary to nullify the Row before copy the cache
FillChar(NewItem^.Row^,FRowBufferSize,#0);
CopyCacheToItem(NewItem);
//insert in the linked list
FCurrentItem^.Previous^.Next:=NewItem;
NewItem^.Next:=FCurrentItem;
NewItem^.Previous:=FCurrentItem^.Previous;
FCurrentItem^.Previous:=NewItem;
//update the cursor in case of a insert
if FCurrentItem <> FEndItem then
FCurrentItem:=NewItem;
Inc(FRecordCount);
if FAutoIncFieldNo <> - 1 then
Inc(FNextAutoInc);
@ -620,13 +646,6 @@ begin
DestroyFields;
if FDataAllocated then
DisposeLinkedList;
{
if (FSqliteHandle <> nil) and not FPersistentHandle then
begin
InternalCloseHandle;
FSqliteHandle := nil;
end;
}
FAddedItems.Clear;
FUpdatedItems.Clear;
FDeletedItems.Clear;
@ -634,6 +653,19 @@ begin
FRecordCount:=0;
end;
procedure TCustomSqliteDataset.InternalCancel;
var
i: Integer;
begin
PPDataRecord(ActiveBuffer)^:=FInternalActiveBuffer;
//free the cache
for i:= 0 to FRowCount - 1 do
begin
StrDispose(FCacheItem^.Row[i]);
FCacheItem^.Row[i]:=nil;
end;
end;
procedure TCustomSqliteDataset.InternalDelete;
var
TempItem:PDataRecord;
@ -669,6 +701,19 @@ begin
end;
end;
procedure TCustomSqliteDataset.InternalEdit;
var
i: Integer;
begin
FInternalActiveBuffer:=PPDataRecord(ActiveBuffer)^;
//copy active item to cache
for i:= 0 to FRowCount - 1 do
FCacheItem^.Row[i]:=StrNew(FInternalActiveBuffer^.Row[i]);
FCacheItem^.BookmarkFlag:=FInternalActiveBuffer^.BookmarkFlag;
//now active buffer is the cache item
PPDataRecord(ActiveBuffer)^:=FCacheItem;
end;
procedure TCustomSqliteDataset.InternalFirst;
begin
FCurrentItem := FBeginItem;
@ -681,14 +726,8 @@ end;
procedure TCustomSqliteDataset.InternalInitRecord(Buffer: PChar);
var
Counter:Integer;
TempStr:String;
begin
for Counter:= 0 to FRowCount - 1 do
begin
StrDispose(FCacheItem^.Row[Counter]);
FCacheItem^.Row[Counter]:=nil;
end;
if FAutoIncFieldNo <> - 1 then
begin
Str(FNextAutoInc,TempStr);
@ -696,6 +735,7 @@ begin
StrPCopy(FCacheItem^.Row[FAutoIncFieldNo],TempStr);
end;
PPDataRecord(Buffer)^:=FCacheItem;
FCacheItem^.BookmarkFlag:=bfInserted;
end;
procedure TCustomSqliteDataset.InternalLast;
@ -732,7 +772,6 @@ begin
FSelectSqlStr:=FSelectSqlStr+FieldDefs[i].Name+',';
FSelectSqlStr:=FSelectSqlStr+FieldDefs[FieldDefs.Count - 1].Name+
' FROM '+FTableName;
//writeln(FSelectSqlStr);
if DefaultFields then
CreateFields;
@ -759,8 +798,16 @@ end;
procedure TCustomSqliteDataset.InternalPost;
begin
if (State<>dsEdit) then
InternalAddRecord(ActiveBuffer,True);
if State <> dsEdit then
InternalAddRecord(ActiveBuffer,True)
else
begin
CopyCacheToItem(FInternalActiveBuffer);
PPDataRecord(ActiveBuffer)^:=FInternalActiveBuffer;
if (FUpdatedItems.IndexOf(FInternalActiveBuffer) = -1) and
(FAddedItems.IndexOf(FInternalActiveBuffer) = -1) then
FUpdatedItems.Add(FInternalActiveBuffer);
end;
end;
procedure TCustomSqliteDataset.InternalSetToRecord(Buffer: PChar);
@ -775,23 +822,59 @@ end;
function TCustomSqliteDataset.FindRecordItem(StartItem: PDataRecord; const KeyFields: string; const KeyValues: Variant; Options: TLocateOptions; DoResync:Boolean):PDataRecord;
var
ValueArray: array of string;
IndexArray: array of integer;
AFieldList: TList;
i,AFieldCount:Integer;
MatchRecord: Boolean;
AValue:String;
AField:TField;
AFieldIndex:Integer;
TempItem:PDataRecord;
begin
Result:=nil;
// Now, it allows to search only one field and ignores options
AField:=Fields.FieldByName(KeyFields); //FieldByName raises an exception if field not found
AFieldIndex:=AField.FieldNo - 1;
//get float types in appropriate format
if not (AField.DataType in [ftFloat,ftDateTime,ftTime,ftDate]) then
AValue:=keyvalues
else
begin
Str(VarToDateTime(keyvalues),AValue);
AValue:=Trim(AValue);
end;
// Currently ignore options
AFieldList:=TList.Create;
try
GetFieldList(AFieldList,KeyFields);
AFieldCount:=AFieldList.Count;
if AFieldCount > 1 then
begin
if VarIsArray(KeyValues) then
begin
if Succ(VarArrayHighBound(KeyValues,1)) <> AFieldCount then
DatabaseError('Number of fields does not correspond to number of values',Self);
end
else
DatabaseError('Wrong number of values specified: expected an array of variants got a variant',Self);
end;
//set the array of values and indexes
SetLength(ValueArray,AFieldCount);
SetLength(IndexArray,AFieldCount);
for i:= 0 to AFieldCount - 1 do
with TField(AFieldList[i]) do
begin
//get float types in appropriate format
if not (DataType in [ftFloat,ftDateTime,ftTime,ftDate]) then
begin
if VarIsArray(KeyValues) then
ValueArray[i]:=keyvalues[i]
else
ValueArray[i]:=keyvalues;
end
else
begin
if VarIsArray(KeyValues) then
Str(VarToDateTime(keyvalues[i]),AValue)
else
Str(VarToDateTime(keyvalues),AValue);
ValueArray[i]:=Trim(AValue);
end;
IndexArray[i]:=FieldNo - 1;
end;
finally
AFieldList.Destroy;
end;
{$ifdef DEBUG}
writeln('##TCustomSqliteDataset.FindRecordItem##');
writeln(' KeyFields: ',keyfields);
@ -802,19 +885,27 @@ begin
TempItem:=StartItem;
while TempItem <> FEndItem do
begin
if TempItem^.Row[AFieldIndex] <> nil then
MatchRecord:=True;
for i:= 0 to AFieldCount - 1 do
begin
if StrComp(TempItem^.Row[AFieldIndex],PChar(AValue)) = 0 then
//todo: handle null values??
if (TempItem^.Row[IndexArray[i]] = nil) or
(StrComp(TempItem^.Row[IndexArray[i]],PChar(ValueArray[i])) <> 0) then
begin
Result:=TempItem;
if DoResync then
begin
FCurrentItem:=TempItem;
Resync([]);
end;
Break;
MatchRecord:= False;
Break;//for
end;
end;
end;
if MatchRecord then
begin
Result:=TempItem;
if DoResync then
begin
FCurrentItem:=TempItem;
Resync([]);
end;
Break;//while
end;
TempItem:=TempItem^.Next;
end;
end;
@ -850,7 +941,7 @@ end;
procedure TCustomSqliteDataset.SetBookmarkData(Buffer: PChar; Data: Pointer);
begin
//The BookMarkData is the Buffer itself;
//The BookMarkData is the Buffer itself: no need to set nothing;
end;
procedure TCustomSqliteDataset.SetBookmarkFlag(Buffer: PChar; Value: TBookmarkFlag);
@ -878,50 +969,50 @@ procedure TCustomSqliteDataset.SetFieldData(Field: TField; Buffer: Pointer;
NativeFormat: Boolean);
var
TempStr:String;
ActiveItem:PDataRecord;
begin
ActiveItem:=PPDataRecord(ActiveBuffer)^;
if (ActiveItem <> FCacheItem) and (FUpdatedItems.IndexOf(ActiveItem) = -1) and (FAddedItems.IndexOf(ActiveItem) = -1) then
FUpdatedItems.Add(ActiveItem);
StrDispose(ActiveItem^.Row[Pred(Field.FieldNo)]);
if not (State in [dsEdit, dsInsert]) then
begin
DatabaseErrorFmt(SNotInEditState,[Name],Self);
Exit;
end;
StrDispose(FCacheItem^.Row[Pred(Field.FieldNo)]);
if Buffer <> nil then
begin
case Field.Datatype of
ftString:
begin
ActiveItem^.Row[Pred(Field.FieldNo)]:=StrNew(PChar(Buffer));
FCacheItem^.Row[Pred(Field.FieldNo)]:=StrNew(PChar(Buffer));
end;
ftInteger:
begin
Str(LongInt(Buffer^),TempStr);
ActiveItem^.Row[Pred(Field.FieldNo)]:=StrAlloc(Length(TempStr)+1);
Move(PChar(TempStr)^,(ActiveItem^.Row[Pred(Field.FieldNo)])^,Length(TempStr)+1);
FCacheItem^.Row[Pred(Field.FieldNo)]:=StrAlloc(Length(TempStr)+1);
Move(PChar(TempStr)^,(FCacheItem^.Row[Pred(Field.FieldNo)])^,Length(TempStr)+1);
end;
ftBoolean,ftWord:
begin
Str(Word(Buffer^),TempStr);
ActiveItem^.Row[Pred(Field.FieldNo)]:=StrAlloc(Length(TempStr)+1);
Move(PChar(TempStr)^,(ActiveItem^.Row[Pred(Field.FieldNo)])^,Length(TempStr)+1);
FCacheItem^.Row[Pred(Field.FieldNo)]:=StrAlloc(Length(TempStr)+1);
Move(PChar(TempStr)^,(FCacheItem^.Row[Pred(Field.FieldNo)])^,Length(TempStr)+1);
end;
ftFloat,ftDateTime,ftDate,ftTime,ftCurrency:
begin
Str(Double(Buffer^),TempStr);
ActiveItem^.Row[Pred(Field.FieldNo)]:=StrAlloc(Length(TempStr));
FCacheItem^.Row[Pred(Field.FieldNo)]:=StrAlloc(Length(TempStr));
//Skips the first space that str returns
//todo: make a custom Str?
Move((PChar(TempStr)+1)^,(ActiveItem^.Row[Pred(Field.FieldNo)])^,Length(TempStr));
Move((PChar(TempStr)+1)^,(FCacheItem^.Row[Pred(Field.FieldNo)])^,Length(TempStr));
end;
ftLargeInt:
begin
Str(Int64(Buffer^),TempStr);
ActiveItem^.Row[Pred(Field.FieldNo)]:=StrAlloc(Length(TempStr)+1);
Move(PChar(TempStr)^,(ActiveItem^.Row[Pred(Field.FieldNo)])^,Length(TempStr)+1);
FCacheItem^.Row[Pred(Field.FieldNo)]:=StrAlloc(Length(TempStr)+1);
Move(PChar(TempStr)^,(FCacheItem^.Row[Pred(Field.FieldNo)])^,Length(TempStr)+1);
end;
end;// case
end//if
else
ActiveItem^.Row[Pred(Field.FieldNo)]:=nil;
FCacheItem^.Row[Pred(Field.FieldNo)]:=nil;
if not (State in [dsCalcFields, dsFilter, dsNewValue]) then
DataEvent(deFieldChange, Ptrint(Field));
end;
@ -936,10 +1027,11 @@ var
Counter:Integer;
TempItem:PDataRecord;
begin
if (Value >= FRecordCount) or (Value < 0) then
if (Value > FRecordCount) or (Value <= 0) then
DatabaseError('Record Number Out Of Range',Self);
CheckBrowseMode;
TempItem:=FBeginItem;
for Counter := 0 to Value do
for Counter := 1 to Value do
TempItem:=TempItem^.Next;
FCurrentItem:=TempItem;
Resync([]);
@ -1280,6 +1372,16 @@ begin
Result:=TableExists(FTableName);
end;
function TCustomSqliteDataset.TableExists(const ATableName: String): Boolean;
begin
Result:=False;
if not (ATableName = '') and FileExists(FFileName) then
begin
ExecSql('SELECT name FROM SQLITE_MASTER WHERE type = ''table'' AND name LIKE '''+ ATableName+ ''';');
Result:=FSqliteReturnId = SQLITE_ROW;
end;
end;
function TCustomSqliteDataset.UpdatesPending: Boolean;
begin
//Sometimes FBeginItem is inserted in FUpdatedItems

View File

@ -41,13 +41,11 @@ type
procedure InternalCloseHandle;override;
procedure BuildLinkedList; override;
protected
procedure InternalCancel;override;
procedure InternalInitFieldDefs; override;
function GetRowsAffected:Integer; override;
public
procedure ExecuteDirect(const ASql: String);override;
function SqliteReturnString: String; override;
function TableExists(const ATableName:String): Boolean;override;
function QuickQuery(const ASql:String;const AStrList: TStrings;FillObjects:Boolean):String;override;
end;
@ -256,81 +254,6 @@ begin
FBeginItem^.Row[Counter]:=nil;
end;
procedure TSqlite3Dataset.InternalCancel;
{
var
vm:Pointer;
i:Integer;
ActiveItem:PDataRecord;
ASql:String;
}
begin
{
//WriteLn('InternalCancel called');
if FPrimaryKeyNo <> - 1 then //requires a primarykey
begin
ActiveItem:=PPDataRecord(ActiveBuffer)^;
if ActiveItem = FBeginItem then //Dataset is empty
Exit;
for i:= 0 to FRowCount -1 do
StrDispose(ActiveItem^.Row[i]);
if FAddedItems.IndexOf(ActiveItem) <> -1 then //the record is not in the database
begin
for i:= 0 to FRowCount - 1 do
begin
ActiveItem^.Row[i]:=nil;
//DataEvent(deFieldChange, Ptrint(Fields[i]));
end;
Exit;
end;
ASql:=FSelectSqlStr+' Where '+Fields[FPrimaryKeyNo].FieldName+
' = '+StrPas(ActiveItem^.Row[FPrimaryKeyNo]);
//writeln(Asql);
sqlite3_prepare(FSqliteHandle,PChar(ASql),-1,@vm,nil);
if sqlite3_step(vm) = SQLITE_ROW then
begin
for i:= 0 to FRowCount - 1 do
begin
ActiveItem^.Row[i]:=StrNew(sqlite3_column_text(vm,i));
//DataEvent(deFieldChange, Ptrint(Fields[i]));
end;
end;
sqlite3_finalize(vm);
end;
}
end;
function TSqlite3Dataset.TableExists(const ATableName:String): Boolean;
var
vm:Pointer;
begin
{$ifdef DEBUG}
writeln('##TSqlite3Dataset.TableExists##');
{$endif}
Result:=False;
if not (ATableName = '') and FileExists(FFileName) then
begin
if FSqliteHandle = nil then
GetSqliteHandle;
FSqliteReturnId:=sqlite3_prepare(FSqliteHandle,
Pchar('SELECT name FROM SQLITE_MASTER WHERE type = ''table'' AND name LIKE '''+ ATableName+ ''';'),
-1,@vm,nil);
{$ifdef DEBUG}
WriteLn(' sqlite3_prepare - SqliteReturnString:',SqliteReturnString);
{$endif}
FSqliteReturnId:=sqlite3_step(vm);
{$ifdef DEBUG}
WriteLn(' sqlite3_step - SqliteReturnString:',SqliteReturnString);
{$endif}
Result:=FSqliteReturnId = SQLITE_ROW;
sqlite3_finalize(vm);
end;
{$ifdef DEBUG}
WriteLn(' Table '+ATableName+' exists: ',Result);
{$endif}
end;
function TSqlite3Dataset.SqliteReturnString: String;
begin
case FSqliteReturnId of

View File

@ -47,7 +47,6 @@ type
public
procedure ExecuteDirect(const ASql: String);override;
function SqliteReturnString: String; override;
function TableExists(const ATableName:String): Boolean;override;
function QuickQuery(const ASql:String;const AStrList: TStrings;FillObjects:Boolean):String;override;
property SqliteEncoding: String read GetSqliteEncoding;
end;
@ -74,93 +73,6 @@ begin
Result:=1;
end;
{
function GetFieldDefs(TheDataset: Pointer; Columns: Integer; ColumnValues: PPChar; ColumnNames: PPChar): integer; cdecl;
var
FieldSize:Word;
i:Integer;
AType:TFieldType;
ColumnStr:String;
begin
//Prepare the array of pchar2sql functions
SetLength(TCustomSqliteDataset(TheDataset).FGetSqlStr,Columns);
// Sqlite is typeless (allows any type in any field)
// regardless of what is in Create Table, but returns
// exactly what is in Create Table statement
// here is a trick to get the datatype.
// If the field contains another type, may have problems
for i:= 0 to Columns - 1 do
begin
ColumnStr:= UpperCase(StrPas(ColumnNames[i + Columns]));
if (ColumnStr = 'INTEGER') or (ColumnStr = 'INT') then
begin
if TCustomSqliteDataset(TheDataset).AutoIncrementKey and
(UpperCase(StrPas(ColumnNames[i])) = UpperCase(TCustomSqliteDataset(TheDataset).PrimaryKey)) then
begin
AType:= ftAutoInc;
DummyAutoIncFieldNo:=i;
end
else
AType:= ftInteger;
FieldSize:=SizeOf(LongInt);
end else if Pos('VARCHAR',ColumnStr) = 1 then
begin
AType:= ftString;
FieldSize:=0;
end else if Pos('BOOL',ColumnStr) = 1 then
begin
AType:= ftBoolean;
FieldSize:=SizeOf(WordBool);
end else if Pos('AUTOINC',ColumnStr) = 1 then
begin
AType:= ftAutoInc;
FieldSize:=SizeOf(LongInt);
if DummyAutoIncFieldNo = -1 then
DummyAutoIncFieldNo:= i;
end else if (Pos('FLOAT',ColumnStr)=1) or (Pos('NUMERIC',ColumnStr)=1) then
begin
AType:= ftFloat;
FieldSize:=SizeOf(Double);
end else if (ColumnStr = 'DATETIME') then
begin
AType:= ftDateTime;
FieldSize:=SizeOf(TDateTime);
end else if (ColumnStr = 'DATE') then
begin
AType:= ftDate;
FieldSize:=SizeOf(TDateTime);
end else if (ColumnStr = 'TIME') then
begin
AType:= ftTime;
FieldSize:=SizeOf(TDateTime);
end else if (ColumnStr = 'LARGEINT') then
begin
AType:= ftLargeInt;
FieldSize:=SizeOf(LargeInt);
end else if (ColumnStr = 'TEXT') then
begin
AType:= ftMemo;
FieldSize:=0;
end else if (ColumnStr = 'CURRENCY') then
begin
AType:= ftCurrency;
FieldSize:=SizeOf(Double);
end else if (ColumnStr = 'WORD') then
begin
AType:= ftWord;
FieldSize:=SizeOf(Word);
end else
begin
AType:=ftString;
FieldSize:=0;
end;
TDataset(TheDataset).FieldDefs.Add(StrPas(ColumnNames[i]), AType, FieldSize, False);
//Set
end;
Result:=-1;
end;
}
{ TSqliteDataset }
function TSqliteDataset.SqliteExec(AHandle: Pointer; ASql: PChar): Integer;
@ -349,38 +261,6 @@ begin
FBeginItem^.Row[Counter]:=nil;
end;
function TSqliteDataset.TableExists(const ATableName:String): Boolean;
var
vm:Pointer;
ColumnNames,ColumnValues:PPChar;
AInt:Integer;
begin
{$ifdef DEBUG}
WriteLn('##TSqliteDataset.TableExists##');
{$endif}
Result:=False;
if not (ATableName = '') and FileExists(FFileName) then
begin
if FSqliteHandle = nil then
GetSqliteHandle;
FSqliteReturnId:=sqlite_compile(FSqliteHandle,
Pchar('SELECT name FROM SQLITE_MASTER WHERE type = ''table'' AND name LIKE '''+ ATableName+ ''';'),
nil,@vm,nil);
{$ifdef DEBUG}
WriteLn(' sqlite_compile - SqliteReturnString:',SqliteReturnString);
{$endif}
FSqliteReturnId:=sqlite_step(vm,@AInt,@ColumnValues,@ColumnNames);
{$ifdef DEBUG}
WriteLn(' sqlite_step - SqliteReturnString:',SqliteReturnString);
{$endif}
Result:=FSqliteReturnId = SQLITE_ROW;
sqlite_finalize(vm, nil);
end;
{$ifdef DEBUG}
WriteLn(' Table '+ATableName+' exists:',Result);
{$endif}
end;
function TSqliteDataset.SqliteReturnString: String;
begin
case FSqliteReturnId of