
//////////////////////////////////////////////////
//  Oracle Data Access Components
//  Copyright © 1998-2014 Devart. All right reserved.
//////////////////////////////////////////////////

{$IFNDEF CLR}
{$I Odac.inc}
unit OraDataTypeMapUni;
{$ENDIF}

interface

uses
  SysUtils, DB,
{$IFDEF VER6P}
{$IFNDEF FPC}
  FMTBcd,
{$ENDIF}
{$ENDIF}
{$IFDEF CLR}
  System.Runtime.InteropServices, System.Text,
{$ELSE}
  CLRClasses,
{$ENDIF}
  CRTypes, CRDataTypeMap, MemData;

const
  oraBase                       = 100;

  oraChar                       = oraBase + 1;
  oraVarchar2                   = oraBase + 2;
  oraNChar                      = oraBase + 3;
  oraNVarchar2                  = oraBase + 4;
  oraNumber                     = oraBase + 5;
  oraBinaryFloat                = oraBase + 6;
  oraBinaryDouble               = oraBase + 7;
  oraDate                       = oraBase + 8;
  oraTimeStamp                  = oraBase + 9;
  oraTimeStampWithTimeZone      = oraBase + 10;
  oraTimeStampWithLocalTimeZone = oraBase + 11;
  oraBlob                       = oraBase + 12;
  oraClob                       = oraBase + 13;
  oraNClob                      = oraBase + 14;
  oraBFile                      = oraBase + 15;
  oraLong                       = oraBase + 16;
  oraRaw                        = oraBase + 17;
  oraLongRaw                    = oraBase + 18;
  oraRowID                      = oraBase + 19;
  oraURowID                     = oraBase + 20;
  oraXML                        = oraBase + 21;
  oraIntervalYM                 = oraBase + 22;
  oraIntervalDS                 = oraBase + 23;

type

  TOraMapRules = class (TCRMapRules)
  public
    class function GetConverterManager: TConverterManager; override;
  end;

  TOraConverterManager = class(TConverterManager)
  protected
  public
    constructor Create;

    class function GetDBProvider: Word; override;
    class function GetDBType(SQLType: Word; IsNational: boolean = False): Word;
  end;

  TOraDataConverters = class(TDataConverters)
  public
    class function NumberToInt8(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function NumberToUInt8(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function NumberToInt16(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function NumberToUInt16(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function NumberToInt32(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function NumberToUInt32(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function NumberToInt64(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function NumberToFloat(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function NumberToSingle(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function NumberToBCD(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
  {$IFDEF VER6P}{$IFNDEF FPC}
    class function NumberToFMTBCD(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
  {$ENDIF}{$ENDIF}
    class function NumberToAStr(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function NumberToWStr(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function NumberToExtAStr(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function NumberToExtWStr(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}

    class function Int8ToNumber(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function UInt8ToNumber(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function Int16ToNumber(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function UInt16ToNumber(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function Int32ToNumber(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function UInt32ToNumber(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function Int64ToNumber(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function FloatToNumber(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function SingleToNumber(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function BCDToNumber(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
  {$IFDEF VER6P}{$IFNDEF FPC}
    class function FMTBCDToNumber(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
  {$ENDIF}{$ENDIF}
    class function AStrToNumber(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function WStrToNumber(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function ExtAStrToNumber(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function ExtWStrToNumber(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function XmlToAStr(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function XmlToWStr(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function AStrToXml(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function WStrToXml(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function IntervalToAStr(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function IntervalToWStr(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function AStrToInterval(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
    class function WStrToInterval(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus; {$IFDEF CLR}static;{$ENDIF}
  end;

  procedure InitOraTypes;

implementation

uses
  CRFunctions, MemUtils,
{$IFNDEF UNIDACPRO}
  OraCall, OraClasses, OraObjects;
{$ELSE}
  OraCallUni, OraClassesUni, OraObjectsUni;
{$ENDIF}

const
  oraVarchar                    = oraBase + 51;
  oraInteger                    = oraBase + 52;
  oraDecimal                    = oraBase + 53;
  oraFloat                      = oraBase + 54;

var
  OraConverterManager: TOraConverterManager;

{ Functions }

procedure InitOraTypes;
begin
  DBTypeInfos.Add(oraChar,                       'Char',                            True,  False);
  DBTypeInfos.Add(oraVarchar2,                   'Varchar2',                        True,  False);
  DBTypeInfos.Add(oraNChar,                      'NChar',                           True,  False);
  DBTypeInfos.Add(oraNVarchar2,                  'NVarchar2',                       True,  False);
//  DBTypeInfos.Add(oraInteger,                    'Integer',                         False, False);
//  DBTypeInfos.Add(oraDecimal,                    'Decimal',                         False, False);
//  DBTypeInfos.Add(oraFloat,                      'Float',                           False, False);
  DBTypeInfos.Add(oraNumber,                     'Number',                          True,  True);
  DBTypeInfos.Add(oraBinaryFloat,                'BinaryFloat',                     False, False);
  DBTypeInfos.Add(oraBinaryDouble,               'BinaryDouble',                    False, False);
  DBTypeInfos.Add(oraDate,                       'Date',                            False, False);
  DBTypeInfos.Add(oraTimeStamp,                  'TimeStamp',                       False, False);
  DBTypeInfos.Add(oraTimeStampWithTimeZone,      'Time Stamp With Time Zone',       False, False);
  DBTypeInfos.Add(oraTimeStampWithLocalTimeZone, 'Time Stamp With Local Time Zone', False, False);
  DBTypeInfos.Add(oraBlob,                       'Blob',                            False, False);
  DBTypeInfos.Add(oraClob,                       'Clob',                            False, False);
  DBTypeInfos.Add(oraNClob,                      'NClob',                           False, False);
  DBTypeInfos.Add(oraBFile,                      'BFile',                           False, False);
  DBTypeInfos.Add(oraLong,                       'Long',                            False, False);
  DBTypeInfos.Add(oraRaw,                        'Raw',                             True,  False);
  DBTypeInfos.Add(oraLongRaw,                    'LongRaw',                         False, False);
  DBTypeInfos.Add(oraRowID,                      'RowID',                           False, False);
  DBTypeInfos.Add(oraURowID,                     'URowID',                          False, False);
  DBTypeInfos.Add(oraXML,                        'XML',                             False, False);
  DBTypeInfos.Add(oraIntervalYM,                 'IntervalYM',                      False, False);
  DBTypeInfos.Add(oraIntervalDS,                 'IntervalDS',                      False, False);
end;

{ TOraDataMapRules }

class function TOraMapRules.GetConverterManager: TConverterManager;
begin
  Result := OraConverterManager;
end;

{ TOraConverterManager }

constructor TOraConverterManager.Create;
begin
  inherited;

  AddFetchConverter(oraChar, dtString);
  AddFetchConverter(oraChar, dtWideString);

  AddFetchConverter(oraVarchar2, dtString);
  AddFetchConverter(oraVarchar2, dtWideString);

  AddFetchConverter(oraNChar, dtString);
  AddFetchConverter(oraNChar, dtWideString);

  AddFetchConverter(oraNVarchar2, dtString);
  AddFetchConverter(oraNVarchar2, dtWideString);

  AddFetchConverter(oraNumber,  1,  4, 0, 0, dtBoolean,  dtSmallint);
  AddFetchConverter(oraNumber,  1,  4, 0, 0, dtInt8,     dtSmallint);
  AddFetchConverter(oraNumber,  1,  4, 0, 0, dtUInt8,    dtSmallint);
  AddFetchConverter(oraNumber,  1,  4, 0, 0, dtSmallint, dtSmallint);
  AddFetchConverter(oraNumber,  1,  4, 0, 0, dtWord,     dtSmallint);
  AddFetchConverter(oraNumber,  1,  4, 0, 0, dtInteger,  dtSmallint);
  AddFetchConverter(oraNumber,  1,  4, 0, 0, dtLongWord, dtSmallint);
  AddFetchConverter(oraNumber,  1,  4, 0, 0, dtLargeint, dtSmallint);

  AddFetchConverter(oraNumber,  1,  9, 0, 0, dtBoolean,  dtInteger);
  AddFetchConverter(oraNumber,  5,  9, 0, 0, dtInt8,     dtInteger);
  AddFetchConverter(oraNumber,  5,  9, 0, 0, dtUInt8,    dtInteger);
  AddFetchConverter(oraNumber,  5,  9, 0, 0, dtSmallint, dtInteger);
  AddFetchConverter(oraNumber,  5,  9, 0, 0, dtWord,     dtInteger);
  AddFetchConverter(oraNumber,  5,  9, 0, 0, dtInteger,  dtInteger);
  AddFetchConverter(oraNumber,  5,  9, 0, 0, dtLongWord, dtInteger);
  AddFetchConverter(oraNumber,  5,  9, 0, 0, dtLargeint, dtInteger);

  AddFetchConverter(oraNumber, 10, -1, 0, 0, dtBoolean,  dtLargeint);
  AddFetchConverter(oraNumber, 10, -1, 0, 0, dtInt8,     dtLargeint);
  AddFetchConverter(oraNumber, 10, -1, 0, 0, dtUInt8,    dtLargeint);
  AddFetchConverter(oraNumber, 10, -1, 0, 0, dtSmallint, dtLargeint);
  AddFetchConverter(oraNumber, 10, -1, 0, 0, dtWord,     dtLargeint);
  AddFetchConverter(oraNumber, 10, -1, 0, 0, dtInteger,  dtLargeint);
  AddFetchConverter(oraNumber, 10, -1, 0, 0, dtLongWord, dtLargeint);
  AddFetchConverter(oraNumber, 10, -1, 0, 0, dtLargeint, dtLargeint);

  AddFetchConverter(oraNumber, dtFloat);
  AddFetchConverter(oraNumber, dtCurrency, dtFloat);
  AddFetchConverter(oraNumber, dtSingle, dtFloat);
  AddFetchConverter(oraNumber, -1, 14, -1, 4, dtBCD);
{$IFDEF VER6P}{$IFNDEF FPC}
  AddFetchConverter(oraNumber, dtBCD, dtFMTBCD);
  AddFetchConverter(oraNumber, dtFMTBCD);
{$ENDIF}{$ENDIF}
  AddFetchConverter(oraNumber, dtNumber);

  AddFetchConverter(oraBinaryFloat, dtFloat);
  AddFetchConverter(oraBinaryFloat, dtSingle);

  AddFetchConverter(oraTimeStamp, dtTime, dtDateTime);
  AddFetchConverter(oraTimeStamp, dtDate, dtDateTime);
  AddFetchConverter(oraTimeStamp, dtDateTime);
{$IFDEF VER6P}
{$IFNDEF FPC}
  AddFetchConverter(oraTimeStamp, dtSQLTimeStamp);
{$ENDIF}
{$ENDIF}
  AddFetchConverter(oraTimeStamp, dtTimeStamp, dtTimeStamp);
  AddFetchConverter(oraTimeStamp, dtTimeStampTZ, dtTimeStamp);
  AddFetchConverter(oraTimeStamp, dtTimeStampLTZ, dtTimeStamp);

  AddFetchConverter(oraTimeStampWithTimeZone, dtTime, dtDateTime);
  AddFetchConverter(oraTimeStampWithTimeZone, dtDate, dtDateTime);
  AddFetchConverter(oraTimeStampWithTimeZone, dtDateTime);
{$IFDEF VER6P}
{$IFNDEF FPC}
  AddFetchConverter(oraTimeStampWithTimeZone, dtSQLTimeStamp);
{$ENDIF}
{$ENDIF}
  AddFetchConverter(oraTimeStampWithTimeZone, dtTimeStamp, dtTimeStampTZ);
  AddFetchConverter(oraTimeStampWithTimeZone, dtTimeStampTZ, dtTimeStampTZ);
  AddFetchConverter(oraTimeStampWithTimeZone, dtTimeStampLTZ, dtTimeStampTZ);

  AddFetchConverter(oraTimeStampWithLocalTimeZone, dtTime, dtDateTime);
  AddFetchConverter(oraTimeStampWithLocalTimeZone, dtDate, dtDateTime);
  AddFetchConverter(oraTimeStampWithLocalTimeZone, dtDateTime);
{$IFDEF VER6P}
{$IFNDEF FPC}
  AddFetchConverter(oraTimeStampWithLocalTimeZone, dtSQLTimeStamp);
{$ENDIF}
{$ENDIF}
  AddFetchConverter(oraTimeStampWithLocalTimeZone, dtTimeStamp, dtTimeStampLTZ);
  AddFetchConverter(oraTimeStampWithLocalTimeZone, dtTimeStampTZ, dtTimeStampLTZ);
  AddFetchConverter(oraTimeStampWithLocalTimeZone, dtTimeStampLTZ, dtTimeStampLTZ);

  AddFetchConverter(oraClob, dtMemo, dtOraClob);
  AddFetchConverter(oraClob, dtWideMemo, dtWideOraClob);

  AddFetchConverter(oraNClob, dtMemo, dtOraClob);
  AddFetchConverter(oraNClob, dtWideMemo, dtWideOraClob);

  AddOnDemandConverter(dtOraBlob, dtString, TDataConverters.MemoToAStr, TDataConverters.AStrToMemo);
  AddOnDemandConverter(dtOraBlob, dtWideString, TDataConverters.MemoToWStr, TDataConverters.WStrToMemo);
  AddOnDemandConverter(dtOraBlob, dtMemo, TDataConverters.CopyPtr, TDataConverters.CopyPtr);
  AddOnDemandConverter(dtOraBlob, dtWideMemo, TDataConverters.CopyPtr, TDataConverters.CopyPtr);

  AddOnDemandConverter(dtOraClob, dtString, TDataConverters.MemoToAStr, TDataConverters.AStrToMemo);
  AddOnDemandConverter(dtOraClob, dtWideString, TDataConverters.MemoToWStr, TDataConverters.WStrToMemo);
  AddOnDemandConverter(dtOraClob, dtMemo, TDataConverters.CopyPtr, TDataConverters.CopyPtr);
//  AddOnDemandConverter(dtOraClob, dtWideMemo, TDataConverters.CopyPtr, TDataConverters.CopyPtr);

  AddOnDemandConverter(dtWideOraClob, dtWideMemo, TDataConverters.CopyPtr, TDataConverters.CopyPtr);

  AddOnDemandConverter(dtNClob, dtString, TDataConverters.MemoToAStr, TDataConverters.AStrToMemo);
  AddOnDemandConverter(dtNClob, dtWideString, TDataConverters.MemoToWStr, TDataConverters.WStrToMemo);
  AddOnDemandConverter(dtNClob, dtMemo, TDataConverters.CopyPtr, TDataConverters.CopyPtr);
//  AddOnDemandConverter(dtNClob, dtWideMemo, TDataConverters.CopyPtr, TDataConverters.CopyPtr);

  AddOnDemandConverter(dtNumber, dtInt8, TOraDataConverters.NumberToInt8, TOraDataConverters.Int8ToNumber);
  AddOnDemandConverter(dtNumber, dtUInt8, TOraDataConverters.NumberToUInt8, TOraDataConverters.UInt8ToNumber);
  AddOnDemandConverter(dtNumber, dtSmallint, TOraDataConverters.NumberToInt16, TOraDataConverters.Int16ToNumber);
  AddOnDemandConverter(dtNumber, dtWord, TOraDataConverters.NumberToUInt16, TOraDataConverters.UInt16ToNumber);
  AddOnDemandConverter(dtNumber, dtInteger, TOraDataConverters.NumberToInt32, TOraDataConverters.Int32ToNumber);
  AddOnDemandConverter(dtNumber, dtUInt32, TOraDataConverters.NumberToUInt32, TOraDataConverters.UInt32ToNumber);
  AddOnDemandConverter(dtNumber, dtInt64, TOraDataConverters.NumberToInt64, TOraDataConverters.Int64ToNumber);
  AddOnDemandConverter(dtNumber, dtFloat, TOraDataConverters.NumberToFloat, TOraDataConverters.FloatToNumber);
  AddOnDemandConverter(dtNumber, dtSingle, TOraDataConverters.NumberToSingle, TOraDataConverters.SingleToNumber);
  AddOnDemandConverter(dtNumber, dtCurrency, TOraDataConverters.NumberToFloat, TOraDataConverters.FloatToNumber);
  AddOnDemandConverter(dtNumber, dtBCD, TOraDataConverters.NumberToBCD, TOraDataConverters.BCDToNumber);
{$IFDEF VER6P}{$IFNDEF FPC}
  AddOnDemandConverter(dtNumber, dtFMTBCD, TOraDataConverters.NumberToFMTBCD, TOraDataConverters.FMTBCDToNumber);
{$ENDIF}{$ENDIF}
  AddOnDemandConverter(dtNumber, dtString, TOraDataConverters.NumberToAStr, TOraDataConverters.AStrToNumber);
  AddOnDemandConverter(dtNumber, dtExtString, TOraDataConverters.NumberToExtAStr, TOraDataConverters.ExtAStrToNumber);
  AddOnDemandConverter(dtNumber, dtWideString, TOraDataConverters.NumberToWStr, TOraDataConverters.WStrToNumber);
  AddOnDemandConverter(dtNumber, dtExtWideString, TOraDataConverters.NumberToExtWStr, TOraDataConverters.ExtWStrToNumber);
  AddOnDemandConverter(dtXML,    dtString, TOraDataConverters.XmlToAStr, TOraDataConverters.AStrToXml);
  AddOnDemandConverter(dtXML,    dtWideString, TOraDataConverters.XmlToWStr, TOraDataConverters.WStrToXml);
  AddOnDemandConverter(dtIntervalYM, dtString, TOraDataConverters.IntervalToAStr, TOraDataConverters.AStrToInterval);
  AddOnDemandConverter(dtIntervalYM, dtWideString, TOraDataConverters.IntervalToWStr, TOraDataConverters.WStrToInterval);
  AddOnDemandConverter(dtIntervalDS, dtString, TOraDataConverters.IntervalToAStr, TOraDataConverters.AStrToInterval);
  AddOnDemandConverter(dtIntervalDS, dtWideString, TOraDataConverters.IntervalToWStr, TOraDataConverters.WStrToInterval);
end;

class function TOraConverterManager.GetDBProvider: Word;
begin
  Result := oraBase;
end;

class function TOraConverterManager.GetDBType(SQLType: Word; IsNational: boolean = False): Word;
begin
  case SQLType of
    SQLT_AFC:
      if IsNational then
        Result := oraNChar
      else
        Result := oraChar;
    SQLT_AVC, SQLT_CHR:
      if IsNational then
        Result := oraNVarchar2
      else
        Result := oraVarchar2;
    SQLT_FLT:
      Result := oraFloat;
    SQLT_NUM:
      Result := oraNumber;
    SQLT_PDN:
      Result := oraDecimal;
    SQLT_IBFLOAT:
      Result := oraBinaryFloat;
    SQLT_IBDOUBLE:
      Result := oraBinaryDouble;
    SQLT_DAT:
      Result := oraDate;
    SQLT_TIMESTAMP:
      Result := oraTimeStamp;
    SQLT_TIMESTAMP_TZ:
      Result := oraTimeStampWithTimeZone;
    SQLT_TIMESTAMP_LTZ:
      Result := oraTimeStampWithLocalTimeZone;
    SQLT_BLOB:
      Result := oraBlob;
    SQLT_CLOB:
      if IsNational then
        Result := oraNClob
      else
        Result := oraClob;
    SQLT_BFILEE:
      Result := oraBFile;
    SQLT_LNG:
      Result := oraLong;
    SQLT_BIN:
      Result := oraRaw;
    SQLT_LBI:
      Result := oraLongRaw;
    SQLT_RID:
      Result := oraRowID;
    SQLT_RDD:
      Result := oraURowID;
    SQLT_NTY:
      Result := oraXML;
    SQLT_INTERVAL_YM:
      Result := oraIntervalYM;
    SQLT_INTERVAL_DS:
      Result := oraIntervalDS;
    else
      Result := 0;
  end;
end;

{ TOraDataConverters }

class function TOraDataConverters.NumberToInt8(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
var
  i: integer;
begin
  i := TOraNumber(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsInteger;
  Result := InternalInt32ToInt8(i, Dest, IgnoreConvertErrors);
end;

class function TOraDataConverters.NumberToUInt8(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
var
  i: integer;
begin
  i := TOraNumber(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsInteger;
  Result := InternalInt32ToUInt8(i, Dest, IgnoreConvertErrors);
end;

class function TOraDataConverters.NumberToInt16(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
var
  i: integer;
begin
  i := TOraNumber(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsInteger;
  Result := InternalInt32ToInt16(i, Dest, IgnoreConvertErrors);
end;

class function TOraDataConverters.NumberToUInt16(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
var
  i: integer;
begin
  i := TOraNumber(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsInteger;
  Result := InternalInt32ToUInt16(i, Dest, IgnoreConvertErrors);
end;

class function TOraDataConverters.NumberToInt32(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
var
  i: integer;
begin
  i := TOraNumber(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsInteger;
  Marshal.WriteInt32(Dest, i);
  Result := csSuccess;
end;

class function TOraDataConverters.NumberToUInt32(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
var
  i64: Int64;
begin
  i64 := TOraNumber(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsLargeInt;
  Result := InternalInt64ToUInt32(i64, Dest, IgnoreConvertErrors);
end;

class function TOraDataConverters.NumberToInt64(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
var
  i64: Int64;
begin
  i64 := TOraNumber(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsLargeInt;
  Marshal.WriteInt64(Dest, i64);
  Result := csSuccess;
end;

class function TOraDataConverters.NumberToFloat(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
begin
  Marshal.WriteInt64(Dest, BitConverter.DoubleToInt64Bits(TOraNumber(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsFloat));
  Result := csSuccess;
end;

class function TOraDataConverters.NumberToSingle(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
begin
  Marshal.WriteInt64(Dest, CRBitConverter.SingleToInt32Bits(TOraNumber(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsFloat));
  Result := csSuccess;
end;

class function TOraDataConverters.NumberToBCD(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
var
  d: Double;
  r: TConvertStatus;
begin
  d := TOraNumber(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsFloat * 10000;

  // Cast check
  if {$IFNDEF CLR}System.{$ENDIF}Frac(d) <> 0 then begin
    Result := csFractionTruncated;
    if not IgnoreConvertErrors then
      Exit
  end
  else
    Result := csSuccess;

  r := WriteInt64AsBCD(Trunc(d), Dest, DestLen, DestScale, IgnoreConvertErrors);
  if Result = csSuccess then
    Result := r;
end;

{$IFDEF VER6P}{$IFNDEF FPC}
class function TOraDataConverters.NumberToFMTBCD(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
begin
  Result := InternalBCDToFMTBCD(TOraNumber(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsBCD, Dest, DestLen, DestScale, IgnoreConvertErrors);
end;
{$ENDIF}{$ENDIF}

class function TOraDataConverters.NumberToAStr(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
var
  Str: String;
begin
  Str := TOraNumber(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsString;
  Result := InternalWriteAStr(AnsiString(Str), Dest, DestLen, IgnoreConvertErrors);
end;

class function TOraDataConverters.NumberToWStr(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
var
  Str: String;
begin
  Str := TOraNumber(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsString;
  Result := InternalWriteWStr(WideString(Str), Dest, DestLen, IgnoreConvertErrors);
end;

class function TOraDataConverters.NumberToExtAStr(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
var
  Str: String;
begin
  Str := TOraNumber(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsString;
  Result := InternalWriteExtAStr(StringHeap, AnsiString(Str), Dest, DestLen, IgnoreConvertErrors);
end;

class function TOraDataConverters.NumberToExtWStr(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
var
  Str: String;
begin
  Str := TOraNumber(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsString;
  Result := InternalWriteExtWStr(StringHeap, WideString(Str), Dest, DestLen, IgnoreConvertErrors);
end;

class function TOraDataConverters.Int8ToNumber(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
begin
  TOraNumber(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsInteger := ShortInt(Marshal.ReadByte(Source));
  Result := csSuccess;
end;

class function TOraDataConverters.UInt8ToNumber(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
begin
  TOraNumber(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsInteger := Marshal.ReadByte(Source);
  Result := csSuccess;
end;

class function TOraDataConverters.Int16ToNumber(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
begin
  TOraNumber(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsInteger := Marshal.ReadInt16(Source);
  Result := csSuccess;
end;

class function TOraDataConverters.UInt16ToNumber(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
begin
  TOraNumber(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsInteger := Word(Marshal.ReadInt16(Source));
  Result := csSuccess;
end;

class function TOraDataConverters.Int32ToNumber(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
begin
  TOraNumber(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsInteger := Marshal.ReadInt32(Source);
  Result := csSuccess;
end;

class function TOraDataConverters.UInt32ToNumber(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
begin
  TOraNumber(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsLargeInt := LongWord(Marshal.ReadInt32(Source));
  Result := csSuccess;
end;

class function TOraDataConverters.Int64ToNumber(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
begin
  TOraNumber(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsLargeInt := Marshal.ReadInt64(Source);
  Result := csSuccess;
end;

class function TOraDataConverters.FloatToNumber(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
begin
  TOraNumber(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsFloat := BitConverter.Int64BitsToDouble(Marshal.ReadInt64(Source));
  Result := csSuccess;
end;

class function TOraDataConverters.SingleToNumber(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
begin
  TOraNumber(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsFloat := CRBitConverter.Int32BitsToSingle(Marshal.ReadInt32(Source));
  Result := csSuccess;
end;

class function TOraDataConverters.BCDToNumber(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
begin
  TOraNumber(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsFloat := Marshal.ReadInt64(Source) / 10000;
  Result := csSuccess;
end;

{$IFDEF VER6P}{$IFNDEF FPC}
class function TOraDataConverters.FMTBCDToNumber(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
var
  bcd: TBcd;
begin
  InternalReadFMTBCD(Source, bcd);
  TOraNumber(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsBCD := bcd;
  Result := csSuccess;
end;
{$ENDIF}{$ENDIF}

class function TOraDataConverters.AStrToNumber(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
var
  AStr: AnsiString;
begin
  AStr := Marshal.PtrToStringAnsi(Source);
  TOraNumber(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsString := string(AStr);
  Result := csSuccess;
end;

class function TOraDataConverters.WStrToNumber(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
var
  WStr: WideString;
begin
  WStr := Marshal.PtrToStringUni(Source);
  TOraNumber(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsString := string(WStr);
  Result := csSuccess;
end;

class function TOraDataConverters.ExtAStrToNumber(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
var
  SourcePtr: IntPtr;
begin
  SourcePtr := Marshal.ReadIntPtr(Source);
  Result := AStrToNumber(StringHeap, SourcePtr, SourceLen, SourceScale, Dest, DestLen, DestScale, IgnoreConvertErrors);
end;

class function TOraDataConverters.ExtWStrToNumber(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
var
  SourcePtr: IntPtr;
begin
  SourcePtr := Marshal.ReadIntPtr(Source);
  Result := WStrToNumber(StringHeap, SourcePtr, SourceLen, SourceScale, Dest, DestLen, DestScale, IgnoreConvertErrors);
end;

class function TOraDataConverters.XmlToAStr(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
var
  Str: AnsiString;
begin
  Str := AnsiString(TOraXML(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsString);
  Result := InternalWriteAStr(Str, Dest, DestLen, IgnoreConvertErrors);
end;

class function TOraDataConverters.XmlToWStr(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
var
  Str: WideString;
begin
  Str := WideString(TOraXML(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsString);
  Result := InternalWriteWStr(Str, Dest, DestLen, IgnoreConvertErrors);
end;

class function TOraDataConverters.AStrToXml(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
var
  XML: TOraXML;
begin
  XML := TOraXML(GetGCHandleTarget(Marshal.ReadIntPtr(Dest)));
  XML.AsString := string(Marshal.PtrToStringAnsi(Source));
  Result := csSuccess;
end;

class function TOraDataConverters.WStrToXml(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
var
  XML: TOraXML;
begin
  XML := TOraXML(GetGCHandleTarget(Marshal.ReadIntPtr(Dest)));
  XML.AsString := string(Marshal.PtrToStringUni(Source));
  Result := csSuccess;
end;

class function TOraDataConverters.IntervalToAStr(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
var
  Str: AnsiString;
begin
  Str := AnsiString(TOraInterval(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsString);
  Result := InternalWriteAStr(Str, Dest, DestLen, IgnoreConvertErrors);
end;

class function TOraDataConverters.IntervalToWStr(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
var
  Str: WideString;
begin
  Str := WideString(TOraInterval(GetGCHandleTarget(Marshal.ReadIntPtr(Source))).AsString);
  Result := InternalWriteWStr(Str, Dest, DestLen, IgnoreConvertErrors);
end;

class function TOraDataConverters.AStrToInterval(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
var
  Interval: TOraInterval;
begin
  Interval := TOraInterval(GetGCHandleTarget(Marshal.ReadIntPtr(Dest)));
  Interval.AsString := string(Marshal.PtrToStringAnsi(Source));
  Result := csSuccess;
end;

class function TOraDataConverters.WStrToInterval(StringHeap: TStringHeap; Source: IntPtr; SourceLen, SourceScale: Integer; Dest: IntPtr; DestLen, DestScale: Integer; IgnoreConvertErrors: Boolean): TConvertStatus;
var
  Interval: TOraInterval;
begin
  Interval := TOraInterval(GetGCHandleTarget(Marshal.ReadIntPtr(Dest)));
  Interval.AsString := string(Marshal.PtrToStringUni(Source));
  Result := csSuccess;
end;

initialization
  InitOraTypes;
  OraConverterManager := TOraConverterManager.Create;

finalization
  OraConverterManager.Free;

end.
