mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-12 18:49:16 +02:00
* 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:
parent
a681f946f8
commit
683f59a70c
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user