Delphi Locate函数[2] - 查询、定位(TCustomADODataSet、TCustomClientDataSet) 功能源码
Delphi Locate函数[2] - 查询、定位(TCustomADODataSet、TCustomClientDataSet)功能源码
1、单元:ADODB
原型:
function TCustomADODataSet.Locate(const KeyFields: string;
const KeyValues: Variant; Options: TLocateOptions): Boolean;
begin
DoBeforeScroll;
Result := LocateRecord(KeyFields, KeyValues, Options, True);
if Result then
begin
Resync([rmExact, rmCenter]);
DoAfterScroll;
end;
end;
TCustomADODataSet.LocateRecord
function TCustomADODataSet.LocateRecord(const KeyFields: string;
const KeyValues: OleVariant; Options: TLocateOptions;
SyncCursor: Boolean): Boolean;
var
Fields: TList;
Buffer: PChar;
I, FieldCount: Integer;
Partial: Boolean;
SortList, FieldExpr, LocateFilter: string;
begin
CheckBrowseMode;
UpdateCursorPos;
CursorPosChanged;
Buffer := TempBuffer;
Partial := loPartialKey in Options;
Fields := TList.Create;
DoBeforeScroll;
try
try
GetFieldList(Fields, KeyFields);
if not Assigned(FLookupCursor) then
FLookupCursor := Recordset.Clone(adLockReadOnly);
if CursorLocation = clUseClient then
begin
for I := 0 to Fields.Count - 1 do
with TField(Fields[I]) do
if Pos(' ', FieldName) > 0 then
SortList := Format('%s[%s],', [SortList, FieldName]) else
SortList := Format('%s%s,', [SortList, FieldName]);
SetLength(SortList, Length(SortList)-1);
if FLookupCursor.Sort <> SortList then
FLookupCursor.Sort := SortList;
end;
FLookupCursor.Filter := '';
FFilterBuffer := Buffer;
SetTempState(dsFilter);
try
InitRecord(Buffer);
FieldCount := Fields.Count;
if FieldCount = 1 then
FLookupCursor.Find(GetFilterStr(FieldByName(KeyFields), KeyValues, Partial), 0,
adSearchForward, EmptyParam)
else
begin
for I := 0 to FieldCount - 1 do
begin
FieldExpr := GetFilterStr(Fields[I], KeyValues[I], (Partial and (I = FieldCount-1)));
if LocateFilter <> '' then
LocateFilter := LocateFilter + ' AND ' + FieldExpr else { Do not localize }
LocateFilter := FieldExpr;
end;
FLookupCursor.Filter := LocateFilter;
end;
finally
RestoreState(dsBrowse);
end;
finally
Fields.Free;
end;
Result := not FLookupCursor.EOF;
if Result then
if SyncCursor then
begin
Recordset.Bookmark := FLookupCursor.Bookmark;
if Recordset.EOF or Recordset.BOF then
begin
Result := False;
CursorPosChanged;
end
end
else
{ For lookups, read all field values into the temp buffer }
for I := 0 to Self.Fields.Count - 1 do
with Self.Fields[I] do
if FieldKind = fkData then
PVariantList(Buffer+SizeOf(TRecInfo))[Index] := FLookupCursor.Fields[FieldNo-1].Value;
except
Result := False;
end;
end;
2、单元:DBClient
原型:
function TCustomClientDataSet.Locate(const KeyFields: string;
const KeyValues: Variant; Options: TLocateOptions): Boolean;
begin
DoBeforeScroll;
Result := LocateRecord(KeyFields, KeyValues, Options, True);
if Result then
begin
Resync([rmExact, rmCenter]);
DoAfterScroll;
end;
end;
TCustomClientDataSet.LocateRecord
function TCustomClientDataSet.LocateRecord(const KeyFields: string;
const KeyValues: Variant; Options: TLocateOptions;
SyncCursor: Boolean): Boolean;
var
Fields: TList;
I: Integer;
Status: DBResult;
FilterOptions: TFilterOptions;
ExprParser: TExprParser;
ValStr, Expr: string;
Value: Variant;
begin
CheckBrowseMode;
UpdateCursorPos;
CursorPosChanged;
CheckProviderEOF;
Fields := TList.Create;
try
GetFieldList(Fields, KeyFields);
Expr := '';
for i := 0 to Fields.Count - 1 do
begin
if (Fields.Count = 1) and not VarIsArray(KeyValues) then
Value := KeyValues else
Value := KeyValues[i];
case TField(Fields[i]).DataType of
ftString, ftFixedChar, ftWideString, ftGUID:
if (i = Fields.Count - 1) and (loPartialKey in Options) then
ValStr := QuotedStr(VarToStr(Value) + '*') else
ValStr := QuotedStr(VarToStr(Value));
ftDate, ftTime, ftDateTime, ftTimeStamp:
ValStr := Format('''%s''',[VarToStr(Value)]);
ftSmallint, ftInteger, ftWord, ftAutoInc, ftBoolean, ftFloat, ftCurrency, ftBCD, ftLargeInt, ftFMTBcd:
ValStr := VarToStr(Value);
else
DatabaseErrorFmt(SBadFieldType, [TField(Fields[i]).FieldName]);
end;
if Expr <> '' then
Expr := Expr + ' and '; { Do not localize }
if VarIsNull(Value) then
Expr := Expr + Format('[%s] IS NULL',[TField(Fields[i]).FieldName]) { Do not localize }
else
Expr := Expr + Format('[%s]=%s',[TField(Fields[i]).FieldName, ValStr]);
end;
FilterOptions := [];
if loCaseInsensitive in Options then
FilterOptions := [foCaseInsensitive];
if not (loPartialKey in Options) then
Include(FilterOptions, foNoPartialCompare);
ExprParser := TExprParser.Create(Self, Expr, FilterOptions, [], '', nil, FieldTypeMap);
try
FDSCursor.MoveToBOF;
Status := FDSCursor.LocateWithFilter(ExprParser.FilterData, ExprParser.DataSize);
if Status = DBERR_NONE then
FDSCursor.GetCurrentRecord(TempBuffer);
finally
ExprParser.Free;
end;
finally
Fields.Free;
end;
Result := Status = DBERR_NONE;
end;
3、单元:DB
function TDataSet.Locate(const KeyFields: string; const KeyValues: Variant;
Options: TLocateOptions): Boolean;
begin
Result := False;
end;
TDataSet.Resync
procedure TDataSet.Resync(Mode: TResyncMode);
var
Count: Integer;
begin
if not IsUniDirectional then
begin
if rmExact in Mode then
begin
CursorPosChanged;
if GetRecord(FBuffers[FRecordCount], gmCurrent, True) <> grOK then
DatabaseError(SRecordNotFound, Self);
end else
if (GetRecord(FBuffers[FRecordCount], gmCurrent, False) <> grOK) and
(GetRecord(FBuffers[FRecordCount], gmNext, False) <> grOK) and
(GetRecord(FBuffers[FRecordCount], gmPrior, False) <> grOK) then
begin
ClearBuffers;
DataEvent(deDataSetChange, 0);
Exit;
end;
if rmCenter in Mode then
Count := (FBufferCount - 1) div 2 else
Count := FActiveRecord;
MoveBuffer(FRecordCount, 0);
ActivateBuffers;
try
while (Count > 0) and GetPriorRecord do Dec(Count);
GetNextRecords;
GetPriorRecords;
finally
DataEvent(deDataSetChange, 0);
end;
end;
end;
创建时间:2021.01.29 更新时间:2021.02.22
博客园 滔Roy https://www.cnblogs.com/guorongtao 希望内容对你有所帮助,谢谢!
浙公网安备 33010602011771号