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

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

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

    function GetConnectionParametersClass: TCRConnectionParametersClass; override;
    function GetConnectionPoolingManagerClass: TCRConnectionPoolManagerClass; override;
    function GetConnectionClass: TCRConnectionClass; override;
    function GetCommandClass: TCRCommandClass; override;
    function GetRecordSetClass: TCRRecordSetClass; override;
    function GetDataSetServiceClass: TDADataSetServiceClass; override;
    function GetLoaderClass: TCRLoaderClass; 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;

  TDBFConnectDialogService = class(TConnectDialogService)
  public
    function UseDatabaseHistory: boolean; override;
    function ServerEnabled: boolean; override;
  end;

  TDBFFormatter = 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,
  DBFClasses, DBFServices, DBFDataTypeMap;
{$ELSE}
  ODBCClassesUni, ODBCParserUni, ODBCServicesUni,
  DBFClassesUni, DBFServicesUni, DBFDataTypeMapUni;
{$ENDIF}

var
  DBFFunctions, DBFMacros: TStrValueStringList;

class function TDBFUniProvider.GetProviderName: string;
begin
  Result := 'DBF';
end;

function TDBFUniProvider.IsServerSupported: boolean;
begin
  Result := False;
end;

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

function TDBFUniProvider.IsPortSupported: boolean;
begin
  Result := False;
end;

function TDBFUniProvider.IsInOutParamSupported: boolean;
begin
  Result := False;
end;

function TDBFUniProvider.IsPoolingSupported: boolean;
begin
  Result := False;
end;

function TDBFUniProvider.GetConnectionParametersClass: TCRConnectionParametersClass;
begin
  Result := TCRConnectionParameters;
end;

function TDBFUniProvider.GetConnectionPoolingManagerClass: TCRConnectionPoolManagerClass;
begin
  Result := TCRConnectionPoolManager;
end;

function TDBFUniProvider.GetConnectionClass: TCRConnectionClass;
begin
  Result := TDBFConnection;
end;

function TDBFUniProvider.GetCommandClass: TCRCommandClass;
begin
  Result := TDBFCommand;
end;

function TDBFUniProvider.GetRecordSetClass: TCRRecordSetClass;
begin
  Result := TDBFRecordSet;
end;

function TDBFUniProvider.GetDataSetServiceClass: TDADataSetServiceClass;
begin
  Result := TCustomDBFDataSetService;
end;

function TDBFUniProvider.GetLoaderClass: TCRLoaderClass;
begin
  Result := TDBFLoader;
end;

function TDBFUniProvider.GetConnectDialogServiceClass: TConnectDialogServiceClass;
begin
  Result := TDBFConnectDialogService;
end;

function TDBFUniProvider.GetSqlFormatterClass: TUniSqlFormatterClass;
begin
  Result := TDBFFormatter;
end;

function TDBFUniProvider.GetConverterManagerClass: TConverterManagerClass;
begin
  Result := TDBFConverterManager;
end;

function TDBFUniProvider.GetConnectionOptions: TOptionsList;
begin
  if FConnectionOptions = nil then begin
    FConnectionOptions := TOptionsList.Create(GetProviderName);
    FConnectionOptions.Add(TStringOption.Create('CollatingSequence', prCollatingSequence, [TDBFConnection], '', True));
    FConnectionOptions.Add(TIntegerOption.Create('ConnectionTimeout', prConnectionTimeout, [TDBFConnection], 15, True));
    FConnectionOptions.Add(TBooleanOption.Create('UseUnicode', prUseUnicode, [TDBFConnection], False, True));
  end;
  Result := FConnectionOptions;
end;

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

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

{ TDBFConnectDialogService }

function TDBFConnectDialogService.UseDatabaseHistory: boolean;
begin
  Result := True;
end;

function TDBFConnectDialogService.ServerEnabled: boolean;
begin
  Result := False;
end;

{ TDBFFormatter }

constructor TDBFFormatter.Create;
begin
  inherited;

  FFunctions := DBFFunctions;
  FPredefinedMacros := DBFMacros;
end;

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

initialization
  UniProviders.RegisterProvider(TDBFUniProvider);

  DBFFunctions := TStrValueStringList.Create;
  DBFFunctions.Add('USER', 'USER');
  DBFFunctions.Add('CHAR_LENGTH', 'LEN(%s)');
  DBFFunctions.Add('LOCATE', 'POSSTR(%1:s, %0:s)');
  DBFFunctions.Add('SUBSTRING', 'SUBSTR(%s, %s, %s)');
  DBFFunctions.Add('CONCAT', '%s + %s');
  DBFFunctions.Add('CHAR', 'CHAR(%s)');
  DBFFunctions.Add('TRIM', 'TRIM(%s)');
  DBFFunctions.Add('TRUNCATE', 'TRUNC(%s, %s)');
  DBFFunctions.Add('CEILING', 'CEILING(%s)');
  // Date-time
  DBFFunctions.Add('CURRENT_DATE', 'CURRENT_DATE');
  DBFFunctions.Add('YEAR', 'YEAR(%s)');
  DBFFunctions.Add('MONTH', 'MONTH(%s)');
  DBFFunctions.Add('DAY', 'DAY(%s)');
  //DBFFunctions.Add('DATEADD', 'DATE(%2:s, ''%1:s %0:s'')');
  //DBFFunctions.Add('DATEDIFF', 'EXTRACT(%s FROM (%2:s - %1:s))');
  // Date-time literals
  DBFFunctions.Add('__DATE_TIME_LITERAL', '(%s)');
  DBFFunctions.Add('__DATE_LITERAL', '(%s)');
  DBFFunctions.Add('__TIME_LITERAL', '(%s)');
  // CONVERT functions
  DBFFunctions.Add('TODATE', '(%s)');
  DBFFunctions.Add('TONUMBER', '(%s)');
  DBFFunctions.Add('TOCHAR', '(%s)');

  DBFMacros := TStrValueStringList.Create;
  DBFMacros.Add('PROVIDER', 'DBF');
  DBFMacros.Add('DBF', '');
  // DataType macros
  DBFMacros.Add('DATETIME', 'DATE');
  DBFMacros.Add('DOUBLE', 'DOUBLE');
  DBFMacros.Add('VARCHAR', 'TEXT');

finalization
  UniProviders.UnRegisterProvider(TDBFUniProvider);

  DBFFunctions.Free;
  DBFMacros.Free;

end.
