?? memtableeh.pas
字號:
function GetBlobFromRecord(Field: TField): TMemBlobData;
function GetBlobSize: Longint;
public
constructor Create(Field: TBlobField; Mode: TBlobStreamMode);
destructor Destroy; override;
function Read(var Buffer; Count: Longint): Longint; override;
function Seek(Offset: Longint; Origin: Word): Longint; override;
function Write(const Buffer; Count: Longint): Longint; override;
procedure Truncate;
end;
{ TMemTableEh }
TMemTableEh = class(TCustomMemTableEh)
published
property Active;
property AutoCalcFields;
property CachedUpdates;
property DetailFields;
property FieldDefs;
property Filtered;
property FetchAllOnOpen; //FetchAllOnOpen
property KeyFields;
property MasterDetailSide;
property MasterFields;
property MasterSource;
property Params;
property ProviderDataSet;
property ReadOnly;
// property ObjectView default False;
property BeforeOpen;
property AfterOpen;
property BeforeClose;
property AfterClose;
property BeforeInsert;
property AfterInsert;
property BeforeEdit;
property AfterEdit;
property BeforePost;
property AfterPost;
property BeforeCancel;
property AfterCancel;
property BeforeDelete;
property AfterDelete;
property BeforeScroll;
property AfterScroll;
property BeforeRefresh;
property AfterRefresh;
property OnCalcFields;
property OnDeleteError;
property OnEditError;
property OnFetchRecord;
property OnFilterRecord;
property OnNewRecord;
property OnPostError;
property OnUpdateRecord;
end;
procedure Register;
implementation
uses Forms, DbConsts, Math{, dbRecordFilter};
procedure Register;
begin
RegisterComponents('EhLib', [TMemTableEh]);
end;
resourcestring
SMemNoRecords = 'No data found';
const
ftBlobTypes = [ftBlob, ftMemo, ftGraphic, ftFmtMemo, ftParadoxOle,
ftDBaseOle, ftTypedBinary {$IFDEF EH_LIB_5}, ftOraBlob, ftOraClob {$ENDIF}];
ftSupported = [ftString, ftSmallint, ftInteger, ftWord, ftBoolean, ftFloat,
ftCurrency, ftDate, ftTime, ftDateTime, ftAutoInc, ftBCD, ftBytes,
ftVarBytes, ftADT, ftFixedChar, ftWideString,
ftLargeint {$IFDEF EH_LIB_5}, ftVariant, ftGuid {$ENDIF}] +
ftBlobTypes;
fkStoredFields = [fkData];
{$IFDEF EH_LIB_5}
GuidSize = 38;
{$ENDIF}
type
PRecInfo = ^TRecInfo;
TRecInfo = packed record
Bookmark: TRecIdEh;
BookmarkFlag: TBookmarkFlag;
RecordStatus: Integer;
RecordNumber: Integer;
end;
TFieldValBuf = packed record
IsNull: Boolean;
DataValue: String;
end;
PFieldValBuf = ^TFieldValBuf;
// TRecBufValues = array [0..0] of Pointer;
// PRecBufValues = ^TRecBufValues;
TFBRecBufValues = array of TFieldValBuf;
TRecBuf = packed record
RecInfo: TRecInfo;
Values: TFBRecBufValues;
end;
PRecBuf = ^TRecBuf;
{ Utility routines }
function 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;
{$IFDEF EH_LIB_5}
ftVariant:
Result := 0;
ftGuid:
Result := AnsiCompareText(PChar(Data1), PChar(Data2));
{$ENDIF}
end;
end;
function CalcFieldLen(FieldType: TFieldType; Size: Word): Word;
begin
if not (FieldType in ftSupported) then
Result := 0
else if (FieldType in ftBlobTypes) then
Result := SizeOf(Longint)
else
begin
Result := Size;
case FieldType of
ftString: Inc(Result);
ftSmallint: Result := SizeOf(SmallInt);
ftInteger: Result := SizeOf(Longint);
ftWord: Result := SizeOf(Word);
ftBoolean: Result := SizeOf(WordBool);
ftFloat: Result := SizeOf(Double);
ftCurrency: Result := SizeOf(Double);
ftBCD: Result := 34;
ftDate, ftTime: Result := SizeOf(Longint);
ftDateTime: Result := SizeOf(TDateTime);
ftBytes: Result := Size;
ftVarBytes: Result := Size + 2;
ftAutoInc: Result := SizeOf(Longint);
ftADT: Result := 0;
ftFixedChar: Inc(Result);
ftWideString: Result := (Result + 1) * 2;
ftLargeint: Result := SizeOf(Int64);
{$IFDEF EH_LIB_5}
ftVariant: Result := SizeOf(Variant);
ftGuid: Result := GuidSize + 1;
{$ENDIF}
end;
end;
end;
procedure CalcDataSize(FieldDef: TFieldDef; var DataSize: Integer);
var
I: Integer;
begin
with FieldDef do
begin
if (DataType in ftSupported - ftBlobTypes) then
Inc(DataSize, CalcFieldLen(DataType, Size) + 1);
for I := 0 to ChildDefs.Count - 1 do
CalcDataSize(ChildDefs[I], DataSize);
end;
end;
procedure Error(const Msg: string);
begin
DatabaseError(Msg);
end;
procedure ErrorFmt(const Msg: string; const Args: array of const);
begin
DatabaseErrorFmt(Msg, Args);
end;
//{$DEBUGINFO OFF}
function VarEquals(const V1, V2: Variant): Boolean;
var i: Integer;
begin
Result := not (VarIsArray(V1) xor VarIsArray(V2));
if not Result then Exit;
Result := False;
try
if VarIsArray(V1) and VarIsArray(V2) and
(VarArrayDimCount(V1) = VarArrayDimCount(V2)) and
(VarArrayLowBound(V1, 1) = VarArrayLowBound(V2, 1)) and
(VarArrayHighBound(V1, 1) = VarArrayHighBound(V2, 1))
then
for i := VarArrayLowBound(V1, 1) to VarArrayHighBound(V1, 1) do
begin
Result := V1[i] = V2[i];
if not Result then Exit;
end
else
Result := V1 = V2;
except
end;
end;
//{$DEBUGINFO ON}
function GetOldFieldValue(DataSet: TDataSet; const FieldName: string): Variant;
var
I: Integer;
Fields: TList;
begin
if Pos(';', FieldName) <> 0 then
begin
Fields := TList.Create;
try
DataSet.GetFieldList(Fields, FieldName);
Result := VarArrayCreate([0, Fields.Count - 1], varVariant);
for I := 0 to Fields.Count - 1 do
Result[I] := TField(Fields[I]).OldValue;
finally
Fields.Free;
end;
end else
Result := DataSet.FieldByName(FieldName).OldValue
end;
{ TMasterDataLinkEh }
constructor TMasterDataLinkEh.Create(DataSet: TDataSet);
begin
inherited Create;
FDataSet := DataSet;
FFields := TList.Create;
end;
destructor TMasterDataLinkEh.Destroy;
begin
FFields.Free;
inherited Destroy;
end;
procedure TMasterDataLinkEh.ActiveChanged;
begin
FFields.Clear;
if Active then
try
DataSet.GetFieldList(FFields, FFieldNames);
except
FFields.Clear;
raise;
end;
if FDataSet.Active and not (csDestroying in FDataSet.ComponentState) then
if Active {and (FFields.Count > 0)} then
begin
if Assigned(FOnMasterChange) then FOnMasterChange(Self);
end else
if Assigned(FOnMasterDisable) then FOnMasterDisable(Self);
end;
procedure TMasterDataLinkEh.CheckBrowseMode;
begin
if FDataSet.Active then FDataSet.CheckBrowseMode;
end;
function TMasterDataLinkEh.GetDetailDataSet: TDataSet;
begin
Result := FDataSet;
end;
procedure TMasterDataLinkEh.LayoutChanged;
begin
ActiveChanged;
end;
procedure TMasterDataLinkEh.RecordChanged(Field: TField);
begin
if (DataSource.State <> dsSetKey) and FDataSet.Active and
{(FFields.Count > 0) and }((Field = nil) or
(FFields.IndexOf(Field) >= 0)) and
Assigned(FOnMasterChange)
then
FOnMasterChange(Self);
end;
procedure TMasterDataLinkEh.SetFieldNames(const Value: string);
begin
if FFieldNames <> Value then
begin
FFieldNames := Value;
ActiveChanged;
end;
end;
{ TMemoryRecordEh }
constructor TMemoryRecordEh.Create(MemoryData: TCustomMemTableEh);
begin
inherited Create;
New(FData);
FUpdateStatus := usUnmodified;
FUpdateIndex := -1;
end;
destructor TMemoryRecordEh.Destroy;
begin
MergeChanges;
Dispose(FData);
inherited Destroy;
end;
function TMemoryRecordEh.GetAttached: Boolean;
begin
Result := (Index <> -1);
end;
procedure TMemoryRecordEh.BeginEdit;
begin
if FChangeCount = 0 then
begin
if FTmpOldRecValue = nil then
New(FTmpOldRecValue);
FTmpOldRecValue^ := FData^;
end;
Inc(FChangeCount);
end;
procedure TMemoryRecordEh.EndEdit(Changed: Boolean);
begin
if Changed then
FChanged := Changed;
if FChangeCount > 0 then
Dec(FChangeCount);
if FChangeCount = 0 then
begin
if FChanged and (RecordsList <> nil) then
RecordsList.Notify(Self, Index, rlnRecChangedEh);
if FChanged and (RecordsList <> nil) and
RecordsList.CachedUpdates and (FUpdateStatus <> usInserted) then
begin
FUpdateStatus := usModified;
if FUpdateIndex = -1 then
FUpdateIndex := RecordsList.FDeltaList.Add(Self);
if FOldData = nil then
FOldData := FTmpOldRecValue;
FTmpOldRecValue := nil;
end;
if FTmpOldRecValue <> nil then
begin
Dispose(FTmpOldRecValue);
FTmpOldRecValue := nil;
end;
FChanged := False;
end;
end;
procedure TMemoryRecordEh.MergeChanges;
begin
if FOldData = nil then Exit;
Dispose(FOldData);
FOldData := nil;
FUpdateStatus := usUnmodified;
end;
function TMemoryRecordEh.GetIndex: Integer;
begin
if FRecordsList <> nil then
Result := FRecordsList.IndexOf(Self) else
Result := -1;
end;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -