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

{$IFNDEF CLR}
{$I ASEDac.inc}
{$IFDEF VER10P}
{$I ASEUniProvider.inc} 
{$ENDIF}
unit ASEUniProvider;
{$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}
  TASEUniProvider = class(TODBCUniProvider)
  public
    class function GetProviderName: string; override;

    function IsDatabaseSupported: boolean; override;
    function IsPortSupported: boolean; override;
    function IsInOutParamSupported: boolean; override;
    function IsPoolingSupported: boolean; override;

    function GetParserClass: TSQLParserClass; 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 GetMetaDataClass: TCRMetaDataClass; override;
    function GetConnectDialogServiceClass: TConnectDialogServiceClass; override;
    function GetSqlFormatterClass: TUniSqlFormatterClass; override;
    function GetConverterManagerClass: TConverterManagerClass; override;

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

  TASEConnectDialogService = class(TConnectDialogService)
  public
  end;

  TASEFormatter = 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,
  ASEClasses, ASEServices, ASEParser, ASEConnectionPool, ASEDataTypeMap;
{$ELSE}
  ODBCClassesUni, ODBCParserUni, ODBCServicesUni,
  ASEClassesUni, ASEServicesUni, ASEParserUni, ASEConnectionPoolUni, ASEDataTypeMapUni;
{$ENDIF}

var
  ASEFunctions, ASEMacros: TStrValueStringList;

class function TASEUniProvider.GetProviderName: string;
begin
  Result := 'ASE';
end;

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

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

function TASEUniProvider.IsInOutParamSupported: boolean;
begin
  Result := True;
end;

function TASEUniProvider.IsPoolingSupported: boolean;
begin
  Result := True;
end;

function TASEUniProvider.GetParserClass: TSQLParserClass;
begin
  Result := TASEParser;
end;

function TASEUniProvider.GetConnectionParametersClass: TCRConnectionParametersClass;
begin
  Result := TASEConnectionParameters;
end;

function TASEUniProvider.GetConnectionPoolingManagerClass: TCRConnectionPoolManagerClass;
begin
  Result := TASEConnectionPoolManager;
end;

function TASEUniProvider.GetConnectionClass: TCRConnectionClass;
begin
  Result := TASEConnection;
end;

function TASEUniProvider.GetServerEnumeratorClass: TCRServerEnumeratorClass;
begin
  Result := TASEServerEnumerator;
end;

function TASEUniProvider.GetTransactionClass: TCRTransactionClass;
begin
  Result := TASETransaction;
end;

function TASEUniProvider.GetCommandClass: TCRCommandClass;
begin
  Result := TASECommand;
end;

function TASEUniProvider.GetRecordSetClass: TCRRecordSetClass;
begin
  Result := TASERecordSet;
end;

function TASEUniProvider.GetDataSetServiceClass: TDADataSetServiceClass;
begin
  Result := TCustomASEDataSetService;
end;

function TASEUniProvider.GetScriptProcessorClass: TDAScriptProcessorClass;
begin
  Result := TASEScriptProcessor;
end;

function TASEUniProvider.GetLoaderClass: TCRLoaderClass;
begin
  Result := TASELoader;
end;

function TASEUniProvider.GetMetaDataClass: TCRMetaDataClass;
begin
  Result := TASEMetaData;
end;

function TASEUniProvider.GetConnectDialogServiceClass: TConnectDialogServiceClass;
begin
  Result := TASEConnectDialogService;
end;

function TASEUniProvider.GetSqlFormatterClass: TUniSqlFormatterClass;
begin
  Result := TASEFormatter;
end;

function TASEUniProvider.GetConverterManagerClass: TConverterManagerClass;
begin
  Result := TASEConverterManager;
end;

function TASEUniProvider.GetConnectionOptions: TOptionsList;
begin
  if FConnectionOptions = nil then begin
    FConnectionOptions := TOptionsList.Create(GetProviderName);
    FConnectionOptions.Add(TIntegerOption.Create('ConnectionTimeout', prConnectionTimeout, [TASEConnection], 15, True));
    FConnectionOptions.Add(TBooleanOption.Create('UseUnicode', prUseUnicode, [TASEConnection], False, True));
    FConnectionOptions.Add(TBooleanOption.Create('AnsiNull', prAnsiNull, [TASEConnection], True, True));
    FConnectionOptions.Add(TStringOption.Create('ApplicationName', prApplicationName, [TASEConnection], '', True));
    FConnectionOptions.Add(TEnumeratorOption.Create('SelectMethod', prSelectMethod, [TASEConnection], Variant(smDirect), TypeInfo(TASESelectMethod), True));
    FConnectionOptions.Add(TEnumeratorOption.Create('EncryptPassword', prEncryptPassword, [TASEConnection], Variant(epDisable), TypeInfo(TASEEncryptPassword)));
    FConnectionOptions.Add(TEnumeratorOption.Create('PrepareMethod', prPrepareMethod, [TASEConnection], Variant(pmPartial), TypeInfo(TASEPrepareMethod)));
    FConnectionOptions.Add(TBooleanOption.Create('DetectFieldsOnPrepare', prDetectFieldsOnPrepare, [TASEConnection], True));
  end;
  Result := FConnectionOptions;
end;

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

function TASEUniProvider.GetDataSetOptions: TOptionsList;
begin
  if FDataSetOptions = nil then begin
    FDataSetOptions := TOptionsList.Create(GetProviderName);
    FDataSetOptions.Add(TIntegerOption.Create('CommandTimeout', prCommandTimeout, [TASERecordSet], 0));
    FDataSetOptions.Add(TBooleanOption.Create('ExtendedFieldsInfo', prExtendedFieldsInfo, [TASERecordSet], True));
    FDataSetOptions.Add(TBooleanOption.Create('FetchAll', prFetchAll, [TASERecordSet], False));
  end;
  Result := FDataSetOptions;
end;

{ TASEFormatter }

constructor TASEFormatter.Create;
begin
  inherited;

  FFunctions := ASEFunctions;
  FPredefinedMacros := ASEMacros;
end;

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

initialization
  UniProviders.RegisterProvider(TASEUniProvider);

  ASEFunctions := TStrValueStringList.Create;
  ASEFunctions.Add('USER', 'USER');
  ASEFunctions.Add('CHAR_LENGTH', 'CHAR_LENGTH(%s)');
  ASEFunctions.Add('LOCATE', 'CHARINDEX(%s, %s)');
  ASEFunctions.Add('SUBSTRING', 'SUBSTRING(%s, %s, %s)');
  ASEFunctions.Add('CONCAT', '%s + %s');
  ASEFunctions.Add('CHAR', 'CHAR(%s)');
  ASEFunctions.Add('TRIM', 'LTRIM(RTRIM(%s))');
  ASEFunctions.Add('TRUNCATE', 'ROUND(%s, %s)');
  ASEFunctions.Add('CEILING', 'CEILING(%s)');
  // Date-time
  ASEFunctions.Add('CURRENT_DATE', 'GETDATE');
  ASEFunctions.Add('YEAR', 'YEAR(%s)');
  ASEFunctions.Add('MONTH', 'MONTH(%s)');
  ASEFunctions.Add('DAY', 'DAY(%s)');
  ASEFunctions.Add('DATEADD', 'DATEADD(%s, %s, %s)');
  ASEFunctions.Add('DATEDIFF', 'DATEDIFF(%s, %s, %s)');
  // Date-time literals
  ASEFunctions.Add('__DATE_TIME_LITERAL', 'CONVERT(DATETIME, %s)');
  ASEFunctions.Add('__DATE_LITERAL', 'CONVERT(DATETIME, %s)');
  ASEFunctions.Add('__TIME_LITERAL', 'CONVERT(DATETIME, %s)');
  // CONVERT functions
  ASEFunctions.Add('TODATE', 'CONVERT(DATETIME, %s)');
  ASEFunctions.Add('TONUMBER', 'CONVERT(FLOAT(53), %s)');
  ASEFunctions.Add('TOCHAR', 'CONVERT(VARCHAR, %s, 20)');

  ASEMacros := TStrValueStringList.Create;
  ASEMacros.Add('PROVIDER', 'ASE');
  ASEMacros.Add('ASE', '');
  // DataType macros
  ASEMacros.Add('DATETIME', 'DATETIME');
  ASEMacros.Add('DOUBLE', 'FLOAT(53)');
  ASEMacros.Add('VARCHAR', 'VARCHAR');

finalization
  UniProviders.UnRegisterProvider(TASEUniProvider);

  ASEFunctions.Free;
  ASEMacros.Free;

end.
