📄 dbf_fields.pas
字号:
unit dbf_fields;
interface
{$I dbf_common.inc}
uses
Classes,
SysUtils,
db,
dbf_common,
dbf_str;
type
PDbfFieldDef = ^TDbfFieldDef;
TDbfFieldDef = class(TCollectionItem)
private
FFieldName: string;
FFieldType: TFieldType;
FNativeFieldType: TDbfFieldType;
FDefaultBuf: PChar;
FMinBuf: PChar;
FMaxBuf: PChar;
FSize: Integer;
FPrecision: Integer;
FHasDefault: Boolean;
FHasMin: Boolean;
FHasMax: Boolean;
FAllocSize: Integer;
FCopyFrom: Integer;
FOffset: Integer;
FAutoInc: Cardinal;
FRequired: Boolean;
FIsLockField: Boolean;
FNullPosition: integer;
function GetDbfVersion: TXBaseVersion;
procedure SetNativeFieldType(lFieldType: TDbfFieldType);
procedure SetFieldType(lFieldType: TFieldType);
procedure SetSize(lSize: Integer);
procedure SetPrecision(lPrecision: Integer);
procedure VCLToNative;
procedure NativeToVCL;
procedure FreeBuffers;
protected
function GetDisplayName: string; override;
procedure AssignTo(Dest: TPersistent); override;
property DbfVersion: TXBaseVersion read GetDbfVersion;
public
constructor Create(ACollection: TCollection); override;
destructor Destroy; override;
procedure Assign(Source: TPersistent); override;
procedure AssignDb(DbSource: TFieldDef);
procedure CheckSizePrecision;
procedure SetDefaultSize;
procedure AllocBuffers;
function IsBlob: Boolean;
property DefaultBuf: PChar read FDefaultBuf;
property MinBuf: PChar read FMinBuf;
property MaxBuf: PChar read FMaxBuf;
property HasDefault: Boolean read FHasDefault write FHasDefault;
property HasMin: Boolean read FHasMin write FHasMin;
property HasMax: Boolean read FHasMax write FHasMax;
property Offset: Integer read FOffset write FOffset;
property AutoInc: Cardinal read FAutoInc write FAutoInc;
property IsLockField: Boolean read FIsLockField write FIsLockField;
property CopyFrom: Integer read FCopyFrom write FCopyFrom;
published
property FieldName: string read FFieldName write FFieldName;
property FieldType: TFieldType read FFieldType write SetFieldType;
property NativeFieldType: TDbfFieldType read FNativeFieldType write SetNativeFieldType;
property NullPosition: integer read FNullPosition write FNullPosition;
property Size: Integer read FSize write SetSize;
property Precision: Integer read FPrecision write SetPrecision;
property Required: Boolean read FRequired write FRequired;
end;
TDbfFieldDefs = class(TCollection)
private
FOwner: TPersistent;
FDbfVersion: TXBaseVersion;
function GetItem(Idx: Integer): TDbfFieldDef;
protected
function GetOwner: TPersistent; override;
public
constructor Create(Owner: TPersistent);
{$ifdef SUPPORT_DEFAULT_PARAMS}
procedure Add(const Name: string; DataType: TFieldType; Size: Integer = 0; Required: Boolean = False);
{$else}
procedure Add(const Name: string; DataType: TFieldType; Size: Integer; Required: Boolean);
{$endif}
function AddFieldDef: TDbfFieldDef;
property Items[Idx: Integer]: TDbfFieldDef read GetItem;
property DbfVersion: TXBaseVersion read FDbfVersion write FDbfVersion;
end;
implementation
uses
dbf_dbffile; // for dbf header structures
{$I dbf_struct.inc}
// I keep changing that fields...
// Last time has been asked by Venelin Georgiev
// Is he going to be the last ?
const
(*
The theory until now was :
ftSmallint 16 bits = -32768 to 32767
123456 = 6 digit max theorically
DIGITS_SMALLINT = 6;
ftInteger 32 bits = -2147483648 to 2147483647
12345678901 = 11 digits max
DIGITS_INTEGER = 11;
ftLargeInt 64 bits = -9223372036854775808 to 9223372036854775807
12345678901234567890 = 20 digits max
DIGITS_LARGEINT = 20;
But in fact if I accept 6 digits into a ftSmallInt then tDbf will not
being able to handles fields with 999999 (6 digits).
So I now oversize the field type in order to accept anithing coming from the
database.
ftSmallint 16 bits = -32768 to 32767
-999 to 9999
4 digits max theorically
DIGITS_SMALLINT = 4;
ftInteger 32 bits = -2147483648 to 2147483647
-99999999 to 999999999 12345678901 = 11 digits max
DIGITS_INTEGER = 9;
ftLargeInt 64 bits = -9223372036854775808 to 9223372036854775807
-99999999999999999 to 999999999999999999
DIGITS_LARGEINT = 18;
*)
DIGITS_SMALLINT = 4;
DIGITS_INTEGER = 9;
DIGITS_LARGEINT = 18;
//====================================================================
// DbfFieldDefs
//====================================================================
function TDbfFieldDefs.GetItem(Idx: Integer): TDbfFieldDef;
begin
Result := TDbfFieldDef(inherited GetItem(Idx));
end;
constructor TDbfFieldDefs.Create(Owner: TPersistent);
begin
inherited Create(TDbfFieldDef);
FOwner := Owner;
end;
function TDbfFieldDefs.AddFieldDef: TDbfFieldDef;
begin
Result := TDbfFieldDef(inherited Add);
end;
function TDbfFieldDefs.GetOwner: TPersistent; {override;}
begin
Result := FOwner;
end;
procedure TDbfFieldDefs.Add(const Name: string; DataType: TFieldType; Size: Integer; Required: Boolean);
var
FieldDef: TDbfFieldDef;
begin
FieldDef := AddFieldDef;
FieldDef.FieldName := Name;
FieldDef.FieldType := DataType;
if Size <> 0 then
FieldDef.Size := Size;
FieldDef.Required := Required;
end;
//====================================================================
// DbfFieldDef
//====================================================================
constructor TDbfFieldDef.Create(ACollection: TCollection); {virtual}
begin
inherited;
FDefaultBuf := nil;
FMinBuf := nil;
FMaxBuf := nil;
FAllocSize := 0;
FCopyFrom := -1;
FPrecision := 0;
FHasDefault := false;
FHasMin := false;
FHasMax := false;
FNullPosition := -1;
end;
destructor TDbfFieldDef.Destroy; {override}
begin
FreeBuffers;
inherited;
end;
procedure TDbfFieldDef.Assign(Source: TPersistent);
var
DbfSource: TDbfFieldDef;
begin
if Source is TDbfFieldDef then
begin
// copy from another TDbfFieldDef
DbfSource := TDbfFieldDef(Source);
FFieldName := DbfSource.FieldName;
FFieldType := DbfSource.FieldType;
FNativeFieldType := DbfSource.NativeFieldType;
FSize := DbfSource.Size;
FPrecision := DbfSource.Precision;
FRequired := DbfSource.Required;
FCopyFrom := DbfSource.Index;
FIsLockField := DbfSource.IsLockField;
FNullPosition := DbfSource.NullPosition;
// copy default,min,max
AllocBuffers;
if DbfSource.DefaultBuf <> nil then
Move(DbfSource.DefaultBuf^, FDefaultBuf^, FAllocSize*3);
FHasDefault := DbfSource.HasDefault;
FHasMin := DbfSource.HasMin;
FHasMax := DbfSource.HasMax;
// do we need offsets?
FOffset := DbfSource.Offset;
FAutoInc := DbfSource.AutoInc;
{$ifdef SUPPORT_FIELDDEF_TPERSISTENT}
end else if Source is TFieldDef then begin
AssignDb(TFieldDef(Source));
{$endif}
end else
inherited Assign(Source);
end;
procedure TDbfFieldDef.AssignDb(DbSource: TFieldDef);
begin
// copy from Db.TFieldDef
FFieldName := DbSource.Name;
FFieldType := DbSource.DataType;
FSize := DbSource.Size;
FPrecision := DbSource.Precision;
FRequired := DbSource.Required;
{$ifdef SUPPORT_FIELDDEF_INDEX}
FCopyFrom := DbSource.Index;
{$endif}
FIsLockField := false;
// convert VCL fieldtypes to native DBF fieldtypes
VCLToNative;
// for integer / float fields try fill in size/precision
if FSize = 0 then
SetDefaultSize
else
CheckSizePrecision;
// VCL does not have default value support
AllocBuffers;
FHasDefault := false;
FHasMin := false;
FHasMax := false;
FOffset := 0;
FAutoInc := 0;
end;
procedure TDbfFieldDef.AssignTo(Dest: TPersistent);
var
DbDest: TFieldDef;
begin
{$ifdef SUPPORT_FIELDDEF_TPERSISTENT}
// copy to VCL fielddef?
if Dest is TFieldDef then
begin
DbDest := TFieldDef(Dest);
// VCL TFieldDef does not know how to handle TDbfFieldDef!
// what a shame :-)
{$ifdef SUPPORT_FIELDDEF_ATTRIBUTES}
DbDest.Attributes := [];
DbDest.ChildDefs.Clear;
DbDest.DataType := FFieldType;
DbDest.Required := FRequired;
DbDest.Size := FSize;
DbDest.Name := FFieldName;
{$endif}
end else
{$endif}
inherited AssignTo(Dest);
end;
function TDbfFieldDef.GetDbfVersion: TXBaseVersion;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -