* Fixed test TestAddDblIndex

* Set the function result properly in DBCompareText 
 * Rewrote TBufDataset.Locate, it now uses parts of the indexes-code (+test)

git-svn-id: trunk@10671 -
This commit is contained in:
joost 2008-04-15 21:29:56 +00:00
parent a681f946f8
commit 683f59a70c
2 changed files with 87 additions and 91 deletions

View File

@ -187,6 +187,7 @@ type
function LoadBuffer(Buffer : PChar): TGetResult; function LoadBuffer(Buffer : PChar): TGetResult;
function GetFieldSize(FieldDef : TFieldDef) : longint; function GetFieldSize(FieldDef : TFieldDef) : longint;
function GetRecordUpdateBuffer : boolean; function GetRecordUpdateBuffer : boolean;
procedure ProcessFieldCompareStruct(AField: TField; var ACompareRec : TDBCompareRec);
procedure SetIndexFieldNames(const AValue: String); procedure SetIndexFieldNames(const AValue: String);
procedure SetIndexName(AValue: String); procedure SetIndexName(AValue: String);
{$IFNDEF ARRAYBUF} {$IFNDEF ARRAYBUF}
@ -303,7 +304,7 @@ end;
function DBCompareText(subValue, aValue: pointer; options: TLocateOptions): LargeInt; function DBCompareText(subValue, aValue: pointer; options: TLocateOptions): LargeInt;
begin begin
DBCompareTextLen(subValue,aValue,Length(pchar(subValue)),options); Result := DBCompareTextLen(subValue,aValue,Length(pchar(subValue)),options);
end; end;
function DBCompareByte(subValue, aValue: pointer; options: TLocateOptions): LargeInt; function DBCompareByte(subValue, aValue: pointer; options: TLocateOptions): LargeInt;
@ -463,19 +464,7 @@ begin
for FieldNr:=0 to FieldsAmount-1 do for FieldNr:=0 to FieldsAmount-1 do
begin begin
AField := TField(IndexFields[FieldNr]); AField := TField(IndexFields[FieldNr]);
ProcessFieldCompareStruct(AField,DBCompareStruct[FieldNr]);
case AField.DataType of
ftString : DBCompareStruct[FieldNr].Comparefunc := @DBCompareText;
ftSmallint : DBCompareStruct[FieldNr].Comparefunc := @DBCompareSmallInt;
ftInteger,ftCurrency,ftBCD : DBCompareStruct[FieldNr].Comparefunc := @DBCompareInt;
ftWord : DBCompareStruct[FieldNr].Comparefunc := @DBCompareWord;
ftBoolean : DBCompareStruct[FieldNr].Comparefunc := @DBCompareByte;
ftFloat : DBCompareStruct[FieldNr].Comparefunc := @DBCompareDouble;
ftDateTime,ftDate,ftTime : DBCompareStruct[FieldNr].Comparefunc := @DBCompareDouble;
ftLargeint : DBCompareStruct[FieldNr].Comparefunc := @DBCompareLargeInt;
else
DatabaseErrorFmt(SErrIndexBasedOnInvField,[AField.FieldName]);
end;
DBCompareStruct[FieldNr].Desc := (DescIndexFields.IndexOf(AField)>-1); DBCompareStruct[FieldNr].Desc := (DescIndexFields.IndexOf(AField)>-1);
if (CInsIndexFields.IndexOf(AField)>-1) then if (CInsIndexFields.IndexOf(AField)>-1) then
@ -483,9 +472,6 @@ begin
else else
DBCompareStruct[FieldNr].Options := []; DBCompareStruct[FieldNr].Options := [];
DBCompareStruct[FieldNr].Off1:=sizeof(TBufRecLinkItem)*FMaxIndexesCount+FFieldBufPositions[AField.FieldNo-1];
DBCompareStruct[FieldNr].Off2:=DBCompareStruct[FieldNr].Off1;
end; end;
finally finally
CInsIndexFields.Free; CInsIndexFields.Free;
@ -972,6 +958,28 @@ begin
Result := (FCurrentUpdateBuffer < length(FUpdateBuffer)) and CompareBuf(FCurrentUpdateBuffer); Result := (FCurrentUpdateBuffer < length(FUpdateBuffer)) and CompareBuf(FCurrentUpdateBuffer);
end; end;
procedure TBufDataset.ProcessFieldCompareStruct(AField: TField; var ACompareRec : TDBCompareRec);
begin
case AField.DataType of
ftString : ACompareRec.Comparefunc := @DBCompareText;
ftSmallint : ACompareRec.Comparefunc := @DBCompareSmallInt;
ftInteger, ftCurrency, ftBCD : ACompareRec.Comparefunc :=
@DBCompareInt;
ftWord : ACompareRec.Comparefunc := @DBCompareWord;
ftBoolean : ACompareRec.Comparefunc := @DBCompareByte;
ftFloat : ACompareRec.Comparefunc := @DBCompareDouble;
ftDateTime, ftDate, ftTime : ACompareRec.Comparefunc :=
@DBCompareDouble;
ftLargeint : ACompareRec.Comparefunc := @DBCompareLargeInt;
else
DatabaseErrorFmt(SErrIndexBasedOnInvField, [AField.FieldName]);
end;
ACompareRec.Off1:=sizeof(TBufRecLinkItem)*FMaxIndexesCount+
FFieldBufPositions[AField.FieldNo-1];
ACompareRec.Off2:=ACompareRec.Off1;
end;
procedure TBufDataset.SetIndexFieldNames(const AValue: String); procedure TBufDataset.SetIndexFieldNames(const AValue: String);
begin begin
if AValue<>'' then if AValue<>'' then
@ -2254,96 +2262,62 @@ end;
Function TBufDataset.Locate(const KeyFields: string; const KeyValues: Variant; options: TLocateOptions) : boolean; Function TBufDataset.Locate(const KeyFields: string; const KeyValues: Variant; options: TLocateOptions) : boolean;
var keyfield : TField; // Field to search in var CurrLinkItem : PBufRecLinkItem;
ValueBuffer : pchar; // Pointer to value to search for, in TField' internal format bm : TBufBookmark;
VBLength : integer; SearchFields : TList;
FieldsAmount : Integer;
DBCompareStruct : TDBCompareStruct;
FieldNr : Integer;
StoreDSState : TDataSetState;
FilterBuffer : PChar;
FieldBufPos : PtrInt; // Amount to add to the record buffer to get the FieldBuffer
CurrLinkItem: PBufRecLinkItem;
CurrBuff : pchar;
bm : TBufBookmark;
CheckNull : Boolean;
SaveState : TDataSetState;
begin begin
{$IFDEF ARRAYBUF} {$IFDEF ARRAYBUF}
DatabaseError('Locate is not supported'); DatabaseError('Locate is not supported');
{$ELSE} {$ELSE}
// For now it is only possible to search in one field at the same time Result := False;
result := False;
if IsEmpty then exit; if IsEmpty then exit;
keyfield := FieldByName(keyfields); // Build the DBCompare structure
CheckNull := VarIsNull(KeyValues); SearchFields := TList.Create;
try
GetFieldList(SearchFields,KeyFields);
FieldsAmount:=SearchFields.Count;
if FieldsAmount=0 then exit;
if not CheckNull then SetLength(DBCompareStruct,FieldsAmount);
begin for FieldNr:=0 to FieldsAmount-1 do
SaveState := State; ProcessFieldCompareStruct(TField(SearchFields[FieldNr]),DBCompareStruct[FieldNr]);
SetTempState(dsFilter); finally
keyfield.Value := KeyValues; SearchFields.Free;
RestoreState(SaveState); end;
FieldBufPos := FFieldBufPositions[keyfield.FieldNo-1];
VBLength := keyfield.DataSize;
ValueBuffer := AllocMem(VBLength);
currbuff := pointer(FCurrentIndex^.FLastRecBuf)+sizeof(TBufRecLinkItem)*FMaxIndexesCount+FieldBufPos;
move(currbuff^,ValueBuffer^,VBLength);
end;
// Set The filter-buffer
StoreDSState:=State;
SetTempState(dsFilter);
SetFieldValues(keyfields,KeyValues);
CurrLinkItem := FCurrentIndex^.FFirstRecBuf; CurrLinkItem := FCurrentIndex^.FFirstRecBuf;
FilterBuffer:=IntAllocRecordBuffer;
move(FCurrentIndex^.FLastRecBuf^,FilterBuffer^,FRecordsize+sizeof(TBufRecLinkItem)*FMaxIndexesCount);
SetTempState(StoreDSState);
if CheckNull then // Iterate through the records until a match is found
while (CurrLinkItem <> FCurrentIndex^.FLastRecBuf) do
begin begin
repeat if (IndexCompareRecords(FilterBuffer,CurrLinkItem,DBCompareStruct) = 0) then
currbuff := pointer(CurrLinkItem)+sizeof(TBufRecLinkItem)*FMaxIndexesCount;
if GetFieldIsnull(pbyte(CurrBuff),keyfield.Fieldno-1) then
begin begin
result := True; Result := True;
break; break;
end; end;
CurrLinkItem := CurrLinkItem^.next; CurrLinkItem := CurrLinkItem^.next;
if CurrLinkItem = FCurrentIndex^.FLastRecBuf then getnextpacket; if CurrLinkItem = FCurrentIndex^.FLastRecBuf then
until CurrLinkItem = FCurrentIndex^.FLastRecBuf; getnextpacket;
end
else if keyfield.DataType = ftString then
begin
repeat
currbuff := pointer(CurrLinkItem)+sizeof(TBufRecLinkItem)*FMaxIndexesCount;
if not GetFieldIsnull(pbyte(CurrBuff),keyfield.Fieldno-1) then
begin
inc(CurrBuff,FieldBufPos);
if DBCompareTextLen(ValueBuffer,CurrBuff,VBLength,options) = 0 then
begin
result := True;
break;
end;
end;
CurrLinkItem := CurrLinkItem^.next;
if CurrLinkItem = FCurrentIndex^.FLastRecBuf then getnextpacket;
until CurrLinkItem = FCurrentIndex^.FLastRecBuf;
end
else
begin
repeat
currbuff := pointer(CurrLinkItem)+sizeof(TBufRecLinkItem)*FMaxIndexesCount;
if not GetFieldIsnull(pbyte(CurrBuff),keyfield.Fieldno-1) then
begin
inc(CurrBuff,FieldBufPos);
if CompareByte(ValueBuffer^,CurrBuff^,VBLength) = 0 then
begin
result := True;
break;
end;
end;
CurrLinkItem := CurrLinkItem^.next;
if CurrLinkItem = FCurrentIndex^.FLastRecBuf then getnextpacket;
until CurrLinkItem = FCurrentIndex^.FLastRecBuf;
end; end;
FreeRecordBuffer(FilterBuffer);
// If a match is found, jump to the found record
if Result then if Result then
begin begin
{$IFDEF ARRAYBUF} {$IFDEF ARRAYBUF}
@ -2354,8 +2328,6 @@ begin
bm.BookmarkFlag := bfCurrent; bm.BookmarkFlag := bfCurrent;
GotoBookmark(@bm); GotoBookmark(@bm);
end; end;
ReAllocmem(ValueBuffer,0);
{$ENDIF} {$ENDIF}
end; end;

View File

@ -30,6 +30,8 @@ type
procedure TestCancelUpdDelete1; procedure TestCancelUpdDelete1;
procedure TestCancelUpdDelete2; procedure TestCancelUpdDelete2;
procedure TestBookmarks; procedure TestBookmarks;
procedure TestLocate;
procedure TestFirst; procedure TestFirst;
procedure TestDelete1; procedure TestDelete1;
@ -564,6 +566,28 @@ begin
end; end;
end; end;
procedure TTestDBBasics.TestLocate;
begin
with DBConnector.GetNDataset(true,13) do
begin
open;
asserttrue(Locate('id',vararrayof([5]),[]));
AssertEquals(5,FieldByName('id').AsInteger);
AssertFalse(Locate('id',vararrayof([15]),[]));
asserttrue(Locate('id',vararrayof([12]),[]));
AssertEquals(12,FieldByName('id').AsInteger);
close;
open;
asserttrue(Locate('id',vararrayof([12]),[]));
AssertEquals(12,FieldByName('id').AsInteger);
asserttrue(Locate('id;name',vararrayof([4,'TestName4']),[]));
AssertEquals(4,FieldByName('id').AsInteger);
assertFalse(Locate('id;name',vararrayof([4,'TestName5']),[]));
end;
end;
procedure TTestDBBasics.TestSetFieldValues; procedure TTestDBBasics.TestSetFieldValues;
var PassException : boolean; var PassException : boolean;
begin begin
@ -1297,7 +1321,7 @@ begin
with ds do with ds do
begin begin
AddIndex('testindex','F'+FieldTypeNames[ftString]+', F'+FieldTypeNames[ftInteger],[]); AddIndex('testindex','F'+FieldTypeNames[ftString]+'; F'+FieldTypeNames[ftInteger],[]);
FList := TStringList.Create; FList := TStringList.Create;
FList.Sorted:=true; FList.Sorted:=true;
FList.CaseSensitive:=True; FList.CaseSensitive:=True;