
//////////////////////////////////////////////////
//  DB2 Data Access Components
//  Copyright © 2008-2014 Devart. All right reserved.
//////////////////////////////////////////////////

{$IFNDEF CLR}

{$I DB2Dac.inc}
unit DB2CallUni;
{$ENDIF}

interface

uses
{$IFDEF MSWINDOWS}
  Windows,
{$ENDIF}
{$IFDEF CLR}
  System.Text, System.Runtime.InteropServices,
{$ELSE}
  CLRClasses,
{$ENDIF}
  Classes, SysUtils, SyncObjs,
  CRTypes,
{$IFNDEF UNIDACPRO}
  ODBCCall;
{$ELSE}
  ODBCCallUni;
{$ENDIF}

const
  DB2DLLName = 'db2cli.dll';

{$IFNDEF CLR}
var
  DB2DLL: string;
{$ELSE}
const
  DB2DLL = DB2DLLName;
{$ENDIF}

type
  _SQLGetLength = function(
    StatementHandle: TSQLHStmt;
    LocatorCType: smallint;
    Locator: integer;
    var StringLength: integer;
    var IndicatorValue: integer
  ): smallint; {$IFNDEF CLR}{$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};{$ENDIF}

  _SQLGetSubString = function(
    StatementHandle: TSQLHStmt;
    LocatorCType: smallint;
    SourceLocator: integer;
    FromPosition: cardinal;
    ForLength: cardinal;
    TargetCType: smallint;
    DataPtr: IntPtr;
    BufferLength: integer;
    var StringLength: integer;
    var IndicatorValue: integer
  ): smallint; {$IFNDEF CLR}{$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};{$ENDIF}

  TDB2CliAPI = class (TODBCCliAPI)
  public
    SQLGetLength: _SQLGetLength;
    SQLGetSubString: _SQLGetSubString;
  end;

  IDB2Environment = interface (IODBCEnvironment)
  ['{28FCB180-3D7E-4E85-B977-0E1963BB8E30}']
    function DB2Cli: TDB2CliAPI;
  end;

  TDB2Environment = class (TODBCEnvironment, IDB2Environment)
  protected
    function GetLibName: string; override;
    function CreateAPI: TODBCCliAPI; override;
    procedure InitFunctions; override;
  public
    destructor Destroy; override;

    function DB2Cli: TDB2CliAPI;
  end;

function GetDB2Environment: IDB2Environment;

implementation

(*{$IFDEF CLR}
uses
{$IFNDEF UNIDACPRO}
  DB2CallCLR;
{$ELSE}
  DB2CallCLRUni;
{$ENDIF}
{$ENDIF}*)

var
  DB2Env: TDB2Environment;
  LockDB2Env: TCriticalSection;

function GetDB2Environment: IDB2Environment;
begin
  LockDB2Env.Enter;
  try
    if DB2Env = nil then
      DB2Env := TDB2Environment.Create(LockDB2Env);
  finally
    LockDB2Env.Leave;
  end;

  Result := DB2Env as IDB2Environment;
end;

function TDB2Environment.GetLibName: string;
begin
{$IFNDEF CLR}
  if DB2DLL = '' then
    DB2DLL := DB2DLLName;
{$ENDIF}
  Result := DB2DLL;
end;

function TDB2Environment.CreateAPI: TODBCCliAPI;
begin
  Result := TDB2CliAPI.Create(self);
end;

procedure TDB2Environment.InitFunctions;
begin
  inherited;

{$IFDEF CLR}
  //SQLGetLength := {$IFNDEF UNIDACPRO}DB2CallCLR{$ELSE}DB2CallCLRUni{$ENDIF}.SQLGetLength;
  //SQLGetSubString := {$IFNDEF UNIDACPRO}DB2CallCLR{$ELSE}DB2CallCLRUni{$ENDIF}.SQLGetSubString;
{$ELSE}
  TDB2CliAPI(FCli).SQLGetLength := GetProc('SQLGetLength');
  TDB2CliAPI(FCli).SQLGetSubString := GetProc('SQLGetSubString');
{$ENDIF}
end;

function TDB2Environment.DB2Cli: TDB2CliAPI;
begin
  Result := TDB2CliAPI(FCli);
end;

destructor TDB2Environment.Destroy;
begin
  DB2Env := nil;

  inherited;
end;

initialization
  LockDB2Env := TCriticalSection.Create;
  DB2Env := nil;

finalization
  LockDB2Env.Free;

end.

