|
@@ -86,6 +86,7 @@ type
|
|
FIndexFieldList: TList;
|
|
FIndexFieldList: TList;
|
|
function GetIndexFields(Value: Integer): TField;
|
|
function GetIndexFields(Value: Integer): TField;
|
|
procedure UpdateIndexFields;
|
|
procedure UpdateIndexFields;
|
|
|
|
+ function FindRecordItem(StartItem: PDataRecord; const KeyFields: string; const KeyValues: Variant; Options: TLocateOptions; DoResync:Boolean):PDataRecord;
|
|
protected
|
|
protected
|
|
FFileName: String;
|
|
FFileName: String;
|
|
FSql: String;
|
|
FSql: String;
|
|
@@ -137,7 +138,6 @@ type
|
|
procedure InternalPost; override;
|
|
procedure InternalPost; override;
|
|
procedure InternalSetToRecord(Buffer: PChar); override;
|
|
procedure InternalSetToRecord(Buffer: PChar); override;
|
|
function IsCursorOpen: Boolean; override;
|
|
function IsCursorOpen: Boolean; override;
|
|
- function Locate(const keyfields: string; const keyvalues: Variant; options: TLocateOptions) : boolean; override;
|
|
|
|
procedure SetBookmarkData(Buffer: PChar; Data: Pointer); override;
|
|
procedure SetBookmarkData(Buffer: PChar; Data: Pointer); override;
|
|
procedure SetBookmarkFlag(Buffer: PChar; Value: TBookmarkFlag); override;
|
|
procedure SetBookmarkFlag(Buffer: PChar; Value: TBookmarkFlag); override;
|
|
procedure SetExpectedAppends(AValue:Integer);
|
|
procedure SetExpectedAppends(AValue:Integer);
|
|
@@ -149,6 +149,9 @@ type
|
|
constructor Create(AOwner: TComponent); override;
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
destructor Destroy; override;
|
|
function GetFieldData(Field: TField; Buffer: Pointer): Boolean; override;
|
|
function GetFieldData(Field: TField; Buffer: Pointer): 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}
|
|
// Additional procedures
|
|
// Additional procedures
|
|
function ApplyUpdates: Boolean; virtual;
|
|
function ApplyUpdates: Boolean; virtual;
|
|
function CreateTable: Boolean; virtual;
|
|
function CreateTable: Boolean; virtual;
|
|
@@ -434,16 +437,26 @@ begin
|
|
begin
|
|
begin
|
|
Move(FieldRow^,PChar(Buffer)^,StrLen(FieldRow)+1);
|
|
Move(FieldRow^,PChar(Buffer)^,StrLen(FieldRow)+1);
|
|
end;
|
|
end;
|
|
- ftInteger,ftBoolean,ftWord,ftAutoInc:
|
|
|
|
|
|
+ ftInteger,ftAutoInc:
|
|
begin
|
|
begin
|
|
Val(StrPas(FieldRow),LongInt(Buffer^),ValError);
|
|
Val(StrPas(FieldRow),LongInt(Buffer^),ValError);
|
|
Result:= ValError = 0;
|
|
Result:= ValError = 0;
|
|
end;
|
|
end;
|
|
- ftFloat,ftDateTime,ftTime,ftDate:
|
|
|
|
|
|
+ ftBoolean,ftWord:
|
|
|
|
+ begin
|
|
|
|
+ Val(StrPas(FieldRow),Word(Buffer^),ValError);
|
|
|
|
+ Result:= ValError = 0;
|
|
|
|
+ end;
|
|
|
|
+ ftFloat,ftDateTime,ftTime,ftDate,ftCurrency:
|
|
begin
|
|
begin
|
|
Val(StrPas(FieldRow),Double(Buffer^),ValError);
|
|
Val(StrPas(FieldRow),Double(Buffer^),ValError);
|
|
Result:= ValError = 0;
|
|
Result:= ValError = 0;
|
|
- end;
|
|
|
|
|
|
+ end;
|
|
|
|
+ ftLargeInt:
|
|
|
|
+ begin
|
|
|
|
+ Val(StrPas(FieldRow),Int64(Buffer^),ValError);
|
|
|
|
+ Result:= ValError = 0;
|
|
|
|
+ end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
@@ -689,20 +702,17 @@ begin
|
|
Result := FDataAllocated;
|
|
Result := FDataAllocated;
|
|
end;
|
|
end;
|
|
|
|
|
|
-function TCustomSqliteDataset.Locate(const keyfields: string; const keyvalues: Variant; options: TLocateOptions) : boolean;
|
|
|
|
|
|
+function TCustomSqliteDataset.FindRecordItem(StartItem: PDataRecord; const KeyFields: string; const KeyValues: Variant; Options: TLocateOptions; DoResync:Boolean):PDataRecord;
|
|
var
|
|
var
|
|
AValue:String;
|
|
AValue:String;
|
|
AField:TField;
|
|
AField:TField;
|
|
AFieldIndex:Integer;
|
|
AFieldIndex:Integer;
|
|
TempItem:PDataRecord;
|
|
TempItem:PDataRecord;
|
|
begin
|
|
begin
|
|
- Result:=False;
|
|
|
|
|
|
+ Result:=nil;
|
|
// Now, it allows to search only one field and ignores options
|
|
// Now, it allows to search only one field and ignores options
|
|
- AField:=Fields.FindField(keyfields);
|
|
|
|
- if AField <> nil then
|
|
|
|
- AFieldIndex:=AField.FieldNo - 1
|
|
|
|
- else
|
|
|
|
- DatabaseError('Field "'+keyfields+'" not found',Self);
|
|
|
|
|
|
+ AField:=Fields.FieldByName(KeyFields); //FieldByName raises an exeception if field not found
|
|
|
|
+ AFieldIndex:=AField.FieldNo - 1;
|
|
//get float types in appropriate format
|
|
//get float types in appropriate format
|
|
if not (AField.DataType in [ftFloat,ftDateTime,ftTime,ftDate]) then
|
|
if not (AField.DataType in [ftFloat,ftDateTime,ftTime,ftDate]) then
|
|
AValue:=keyvalues
|
|
AValue:=keyvalues
|
|
@@ -712,25 +722,25 @@ begin
|
|
AValue:=Trim(AValue);
|
|
AValue:=Trim(AValue);
|
|
end;
|
|
end;
|
|
{$ifdef DEBUG}
|
|
{$ifdef DEBUG}
|
|
- writeln('=Locate=');
|
|
|
|
|
|
+ writeln('=FindRecord=');
|
|
writeln('keyfields: ',keyfields);
|
|
writeln('keyfields: ',keyfields);
|
|
writeln('keyvalues: ',keyvalues);
|
|
writeln('keyvalues: ',keyvalues);
|
|
writeln('AValue: ',AValue);
|
|
writeln('AValue: ',AValue);
|
|
{$endif}
|
|
{$endif}
|
|
//Search the list
|
|
//Search the list
|
|
- TempItem:=FBeginItem^.Next;
|
|
|
|
|
|
+ TempItem:=StartItem;
|
|
while TempItem <> FEndItem do
|
|
while TempItem <> FEndItem do
|
|
begin
|
|
begin
|
|
if TempItem^.Row[AFieldIndex] <> nil then
|
|
if TempItem^.Row[AFieldIndex] <> nil then
|
|
begin
|
|
begin
|
|
- writeln('TempItem^.Row[AFieldIndex]: ',TempItem^.Row[AFieldIndex]);
|
|
|
|
- writeln('PChar(AValue): ',PChar(AValue));
|
|
|
|
- writeln('StrComp result: ',StrComp(TempItem^.Row[AFieldIndex],PChar(AValue)));
|
|
|
|
if StrComp(TempItem^.Row[AFieldIndex],PChar(AValue)) = 0 then
|
|
if StrComp(TempItem^.Row[AFieldIndex],PChar(AValue)) = 0 then
|
|
begin
|
|
begin
|
|
- Result:=True;
|
|
|
|
- FCurrentItem:=TempItem;
|
|
|
|
- Resync([]);
|
|
|
|
|
|
+ Result:=TempItem;
|
|
|
|
+ if DoResync then
|
|
|
|
+ begin
|
|
|
|
+ FCurrentItem:=TempItem;
|
|
|
|
+ Resync([]);
|
|
|
|
+ end;
|
|
Break;
|
|
Break;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
@@ -738,6 +748,27 @@ begin
|
|
end;
|
|
end;
|
|
end;
|
|
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;
|
|
|
|
+begin
|
|
|
|
+ Result:=FindRecordItem(PPDataRecord(ActiveBuffer)^^.Next,KeyFields,KeyValues,Options,True) <> nil;
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+function TCustomSqliteDataset.Lookup(const KeyFields: string; const KeyValues: Variant; const ResultFields: string): Variant;
|
|
|
|
+var
|
|
|
|
+ TempItem:PDataRecord;
|
|
|
|
+begin
|
|
|
|
+ TempItem:=FindRecordItem(FBeginItem^.Next,KeyFields,KeyValues,[],False);
|
|
|
|
+ if TempItem <> nil then
|
|
|
|
+ Result:=TempItem^.Row[FieldByName(ResultFields).FieldNo - 1]
|
|
|
|
+ else
|
|
|
|
+ Result:=False;
|
|
|
|
+end;
|
|
|
|
+
|
|
procedure TCustomSqliteDataset.SetBookmarkData(Buffer: PChar; Data: Pointer);
|
|
procedure TCustomSqliteDataset.SetBookmarkData(Buffer: PChar; Data: Pointer);
|
|
begin
|
|
begin
|
|
//The BookMarkData is the Buffer itself;
|
|
//The BookMarkData is the Buffer itself;
|
|
@@ -750,22 +781,18 @@ end;
|
|
|
|
|
|
procedure TCustomSqliteDataset.SetExpectedAppends(AValue:Integer);
|
|
procedure TCustomSqliteDataset.SetExpectedAppends(AValue:Integer);
|
|
begin
|
|
begin
|
|
- if Assigned(FAddedItems) then
|
|
|
|
- FAddedItems.Capacity:=AValue;
|
|
|
|
|
|
+ FAddedItems.Capacity:=AValue;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TCustomSqliteDataset.SetExpectedUpdates(AValue:Integer);
|
|
procedure TCustomSqliteDataset.SetExpectedUpdates(AValue:Integer);
|
|
begin
|
|
begin
|
|
- if Assigned(FUpdatedItems) then
|
|
|
|
- FUpdatedItems.Capacity:=AValue;
|
|
|
|
|
|
+ FUpdatedItems.Capacity:=AValue;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TCustomSqliteDataset.SetExpectedDeletes(AValue:Integer);
|
|
procedure TCustomSqliteDataset.SetExpectedDeletes(AValue:Integer);
|
|
begin
|
|
begin
|
|
- if Assigned(FDeletedItems) then
|
|
|
|
- FDeletedItems.Capacity:=AValue;
|
|
|
|
- if Assigned(FOrphanItems) then
|
|
|
|
- FOrphanItems.Capacity:=AValue;
|
|
|
|
|
|
+ FDeletedItems.Capacity:=AValue;
|
|
|
|
+ FOrphanItems.Capacity:=AValue;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TCustomSqliteDataset.SetFieldData(Field: TField; Buffer: Pointer);
|
|
procedure TCustomSqliteDataset.SetFieldData(Field: TField; Buffer: Pointer);
|
|
@@ -785,18 +812,30 @@ begin
|
|
begin
|
|
begin
|
|
ActiveItem^.Row[Pred(Field.FieldNo)]:=StrNew(PChar(Buffer));
|
|
ActiveItem^.Row[Pred(Field.FieldNo)]:=StrNew(PChar(Buffer));
|
|
end;
|
|
end;
|
|
- ftInteger,ftBoolean,ftWord:
|
|
|
|
|
|
+ ftInteger:
|
|
begin
|
|
begin
|
|
Str(LongInt(Buffer^),TempStr);
|
|
Str(LongInt(Buffer^),TempStr);
|
|
ActiveItem^.Row[Pred(Field.FieldNo)]:=StrAlloc(Length(TempStr)+1);
|
|
ActiveItem^.Row[Pred(Field.FieldNo)]:=StrAlloc(Length(TempStr)+1);
|
|
StrPCopy(ActiveItem^.Row[Pred(Field.FieldNo)],TempStr);
|
|
StrPCopy(ActiveItem^.Row[Pred(Field.FieldNo)],TempStr);
|
|
end;
|
|
end;
|
|
- ftFloat,ftDateTime,ftDate,ftTime:
|
|
|
|
|
|
+ ftBoolean,ftWord:
|
|
|
|
+ begin
|
|
|
|
+ Str(Word(Buffer^),TempStr);
|
|
|
|
+ ActiveItem^.Row[Pred(Field.FieldNo)]:=StrAlloc(Length(TempStr)+1);
|
|
|
|
+ StrPCopy(ActiveItem^.Row[Pred(Field.FieldNo)],TempStr);
|
|
|
|
+ end;
|
|
|
|
+ ftFloat,ftDateTime,ftDate,ftTime,ftCurrency:
|
|
begin
|
|
begin
|
|
Str(Double(Buffer^),TempStr);
|
|
Str(Double(Buffer^),TempStr);
|
|
ActiveItem^.Row[Pred(Field.FieldNo)]:=StrAlloc(Length(TempStr)+1);
|
|
ActiveItem^.Row[Pred(Field.FieldNo)]:=StrAlloc(Length(TempStr)+1);
|
|
StrPCopy(ActiveItem^.Row[Pred(Field.FieldNo)],TempStr);
|
|
StrPCopy(ActiveItem^.Row[Pred(Field.FieldNo)],TempStr);
|
|
- end;
|
|
|
|
|
|
+ end;
|
|
|
|
+ ftLargeInt:
|
|
|
|
+ begin
|
|
|
|
+ Str(Int64(Buffer^),TempStr);
|
|
|
|
+ ActiveItem^.Row[Pred(Field.FieldNo)]:=StrAlloc(Length(TempStr)+1);
|
|
|
|
+ StrPCopy(ActiveItem^.Row[Pred(Field.FieldNo)],TempStr);
|
|
|
|
+ end;
|
|
end;// case
|
|
end;// case
|
|
end//if
|
|
end//if
|
|
else
|
|
else
|
|
@@ -834,14 +873,19 @@ var
|
|
AFilter:String;
|
|
AFilter:String;
|
|
i:Integer;
|
|
i:Integer;
|
|
begin
|
|
begin
|
|
- AFilter:=' where ';
|
|
|
|
- for i:= 0 to FMasterLink.Fields.Count - 1 do
|
|
|
|
- begin
|
|
|
|
- AFilter:=AFilter + IndexFields[i].FieldName +' = '+ GetSqlStr(TField(FMasterLink.Fields[i]));
|
|
|
|
- if i <> FMasterLink.Fields.Count - 1 then
|
|
|
|
- AFilter:= AFilter + ' and ';
|
|
|
|
|
|
+ if FMasterLink.Dataset.RecordCount = 0 then //Retrieve all data
|
|
|
|
+ FSql:='Select * from '+FTableName
|
|
|
|
+ else
|
|
|
|
+ begin
|
|
|
|
+ AFilter:=' where ';
|
|
|
|
+ for i:= 0 to FMasterLink.Fields.Count - 1 do
|
|
|
|
+ begin
|
|
|
|
+ AFilter:=AFilter + IndexFields[i].FieldName +' = '+ GetSqlStr(TField(FMasterLink.Fields[i]));
|
|
|
|
+ if i <> FMasterLink.Fields.Count - 1 then
|
|
|
|
+ AFilter:= AFilter + ' and ';
|
|
|
|
+ end;
|
|
|
|
+ FSql:='Select * from '+FTableName+AFilter;
|
|
end;
|
|
end;
|
|
- FSql:='Select * from '+FTableName+AFilter;
|
|
|
|
{$ifdef DEBUG}
|
|
{$ifdef DEBUG}
|
|
writeln('Sql used to filter detail dataset:');
|
|
writeln('Sql used to filter detail dataset:');
|
|
writeln(FSql);
|
|
writeln(FSql);
|
|
@@ -1080,13 +1124,17 @@ begin
|
|
ftDate:
|
|
ftDate:
|
|
SqlTemp:=SqlTemp + ' DATE';
|
|
SqlTemp:=SqlTemp + ' DATE';
|
|
ftTime:
|
|
ftTime:
|
|
- SqlTemp:=SqlTemp + ' TIME';
|
|
|
|
|
|
+ SqlTemp:=SqlTemp + ' TIME';
|
|
|
|
+ ftLargeInt:
|
|
|
|
+ SqlTemp:=SqlTemp + ' LARGEINT';
|
|
|
|
+ ftCurrency:
|
|
|
|
+ SqlTemp:=SqlTemp + ' CURRENCY';
|
|
ftAutoInc:
|
|
ftAutoInc:
|
|
SqlTemp:=SqlTemp + ' AUTOINC';
|
|
SqlTemp:=SqlTemp + ' AUTOINC';
|
|
ftMemo:
|
|
ftMemo:
|
|
SqlTemp:=SqlTemp + ' MEMO';
|
|
SqlTemp:=SqlTemp + ' MEMO';
|
|
else
|
|
else
|
|
- SqlTemp:=SqlTemp + ' VARCHAR';
|
|
|
|
|
|
+ DatabaseError('Field type "'+FieldTypeNames[FieldDefs[Counter].DataType]+'" not supported',Self);
|
|
end;
|
|
end;
|
|
if Counter <> FieldDefs.Count - 1 then
|
|
if Counter <> FieldDefs.Count - 1 then
|
|
SqlTemp:=SqlTemp+ ' , ';
|
|
SqlTemp:=SqlTemp+ ' , ';
|