📄 jvqmemorydataset.pas
字号:
end;
destructor TJvMemoryRecord.Destroy;
begin
SetMemoryData(nil, True);
inherited Destroy;
end;
function TJvMemoryRecord.GetIndex: Integer;
begin
if FMemoryData <> nil then
Result := FMemoryData.FRecords.IndexOf(Self)
else
Result := -1;
end;
procedure TJvMemoryRecord.SetMemoryData(Value: TJvMemoryData; UpdateParent: Boolean);
var
I: Integer;
DataSize: Integer;
begin
if FMemoryData <> Value then
begin
if FMemoryData <> nil then
begin
FMemoryData.FRecords.Remove(Self);
if FMemoryData.BlobFieldCount > 0 then
Finalize(PMemBlobArray(FBlobs)[0], FMemoryData.BlobFieldCount);
ReallocMem(FBlobs, 0);
ReallocMem(FData, 0);
FMemoryData := nil;
end;
if Value <> nil then
begin
if UpdateParent then
begin
Value.FRecords.Add(Self);
Inc(Value.FLastID);
FID := Value.FLastID;
end;
FMemoryData := Value;
if Value.BlobFieldCount > 0 then
begin
ReallocMem(FBlobs, Value.BlobFieldCount * SizeOf(Pointer));
Initialize(PMemBlobArray(FBlobs)[0], Value.BlobFieldCount);
end;
DataSize := 0;
for I := 0 to Value.FieldDefs.Count - 1 do
CalcDataSize(Value.FieldDefs[I], DataSize);
ReallocMem(FData, DataSize);
end;
end;
end;
procedure TJvMemoryRecord.SetIndex(Value: Integer);
var
CurIndex: Integer;
begin
CurIndex := GetIndex;
if (CurIndex >= 0) and (CurIndex <> Value) then
FMemoryData.FRecords.Move(CurIndex, Value);
end;
//=== { TJvMemoryData } ======================================================
constructor TJvMemoryData.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FRecordPos := -1;
FLastID := Low(Integer);
FAutoInc := 1;
FRecords := TList.Create;
//------- Added by CFZ ------------------
FStatusName := STATUSNAME;
FDeletedValues := TList.Create;
FRowsOriginal := 0;
FRowsChanged := 0;
FRowsAffected := 0;
FSaveLoadState := slsNone;
FDataSetClosed := True;
//---------------------------------------
end;
destructor TJvMemoryData.Destroy;
var
I: Integer;
PFValues: TPVariant;
begin
//------- Added by CFZ ------------------
if Assigned(FDeletedValues) then
begin
if FDeletedValues.Count > 0 then
for I := 0 to (FDeletedValues.Count - 1) do
begin
PFValues := FDeletedValues[I];
Dispose(PFValues);
end;
FreeAndNil(FDeletedValues);
end;
//---------------------------------------
FreeIndexList;
ClearRecords;
FRecords.Free;
ReallocMem(FOffsets, 0);
inherited Destroy;
end;
function TJvMemoryData.CompareFields(Data1, Data2: Pointer; FieldType: TFieldType;
CaseInsensitive: Boolean): Integer;
begin
Result := 0;
case FieldType of
ftString:
if CaseInsensitive then
Result := AnsiCompareText(PChar(Data1), PChar(Data2))
else
Result := AnsiCompareStr(PChar(Data1), PChar(Data2));
ftSmallint:
if Smallint(Data1^) > Smallint(Data2^) then
Result := 1
else
if Smallint(Data1^) < Smallint(Data2^) then
Result := -1;
ftInteger, ftDate, ftTime, ftAutoInc:
if Longint(Data1^) > Longint(Data2^) then
Result := 1
else
if Longint(Data1^) < Longint(Data2^) then
Result := -1;
ftWord:
if Word(Data1^) > Word(Data2^) then
Result := 1
else
if Word(Data1^) < Word(Data2^) then
Result := -1;
ftBoolean:
if WordBool(Data1^) and not WordBool(Data2^) then
Result := 1
else
if not WordBool(Data1^) and WordBool(Data2^) then
Result := -1;
ftFloat, ftCurrency:
if Double(Data1^) > Double(Data2^) then
Result := 1
else
if Double(Data1^) < Double(Data2^) then
Result := -1;
ftDateTime:
if TDateTime(Data1^) > TDateTime(Data2^) then
Result := 1
else
if TDateTime(Data1^) < TDateTime(Data2^) then
Result := -1;
ftFixedChar:
if CaseInsensitive then
Result := AnsiCompareText(PChar(Data1), PChar(Data2))
else
Result := AnsiCompareStr(PChar(Data1), PChar(Data2));
ftWideString:
if CaseInsensitive then
Result := AnsiCompareText(WideCharToString(PWideChar(Data1)),
WideCharToString(PWideChar(Data2)))
else
Result := AnsiCompareStr(WideCharToString(PWideChar(Data1)),
WideCharToString(PWideChar(Data2)));
ftLargeint:
if Int64(Data1^) > Int64(Data2^) then
Result := 1
else
if Int64(Data1^) < Int64(Data2^) then
Result := -1;
ftVariant:
Result := 0;
ftGuid:
Result := CompareText(PChar(Data1), PChar(Data2));
end;
end;
function TJvMemoryData.GetCapacity: Integer;
begin
if FRecords <> nil then
Result := FRecords.Capacity
else
Result := 0;
end;
procedure TJvMemoryData.SetCapacity(Value: Integer);
begin
if FRecords <> nil then
FRecords.Capacity := Value;
end;
function TJvMemoryData.AddRecord: TJvMemoryRecord;
begin
Result := TJvMemoryRecord.Create(Self);
end;
function TJvMemoryData.FindRecordID(ID: Integer): TJvMemoryRecord;
var
I: Integer;
begin
for I := 0 to FRecords.Count - 1 do
begin
Result := TJvMemoryRecord(FRecords[I]);
if Result.ID = ID then
Exit;
end;
Result := nil;
end;
function TJvMemoryData.InsertRecord(Index: Integer): TJvMemoryRecord;
begin
Result := AddRecord;
Result.Index := Index;
end;
function TJvMemoryData.GetMemoryRecord(Index: Integer): TJvMemoryRecord;
begin
Result := TJvMemoryRecord(FRecords[Index]);
end;
procedure TJvMemoryData.InitFieldDefsFromFields;
var
I: Integer;
Offset: Word;
begin
if FieldDefs.Count = 0 then
begin
for I := 0 to FieldCount - 1 do
begin
with Fields[I] do
if (FieldKind in fkStoredFields) and not (DataType in ftSupported) then
ErrorFmt(SUnknownFieldType, [DisplayName]);
end;
FreeIndexList;
end;
Offset := 0;
inherited InitFieldDefsFromFields;
{ Calculate fields offsets }
ReallocMem(FOffsets, FieldDefList.Count * SizeOf(Word));
for I := 0 to FieldDefList.Count - 1 do
begin
FOffsets^[I] := Offset;
with FieldDefList[I] do
begin
if DataType in ftSupported - ftBlobTypes then
Inc(Offset, CalcFieldLen(DataType, Size) + 1);
end;
end;
end;
function TJvMemoryData.FindFieldData(Buffer: Pointer; Field: TField): Pointer;
var
Index: Integer;
DataType: TFieldType;
begin
Result := nil;
Index := FieldDefList.IndexOf(Field.FullName);
if (Index >= 0) and (Buffer <> nil) then
begin
DataType := FieldDefList[Index].DataType;
if DataType in ftSupported then
if DataType in ftBlobTypes then
Result := Pointer(GetBlobData(Field, Buffer))
else
Result := (PChar(Buffer) + FOffsets[Index]);
end;
end;
function TJvMemoryData.CalcRecordSize: Integer;
var
I: Integer;
begin
Result := 0;
for I := 0 to FieldDefs.Count - 1 do
CalcDataSize(FieldDefs[I], Result);
end;
procedure TJvMemoryData.InitBufferPointers(GetProps: Boolean);
begin
if GetProps then
FRecordSize := CalcRecordSize;
FBookmarkOfs := FRecordSize + CalcFieldsSize;
FBlobOfs := FBookmarkOfs + SizeOf(TMemBookmarkInfo);
FRecBufSize := FBlobOfs + BlobFieldCount * SizeOf(Pointer);
end;
procedure TJvMemoryData.ClearRecords;
begin
while FRecords.Count > 0 do
TObject(FRecords.Last).Free;
FLastID := Low(Integer);
FRecordPos := -1;
end;
function TJvMemoryData.AllocRecordBuffer: PChar;
begin
Result := StrAlloc(FRecBufSize);
if BlobFieldCount > 0 then
Initialize(PMemBlobArray(Result + FBlobOfs)[0], BlobFieldCount);
end;
procedure TJvMemoryData.FreeRecordBuffer(var Buffer: PChar);
begin
if BlobFieldCount > 0 then
Finalize(PMemBlobArray(Buffer + FBlobOfs)[0], BlobFieldCount);
StrDispose(Buffer);
Buffer := nil;
end;
procedure TJvMemoryData.ClearCalcFields(Buffer: PChar);
begin
FillChar(Buffer[FRecordSize], CalcFieldsSize, 0);
end;
procedure TJvMemoryData.InternalInitRecord(Buffer: PChar);
var
I: Integer;
begin
FillChar(Buffer^, FBlobOfs, 0);
for I := 0 to BlobFieldCount - 1 do
PMemBlobArray(Buffer + FBlobOfs)[I] := '';
end;
procedure TJvMemoryData.InitRecord(Buffer: PChar);
begin
inherited InitRecord(Buffer);
with PMemBookmarkInfo(Buffer + FBookmarkOfs)^ do
begin
BookmarkData := Low(Integer);
BookmarkFlag := bfInserted;
end;
end;
function TJvMemoryData.GetCurrentRecord(Buffer: PChar): Boolean;
begin
Result := False;
if not IsEmpty and (GetBookmarkFlag(ActiveBuffer) = bfCurrent) then
begin
UpdateCursorPos;
if (FRecordPos >= 0) and (FRecordPos < RecordCount) then
begin
Move(Records[FRecordPos].Data^, Buffer^, FRecordSize);
Result := True;
end;
end;
end;
procedure TJvMemoryData.RecordToBuffer(Rec: TJvMemoryRecord; Buffer: PChar);
var
I: Integer;
begin
Move(Rec.Data^, Buffer^, FRecordSize);
with PMemBookmarkInfo(Buffer + FBookmarkOfs)^ do
begin
BookmarkData := Rec.ID;
BookmarkFlag := bfCurrent;
end;
for I := 0 to BlobFieldCount - 1 do
PMemBlobArray(Buffer + FBlobOfs)[I] := PMemBlobArray(Rec.FBlobs)[I];
GetCalcFields(Buffer);
end;
function TJvMemoryData.GetRecord(Buffer: PChar; GetMode: TGetMode;
DoCheck: Boolean): TGetResult;
var
Accept: Boolean;
begin
Result := grOk;
Accept := True;
case GetMode of
gmPrior:
if FRecordPos <= 0 then
begin
Result := grBOF;
FRecordPos := -1;
end
else
begin
repeat
Dec(FRecordPos);
if Filtered then
Accept := RecordFilter;
until Accept or (FRecordPos < 0);
if not Accept then
begin
Result := grBOF;
FRecordPos := -1;
end;
end;
gmCurrent:
if (FRecordPos < 0) or (FRecordPos >= RecordCount) then
Result := grError
else
if Filtered then
if not RecordFilter then
Result := grError;
gmNext:
if FRecordPos >= RecordCount - 1 then
Result := grEOF
else
begin
repeat
Inc(FRecordPos);
if Filtered then
Accept := RecordFilter;
until Accept or (FRecordPos > RecordCount - 1);
if not Accept then
begin
Result := grEOF;
FRecordPos := RecordCount - 1;
end;
end;
end;
if Result = grOk then
RecordToBuffer(Records[FRecordPos], Buffer)
else
if (Result = grError) and DoCheck then
Error(RsEMemNoRecords);
end;
function TJvMemoryData.GetRecordSize: Word;
begin
Result := FRecordSize;
end;
function TJvMemoryData.GetActiveRecBuf(var RecBuf: PChar): Boolean;
begin
case State of
dsBrowse:
if IsEmpty then
RecBuf := nil
else
RecBuf := ActiveBuffer;
dsEdit, dsInsert:
RecBuf := ActiveBuffer;
dsCalcFields:
RecBuf := CalcBuffer;
dsFilter:
RecBuf := TempBuffer;
else
RecBuf := nil;
end;
Result := RecBuf <> nil;
end;
function TJvMemoryData.GetFieldData(Field: TField; Buffer: Pointer): Boolean;
var
RecBuf, Data: PChar;
VarData: Variant;
begin
Result := False;
if not GetActiveRecBuf(RecBuf) then
Exit;
if Field.FieldNo > 0 then
begin
Data := FindFieldData(RecBuf, Field);
if Data <> nil then
begin
if Field is TBlobField then
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -