mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-06 10:50:31 +02:00
* Fix crash when using a lookup field of memo type (correctly calculate field offset)
* Ensure Field Change event is always called in Write mode (Write method is not called if new text is empty) git-svn-id: trunk@14120 -
This commit is contained in:
parent
d111f9220d
commit
5f3905f095
@ -56,17 +56,22 @@ type
|
||||
Previous: PDataRecord;
|
||||
end;
|
||||
|
||||
{ TDSStream }
|
||||
//todo: refactor into two or three classes
|
||||
TDSStream = class(TStream)
|
||||
private
|
||||
FActiveItem: PDataRecord;
|
||||
FEditItem: PDataRecord;
|
||||
FDataset: TCustomSqliteDataset;
|
||||
FFieldRow: PChar;
|
||||
FField: TField;
|
||||
FFieldOffset: Integer;
|
||||
FRowSize: Integer;
|
||||
FPosition: LongInt;
|
||||
FWriteMode: Boolean;
|
||||
public
|
||||
constructor Create(Dataset: TCustomSqliteDataset; Field: TField);
|
||||
constructor Create(Dataset: TCustomSqliteDataset; Field: TField;
|
||||
FieldOffset: Integer; EditItem: PDataRecord; WriteMode: Boolean);
|
||||
destructor Destroy; override;
|
||||
function Write(const Buffer; Count: LongInt): LongInt; override;
|
||||
function Read(var Buffer; Count: LongInt): LongInt; override;
|
||||
function Seek(Offset: LongInt; Origin: Word): LongInt; override;
|
||||
@ -329,23 +334,29 @@ end;
|
||||
|
||||
// TDSStream
|
||||
|
||||
constructor TDSStream.Create(Dataset: TCustomSqliteDataset; Field: TField);
|
||||
constructor TDSStream.Create(Dataset: TCustomSqliteDataset; Field: TField;
|
||||
FieldOffset: Integer; EditItem: PDataRecord; WriteMode: Boolean);
|
||||
begin
|
||||
inherited Create;
|
||||
//FPosition := 0;
|
||||
FDataset := Dataset;
|
||||
FField := Field;
|
||||
if Field.FieldNo >= 0 then
|
||||
FFieldOffset := Field.FieldNo - 1
|
||||
else
|
||||
FFieldOffset := Dataset.FieldDefs.Count + Dataset.FCalcFieldList.IndexOf(Field);
|
||||
FActiveItem := PPDataRecord(Dataset.ActiveBuffer)^;
|
||||
FFieldRow := FActiveItem^.Row[FFieldOffset];
|
||||
FFieldOffset := FieldOffset;
|
||||
FWriteMode := WriteMode;
|
||||
FEditItem := EditItem;
|
||||
FFieldRow := FEditItem^.Row[FFieldOffset];
|
||||
if FFieldRow <> nil then
|
||||
FRowSize := StrLen(FFieldRow);
|
||||
//else
|
||||
// FRowSize := 0;
|
||||
end;
|
||||
end;
|
||||
|
||||
destructor TDSStream.Destroy;
|
||||
begin
|
||||
if FWriteMode and not (FDataset.State in [dsCalcFields, dsFilter, dsNewValue]) then
|
||||
FDataset.DataEvent(deFieldChange, PtrInt(FField));
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function TDSStream.Seek(Offset: LongInt; Origin: Word): LongInt;
|
||||
begin
|
||||
@ -362,30 +373,29 @@ var
|
||||
NewRow: PChar;
|
||||
begin
|
||||
Result := Count;
|
||||
if Count = 0 then
|
||||
Exit;
|
||||
//FRowSize is always 0 when FPosition = 0,
|
||||
//so there's no need to check FPosition
|
||||
NewRow := StrAlloc(FRowSize + Count + 1);
|
||||
(NewRow + Count + FRowSize)^ := #0;
|
||||
if FRowSize > 0 then
|
||||
Move(FFieldRow^, NewRow^, FRowSize);
|
||||
Move(Buffer, (NewRow + FRowSize)^, Count);
|
||||
FActiveItem^.Row[FFieldOffset] := NewRow;
|
||||
StrDispose(FFieldRow);
|
||||
{$ifdef DEBUG_SQLITEDS}
|
||||
WriteLn('##TDSStream.Write##');
|
||||
WriteLn(' FPosition(Before): ', FPosition);
|
||||
WriteLn(' FRowSize(Before): ', FRowSize);
|
||||
WriteLn(' FPosition(After): ', FPosition+Count);
|
||||
WriteLn(' FRowSize(After): ', StrLen(NewRow));
|
||||
//WriteLn(' Stream Value: ',NewRow);
|
||||
{$endif}
|
||||
FFieldRow := NewRow;
|
||||
FRowSize := StrLen(NewRow);
|
||||
Inc(FPosition, Count);
|
||||
if not (FDataset.State in [dsCalcFields, dsFilter, dsNewValue]) then
|
||||
FDataset.DataEvent(deFieldChange, PtrInt(FField));
|
||||
if Count > 0 then
|
||||
begin
|
||||
//FRowSize is always 0 when FPosition = 0,
|
||||
//so there's no need to check FPosition
|
||||
NewRow := StrAlloc(FRowSize + Count + 1);
|
||||
(NewRow + Count + FRowSize)^ := #0;
|
||||
if FRowSize > 0 then
|
||||
Move(FFieldRow^, NewRow^, FRowSize);
|
||||
Move(Buffer, (NewRow + FRowSize)^, Count);
|
||||
FEditItem^.Row[FFieldOffset] := NewRow;
|
||||
StrDispose(FFieldRow);
|
||||
{$ifdef DEBUG_SQLITEDS}
|
||||
WriteLn('##TDSStream.Write##');
|
||||
WriteLn(' FPosition(Before): ', FPosition);
|
||||
WriteLn(' FRowSize(Before): ', FRowSize);
|
||||
WriteLn(' FPosition(After): ', FPosition+Count);
|
||||
WriteLn(' FRowSize(After): ', StrLen(NewRow));
|
||||
//WriteLn(' Stream Value: ',NewRow);
|
||||
{$endif}
|
||||
FFieldRow := NewRow;
|
||||
FRowSize := StrLen(NewRow);
|
||||
Inc(FPosition, Count);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TDSStream.Read(var Buffer; Count: Longint): LongInt;
|
||||
@ -456,18 +466,31 @@ begin
|
||||
end;
|
||||
|
||||
function TCustomSqliteDataset.CreateBlobStream(Field: TField; Mode: TBlobStreamMode): TStream;
|
||||
var
|
||||
FieldOffset: Integer;
|
||||
EditItem: PDataRecord;
|
||||
begin
|
||||
if Field.FieldNo >= 0 then
|
||||
begin
|
||||
if Mode = bmWrite then
|
||||
EditItem := FCacheItem
|
||||
else
|
||||
EditItem := PPDataRecord(ActiveBuffer)^;
|
||||
FieldOffset := Field.FieldNo - 1;
|
||||
end
|
||||
else
|
||||
begin
|
||||
EditItem := PPDataRecord(CalcBuffer)^;
|
||||
FieldOffset := FieldDefs.Count + FCalcFieldList.IndexOf(Field);
|
||||
end;
|
||||
if Mode = bmWrite then
|
||||
begin
|
||||
if not (State in [dsEdit, dsInsert]) then
|
||||
begin
|
||||
DatabaseErrorFmt(SNotEditing,[Name],Self);
|
||||
Exit;
|
||||
end;
|
||||
StrDispose(FCacheItem^.Row[Field.FieldNo - 1]);
|
||||
FCacheItem^.Row[Field.FieldNo - 1] := nil;
|
||||
if not (State in [dsEdit, dsInsert, dsCalcFields]) then
|
||||
DatabaseErrorFmt(SNotEditing, [Name], Self);
|
||||
StrDispose(EditItem^.Row[FieldOffset]);
|
||||
EditItem^.Row[FieldOffset] := nil;
|
||||
end;
|
||||
Result := TDSStream.Create(Self, Field);
|
||||
Result := TDSStream.Create(Self, Field, FieldOffset, EditItem, Mode = bmWrite);
|
||||
end;
|
||||
|
||||
procedure TCustomSqliteDataset.DoBeforeClose;
|
||||
|
Loading…
Reference in New Issue
Block a user