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

{$IFNDEF CLR}
{$I DB2Dac.inc}
{$IFDEF VER10P}
{$I DB2UniProvider.inc}
{$ENDIF}
unit DB2UniProvider;
{$ENDIF}

interface

uses
  SysUtils, Classes, Variants, DB, CRAccess, CRConnectionPool, MemData,
  {$IFNDEF FPC}MemDS{$ELSE}MemDataSet{$ENDIF}, DBAccess,
  CRTypes, CRParser, CRDataTypeMap,
  DAScript, DADump, UniProvider, ODBCUniProvider;

type

{$IFDEF VER16P}
  [ComponentPlatformsAttribute(pidWin32 or pidWin64)]
{$ENDIF}
  TDB2UniProvider = class(TODBCUniProvider)
  public
    class function GetProviderName: string; override;

    function IsDatabaseSupported: boolean; override;
    function IsPortSupported: boolean; override;
    function GetConnectionParametersClass: TCRConnectionParametersClass; override;
    function GetConnectionPoolingManagerClass: TCRConnectionPoolManagerClass; override;
    function GetConnectionClass: TCRConnectionClass; override;
    function GetServerEnumeratorClass: TCRServerEnumeratorClass; override;
    function GetTransactionClass: TCRTransactionClass; override;
    function GetCommandClass: TCRCommandClass; override;
    function GetRecordSetClass: TCRRecordSetClass; override;
    function GetDataSetServiceClass: TDADataSetServiceClass; override;
    function GetScriptProcessorClass: TDAScriptProcessorClass; override;
    function GetLoaderClass: TCRLoaderClass; override;
    function GetSqlFormatterClass: TUniSqlFormatterClass; override;
    function GetConverterManagerClass: TConverterManagerClass; override;

    function GetConnectionOptions: TOptionsList; override;
    function GetSQLOptions: TOptionsList; override;
    function GetDataSetOptions: TOptionsList; override;
  end;

  TDB2Formatter = class(TUniSqlFormatter)
  protected
  public
    constructor Create; override;
  end;

{$IFNDEF FPC}
procedure RegisterComponent;
{$ELSE}
procedure Register;
{$ENDIF}

implementation

uses
  DAConsts, UniConsts,
{$IFNDEF UNIDACPRO}
  ODBCClasses, ODBCParser, ODBCServices,
  DB2Classes, DB2Services, DB2ConnectionPool, DB2DataTypeMap;
{$ELSE}
  ODBCClassesUni, ODBCParserUni, ODBCServicesUni,
  DB2ClassesUni, DB2ServicesUni, DB2ConnectionPoolUni, DB2DataTypeMapUni;
{$ENDIF}

var
  DB2Functions, DB2Macros: TStrValueStringList;

class function TDB2UniProvider.GetProviderName: string;
begin
  Result := 'DB2';
end;

function TDB2UniProvider.IsDatabaseSupported: boolean;
begin
  Result := True;
end;

function TDB2UniProvider.IsPortSupported: boolean;
begin
  Result := True;
end;

function TDB2UniProvider.GetConnectionParametersClass: TCRConnectionParametersClass;
begin
  Result := TDB2ConnectionParameters;
end;

function TDB2UniProvider.GetConnectionPoolingManagerClass: TCRConnectionPoolManagerClass;
begin
  Result := TDB2ConnectionPoolManager;
end;

function TDB2UniProvider.GetConnectionClass: TCRConnectionClass;
begin
  Result := TDB2Connection;
end;

function TDB2UniProvider.GetServerEnumeratorClass: TCRServerEnumeratorClass;
begin
  Result := TDB2ServerEnumerator;
end;

function TDB2UniProvider.GetTransactionClass: TCRTransactionClass;
begin
  Result := TDB2Transaction;
end;

function TDB2UniProvider.GetCommandClass: TCRCommandClass;
begin
  Result := TDB2Command;
end;

function TDB2UniProvider.GetRecordSetClass: TCRRecordSetClass;
begin
  Result := TDB2RecordSet;
end;

function TDB2UniProvider.GetDataSetServiceClass: TDADataSetServiceClass;
begin
  Result := TCustomDB2DataSetService;
end;

function TDB2UniProvider.GetScriptProcessorClass: TDAScriptProcessorClass;
begin
  Result := TDB2ScriptProcessor;
end;

function TDB2UniProvider.GetLoaderClass: TCRLoaderClass;
begin
  Result := TDB2Loader;
end;

function TDB2UniProvider.GetSqlFormatterClass: TUniSqlFormatterClass;
begin
  Result := TDB2Formatter;
end;

function TDB2UniProvider.GetConverterManagerClass: TConverterManagerClass;
begin
  Result := TDB2ConverterManager;
end;

function TDB2UniProvider.GetConnectionOptions: TOptionsList;
begin
  if FConnectionOptions = nil then begin
    FConnectionOptions := TOptionsList.Create(GetProviderName);
    FConnectionOptions.Add(TIntegerOption.Create('ConnectionTimeout', prConnectionTimeout, [TDB2Connection, TDB2ConnectionParameters], 15, True));
    FConnectionOptions.Add(TStringOption.Create('FunctionPath', prFunctionPath, [TDB2Connection, TDB2ConnectionParameters], '', True));
    FConnectionOptions.Add(TStringOption.Create('Schema', prSchema, [TDB2Connection, TDB2ConnectionParameters], '', True));
    FConnectionOptions.Add(TBooleanOption.Create('UseUnicode', prUseUnicode, [TDB2Connection], False, True));
  end;
  Result := FConnectionOptions;
end;

function TDB2UniProvider.GetSQLOptions: TOptionsList;
begin
  if FSQLOptions = nil then begin
    FSQLOptions := TOptionsList.Create(GetProviderName);
    FSQLOptions.Add(TIntegerOption.Create('CommandTimeout', prCommandTimeout, [TDB2Command], 0));
  end;
  Result := FSQLOptions;
end;

function TDB2UniProvider.GetDataSetOptions: TOptionsList;
begin
  if FDataSetOptions = nil then begin
    FDataSetOptions := TOptionsList.Create(GetProviderName);
    FDataSetOptions.Add(TIntegerOption.Create('CommandTimeout', prCommandTimeout, [TDB2RecordSet], 0));
    FDataSetOptions.Add(TBooleanOption.Create('ExtendedFieldsInfo', prExtendedFieldsInfo, [TDB2RecordSet], True));
    FDataSetOptions.Add(TStringOption.Create('KeySequence', prKeySequence, [TCustomDB2DataSetService], ''));
    FDataSetOptions.Add(TBooleanOption.Create('FetchAll', prFetchAll, [TDB2RecordSet], False));
    FDataSetOptions.Add(TEnumeratorOption.Create('SequenceMode', prSequenceMode, [TCustomDB2DataSetService], Variant(smPost), TypeInfo(TDB2SequenceMode)));
  end;
  Result := FDataSetOptions;
end;

{ TDB2Formatter }

constructor TDB2Formatter.Create;
begin
  inherited;

  FFunctions := DB2Functions;
  FPredefinedMacros := DB2Macros;
end;

{$IFNDEF FPC}
procedure RegisterComponent;
{$ELSE}
procedure Register;
{$ENDIF}
begin
  RegisterComponents('UniDAC Providers', [TDB2UniProvider]);
end;

initialization
  UniProviders.RegisterProvider(TDB2UniProvider);

  DB2Functions := TStrValueStringList.Create;
  DB2Functions.Add('USER', 'USER');
  DB2Functions.Add('CHAR_LENGTH', 'LENGTH(%s)');
  DB2Functions.Add('LOCATE', 'POSSTR(%1:s, %0:s)');
  DB2Functions.Add('SUBSTRING', 'SUBSTR(%s, %s, %s)');
  DB2Functions.Add('CONCAT', '%s || %s');
  DB2Functions.Add('CHAR', 'CHR(%s)');
  DB2Functions.Add('TRIM', 'TRIM(%s)');
  DB2Functions.Add('TRUNCATE', 'TRUNCATE(%s, %s)');
  DB2Functions.Add('CEILING', 'CEILING(%s)');
  // Date-time
  DB2Functions.Add('CURRENT_DATE', 'CURRENT_DATE');
  DB2Functions.Add('YEAR', 'YEAR(%s)');
  DB2Functions.Add('MONTH', 'MONTH(%s)');
  DB2Functions.Add('DAY', 'DAY(%s)');
  //DB2Functions.Add('DATEADD', 'DATE(%2:s, ''%1:s %0:s'')');
  //DB2Functions.Add('DATEDIFF', 'EXTRACT(%s FROM (%2:s - %1:s))');
  // Date-time literals
  DB2Functions.Add('__DATE_TIME_LITERAL', 'CAST(%s AS TIMESTAMP)');
  DB2Functions.Add('__DATE_LITERAL', 'CAST(%s AS DATE)');
  DB2Functions.Add('__TIME_LITERAL', 'CAST(%s AS TIME)');
  // CONVERT functions
  DB2Functions.Add('TODATE', 'CAST(%s AS TIMESTAMP)');
  DB2Functions.Add('TONUMBER', 'CAST(%s AS DOUBLE)');
  DB2Functions.Add('TOCHAR', 'CAST(%s AS VARCHAR)');

  DB2Macros := TStrValueStringList.Create;
  DB2Macros.Add('PROVIDER', 'DB2');
  DB2Macros.Add('DB2', '');
  // DataType macros
  DB2Macros.Add('DATETIME', 'TIMESTAMP');
  DB2Macros.Add('DOUBLE', 'DOUBLE');
  DB2Macros.Add('VARCHAR', 'VARCHAR');

finalization
  UniProviders.UnRegisterProvider(TDB2UniProvider);

  DB2Functions.Free;
  DB2Macros.Free;

end.
