unit ABSVariant;

{$I ABSVer.inc}

interface

uses SysUtils, Classes,

      Windows, Math,

// AbsoluteDatabase units

{$IFNDEF D6H}
     ABSD4Routines,
{$ENDIF}
     {$IFDEF DEBUG_LOG}
     ABSDebug,
     {$ENDIF}
     ABSCompression,
     ABSTypes,
     ABSTypesRoutines,
     ABSConst,
     ABSConverts,
     ABSMemory,
     ABSExcept;

var
  DefaultLocaleToCompareWideStrings: LCID = LOCALE_USER_DEFAULT;

type

 TABSVariant = class(TObject)
  private
   FDataType:     TABSBaseFieldType;    // type of data
   FDataSize:     Integer;              // size of data value
   FPData:        PAnsiChar;             // Binary data representation
   FIsDataLinked: ByteBool;             // freemem required?
   FIsNull:       ByteBool;             // Abstract Boolean Flag
  public
   procedure LoadFromStream(Stream: TStream);
   procedure SaveToStream(Stream: TStream);
   // Constructor
   constructor Create(DataType: TABSBaseFieldType = bftUnknown);
   // Destructor
   destructor Destroy; override;
   // SetNull
   procedure SetNull(DataType: TABSBaseFieldType = bftUnknown);
   // Free Buffer
   procedure Clear(DataType: TABSBaseFieldType = bftUnknown);
   // Assign data from source (or make link to Source.Data)
   procedure Assign(Source: TABSVariant; CopyDataFlag: boolean = true);
   // Set Data (or make link to Data)
   procedure SetData(Buffer: Pointer; Size: Integer;
                     DataType: TABSBaseFieldType;
                     CopyDataFlag: boolean = true);
   // Copy Data to Address
   function CopyDataToAddress(Buffer: Pointer; MaxSize: Integer = -1): boolean;
   // Cast to new data type
   procedure Cast(NewDataType: TABSBaseFieldType);
   // return true if DataType is numeric
   function IsNumericDataType: Boolean;
   // return true if DataType is String or WideString
   function IsStringDataType: Boolean;
   // return true if DataType is WideString
   function IsWideStringDataType: Boolean;
   // return true if DataType is BLOB
   function IsBlobDataType: Boolean;
   // return true if DataType is Time, Date, DateTime
   function IsDateTimeDataType: Boolean;

   // return Length of String or -1 (if not IsStringType)
   function StrLen: Integer;

   // data := -data ( if not number then raise)
   procedure InvertValue;
   // data := data + value
   procedure Add(Value: TABSVariant);
   // data := data - value
   procedure Sub(Value: TABSVariant);
   // data := data * value
   procedure Mul(Value: TABSVariant);
   // data := data / value
   procedure Division(Value: TABSVariant);

   // Compare with another Variants
   function Compare(
                    Value: TABSVariant;
                    TrueFalseNullLogic: boolean = True;
                    CaseInsensitive: boolean = True;
                    PartialKey: boolean = False
                   ): TABSCompareResult;

   // if it's possible w/o data loss, converts value of WideString to AnsiString
   procedure TryToReduceWideStringToAnsiString;
  private
   // Set Data Type
   procedure SetDataType(DataType: TABSBaseFieldType);
   // CastResultToType
   procedure CastResultToType(NewDataType: TABSBaseFieldType; out Result);
   // Cast value to empty FPData
   procedure CastAndSetData(const Value; ValueType: TABSBaseFieldType);
   // raise EABSException if FPData = nil
   procedure CheckDataForNull;

  private
   // return (FPData = nil)
   function GetIsNull: Boolean;

   // Set typed Data to Variant
   procedure SetDataValue(const value; ValueType: TABSBaseFieldType);
   // Set typed Data from Variant
   procedure GetDataValue(out Value; ValueType: TABSBaseFieldType);

   // Set Data for Signed Int8 (Shortint)
   procedure SetDataAsSignedInt8(Value: Shortint);
   // Get Data for Signed Int8 (Shortint)
   function  GetDataAsSignedInt8: Shortint;

   // Set Data for Signed Int16 (Smallint)
   procedure SetDataAsSignedInt16(Value: Smallint);
   // Get Data for Signed Int16 (Smallint)
   function  GetDataAsSignedInt16: Smallint;

   // Set Data for Signed Int32 (Integer)
   procedure SetDataAsSignedInt32(Value: Integer);
   // Get Data for Signed Int32 (Integer)
   function  GetDataAsSignedInt32: Integer;

   // Set Data for Signed Int64 (Int64)
   procedure SetDataAsSignedInt64(Value: Int64);
   // Get Data for Signed Int64 (Int64)
   function  GetDataAsSignedInt64: Int64;

   // Set Data for Unsigned Int8 (Byte)
   procedure SetDataAsUnsignedInt8(Value: Byte);
   // Get Data for Unsigned Int8 (Byte)
   function  GetDataAsUnsignedInt8: Byte;

   // Set Data for Unsigned Int16 (Word)
   procedure SetDataAsUnsignedInt16(Value: Word);
   // Get Data for Unsigned Int16 (Word)
   function  GetDataAsUnsignedInt16: Word;

   // Set Data for Unsigned Int32 (Cardinal)
   procedure SetDataAsUnsignedInt32(Value: Cardinal);
   // Get Data for Unsigned Int32 (Cardinal)
   function  GetDataAsUnsignedInt32: Cardinal;


   // Set Data for Char, Varchar (String)
   procedure SetDataAsAnsiString(Value: AnsiString);
   // Get Data as String
   function  GetDataAsAnsiString: AnsiString;

   // Set Data for WideChar, WideVarchar (WideString)
   procedure SetDataAsWideString(Value: WideString);
   // Get Data as WideString
   function  GetDataAsWideString: WideString;


   // Set Data for Single
   procedure SetDataAsSingle(Value: Single);
   // Get Data for Single
   function  GetDataAsSingle: Single;

   // Set Data for Double
   procedure SetDataAsDouble(Value: Double);
   // Get Data for Double
   function  GetDataAsDouble: Double;

   // Set Data for Extended
   procedure SetDataAsExtended(Value: Extended);
   // Get Data for Extended
   function  GetDataAsExtended: Extended;


   // Set Data for ABSDate
   procedure SetDataAsABSDate(Value: TABSDate);
   // Get Data for ABSDate
   function  GetDataAsABSDate: TABSDate;
   // Set Data for TDate
   procedure SetDataAsTDate(Value: TDateTime);
   // Get Data for TDate
   function  GetDataAsTDate: TDateTime;


   // Set Data for ABSTime
   procedure SetDataAsABSTime(Value: TABSTime);
   // Get Data for ABSTime
   function  GetDataAsABSTime: TABSTime;
   // Set Data for TTime
   procedure SetDataAsTTime(Value: TDateTime);
   // Get Data for TTime
   function  GetDataAsTTime: TDateTime;

   // Set Data for ABSDateTime
   procedure SetDataAsABSDateTime(Value: TABSDateTime);
   // Get Data for ABSDateTime
   function  GetDataAsABSDateTime: TABSDateTime;
   // Set Data for TDateTime
   procedure SetDataAsTDateTime(Value: TDateTime);
   // Get Data for TDateTime
   function  GetDataAsTDateTime: TDateTime;

   // Set Data for Boolean
   procedure SetDataAsBoolean(Value: TABSLogical);
   // Get Data for Boolean
   function  GetDataAsBoolean: TABSLogical;


   // Set Data for Currency
   procedure SetDataAsCurrency(Value: TABSCurrency);
   // Get Data for Currency
   function  GetDataAsCurrency: TABSCurrency;

   // Set Data from Borland Variant type
   procedure SetDataAsVariant(Value: Variant);
   // Get Data to Borland Variant type
   function GetDataAsVariant: Variant;

  public
   property DataType: TABSBaseFieldType read FDataType write SetDataType;
   property DataSize: Integer read FDataSize;
   property IsNull: Boolean read GetIsNull;
   property pData: PAnsiChar read FPData;
   property IsDataLinked: ByteBool read FIsDataLinked;
  public
   property AsShortint: Shortint      read GetDataAsSignedInt8    write SetDataAsSignedInt8;
   property AsSmallint: Smallint      read GetDataAsSignedInt16   write SetDataAsSignedInt16;
   property AsInteger: Integer        read GetDataAsSignedInt32   write SetDataAsSignedInt32;
   property AsInt64: Int64            read GetDataAsSignedInt64   write SetDataAsSignedInt64;
   property AsByte: Byte              read GetDataAsUnsignedInt8  write SetDataAsUnsignedInt8;
   property AsWord: Word              read GetDataAsUnsignedInt16 write SetDataAsUnsignedInt16;
   property AsCardinal: Cardinal      read GetDataAsUnsignedInt32 write SetDataAsUnsignedInt32;
   property AsLongWord: Cardinal      read GetDataAsUnsignedInt32 write SetDataAsUnsignedInt32;

   property AsSingle: Single          read GetDataAsSingle        write SetDataAsSingle;
   property AsDouble: Double          read GetDataAsDouble        write SetDataAsDouble;
   property AsExtended: Extended      read GetDataAsExtended      write SetDataAsExtended;

   property AsAnsiString: AnsiString      read GetDataAsAnsiString        write SetDataAsAnsiString;
   property AsWideString: WideString  read GetDataAsWideString    write SetDataAsWideString;

   property AsABSDate: TABSDate       read GetDataAsABSDate       write SetDataAsABSDate;
   property AsABSTime: TABSTime       read GetDataAsABSTime       write SetDataAsABSTime;
   property AsABSDateTime: TABSDateTime read GetDataAsABSDateTime write SetDataAsABSDateTime;
   property AsTDate: TDateTime            read GetDataAsTDate         write SetDataAsTDate;
   property AsTTime: TDateTime            read GetDataAsTTime         write SetDataAsTTime;
   property AsTDateTime: TDateTime    read GetDataAsTDateTime     write SetDataAsTDateTime;

   property AsBoolean: TABSLogical    read GetDataAsBoolean       write SetDataAsBoolean;
   property AsLogical: TABSLogical    read GetDataAsBoolean       write SetDataAsBoolean;
   property AsCurrency: TABSCurrency  read GetDataAsCurrency      write SetDataAsCurrency;

   property AsVariant: Variant        read GetDataAsVariant       write SetDataAsVariant;
 end;


// Return Common DataType for 2 types, or ftUnknown
function GetCommonDataType(a,b: TABSBaseFieldType; ForCompare: Boolean=False): TABSBaseFieldType; overload;
// Return Common DataType for 2 types, or ftUnknown
function GetCommonDataType(a,b: TABSAdvancedFieldType; ForCompare: Boolean=False): TABSAdvancedFieldType; overload;

// Allocate new buffer and convert data to it
function CastToNewBuffer(
                          const Buffer;
                          const DataSize: Integer;
                          const DataType: TABSBaseFieldType;
                          const NewDataType: TABSBaseFieldType
                        ): PAnsiChar; overload;


// Allocate new buffer and convert data to it
function CastToNewBuffer(
                          const Buffer;
                          const DataSize: Integer;
                          const DataType: TABSBaseFieldType;
                          const NewDataType: TABSBaseFieldType;
                          out NewDataSize: Integer
                        ): PAnsiChar; overload;

// Compare 2 values
function CompareValueBuffers(
                              Buffer1, Buffer2: Pointer;
                              BaseFieldType1, BaseFieldType2: TABSBaseFieldType;
                              IsField1Null: Boolean = false;
                              IsField2Null: Boolean = false;
                              PartialCompareLength: Integer = -1;
                              IgnoreCase: Boolean = false;
                              LocaleID: LCID = LOCALE_USER_DEFAULT
                            ): TABSCompareResult;

// Compare 2 values in sense of order (-1,0,1)
function CompareValueBuffersForOrder(
                              Buffer1, Buffer2: Pointer;
                              BaseFieldType1, BaseFieldType2: TABSBaseFieldType;
                              IsField1Null: Boolean = false;
                              IsField2Null: Boolean = false;
                              PartialCompareLength: Integer = -1;
                              IgnoreCase: Boolean = false;
                              LocaleID: LCID = LOCALE_USER_DEFAULT
                            ): Integer;

implementation

uses
{$IFDEF D6H}
     Variants,
{$ENDIF}
     ABSStrUtils,
     ABSMain;



//------------------------------------------------------------------------------
// load from stream
//------------------------------------------------------------------------------
procedure TABSVariant.LoadFromStream(Stream: TStream);
begin
  Clear;
  LoadDataFromStream(FDataType,Sizeof(FDataType),Stream,10183);
  LoadDataFromStream(FIsNull,Sizeof(FIsNull),Stream,10184);
  if (not FIsNull) then
   begin
    LoadDataFromStream(FDataSize,Sizeof(FDataSize),Stream,10185);
    FPData := MemoryManager.GetMem(FDataSize);
    LoadDataFromStream(FPData^,FDataSize,Stream,10186);
   end;
end; // LoadFromStream


//------------------------------------------------------------------------------
// save to stream
//------------------------------------------------------------------------------
procedure TABSVariant.SaveToStream(Stream: TStream);
begin
  SaveDataToStream(FDataType,Sizeof(FDataType),Stream,10179);
  SaveDataToStream(FIsNull,Sizeof(FIsNull),Stream,10180);
  if (not FIsNull) then
   begin
    SaveDataToStream(FDataSize,Sizeof(FDataSize),Stream,10181);
    SaveDataToStream(FPData^,FDataSize,Stream,10182);
   end;
end; // SaveToStream


//------------------------------------------------------------------------------
// Create
//------------------------------------------------------------------------------
constructor TABSVariant.Create(DataType: TABSBaseFieldType);
begin
  FPData := nil;
  FDataType := DataType;
  FDataSize := 0;
  FIsDataLinked := false;
  FIsNull := True;
end;//Create


//------------------------------------------------------------------------------
// Destroy
//------------------------------------------------------------------------------
destructor TABSVariant.Destroy;
begin
  Clear;
end;//Destroy


//------------------------------------------------------------------------------
// SetNull
//------------------------------------------------------------------------------
procedure TABSVariant.SetNull(DataType: TABSBaseFieldType);
begin
  FIsNull := True;
end;//SetNull


//------------------------------------------------------------------------------
// Free Buffer
//------------------------------------------------------------------------------
procedure TABSVariant.Clear(DataType: TABSBaseFieldType);
begin
  if ((FPData <> nil) and (not FIsDataLinked)) then
      MemoryManager.FreeAndNillMem(FPData);
  FPData := nil;
  FDataType := DataType;
  FDataSize := 0;
  FIsDataLinked := false;
  FIsNull := True;
end;//Clear


//------------------------------------------------------------------------------
// Set Data Type
//------------------------------------------------------------------------------
procedure TABSVariant.SetDataType(DataType: TABSBaseFieldType);
begin
  if not IsNull then
    try
      Cast(DataType);
    except
      Clear(DataType);
    end
  else
   if (FPData <> nil) then
    Clear(DataType)
   else
    FDataType := DataType;
end;//SetDataType


//------------------------------------------------------------------------------
// CastResultToType
//------------------------------------------------------------------------------
procedure TABSVariant.CastResultToType(NewDataType: TABSBaseFieldType; out Result);
var
  p: Pointer;
  TmpSize: Integer;
begin
  p := CastToNewBuffer(FPData, FDataSize, FDataType, NewDataType, TmpSize);
    case NewDataType of
      bftChar,
      bftVarChar:
        begin
          SetLength(AnsiString(Result), TmpSize-1);
          if (PAnsiChar(Result) <> nil) then
            Move(PAnsiChar(p)^, PAnsiChar(Result)^, TmpSize);
        end;
      bftWideChar, bftWideVarChar:
        begin
          SetLength(WideString(Result), (TmpSize) div 2 - 1);
          if (PWideChar(Result) <> nil) then
            Move(PWideChar(p)^, PWideChar(Result)^, TmpSize);
        end;
      else
        Move(p^, Result, TmpSize);
    end;
  MemoryManager.FreeAndNillMem(p);
end;//CastResultToType


//------------------------------------------------------------------------------
// Cast value to empty FPData
//------------------------------------------------------------------------------
procedure TABSVariant.CastAndSetData(const Value; ValueType: TABSBaseFieldType);
var p: Pointer;
begin
  if ((FPData <> nil) and (not FIsDataLinked)) then
    MemoryManager.FreeAndNillMem(FPData);
  if (ValueType in [bftChar, bftVarChar, bftWideChar, bftWideVarchar]) then
    p := Pointer(Value)
  else
    p := @Value;
  FPData := CastToNewBuffer(p, -1, ValueType, FDataType, FDataSize);
end;//CastAndSetData


//------------------------------------------------------------------------------
// raise EABSException if FPData = nil
//------------------------------------------------------------------------------
procedure TABSVariant.CheckDataForNull;
begin
 if IsNull then
   raise EABSException.Create(30016, ErrorGValueIsNull);
end;//CheckDataForNull


//------------------------------------------------------------------------------
// Assign data from source (or make link to Source.Data)
//------------------------------------------------------------------------------
procedure TABSVariant.Assign(Source: TABSVariant; CopyDataFlag: boolean = true);
begin
  Clear;
  FDataType := Source.FDataType;
  FDataSize := Source.FDataSize;
  FIsDataLinked := not CopyDataFlag;
  FIsNull := Source.FIsNull;

  if (not Source.IsNull) then
    if (CopyDataFlag) then
      begin
        FPData := MemoryManager.GetMem(FDataSize);
        Move(Source.FPData^, FPData^, FDataSize);
      end
    else
      FPData := Source.FPData;
end;//Assign


//------------------------------------------------------------------------------
// Set Data (or make link to Data)
//------------------------------------------------------------------------------
procedure TABSVariant.SetData(Buffer: Pointer; Size: Integer;
  DataType: TABSBaseFieldType; CopyDataFlag: boolean);
begin
  if (CopyDataFlag) then
    begin
      if ((FPData <> nil) and
          (not FIsDataLinked) and
          (Size = FDataSize)) then
      // Using Old Buffer (FPData)
      else
        begin
          Clear;
          FPData := MemoryManager.GetMem(Size);
        end
    end
  else
    begin
      Clear;
      FPData := Buffer;
    end;

  FDataType := DataType;
  FDataSize := Size;
  FIsNull := False;
  FIsDataLinked := not CopyDataFlag;
  if (CopyDataFlag) then
    Move(Buffer^, FPData^, FDataSize);
end;//SetData


//------------------------------------------------------------------------------
// Copy Data to Address
//------------------------------------------------------------------------------
function TABSVariant.CopyDataToAddress(Buffer: Pointer; MaxSize: Integer): boolean;
var
  L: Integer;
begin
  if (IsNull) then
    begin
      Result := False;
    end
  else
    begin
      L := DataSize;
      if (MaxSize <> -1) then
       if (L > MaxSize) then
        raise EABSException.Create(20056, ErrorABufferSizeExceeded);

      if (IsStringDataType and (L<=1)) then
        Result := False
      else
        begin
          Move(FPData^, Buffer^, L);
          Result := True;
        end;
    end;
end;//CopyDataToAddress




//------------------------------------------------------------------------------
// return (FPData = nil)
//------------------------------------------------------------------------------
function TABSVariant.GetIsNull: Boolean;
begin
  Result := FIsNull or (FPData = nil);
end;//GetIsNull


//------------------------------------------------------------------------------
// Set typed Data to Variant
//------------------------------------------------------------------------------
procedure TABSVariant.SetDataValue(const value; ValueType: TABSBaseFieldType);
begin
  if ( (FDataType = ValueType) and
       (FPData <> nil) and
       (not IsStringDataType) and     // Assign if simple type (Integer, ...)
       (not FIsDataLinked) ) then
   begin
    Move(Value, FPData^, FDataSize)
   end
  else
   begin
    if (FPData <> nil) then
      Clear(FDataType);
    if FDataType = bftUnknown then
      FDataType := ValueType;

    // Set NULL if value=''
    if ((IsStringFieldType(ValueType) and (PAnsiChar(value) = nil)) or
        (IsWideStringFieldType(ValueType) and (Length(WideString(PWideChar(value)))=0)) or
        (IsStringFieldType(ValueType) and (not IsWideStringFieldType(ValueType)) and (SysUtils.StrLen(PAnsiChar(value))=0))) then
     begin
      FIsDataLinked := False;
      Exit;
     end;

    if FDataType = ValueType then
      AllocMemAndSetData(FDataType, Value, FPData, FDataSize)
    else
      CastAndSetData(Value, ValueType);
  end;
  FIsNull := False;
  FIsDataLinked := False;
end;//SetDataValue


//------------------------------------------------------------------------------
// Set typed Data from Variant
//------------------------------------------------------------------------------
procedure TABSVariant.GetDataValue(out Value; ValueType: TABSBaseFieldType);
begin
  if (not IsStringFieldType(ValueType)) then
    CheckDataForNull;

  if (IsStringFieldType(ValueType) and IsNull) then
    begin
      case ValueType of
        bftChar,
        bftVarchar:
          SetLength(AnsiString(Value), 0);
        bftWideChar,
        bftWideVarchar:
          SetLength(WideString(Value), 0)
      end;
    end
  else
    if FDataType = ValueType then
     begin
       case ValueType of
        bftChar,
        bftVarchar:
          begin
            SetLength(AnsiString(Value), SysUtils.StrLen(FPData));
            Move(PAnsiChar(FPData)^, PAnsiChar(Value)^, SysUtils.StrLen(FPData));
          end;
        bftBlob:
          begin
            SetLength(AnsiString(Value), FDataSize-1);
            Move(PAnsiChar(FPData)^, PAnsiChar(Value)^, FDataSize-1);
          end;
        bftWideChar,
        bftWideVarchar:
          begin
            SetLength(WideString(Value), Length(WideString(PWideChar(FPData))));
            Move(PWideChar(FPData)^, PWideChar(Value)^, Length(WideString(PWideChar(FPData)))*sizeof(WideChar));
          end;
        else
          CopyDataToAddress(@Value);
       end;
     end
    else
      CastResultToType(ValueType, Value);
end;//GetDataValue


//------------------------------------------------------------------------------
// Set Data for Int8 (Shortint)
//------------------------------------------------------------------------------
procedure TABSVariant.SetDataAsSignedInt8(Value: Shortint);
begin
  SetDataValue(Value, bftSignedInt8);
end;//SetDataAsSignedInt8


//------------------------------------------------------------------------------
// Get Data for Int8 (Shortint)
//------------------------------------------------------------------------------
function TABSVariant.GetDataAsSignedInt8: Shortint;
begin
  GetDataValue(Result, bftSignedInt8);
end;//GetDataAsSignedInt8



//------------------------------------------------------------------------------
// Set Data for Signed Int16 (Smallint)
//------------------------------------------------------------------------------
procedure TABSVariant.SetDataAsSignedInt16(Value: Smallint);
begin
  SetDataValue(Value, bftSignedInt16);
end;//SetDataAsSignedInt16


//------------------------------------------------------------------------------
// Get Data for Signed Int16 (Smallint)
//------------------------------------------------------------------------------
function TABSVariant.GetDataAsSignedInt16: Smallint;
begin
  GetDataValue(Result, bftSignedInt16);
end;



//------------------------------------------------------------------------------
// Set Data for Signed Int32 (Integer)
//------------------------------------------------------------------------------
procedure TABSVariant.SetDataAsSignedInt32(Value: Integer);
begin
  SetDataValue(Value, bftSignedInt32);
end;//SetDataAsSignedInt32


//------------------------------------------------------------------------------
// Get Data for Signed Int32 (Integer)
//------------------------------------------------------------------------------
function TABSVariant.GetDataAsSignedInt32: Integer;
begin
  GetDataValue(Result, bftSignedInt32);
end;//GetDataAsSignedInt32



//------------------------------------------------------------------------------
// Set Data for Signed Int64 (Int64)
//------------------------------------------------------------------------------
procedure TABSVariant.SetDataAsSignedInt64(Value: Int64);
begin
  SetDataValue(Value, bftSignedInt64);
end;//SetDataAsSignedInt64


//------------------------------------------------------------------------------
// Get Data for Signed Int64 (Int64)
//------------------------------------------------------------------------------
function TABSVariant.GetDataAsSignedInt64: Int64;
begin
  GetDataValue(Result, bftSignedInt64);
end;//GetDataAsSignedInt64


//------------------------------------------------------------------------------
// Set Data for Unsigned Int8 (Byte)
//------------------------------------------------------------------------------
procedure TABSVariant.SetDataAsUnsignedInt8(Value: Byte);
begin
  SetDataValue(Value, bftUnsignedInt8);
end;//SetDataAsUnsignedInt8


//------------------------------------------------------------------------------
// Get Data for Unsigned Int8 (Byte)
//------------------------------------------------------------------------------
function TABSVariant.GetDataAsUnsignedInt8: Byte;
begin
  GetDataValue(Result, bftUnsignedInt8);
end;//GetDataAsUnsignedInt8


//------------------------------------------------------------------------------
// Set Data for Unsigned Int16 (Word)
//------------------------------------------------------------------------------
procedure TABSVariant.SetDataAsUnsignedInt16(Value: Word);
begin
  SetDataValue(Value, bftUnsignedInt16);
end;//SetDataAsUnsignedInt16


//------------------------------------------------------------------------------
// Get Data for Unsigned Int16 (Word)
//------------------------------------------------------------------------------
function TABSVariant.GetDataAsUnsignedInt16: Word;
begin
  GetDataValue(Result, bftUnsignedInt16);
end;//GetDataAsUnsignedInt16


//------------------------------------------------------------------------------
// Set Data for Unsigned Int32 (Cardinal)
//------------------------------------------------------------------------------
procedure TABSVariant.SetDataAsUnsignedInt32(Value: Cardinal);
begin
  SetDataValue(Value, bftUnsignedInt32);
end;//SetDataAsUnsignedInt32


//------------------------------------------------------------------------------
// Get Data for Unsigned Int32 (Cardinal)
//------------------------------------------------------------------------------
function TABSVariant.GetDataAsUnsignedInt32: Cardinal;
begin
  GetDataValue(Result, bftUnsignedInt32);
end;//GetDataAsUnsignedInt32


//------------------------------------------------------------------------------
// Set Data for Char, Varchar (String)
//------------------------------------------------------------------------------
procedure TABSVariant.SetDataAsAnsiString(Value: AnsiString);
begin
  SetDataValue(Value, bftVarchar);
end;//SetDataAsAnsiString


//------------------------------------------------------------------------------
// Get Data as String
//------------------------------------------------------------------------------
function TABSVariant.GetDataAsAnsiString: AnsiString;
begin
  GetDataValue(Result, bftVarchar);
end;//GetDataAsAnsiString


//------------------------------------------------------------------------------
// Set Data for WideChar, WideVarchar (WideString)
//------------------------------------------------------------------------------
procedure TABSVariant.SetDataAsWideString(Value: WideString);
begin
  SetDataValue(Value, bftWideVarchar);
end;//SetDataAsWideString


//------------------------------------------------------------------------------
// Get Data as WideString
//------------------------------------------------------------------------------
function TABSVariant.GetDataAsWideString: WideString;
begin
  GetDataValue(Result, bftWideVarchar);
end;//GetDataAsWideString


//------------------------------------------------------------------------------
// Set Data for Single
//------------------------------------------------------------------------------
procedure TABSVariant.SetDataAsSingle(Value: Single);
begin
  SetDataValue(Value, bftSingle);
end;//SetDataAsSingle


//------------------------------------------------------------------------------
// Get Data for Single
//------------------------------------------------------------------------------
function TABSVariant.GetDataAsSingle: Single;
begin
  GetDataValue(Result, bftSingle);
end;//GetDataAsSingle


//------------------------------------------------------------------------------
// Set Data for Double
//------------------------------------------------------------------------------
procedure TABSVariant.SetDataAsDouble(Value: Double);
begin
  SetDataValue(Value, bftDouble);
end;//SetDataAsDouble


//------------------------------------------------------------------------------
// Get Data for Double
//------------------------------------------------------------------------------
function TABSVariant.GetDataAsDouble: Double;
begin
  GetDataValue(Result, bftDouble);
end;//GetDataAsDouble


//------------------------------------------------------------------------------
// Set Data for Extended
//------------------------------------------------------------------------------
procedure TABSVariant.SetDataAsExtended(Value: Extended);
begin
  SetDataValue(Value, bftExtended);
end;//SetDataAsExtended


//------------------------------------------------------------------------------
// Get Data for Extended
//------------------------------------------------------------------------------
function TABSVariant.GetDataAsExtended: Extended;
begin
  GetDataValue(Result, bftExtended);
end;//GetDataAsExtended




//------------------------------------------------------------------------------
// Set Data for ABSDate
//------------------------------------------------------------------------------
procedure TABSVariant.SetDataAsABSDate(Value: TABSDate);
begin
  SetDataValue(Value, bftDate);
end;//SetDataAsABSDate


//------------------------------------------------------------------------------
// Get Data for ABSDate
//------------------------------------------------------------------------------
function TABSVariant.GetDataAsABSDate: TABSDate;
begin
  GetDataValue(Result, bftDate);
end;//GetDataAsABSDate


//------------------------------------------------------------------------------
// Set Data for TDate
//------------------------------------------------------------------------------
procedure TABSVariant.SetDataAsTDate(Value: TDateTime);
begin
  SetDataAsABSDate(DateToABSDate(Value));
end;//SetDataAsTDate


//------------------------------------------------------------------------------
// Get Data for TDate
//------------------------------------------------------------------------------
function TABSVariant.GetDataAsTDate: TDateTime;
begin
  Result := ABSDateToDate(GetDataAsABSDate);
end;//GetDataAsTDate


//------------------------------------------------------------------------------
// Set Data for ABSTime
//------------------------------------------------------------------------------
procedure TABSVariant.SetDataAsABSTime(Value: TABSTime);
begin
  SetDataValue(Value, bftTime);
end;//SetDataAsABSTime


//------------------------------------------------------------------------------
// Get Data for ABSTime
//------------------------------------------------------------------------------
function TABSVariant.GetDataAsABSTime: TABSTime;
begin
  GetDataValue(Result, bftTime);
end;//GetDataAsABSTime


//------------------------------------------------------------------------------
// Set Data for TTime
//------------------------------------------------------------------------------
procedure TABSVariant.SetDataAsTTime(Value: TDateTime);
begin
  SetDataAsABSTime(TimeToABSTime(Value));
end;//SetDataAsTTime


//------------------------------------------------------------------------------
// Get Data for ABSTime
//------------------------------------------------------------------------------
function TABSVariant.GetDataAsTTime: TDateTime;
begin
  Result := ABSTimeToTime(GetDataAsABSTime);
end;//GetDataAsTTime



//------------------------------------------------------------------------------
// Set Data for ABSDateTime
//------------------------------------------------------------------------------
procedure TABSVariant.SetDataAsABSDateTime(Value: TABSDateTime);
begin
  SetDataValue(Value, bftDateTime);
end;//SetDataAsABSDateTime


//------------------------------------------------------------------------------
// Get Data for ABSDateTime
//------------------------------------------------------------------------------
function TABSVariant.GetDataAsABSDateTime: TABSDateTime;
begin
  GetDataValue(Result, bftDateTime);
end;//GetDataAsABSDateTime


//------------------------------------------------------------------------------
// Set Data for TDateTime
//------------------------------------------------------------------------------
procedure TABSVariant.SetDataAsTDateTime(Value: TDateTime);
begin
  SetDataAsABSDateTime(DateTimeToABSDateTime(Value));
end;//SetDataAsTDateTime


//------------------------------------------------------------------------------
// Get Data for TDateTime
//------------------------------------------------------------------------------
function TABSVariant.GetDataAsTDateTime: TDateTime;
begin
  Result := ABSDateTimeToDateTime(GetDataAsABSDateTime);
end;//GetDataAsTDateTime



procedure TABSVariant.SetDataAsBoolean(Value: TABSLogical);
begin
  SetDataValue(Value, bftLogical);
end;


//------------------------------------------------------------------------------
// Get Data for Boolean
//------------------------------------------------------------------------------
function TABSVariant.GetDataAsBoolean: TABSLogical;
begin
  GetDataValue(Result, bftLogical);
end;//GetDataAsBoolean


//------------------------------------------------------------------------------
// Set Data for Currency
//------------------------------------------------------------------------------
procedure TABSVariant.SetDataAsCurrency(Value: TABSCurrency);
begin
  SetDataValue(Value, bftCurrency);
end;//SetDataAsCurrency


//------------------------------------------------------------------------------
// Get Data for Currency
//------------------------------------------------------------------------------
function TABSVariant.GetDataAsCurrency: TABSCurrency;
begin
  GetDataValue(Result, bftCurrency);
end;//GetDataAsCurrency


//------------------------------------------------------------------------------
// Set Data from Borland Variant type
//------------------------------------------------------------------------------
procedure TABSVariant.SetDataAsVariant(Value: Variant);
begin
  case VarType(Value) of
    varSmallint:
      AsSmallint := Value;
    varInteger:
      AsInteger := Value;
    varSingle:
      AsSingle := Value;
    varDouble:
      AsDouble := Value;
    varCurrency:
      AsCurrency := Value;
    varDate:
      AsTDateTime := Value;
    varOleStr:
      AsWideString := Value;
    //varDispatch
    //varError
    varBoolean: AsBoolean := Value;
    //varVariant
    //varUnknown
{$IFDEF D6H}
    varShortInt:
      AsShortInt := Value;
    varWord:
      AsWord := Value;
    varLongWord:
      AsCardinal := Value;
    varInt64:
      AsInt64 := Value;
{$ENDIF}
    varByte:
      AsByte := Value;
    //varStrArg
    //varString,
    varString .. varString + $1F:
{$IFDEF D12H}
      if (VarType(Value) = varUString) then
       AsWideString := Value
      else
{$ENDIF}
       AsAnsiString := AnsiString(Value);
    //varAny
    //varTypeMask
    //varArray
    //varByRef
    varNull, varEmpty:
      SetNull(FDataType);
    else
      raise EABSException.Create(30113, ErrorGUnsupportedVariantType, [IntToStr(VarType(Value))]);
  end;
end;//SetDataAsVariant


//------------------------------------------------------------------------------
// Get Data to Borland Variant type
//------------------------------------------------------------------------------
function TABSVariant.GetDataAsVariant: Variant;
begin
  if (IsNull) then
    Result := Null
  else
    case FDataType of
      bftChar,
      bftVarchar:
        Result := AsAnsiString;
      bftWideChar,
      bftWideVarchar:
        Result := AsWideString;


      bftSignedInt8:
        Result := AsShortint;
      bftSignedInt16:
        Result := AsSmallint;
      bftSignedInt32:
        Result := AsInteger;
  {$IFDEF D6H}
      bftSignedInt64:
        Result := AsInt64;
  {$ENDIF}
      bftUnsignedInt8:
        Result := AsByte;
      bftUnsignedInt16:
        Result := AsWord;
      bftUnsignedInt32:
        Result := AsCardinal;

      bftSingle:
        Result := AsSingle;
      bftDouble:
        Result := AsDouble;
      bftExtended:
        Result := AsExtended;

      bftDate:
        Result := AsTDate;
      bftTime:
        Result := AsTTime;
      bftDateTime:
        Result := AsTDateTime;

      bftLogical:
        Result := AsLogical;

      bftCurrency:
        Result := AsCurrency;

      bftBlob:
        Result := AsAnsiString;

      else
        // Check for null
        if (IsNull) then
          Result := Null
        else
        raise EABSException.Create(30114, ErrorGUnsupportedVariantType, [BftToStr(FDataType)]);
    end;//case
end;//GetDataAsVariant


//------------------------------------------------------------------------------
// Cast
//------------------------------------------------------------------------------
procedure TABSVariant.Cast(NewDataType: TABSBaseFieldType);
var p: Pointer;
    NewSize: Integer;
begin
  if (FDataType = NewDataType) then
    Exit;

  if ( IsNull ) then
    begin
      Clear(NewDataType);
    end
  else
    begin
      if (FDataType = bftClob) and (NewDataType = bftVarChar) then
        begin
          Inc(FDataSize);
          MemoryManager.ReallocMem(FPData, FDataSize, True);
          FDataType := NewDataType;
        end
       else
        begin
          p := CastToNewBuffer(FPData, FDataSize, FDataType, NewDataType, NewSize);
          Clear(NewDataType);
          FIsNull := False;
          FDataType := NewDataType;
          FPData := p;
          FDataSize := NewSize;
        end;
    end;
end;//Cast


//------------------------------------------------------------------------------
// return true if DataType is numeric
//------------------------------------------------------------------------------
function TABSVariant.IsNumericDataType: Boolean;
begin
  Result := IsNumericFieldType(FDataType);
end;//IsNumericDataType


//------------------------------------------------------------------------------
// return true if DataType is String
//------------------------------------------------------------------------------
function TABSVariant.IsStringDataType: Boolean;
begin
  Result := IsStringFieldType(FDataType);
end;//IsStringDataType


//------------------------------------------------------------------------------
// return true if DataType is WideString
//------------------------------------------------------------------------------
function TABSVariant.IsWideStringDataType: Boolean;
begin
  Result := IsWideStringFieldType(FDataType);
end;//IsStringDataType


//------------------------------------------------------------------------------
// return true if DataType is BLOB
//------------------------------------------------------------------------------
function TABSVariant.IsBlobDataType: Boolean;
begin
  Result := IsBLOBFieldType(FDataType);
end;//IsBlobDataType


//------------------------------------------------------------------------------
// return true if DataType is Time, Date, DateTime
//------------------------------------------------------------------------------
function TABSVariant.IsDateTimeDataType: Boolean;
begin
  Result := IsDateTimeFieldType(FDataType);
end;//IsDateTimeFieldType


//------------------------------------------------------------------------------
// return Length of String or -1 (if not IsStringType)
//------------------------------------------------------------------------------
function TABSVariant.StrLen: Integer;
begin
  if (IsStringDataType and (not IsNull)) then
    if (IsWideStringDataType) then
      Result := ((FDataSize) div 2) - 1
    else
      Result := FDataSize - 1
  else
    Result := -1;
end;


//------------------------------------------------------------------------------
// value := -value ( if not number then raise)
//------------------------------------------------------------------------------
procedure TABSVariant.InvertValue;
begin
  if not IsNull then
    case FDataType of
      bftSignedInt8:      AsShortint := -AsShortint;
      bftSignedInt16:     AsSmallint := -AsSmallint;
      bftSignedInt32:     AsInteger := -AsInteger;
      bftSignedInt64:     AsInt64 := -AsInt64;

      bftUnsignedInt8:    AsShortint := -AsByte;
      bftUnsignedInt16:   AsSmallint := -AsWord;
      bftUnsignedInt32:   AsInteger := -AsCardinal;

      bftSingle:          AsSingle := -AsSingle;
      bftDouble:          AsDouble := -AsDouble;
      bftExtended:        AsExtended := -AsExtended;

      bftDate:            AsABSDate := -AsABSDate;

      bftLogical:         AsLogical := not AsLogical;
      bftCurrency:        AsCurrency := -AsCurrency;
      else
        raise EABSException.Create(30123, ErrorGCannotInvertValue, [BftToStr(FDataType)]);
    end;
end;//InvertValue


{$IFOPT Q+}
 {$DEFINE RESET_OVERFLOW}
 {$Q-}
{$ENDIF}
//------------------------------------------------------------------------------
// data := data + value
//------------------------------------------------------------------------------
procedure TABSVariant.Add(Value: TABSVariant);
var
  dt: TABSDateTime;
begin
  if Value.IsNull then
   begin
    if not IsStringDataType then SetNull(FDataType)
   end
  else
    if not IsNull then
      begin
        Cast(GetCommonDataType(FDataType, Value.DataType));
        case FDataType of
          bftChar,
          bftVarchar:         AsAnsiString := AsAnsiString + Value.AsAnsiString;
          bftWideChar,
          bftWideVarchar:     AsWideString := AsWideString + Value.AsWideString;

          bftSignedInt8:      AsShortint := AsShortint + Value.AsShortint;
          bftSignedInt16:     AsSmallint := AsSmallint + Value.AsSmallint;
          bftSignedInt32:     AsInteger := AsInteger + Value.AsInteger;
          bftSignedInt64:     AsInt64 := AsInt64 + Value.AsInt64;

          bftUnsignedInt8:    AsByte := AsByte + Value.AsByte;
          bftUnsignedInt16:   AsWord := AsWord + Value.AsWord;
          bftUnsignedInt32:   AsCardinal := AsCardinal + Value.AsCardinal;

          bftSingle:          AsSingle := AsSingle + Value.AsSingle;
          bftDouble:          AsDouble := AsDouble + Value.AsDouble;
          bftExtended:        AsExtended := AsExtended + Value.AsExtended;

          bftDate:            AsABSDate := AsABSDate + Value.AsABSDate;
          bftTime:            AsABSTime := AsABSTime + Value.AsABSTime;
          bftDateTime:        begin
                                dt := AsABSDateTime;
                                dt.Date := dt.Date + Value.AsABSDateTime.Date;
                                dt.Time := dt.Time + Value.AsABSDateTime.Time;
                                if (dt.Time >= MILSECS_IN_DAY) then
                                 begin
                                  dt.Date := dt.Date + dt.Time div MILSECS_IN_DAY;
                                  dt.Time := dt.Time mod MILSECS_IN_DAY;
                                 end;
                                AsABSDateTime := dt;
                              end;

          bftLogical:         AsLogical := AsLogical or Value.AsLogical;
          bftCurrency:        AsCurrency := AsCurrency + Value.AsCurrency;
          else
            raise EABSException.Create(30124, ErrorGNotNumericDataType, ['+']);
        end;
      end
    else//If IsNull
      if not IsStringDataType then
        SetNull(FDataType)
      else
        Assign(Value);

end;//Add


//------------------------------------------------------------------------------
// data := data - value
//------------------------------------------------------------------------------
procedure TABSVariant.Sub(Value: TABSVariant);
var
  dt: TABSDateTime;
begin
  if Value.IsNull then
    SetNull(FDataType)
  else
    if not IsNull then
      begin
        Cast(GetCommonDataType(FDataType, Value.DataType));
        case FDataType of
          bftSignedInt8:      AsShortint := AsShortint - Value.AsShortint;
          bftSignedInt16:     AsSmallint := AsSmallint - Value.AsSmallint;
          bftSignedInt32:     AsInteger := AsInteger - Value.AsInteger;
          bftSignedInt64:     AsInt64 := AsInt64 - Value.AsInt64;

          bftUnsignedInt8:    AsByte := AsByte - Value.AsByte;
          bftUnsignedInt16:   AsWord := AsWord - Value.AsWord;
          bftUnsignedInt32:   AsCardinal := AsCardinal - Value.AsCardinal;

          bftSingle:          AsSingle := AsSingle - Value.AsSingle;
          bftDouble:          AsDouble := AsDouble - Value.AsDouble;
          bftExtended:        AsExtended := AsExtended - Value.AsExtended;

          bftDate:            AsABSDate := AsABSDate - Value.AsABSDate;
          bftTime:            AsABSTime := AsABSTime - Value.AsABSTime;
          bftDateTime:        begin
                                dt := AsABSDateTime;
                                dt.Date := dt.Date - Value.AsABSDateTime.Date;
                                dt.Time := dt.Time - Value.AsABSDateTime.Time;
                                if (dt.Time >= MILSECS_IN_DAY) then
                                 begin
                                  dt.Date := dt.Date + dt.Time div MILSECS_IN_DAY;
                                  dt.Time := dt.Time mod MILSECS_IN_DAY;
                                 end;
                                AsABSDateTime := dt;
                              end;

          bftLogical:         AsLogical := AsLogical or Value.AsLogical;
          bftCurrency:        AsCurrency := AsCurrency - Value.AsCurrency;

          else
            raise EABSException.Create(30125, ErrorGNotNumericDataType, ['-']);
        end;
      end;
end;//Sub


//------------------------------------------------------------------------------
// data := data * value
//------------------------------------------------------------------------------
procedure TABSVariant.Mul(Value: TABSVariant);
var
  dt: TABSDateTime;
begin
  if Value.IsNull then
    SetNull(FDataType)
  else
    if not IsNull then
      begin
        Cast(GetCommonDataType(FDataType, Value.DataType));
        case FDataType of
          bftSignedInt8:      AsShortint := AsShortint * Value.AsShortint;
          bftSignedInt16:     AsSmallint := AsSmallint * Value.AsSmallint;
          bftSignedInt32:     AsInteger := AsInteger * Value.AsInteger;
          bftSignedInt64:     AsInt64 := AsInt64 * Value.AsInt64;

          bftUnsignedInt8:    AsByte := AsByte * Value.AsByte;
          bftUnsignedInt16:   AsWord := AsWord * Value.AsWord;
          bftUnsignedInt32:   AsCardinal := AsCardinal * Value.AsCardinal;

          bftSingle:          AsSingle := AsSingle * Value.AsSingle;
          bftDouble:          AsDouble := AsDouble * Value.AsDouble;
          bftExtended:        AsExtended := AsExtended * Value.AsExtended;

          bftDate:            AsABSDate := AsABSDate * Value.AsABSDate;
          bftTime:            AsABSTime := AsABSTime * Value.AsABSTime;
          bftDateTime:        begin
                                dt := AsABSDateTime;
                                dt.Date := dt.Date * Value.AsABSDateTime.Date;
                                dt.Time := dt.Time * Value.AsABSDateTime.Time;
                                if (dt.Time >= MILSECS_IN_DAY) then
                                 begin
                                  dt.Date := dt.Date + dt.Time div MILSECS_IN_DAY;
                                  dt.Time := dt.Time mod MILSECS_IN_DAY;
                                 end;
                                AsABSDateTime := dt;
                              end;

          bftLogical:         AsLogical := AsLogical or Value.AsLogical;
          bftCurrency:        AsCurrency := AsCurrency * Value.AsCurrency;
          else
            raise EABSException.Create(30126, ErrorGNotNumericDataType, ['*']);
        end;
      end;
end;//Mul


//------------------------------------------------------------------------------
// data := data / value
//------------------------------------------------------------------------------
procedure TABSVariant.Division(Value: TABSVariant);
var
  dt: TABSDateTime;
begin
  if Value.IsNull then
    SetNull(FDataType)
  else
    if not IsNull then
      begin
        try
          Cast(GetCommonDataType(FDataType, Value.DataType));
          case FDataType of
            bftSignedInt8:      AsShortint := AsShortint div Value.AsShortint;
            bftSignedInt16:     AsSmallint := AsSmallint div Value.AsSmallint;
            bftSignedInt32:     AsInteger := AsInteger div Value.AsInteger;
            bftSignedInt64:     AsInt64 := AsInt64 div Value.AsInt64;

            bftUnsignedInt8:    AsByte := AsByte div Value.AsByte;
            bftUnsignedInt16:   AsWord := AsWord div Value.AsWord;
            bftUnsignedInt32:   AsCardinal := AsCardinal div Value.AsCardinal;

            bftSingle:          AsSingle := AsSingle / Value.AsSingle;
            bftDouble:          AsDouble := AsDouble / Value.AsDouble;
            bftExtended:        AsExtended := AsExtended / Value.AsExtended;

            bftDate:            AsABSDate := AsABSDate div Value.AsABSDate;
            bftTime:            AsABSTime := AsABSTime div Value.AsABSTime;
            bftDateTime:        begin
                                  dt := AsABSDateTime;
                                  dt.Date := dt.Date div Value.AsABSDateTime.Date;
                                  dt.Time := dt.Time div Value.AsABSDateTime.Time;
                                  if (dt.Time >= MILSECS_IN_DAY) then
                                   begin
                                    dt.Date := dt.Date + dt.Time div MILSECS_IN_DAY;
                                    dt.Time := dt.Time mod MILSECS_IN_DAY;
                                   end;
                                  AsABSDateTime := dt;
                                end;

            bftLogical:         AsLogical := AsLogical or Value.AsLogical;
            bftCurrency:        AsCurrency := AsCurrency / Value.AsCurrency;
            else
              raise EABSException.Create(30127, ErrorGNotNumericDataType, ['/']);
          end;
        except
          on EABSException do raise;
          on e: Exception do
            raise EABSException.Create(30128, ErrorGDivisionError, [e.Message]);
      end;
    end;
end;//Division
 {$IFDEF RESET_OVERFLOW}
  {$Q+}
 {$ENDIF}


//------------------------------------------------------------------------------
// Compare with another Variants
//------------------------------------------------------------------------------
function TABSVariant.Compare(Value: TABSVariant; TrueFalseNullLogic, CaseInsensitive, PartialKey: boolean): TABSCompareResult;
var
  i: Integer;
begin
  if (PartialKey) then
    // 5.07
    // fix LikeTest1
    // begin old code
    // i := min(StrLen, Value.StrLen)
    // end old code
    i := Value.StrLen
  else
    i := -1;
  Result := CompareValueBuffers(FPData, Value.FPData,
                                FDataType, Value.DataType,
                                IsNull, Value.IsNull,
                                i, CaseInsensitive);
  if (not TrueFalseNullLogic) then
   case Result of
    cmprBothNull:
      Result := cmprEqual;
    cmprLeftNull:
      Result := cmprLower;
    cmprRightNull:
      Result := cmprGreater;
   end;
end;//Compare


//------------------------------------------------------------------------------
// if it's possible w/o data loss, converts value of WideString to AnsiString
//------------------------------------------------------------------------------
procedure TABSVariant.TryToReduceWideStringToAnsiString;
var
  ws: WideString;
begin
  if (IsWideStringDataType) then
    if (WideString(AsAnsiString) = AsWideString) then
      begin
        ws := AsWideString;
        Clear;
        AsAnsiString := AnsiString(ws);
      end;
end;// TryToReduceWideStringToAnsiString

//------------------------------------------------------------------------------
// Return Common DataType for 2 types, or ftUnknown
//------------------------------------------------------------------------------
function GetCommonDataType(a,b: TABSBaseFieldType; ForCompare: Boolean=False): TABSBaseFieldType;
begin
{  if (a = b) then
    begin
      Result := a;
      Exit;
    end;
}
  Result := bftUnknown;
  case a of
    bftChar:
      case b of
        bftChar:             Result := bftChar;
        bftWideChar:         Result := bftWideChar;
        bftVarchar:          Result := bftVarchar;
        bftWideVarchar:      Result := bftWideVarchar;

        bftSignedInt8:       Result := bftChar;
        bftSignedInt16:      Result := bftChar;
        bftSignedInt32:      Result := bftChar;
        bftSignedInt64:      Result := bftChar;
        bftUnsignedInt8:     Result := bftChar;
        bftUnsignedInt16:    Result := bftChar;
        bftUnsignedInt32:    Result := bftChar;

        bftSingle:           Result := bftChar;
        bftDouble:           Result := bftChar;
        bftExtended:         Result := bftChar;

        bftDate:             if ForCompare then Result := bftDate else Result := bftChar;
        bftTime:             if ForCompare then Result := bftTime else Result := bftChar;
        bftDateTime:         if ForCompare then Result := bftDateTime else Result := bftChar;

        bftLogical:          Result := bftChar;
        bftCurrency:         Result := bftChar;

        bftClob:             Result := bftChar;
        bftWideClob:         Result := bftWideChar;
      end;
    bftWideChar:
      case b of
        bftChar:             Result := bftWideChar;
        bftWideChar:         Result := bftWideChar;
        bftVarchar:          Result := bftWideChar;
        bftWideVarchar:      Result := bftWideVarchar;

        bftSignedInt8:       Result := bftWideChar;
        bftSignedInt16:      Result := bftWideChar;
        bftSignedInt32:      Result := bftWideChar;
        bftSignedInt64:      Result := bftWideChar;
        bftUnsignedInt8:     Result := bftWideChar;
        bftUnsignedInt16:    Result := bftWideChar;
        bftUnsignedInt32:    Result := bftWideChar;

        bftSingle:           Result := bftWideChar;
        bftDouble:           Result := bftWideChar;
        bftExtended:         Result := bftWideChar;

        bftDate:             if ForCompare then Result := bftDate else Result := bftWideChar;
        bftTime:             if ForCompare then Result := bftTime else Result := bftWideChar;
        bftDateTime:         if ForCompare then Result := bftDateTime else Result := bftWideChar;

        bftLogical:          Result := bftWideChar;
        bftCurrency:         Result := bftWideChar;

        bftClob:             Result := bftWideChar;
        bftWideClob:         Result := bftWideChar;
      end;
    bftVarchar:
      case b of
        bftChar:             Result := bftVarchar;
        bftWideChar:         Result := bftWideChar;
        bftVarchar:          Result := bftVarchar;
        bftWideVarchar:      Result := bftWideVarchar;

        bftSignedInt8:       Result := bftVarchar;
        bftSignedInt16:      Result := bftVarchar;
        bftSignedInt32:      Result := bftVarchar;
        bftSignedInt64:      Result := bftVarchar;
        bftUnsignedInt8:     Result := bftVarchar;
        bftUnsignedInt16:    Result := bftVarchar;
        bftUnsignedInt32:    Result := bftVarchar;

        bftSingle:           Result := bftVarchar;
        bftDouble:           Result := bftVarchar;
        bftExtended:         Result := bftVarchar;

        bftDate:             if ForCompare then Result := bftDate else Result := bftVarchar;
        bftTime:             if ForCompare then Result := bftTime else Result := bftVarchar;
        bftDateTime:         if ForCompare then Result := bftDateTime else Result := bftVarchar;

        bftLogical:          Result := bftVarchar;
        bftCurrency:         Result := bftVarchar;

        bftClob:             Result := bftVarchar;
        bftWideClob:         Result := bftWideVarchar;
      end;
    bftWideVarchar:
      case b of
        bftChar:             Result := bftWideVarchar;
        bftWideChar:         Result := bftWideVarchar;
        bftVarchar:          Result := bftWideVarchar;
        bftWideVarchar:      Result := bftWideVarchar;

        bftSignedInt8:       Result := bftWideVarchar;
        bftSignedInt16:      Result := bftWideVarchar;
        bftSignedInt32:      Result := bftWideVarchar;
        bftSignedInt64:      Result := bftWideVarchar;
        bftUnsignedInt8:     Result := bftWideVarchar;
        bftUnsignedInt16:    Result := bftWideVarchar;
        bftUnsignedInt32:    Result := bftWideVarchar;

        bftSingle:           Result := bftWideVarchar;
        bftDouble:           Result := bftWideVarchar;
        bftExtended:         Result := bftWideVarchar;

        bftDate:             if ForCompare then Result := bftDate else Result := bftWideVarchar;
        bftTime:             if ForCompare then Result := bftTime else Result := bftWideVarchar;
        bftDateTime:         if ForCompare then Result := bftDateTime else Result := bftWideVarchar;

        bftLogical:          Result := bftWideVarchar;
        bftCurrency:         Result := bftWideVarchar;

        bftClob:             Result := bftWideVarchar;
        bftWideClob:         Result := bftWideVarchar;
      end;
    bftSignedInt8:
      case b of
        bftChar:             Result := bftChar;
        bftWideChar:         Result := bftWideChar;
        bftVarchar:          Result := bftVarchar;
        bftWideVarchar:      Result := bftWideVarchar;

        bftSignedInt8:       Result := bftSignedInt8;
        bftSignedInt16:      Result := bftSignedInt16;
        bftSignedInt32:      Result := bftSignedInt32;
        bftSignedInt64:      Result := bftSignedInt64;
        bftUnsignedInt8:     Result := bftSignedInt16;
        bftUnsignedInt16:    Result := bftUnsignedInt16;
        bftUnsignedInt32:    Result := bftUnsignedInt32;

        bftSingle:           Result := bftSingle;
        bftDouble:           Result := bftDouble;
        bftExtended:         Result := bftExtended;

        bftDate:             Result := bftDate;
        bftTime:             Result := bftTime;
        bftDateTime:         Result := bftDateTime;

        bftLogical:          Result := bftSignedInt8;
        bftCurrency:         Result := bftCurrency;

      end;
    bftSignedInt16:
      case b of
        bftChar:             Result := bftChar;
        bftWideChar:         Result := bftWideChar;
        bftVarchar:          Result := bftVarchar;
        bftWideVarchar:      Result := bftWideVarchar;

        bftSignedInt8:       Result := bftSignedInt16;
        bftSignedInt16:      Result := bftSignedInt16;
        bftSignedInt32:      Result := bftSignedInt32;
        bftSignedInt64:      Result := bftSignedInt64;
        bftUnsignedInt8:     Result := bftSignedInt16;
        bftUnsignedInt16:    Result := bftUnsignedInt16;
        bftUnsignedInt32:    Result := bftUnsignedInt32;

        bftSingle:           Result := bftSingle;
        bftDouble:           Result := bftDouble;
        bftExtended:         Result := bftExtended;

        bftDate:             Result := bftDate;
        bftTime:             Result := bftTime;
        bftDateTime:         Result := bftDateTime;

        bftLogical:          Result := bftSignedInt16;
        bftCurrency:         Result := bftCurrency;

      end;
    bftSignedInt32:
      case b of
        bftChar:             Result := bftChar;
        bftWideChar:         Result := bftWideChar;
        bftVarchar:          Result := bftVarchar;
        bftWideVarchar:      Result := bftWideVarchar;

        bftSignedInt8:       Result := bftSignedInt32;
        bftSignedInt16:      Result := bftSignedInt32;
        bftSignedInt32:      Result := bftSignedInt32;
        bftSignedInt64:      Result := bftSignedInt64;
        bftUnsignedInt8:     Result := bftSignedInt32;
        bftUnsignedInt16:    Result := bftSignedInt32;
        bftUnsignedInt32:    Result := bftSignedInt64;

        bftSingle:           Result := bftSingle;
        bftDouble:           Result := bftDouble;
        bftExtended:         Result := bftExtended;

        bftDate:             Result := bftDate;
        bftTime:             Result := bftTime;
        bftDateTime:         Result := bftDateTime;

        bftLogical:          Result := bftSignedInt32;
        bftCurrency:         Result := bftCurrency;

      end;
    bftSignedInt64:
      case b of
        bftChar:             Result := bftChar;
        bftWideChar:         Result := bftWideChar;
        bftVarchar:          Result := bftVarchar;
        bftWideVarchar:      Result := bftWideVarchar;

        bftSignedInt8:       Result := bftSignedInt64;
        bftSignedInt16:      Result := bftSignedInt64;
        bftSignedInt32:      Result := bftSignedInt64;
        bftSignedInt64:      Result := bftSignedInt64;
        bftUnsignedInt8:     Result := bftSignedInt64;
        bftUnsignedInt16:    Result := bftSignedInt64;
        bftUnsignedInt32:    Result := bftSignedInt64;

        bftSingle:           Result := bftSingle;
        bftDouble:           Result := bftDouble;
        bftExtended:         Result := bftExtended;

        bftDate:             Result := bftDate;
        bftTime:             Result := bftTime;
        bftDateTime:         Result := bftDateTime;

        bftLogical:          Result := bftSignedInt64;
        bftCurrency:         Result := bftCurrency;

      end;
    bftUnsignedInt8:
      case b of
        bftChar:             Result := bftChar;
        bftWideChar:         Result := bftWideChar;
        bftVarchar:          Result := bftVarchar;
        bftWideVarchar:      Result := bftWideVarchar;

        bftSignedInt8:       Result := bftSignedInt16;
        bftSignedInt16:      Result := bftSignedInt16;
        bftSignedInt32:      Result := bftSignedInt32;
        bftSignedInt64:      Result := bftSignedInt64;
        bftUnsignedInt8:     Result := bftUnsignedInt8;
        bftUnsignedInt16:    Result := bftUnsignedInt16;
        bftUnsignedInt32:    Result := bftUnsignedInt32;

        bftSingle:           Result := bftSingle;
        bftDouble:           Result := bftDouble;
        bftExtended:         Result := bftExtended;

        bftDate:             Result := bftDate;
        bftTime:             Result := bftTime;
        bftDateTime:         Result := bftDateTime;

        bftLogical:          Result := bftUnsignedInt8;
        bftCurrency:         Result := bftCurrency;

      end;
    bftUnsignedInt16:
      case b of
        bftChar:             Result := bftChar;
        bftWideChar:         Result := bftWideChar;
        bftVarchar:          Result := bftVarchar;
        bftWideVarchar:      Result := bftWideVarchar;

        bftSignedInt8:       Result := bftSignedInt32;
        bftSignedInt16:      Result := bftSignedInt32;
        bftSignedInt32:      Result := bftSignedInt32;
        bftSignedInt64:      Result := bftSignedInt64;
        bftUnsignedInt8:     Result := bftUnsignedInt16;
        bftUnsignedInt16:    Result := bftUnsignedInt16;
        bftUnsignedInt32:    Result := bftUnsignedInt32;

        bftSingle:           Result := bftSingle;
        bftDouble:           Result := bftDouble;
        bftExtended:         Result := bftExtended;

        bftDate:             Result := bftDate;
        bftTime:             Result := bftTime;
        bftDateTime:         Result := bftDateTime;

        bftLogical:          Result := bftUnsignedInt16;
        bftCurrency:         Result := bftCurrency;

      end;
    bftUnsignedInt32:
      case b of
        bftChar:             Result := bftChar;
        bftWideChar:         Result := bftWideChar;
        bftVarchar:          Result := bftVarchar;
        bftWideVarchar:      Result := bftWideVarchar;

        bftSignedInt8:       Result := bftSignedInt64;
        bftSignedInt16:      Result := bftSignedInt64;
        bftSignedInt32:      Result := bftSignedInt64;
        bftSignedInt64:      Result := bftSignedInt64;
        bftUnsignedInt8:     Result := bftUnsignedInt32;
        bftUnsignedInt16:    Result := bftUnsignedInt32;
        bftUnsignedInt32:    Result := bftUnsignedInt32;

        bftSingle:           Result := bftSingle;
        bftDouble:           Result := bftDouble;
        bftExtended:         Result := bftExtended;

        bftDate:             Result := bftDate;
        bftTime:             Result := bftTime;
        bftDateTime:         Result := bftDateTime;

        bftLogical:          Result := bftUnsignedInt32;
        bftCurrency:         Result := bftCurrency;

      end;

    bftSingle:
      case b of
        bftChar:             Result := bftChar;
        bftWideChar:         Result := bftWideChar;
        bftVarchar:          Result := bftVarchar;
        bftWideVarchar:      Result := bftWideVarchar;

        bftSignedInt8:       Result := bftSingle;
        bftSignedInt16:      Result := bftSingle;
        bftSignedInt32:      Result := bftSingle;
        bftSignedInt64:      Result := bftSingle;
        bftUnsignedInt8:     Result := bftSingle;
        bftUnsignedInt16:    Result := bftSingle;
        bftUnsignedInt32:    Result := bftSingle;

        bftSingle:           Result := bftSingle;
        bftDouble:           Result := bftDouble;
        bftExtended:         Result := bftExtended;

        bftDate:             Result := bftDate;
        bftTime:             Result := bftTime;
        bftDateTime:         Result := bftDateTime;

        bftLogical:          Result := bftSingle;
        bftCurrency:         Result := bftCurrency;

      end;
    bftDouble:
      case b of
        bftChar:             Result := bftChar;
        bftWideChar:         Result := bftWideChar;
        bftVarchar:          Result := bftVarchar;
        bftWideVarchar:      Result := bftWideVarchar;

        bftSignedInt8:       Result := bftDouble;
        bftSignedInt16:      Result := bftDouble;
        bftSignedInt32:      Result := bftDouble;
        bftSignedInt64:      Result := bftDouble;
        bftUnsignedInt8:     Result := bftDouble;
        bftUnsignedInt16:    Result := bftDouble;
        bftUnsignedInt32:    Result := bftDouble;

        bftSingle:           Result := bftDouble;
        bftDouble:           Result := bftDouble;
        bftExtended:         Result := bftExtended;

        bftDate:             Result := bftDate;
        bftTime:             Result := bftTime;
        bftDateTime:         Result := bftDateTime;

        bftLogical:          Result := bftDouble;
        bftCurrency:         Result := bftCurrency;

      end;
    bftExtended:
      case b of
        bftChar:             Result := bftChar;
        bftWideChar:         Result := bftWideChar;
        bftVarchar:          Result := bftVarchar;
        bftWideVarchar:      Result := bftWideVarchar;

        bftSignedInt8:       Result := bftExtended;
        bftSignedInt16:      Result := bftExtended;
        bftSignedInt32:      Result := bftExtended;
        bftSignedInt64:      Result := bftExtended;
        bftUnsignedInt8:     Result := bftExtended;
        bftUnsignedInt16:    Result := bftExtended;
        bftUnsignedInt32:    Result := bftExtended;

        bftSingle:           Result := bftExtended;
        bftDouble:           Result := bftExtended;
        bftExtended:         Result := bftExtended;

        bftDate:             Result := bftDate;
        bftTime:             Result := bftTime;
        bftDateTime:         Result := bftDateTime;

        bftLogical:          Result := bftExtended;
        bftCurrency:         Result := bftCurrency;

      end;

    bftDate:
      case b of
        bftChar:             if ForCompare then Result := bftDate else Result := bftChar;
        bftWideChar:         if ForCompare then Result := bftDate else Result := bftWideChar;
        bftVarchar:          if ForCompare then Result := bftDate else Result := bftVarchar;
        bftWideVarchar:      if ForCompare then Result := bftDate else Result := bftWideVarchar;

        bftSignedInt8:       Result := bftDate;
        bftSignedInt16:      Result := bftDate;
        bftSignedInt32:      Result := bftDate;
        bftSignedInt64:      Result := bftDate;
        bftUnsignedInt8:     Result := bftDate;
        bftUnsignedInt16:    Result := bftDate;
        bftUnsignedInt32:    Result := bftDate;

        bftSingle:           Result := bftDate;
        bftDouble:           Result := bftDate;
        bftExtended:         Result := bftDate;

        bftDate:             Result := bftDate;
        bftTime:             Result := bftDateTime;
        bftDateTime:         Result := bftDateTime;

        bftLogical:          Result := bftUnknown;
        bftCurrency:         Result := bftUnknown;

      end;
    bftTime:
      case b of
        bftChar:             if ForCompare then Result := bftTime else Result := bftChar;
        bftWideChar:         if ForCompare then Result := bftTime else Result := bftWideChar;
        bftVarchar:          if ForCompare then Result := bftTime else Result := bftVarchar;
        bftWideVarchar:      if ForCompare then Result := bftTime else Result := bftWideVarchar;

        bftSignedInt8:       Result := bftTime;
        bftSignedInt16:      Result := bftTime;
        bftSignedInt32:      Result := bftTime;
        bftSignedInt64:      Result := bftTime;
        bftUnsignedInt8:     Result := bftTime;
        bftUnsignedInt16:    Result := bftTime;
        bftUnsignedInt32:    Result := bftTime;

        bftSingle:           Result := bftTime;
        bftDouble:           Result := bftTime;
        bftExtended:         Result := bftTime;

        bftDate:             Result := bftDateTime;
        bftTime:             Result := bftTime;
        bftDateTime:         Result := bftDateTime;

        bftLogical:          Result := bftUnknown;
        bftCurrency:         Result := bftUnknown;

      end;
    bftDateTime:
      case b of
        bftChar:             if ForCompare then Result := bftDateTime else Result := bftChar;
        bftWideChar:         if ForCompare then Result := bftDateTime else Result := bftWideChar;
        bftVarchar:          if ForCompare then Result := bftDateTime else Result := bftVarchar;
        bftWideVarchar:      if ForCompare then Result := bftDateTime else Result := bftWideVarchar;

        bftSignedInt8:       Result := bftDateTime;
        bftSignedInt16:      Result := bftDateTime;
        bftSignedInt32:      Result := bftDateTime;
        bftSignedInt64:      Result := bftDateTime;
        bftUnsignedInt8:     Result := bftDateTime;
        bftUnsignedInt16:    Result := bftDateTime;
        bftUnsignedInt32:    Result := bftDateTime;

        bftSingle:           Result := bftDateTime;
        bftDouble:           Result := bftDateTime;
        bftExtended:         Result := bftDateTime;

        bftDate:             Result := bftDateTime;
        bftTime:             Result := bftDateTime;
        bftDateTime:         Result := bftDateTime;

        bftLogical:          Result := bftUnknown;
        bftCurrency:         Result := bftUnknown;

      end;

    bftLogical:
      case b of
        bftChar:             Result := bftChar;
        bftWideChar:         Result := bftWideChar;
        bftVarchar:          Result := bftVarchar;
        bftWideVarchar:      Result := bftWideVarchar;

        bftSignedInt8:       Result := bftSignedInt8;
        bftSignedInt16:      Result := bftSignedInt16;
        bftSignedInt32:      Result := bftSignedInt32;
        bftSignedInt64:      Result := bftSignedInt64;
        bftUnsignedInt8:     Result := bftUnsignedInt8;
        bftUnsignedInt16:    Result := bftUnsignedInt16;
        bftUnsignedInt32:    Result := bftUnsignedInt32;

        bftSingle:           Result := bftSingle;
        bftDouble:           Result := bftDouble;
        bftExtended:         Result := bftExtended;

        bftDate:             Result := bftUnknown;
        bftTime:             Result := bftUnknown;
        bftDateTime:         Result := bftUnknown;

        bftLogical:          Result := bftLogical;
        bftCurrency:         Result := bftUnknown;

      end;
    bftCurrency:
      case b of
        bftChar:             Result := bftChar;
        bftWideChar:         Result := bftWideChar;
        bftVarchar:          Result := bftVarchar;
        bftWideVarchar:      Result := bftWideVarchar;
        // 5.09: fix currecy with integer compare bug
        bftSignedInt8:       Result := bftCurrency;
        bftSignedInt16:      Result := bftCurrency;
        bftSignedInt32:      Result := bftCurrency;
        bftSignedInt64:      Result := bftCurrency;
        bftUnsignedInt8:     Result := bftCurrency;
        bftUnsignedInt16:    Result := bftCurrency;
        bftUnsignedInt32:    Result := bftCurrency;

        bftSingle:           Result := bftSingle;
        bftDouble:           Result := bftDouble;
        bftExtended:         Result := bftExtended;

        bftDate:             Result := bftUnknown;
        bftTime:             Result := bftUnknown;
        bftDateTime:         Result := bftUnknown;

        bftLogical:          Result := bftUnknown;
        bftCurrency:         Result := bftCurrency;
      end;

    bftClob:
      case b of
        bftClob:             Result := bftChar;
        bftWideClob:         Result := bftWideChar;
        bftChar:             Result := bftChar;
        bftWideChar:         Result := bftWideChar;
        bftVarchar:          Result := bftVarchar;
        bftWideVarchar:      Result := bftWideVarchar;
      end;

    bftWideClob:
      case b of
        bftWideClob:         Result := bftWideChar;
        bftClob:             Result := bftWideChar;
        bftChar:             Result := bftWideChar;
        bftWideChar:         Result := bftWideChar;
        bftVarchar:          Result := bftWideVarchar;
        bftWideVarchar:      Result := bftWideVarchar;
      end;

  end;
end;//GetCommonDataType


//------------------------------------------------------------------------------
// Return Common DataType for 2 types, or ftUnknown
//------------------------------------------------------------------------------
function GetCommonDataType(a,b: TABSAdvancedFieldType; ForCompare: Boolean=False): TABSAdvancedFieldType;
var
   b1,b2, CommonBft: TABSBaseFieldType;
begin
  b1 := AdvancedFieldTypeToBaseFieldType(a);
  b2 := AdvancedFieldTypeToBaseFieldType(b);
  CommonBft := GetCommonDataType(b1, b2, ForCompare);

  if (CommonBft = b1) then
    Result := a
  else if (CommonBft = b2) then
    Result := b
  else
    Result := BaseFieldTypeToAdvancedFieldType(CommonBft);

end;//GetCommonDataType

//------------------------------------------------------------------------------
// Allocate new buffer and convert data to it
//------------------------------------------------------------------------------
function CastToNewBuffer(
                          const Buffer;
                          const DataSize: Integer;
                          const DataType: TABSBaseFieldType;
                          const NewDataType: TABSBaseFieldType
                        ): PAnsiChar;
var
   Size: Integer;
begin
  Result := CastToNewBuffer(Buffer, DataSize, DataType, NewDataType, Size);
end;//CastToNewBuffer


//------------------------------------------------------------------------------
// Allocate new buffer and convert data to it
//------------------------------------------------------------------------------
function CastToNewBuffer(
                          const Buffer;
                          const DataSize: Integer;
                          const DataType: TABSBaseFieldType;
                          const NewDataType: TABSBaseFieldType;
                          out NewDataSize: Integer
                        ): PAnsiChar;
var

  s: AnsiString;
  ws: WideString;
  si8:  Shortint;
  si16: Smallint;
  si32: Integer;
  si64: Int64;
  ui8:  Byte;
  ui16: Word;
  ui32: Cardinal;
  sng:  Single;
  dbl:  Double;
  ext:  Extended;
  dt:   TABSDateTime;
  d:    TABSDate;
  t:    TABSTime;
  b:    TABSLogical;
  cur:  TABSCurrency;

  datetime: TDateTime;
  oldSeparator: AnsiChar;

begin
  Result := nil;
  try
    case DataType of
      bftChar,
      bftVarchar:  //  from String
        case NewDataType of
          bftChar,
          bftVarchar:
            begin
              AllocMemAndSetData(bftVarchar, Buffer, Result, NewDataSize);
            end;
          bftWideChar,
          bftWideVarchar:
            begin
              ws := WideString(PAnsiChar(Buffer));
              AllocMemAndSetData(bftWideVarchar, ws, Result, NewDataSize);
            end;
          bftSignedInt8:
            begin
              si8 := StrToInt(string(PAnsiChar(Buffer)));
              AllocMemAndSetData(bftSignedInt8, si8, Result, NewDataSize);
            end;
          bftSignedInt16:
            begin
              si16 := StrToInt(string(PAnsiChar(Buffer)));
              AllocMemAndSetData(bftSignedInt16, si16, Result, NewDataSize);
            end;
          bftSignedInt32:
            begin
              si32 := StrToInt(string(PAnsiChar(Buffer)));
              AllocMemAndSetData(bftSignedInt32, si32, Result, NewDataSize);
            end;
          bftSignedInt64:
            begin
              si64 := StrToInt64(string(PAnsiChar(Buffer)));
              AllocMemAndSetData(bftSignedInt64, si64, Result, NewDataSize);
            end;
          bftUnsignedInt8:
            begin
              ui8 := StrToInt(string(PAnsiChar(Buffer)));
              AllocMemAndSetData(bftUnsignedInt8, ui8, Result, NewDataSize);
            end;
          bftUnsignedInt16:
            begin
              ui16 := StrToInt(string(PAnsiChar(Buffer)));
              AllocMemAndSetData(bftUnsignedInt16, ui16, Result, NewDataSize);
            end;
          bftUnsignedInt32:
            begin
              ui32 := StrToInt(string(PAnsiChar(Buffer)));
              AllocMemAndSetData(bftUnsignedInt32, ui32, Result, NewDataSize);
            end;

          bftSingle:
            begin
              oldSeparator := AnsiChar({$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif});
              {$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif} := '.';
              try
                sng := StrToFloat(string(PAnsiChar(Buffer)));
              finally
                {$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif} := Char(oldSeparator);
              end;
              AllocMemAndSetData(bftSingle, sng, Result, NewDataSize);
            end;
          bftDouble:
            begin
              oldSeparator := AnsiChar({$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif});
              {$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif} := '.';
              try
                dbl := StrToFloat(PAnsiChar(Buffer));
              finally
                {$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif} := Char(oldSeparator);
              end;
              AllocMemAndSetData(bftDouble, dbl, Result, NewDataSize);
            end;
          bftExtended:
            begin
              oldSeparator := AnsiChar({$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif});
              {$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif} := '.';
              try
                ext := StrToFloat(PAnsiChar(Buffer));
              finally
                {$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif} := Char(oldSeparator);
              end;
              AllocMemAndSetData(bftExtended, ext, Result, NewDataSize);
            end;

          bftDate:
            begin
              if (not ISOTimeStampStrToDateTime(PAnsiChar(Buffer), datetime)) then
                if (not ISODateStrToDate(PAnsiChar(Buffer), datetime)) then
                  datetime := StrToDate(PAnsiChar(Buffer));
              d := DateToABSDate(datetime);
              AllocMemAndSetData(bftDate, d, Result, NewDataSize);
            end;
          bftTime:
            begin
              if (not ISOTimeStrToTime(PAnsiChar(Buffer), datetime)) then
                datetime := StrToTime(PAnsiChar(Buffer));
              t := TimeToABSTime(datetime);
              AllocMemAndSetData(bftTime, t, Result, NewDataSize);
            end;
          bftDateTime:
            begin
              if (not ISOTimeStampStrToDateTime(PAnsiChar(Buffer), datetime)) then
                if (not ISODateStrToDate(PAnsiChar(Buffer), datetime)) then
                  datetime := StrToDateTime(PAnsiChar(Buffer));
              dt := DateTimeToABSDateTime(datetime);
              AllocMemAndSetData(bftDateTime, dt, Result, NewDataSize);
            end;

          bftLogical:
            begin
              s := UpperCase(PAnsiChar(Buffer));
              b := (s = '1') or (s = 'TRUE');
              AllocMemAndSetData(bftLogical, b, Result, NewDataSize);
            end;
          bftCurrency:
            begin
              cur := StrToCurr(PAnsiChar(Buffer));
              AllocMemAndSetData(bftCurrency, cur, Result, NewDataSize);
            end;
          bftBlob:
            begin
              AllocMemAndSetData(bftVarchar, PAnsiChar(Buffer), Result, NewDataSize);
            end;
        end;

      bftWideChar,
      bftWideVarchar:  // from WideString
        case NewDataType of
          bftChar,
          bftVarchar:
            begin
              ws := WideString(PWideChar(Buffer));
              s := ws;
              AllocMemAndSetData(bftVarchar, s, Result, NewDataSize);
            end;
          bftWideChar,
          bftWideVarchar:
            begin
              ws := WideString(PWideChar(Buffer));
              AllocMemAndSetData(bftWideVarchar, ws, Result, NewDataSize);
            end;
          bftSignedInt8:
            begin
              si8 := StrToInt(PWideChar(Buffer));
              AllocMemAndSetData(bftSignedInt8, si8, Result, NewDataSize);
            end;
          bftSignedInt16:
            begin
              si16 := StrToInt(PWideChar(Buffer));
              AllocMemAndSetData(bftSignedInt16, si16, Result, NewDataSize);
            end;
          bftSignedInt32:
            begin
              si32 := StrToInt(PWideChar(Buffer));
              AllocMemAndSetData(bftSignedInt32, si32, Result, NewDataSize);
            end;
          bftSignedInt64:
            begin
              si64 := StrToInt64(PWideChar(Buffer));
              AllocMemAndSetData(bftSignedInt64, si64, Result, NewDataSize);
            end;
          bftUnsignedInt8:
            begin
              ui8 := StrToInt(PWideChar(Buffer));
              AllocMemAndSetData(bftUnsignedInt8, ui8, Result, NewDataSize);
            end;
          bftUnsignedInt16:
            begin
              ui16 := StrToInt(PWideChar(Buffer));
              AllocMemAndSetData(bftUnsignedInt16, ui16, Result, NewDataSize);
            end;
          bftUnsignedInt32:
            begin
              ui32 := StrToInt(PWideChar(Buffer));
              AllocMemAndSetData(bftUnsignedInt32, ui32, Result, NewDataSize);
            end;

          bftSingle:
            begin
              oldSeparator := AnsiChar({$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif});
              {$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif} := '.';
              try
                sng := StrToFloat(PWideChar(Buffer));
              finally
                {$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif} := Char(oldSeparator);
              end;
              AllocMemAndSetData(bftSingle, sng, Result, NewDataSize);
            end;
          bftDouble:
            begin
              oldSeparator := AnsiChar({$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif});
              {$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif} := '.';
              try
                dbl := StrToFloat(PWideChar(Buffer));
              finally
                {$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif} := Char(oldSeparator);
              end;
              AllocMemAndSetData(bftDouble, dbl, Result, NewDataSize);
            end;
          bftExtended:
            begin
              oldSeparator := AnsiChar({$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif});
              {$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif} := '.';
              try
                ext := StrToFloat(PWideChar(Buffer));
              finally
                {$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif} := Char(oldSeparator);
              end;
              AllocMemAndSetData(bftExtended, ext, Result, NewDataSize);
            end;

          bftDate:
            begin
              d := DateToABSDate(StrToDate(PWideChar(Buffer)));
              AllocMemAndSetData(bftDate, d, Result, NewDataSize);
            end;
          bftTime:
            begin
              t := TimeToABSTime(StrToTime(PWideChar(Buffer)));
              AllocMemAndSetData(bftTime, t, Result, NewDataSize);
            end;
          bftDateTime:
            begin
              dt := DateTimeToABSDateTime(StrToDateTime(PWideChar(Buffer)));
              AllocMemAndSetData(bftDateTime, dt, Result, NewDataSize);
            end;

          bftLogical:
            begin
              s := UpperCase(PWideChar(Buffer));
              b := (s = '1') or (s = 'TRUE');
              AllocMemAndSetData(bftLogical, b, Result, NewDataSize);
            end;
          bftCurrency:
            begin
              cur := StrToCurr(PWideChar(Buffer));
              AllocMemAndSetData(bftCurrency, cur, Result, NewDataSize);
            end;
          bftBlob:
            begin
              ws := WideString(PWideChar(Buffer));
              AllocMemAndSetData(bftWideVarchar, ws, Result, NewDataSize);
            end;
        end;


      bftSignedInt8:  // from Shortint
        case NewDataType of
          bftChar,
          bftVarchar:
            begin
              s := IntToStr(PShortint(Buffer)^);
              AllocMemAndSetData(bftVarchar, s, Result, NewDataSize);
            end;
          bftWideChar,
          bftWideVarchar:
            begin
              ws := IntToStr(PShortint(Buffer)^);
              AllocMemAndSetData(bftWideVarchar, ws, Result, NewDataSize);
            end;
          bftSignedInt8:
            begin
              si8 := PShortint(Buffer)^;
              AllocMemAndSetData(bftSignedInt8, si8, Result, NewDataSize);
            end;
          bftSignedInt16:
            begin
              si16 := PShortint(Buffer)^;
              AllocMemAndSetData(bftSignedInt16, si16, Result, NewDataSize);
            end;
          bftSignedInt32:
            begin
              si32 := PShortint(Buffer)^;
              AllocMemAndSetData(bftSignedInt32, si32, Result, NewDataSize);
            end;
          bftSignedInt64:
            begin
              si64 := PShortint(Buffer)^;
              AllocMemAndSetData(bftSignedInt64, si64, Result, NewDataSize);
            end;
          bftUnsignedInt8:
            begin
              ui8 := PShortint(Buffer)^;
              AllocMemAndSetData(bftUnsignedInt8, ui8, Result, NewDataSize);
            end;
          bftUnsignedInt16:
            begin
              ui16 := PShortint(Buffer)^;
              AllocMemAndSetData(bftUnsignedInt16, ui16, Result, NewDataSize);
            end;
          bftUnsignedInt32:
            begin
              ui32 := PShortint(Buffer)^;
              AllocMemAndSetData(bftUnsignedInt32, ui32, Result, NewDataSize);
            end;

          bftSingle:
            begin
              sng := PShortint(Buffer)^;
              AllocMemAndSetData(bftSingle, sng, Result, NewDataSize);
            end;
          bftDouble:
            begin
              dbl := PShortint(Buffer)^;
              AllocMemAndSetData(bftDouble, dbl, Result, NewDataSize);
            end;
          bftExtended:
            begin
              ext := PShortint(Buffer)^;
              AllocMemAndSetData(bftExtended, ext, Result, NewDataSize);
            end;

          bftDate:
            begin
              d := PShortint(Buffer)^;
              AllocMemAndSetData(bftDate, d, Result, NewDataSize);
            end;
          bftTime:
            begin
              t := PShortint(Buffer)^;
              AllocMemAndSetData(bftTime, t, Result, NewDataSize);
            end;
          bftDateTime:
            begin
              dt.Time := TIME_IS_NULL;
              dt.Date := PShortint(Buffer)^;
              AllocMemAndSetData(bftDateTime, dt, Result, NewDataSize);
            end;
          bftLogical:
            begin
              b := not (PShortint(Buffer)^ = 0);
              AllocMemAndSetData(bftLogical, b, Result, NewDataSize);
            end;
          bftCurrency:
            begin
              cur := PShortint(Buffer)^;
              AllocMemAndSetData(bftCurrency, cur, Result, NewDataSize);
            end;
        end;                        

      bftSignedInt16:  // fro Smallint
        case NewDataType of
          bftChar,
          bftVarchar:
            begin
              s := IntToStr(PSmallint(Buffer)^);
              AllocMemAndSetData(bftVarchar, s, Result, NewDataSize);
            end;
          bftWideChar,
          bftWideVarchar:
            begin
              ws := IntToStr(PSmallint(Buffer)^);
              AllocMemAndSetData(bftWideVarchar, ws, Result, NewDataSize);
            end;
          bftSignedInt8:
            begin
              si8 := PSmallint(Buffer)^;
              AllocMemAndSetData(bftSignedInt8, si8, Result, NewDataSize);
            end;
          bftSignedInt16:
            begin
              si16 := PSmallint(Buffer)^;
              AllocMemAndSetData(bftSignedInt16, si16, Result, NewDataSize);
            end;
          bftSignedInt32:
            begin
              si32 := PSmallint(Buffer)^;
              AllocMemAndSetData(bftSignedInt32, si32, Result, NewDataSize);
            end;
          bftSignedInt64:
            begin
              si64 := PSmallint(Buffer)^;
              AllocMemAndSetData(bftSignedInt64, si64, Result, NewDataSize);
            end;
          bftUnsignedInt8:
            begin
              ui8 := PSmallint(Buffer)^;
              AllocMemAndSetData(bftUnsignedInt8, ui8, Result, NewDataSize);
            end;
          bftUnsignedInt16:
            begin
              ui16 := PSmallint(Buffer)^;
              AllocMemAndSetData(bftUnsignedInt16, ui16, Result, NewDataSize);
            end;
          bftUnsignedInt32:
            begin
              ui32 := PSmallint(Buffer)^;
              AllocMemAndSetData(bftUnsignedInt32, ui32, Result, NewDataSize);
            end;

          bftSingle:
            begin
              sng := PSmallint(Buffer)^;
              AllocMemAndSetData(bftSingle, sng, Result, NewDataSize);
            end;
          bftDouble:
            begin
              dbl := PSmallint(Buffer)^;
              AllocMemAndSetData(bftDouble, dbl, Result, NewDataSize);
            end;
          bftExtended:
            begin
              ext := PSmallint(Buffer)^;
              AllocMemAndSetData(bftExtended, ext, Result, NewDataSize);
            end;

          bftDate:
            begin
              d := PSmallint(Buffer)^;
              AllocMemAndSetData(bftDate, d, Result, NewDataSize);
            end;
          bftTime:
            begin
              t := PSmallint(Buffer)^;
              AllocMemAndSetData(bftTime, t, Result, NewDataSize);
            end;
          bftDateTime:
            begin
              dt.Time := TIME_IS_NULL;
              dt.Date := PSmallint(Buffer)^;
              AllocMemAndSetData(bftDateTime, dt, Result, NewDataSize);
            end;
          bftLogical:
            begin
              b := not (PSmallint(Buffer)^ = 0);
              AllocMemAndSetData(bftLogical, b, Result, NewDataSize);
            end;
          bftCurrency:
            begin
              cur := PSmallint(Buffer)^;
              AllocMemAndSetData(bftCurrency, cur, Result, NewDataSize);
            end;
        end;


      bftSignedInt32:  // from Integer
        case NewDataType of
          bftChar,
          bftVarchar:
            begin
              s := IntToStr(PInteger(Buffer)^);
              AllocMemAndSetData(bftVarchar, s, Result, NewDataSize);
            end;
          bftWideChar,
          bftWideVarchar:
            begin
              ws := IntToStr(PInteger(Buffer)^);
              AllocMemAndSetData(bftWideVarchar, ws, Result, NewDataSize);
            end;
          bftSignedInt8:
            begin
              si8 := PInteger(Buffer)^;
              AllocMemAndSetData(bftSignedInt8, si8, Result, NewDataSize);
            end;
          bftSignedInt16:
            begin
              si16 := PInteger(Buffer)^;
              AllocMemAndSetData(bftSignedInt16, si16, Result, NewDataSize);
            end;
          bftSignedInt32:
            begin
              si32 := PInteger(Buffer)^;
              AllocMemAndSetData(bftSignedInt32, si32, Result, NewDataSize);
            end;
          bftSignedInt64:
            begin
              si64 := PInteger(Buffer)^;
              AllocMemAndSetData(bftSignedInt64, si64, Result, NewDataSize);
            end;
          bftUnsignedInt8:
            begin
              ui8 := PInteger(Buffer)^;
              AllocMemAndSetData(bftUnsignedInt8, ui8, Result, NewDataSize);
            end;
          bftUnsignedInt16:
            begin
              ui16 := PInteger(Buffer)^;
              AllocMemAndSetData(bftUnsignedInt16, ui16, Result, NewDataSize);
            end;
          bftUnsignedInt32:
            begin
              ui32 := PInteger(Buffer)^;
              AllocMemAndSetData(bftUnsignedInt32, ui32, Result, NewDataSize);
            end;

          bftSingle:
            begin
              sng := PInteger(Buffer)^;
              AllocMemAndSetData(bftSingle, sng, Result, NewDataSize);
            end;
          bftDouble:
            begin
              dbl := PInteger(Buffer)^;
              AllocMemAndSetData(bftDouble, dbl, Result, NewDataSize);
            end;
          bftExtended:
            begin
              ext := PInteger(Buffer)^;
              AllocMemAndSetData(bftExtended, ext, Result, NewDataSize);
            end;

          bftDate:
            begin
              d := PInteger(Buffer)^;
              AllocMemAndSetData(bftDate, d, Result, NewDataSize);
            end;
          bftTime:
            begin
              t := PInteger(Buffer)^;
              AllocMemAndSetData(bftTime, t, Result, NewDataSize);
            end;
          bftDateTime:
            begin
              dt.Time := TIME_IS_NULL;
              dt.Date := PInteger(Buffer)^;
              AllocMemAndSetData(bftDateTime, dt, Result, NewDataSize);
            end;
          bftLogical:
            begin
              b := not (PInteger(Buffer)^ = 0);
              AllocMemAndSetData(bftLogical, b, Result, NewDataSize);
            end;
          bftCurrency:
            begin
              cur := PInteger(Buffer)^;
              AllocMemAndSetData(bftCurrency, cur, Result, NewDataSize);
            end;
        end;

      bftSignedInt64:  // from int64
        case NewDataType of
          bftChar,
          bftVarchar:
            begin
              s := IntToStr(PInt64(Buffer)^);
              AllocMemAndSetData(bftVarchar, s, Result, NewDataSize);
            end;
          bftWideChar,
          bftWideVarchar:
            begin
              ws := IntToStr(PInt64(Buffer)^);
              AllocMemAndSetData(bftWideVarchar, ws, Result, NewDataSize);
            end;
          bftSignedInt8:
            begin
              si8 := PInt64(Buffer)^;
              AllocMemAndSetData(bftSignedInt8, si8, Result, NewDataSize);
            end;
          bftSignedInt16:
            begin
              si16 := PInt64(Buffer)^;
              AllocMemAndSetData(bftSignedInt16, si16, Result, NewDataSize);
            end;
          bftSignedInt32:
            begin
              si32 := PInt64(Buffer)^;
              AllocMemAndSetData(bftSignedInt32, si32, Result, NewDataSize);
            end;
          bftSignedInt64:
            begin
              si64 := PInt64(Buffer)^;
              AllocMemAndSetData(bftSignedInt64, si64, Result, NewDataSize);
            end;
          bftUnsignedInt8:
            begin
              ui8 := Byte(PInt64(Buffer)^);
              AllocMemAndSetData(bftUnsignedInt8, ui8, Result, NewDataSize);
            end;
          bftUnsignedInt16:
            begin
              ui16 := PInt64(Buffer)^;
              AllocMemAndSetData(bftUnsignedInt16, ui16, Result, NewDataSize);
            end;
          bftUnsignedInt32:
            begin
              ui32 := PInt64(Buffer)^;
              AllocMemAndSetData(bftUnsignedInt32, ui32, Result, NewDataSize);
            end;

          bftSingle:
            begin
              sng := PInt64(Buffer)^;
              AllocMemAndSetData(bftSingle, sng, Result, NewDataSize);
            end;
          bftDouble:
            begin
              dbl := PInt64(Buffer)^;
              AllocMemAndSetData(bftDouble, dbl, Result, NewDataSize);
            end;
          bftExtended:
            begin
              ext := PInt64(Buffer)^;
              AllocMemAndSetData(bftExtended, ext, Result, NewDataSize);
            end;

          bftDate:
            begin
              d := PInt64(Buffer)^;
              AllocMemAndSetData(bftDate, d, Result, NewDataSize);
            end;
          bftTime:
            begin
              t := PInt64(Buffer)^;
              AllocMemAndSetData(bftTime, t, Result, NewDataSize);
            end;
          bftDateTime:
            begin
              dt.Time := TIME_IS_NULL;
              dt.Date := PInt64(Buffer)^;
              AllocMemAndSetData(bftDateTime, dt, Result, NewDataSize);
            end;
          bftLogical:
            begin
              b := not (PInt64(Buffer)^ = 0);
              AllocMemAndSetData(bftLogical, b, Result, NewDataSize);
            end;
          bftCurrency:
            begin
              cur := PInt64(Buffer)^;
              AllocMemAndSetData(bftCurrency, cur, Result, NewDataSize);
            end;
        end;


      bftUnsignedInt8:  // from Byte
        case NewDataType of
          bftChar,
          bftVarchar:
            begin
              s := IntToStr(PByte(Buffer)^);
              AllocMemAndSetData(bftVarchar, s, Result, NewDataSize);
            end;
          bftWideChar,
          bftWideVarchar:
            begin
              ws := IntToStr(PByte(Buffer)^);
              AllocMemAndSetData(bftWideVarchar, ws, Result, NewDataSize);
            end;
          bftSignedInt8:
            begin
              si8 := PByte(Buffer)^;
              AllocMemAndSetData(bftSignedInt8, si8, Result, NewDataSize);
            end;
          bftSignedInt16:
            begin
              si16 := PByte(Buffer)^;
              AllocMemAndSetData(bftSignedInt16, si16, Result, NewDataSize);
            end;
          bftSignedInt32:
            begin
              si32 := PByte(Buffer)^;
              AllocMemAndSetData(bftSignedInt32, si32, Result, NewDataSize);
            end;
          bftSignedInt64:
            begin
              si64 := PByte(Buffer)^;
              AllocMemAndSetData(bftSignedInt64, si64, Result, NewDataSize);
            end;
          bftUnsignedInt8:
            begin
              ui8 := PByte(Buffer)^;
              AllocMemAndSetData(bftUnsignedInt8, ui8, Result, NewDataSize);
            end;
          bftUnsignedInt16:
            begin
              ui16 := PByte(Buffer)^;
              AllocMemAndSetData(bftUnsignedInt16, ui16, Result, NewDataSize);
            end;
          bftUnsignedInt32:
            begin
              ui32 := PByte(Buffer)^;
              AllocMemAndSetData(bftUnsignedInt32, ui32, Result, NewDataSize);
            end;

          bftSingle:
            begin
              sng := PByte(Buffer)^;
              AllocMemAndSetData(bftSingle, sng, Result, NewDataSize);
            end;
          bftDouble:
            begin
              dbl := PByte(Buffer)^;
              AllocMemAndSetData(bftDouble, dbl, Result, NewDataSize);
            end;
          bftExtended:
            begin
              ext := PByte(Buffer)^;
              AllocMemAndSetData(bftExtended, ext, Result, NewDataSize);
            end;

          bftDate:
            begin
              d := PByte(Buffer)^;
              AllocMemAndSetData(bftDate, d, Result, NewDataSize);
            end;
          bftTime:
            begin
              t := PByte(Buffer)^;
              AllocMemAndSetData(bftTime, t, Result, NewDataSize);
            end;
          bftDateTime:
            begin
              dt.Time := TIME_IS_NULL;
              dt.Date := PByte(Buffer)^;
              AllocMemAndSetData(bftDateTime, dt, Result, NewDataSize);
            end;
          bftLogical:
            begin
              b := not (PByte(Buffer)^ = 0);
              AllocMemAndSetData(bftLogical, b, Result, NewDataSize);
            end;
          bftCurrency:
            begin
              cur := PByte(Buffer)^;
              AllocMemAndSetData(bftCurrency, cur, Result, NewDataSize);
            end;
        end;

      bftUnsignedInt16:  // from Word
        case NewDataType of
          bftChar,
          bftVarchar:
            begin
              s := IntToStr(PWord(Buffer)^);
              AllocMemAndSetData(bftVarchar, s, Result, NewDataSize);
            end;
          bftWideChar,
          bftWideVarchar:
            begin
              ws := IntToStr(PWord(Buffer)^);
              AllocMemAndSetData(bftWideVarchar, ws, Result, NewDataSize);
            end;
          bftSignedInt8:
            begin
              si8 := PWord(Buffer)^;
              AllocMemAndSetData(bftSignedInt8, si8, Result, NewDataSize);
            end;
          bftSignedInt16:
            begin
              si16 := PWord(Buffer)^;
              AllocMemAndSetData(bftSignedInt16, si16, Result, NewDataSize);
            end;
          bftSignedInt32:
            begin
              si32 := PWord(Buffer)^;
              AllocMemAndSetData(bftSignedInt32, si32, Result, NewDataSize);
            end;
          bftSignedInt64:
            begin
              si64 := PWord(Buffer)^;
              AllocMemAndSetData(bftSignedInt64, si64, Result, NewDataSize);
            end;
          bftUnsignedInt8:
            begin
              ui8 := PWord(Buffer)^;
              AllocMemAndSetData(bftUnsignedInt8, ui8, Result, NewDataSize);
            end;
          bftUnsignedInt16:
            begin
              ui16 := PWord(Buffer)^;
              AllocMemAndSetData(bftUnsignedInt16, ui16, Result, NewDataSize);
            end;
          bftUnsignedInt32:
            begin
              ui32 := PWord(Buffer)^;
              AllocMemAndSetData(bftUnsignedInt32, ui32, Result, NewDataSize);
            end;

          bftSingle:
            begin
              sng := PWord(Buffer)^;
              AllocMemAndSetData(bftSingle, sng, Result, NewDataSize);
            end;
          bftDouble:
            begin
              dbl := PWord(Buffer)^;
              AllocMemAndSetData(bftDouble, dbl, Result, NewDataSize);
            end;
          bftExtended:
            begin
              ext := PWord(Buffer)^;
              AllocMemAndSetData(bftExtended, ext, Result, NewDataSize);
            end;

          bftDate:
            begin
              d := PWord(Buffer)^;
              AllocMemAndSetData(bftDate, d, Result, NewDataSize);
            end;
          bftTime:
            begin
              t := PWord(Buffer)^;
              AllocMemAndSetData(bftTime, t, Result, NewDataSize);
            end;
          bftDateTime:
            begin
              dt.Time := TIME_IS_NULL;
              dt.Date := PWord(Buffer)^;
              AllocMemAndSetData(bftDateTime, dt, Result, NewDataSize);
            end;
          bftLogical:
            begin
              b := not (PWord(Buffer)^ = 0);
              AllocMemAndSetData(bftLogical, b, Result, NewDataSize);
            end;
          bftCurrency:
            begin
              cur := PWord(Buffer)^;
              AllocMemAndSetData(bftCurrency, cur, Result, NewDataSize);
            end;
        end;

      bftUnsignedInt32:  // from Cardinal
        case NewDataType of
          bftChar,
          bftVarchar:
            begin
              s := IntToStr(PCardinal(Buffer)^);
              AllocMemAndSetData(bftVarchar, s, Result, NewDataSize);
            end;
          bftWideChar,
          bftWideVarchar:
            begin
              ws := IntToStr(PCardinal(Buffer)^);
              AllocMemAndSetData(bftWideVarchar, ws, Result, NewDataSize);
            end;
          bftSignedInt8:
            begin
              si8 := PCardinal(Buffer)^;
              AllocMemAndSetData(bftSignedInt8, si8, Result, NewDataSize);
            end;
          bftSignedInt16:
            begin
              si16 := PCardinal(Buffer)^;
              AllocMemAndSetData(bftSignedInt16, si16, Result, NewDataSize);
            end;
          bftSignedInt32:
            begin
              si32 := PCardinal(Buffer)^;
              AllocMemAndSetData(bftSignedInt32, si32, Result, NewDataSize);
            end;
          bftSignedInt64:
            begin
              si64 := PCardinal(Buffer)^;
              AllocMemAndSetData(bftSignedInt64, si64, Result, NewDataSize);
            end;
          bftUnsignedInt8:
            begin
              ui8 := PCardinal(Buffer)^;
              AllocMemAndSetData(bftUnsignedInt8, ui8, Result, NewDataSize);
            end;
          bftUnsignedInt16:
            begin
              ui16 := PCardinal(Buffer)^;
              AllocMemAndSetData(bftUnsignedInt16, ui16, Result, NewDataSize);
            end;
          bftUnsignedInt32:
            begin
              ui32 := PCardinal(Buffer)^;
              AllocMemAndSetData(bftUnsignedInt32, ui32, Result, NewDataSize);
            end;

          bftSingle:
            begin
              sng := PCardinal(Buffer)^;
              AllocMemAndSetData(bftSingle, sng, Result, NewDataSize);
            end;
          bftDouble:
            begin
              dbl := PCardinal(Buffer)^;
              AllocMemAndSetData(bftDouble, dbl, Result, NewDataSize);
            end;
          bftExtended:
            begin
              ext := PCardinal(Buffer)^;
              AllocMemAndSetData(bftExtended, ext, Result, NewDataSize);
            end;

          bftDate:
            begin
              d := PCardinal(Buffer)^;
              AllocMemAndSetData(bftDate, d, Result, NewDataSize);
            end;
          bftTime:
            begin
              t := PCardinal(Buffer)^;
              AllocMemAndSetData(bftTime, t, Result, NewDataSize);
            end;
          bftDateTime:
            begin
              dt.Time := TIME_IS_NULL;
              dt.Date := PCardinal(Buffer)^;
              AllocMemAndSetData(bftDateTime, dt, Result, NewDataSize);
            end;
          bftLogical:
            begin
              b := not (PCardinal(Buffer)^ = 0);
              AllocMemAndSetData(bftLogical, b, Result, NewDataSize);
            end;
          bftCurrency:
            begin
              cur := PCardinal(Buffer)^;
              AllocMemAndSetData(bftCurrency, cur, Result, NewDataSize);
            end;
        end;

      bftSingle:  // from Single
        case NewDataType of
          bftChar,
          bftVarchar:
            begin
              s := FloatToStr(PSingle(Buffer)^);
              AllocMemAndSetData(bftVarchar, s, Result, NewDataSize);
            end;
          bftWideChar,
          bftWideVarchar:
            begin
              ws := FloatToStr(PSingle(Buffer)^);
              AllocMemAndSetData(bftWideVarchar, ws, Result, NewDataSize);
            end;
          bftSignedInt8:
            begin
              si8 := Trunc(PSingle(Buffer)^);
              AllocMemAndSetData(bftSignedInt8, si8, Result, NewDataSize);
            end;
          bftSignedInt16:
            begin
              si16 := Trunc(PSingle(Buffer)^);
              AllocMemAndSetData(bftSignedInt16, si16, Result, NewDataSize);
            end;
          bftSignedInt32:
            begin
              si32 := Trunc(PSingle(Buffer)^);
              AllocMemAndSetData(bftSignedInt32, si32, Result, NewDataSize);
            end;
          bftSignedInt64:
            begin
              si64 := Trunc(PSingle(Buffer)^);
              AllocMemAndSetData(bftSignedInt64, si64, Result, NewDataSize);
            end;
          bftUnsignedInt8:
            begin
              ui8 := Trunc(PSingle(Buffer)^);
              AllocMemAndSetData(bftUnsignedInt8, ui8, Result, NewDataSize);
            end;
          bftUnsignedInt16:
            begin
              ui16 := Trunc(PSingle(Buffer)^);
              AllocMemAndSetData(bftUnsignedInt16, ui16, Result, NewDataSize);
            end;
          bftUnsignedInt32:
            begin
              ui32 := Trunc(PSingle(Buffer)^);
              AllocMemAndSetData(bftUnsignedInt32, ui32, Result, NewDataSize);
            end;

          bftSingle:
            begin
              sng := PSingle(Buffer)^;
              AllocMemAndSetData(bftSingle, sng, Result, NewDataSize);
            end;
          bftDouble:
            begin
              dbl := PSingle(Buffer)^;
              AllocMemAndSetData(bftDouble, dbl, Result, NewDataSize);
            end;
          bftExtended:
            begin
              ext := PSingle(Buffer)^;
              AllocMemAndSetData(bftExtended, ext, Result, NewDataSize);
            end;

          bftDate:
            begin
              d := Trunc(PSingle(Buffer)^);
              AllocMemAndSetData(bftDate, d, Result, NewDataSize);
            end;
          bftTime:
            begin
              t := Trunc(PSingle(Buffer)^) mod MILSECS_IN_DAY;
              AllocMemAndSetData(bftTime, t, Result, NewDataSize);
            end;
          bftDateTime:
            begin
              dt.Time := Trunc(Frac(PSingle(Buffer)^)*MILSECS_IN_DAY);
              dt.Date := Trunc(PSingle(Buffer)^);
              AllocMemAndSetData(bftDateTime, dt, Result, NewDataSize);
            end;
          bftLogical:
            begin
              b := not (PSingle(Buffer)^ = 0);
              AllocMemAndSetData(bftLogical, b, Result, NewDataSize);
            end;
          bftCurrency:
            begin
              cur := PSingle(Buffer)^;
              AllocMemAndSetData(bftCurrency, cur, Result, NewDataSize);
            end;
        end;

      bftDouble:  // From Double
        case NewDataType of
          bftChar,
          bftVarchar:
            begin
              s := FloatToStr(PDouble(Buffer)^);
              AllocMemAndSetData(bftVarchar, s, Result, NewDataSize);
            end;
          bftWideChar,
          bftWideVarchar:
            begin
              ws := FloatToStr(PDouble(Buffer)^);
              AllocMemAndSetData(bftWideVarchar, ws, Result, NewDataSize);
            end;
          bftSignedInt8:
            begin
              si8 := Trunc(PDouble(Buffer)^);
              AllocMemAndSetData(bftSignedInt8, si8, Result, NewDataSize);
            end;
          bftSignedInt16:
            begin
              si16 := Trunc(PDouble(Buffer)^);
              AllocMemAndSetData(bftSignedInt16, si16, Result, NewDataSize);
            end;
          bftSignedInt32:
            begin
              si32 := Trunc(PDouble(Buffer)^);
              AllocMemAndSetData(bftSignedInt32, si32, Result, NewDataSize);
            end;
          bftSignedInt64:
            begin
              si64 := Trunc(PDouble(Buffer)^);
              AllocMemAndSetData(bftSignedInt64, si64, Result, NewDataSize);
            end;
          bftUnsignedInt8:
            begin
              ui8 := Trunc(PDouble(Buffer)^);
              AllocMemAndSetData(bftUnsignedInt8, ui8, Result, NewDataSize);
            end;
          bftUnsignedInt16:
            begin
              ui16 := Trunc(PDouble(Buffer)^);
              AllocMemAndSetData(bftUnsignedInt16, ui16, Result, NewDataSize);
            end;
          bftUnsignedInt32:
            begin
              ui32 := Trunc(PDouble(Buffer)^);
              AllocMemAndSetData(bftUnsignedInt32, ui32, Result, NewDataSize);
            end;

          bftSingle:
            begin
              sng := PDouble(Buffer)^;
              AllocMemAndSetData(bftSingle, sng, Result, NewDataSize);
            end;
          bftDouble:
            begin
              dbl := PDouble(Buffer)^;
              AllocMemAndSetData(bftDouble, dbl, Result, NewDataSize);
            end;
          bftExtended:
            begin
              ext := PDouble(Buffer)^;
              AllocMemAndSetData(bftExtended, ext, Result, NewDataSize);
            end;

          bftDate:
            begin
              d := Trunc(PDouble(Buffer)^);
              AllocMemAndSetData(bftDate, d, Result, NewDataSize);
            end;
          bftTime:
            begin
              t := Trunc(PDouble(Buffer)^) mod MILSECS_IN_DAY;
              AllocMemAndSetData(bftTime, t, Result, NewDataSize);
            end;
          bftDateTime:
            begin
              dt.Time := Trunc(Frac(PDouble(Buffer)^)*MILSECS_IN_DAY);
              dt.Date := Trunc(PDouble(Buffer)^);
              AllocMemAndSetData(bftDateTime, dt, Result, NewDataSize);
            end;
          bftLogical:
            begin
              b := not (PDouble(Buffer)^ = 0);
              AllocMemAndSetData(bftLogical, b, Result, NewDataSize);
            end;
          bftCurrency:
            begin
              cur := PDouble(Buffer)^;
              AllocMemAndSetData(bftCurrency, cur, Result, NewDataSize);
            end;
        end;

      bftExtended: // From Extended
        case NewDataType of
          bftChar,
          bftVarchar:
            begin
              s := FloatToStr(PExtended(Buffer)^);
              AllocMemAndSetData(bftVarchar, s, Result, NewDataSize);
            end;
          bftWideChar,
          bftWideVarchar:
            begin
              ws := FloatToStr(PExtended(Buffer)^);
              AllocMemAndSetData(bftWideVarchar, ws, Result, NewDataSize);
            end;
          bftSignedInt8:
            begin
              si8 := Trunc(PExtended(Buffer)^);
              AllocMemAndSetData(bftSignedInt8, si8, Result, NewDataSize);
            end;
          bftSignedInt16:
            begin
              si16 := Trunc(PExtended(Buffer)^);
              AllocMemAndSetData(bftSignedInt16, si16, Result, NewDataSize);
            end;
          bftSignedInt32:
            begin
              si32 := Trunc(PExtended(Buffer)^);
              AllocMemAndSetData(bftSignedInt32, si32, Result, NewDataSize);
            end;
          bftSignedInt64:
            begin
              si64 := Trunc(PExtended(Buffer)^);
              AllocMemAndSetData(bftSignedInt64, si64, Result, NewDataSize);
            end;
          bftUnsignedInt8:
            begin
              ui8 := Trunc(PExtended(Buffer)^);
              AllocMemAndSetData(bftUnsignedInt8, ui8, Result, NewDataSize);
            end;
          bftUnsignedInt16:
            begin
              ui16 := Trunc(PExtended(Buffer)^);
              AllocMemAndSetData(bftUnsignedInt16, ui16, Result, NewDataSize);
            end;
          bftUnsignedInt32:
            begin
              ui32 := Trunc(PExtended(Buffer)^);
              AllocMemAndSetData(bftUnsignedInt32, ui32, Result, NewDataSize);
            end;

          bftSingle:
            begin
              sng := PExtended(Buffer)^;
              AllocMemAndSetData(bftSingle, sng, Result, NewDataSize);
            end;
          bftDouble:
            begin
              dbl := PExtended(Buffer)^;
              AllocMemAndSetData(bftDouble, dbl, Result, NewDataSize);
            end;
          bftExtended:
            begin
              ext := PExtended(Buffer)^;
              AllocMemAndSetData(bftExtended, ext, Result, NewDataSize);
            end;

          bftDate:
            begin
              d := Trunc(PExtended(Buffer)^);
              AllocMemAndSetData(bftDate, d, Result, NewDataSize);
            end;
          bftTime:
            begin
              t := Trunc(PExtended(Buffer)^) mod MILSECS_IN_DAY;
              AllocMemAndSetData(bftTime, t, Result, NewDataSize);
            end;
          bftDateTime:
            begin
              dt.Time := Trunc(Frac(PExtended(Buffer)^)*MILSECS_IN_DAY);
              dt.Date := Trunc(PExtended(Buffer)^);
              AllocMemAndSetData(bftDateTime, dt, Result, NewDataSize);
            end;
          bftLogical:
            begin
              b := not (PExtended(Buffer)^ = 0);
              AllocMemAndSetData(bftLogical, b, Result, NewDataSize);
            end;
          bftCurrency:
            begin
              cur := PExtended(Buffer)^;
              AllocMemAndSetData(bftCurrency, cur, Result, NewDataSize);
            end;
        end;


      bftDate:  // from Date
        case NewDataType of
          bftChar,
          bftVarchar:
            begin
              d := PABSDate(Buffer)^;
              if (d = DATE_IS_NULL) then
                s := ''
              else
                s := DateToStr(ABSDateToDate(d));
              AllocMemAndSetData(bftVarchar, s, Result, NewDataSize);
            end;
          bftWideChar,
          bftWideVarchar:
            begin
              d := PABSDate(Buffer)^;
              if (d = DATE_IS_NULL) then
                ws := ''
              else
                ws := DateToStr(ABSDateToDate(d));
              AllocMemAndSetData(bftWideVarchar, ws, Result, NewDataSize);
            end;
          bftSignedInt8:
            begin
              si8 := PABSDate(Buffer)^;
              AllocMemAndSetData(bftSignedInt8, si8, Result, NewDataSize);
            end;
          bftSignedInt16:
            begin
              si16 := PABSDate(Buffer)^;
              AllocMemAndSetData(bftSignedInt16, si16, Result, NewDataSize);
            end;
          bftSignedInt32:
            begin
              si32 := PABSDate(Buffer)^;
              AllocMemAndSetData(bftSignedInt32, si32, Result, NewDataSize);
            end;
          bftSignedInt64:
            begin
              si64 := PABSDate(Buffer)^;
              AllocMemAndSetData(bftSignedInt64, si64, Result, NewDataSize);
            end;
          bftUnsignedInt8:
            begin
              ui8 := PABSDate(Buffer)^;
              AllocMemAndSetData(bftUnsignedInt8, ui8, Result, NewDataSize);
            end;
          bftUnsignedInt16:
            begin
              ui16 := PABSDate(Buffer)^;
              AllocMemAndSetData(bftUnsignedInt16, ui16, Result, NewDataSize);
            end;
          bftUnsignedInt32:
            begin
              ui32 := PABSDate(Buffer)^;
              AllocMemAndSetData(bftUnsignedInt32, ui32, Result, NewDataSize);
            end;

          bftSingle:
            begin
              sng := PABSDate(Buffer)^;
              AllocMemAndSetData(bftSingle, sng, Result, NewDataSize);
            end;
          bftDouble:
            begin
              dbl := PABSDate(Buffer)^;
              AllocMemAndSetData(bftDouble, dbl, Result, NewDataSize);
            end;
          bftExtended:
            begin
              ext := PABSDate(Buffer)^;
              AllocMemAndSetData(bftExtended, ext, Result, NewDataSize);
            end;

          bftDate:
            begin
              d := PABSDate(Buffer)^;
              AllocMemAndSetData(bftDate, d, Result, NewDataSize);
            end;
          bftTime:
            begin
              t := PABSDate(Buffer)^ mod MILSECS_IN_DAY;
              AllocMemAndSetData(bftTime, t, Result, NewDataSize);
            end;
          bftDateTime:
            begin
              dt.Time := TIME_IS_NULL;
              dt.Date := PABSDate(Buffer)^;
              AllocMemAndSetData(bftDateTime, dt, Result, NewDataSize);
            end;
          bftLogical:
            begin
              b := not (PABSDate(Buffer)^ = DATE_IS_NULL);
              AllocMemAndSetData(bftLogical, b, Result, NewDataSize);
            end;
          bftCurrency:
            begin
              cur := PABSDate(Buffer)^;
              AllocMemAndSetData(bftCurrency, cur, Result, NewDataSize);
            end;
        end;


      bftTime:  // from Time
        case NewDataType of
          bftChar,
          bftVarchar:
            begin
              t := PABSTime(Buffer)^;
              if (t = TIME_IS_NULL) then
                s := ''
              else
                s := TimeToStr(ABSTimeToTime(t));
              AllocMemAndSetData(bftVarchar, s, Result, NewDataSize);
            end;
          bftWideChar,
          bftWideVarchar:
            begin
              t := PABSTime(Buffer)^;
              if (t = TIME_IS_NULL) then
                ws := ''
              else
                ws := TimeToStr(ABSTimeToTime(T));
              AllocMemAndSetData(bftWideVarchar, ws, Result, NewDataSize);
            end;
          bftSignedInt8:
            begin
              si8 := PABSTime(Buffer)^;
              AllocMemAndSetData(bftSignedInt8, si8, Result, NewDataSize);
            end;
          bftSignedInt16:
            begin
              si16 := PABSTime(Buffer)^;
              AllocMemAndSetData(bftSignedInt16, si16, Result, NewDataSize);
            end;
          bftSignedInt32:
            begin
              si32 := PABSTime(Buffer)^;
              AllocMemAndSetData(bftSignedInt32, si32, Result, NewDataSize);
            end;
          bftSignedInt64:
            begin
              si64 := PABSTime(Buffer)^;
              AllocMemAndSetData(bftSignedInt64, si64, Result, NewDataSize);
            end;
          bftUnsignedInt8:
            begin
              ui8 := PABSTime(Buffer)^;
              AllocMemAndSetData(bftUnsignedInt8, ui8, Result, NewDataSize);
            end;
          bftUnsignedInt16:
            begin
              ui16 := PABSTime(Buffer)^;
              AllocMemAndSetData(bftUnsignedInt16, ui16, Result, NewDataSize);
            end;
          bftUnsignedInt32:
            begin
              ui32 := PABSTime(Buffer)^;
              AllocMemAndSetData(bftUnsignedInt32, ui32, Result, NewDataSize);
            end;

          bftSingle:
            begin
              sng := PABSTime(Buffer)^;
              AllocMemAndSetData(bftSingle, sng, Result, NewDataSize);
            end;
          bftDouble:
            begin
              dbl := PABSTime(Buffer)^;
              AllocMemAndSetData(bftDouble, dbl, Result, NewDataSize);
            end;
          bftExtended:
            begin
              ext := PABSTime(Buffer)^;
              AllocMemAndSetData(bftExtended, ext, Result, NewDataSize);
            end;

          bftDate:
            begin
              d := PABSTime(Buffer)^;
              AllocMemAndSetData(bftDate, d, Result, NewDataSize);
            end;
          bftTime:
            begin
              t := PABSTime(Buffer)^;
              AllocMemAndSetData(bftTime, t, Result, NewDataSize);
            end;
          bftDateTime:
            begin
              dt.Time := PABSTime(Buffer)^;
              dt.Date := DATE_IS_NULL;
              AllocMemAndSetData(bftDateTime, dt, Result, NewDataSize);
            end;
          bftLogical:
            begin
              b := not (PABSTime(Buffer)^ = TIME_IS_NULL);
              AllocMemAndSetData(bftLogical, b, Result, NewDataSize);
            end;
          bftCurrency:
            begin
              cur := PABSTime(Buffer)^;
              AllocMemAndSetData(bftCurrency, cur, Result, NewDataSize);
            end;
        end;


      bftDateTime:  // from DateTime
        case NewDataType of
          bftChar,
          bftVarchar:
            begin
              dt := PABSDateTime(Buffer)^;
              if (dt.Date = DATE_IS_NULL) and (dt.Time = TIME_IS_NULL) then
                s := ''
              else
                s := DateTimeToStr(ABSDateTimeToDateTime(dt));
              AllocMemAndSetData(bftVarchar, s, Result, NewDataSize);
            end;
          bftWideChar,
          bftWideVarchar:
            begin
              dt := PABSDateTime(Buffer)^;
              if (dt.Date = DATE_IS_NULL) and (dt.Time = TIME_IS_NULL) then
                ws := ''
              else
                ws := DateTimeToStr(ABSDateTimeToDateTime(dt));
              AllocMemAndSetData(bftVarchar, s, Result, NewDataSize);
            end;
          bftSignedInt8:
            begin
              si8 := PABSDateTime(Buffer)^.Date;
              AllocMemAndSetData(bftSignedInt8, si8, Result, NewDataSize);
            end;
          bftSignedInt16:
            begin
              si16 := PABSDateTime(Buffer)^.Date;
              AllocMemAndSetData(bftSignedInt16, si16, Result, NewDataSize);
            end;
          bftSignedInt32:
            begin
              si32 := PABSDateTime(Buffer)^.Date;
              AllocMemAndSetData(bftSignedInt32, si32, Result, NewDataSize);
            end;
          bftSignedInt64:
            begin
              si64 := PABSDateTime(Buffer)^.Date;
              AllocMemAndSetData(bftSignedInt64, si64, Result, NewDataSize);
            end;
          bftUnsignedInt8:
            begin
              ui8 := PABSDateTime(Buffer)^.Date;
              AllocMemAndSetData(bftUnsignedInt8, ui8, Result, NewDataSize);
            end;
          bftUnsignedInt16:
            begin
              ui16 := PABSDateTime(Buffer)^.Date;
              AllocMemAndSetData(bftUnsignedInt16, ui16, Result, NewDataSize);
            end;
          bftUnsignedInt32:
            begin
              ui32 := PABSDateTime(Buffer)^.Date;
              AllocMemAndSetData(bftUnsignedInt32, ui32, Result, NewDataSize);
            end;

          bftSingle:
            begin
              sng := 0;
              if (PABSDateTime(Buffer)^.Date <> DATE_IS_NULL) then
                sng := sng + PABSDateTime(Buffer)^.Date;
              if (PABSDateTime(Buffer)^.Time <> TIME_IS_NULL) then
                sng := sng + MILSECS_IN_DAY / PABSDateTime(Buffer)^.Time;
              AllocMemAndSetData(bftSingle, sng, Result, NewDataSize);
            end;
          bftDouble:
            begin
              dbl := 0;
              if (PABSDateTime(Buffer)^.Date <> DATE_IS_NULL) then
                dbl := dbl + PABSDateTime(Buffer)^.Date;
              if (PABSDateTime(Buffer)^.Time <> TIME_IS_NULL) then
                dbl := dbl + PABSDateTime(Buffer)^.Time / MILSECS_IN_DAY;
              AllocMemAndSetData(bftDouble, dbl, Result, NewDataSize);
            end;
          bftExtended:
            begin
              ext := 0;
              if (PABSDateTime(Buffer)^.Date <> DATE_IS_NULL) then
                ext := ext + PABSDateTime(Buffer)^.Date;
              if (PABSDateTime(Buffer)^.Time <> TIME_IS_NULL) then
                ext := ext + MILSECS_IN_DAY / PABSDateTime(Buffer)^.Time;
              AllocMemAndSetData(bftExtended, ext, Result, NewDataSize);
            end;

          bftDate:
            begin
              d := PABSDateTime(Buffer)^.Date;
              AllocMemAndSetData(bftDate, d, Result, NewDataSize);
            end;
          bftTime:
            begin
              t := PABSDateTime(Buffer)^.Time;
              AllocMemAndSetData(bftTime, t, Result, NewDataSize);
            end;
          bftDateTime:
            begin
              dt := PABSDateTime(Buffer)^;
              AllocMemAndSetData(bftDateTime, dt, Result, NewDataSize);
            end;
          bftLogical:
            begin
              b := not ((PABSDateTime(Buffer)^.Date = DATE_IS_NULL) and
                        (PABSDateTime(Buffer)^.Time = TIME_IS_NULL) );
              AllocMemAndSetData(bftLogical, b, Result, NewDataSize);
            end;
          bftCurrency:
            begin
              ext := 0;
              if (PABSDateTime(Buffer)^.Date <> DATE_IS_NULL) then
                ext := ext + PABSDateTime(Buffer)^.Date;
              if (PABSDateTime(Buffer)^.Time <> TIME_IS_NULL) then
                ext := ext + MILSECS_IN_DAY / PABSDateTime(Buffer)^.Time;
              cur := FloatToCurr(ext);
              AllocMemAndSetData(bftCurrency, cur, Result, NewDataSize);
            end;
        end;


      bftLogical:  // From Logical
        case NewDataType of
          bftChar,
          bftVarchar:
            begin
              if (PABSLogical(Buffer)^) then
                s := 'True'
              else
                s := 'False';
//                s := BoolToStr(PABSLogical(Buffer)^, true); {causes mem-leak}
              AllocMemAndSetData(bftVarchar, s, Result, NewDataSize);
            end;
          bftWideChar,
          bftWideVarchar:
            begin
              ws := BoolToStr(PABSLogical(Buffer)^, true);
              AllocMemAndSetData(bftWideVarchar, ws, Result, NewDataSize);
            end;
          bftSignedInt8:
            begin
              if PABSLogical(Buffer)^ then
                si8 := 1
              else
                si8 := 0;
              AllocMemAndSetData(bftSignedInt8, si8, Result, NewDataSize);
            end;
          bftSignedInt16:
            begin
              if PABSLogical(Buffer)^ then
                si16 := 1
              else
                si16 := 0;
              AllocMemAndSetData(bftSignedInt16, si16, Result, NewDataSize);
            end;
          bftSignedInt32:
            begin
              if PABSLogical(Buffer)^ then
                si32 := 1
              else
                si32 := 0;
              AllocMemAndSetData(bftSignedInt32, si32, Result, NewDataSize);
            end;
          bftSignedInt64:
            begin
              if PABSLogical(Buffer)^ then
                si64 := 1
              else
                si64 := 0;
              AllocMemAndSetData(bftSignedInt64, si64, Result, NewDataSize);
            end;
          bftUnsignedInt8:
            begin
              if PABSLogical(Buffer)^ then
                ui8 := 1
              else
                ui8 := 0;
              AllocMemAndSetData(bftUnsignedInt8, ui8, Result, NewDataSize);
            end;
          bftUnsignedInt16:
            begin
              if PABSLogical(Buffer)^ then
                ui16 := 1
              else
                ui16 := 0;
              AllocMemAndSetData(bftUnsignedInt16, ui16, Result, NewDataSize);
            end;
          bftUnsignedInt32:
            begin
              if PABSLogical(Buffer)^ then
                ui32 := 1
              else
                ui32 := 0;
              AllocMemAndSetData(bftUnsignedInt32, ui32, Result, NewDataSize);
            end;

          bftSingle:
            begin
              if PABSLogical(Buffer)^ then
                sng := 1
              else
                sng := 0;
              AllocMemAndSetData(bftSingle, sng, Result, NewDataSize);
            end;
          bftDouble:
            begin
              if PABSLogical(Buffer)^ then
                dbl := 1
              else
                dbl := 0;
              AllocMemAndSetData(bftDouble, dbl, Result, NewDataSize);
            end;
          bftExtended:
            begin
              if PABSLogical(Buffer)^ then
                ext := 1
              else
                ext := 0;
              AllocMemAndSetData(bftExtended, ext, Result, NewDataSize);
            end;

          bftDate:;      // No CAST
          bftTime:;
          bftDateTime:;

          bftLogical:
            begin
              b := PABSLogical(Buffer)^;
              AllocMemAndSetData(bftLogical, b, Result, NewDataSize);
            end;
          bftCurrency: ; // No CAST
        end;

      bftCurrency:  // from Currency
        case NewDataType of
          bftChar,
          bftVarchar:
            begin
              s := CurrToStr(PABSCurrency(Buffer)^);
              AllocMemAndSetData(bftVarchar, s, Result, NewDataSize);
            end;
          bftWideChar,
          bftWideVarchar:
            begin
              ws := CurrToStr(PABSCurrency(Buffer)^);
              AllocMemAndSetData(bftWideVarchar, ws, Result, NewDataSize);
            end;
          bftSignedInt8:
            begin
              si8 := Trunc(PABSCurrency(Buffer)^);
              AllocMemAndSetData(bftSignedInt8, si8, Result, NewDataSize);
            end;
          bftSignedInt16:
            begin
              si16 := Trunc(PABSCurrency(Buffer)^);
              AllocMemAndSetData(bftSignedInt16, si16, Result, NewDataSize);
            end;
          bftSignedInt32:
            begin
              si32 := Trunc(PABSCurrency(Buffer)^);
              AllocMemAndSetData(bftSignedInt32, si32, Result, NewDataSize);
            end;
          bftSignedInt64:
            begin
              si64 := Trunc(PABSCurrency(Buffer)^);
              AllocMemAndSetData(bftSignedInt64, si64, Result, NewDataSize);
            end;
          bftUnsignedInt8:
            begin
              ui8 := Trunc(PABSCurrency(Buffer)^);
              AllocMemAndSetData(bftUnsignedInt8, ui8, Result, NewDataSize);
            end;
          bftUnsignedInt16:
            begin
              ui16 := Trunc(PABSCurrency(Buffer)^);
              AllocMemAndSetData(bftUnsignedInt16, ui16, Result, NewDataSize);
            end;
          bftUnsignedInt32:
            begin
              ui32 := Trunc(PABSCurrency(Buffer)^);
              AllocMemAndSetData(bftUnsignedInt32, ui32, Result, NewDataSize);
            end;

          bftSingle:
            begin
              sng := PABSCurrency(Buffer)^;
              AllocMemAndSetData(bftSingle, sng, Result, NewDataSize);
            end;
          bftDouble:
            begin
              dbl := PABSCurrency(Buffer)^;
              AllocMemAndSetData(bftDouble, dbl, Result, NewDataSize);
            end;
          bftExtended:
            begin
              ext := PABSCurrency(Buffer)^;
              AllocMemAndSetData(bftExtended, ext, Result, NewDataSize);
            end;

          bftDate:;     // No CAST
          bftTime:;
          bftDateTime:;
          bftLogical:
            begin
              b := not (PABSCurrency(Buffer)^ = 0);
              AllocMemAndSetData(bftLogical, b, Result, NewDataSize);
            end;
          bftCurrency:
            begin
              cur := PABSCurrency(Buffer)^;
              AllocMemAndSetData(bftCurrency, cur, Result, NewDataSize);
            end;
        end;

      bftClob:  //  from Clob
        case NewDataType of
          bftChar,
          bftVarchar:
            begin
              if (DataSize > 0) then
                begin
                  Result := MemoryManager.GetMem(DataSize+1);
                  Move(PAnsiChar(Buffer)^, Result^, DataSize);
                  (Result+DataSize)^ := #0;
                  NewDataSize := DataSize+1;
                end
              else
                AllocMemAndSetData(bftVarchar, Buffer, Result, NewDataSize);
            end;
          bftWideChar,
          bftWideVarchar:
            begin
              ws := WideString(PAnsiChar(Buffer));
              AllocMemAndSetData(bftWideVarchar, ws, Result, NewDataSize);
            end;
          bftSignedInt8:
            begin
              si8 := StrToInt(PAnsiChar(Buffer));
              AllocMemAndSetData(bftSignedInt8, si8, Result, NewDataSize);
            end;
          bftSignedInt16:
            begin
              si16 := StrToInt(PAnsiChar(Buffer));
              AllocMemAndSetData(bftSignedInt16, si16, Result, NewDataSize);
            end;
          bftSignedInt32:
            begin
              si32 := StrToInt(PAnsiChar(Buffer));
              AllocMemAndSetData(bftSignedInt32, si32, Result, NewDataSize);
            end;
          bftSignedInt64:
            begin
              si64 := StrToInt(PAnsiChar(Buffer));
              AllocMemAndSetData(bftSignedInt64, si64, Result, NewDataSize);
            end;
          bftUnsignedInt8:
            begin
              ui8 := StrToInt(PAnsiChar(Buffer));
              AllocMemAndSetData(bftUnsignedInt8, ui8, Result, NewDataSize);
            end;
          bftUnsignedInt16:
            begin
              ui16 := StrToInt(PAnsiChar(Buffer));
              AllocMemAndSetData(bftUnsignedInt16, ui16, Result, NewDataSize);
            end;
          bftUnsignedInt32:
            begin
              ui32 := StrToInt(PAnsiChar(Buffer));
              AllocMemAndSetData(bftUnsignedInt32, ui32, Result, NewDataSize);
            end;

          bftSingle:
            begin
              oldSeparator := AnsiChar({$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif});
              {$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif} := '.';
              try
                sng := StrToFloat(PAnsiChar(Buffer));
              finally
                {$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif} := Char(oldSeparator);
              end;
              AllocMemAndSetData(bftSingle, sng, Result, NewDataSize);
            end;
          bftDouble:
            begin
              oldSeparator := AnsiChar({$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif});
              {$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif} := '.';
              try
                dbl := StrToFloat(PAnsiChar(Buffer));
              finally
                {$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif} := Char(oldSeparator);
              end;
              AllocMemAndSetData(bftDouble, dbl, Result, NewDataSize);
            end;
          bftExtended:
            begin
              oldSeparator := AnsiChar({$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif});
              {$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif} := '.';
              try
                ext := StrToFloat(PAnsiChar(Buffer));
              finally
                {$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif} := Char(oldSeparator);
              end;
              AllocMemAndSetData(bftExtended, ext, Result, NewDataSize);
            end;

          bftDate:
            begin
              d := DateToABSDate(StrToDate(PAnsiChar(Buffer)));
              AllocMemAndSetData(bftDate, d, Result, NewDataSize);
            end;
          bftTime:
            begin
              t := TimeToABSTime(StrToTime(PAnsiChar(Buffer)));
              AllocMemAndSetData(bftTime, t, Result, NewDataSize);
            end;
          bftDateTime:
            begin
              dt := DateTimeToABSDateTime(StrToDateTime(PAnsiChar(Buffer)));
              AllocMemAndSetData(bftDateTime, dt, Result, NewDataSize);
            end;

          bftLogical:
            begin
              s := UpperCase(PAnsiChar(Buffer));
              b := (s = '1') or (s = 'TRUE');
              AllocMemAndSetData(bftLogical, b, Result, NewDataSize);
            end;
          bftCurrency:
            begin
              cur := StrToCurr(PAnsiChar(Buffer));
              AllocMemAndSetData(bftCurrency, cur, Result, NewDataSize);
            end;
          bftBlob:
            begin
              AllocMemAndSetData(bftVarchar, PAnsiChar(Buffer), Result, NewDataSize);
            end;
        end;

      bftWideClob:  //  from WideClob
        case NewDataType of
          bftChar,
          bftVarchar:
            begin
              if (DataSize > 0) then
                begin
                  Result := MemoryManager.GetMem(DataSize+1);
                  Move(PAnsiChar(AnsiString(WideString(PWideChar(Buffer))))^, Result^, DataSize);
                  PWideChar(Result+DataSize)^ := #0;
                  NewDataSize := DataSize+2;
                end
              else
                AllocMemAndSetData(bftVarchar, Buffer, Result, NewDataSize);
            end;
          bftWideChar,
          bftWideVarchar:
            begin
              ws := WideString(PWideChar(Buffer));
              AllocMemAndSetData(bftWideVarchar, ws, Result, NewDataSize);
            end;
          bftSignedInt8:
            begin
              si8 := StrToInt(PWideChar(Buffer));
              AllocMemAndSetData(bftSignedInt8, si8, Result, NewDataSize);
            end;
          bftSignedInt16:
            begin
              si16 := StrToInt(PWideChar(Buffer));
              AllocMemAndSetData(bftSignedInt16, si16, Result, NewDataSize);
            end;
          bftSignedInt32:
            begin
              si32 := StrToInt(PWideChar(Buffer));
              AllocMemAndSetData(bftSignedInt32, si32, Result, NewDataSize);
            end;
          bftSignedInt64:
            begin
              si64 := StrToInt(PWideChar(Buffer));
              AllocMemAndSetData(bftSignedInt64, si64, Result, NewDataSize);
            end;
          bftUnsignedInt8:
            begin
              ui8 := StrToInt(PWideChar(Buffer));
              AllocMemAndSetData(bftUnsignedInt8, ui8, Result, NewDataSize);
            end;
          bftUnsignedInt16:
            begin
              ui16 := StrToInt(PWideChar(Buffer));
              AllocMemAndSetData(bftUnsignedInt16, ui16, Result, NewDataSize);
            end;
          bftUnsignedInt32:
            begin
              ui32 := StrToInt(PWideChar(Buffer));
              AllocMemAndSetData(bftUnsignedInt32, ui32, Result, NewDataSize);
            end;

          bftSingle:
            begin
              oldSeparator := AnsiChar({$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif});
              {$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif} := '.';
              try
                sng := StrToFloat(PWideChar(Buffer));
              finally
                {$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif} := Char(oldSeparator);
              end;
              AllocMemAndSetData(bftSingle, sng, Result, NewDataSize);
            end;
          bftDouble:
            begin
              oldSeparator := AnsiChar({$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif});
              {$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif} := '.';
              try
                dbl := StrToFloat(PWideChar(Buffer));
              finally
                {$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif} := Char(oldSeparator);
              end;
              AllocMemAndSetData(bftDouble, dbl, Result, NewDataSize);
            end;
          bftExtended:
            begin
              oldSeparator := AnsiChar({$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif});
              {$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif} := '.';
              try
                ext := StrToFloat(PWideChar(Buffer));
              finally
                {$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif} := Char(oldSeparator);
              end;
              AllocMemAndSetData(bftExtended, ext, Result, NewDataSize);
            end;

          bftDate:
            begin
              d := DateToABSDate(StrToDate(PWideChar(Buffer)));
              AllocMemAndSetData(bftDate, d, Result, NewDataSize);
            end;
          bftTime:
            begin
              t := TimeToABSTime(StrToTime(PWideChar(Buffer)));
              AllocMemAndSetData(bftTime, t, Result, NewDataSize);
            end;
          bftDateTime:
            begin
              dt := DateTimeToABSDateTime(StrToDateTime(PWideChar(Buffer)));
              AllocMemAndSetData(bftDateTime, dt, Result, NewDataSize);
            end;

          bftLogical:
            begin
              s := UpperCase(PWideChar(Buffer));
              b := (s = '1') or (s = 'TRUE');
              AllocMemAndSetData(bftLogical, b, Result, NewDataSize);
            end;
          bftCurrency:
            begin
              cur := StrToCurr(PWideChar(Buffer));
              AllocMemAndSetData(bftCurrency, cur, Result, NewDataSize);
            end;
          bftBlob:
            begin
              AllocMemAndSetData(bftVarchar, PWideChar(Buffer), Result, NewDataSize);
            end;
        end;

      bftBlob:  //  from Blob
        case NewDataType of
          bftChar,
          bftVarchar:
            begin
              if (DataSize > 0) then
                begin
                  Result := MemoryManager.GetMem(DataSize+1);
                  Move(PAnsiChar(Buffer)^, Result^, DataSize);
                  (Result+DataSize)^ := #0;
                  NewDataSize := DataSize+1;
                end
              else
                AllocMemAndSetData(bftVarchar, Buffer, Result, NewDataSize);
            end;
          bftWideChar,
          bftWideVarchar:
            begin
              ws := WideString(PAnsiChar(Buffer));
              AllocMemAndSetData(bftWideVarchar, ws, Result, NewDataSize);
            end;
          bftSignedInt8:
            begin
              si8 := StrToInt(PAnsiChar(Buffer));
              AllocMemAndSetData(bftSignedInt8, si8, Result, NewDataSize);
            end;
          bftSignedInt16:
            begin
              si16 := StrToInt(PAnsiChar(Buffer));
              AllocMemAndSetData(bftSignedInt16, si16, Result, NewDataSize);
            end;
          bftSignedInt32:
            begin
              si32 := StrToInt(PAnsiChar(Buffer));
              AllocMemAndSetData(bftSignedInt32, si32, Result, NewDataSize);
            end;
          bftSignedInt64:
            begin
              si64 := StrToInt(PAnsiChar(Buffer));
              AllocMemAndSetData(bftSignedInt64, si64, Result, NewDataSize);
            end;
          bftUnsignedInt8:
            begin
              ui8 := StrToInt(PAnsiChar(Buffer));
              AllocMemAndSetData(bftUnsignedInt8, ui8, Result, NewDataSize);
            end;
          bftUnsignedInt16:
            begin
              ui16 := StrToInt(PAnsiChar(Buffer));
              AllocMemAndSetData(bftUnsignedInt16, ui16, Result, NewDataSize);
            end;
          bftUnsignedInt32:
            begin
              ui32 := StrToInt(PAnsiChar(Buffer));
              AllocMemAndSetData(bftUnsignedInt32, ui32, Result, NewDataSize);
            end;

          bftSingle:
            begin
              oldSeparator := AnsiChar({$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif});
              {$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif} := '.';
              try
                sng := StrToFloat(PAnsiChar(Buffer));
              finally
                {$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif} := Char(oldSeparator);
              end;
              AllocMemAndSetData(bftSingle, sng, Result, NewDataSize);
            end;
          bftDouble:
            begin
              oldSeparator := AnsiChar({$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif});
              {$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif} := '.';
              try
                dbl := StrToFloat(PAnsiChar(Buffer));
              finally
                {$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif} := Char(oldSeparator);
              end;
              AllocMemAndSetData(bftDouble, dbl, Result, NewDataSize);
            end;
          bftExtended:
            begin
              oldSeparator := AnsiChar({$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif});
              {$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif} := '.';
              try
                ext := StrToFloat(PAnsiChar(Buffer));
              finally
                {$ifndef D17H}DecimalSeparator{$else}FormatSettings.DecimalSeparator{$endif} := Char(oldSeparator);
              end;
              AllocMemAndSetData(bftExtended, ext, Result, NewDataSize);
            end;

          bftDate:
            begin
              d := DateToABSDate(StrToDate(PAnsiChar(Buffer)));
              AllocMemAndSetData(bftDate, d, Result, NewDataSize);
            end;
          bftTime:
            begin
              t := TimeToABSTime(StrToTime(PAnsiChar(Buffer)));
              AllocMemAndSetData(bftTime, t, Result, NewDataSize);
            end;
          bftDateTime:
            begin
              dt := DateTimeToABSDateTime(StrToDateTime(PAnsiChar(Buffer)));
              AllocMemAndSetData(bftDateTime, dt, Result, NewDataSize);
            end;

          bftLogical:
            begin
              s := AnsiString(UpperCase(PAnsiChar(Buffer)));
              b := (s = '1') or (s = 'TRUE');
              AllocMemAndSetData(bftLogical, b, Result, NewDataSize);
            end;
          bftCurrency:
            begin
              cur := StrToCurr(PAnsiChar(Buffer));
              AllocMemAndSetData(bftCurrency, cur, Result, NewDataSize);
            end;
          bftBlob:
            begin
              AllocMemAndSetData(bftVarchar, PAnsiChar(Buffer), Result, NewDataSize);
            end;
        end;

      //else raise EABSException.Create
    end;
  except
    raise EABSException.Create(30051, ErrorGCastError,
                                   [BftToStr(DataType), BftToStr(NewDataType)]);
  end;

  if (Result = nil) then
    raise EABSException.Create(30052, ErrorGCastError,
                                  [BftToStr(DataType), BftToStr(NewDataType)]);
end;//Cast



//------------------------------------------------------------------------------
// Compare 2 values
//------------------------------------------------------------------------------
function CompareValueBuffers(
                              Buffer1, Buffer2: Pointer;
                              BaseFieldType1, BaseFieldType2: TABSBaseFieldType;
                              IsField1Null: Boolean = false;
                              IsField2Null: Boolean = false;
                              PartialCompareLength: Integer = -1;
                              IgnoreCase: Boolean = false;
                              LocaleID: LCID = LOCALE_USER_DEFAULT
                            ): TABSCompareResult;
var
   Value1,Value2 : Pointer;
   NewBuffer1, NewBuffer2: Pointer;

   CommonType: TABSBaseFieldType;
   StrCmpResult: Integer;
   StrCmpFlags: DWORD;
//   Tmp1, Tmp2: Integer;
   //Variant1, Variant2: TABSVariant;
begin
 Result := cmprEqual;
 // Check NULLs
 if (IsField1Null or IsField2Null) then
  begin
     if (IsField1Null and IsField2Null) then
      result := cmprBothNull
     else
     if (IsField1Null) then
       result := cmprLeftNull
     else
       result := cmprRightNull;
   Exit;
  end;

  NewBuffer1 := nil;
  NewBuffer2 := nil;
  try

  // Cast both to common Type
  if ((BaseFieldType1 = BaseFieldType2) and (not (BaseFieldType1 in [bftClob, bftWideclob]))) then
   begin
     Value1 := Buffer1;
     Value2 := Buffer2;
     CommonType := BaseFieldType1;
   end
  else
   begin
     CommonType := GetCommonDataType(BaseFieldType1, BaseFieldType2, True);
     // Cannot compare
     if (CommonType = bftUnknown) then
       raise EABSException.Create(30044, ErrorGCatnnotCompareIncompatibleDataTypes,
                                  [bftToStr(BaseFieldType1), bftToStr(BaseFieldType2)]);

     // Cast 1-st parameter
     if (CommonType <> BaseFieldType1) then
       begin
         NewBuffer1 := CastToNewBuffer(Buffer1, -1, BaseFieldType1, CommonType);
         Value1 := NewBuffer1;
       end
     else
       Value1 := Buffer1;

     // Cast 2-nd parameter
     if (CommonType <> BaseFieldType2) then
       begin
         NewBuffer2 := CastToNewBuffer(Buffer2, -1, BaseFieldType2, CommonType);
         Value2 := NewBuffer2;
       end
     else
       Value2 := Buffer2;

   end;//Cast both to common Type

  if ((Value1 = nil) or (Value2 = nil)) then
    raise EABSException.Create(30140, ErrorGValueIsNull);

  case CommonType of
    bftChar,
    bftBytes,
    bftVarchar:
      begin
        StrCmpFlags := SORT_STRINGSORT;
        if IgnoreCase then
          StrCmpFlags := StrCmpFlags + NORM_IGNORECASE;
{$IFDEF D12H}
        StrCmpResult := Windows.CompareStringA(
{$ELSE}
        StrCmpResult := Windows.CompareString(
{$ENDIF}
                                              LocaleID, StrCmpFlags,
                                              Value1, PartialCompareLength,
                                              Value2,PartialCompareLength);
        case StrCmpResult of
          1:   Result := cmprLower;
          2:   Result := cmprEqual;
          3:   Result := cmprGreater;
            else raise EABSException.Create(30045, ErrorGUnknownReturnCode, [StrCmpResult]);
        end;
      end;
    bftWideChar,
    bftWideVarchar:
      begin
        StrCmpFlags := SORT_STRINGSORT;
        if IgnoreCase then
          StrCmpFlags := StrCmpFlags + NORM_IGNORECASE;
        StrCmpResult := ABSStrUtils.CompareStringW(DefaultLocaleToCompareWideStrings,
                                               StrCmpFlags,
                                               Value1, PartialCompareLength,
                                               Value2,PartialCompareLength);

        case StrCmpResult of
          1:   Result := cmprLower;
          2:   Result := cmprEqual;
          3:   Result := cmprGreater;
            else raise EABSException.Create(30046, ErrorAUnicodeNotSupported);
        end;
      end;
    bftSignedInt8:
      begin
        if (pShortint(Value1)^ = pShortint(Value2)^) then
          Result := cmprEqual
        else
          if (pShortint(Value1)^ > pShortint(Value2)^) then
            Result := cmprGreater
          else
            Result := cmprLower;
      end;
    bftSignedInt16:
      begin
        if (pSmallInt(Value1)^ = pSmallInt(Value2)^) then
          Result := cmprEqual
        else
          if (pSmallInt(Value1)^ > pSmallInt(Value2)^) then
            Result := cmprGreater
          else
            Result := cmprLower;
      end;
    bftSignedInt32:
      begin
        if (pInteger(Value1)^ = pInteger(Value2)^) then
          Result := cmprEqual
        else
          if (pInteger(Value1)^ > pInteger(Value2)^) then
            Result := cmprGreater
          else
            Result := cmprLower;
      end;
    bftSignedInt64:
      begin
        if (pInt64(Value1)^ = pInt64(Value2)^) then
          Result := cmprEqual
        else
          if (pInt64(Value1)^ > pInt64(Value2)^) then
            Result := cmprGreater
          else
            Result := cmprLower;
      end;
    bftUnSignedInt8:
      begin
        if (pByte(Value1)^ = pByte(Value2)^) then
          Result := cmprEqual
        else
          if (pByte(Value1)^ > pByte(Value2)^) then
            Result := cmprGreater
          else
            Result := cmprLower;
      end;
    bftUnSignedInt16:
      begin
        if (pWord(Value1)^ = pWord(Value2)^) then
          Result := cmprEqual
        else
          if (pWord(Value1)^ > pWord(Value2)^) then
            Result := cmprGreater
          else
            Result := cmprLower;
      end;
    bftUnSignedInt32:
      begin
        if (pLongword(Value1)^ = pLongword(Value2)^) then
          Result := cmprEqual
        else
          if (pLongword(Value1)^ > pLongword(Value2)^) then
            Result := cmprGreater
          else
            Result := cmprLower;
      end;
    bftSingle:
      begin
        if (pSingle(Value1)^ = pSingle(Value2)^) then
          Result := cmprEqual
        else
          if (pSingle(Value1)^ > pSingle(Value2)^) then
            Result := cmprGreater
          else
            Result := cmprLower;
      end;
    bftDouble:
      begin
        if (pDouble(Value1)^ = pDouble(Value2)^) then
          Result := cmprEqual
        else
          if (pDouble(Value1)^ > pDouble(Value2)^) then
            Result := cmprGreater
          else
            Result := cmprLower;
      end;
    bftExtended:
      begin
        if (pExtended(Value1)^ = pExtended(Value2)^) then
          Result := cmprEqual
        else
          if (pExtended(Value1)^ > pExtended(Value2)^) then
            Result := cmprGreater
          else
            Result := cmprLower;
      end;
    bftDate:
      begin
        if (PABSDate(Value1)^ = PABSDate(Value2)^) then
          Result := cmprEqual
        else
          if (PABSDate(Value1)^ > PABSDate(Value2)^) then
            Result := cmprGreater
          else
            Result := cmprLower;
      end;
    bftTime:
      begin
        if (PABSTime(Value1)^ = PABSTime(Value2)^) then
          Result := cmprEqual
        else
          if (PABSTime(Value1)^ > PABSTime(Value2)^) then
            Result := cmprGreater
          else
            Result := cmprLower;
      end;
    bftDateTime:
      begin
        // Comparing Date perts
        if (PABSDateTime(Value1)^.Date = PABSDateTime(Value2)^.Date) then
          // Time part IS NULL --> result = ???
          //if ( (PABSDateTime(Value1)^.Time = TIME_IS_NULL) or
          //     (PABSDateTime(Value2)^.Time = TIME_IS_NULL) then ;

          // date1 = date2. Comparing times

          if (PABSDateTime(Value1)^.Time = PABSDateTime(Value2)^.Time) then
            // Time1 = Time 2
            Result := cmprEqual
          else
            // Time1 <> Time 2
            if (PABSDateTime(Value1)^.Time > PABSDateTime(Value2)^.Time) then
              Result := cmprGreater
            else
              Result := cmprLower
        else
          // Date1 <> Date2
          if (PABSTime(Value1)^ > PABSTime(Value2)^) then
            Result := cmprGreater
          else
            Result := cmprLower;
      end;
    bftLogical:
      begin
        if (PABSLogical(Value1)^ = PABSLogical(Value2)^) then
          Result := cmprEqual
        else
          if (PABSLogical(Value1)^ > PABSLogical(Value2)^) then
            Result := cmprGreater
          else
            Result := cmprLower;
      end;
    bftCurrency:
      begin
        if (PABSCurrency(Value1)^ = PABSCurrency(Value2)^) then
          Result := cmprEqual
        else
          if (PABSCurrency(Value1)^ > PABSCurrency(Value2)^) then
            Result := cmprGreater
          else
            Result := cmprLower;
      end;

    else
        raise EABSException.Create(30047, ErrorGUnknownDataType, [BftToStr(CommonType)]);
    end;
  finally
    if NewBuffer1 <> nil then
      MemoryManager.FreeAndNillMem(NewBuffer1);
    if NewBuffer2 <> nil then
      MemoryManager.FreeAndNillMem(NewBuffer2);
  end;
end;//CompareValueBuffers


//------------------------------------------------------------------------------
// Compare 2 values in sense of order (-1,0,1)
//------------------------------------------------------------------------------
function CompareValueBuffersForOrder(
                              Buffer1, Buffer2: Pointer;
                              BaseFieldType1, BaseFieldType2: TABSBaseFieldType;
                              IsField1Null: Boolean = false;
                              IsField2Null: Boolean = false;
                              PartialCompareLength: Integer = -1;
                              IgnoreCase: Boolean = false;
                              LocaleID: LCID = LOCALE_USER_DEFAULT
                            ): Integer;
var
  cmpResult: TABSCompareResult;
begin
  cmpResult := CompareValueBuffers(
              Buffer1, Buffer2, BaseFieldType1, BaseFieldType2,
              IsField1Null, IsField2Null, PartialCompareLength,
              IgnoreCase, LocaleID);
  case cmpResult of
   cmprBothNull, cmprEqual:    Result := 0;
   cmprLeftNull, cmprLower:    Result := -1;
   cmprRightNull, cmprGreater: Result := 1;
  else
   Result := 0;
  end;
end;// CompareValueBuffersForOrder



end.

