
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@5438 8e941d3f-bd1b-0410-a28a-d453659cc2b4
1073 lines
30 KiB
ObjectPascal
1073 lines
30 KiB
ObjectPascal
{*********************************************************}
|
|
{* FlashFiler: Field and Record Conversion Routines *}
|
|
{*********************************************************}
|
|
|
|
(* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is TurboPower FlashFiler
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* TurboPower Software
|
|
*
|
|
* Portions created by the Initial Developer are Copyright (C) 1996-2002
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* ***** END LICENSE BLOCK ***** *)
|
|
|
|
{$I ffdefine.inc}
|
|
|
|
unit ffclconv;
|
|
|
|
interface
|
|
|
|
uses
|
|
Windows,
|
|
SysUtils,
|
|
DB,
|
|
ffclbde,
|
|
ffsrbde,
|
|
ffllbase,
|
|
ffllexcp,
|
|
ffconst,
|
|
ffclbase;
|
|
|
|
procedure GetBDEFieldDescriptor(const FFFieldDesc : TFFFieldDescriptor;
|
|
var BDEFldDesc : FLDDesc);
|
|
{-converts a FlashFiler field descriptor into a physical BDE one}
|
|
|
|
procedure GetBDEIndexDescriptor(const FFIndexDesc : TFFIndexDescriptor;
|
|
var BDEIdxDesc : IDXDesc);
|
|
{-converts a FlashFiler index descriptor into a BDE one}
|
|
|
|
procedure GetBDELogicalFieldDescriptor(const FFFieldDesc : FLDDesc;
|
|
var BDEFieldDesc : FLDDesc);
|
|
{-converts a FlashFiler based BDE field description to a logical one
|
|
NOTE: the field iOffset is not set - to be calculated later}
|
|
|
|
procedure GetBDEVChkDescriptor(FFVChkDesc : TffVCheckDescriptor;
|
|
var BDEVChkDesc : VCHKDesc;
|
|
FieldNumber : longint;
|
|
Required : boolean);
|
|
{-converts a FlashFiler validity check descriptor into a BDE one}
|
|
|
|
|
|
function GetFFSearchKeyAction(
|
|
const aDBISearchCond : DBISearchCond) : TffSearchKeyAction;
|
|
{-convert a BDE search action to the FF one}
|
|
|
|
function MapBDEDataToFF(FFType : TffFieldType;
|
|
PhySize : integer;
|
|
aSource : pointer;
|
|
aDest : pointer) : boolean;
|
|
{-maps a BDE logical field value in aSource to the equivalent FF
|
|
value in aDest. Note that type conversion is assumed to be the
|
|
reverse of MapFFTypeToBDE}
|
|
|
|
procedure MapBDETypeToFF(BDEType : word;
|
|
BDESubType : word;
|
|
LogSize : integer;
|
|
var FFType : TffFieldType;
|
|
var PhySize : word);
|
|
{-maps a BDE field type/subtype to the nearest FF type and returns
|
|
the physical size}
|
|
|
|
function MapFFDataToBDE(FFType : TffFieldType;
|
|
PhySize : integer;
|
|
aSource : pointer;
|
|
aDest : pointer) : boolean;
|
|
{-maps a FlashFiler field value in aSource to the equivalent BDE
|
|
value in aDest. Note that type conversion is assumed to be the
|
|
same as MapFFTypeToBDE}
|
|
|
|
procedure MapFFTypeToBDE(FFType : TffFieldType;
|
|
PhySize : integer;
|
|
var BDEType : word;
|
|
var BDESubType : word;
|
|
var LogSize : word);
|
|
{-maps a FlashFiler field type to the nearest BDE logical type/
|
|
subtype and returns the logical size}
|
|
|
|
procedure MapVCLTypeToFF(const VCLType : TFieldType;
|
|
const VCLSize : integer;
|
|
var FFType : TffFieldType;
|
|
var FFSize : word);
|
|
{-maps a VCL field type to the nearest FF equivalent. If the specified
|
|
VCLType is not supported, FFType is set to fftReserved20. }
|
|
|
|
function FFBDEDateEncode(aDay : word;
|
|
aMonth : word;
|
|
aYear : word) : DBIDATE;
|
|
{-converts day, month, year to a raw date for a field}
|
|
|
|
procedure FFBDEDateDecode(aDate : DBIDATE;
|
|
var aDay : word;
|
|
var aMonth : word;
|
|
var aYear : word);
|
|
{-converts a raw date from a field to day, month, year}
|
|
|
|
function FFBDETimeEncode(aHour : Word;
|
|
aMin : Word;
|
|
aMilSec : Word) : DBITIME;
|
|
{-converts hour, min, milsec to a raw time for a field}
|
|
|
|
procedure FFBDETimeDecode(aTime : DBITIME;
|
|
var aHour : Word;
|
|
var aMin : Word;
|
|
var aMilSec : Word);
|
|
{-converts a raw time from a field to hour, min, milsec}
|
|
|
|
implementation
|
|
|
|
uses
|
|
ffstdate;
|
|
|
|
{Notes on date and time formats: There are four different date formats
|
|
in play here in FlashFiler Client:
|
|
TffDBIDate : a longint being the number of days since 1/1/0100;
|
|
this is the BDE logical type
|
|
TDateTime : a double whose integral part is
|
|
(Delphi 1) the number of days since 1/1/0100
|
|
(Delphi 2+) the number of days since 1/1/1800
|
|
TStDate : a longint being the number of days since 1/1/1600.
|
|
The big problem is the different definitions of TDateTime. In Delphi
|
|
1, to convert from TffDBIDate to TDateTime is an assignment (they use
|
|
the same base date; in later compilers, you have to add 693594 days
|
|
(and vice versa for the inverse operation). To convert TStDates to
|
|
TDateTimes, use the StDate routine StDateToDateTime and
|
|
DateTimeToStDate.
|
|
|
|
Times are less confusing. The BDE logical type (TffDbiTime) is the
|
|
number of milliseconds since midnight in a longint and the conversion
|
|
from TStTime (the seconds since midnight) is simple.
|
|
|
|
Unions of dates and times are also relatively simple. The BDE logical
|
|
type TffTimeStamp is a number of milliseconds since the standard BDE
|
|
base date.
|
|
|
|
Note that FlashFiler stores its datetimes as the Delphi 1
|
|
TDateTime type, so the conversion between the FlashFiler physical
|
|
value and the BDE logical value is a matter of multiplying/dividing by
|
|
the number of milliseconds in a day.}
|
|
|
|
const
|
|
IGNORE_OEMANSI : Boolean = True;
|
|
IGNORE_ANSIOEM : Boolean = True;
|
|
dsMaxStringSize = 8192; {copied from DB.PAS}
|
|
|
|
|
|
{===Interfaced routines==============================================}
|
|
procedure GetBDEFieldDescriptor(const FFFieldDesc : TFFFieldDescriptor;
|
|
var BDEFldDesc : FLDDesc);
|
|
begin
|
|
{clear the result structure to binary zeros}
|
|
FillChar(BDEFldDesc, sizeof(FLDDesc), 0);
|
|
{fill the relevant parts of the result structure}
|
|
with BDEFldDesc, FFFieldDesc do begin
|
|
iFldNum := succ(fdNumber);
|
|
FFStrPCopy(szName, fdName);
|
|
iFldType := ord(fdType);
|
|
iSubType := 0;
|
|
iUnits1 := fdUnits;
|
|
iUnits2 := fdDecPl;
|
|
iOffset := fdOffset;
|
|
iLen := fdLength;
|
|
{iNullOffset := 0;}
|
|
if Assigned(fdVCheck) or fdRequired then
|
|
efldvVchk := fldvHASCHECKS
|
|
else
|
|
efldvVchk := fldvNOCHECKS;
|
|
efldrRights := fldrREADWRITE;
|
|
{bCalcField := False;}
|
|
end;
|
|
end;
|
|
{--------}
|
|
procedure GetBDEIndexDescriptor(const FFIndexDesc : TFFIndexDescriptor;
|
|
var BDEIdxDesc : IDXDesc);
|
|
var
|
|
i : Integer;
|
|
begin
|
|
{clear the result structure to binary zeros}
|
|
FillChar(BDEIdxDesc, sizeof(IDXDesc), 0);
|
|
{fill the relevant parts of the result structure}
|
|
with FFIndexDesc, BDEidxDesc do begin
|
|
StrPLCopy(szName, idName, sizeof(szName) - 1);
|
|
iIndexId := idNumber;
|
|
{StrCopy(szTagName, '');}
|
|
StrCopy(szFormat, 'BTREE');
|
|
{bPrimary := false;}
|
|
bUnique := not idDups;
|
|
bDescending := not idAscend;
|
|
bMaintained := True; {all FF keys are maintained}
|
|
{bSubSet := false;}
|
|
{iCost := 0}
|
|
if (idCount = -1) then begin
|
|
{this is a User-defined or Seq.Access Index: we'll treat it as
|
|
an expression Index - see dBASE info...}
|
|
bExpIdx := True;
|
|
iFldsInKey := 0;
|
|
end
|
|
else {it's a composite index} begin
|
|
bExpIdx := False;
|
|
iFldsInKey := idCount;
|
|
for i := 0 to pred(iFldsInKey) do
|
|
aiKeyFld[i] := succ(idFields[i]); {FF fields are 0-based, BDE's are 1-based}
|
|
end;
|
|
iKeyLen := idKeyLen;
|
|
{bOutOfDate := false;}
|
|
{iKeyExpType := 0;}
|
|
{StrCopy(szKeyExp, '');}
|
|
{StrCopy(szKeyCond, '');}
|
|
bCaseInsensitive := idNoCase;
|
|
{iBlockSize := 0;}
|
|
{iRestrNum := 0}
|
|
end;
|
|
end;
|
|
{--------}
|
|
procedure GetBDELogicalFieldDescriptor(const FFFieldDesc : FLDDesc;
|
|
var BDEFieldDesc : FLDDesc);
|
|
begin
|
|
{clear the result structure to binary zeros}
|
|
FillChar(BDEFieldDesc, sizeof(BDEFieldDesc), 0);
|
|
{fill the relevant parts of the result structure}
|
|
with BDEFieldDesc do begin
|
|
iFldNum := FFFieldDesc.iFldNum;
|
|
StrCopy(szName, FFFieldDesc.szName);
|
|
MapFFTypeToBDE(TFFFieldType(FFFieldDesc.iFldType),
|
|
FFFieldDesc.iLen,
|
|
iFldType,
|
|
iSubType,
|
|
iLen);
|
|
if (iFldType = fldZSTRING) then
|
|
iUnits1 := iLen
|
|
else if (iFldType = fldBYTES) then
|
|
iUnits1 := iLen;
|
|
{iUnits2 := 0; - unused}
|
|
{iOffset := 0; - this is set later}
|
|
{iNullOffset := 0; - there is none in a converted desc}
|
|
efldvVchk := fldvNOCHECKS;
|
|
efldrRights := fldrREADWRITE;
|
|
{bCalcField := 0;}
|
|
end;
|
|
end;
|
|
{--------}
|
|
procedure GetBDEVChkDescriptor(FFVChkDesc : TffVCheckDescriptor;
|
|
var BDEVChkDesc : VCHKDesc;
|
|
FieldNumber : longint;
|
|
Required : boolean);
|
|
begin
|
|
{clear the result structure to binary zeros}
|
|
FillChar(BDEVchkDesc, sizeof(VCHKDesc), 0);
|
|
{fill the relevant parts of the result structure}
|
|
with BDEVChkDesc, FFVChkDesc do begin
|
|
iFldNum := FieldNumber;
|
|
bRequired := Required;
|
|
bHasMinVal := vdHasMinVal;
|
|
bHasMaxVal := vdHasMaxVal;
|
|
bHasDefVal := vdHasDefVal;
|
|
if vdHasMinVal then
|
|
Move(vdMinVal, aMinVal, 254);
|
|
if vdHasMaxVal then
|
|
Move(vdMaxVal, aMaxVal, 254);
|
|
if vdHasDefVal then
|
|
Move(vdDefVal, aDefVal, 254);
|
|
StrPCopy(szPict, vdPicture);
|
|
{elkupType := lkupNONE;}
|
|
{szLkupTblName[0] := #0;}
|
|
end;
|
|
end;
|
|
{--------}
|
|
function GetFFSearchKeyAction(
|
|
const aDBISearchCond : DBISearchCond) : TffSearchKeyAction;
|
|
begin
|
|
case aDBISearchCond of
|
|
keySEARCHEQ : Result := skaEqual;
|
|
keySEARCHGT : Result := skaGreater;
|
|
keySEARCHGEQ : Result := skaGreaterEqual;
|
|
else
|
|
Result := skaEqual;
|
|
end;
|
|
end;
|
|
{--------}
|
|
function MapBDEDataToFF(FFType : TffFieldType;
|
|
PhySize : integer;
|
|
aSource : pointer;
|
|
aDest : pointer) : boolean;
|
|
var
|
|
WorkWideChar : array [0..1] of WideChar;
|
|
DateValue : TStDate;
|
|
begin
|
|
{WARNING: the case statement below is in ascending order of switch
|
|
value}
|
|
Result := true;
|
|
case FFType of
|
|
fftBoolean:
|
|
begin
|
|
Boolean(aDest^) := WordBool(aSource^);
|
|
end;
|
|
fftChar:
|
|
begin
|
|
Char(aDest^) := Char(aSource^); {copy one character}
|
|
end;
|
|
fftWideChar:
|
|
begin
|
|
if not IGNORE_ANSIOEM then
|
|
AnsiToOEM(aSource, aSource);
|
|
StringToWideChar(StrPas(aSource), WorkWideChar, PhySize);
|
|
Move(WorkWideChar[0], aDest^, sizeof(WideChar));
|
|
end;
|
|
fftByte:
|
|
begin
|
|
Byte(aDest^) := Word(aSource^);
|
|
end;
|
|
fftWord16:
|
|
begin
|
|
Word(aDest^) := Word(aSource^);
|
|
end;
|
|
fftWord32:
|
|
begin
|
|
LongInt(aDest^) := LongInt(aSource^);
|
|
end;
|
|
fftInt8:
|
|
begin
|
|
ShortInt(aDest^) := ShortInt(aSource^); {!!.07}
|
|
end;
|
|
fftInt16:
|
|
begin
|
|
SmallInt(aDest^) := SmallInt(aSource^);
|
|
end;
|
|
fftInt32:
|
|
begin
|
|
LongInt(aDest^) := LongInt(aSource^);
|
|
end;
|
|
fftAutoInc:
|
|
begin
|
|
LongInt(aDest^) := LongInt(aSource^);
|
|
end;
|
|
fftSingle:
|
|
begin
|
|
Single(aDest^) := Double(aSource^);
|
|
end;
|
|
fftDouble:
|
|
begin
|
|
Double(aDest^) := Double(aSource^);
|
|
end;
|
|
fftExtended:
|
|
begin
|
|
Extended(aDest^) := Double(aSource^);
|
|
end;
|
|
fftComp:
|
|
begin
|
|
Comp(aDest^) := Double(aSource^);
|
|
end;
|
|
fftCurrency:
|
|
begin
|
|
Currency(aDest^) := Double(aSource^);
|
|
end;
|
|
fftStDate:
|
|
begin
|
|
DateValue := DateTimeToStDate(
|
|
DbiDate(aSource^) - 693594.0);
|
|
if DateValue = BadDate then begin
|
|
TStDate(aDest^) := 0;
|
|
Result := false;
|
|
end
|
|
else
|
|
TStDate(aDest^) := DateValue;
|
|
end;
|
|
fftStTime:
|
|
begin
|
|
{StTimes are stored as # seconds since midnight; BDE logical
|
|
times as # milliseconds; to convert, divide by 1000}
|
|
TStTime(aDest^) := DBITime(aSource^) div 1000;
|
|
end;
|
|
fftDateTime:
|
|
begin
|
|
{FF datetimes are compatible with Delphi's TDateTime, viz:
|
|
<days>.<timefraction>; BDE stores as # millisecs since
|
|
base date; to convert, divide by # millisecs/day}
|
|
TDateTime(aDest^) := TimeStamp(aSource^) / 86400000.0;
|
|
end;
|
|
fftBLOB,
|
|
fftBLOBMemo,
|
|
fftBLOBFmtMemo,
|
|
fftBLOBOLEObj,
|
|
fftBLOBGraphic,
|
|
fftBLOBDBSOLEObj,
|
|
fftBLOBTypedBin,
|
|
fftBLOBFile:
|
|
begin
|
|
{just copy over the BLOB number}
|
|
LongInt(aDest^) := LongInt(aSource^);
|
|
end;
|
|
fftByteArray:
|
|
begin
|
|
Move(aSource^, aDest^, PhySize);
|
|
end;
|
|
fftShortString,
|
|
fftShortAnsiStr:
|
|
begin
|
|
if not IGNORE_ANSIOEM then
|
|
AnsiToOEM(aSource, aSource);
|
|
TffShStr(aDest^) := StrPas(aSource);
|
|
end;
|
|
fftNullString,
|
|
fftNullAnsiStr:
|
|
begin
|
|
if not IGNORE_ANSIOEM then
|
|
AnsiToOEM(aSource, aSource);
|
|
StrLCopy(aDest, aSource, pred(PhySize));
|
|
end;
|
|
fftWideString:
|
|
begin
|
|
{convert this to a Pascal String}
|
|
if not IGNORE_ANSIOEM then
|
|
AnsiToOEM(aSource, aSource);
|
|
StringToWideChar(StrPas(aSource), PWideChar(aDest), pred(PhySize));
|
|
end;
|
|
else
|
|
Result := false;
|
|
end;
|
|
end;
|
|
{--------}
|
|
procedure MapBDETypeToFF(BDEType : word;
|
|
BDESubType : word;
|
|
LogSize : integer;
|
|
var FFType : TffFieldType;
|
|
var PhySize : word);
|
|
begin
|
|
{WARNING: the case statement below is in ascending order of switch
|
|
value}
|
|
case BDEType of
|
|
fldZSTRING:
|
|
begin
|
|
FFType := fftNullString;
|
|
PhySize := LogSize;
|
|
end;
|
|
fldDATE:
|
|
begin
|
|
FFType := fftStDate;
|
|
PhySize := sizeof(TStDate);
|
|
end;
|
|
fldBLOB:
|
|
begin
|
|
case BDESubType of
|
|
fldstMEMO : FFType := fftBLOBMemo;
|
|
fldstBINARY : FFType := fftBLOB;
|
|
fldstFMTMEMO : FFType := fftBLOBFmtMemo;
|
|
fldstOLEOBJ : FFType := fftBLOBOLEObj;
|
|
fldstGRAPHIC : FFType := fftBLOBGraphic;
|
|
fldstDBSOLEOBJ : FFType := fftBLOBDBSOLEObj;
|
|
fldstTYPEDBINARY : FFType := fftBLOBTypedBin;
|
|
fldstBFILE : FFType := fftBLOBFile;
|
|
else
|
|
FFRaiseExceptionNoData(EffClientException, ffStrResClient, ffccInvalidParameter);
|
|
end;
|
|
PhySize := sizeof(longint);
|
|
end;
|
|
fldBOOL:
|
|
begin
|
|
FFType := fftBoolean;
|
|
PhySize := sizeof(boolean);
|
|
end;
|
|
fldINT16:
|
|
begin
|
|
FFType := fftInt16;
|
|
PhySize := sizeof(smallint);
|
|
end;
|
|
fldINT32:
|
|
begin
|
|
if (BDESubType = fldstAUTOINC) then
|
|
FFType := fftAutoInc
|
|
else
|
|
FFType := fftInt32;
|
|
PhySize := sizeof(longint);
|
|
end;
|
|
fldFLOAT:
|
|
begin
|
|
if BDESubType = fldstMoney then begin
|
|
FFType := fftCurrency;
|
|
PhySize := sizeof(Currency);
|
|
end
|
|
else begin
|
|
FFType := fftDouble;
|
|
PhySize := sizeof(double);
|
|
end;
|
|
end;
|
|
fldBCD:
|
|
begin
|
|
FFType := fftCurrency;
|
|
PhySize := sizeof(Currency);
|
|
end;
|
|
fldBYTES:
|
|
begin
|
|
FFType := fftByteArray;
|
|
PhySize := LogSize;
|
|
end;
|
|
fldTIME:
|
|
begin
|
|
FFType := fftstTime;
|
|
PhySize := sizeof(TStTime);
|
|
end;
|
|
fldTIMESTAMP:
|
|
begin
|
|
FFType := fftDateTime;
|
|
PhySize := sizeof(TDateTime);
|
|
end;
|
|
fldUINT16:
|
|
begin
|
|
FFType := fftWord16;
|
|
PhySize := sizeof(word);
|
|
end;
|
|
fldUINT32:
|
|
begin
|
|
FFType := fftWord32;
|
|
PhySize := sizeof(TffWord32);
|
|
end;
|
|
fldFLOATIEEE:
|
|
begin
|
|
FFType := fftExtended;
|
|
PhySize := sizeof(Extended);
|
|
end;
|
|
fldVARBYTES:
|
|
begin
|
|
if (LogSize > 256) then
|
|
FFRaiseExceptionNoData(EffClientException, ffStrResClient, ffccInvalidParameter);
|
|
FFType := fftShortString;
|
|
PhySize := LogSize;
|
|
end;
|
|
else
|
|
FFRaiseExceptionNoData(EffClientException, ffStrResClient, ffccInvalidParameter);
|
|
end;
|
|
end;
|
|
{--------}
|
|
function MapFFDataToBDE(FFType : TffFieldType;
|
|
PhySize : Integer;
|
|
aSource : Pointer;
|
|
aDest : Pointer)
|
|
: Boolean;
|
|
var
|
|
WorkString : string;
|
|
begin
|
|
{WARNING: the case statement below is in ascending order of switch
|
|
value}
|
|
Result := True;
|
|
case FFType of
|
|
fftBoolean:
|
|
begin
|
|
WordBool(aDest^) := Boolean(aSource^);
|
|
end;
|
|
fftChar:
|
|
begin
|
|
word(aDest^) := 0;
|
|
char(aDest^) := char(aSource^);
|
|
end;
|
|
fftWideChar:
|
|
begin
|
|
{convert this to a Pascal String}
|
|
WorkString := WideCharLenToString(PWideChar(aSource), 1);
|
|
StrPLCopy(aDest, WorkString, pred(PhySize));
|
|
if not IGNORE_OEMANSI then
|
|
OEMToAnsi(aDest, aDest);
|
|
end;
|
|
fftByte:
|
|
begin
|
|
Word(aDest^) := Byte(aSource^);
|
|
end;
|
|
fftWord16:
|
|
begin
|
|
Word(aDest^) := Word(aSource^);
|
|
end;
|
|
fftWord32:
|
|
begin
|
|
LongInt(aDest^) := LongInt(aSource^);
|
|
end;
|
|
fftInt8:
|
|
begin
|
|
{NOTE: This maps to a SmallInt because the VCL does not have
|
|
an 8-bit integer field type. }
|
|
SmallInt(aDest^) := ShortInt(aSource^);
|
|
end;
|
|
fftInt16:
|
|
begin
|
|
SmallInt(aDest^) := SmallInt(aSource^);
|
|
end;
|
|
fftInt32:
|
|
begin
|
|
LongInt(aDest^) := LongInt(aSource^);
|
|
end;
|
|
fftAutoInc:
|
|
begin
|
|
LongInt(aDest^) := LongInt(aSource^);
|
|
end;
|
|
fftSingle:
|
|
begin
|
|
Double(aDest^) := Single(aSource^);
|
|
end;
|
|
fftDouble:
|
|
begin
|
|
Double(aDest^) := Double(aSource^);
|
|
end;
|
|
fftExtended:
|
|
begin
|
|
Double(aDest^) := Extended(aSource^);
|
|
end;
|
|
fftComp:
|
|
begin
|
|
Double(aDest^) := Comp(aSource^);
|
|
end;
|
|
fftCurrency:
|
|
begin
|
|
Double(aDest^) := Currency(aSource^);
|
|
end;
|
|
fftStDate:
|
|
begin
|
|
if TStDate(aSource^) = BadDate then
|
|
Result := false
|
|
else {it's a valid StDate value} begin
|
|
DbiDate(aDest^) :=
|
|
Trunc(StDateToDateTime(TStDate(aSource^)))
|
|
+ 693594;
|
|
end;
|
|
end;
|
|
fftStTime:
|
|
begin
|
|
{StTimes are stored as # seconds since midnight; BDE logical
|
|
times as # milliseconds; to convert, multiply by 1000}
|
|
if TStTime(aSource^) = BadTime then
|
|
Result := false
|
|
else {it's a valid StDate value} begin
|
|
DBITime(aDest^) := TStTime(aSource^) * 1000;
|
|
end;
|
|
end;
|
|
fftDateTime:
|
|
begin
|
|
{FF datetimes are compatible with Delphi's TDateTime, viz:
|
|
<days>.<timefraction>; BDE stores as # millisecs since
|
|
base date; to convert, multiply by # millisecs/day}
|
|
TimeStamp(aDest^) := TDateTime(aSource^) * 86400000.0;
|
|
end;
|
|
fftBLOB,
|
|
fftBLOBMemo,
|
|
fftBLOBFmtMemo,
|
|
fftBLOBOLEObj,
|
|
fftBLOBGRAPHIC,
|
|
fftBLOBDBSOLEOBJ,
|
|
fftBLOBTypedBin,
|
|
fftBLOBFile:
|
|
begin
|
|
{just copy the BLOB number over}
|
|
longint(aDest^) := longint(aSource^);
|
|
end;
|
|
fftByteArray:
|
|
begin
|
|
Move(aSource^, aDest^, PhySize);
|
|
end;
|
|
fftShortString,
|
|
fftShortAnsiStr:
|
|
begin
|
|
StrPLCopy(aDest, TffShStr(aSource^), pred(PhySize));
|
|
if not IGNORE_OEMANSI then
|
|
OEMToAnsi(aDest, aDest);
|
|
end;
|
|
fftNullString,
|
|
fftNullAnsiStr:
|
|
begin
|
|
StrLCopy(aDest, aSource, pred(PhySize));
|
|
if not IGNORE_ANSIOEM then
|
|
AnsiToOEM(aDest, aDest);
|
|
end;
|
|
fftWideString:
|
|
begin
|
|
{convert this to a Pascal String}
|
|
WorkString := WideCharLenToString(PWideChar(aSource),
|
|
lstrlenw(PWideChar(aSource)));
|
|
StrPLCopy(aDest, WorkString, pred(PhySize));
|
|
if not IGNORE_OEMANSI then
|
|
OEMToAnsi(aDest, aDest);
|
|
end;
|
|
else
|
|
Result := false;
|
|
end;
|
|
end;
|
|
{--------}
|
|
procedure MapFFTypeToBDE(FFType : TFFFieldType;
|
|
PhySize : integer;
|
|
var BDEType : word;
|
|
var BDESubType : word;
|
|
var LogSize : word);
|
|
begin
|
|
BDESubType := 0;
|
|
case FFType of
|
|
fftBoolean: {..8-bit boolean flag}
|
|
begin
|
|
BDEType := fldBOOL;
|
|
LogSize := sizeof(WordBool);
|
|
end;
|
|
fftChar: {..8-bit character}
|
|
begin
|
|
BDEType := fldZString;
|
|
LogSize := 1;
|
|
end;
|
|
fftWideChar: {..16-bit character (UNICODE)}
|
|
begin
|
|
BDEType := fldZString;
|
|
LogSize := 1;
|
|
end;
|
|
fftByte: {..byte (8-bit unsigned integer)}
|
|
begin
|
|
BDEType := fldUINT16;
|
|
LogSize := sizeof(word);
|
|
end;
|
|
fftWord16: {..16-bit unsigned integer (aka word)}
|
|
begin
|
|
BDEType := fldUINT16;
|
|
LogSize := sizeof(word);
|
|
end;
|
|
fftWord32: {..32-bit unsigned integer}
|
|
begin
|
|
BDEType := fldINT32;
|
|
LogSize := sizeof(longint);
|
|
end;
|
|
fftInt8: {..8-bit signed integer}
|
|
begin
|
|
BDEType := fldINT16;
|
|
LogSize := sizeof(smallint);
|
|
end;
|
|
fftInt16: {..16-bit signed integer}
|
|
begin
|
|
BDEType := fldINT16;
|
|
LogSize := sizeof(smallint);
|
|
end;
|
|
fftInt32: {..32-bit signed integer}
|
|
begin
|
|
BDEType := fldINT32;
|
|
LogSize := sizeof(longint);
|
|
end;
|
|
fftAutoInc: {..32-bit unsigned auto-increment }
|
|
begin
|
|
BDEType := fldINT32;
|
|
BDESubType := fldstAUTOINC;
|
|
LogSize := sizeof(longint);
|
|
end;
|
|
fftSingle: {..IEEE single (4 bytes)}
|
|
begin
|
|
BDEType := fldFLOAT;
|
|
LogSize := sizeof(double);
|
|
end;
|
|
fftDouble: {..IEEE double (8 bytes)}
|
|
begin
|
|
BDEType := fldFLOAT;
|
|
LogSize := sizeof(double);
|
|
end;
|
|
fftExtended: {..IEEE extended (10 bytes)}
|
|
begin
|
|
BDEType := fldFLOAT; {BDE doesn't REALLY support 80-bit float}
|
|
LogSize := sizeof(double);
|
|
end;
|
|
fftComp: {..IEEE comp type (8 bytes signed integer)
|
|
range -2E63+1..2E63-1}
|
|
begin
|
|
BDEType := fldFLOAT;
|
|
LogSize := sizeof(double);
|
|
end;
|
|
fftCurrency: {..Delphi currency type (8 bytes: scaled integer)
|
|
range -922337203685477.5808..922337203685477.5807}
|
|
begin
|
|
BDEType := fldFloat;
|
|
BDESubType := fldstMONEY;
|
|
LogSize := sizeof(double);
|
|
end;
|
|
fftStDate: {..SysTools date type (4 bytes)}
|
|
begin
|
|
BDEType := fldDATE;
|
|
LogSize := sizeof(DBIDATE);
|
|
end;
|
|
fftStTime: {..SysTools time type (4 bytes)}
|
|
begin
|
|
BDEType := fldTIME;
|
|
LogSize := sizeof(DbiTIME);
|
|
end;
|
|
fftDateTime: {..Delphi date/time type (8 bytes)}
|
|
begin
|
|
BDEType := fldTIMESTAMP;
|
|
LogSize := sizeof(TIMESTAMP);
|
|
end;
|
|
fftBLOB, fftBLOBFile:
|
|
begin
|
|
BDEType := fldBLOB;
|
|
BDESubType := fldstBINARY;
|
|
LogSize := sizeof(longint);
|
|
end;
|
|
fftBLOBMemo:
|
|
begin
|
|
BDEType := fldBLOB;
|
|
BDESubType := fldstMEMO;
|
|
LogSize := sizeof(longint);
|
|
end;
|
|
fftBLOBFmtMemo:
|
|
begin
|
|
BDEType := fldBLOB;
|
|
BDESubType := fldstFMTMEMO;
|
|
LogSize := sizeof(longint);
|
|
end;
|
|
fftBLOBOLEObj:
|
|
begin
|
|
BDEType := fldBLOB;
|
|
BDESubType := fldstOLEOBJ;
|
|
LogSize := sizeof(longint);
|
|
end;
|
|
fftBLOBGRAPHIC:
|
|
begin
|
|
BDEType := fldBLOB;
|
|
BDESubType := fldstGRAPHIC;
|
|
LogSize := sizeof(longint);
|
|
end;
|
|
fftBLOBDBSOLEOBJ:
|
|
begin
|
|
BDEType := fldBLOB;
|
|
BDESubType := fldstDBSOLEOBJ;
|
|
LogSize := sizeof(longint);
|
|
end;
|
|
fftBLOBTypedBin:
|
|
begin
|
|
BDEType := fldBLOB;
|
|
BDESubType := fldstTYPEDBINARY;
|
|
LogSize := sizeof(longint);
|
|
end;
|
|
fftByteArray: {..array of bytes}
|
|
begin
|
|
BDEType := fldBYTES;
|
|
LogSize := PhySize;
|
|
end;
|
|
fftShortString, {..length byte string}
|
|
fftShortAnsiStr:
|
|
begin
|
|
BDEType := fldZSTRING;
|
|
LogSize := pred(PhySize);
|
|
end;
|
|
fftNullString, {..null-terminated string}
|
|
fftNullAnsiStr,
|
|
fftWideString:
|
|
begin
|
|
if (PhySize <= dsMaxStringSize) then begin
|
|
BDEType := fldZSTRING;
|
|
{Begin !!.11}
|
|
if FFType = fftWideString then
|
|
LogSize := pred(PhySize div 2)
|
|
else
|
|
LogSize := pred(PhySize);
|
|
{End !!.11}
|
|
end
|
|
else begin
|
|
BDEType := fldBLOB;
|
|
BDESubType := fldstMEMO;
|
|
LogSize := sizeof(longint);
|
|
end;
|
|
end;
|
|
else
|
|
FFRaiseExceptionNoData(EffClientException, ffStrResClient, ffccInvalidParameter);
|
|
end;
|
|
end;
|
|
{--------}
|
|
procedure MapVCLTypeToFF(const VCLType : TFieldType;
|
|
const VCLSize : integer;
|
|
var FFType : TffFieldType;
|
|
var FFSize : word);
|
|
begin
|
|
case VCLType of
|
|
ftString :
|
|
begin
|
|
FFType := fftNullString;
|
|
FFSize := VCLSize;
|
|
end;
|
|
ftSmallInt :
|
|
begin
|
|
FFType := fftInt16;
|
|
FFSize := SizeOf(smallInt);
|
|
end;
|
|
ftInteger :
|
|
begin
|
|
FFType := fftInt32;
|
|
FFSize := SizeOf(longInt);
|
|
end;
|
|
ftWord :
|
|
begin
|
|
FFType := fftWord16;
|
|
FFSize := SizeOf(Word);
|
|
end;
|
|
ftBoolean :
|
|
begin
|
|
FFType := fftBoolean;
|
|
FFSize := SizeOf(Boolean);
|
|
end;
|
|
ftFloat :
|
|
begin
|
|
FFType := fftDouble;
|
|
FFSize := SizeOf(Double);
|
|
end;
|
|
ftCurrency :
|
|
begin
|
|
FFType := fftCurrency;
|
|
FFSize := SizeOf(Currency);
|
|
end;
|
|
ftBCD :
|
|
begin
|
|
FFType := fftCurrency;
|
|
FFSize := SizeOf(Currency);
|
|
end;
|
|
ftDate :
|
|
begin
|
|
FFType := fftStDate;
|
|
FFSize := sizeof(TStDate);
|
|
end;
|
|
ftTime :
|
|
begin
|
|
FFType := fftstTime;
|
|
FFSize := SizeOf(TStTime);
|
|
end;
|
|
ftDateTime :
|
|
begin
|
|
FFType := fftDateTime;
|
|
FFSize := SizeOf(TDateTime);
|
|
end;
|
|
ftBytes :
|
|
begin
|
|
FFType := fftByteArray;
|
|
FFSize := VCLSize;
|
|
end;
|
|
ftVarBytes :
|
|
begin
|
|
if (VCLSize <= 256) then begin
|
|
FFType := fftShortString;
|
|
FFSize := VCLSize;
|
|
end else begin
|
|
FFType := fftReserved20;
|
|
FFSize := 0;
|
|
end;
|
|
end;
|
|
ftAutoInc :
|
|
begin
|
|
FFType := fftAutoInc;
|
|
FFSize := SizeOf(LongInt);
|
|
end;
|
|
ftBlob :
|
|
begin
|
|
FFType := fftBLOB;
|
|
FFSize := SizeOf(TffInt64); {!!.13}
|
|
end;
|
|
ftMemo :
|
|
begin
|
|
FFType := fftBLOBMemo;
|
|
FFSize := SizeOf(TffInt64); {!!.13}
|
|
end;
|
|
ftGraphic :
|
|
begin
|
|
FFType := fftBLOBGraphic;
|
|
FFSize := SizeOf(TffInt64); {!!.13}
|
|
end;
|
|
ftFmtMemo :
|
|
begin
|
|
FFType := fftBLOBFmtMemo;
|
|
FFSize := SizeOf(TffInt64); {!!.13}
|
|
end;
|
|
ftParadoxOLE :
|
|
begin
|
|
FFType := fftBLOBOleObj;
|
|
FFSize := SizeOf(TffInt64); {!!.13}
|
|
end;
|
|
ftDBaseOLE :
|
|
begin
|
|
FFType := fftBLOBDBSOleObj;
|
|
FFSize := SizeOf(TffInt64); {!!.13}
|
|
end;
|
|
ftTypedBinary :
|
|
begin
|
|
FFType := fftBLOBTypedBin;
|
|
FFSize := SizeOf(TffInt64); {!!.13}
|
|
end;
|
|
{$IFDEF DCC4OrLater}
|
|
ftFixedChar :
|
|
begin
|
|
FFType := fftNullString;
|
|
FFSize := VCLSize;
|
|
end;
|
|
ftWideString :
|
|
begin
|
|
FFType := fftWideString;
|
|
FFSize := VCLSize;
|
|
end;
|
|
{$ENDIF}
|
|
{$IFDEF DCC5OrLater}
|
|
ftGUID :
|
|
begin
|
|
FFType := fftNullString;
|
|
FFSize := VCLSize;
|
|
end;
|
|
{$ENDIF}
|
|
else
|
|
{ Use this to represent an unsupported field type. }
|
|
FFType := fftReserved20;
|
|
FFSize := 0;
|
|
end;
|
|
end;
|
|
{--------}
|
|
function FFBDEDateEncode(aDay : word;
|
|
aMonth : word;
|
|
aYear : word) : DBIDATE;
|
|
begin
|
|
Result := trunc(SysUtils.EncodeDate(aYear, aMonth, aDay))
|
|
+ 693594;
|
|
end;
|
|
{--------}
|
|
procedure FFBDEDateDecode(aDate : DBIDATE;
|
|
var aDay : word;
|
|
var aMonth : word;
|
|
var aYear : word);
|
|
var
|
|
DT : TDateTime;
|
|
begin
|
|
DT := aDate - 693594.0;
|
|
SysUtils.DecodeDate(DT, aYear, aMonth, aDay);
|
|
end;
|
|
{--------}
|
|
function FFBDETimeEncode(aHour : Word;
|
|
aMin : Word;
|
|
aMilSec : Word) : DBITIME;
|
|
{-converts hour, min, milsec to a raw time for a field}
|
|
begin
|
|
Result := trunc(SysUtils.EncodeTime(aHour, aMin, aMilSec mod 1000,
|
|
aMilSec div 1000) * 86400000.0);
|
|
end;
|
|
{--------}
|
|
procedure FFBDETimeDecode(aTime : DBITIME;
|
|
var aHour : Word;
|
|
var aMin : Word;
|
|
var aMilSec : Word);
|
|
{-converts a raw time from a field to hour, min, milsec}
|
|
var
|
|
DT : TDateTime;
|
|
aSec : Word;
|
|
begin
|
|
DT := aTime / 86400000.0;
|
|
SysUtils.DecodeTime(DT, aHour, aMin, aSec, aMilSec);
|
|
aMilSec := aMilSec + aSec * 1000;
|
|
end;
|
|
|
|
{====================================================================}
|
|
|
|
end.
|
|
|