{-------------------------------------------------------------------------------} { Data Abstract Library - Driver Library } { } { compiler: Delphi 6 and up } { platform: Win32 } { } { (c)opyright RemObjects Software. all rights reserved. } { } { Using this code requires a valid license of the Data Abstract } { which can be obtained at http://www.remobjects.com. } { } { Based on AnyDAC Driver by Dmitry Arefiev (www.da-soft.com) } {-------------------------------------------------------------------------------} {$IFDEF MSWINDOWS} {$I ..\DataAbstract.inc} {$ELSE} {$I ../DataAbstract.inc} {$ENDIF} {$I uAD.inc} unit uDAAnyDACDriver; interface uses DB, Classes, uROClasses, uDAEngine, uDAInterfaces, uDAInterfacesEx, uDAUtils, uDAOracleInterfaces, uDAMySQLInterfaces, uDAADOInterfaces, uDAIBInterfaces, uDADB2Interfaces, uDASybaseInterfaces, uADStanIntf, uADStanOption, uADDatSManager, uADPhysIntf, uADCompClient {$IFDEF AnyDAC_MONITOR} ,uADMoniBase, uADMoniCustom {$ENDIF} ; const C_DriverMajVer = 3; C_DriverMinVer = 50; type TDAAnyDACDriverType = TADRDBMSKind; { TDAAnyDACDriver } TDAAnyDACDriver = class(TDADriverReference) end; { TDAEAnyDACDriver } TDAEAnyDACDriver = class(TDAEDriver, IDADriver40) private FConnectionDefs: TStringList; FConnectionDefIndex: Integer; {$IFDEF AnyDAC_MONITOR} FMonitor: TADMoniCustomClientLink; FTraceCallback: TDALogTraceEvent; procedure DoTrace(ASender: TADMoniClientLinkBase; const AClassName, AObjName, AMessage: String); {$ENDIF} function LookupConnectionString(const AConnectionString: String; AParsedParams: TStringList): String; protected {$IFDEF AnyDAC_MONITOR} procedure DoSetTraceOptions(TraceActive: Boolean; TraceOptions: TDATraceOptions; Callback: TDALogTraceEvent); override; {$ENDIF} function GetConnectionClass: TDAEConnectionClass; override; // IDADriver procedure Initialize; override; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} procedure Finalize; override; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} function GetDriverID: string; override; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} function GetDescription: string; override; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} function GetMajVersion: byte; override; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} function GetMinVersion: byte; override; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} // IDADriver40 procedure GetAuxDrivers(out List: IROStrings); override; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} procedure GetAuxParams(const AuxDriver: string; out List: IROStrings); override; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} function GetAvailableDriverOptions: TDAAvailableDriverOptions; override; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} function GetDefaultConnectionType(const AuxDriver: string): string; override; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} function GetProviderDefaultCustomParameters(Provider: string): string; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} end; { TDAEAnyDACConnection } TDAEAnyDACConnection = class(TDAEConnection, IDAConnection, IDAADOConnection, IDAInterbaseConnection, IDAIBTransactionAccess, IDAIBConnectionProperties, IDAOracleConnection, IDAMySQLConnection, IDADB2Connection, IDASybaseConnection, IDAConnectionModelling, IDACanQueryDatabaseNames, IDAFileBasedDatabase, IDAUseGenerators, IDACanQueryGeneratorsNames, IDATestableObject) private FADConnection: TADConnection; fDriverType: TDAAnyDACDriverType; fMSSQLSchemaEnabled: Boolean; fBiDirectionalDataSets: Boolean; fDirectMode: Boolean; FDataTypeSchema: String; FMySQLVersion: integer; FDataBaseName: string; procedure DoGetNames(AList: IROStrings; AObjectType: TDAObjecttype); procedure Native_DoGetTableFields(aTableName: string; out Fields: TDAFieldCollection); procedure Native_DoGetForeignKeys(ForeignKeys: TDADriverForeignKeyCollection); function Native_DoGetLastAutoInc(const GeneratorName: string): integer; function Native_GetQuoteChars: TDAQuoteCharArray; function GetAnyDACPhysConnection:IADPhysConnection; procedure MapAsFIB; function GetMySQLVersion: integer; function GetDataBaseName: string; protected // IInterface function QueryInterface(const IID: TGUID; out Obj): HResult; override; stdcall; // TDAEConnection function CreateCustomConnection: TCustomConnection; override; function CreateMacroProcessor: TDASQLMacroProcessor; override; function GetDatasetClass: TDAEDatasetClass; override; function GetStoredProcedureClass: TDAEStoredProcedureClass; override; procedure DoApplyConnectionString(aConnStrParser: TDAConnectionStringParser; aConnectionObject: TCustomConnection); override; procedure SetupDataset(ADataSet: TADRdbmsDataSet; AFetchMeta: Boolean); procedure SetupOptions(AOptions: IADStanOptions; AFetchMeta: Boolean); function DoBeginTransaction: integer; override; procedure DoCommitTransaction; override; procedure DoRollbackTransaction; override; function DoGetInTransaction: boolean; override; procedure DoGetTableNames(out List: IROStrings); override; procedure DoGetViewNames(out List: IROStrings); override; procedure DoGetStoredProcedureNames(out List: IROStrings); override; procedure DoGetTableFields(const aTableName: string; out Fields: TDAFieldCollection); override; procedure DoGetStoredProcedureParams(const aStoredProcedureName: string; out Params: TDAParamCollection); override; procedure DoGetForeignKeys(out ForeignKeys: TDADriverForeignKeyCollection); override; function DoGetLastAutoInc(const GeneratorName: string): integer; override; // IDATestObject // nothing // IDAConnection function GetSPSelectSyntax(AHasArguments: Boolean): string; override; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} function GetQuoteChars: TDAQuoteCharArray; override; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} function IdentifierNeedsQuoting(const AIdentifier: string): boolean; override; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} // IDAADOConnection function GetProviderName: string; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} function GetProviderType: TDAOleDBProviderType; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} function GetCommandTimeout: Integer; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} procedure SetCommandTimeout(const Value: Integer); {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} // IDAInterbaseConnection // nothing // IDAIBTransactionAccess function GetTransaction: TObject; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} // IDAIBConnectionProperties function GetRole: string; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} procedure SetRole(const Value: string); {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} function GetSQLDialect: integer; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} procedure SetSQLDialect(Value: integer); {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} function GetCharset: string; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} procedure SetCharset(const Value: string); {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} procedure Commit; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} procedure CommitRetaining; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} procedure Rollback; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} procedure RollbackRetaining; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} // IDAOracleConnection // nothing // IDAConnectionModelling function FieldToDeclaration(aField: TDAField): string; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} function BuildCreateTableSQL(aDataSet: TDADataSet; const aOverrideName: string = ''): string; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} procedure CreateTable(aDataSet: TDADataSet; const aOverrideName: string = ''); {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} // IDACanQueryDatabaseNames function GetDatabaseNames: IROStrings; // IDAFileBasedDatabase function GetFileExtensions: IROStrings; // IDADirectoryBasedDatabase // nothing // IDAUseGenerators function GetNextAutoinc(const GeneratorName: string): integer; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} // IDACanQueryGeneratorsNames function GetGeneratorNames: IROStrings; end; { TDAEAnyDACQuery } TDAEAnyDACQuery = class(TDAEDataset, IDAMustSetParams) protected function CreateDataset(aConnection: TDAEConnection): TDataset; override; // TDAEDataset procedure DoPrepare(AValue: boolean); override; function DoExecute: integer; override;{$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} function DoGetSQL: string; override; procedure DoSetSQL(const AValue: string); override; procedure ClearParams; override; // IDAMustSetParams procedure SetParamValues(AParams: TDAParamCollection); override; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} procedure GetParamValues(AParams: TDAParamCollection); override; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} end; { TDAEAnyDACStoredProcedure } TDAEAnyDACStoredProcedure = class(TDAEStoredProcedure, IDAMustSetParams) protected function CreateDataset(aConnection: TDAEConnection): TDataset; override; // TDAEDataset procedure RefreshParams; override; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} function GetStoredProcedureName: string; override; procedure SetStoredProcedureName(const Name: string); override; function DoExecute: integer; override; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} function Execute: integer; override; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} // IDAMustSetParams procedure SetParamValues(AParams: TDAParamCollection); override; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} procedure GetParamValues(AParams: TDAParamCollection); override; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} end; TDAEAnyDACNativeDatabaseAccess = class; { TDAEAnyDACNativeField } TDAEAnyDACNativeField = class(TInterfacedObject, IDANativeField) private FCol: TADDatSColumn; FCmd: IADPhysCommand; fParent: TDAEAnyDACNativeDatabaseAccess; protected function GetNativeObject: TObject; function isTFieldCompatible: Boolean; function GetFieldName: string; function GetDataType: TFieldType; function GetSize: integer; function GetDecimalPrecision: Integer; procedure SetDecimalPrecision(Value: integer); function GetDecimalScale: Integer; procedure SetDecimalScale(Value: integer); procedure SetDataType(Value: TFieldType); function GetFieldIndex: integer; function GetValue: Variant; function IsNull: Boolean; public constructor Create(ACol: TADDatSColumn; const ACmd: IADPhysCommand; AParent: TDAEAnyDACNativeDatabaseAccess); end; { TDAEAnyDACNativeDatabaseAccess } TDAEAnyDACNativeDatabaseAccessFlags = set of (nfActive, nfBOF, nfEOF); TDAEAnyDACNativeDatabaseAccess = class(TObject, IInterface, IDANativeDatabaseAccess) private FCmd: IADPhysCommand; FTab: TADDatSTable; FFlags: TDAEAnyDACNativeDatabaseAccessFlags; FRowIndex: Integer; FRowsPurged: Integer; FBuffs: array of Pointer; procedure First; procedure CheckActive; procedure CheckBidir; function LocateRecord(const KeyFields: string; const KeyValues: Variant; Options: TLocateOptions; AChangePos: Boolean): Integer; function IsNull(Index: integer): Boolean; protected // IInterface function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; // IDANativeDatabaseAccess procedure ClearFieldDefs; function GetRecordCount: Integer; function GetBOF: Boolean; function GetEOF: Boolean; function GetActive: Boolean; procedure SetActive(const aValue: Boolean); procedure Next; function Locate(const KeyFields: string; const KeyValues: Variant; Options: TLocateOptions): Boolean; function Lookup(const KeyFields: string; const KeyValues: Variant; const ResultFields: string): Variant; function GetFieldName(Index: Integer): string; procedure DisableControls; procedure EnableControls; function GetIsEmpty: boolean; procedure FreeBookmark(Bookmark: TBookmark); function GetBookMark: pointer; procedure GotoBookmark(Bookmark: TBookmark); function GetState: TDatasetState; function ControlsDisabled: Boolean; procedure Prepare(const AValue: Boolean); function GetFields(Index: integer): IDANativeField; function FieldCount: Integer; function FindField(const FieldName: string): IDANativeField; function IsTDatasetCompatible: Boolean; function GetNativeFieldData(Index: Integer; var Data: pointer; var DataSize: cardinal):Boolean; function GetNativeFieldValue(Index: Integer): Variant; function CanFreeNativeFieldData: Boolean; public Constructor Create(ADAEConnection: TDAEAnyDACConnection); destructor Destroy; override; end; { TDAEAnyDACQueryNative } TDAEAnyDACQueryNative = class(TDAEDataset, IDAMustSetParams) private function GetNativeObject: TDAEAnyDACNativeDatabaseAccess; protected function CreateDataset(aConnection: TDAEConnection): TDataset; override; function CreateNativeObject(aConnection: TDAEConnection): TObject; override; function CreateNativeDatabaseAccess: IDANativeDatabaseAccess; override; // TDAEDataset procedure DoPrepare(AValue: boolean); override; function DoExecute: integer; override; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} function DoGetSQL: string; override; procedure DoSetSQL(const AValue: string); override; procedure ClearParams; override; // IDAMustSetParams procedure SetParamValues(AParams: TDAParamCollection); override; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} procedure GetParamValues(AParams: TDAParamCollection); override; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} public property NativeObject: TDAEAnyDACNativeDatabaseAccess read GetNativeObject; end; { TDAEAnyDACStoredProcedureNative } TDAEAnyDACStoredProcedureNative = class(TDAEStoredProcedure, IDAMustSetParams) private function GetNativeObject: TDAEAnyDACNativeDatabaseAccess; protected function CreateDataset(aConnection: TDAEConnection): TDataset; override; function CreateNativeObject(aConnection: TDAEConnection): TObject; override; function CreateNativeDatabaseAccess: IDANativeDatabaseAccess; override; // TDAEDataset procedure RefreshParams; override; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} function GetStoredProcedureName: string; override; procedure SetStoredProcedureName(const Name: string); override; function DoExecute: integer; override; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} function Execute: integer; override; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} // IDAMustSetParams procedure SetParamValues(AParams: TDAParamCollection); override; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} procedure GetParamValues(AParams: TDAParamCollection); override; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF} public property NativeObject: TDAEAnyDACNativeDatabaseAccess read GetNativeObject; end; procedure Register; function GetDriverObject: IDADriver; stdcall; function AnyDACDriverIdToAnyDACDriverType(Provider: string): TDAAnyDACDriverType; implementation uses {$IFDEF FPC} LResources, {$ENDIF} {$IFDEF MSWINDOWS} Windows, {$ENDIF} SysUtils, Variants, FmtBCD, uDADriverManager, uDARes, uDAHelpers, uROBinaryHelpers, uADStanParam, uADStanConst, uADStanFactory, uADGUIxConsoleWait, uADPhysManager, uADPhysODBC, uADPhysOracl, uADPhysMySQL, uADPhysMSSQL, uADPhysMSAcc, uADPhysDB2, uADPhysASA, uADPhysIB, uADPhysADS, uADStanUtil {$IFDEF AnyDAC_D11} , uADPhysTDBX {$ELSE} {$IFDEF AnyDAC_D6} , uADPhysDbExp {$ENDIF} {$ENDIF}; {$IFNDEF FPC} {$R DataAbstract_AnyDACDriver_Glyphs.res} {$ENDIF} {$IFDEF DataAbstract_SchemaModelerOnly} {$INCLUDE ..\DataAbstract_SchemaModelerOnly.inc} {$ENDIF DataAbstract_SchemaModelerOnly} {------------------------------------------------------------------------------} { Generic procedures } {------------------------------------------------------------------------------} function AnyDACDriverIdToAnyDACDriverType(Provider: string): TDAAnyDACDriverType; var FConnectionIntf: IADPhysConnection; oConMeta: IADPhysConnectionMetadata; begin Result := mkUnknown; if Provider = '' then Exit; try with TADConnection.Create(nil) do try ResultConnectionDef.DriverID := Provider; ADPhysManager.CreateConnection(ResultConnectionDef, FConnectionIntf); if FConnectionIntf <> nil then begin FConnectionIntf.CreateMetadata(oConMeta); Result := oConMeta.Kind; end; finally Free; end; except // hide an exception end; end; {------------------------------------------------------------------------------} procedure SetADParamValuesFromDA(ADAParams: TDAParamCollection; AADParams: TADParams; ASetType: Boolean); var i: integer; oDAPar: TDAParam; oADPar: TADParam; begin for i := 0 to AADParams.Count - 1 do begin oADPar := AADParams[i]; oDAPar := ADAParams.ParamByName(oADPar.Name); oADPar.ParamType := TParamType(oDAPar.ParamType); if oDAPar.ParamType in [daptInput, daptInputOutput, daptUnknown] then if oDAPar.DataType in [datBlob, datMemo, datWideMemo] then begin if ASetType then if oDAPar.BlobType = dabtUnknown then case oDAPar.DataType of datMemo: oADPar.DataType := ftMemo; datBlob: oADPar.DataType := ftBlob; datWideMemo: oADPar.DataType := {$IFDEF AnyDAC_D10} ftWideMemo {$ELSE} ftFmtMemo {$ENDIF}; end else oADPar.DataType := BlobTypeMappings[oDAPar.BlobType]; if VarIsEmpty(oDAPar.Value) or VarIsNull(oDAPar.Value) then oADPar.Clear else oADPar.AsBlob := VariantBinaryToString(oDAPar.Value); end else begin if ASetType then oADPar.DataType := DATypeToVCLType(oDAPar.DataType); if VarIsEmpty(oDAPar.Value) or VarIsNull(oDAPar.Value) then oADPar.Clear else oADPar.Value := oDAPar.Value; end else if ASetType then begin oADPar.DataType := DATypeToVCLType(oDAPar.DataType); oADPar.Size := oDAPar.Size; oADPar.Precision := oDAPar.DecimalPrecision; oADPar.NumericScale := oDAPar.DecimalScale; end; end; end; {------------------------------------------------------------------------------} procedure GetDAParamValuesFromAD(Params: TDAParamCollection; AADParams: TADParams); var i: integer; oDAPar: TDAParam; oADPar: TADParam; begin if not Assigned(AADParams) then Exit; for i := 0 to AADParams.Count - 1 do begin oADPar := AADParams[i]; oDAPar := Params.ParamByName(oADPar.Name); if oDAPar.ParamType in [daptOutput, daptInputOutput, daptResult] then oDAPar.Value := oADPar.Value; end; end; {------------------------------------------------------------------------------} function MapAD2DADataType(AADDataType: TADDataType; out ABlobType: TDABlobType): TDADataType; begin ABlobType := dabtUnknown; case AADDataType of dtUnknown: Result := datUnknown; dtBoolean: Result := datBoolean; dtSByte: Result := datShortInt; dtInt16: Result := datSmallInt; dtInt32: Result := datInteger; dtInt64: Result := datLargeInt; dtByte: Result := datByte; dtUInt16: Result := datWord; dtUInt32: Result := datCardinal; dtUInt64: Result := datLargeUInt; dtDouble: Result := datFloat; dtCurrency: Result := datFloat; // Double dtBCD: Result := datCurrency; // Currency dtFmtBCD: Result := datDecimal; // TBcd dtDateTime: Result := datDateTime; dtTime: Result := datDateTime; dtDate: Result := datDateTime; dtDateTimeStamp: Result := datDateTime; dtAnsiString: Result := datString; dtWideString: Result := datWideString; dtByteString: Result := datString; dtBlob: begin Result := datBlob; ABlobType := dabtBlob; end; dtMemo: begin Result := datMemo; ABlobType := dabtMemo; end; dtWideMemo: begin Result := datWideMemo; ABlobType := dabtMemo; end; dtHBlob: begin Result := datBlob; ABlobType := dabtOraBlob; end; dtHMemo: begin Result := datMemo; ABlobType := dabtOraClob; end; dtWideHMemo: begin Result := datWideMemo; ABlobType := dabtOraClob; end; dtHBFile: begin Result := datBlob; ABlobType := dabtOraBlob; end; dtGUID: Result := datGuid; else raise Exception.CreateFmt('AnyDAC data type [%s] is not supported by DataAbstract', [C_AD_DataTypeNames[AADDataType]]); end; end; {------------------------------------------------------------------------------} { TDAEAnyDACDriver } {------------------------------------------------------------------------------} function TDAEAnyDACDriver.GetAvailableDriverOptions: TDAAvailableDriverOptions; begin result := [doAuxDriver, doServerName, doDatabaseName, doLogin, doCustom]; end; {------------------------------------------------------------------------------} function TDAEAnyDACDriver.GetConnectionClass: TDAEConnectionClass; begin result := TDAEAnyDACConnection; end; {------------------------------------------------------------------------------} function TDAEAnyDACDriver.GetDriverID: string; begin result := 'AnyDAC'; end; {------------------------------------------------------------------------------} function TDAEAnyDACDriver.GetDescription: string; begin result := 'RemObjects AnyDAC v ' + C_AD_Version + ' Driver' {$IFDEF DataAbstract_SchemaModelerOnly} + SchemaModelerOnly{$ENDIF}; end; {------------------------------------------------------------------------------} function TDAEAnyDACDriver.GetMajVersion: byte; begin Result := C_DriverMajVer; end; {------------------------------------------------------------------------------} function TDAEAnyDACDriver.GetMinVersion: byte; begin Result := C_DriverMinVer; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACDriver.GetAuxDrivers(out List: IROStrings); begin List := NewROStrings; ADManager.GetDriverNames(List.Strings); end; {------------------------------------------------------------------------------} function TDAEAnyDACDriver.GetProviderDefaultCustomParameters(Provider: string): string; begin Result := ''; case AnyDACDriverIdToAnyDACDriverType(Provider) of mkOracle: Result := S_AD_ConnParam_Common_OSAuthent + '=No;'; mkMSSQL: Result := 'Schemas=1;Integrated Security=SSPI;'; mkMySQL: Result := MYSQL_GetDefaultCustomParameters; mkInterbase: Result := S_AD_ConnParam_IB_Protocol + '=TCPIP;'; end; end; {------------------------------------------------------------------------------} function TDAEAnyDACDriver.GetDefaultConnectionType(const AuxDriver: string): string; begin case AnyDACDriverIdToAnyDACDriverType(AuxDriver) of mkOracle: Result := Oracle_DriverType; mkMSSQL: Result := MSSQL_DriverType; mkMSAccess: Result := Access_DriverType; mkMySQL: Result := MySQL_DriverType; mkDB2: Result := DB2_DriverType; mkASA: Result := ASA_DriverType; mkInterbase: Result := IB_DriverType; else Result := inherited GetDefaultConnectionType(AuxDriver); end; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACDriver.GetAuxParams(const AuxDriver: string; out List: IROStrings); const C_Line: String = '-----------------------------'; begin inherited; List.Add('AnyDAC Driver parameters'); List.Add(C_Line); case AnyDACDriverIdToAnyDACDriverType(AuxDriver) of mkOracle: ; mkMSSQL: MSSQL_GetAuxParams(List); mkMSAccess: ; mkMySQL: MYSQL_GetAuxParams(List); mkDB2: ; mkASA: ; mkInterbase: begin AddIBAuxParams(List); List.Add('DataTypeSchema='); end; end; List.Add('ConnectionDefName='); List.Add('BiDirectionalDataSets=0,1'); List.Add('DirectMode=0,1'); List.Add(''); case AnyDACDriverIdToAnyDACDriverType(AuxDriver) of mkOracle: begin List.Add('Oracle AuxDriver parameters'); List.Add(C_Line); List.Add('You can pass any parameters directly to aux driver. Use the prefix ''@'' for this, e.g.:'); List.Add('@SQLTrace=True;@Pooled=True'); List.Add(''); List.Add('Detailed description of aux driver parameters you can find at:'); List.Add('http://wiki.remobjects.com/wiki/Connect_to_Oracle_Server_(AnyDAC)'); end; mkMSSQL: begin List.Add('MSSQL AuxDriver parameters'); List.Add(C_Line); List.Add(''); List.Add('You can pass any parameters directly to aux driver. Use the prefix ''@'' for this, e.g.:'); List.Add('@App=My DA Server;@Pooled=True'); List.Add(''); List.Add('Detailed description of aux driver parameters you can find at:'); List.Add('http://wiki.remobjects.com/wiki/Connect_to_Microsoft_SQL_Server_(AnyDAC)'); end; mkMSAccess: begin List.Add('MSAccess AuxDriver parameters'); List.Add(C_Line); List.Add('You can pass any parameters directly to aux driver. Use the prefix ''@'' for this, e.g.:'); List.Add('@ReadOnly=True;@Pooled=True'); List.Add(''); List.Add('Detailed description of aux driver parameters you can find at:'); List.Add('http://wiki.remobjects.com/wiki/Connect_to_MS_Access_database_(AnyDAC)'); end; mkMySQL: begin List.Add('MySQL AuxDriver parameters'); List.Add(C_Line); List.Add('You can pass any parameters directly to aux driver. Use the prefix ''@'' for this, e.g.:'); List.Add('@CharacterSet=utf8;@Pooled=True'); List.Add(''); List.Add('Detailed description of aux driver parameters you can find at:'); List.Add('http://wiki.remobjects.com/wiki/Connect_to_MySQL_Server_(AnyDAC)'); end; mkDB2: begin List.Add('DB2 AuxDriver parameters'); List.Add(C_Line); List.Add('You can pass any parameters directly to aux driver. Use the prefix ''@'' for this, e.g.:'); List.Add('@Alias=MyDB;@Pooled=True'); List.Add(''); List.Add('Detailed description of aux driver parameters you can find at:'); List.Add('http://wiki.remobjects.com/wiki/Connect_to_IBM_DB2_Server_(AnyDAC)'); end; mkASA: begin List.Add('ASA AuxDriver parameters'); List.Add(C_Line); List.Add('You can pass any parameters directly to aux driver. Use the prefix ''@'' for this, e.g.:'); List.Add('@ODBCAdvanced=AutoStart=Yes;@DatabaseFile=C:\sybase\addemo_asa10.db;@Pooled=True'); List.Add(''); List.Add('Detailed description of aux driver parameters you can find at:'); List.Add('http://wiki.remobjects.com/wiki/Connect_to_Sybase_SQL_Anywhere_(AnyDAC)'); end; mkInterBase: begin List.Add('IB/FB AuxDriver parameters'); List.Add(C_Line); List.Add('You can pass any parameters directly to aux driver. Use the prefix ''@'' for this, e.g.:'); List.Add('@Protocol=TCPIP;@CharacterSet=win1251;@Pooled=True'); List.Add(''); List.Add('Detailed description of aux driver parameters you can find at:'); List.Add('http://wiki.remobjects.com/wiki/Connect_to_Interbase_or_Firebird_Server_(AnyDAC)'); end; end; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACDriver.Initialize; begin FConnectionDefs := TStringList.Create; FConnectionDefs.Sorted := True; FConnectionDefIndex := 0; ADManager.Open; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACDriver.Finalize; begin ADManager.Close; {$IFDEF AnyDAC_MONITOR} FreeAndNil(FMonitor); {$ENDIF} ADTerminate; end; {------------------------------------------------------------------------------} function TDAEAnyDACDriver.LookupConnectionString(const AConnectionString: String; AParsedParams: TStringList): String; var i: Integer; begin i := FConnectionDefs.IndexOf(AConnectionString); if i = -1 then begin Inc(FConnectionDefIndex); FConnectionDefs.AddObject(AConnectionString, TObject(FConnectionDefIndex)); with ADManager.ConnectionDefs.AddConnectionDef do begin Name := Format('__DACD_%d', [FConnectionDefIndex]); Params.AddStrings(AParsedParams); Result := Name; end; end else Result := Format('__DACD_%d', [Integer(FConnectionDefs.Objects[i])]); end; {------------------------------------------------------------------------------} {$IFDEF AnyDAC_MONITOR} procedure TDAEAnyDACDriver.DoTrace(ASender: TADMoniClientLinkBase; const AClassName, AObjName, AMessage: String); begin if Assigned(FTraceCallback) then FTraceCallback(ASender, AMessage, 0); end; {------------------------------------------------------------------------------} procedure TDAEAnyDACDriver.DoSetTraceOptions(TraceActive: boolean; TraceOptions: TDATraceOptions; Callback: TDALogTraceEvent); var eKinds: TADMoniEventKinds; begin inherited; if TraceActive then begin FTraceCallBack := Callback; eKinds := []; if toPrepare in TraceOptions then eKinds := eKinds + [ekCmdPrepare]; if toExecute in TraceOptions then eKinds := eKinds + [ekCmdExecute]; if toFetch in TraceOptions then eKinds := eKinds + [ekCmdDataIn]; if toError in TraceOptions then eKinds := eKinds + [ekError]; // if toStmt in TraceOptions then eKinds := eKinds + [tfStmt]; if toConnect in TraceOptions then eKinds := eKinds + [ekConnConnect]; if toTransact in TraceOptions then eKinds := eKinds + [ekConnTransact]; // if toBlob in TraceOptions then eKinds := eKinds + [tfBlob]; if toService in TraceOptions then eKinds := eKinds + [ekVendor]; if toMisc in TraceOptions then eKinds := eKinds + [ekConnService, ekLiveCycle, ekAdaptUpdate]; if toParams in TraceOptions then eKinds := eKinds + [ekCmdDataIn, ekCmdDataOut]; if FMonitor = nil then FMonitor := TADMoniCustomClientLink.Create(Self); FMonitor.Tracing := False; FMonitor.OnOutput := DoTrace; FMonitor.EventKinds := eKinds; FMonitor.Tracing := True; end else begin if FMonitor <> nil then FMonitor.Tracing := False; FTraceCallback := nil; end; end; {$ENDIF} {------------------------------------------------------------------------------} { TDAEAnyDACConnection } {------------------------------------------------------------------------------} function TDAEAnyDACConnection.QueryInterface(const IID: TGUID; out Obj): HResult; begin Result := E_NOINTERFACE; if IsEqualGUID(IID, IDAADOConnection) then begin if fDriverType <> mkMSSQL then Exit; end else if IsEqualGUID(IID, IDAInterbaseConnection) then begin if fDriverType <> mkInterbase then Exit; end else if IsEqualGUID(IID, IDAIBTransactionAccess) then begin if fDriverType <> mkInterbase then Exit; end else if IsEqualGUID(IID, IDAIBConnectionProperties) then begin if fDriverType <> mkInterbase then Exit; end else if IsEqualGUID(IID, IDAOracleConnection) then begin if fDriverType <> mkOracle then Exit; end else if IsEqualGUID(IID, IDADB2Connection) then begin if fDriverType <> mkDB2 then Exit; end else if IsEqualGUID(IID, IDASybaseConnection) then begin if not (fDriverType in [mkASA, mkADS]) then Exit; end else if IsEqualGUID(IID, IDAMySQLConnection) then begin if fDriverType <> mkMySQL then Exit; end else if IsEqualGUID(IID, IDACanQueryDatabaseNames) then begin if (fDriverType in [mkInterBase, mkMSAccess]) then Exit; end else if IsEqualGUID(IID, IDAFileBasedDatabase) then begin if not (fDriverType in [mkInterBase,mkMSAccess]) then Exit; end else if IsEqualGUID(IID, IDAUseGenerators) then begin if not (fDriverType in [mkInterBase, mkOracle]) then Exit; end else if IsEqualGUID(IID, IDACanQueryGeneratorsNames) then begin if not (fDriverType in [mkInterBase]) then Exit; end // else if IsEqualGUID(IID, IDAConnectionModelling) then ; Result := inherited QueryInterface(IID, Obj); end; {------------------------------------------------------------------------------} function TDAEAnyDACConnection.GetDatasetClass: TDAEDatasetClass; begin if FDirectMode then result := TDAEAnyDACQueryNative else result := TDAEAnyDACQuery; end; {------------------------------------------------------------------------------} function TDAEAnyDACConnection.GetStoredProcedureClass: TDAEStoredProcedureClass; begin if FDirectMode then result := TDAEAnyDACStoredProcedureNative else result := TDAEAnyDACStoredProcedure; end; {------------------------------------------------------------------------------} function TDAEAnyDACConnection.CreateCustomConnection: TCustomConnection; begin fDriverType := mkUnknown; FADConnection := TADConnection.Create(nil); with FADConnection do begin LoginPrompt := False; FetchOptions.Mode := fmAll; FetchOptions.RowsetSize := 100; ResourceOptions.SilentMode := True; ResourceOptions.UnifyParamNames := True; end; result := FADConnection; end; {------------------------------------------------------------------------------} function TDAEAnyDACConnection.GetAnyDACPhysConnection: IADPhysConnection; begin Result := FADConnection.ConnectionIntf; if Result = nil then ADPhysManager.CreateConnection(FADConnection.ConnectionDefName, Result); end; {------------------------------------------------------------------------------} { Database= S_AD_ConnParam_Common_Database User_Name= S_AD_ConnParam_Common_UserName Password= S_AD_ConnParam_Common_Password Oracle ====== OSAuthent= S_AD_ConnParam_Common_OSAuthent DriverID=Ora MSAccess ======== SystemDB= S_AD_ConnParam_MSAcc_SysDB DriverID=MSAcc DB2 === Alias= S_AD_ConnParam_DB2_Alias Server= S_AD_ConnParam_Common_Server Port= S_AD_ConnParam_Common_Port Protocol= S_AD_ConnParam_DB2_Protocol DriverID=DB2 ASA === Server= S_AD_ConnParam_Common_Server DatabaseFile= S_AD_ConnParam_ASA_DatabaseFile OSAuthent= S_AD_ConnParam_Common_OSAuthent App= S_AD_ConnParam_ASA_App Compress= S_AD_ConnParam_ASA_Compress Encrypt= S_AD_ConnParam_ASA_Encrypt DriverID=ASA ADS === DefaultType= ServerTypes= DriverID=ADS MSSQL ===== Server= S_AD_ConnParam_Common_Server Network= S_AD_ConnParam_MSSQL_Network Address= S_AD_ConnParam_MSSQL_Address OSAuthent= S_AD_ConnParam_Common_OSAuthent Workstation= S_AD_ConnParam_MSSQL_Workstation App= S_AD_ConnParam_MSSQL_App Encrypt= S_AD_ConnParam_MSSQL_Encrypt Language= S_AD_ConnParam_MSSQL_Language DriverID=MSSQL MySQL ===== CharacterSet= S_AD_ConnParam_Common_CharacterSet Server= S_AD_ConnParam_Common_Server Port= S_AD_ConnParam_Common_Port DriverID=MySQL IB == Protocol= S_AD_ConnParam_IB_Protocol Server= S_AD_ConnParam_Common_Server InstanceName= S_AD_ConnParam_IB_InstanceName CharacterSet= S_AD_ConnParam_Common_CharacterSet RoleName= S_AD_ConnParam_IB_RoleName SQLDialect= S_AD_ConnParam_IB_SQLDialect DriverID=IB Other ===== ODBCDriver= DataSource= RDBMS= ODBCAdvanced= DriverID=ODBC } procedure TDAEAnyDACConnection.DoApplyConnectionString( aConnStrParser: TDAConnectionStringParser; aConnectionObject: TCustomConnection); var sName, sValue: string; i: integer; oParams: TStringList; begin FMySQLVersion := -1; fDriverType := mkUnknown; FDataTypeSchema := ''; fMSSQLSchemaEnabled := False; fBiDirectionalDataSets := False; fDirectMode := False; inherited DoApplyConnectionString(aConnStrParser, aConnectionObject); oParams := TStringList.Create; try with aConnStrParser do begin oParams.Values[S_AD_ConnParam_Common_DriverID] := AuxDriver; fDriverType := AnyDACDriverIdToAnyDACDriverType(AuxDriver); if (Self.UserID <> '') then oParams.Values[S_AD_ConnParam_Common_UserName] := Self.UserID else if (UserID <> '') then oParams.Values[S_AD_ConnParam_Common_UserName] := UserID; if (Self.Password <> '') then oParams.Values[S_AD_ConnParam_Common_Password] := Self.Password else if (Password <> '') then oParams.Values[S_AD_ConnParam_Common_Password] := Password; if Database <> '' then oParams.Values[S_AD_ConnParam_Common_Database] := Database; FDataBaseName := DataBase; if Server <> '' then oParams.Values[S_AD_ConnParam_Common_Server] := Server; for i := 0 to AuxParamsCount - 1 do begin sName := AuxParamNames[i]; if sName = '' then Continue; sValue := AuxParams[AuxParamNames[i]]; if SameText(sName, 'Schemas') then begin fMSSQLSchemaEnabled := sValue = '1'; Continue; end else if SameText(sName, 'Dialect') then begin if fDriverType = mkInterBase then sName := S_AD_ConnParam_IB_SQLDialect; end else if SameText(sName, 'Role') then begin if fDriverType = mkInterBase then sName := S_AD_ConnParam_IB_RoleName; end else if SameText(sName, 'Charset') then begin if fDriverType = mkInterBase then sName := S_AD_ConnParam_Common_CharacterSet; end else if SameText(sName, 'Port') then begin if StrToIntDef(sValue, -1) <> -1 then sName := S_AD_ConnParam_Common_Port; end else if SameText(sName, 'ConnectionDefName') then sName := S_AD_DefinitionParam_Common_ConnectionDef else if SameText(sName, 'DataTypeSchema') then begin if fDriverType = mkInterBase then FDataTypeSchema := UpperCase(sValue); end else if SameText(sName, 'Integrated Security') then begin if (fDriverType = mkMSSQL) and (sValue = 'SSPI') then begin sName := S_AD_ConnParam_Common_OSAuthent; sValue := 'Yes'; end else Continue; end else if SameText(sName, 'BiDirectionalDataSets') then begin fBiDirectionalDataSets := sValue = '1'; Continue; end else if SameText(sName, 'DirectMode') then begin fDirectMode := sValue = '1'; Continue; end else if sName[1] = '@' then sName := Pchar(sName) + 1; oParams.Values[sName] := sValue; end; end; FADConnection.ConnectionDefName := TDAEAnyDACDriver(Driver).LookupConnectionString(GetConnectionString, oParams); if FDataTypeSchema = 'FIB' then MapAsFIB; finally oParams.Free; end; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACConnection.MapAsFIB; begin with FADConnection.FormatOptions do begin OwnMapRules := True; MapRules.Clear; with MapRules.Add do begin SourceDataType := dtFmtBCD; TargetDataType := dtDouble; end; with MapRules.Add do begin SourceDataType := dtCurrency; TargetDataType := dtDouble; end; with MapRules.Add do begin SourceDataType := dtBCD; TargetDataType := dtBCD; end; with MapRules.Add do begin SourceDataType := dtInt64; TargetDataType := dtBCD; end; end; end; {------------------------------------------------------------------------------} function TDAEAnyDACConnection.DoBeginTransaction: integer; begin Result := 0; FADConnection.StartTransaction; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACConnection.DoCommitTransaction; begin FADConnection.Commit; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACConnection.DoRollbackTransaction; begin FADConnection.Rollback; end; {------------------------------------------------------------------------------} function TDAEAnyDACConnection.DoGetInTransaction: boolean; begin result := FADConnection.InTransaction; end; {------------------------------------------------------------------------------} function TDAEAnyDACConnection.Native_DoGetLastAutoInc(const GeneratorName: string): integer; var v: Variant; begin v := FADConnection.GetLastAutoGenValue(GeneratorName); if VarIsNull(v) then Result := -1 else Result := v; end; {------------------------------------------------------------------------------} function TDAEAnyDACConnection.DoGetLastAutoInc(const GeneratorName: string): integer; begin case fDriverType of mkOracle: Result := Oracle_DoGetLastAutoInc(GeneratorName, GetDatasetClass.Create(Self)); mkMSSQL: Result := MSSQL_DoGetLastAutoInc(GeneratorName, GetDatasetClass.Create(Self)); mkMySQL: Result := MySQL_GetLastAutoInc(GeneratorName, GetDatasetClass.Create(Self)); mkInterBase: Result := IB_GetLastAutoInc(GeneratorName, GetDatasetClass.Create(Self)); else Result := Native_DoGetLastAutoInc(GeneratorName); end; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACConnection.DoGetStoredProcedureNames(out List: IROStrings); begin inherited; case fDriverType of mkOracle: Oracle_DoGetNames(GetDatasetClass.Create(Self), List, dotProcedure); mkMSSQL: MSSQL_DoGetNames(GetDatasetClass.Create(Self), List, dotProcedure, fMSSQLSchemaEnabled); mkMySQL: MYSQL_DoGetNames(GetDatasetClass.Create(Self), List, dotProcedure, GetDataBaseName,GetMySQLVersion); mkInterbase: IB_GetObjectNames(GetDatasetClass.Create(Self), List, dotProcedure); else DoGetNames(List, dotProcedure); end end; {------------------------------------------------------------------------------} procedure TDAEAnyDACConnection.DoGetViewNames(out List: IROStrings); begin inherited; case fDriverType of mkOracle: Oracle_DoGetNames(GetDatasetClass.Create(Self), List, dotView); mkMSSQL: MSSQL_DoGetNames(GetDatasetClass.Create(Self), List, dotView, fMSSQLSchemaEnabled); mkMySQL: MYSQL_DoGetNames(GetDatasetClass.Create(Self), List, dotView, GetDataBaseName,GetMySQLVersion); mkInterbase: IB_GetObjectNames(GetDatasetClass.Create(Self), List, dotView); else DoGetNames(List, dotView); end end; {------------------------------------------------------------------------------} procedure TDAEAnyDACConnection.DoGetTableNames(out List: IROStrings); begin inherited; case fDriverType of mkOracle: Oracle_DoGetNames(GetDatasetClass.Create(Self), List, dotTable); mkMSSQL: MSSQL_DoGetNames(GetDatasetClass.Create(Self), List, dotTable, fMSSQLSchemaEnabled); mkMySQL: MYSQL_DoGetNames(GetDatasetClass.Create(Self), List, dotTable, GetDataBaseName,GetMySQLVersion); mkInterbase: IB_GetObjectNames(GetDatasetClass.Create(Self), List, dotTable); else DoGetNames(List, dotTable); end end; {------------------------------------------------------------------------------} procedure TDAEAnyDACConnection.Native_DoGetTableFields(aTableName: string; out Fields: TDAFieldCollection); var oMIQ: TADMetaInfoQuery; eAttrs: TADDataAttributes; eBlobType: TDABlobType; lUseROWIDAsPK: Boolean; oFld: TDAField; begin aTableName := QuoteIdentifierIfNeeded(aTableName); Fields := TDAFieldCollection.Create(nil); lUseROWIDAsPK := False; oMIQ := TADMetaInfoQuery.Create(nil); try oMIQ.Connection := FADConnection; oMIQ.ObjectName := aTableName; oMIQ.MetaInfoKind := mkTableFields; oMIQ.Open; while not oMIQ.Eof do begin with Fields.Add do begin Name := oMIQ.FieldByName('COLUMN_NAME').AsString; Size := oMIQ.FieldByName('COLUMN_LENGTH').AsInteger; eAttrs := TADDataAttributes({$IFDEF FPC}ord{$ELSE}Word{$ENDIF}(oMIQ.FieldByName('COLUMN_ATTRIBUTES').AsInteger)); DataType := MapAD2DADataType(TADDataType(oMIQ.FieldByName('COLUMN_DATATYPE').AsInteger), eBlobType); if eBlobType <> dabtUnknown then BlobType := eBlobType; if (DataType = datInteger) and (caAutoInc in eAttrs) then DataType := datAutoInc; Required := not (caAllowNull in eAttrs); ReadOnly := caReadOnly in eAttrs; if caROWID in eAttrs then begin InPrimaryKey := True; lUseROWIDAsPK := True; end; // DefaultValue // ServerAutoRefresh end; oMIQ.Next; end; if not lUseROWIDAsPK then begin oMIQ.Close; oMIQ.BaseObjectName := oMIQ.ObjectName; oMIQ.ObjectName := ''; oMIQ.MetaInfoKind := mkPrimaryKeyFields; oMIQ.Open; while not oMIQ.Eof do begin oFld := Fields.FindField(oMIQ.FieldByName('COLUMN_NAME').AsString); if oFld <> nil then oFld.InPrimaryKey := True; oMIQ.Next; end; end; finally oMIQ.Free; end; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACConnection.Native_DoGetForeignKeys(ForeignKeys: TDADriverForeignKeyCollection); var oTabs, oFKeys, oFKeyFields: TADMetaInfoQuery; sFKFields, sPKFields: String; oConnMeta: IADPhysConnectionMetadata; function QuoteName(const AName: String): String; begin if AName = '' then Result := '' else Result := oConnMeta.NameQuotaChar1 + AName + oConnMeta.NameQuotaChar2; end; begin GetAnyDACPhysConnection.CreateMetadata(oConnMeta); ForeignKeys := TDADriverForeignKeyCollection.Create(nil); oTabs := TADMetaInfoQuery.Create(nil); oFKeys := TADMetaInfoQuery.Create(nil); oFKeyFields := TADMetaInfoQuery.Create(nil); try oTabs.Connection := FADConnection; oTabs.MetaInfoKind := mkTables; oTabs.TableKinds := [tkTable, tkTempTable, tkLocalTable]; oFKeys.MetaInfoKind := mkForeignKeys; oFKeys.Connection := FADConnection; oFKeys.MetaInfoKind := mkForeignKeys; oFKeyFields.Connection := FADConnection; oFKeyFields.MetaInfoKind := mkForeignKeyFields; oTabs.Open; while not oTabs.Eof do begin oFKeys.Close; oFKeys.CatalogName := QuoteName(oTabs.Fields[1].AsString); oFKeys.SchemaName := QuoteName(oTabs.Fields[2].AsString); oFKeys.ObjectName := QuoteName(oTabs.Fields[3].AsString); oFKeys.Open; while not oFKeys.Eof do begin oFKeyFields.Close; oFKeyFields.CatalogName := QuoteName(oFKeys.Fields[1].AsString); oFKeyFields.SchemaName := QuoteName(oFKeys.Fields[2].AsString); oFKeyFields.BaseObjectName := QuoteName(oFKeys.Fields[3].AsString); oFKeyFields.ObjectName := QuoteName(oFKeys.Fields[4].AsString); oFKeyFields.Open; sPKFields := ''; sFKFields := ''; while not oFKeyFields.Eof do begin if sPKFields <> '' then sPKFields := sPKFields + ','; sPKFields := sPKFields + oFKeyFields.Fields[6].AsString; if sFKFields <> '' then sFKFields := sFKFields + ','; sFKFields := sFKFields + oFKeyFields.Fields[5].AsString; oFKeyFields.Next; end; with ForeignKeys.Add do begin PKTable := FADConnection.EncodeObjectName(oFKeys.Fields[5].AsString, oFKeys.Fields[6].AsString, '', oFKeys.Fields[7].AsString); PKField := sPKFields; FKTable := FADConnection.EncodeObjectName(oFKeys.Fields[1].AsString, oFKeys.Fields[2].AsString, '', oFKeys.Fields[3].AsString); FKField := sFKFields; end; oFKeys.Next; end; oTabs.Next; end; finally oTabs.Free; oFKeys.Free; oFKeyFields.Free; end; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACConnection.DoGetNames(AList: IROStrings; AObjectType: TDAObjecttype); begin case AObjectType of dotTable: FADConnection.GetTableNames('', '', '', AList.Strings, [osMy], [tkTable]); dotProcedure: FADConnection.GetStoredProcNames('', '', '', '', AList.Strings, [osMy]); dotView: FADConnection.GetTableNames('', '', '', AList.Strings, [osMy], [tkView]); end; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACConnection.DoGetTableFields(const aTableName: string; out Fields: TDAFieldCollection); begin case fDriverType of mkOracle: Oracle_DoGetTableFields(QuoteIdentifierIfNeeded(aTableName), GetDatasetClass.Create(Self), Fields); mkMSSQL: MSSQL_DoGetTableFields(QuoteIdentifierIfNeeded(aTableName), GetDatasetClass.Create(Self), Fields); mkMySQL: MYSQL_DoGetTableFields(QuoteIdentifierIfNeeded(aTableName),GetDatasetClass.Create(Self),Fields, GetDataBaseName,GetMySQLVersion); mkInterBase: IB_GetTableFields(QuoteIdentifierIfNeeded(aTableName), GetDatasetClass.Create(Self), Fields); else Native_DoGetTableFields(aTableName,Fields); end; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACConnection.DoGetStoredProcedureParams( const aStoredProcedureName: string; out Params: TDAParamCollection); begin case fDriverType of mkMySQL: MYSQL_DoGetStoredProcedureParams(aStoredProcedureName, GetDatasetClass.Create(Self), Params, GetDataBaseName); mkOracle: Oracle_DoGetStoredProcedureParams(aStoredProcedureName, GetDatasetClass.Create(Self), Params); mkMSSQL: MSSQL_DoGetStoredProcedureParams(aStoredProcedureName, GetDatasetClass.Create(Self), Params); else inherited; end; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACConnection.DoGetForeignKeys( out ForeignKeys: TDADriverForeignKeyCollection); begin inherited; case fDriverType of mkOracle: Oracle_DoGetForeignKeys(GetDatasetClass.Create(Self), ForeignKeys); mkMSSQL: MSSQL_DoGetForeignKeys(GetDatasetClass.Create(Self), ForeignKeys, fMSSQLSchemaEnabled); mkMySQL: MYSQL_DoGetForeignKeys(GetDatasetClass.Create(Self), ForeignKeys, GetDataBaseName,GetMySQLVersion); mkInterBase: IB_DoGetForeignKeys(GetDatasetClass.Create(Self), ForeignKeys); else Native_DoGetForeignKeys(ForeignKeys); end; end; {------------------------------------------------------------------------------} function TDAEAnyDACConnection.CreateMacroProcessor: TDASQLMacroProcessor; begin case fDriverType of mkOracle: Result := Oracle_CreateMacroProcessor; mkMSSQL,mkMSAccess: Result := MSSQL_CreateMacroProcessor; mkInterBase: Result := IB_CreateMacroProcessor; else Result := inherited CreateMacroProcessor; end; end; {------------------------------------------------------------------------------} // IDAConnection function TDAEAnyDACConnection.GetSPSelectSyntax(AHasArguments: Boolean): string; begin case fDriverType of mkOracle: Result := Oracle_GetSPSelectSyntax(AHasArguments); mkMSSQL: Result := MSSQL_GetSPSelectSyntax(AHasArguments); mkInterBase: Result := IB_GetSPSelectSyntax(AHasArguments); else Result := inherited GetSPSelectSyntax(AHasArguments); end; end; {------------------------------------------------------------------------------} function TDAEAnyDACConnection.Native_GetQuoteChars: TDAQuoteCharArray; var oConnMeta: IADPhysConnectionMetadata; begin GetAnyDACPhysConnection.CreateMetadata(oConnMeta); result[0] := oConnMeta.NameQuotaChar1; result[1] := oConnMeta.NameQuotaChar2; end; {------------------------------------------------------------------------------} function TDAEAnyDACConnection.GetQuoteChars: TDAQuoteCharArray; begin case fDriverType of mkMSSQL: Result := MSSQL_GetQuoteChars; mkOracle: Result := Oracle_GetQuoteChars; else Result := Native_GetQuoteChars; end; end; {------------------------------------------------------------------------------} function TDAEAnyDACConnection.IdentifierNeedsQuoting(const AIdentifier: string): boolean; begin Result := inherited IdentifierNeedsQuoting(AIdentifier); if not Result then case fDriverType of mkORACLE: Result := Oracle_IdentifierNeedsQuoting(AIdentifier); mkMSSQL: Result := MSSQL_IdentifierNeedsQuoting(AIdentifier); mkMySQL: Result := MYSQL_IdentifierNeedsQuoting(AIdentifier); mkInterBase: Result := IB_IdentifierNeedsQuoting(AIdentifier, GetSQLDialect); mkDB2: Result := DB2_IdentifierNeedsQuoting(AIdentifier); mkASA,mkADS: Result := Sybase_IdentifierNeedsQuoting(AIdentifier); else end; end; {------------------------------------------------------------------------------} // IDAADOConnection function TDAEAnyDACConnection.GetCommandTimeout: Integer; begin Result := Integer(FADConnection.ResourceOptions.CmdExecTimeout); end; {------------------------------------------------------------------------------} procedure TDAEAnyDACConnection.SetCommandTimeout(const Value: Integer); begin FADConnection.ResourceOptions.CmdExecTimeout := Value; end; {------------------------------------------------------------------------------} function TDAEAnyDACConnection.GetProviderName: string; begin Result := FADConnection.ResultConnectionDef.DriverID; end; {------------------------------------------------------------------------------} function TDAEAnyDACConnection.GetProviderType: TDAOleDBProviderType; var s: String; begin s := GetProviderName; if SameText(s, S_AD_MSSQLId) then Result := oledb_MSSQL else if SameText(s, S_AD_MSAccId) then Result := oledb_Jet else if SameText(s, S_AD_OraId) then Result := oledb_Oracle else if SameText(s, S_AD_ODBCId) then Result := oledb_ODBC else Result := oledb_Unknown; // oledb_MSSQL2005 // oledb_Postgresql // oleDb_VisualFoxPro end; {------------------------------------------------------------------------------} // IDAIBTransactionAccess function TDAEAnyDACConnection.GetTransaction: TObject; begin Result := FADConnection.Transaction; end; {------------------------------------------------------------------------------} // IDAIBConnectionProperties function TDAEAnyDACConnection.GetSQLDialect: integer; begin Result := StrToIntDef(FADConnection.Params.Values[S_AD_ConnParam_IB_SQLDialect],3); end; {------------------------------------------------------------------------------} procedure TDAEAnyDACConnection.SetSQLDialect(Value: integer); begin FADConnection.Params.Values[S_AD_ConnParam_IB_SQLDialect] := IntToStr(Value); end; {------------------------------------------------------------------------------} function TDAEAnyDACConnection.GetCharset: string; begin Result := FADConnection.Params.Values[S_AD_ConnParam_Common_CharacterSet]; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACConnection.SetCharset(const Value: string); begin FADConnection.Params.Values[S_AD_ConnParam_Common_CharacterSet] := Value; end; {------------------------------------------------------------------------------} function TDAEAnyDACConnection.GetRole: string; begin Result := FADConnection.Params.Values[S_AD_ConnParam_IB_RoleName]; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACConnection.SetRole(const Value: string); begin FADConnection.Params.Values[S_AD_ConnParam_IB_RoleName] := Value; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACConnection.Commit; begin Self.DoCommitTransaction; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACConnection.Rollback; begin Self.DoRollbackTransaction; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACConnection.CommitRetaining; begin FADConnection.CommitRetaining; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACConnection.RollbackRetaining; begin FADConnection.RollbackRetaining; end; {------------------------------------------------------------------------------} // IDAConnectionModelling function TDAEAnyDACConnection.FieldToDeclaration(aField: TDAField): string; begin Result := ''; case fDriverType of mkMSSQL: case aField.DataType of datString: result := Format('varchar(%d)', [aField.Size]); datDateTime: result := 'datetime'; datFloat: result := 'float'; datCurrency: result := 'money'; datAutoInc: result := 'int IDENTITY(1,1)'; datInteger: result := 'int'; datLargeInt: result := 'bigint'; datBoolean: result := 'bit'; datMemo: result := 'text'; datBlob: result := 'image'; datWideString: result := Format('nvarchar(%d)', [aField.Size]); datWideMemo: result := 'ntext'; datLargeAutoInc: result := 'bigint IDENTITY(1,1)'; datByte: result := 'smallint'; datShortInt: result := 'smallint'; datWord: result := 'int'; datSmallInt: result := 'smallint'; datCardinal: result := 'bigint'; datLargeUInt: result := 'bigint'; datGuid: result := 'uniqueidentifier'; datXml: result := 'ntext'; datDecimal: result := 'decimal'; datSingleFloat: result := 'real'; end; mkOracle: case aField.DataType of datString: result := Format('varchar2(%d)', [aField.Size]); datDateTime: result := 'date'; datFloat: result := 'float'; datCurrency: result := 'number(19,4)'; datAutoInc: result := 'number(10,0)'; datInteger: result := 'number(10,0)'; datLargeInt: result := 'number(19,0)'; datBoolean: result := 'number(1)'; datMemo, datBlob: case aField.BlobType of dabtBlob: result := 'long raw'; dabtMemo: result := 'long'; dabtOraBlob: result := 'blob'; dabtOraClob: result := 'clob'; else if aField.DataType = datMemo then result := 'long' else result := 'long raw'; end; datWideString: result := Format('nvarchar2(%d)', [aField.Size]); datWideMemo: result := 'nclob'; datLargeAutoInc: result := 'number(19,0)'; datByte: result := 'number(3,0)'; datShortInt: result := 'number(3,0)'; datWord: result := 'number(5,0)'; datSmallInt: result := 'number(5,0)'; datCardinal: result := 'number(10,0)'; datLargeUInt: result := 'number(19,0)'; datGuid: result := 'varchar2(38)'; datXml: result := 'XMLType'; datDecimal: result := 'number'; datSingleFloat: result := 'float'; end; mkMySQL: case aField.DataType of datString: result := Format('varchar(%d)', [aField.Size]); datDateTime: result := 'datetime'; datFloat: result := 'double'; datCurrency: result := 'decimal(19,4)'; datAutoInc: result := 'int auto_increment'; datInteger: result := 'int'; datLargeInt: result := 'bigint'; datBoolean: result := 'bool'; datMemo: result := 'longtext'; datBlob: result := 'longblob'; datWideString: result := Format('varchar(%d) character set utf8', [aField.Size]); datWideMemo: result := 'longtext character set utf8'; datLargeAutoInc: result := 'bigint auto_increment'; datByte: result := 'tinyint unsigned'; datShortInt: result := 'tinyint'; datWord: result := 'smallint unsigned'; datSmallInt: result := 'smallint'; datCardinal: result := 'int unsigned'; datLargeUInt: result := 'bigint unsigned'; datGuid: result := 'varchar(38)'; datXml: result := 'longtext'; datDecimal: result := 'decimal'; datSingleFloat: result := 'float'; end; mkMSAccess: case aField.DataType of datString: result := Format('varchar(%d)', [aField.Size]); datDateTime: result := 'datetime'; datFloat: result := 'float'; datCurrency: result := 'currency'; datAutoInc: result := 'IDENTITY(1,1)'; datInteger: result := 'integer'; datLargeInt: result := 'decimal(19,0)'; datBoolean: result := 'boolean'; datMemo: result := 'memo'; datBlob: result := 'image'; datWideString: result := Format('nchar(%d)', [aField.Size]); datWideMemo: result := 'ntext'; datLargeAutoInc: result := 'IDENTITY(1,1)'; datByte: result := 'byte'; datShortInt: result := 'tinyint'; datWord: result := 'smallint'; datSmallInt: result := 'smallint'; datCardinal: result := 'integer'; datLargeUInt: result := 'decimal(19,0)'; datGuid: result := 'varchar(38)'; datXml: result := 'ntext'; datDecimal: result := 'decimal'; datSingleFloat: result := 'real'; end; mkDB2: case aField.DataType of datString: result := Format('varchar(%d)', [aField.Size]); datDateTime: result := 'timestamp'; datFloat: result := 'real'; datCurrency: result := 'decimal(19,4)'; datAutoInc: result := 'integer not null generated always as identity (start with 1, increment by 1, no cache)'; datInteger: result := 'integer'; datLargeInt: result := 'bigint'; // >= 9.1 datBoolean: result := 'smallint'; datMemo, datBlob: case aField.BlobType of dabtBlob: result := 'long varchar for bit data'; dabtMemo: result := 'long varchar '; dabtOraBlob: result := 'blob'; dabtOraClob: result := 'clob'; else if aField.DataType = datMemo then result := 'long varchar' else result := 'long varchar for bit data'; end; datWideString: result := Format('vargraphic(%d)', [aField.Size]); datWideMemo: result := 'clob'; datLargeAutoInc: result := 'bigint not null generated always as identity (start with 1, increment by 1, no cache)'; // >= 9.1 datByte: result := 'smallint'; datShortInt: result := 'smallint'; datWord: result := 'smallint'; datSmallInt: result := 'smallint'; datCardinal: result := 'integer'; datLargeUInt: result := 'bigint'; // >= 9.1 datGuid: result := 'varchar(38)'; datXml: result := 'clob'; datDecimal: result := 'number'; datSingleFloat: result := 'real'; end; mkASA: case aField.DataType of datString: result := Format('varchar(%d)', [aField.Size]); datDateTime: result := 'timestamp'; datFloat: result := 'double'; datCurrency: result := 'money'; datAutoInc: result := 'integer identity(1,1)'; datInteger: result := 'integer'; datLargeInt: result := 'bigint'; datBoolean: result := 'bit'; datMemo: result := 'text'; datBlob: result := 'image'; datWideString: result := Format('nvarchar(%d)', [aField.Size]); datWideMemo: result := 'ntext'; datLargeAutoInc: result := 'bigint identity(1,1)'; datByte: result := 'unsigned tinyint'; datShortInt: result := 'tinyint'; datWord: result := 'unsigned smallint'; datSmallInt: result := 'smallint'; datCardinal: result := 'unsigned integer'; datLargeUInt: result := 'unsigned bigint'; datGuid: result := 'uniqueidentifierstr'; datXml: result := 'xml'; datDecimal: result := 'decimal'; datSingleFloat: result := 'real'; end; mkInterbase: case aField.DataType of datString: result := Format('varchar(%d)', [aField.Size]); datDateTime: result := 'timestamp'; datFloat: result := 'double precision'; datCurrency: result := 'decimal(18,4)'; datAutoInc: result := 'integer'; datInteger: result := 'integer'; datLargeInt: result := 'decimal(18,0)'; datBoolean: result := 'integer check (value in (0, 1))'; datMemo, datBlob: case aField.BlobType of dabtBlob: result := 'blob(2000,0)'; dabtMemo: result := 'blob(2000,1)'; dabtOraBlob: result := 'blob(2000,0)'; dabtOraClob: result := 'blob(2000,1)'; else if aField.DataType = datMemo then result := 'blob(2000,1)' else result := 'blob(2000,0)'; end; datWideString: result := Format('varchar(%d) character set unicode_fss', [aField.Size]); datWideMemo: result := 'blob sub_type 1 segment size 2000 character set unicode_fss'; datLargeAutoInc: result := 'decimal(18,0)'; datByte: result := 'smallint'; datShortInt: result := 'smallint'; datWord: result := 'smallint'; datSmallInt: result := 'smallint'; datCardinal: result := 'decimal(10,0)'; datLargeUInt: result := 'decimal(18,0)'; datGuid: result := 'varchar(38)'; datXml: result := 'blob(2000,1)'; datDecimal: result := 'decimal(18,6)'; datSingleFloat: result := 'float'; end; end; if Result = '' then raise Exception.CreateFmt('DataAbstract [%d] data type of field [%s] for DBMS [%s] is not supported', [Integer(aField.DataType), aField.Name, C_AD_PhysRDBMSKinds[fDriverType]]); end; {------------------------------------------------------------------------------} function TDAEAnyDACConnection.BuildCreateTableSQL(aDataSet: TDADataSet; const aOverrideName: string): string; var lName: string; begin lName := aOverrideName; if lName = '' then lName := aDataSet.Name; result := uDAHelpers.BuildCreateStatementForTable(aDataSet, lName, self); end; {------------------------------------------------------------------------------} procedure TDAEAnyDACConnection.CreateTable(aDataSet: TDADataSet; const aOverrideName: string); var sSQL: string; begin sSQL := BuildCreateTableSQL(aDataSet, aOverrideName); with NewCommand(sSQL, stSQL) do Execute(); end; {------------------------------------------------------------------------------} // IDACanQueryDatabaseNames function TDAEAnyDACConnection.GetDataBaseName: string; begin Result := FDataBaseName; end; function TDAEAnyDACConnection.GetDatabaseNames: IROStrings; begin case fDriverType of mkMSSQL: Result := MSSQL_GetDatabaseNames(Self); mkMySQL: Result := MYSQL_GetDatabaseNames(Self); else Result := NewROStrings; end; end; {------------------------------------------------------------------------------} // IDAFileBasedDatabase function TDAEAnyDACConnection.GetFileExtensions: IROStrings; begin case fDriverType of mkInterBase: Result := IB_GetFileExtensions; mkMSAccess: Result := MSACCESS_GetFileExtensions; else Result := NewROStrings; end; end; {------------------------------------------------------------------------------} // IDAUseGenerators function TDAEAnyDACConnection.GetNextAutoinc(const GeneratorName: string): integer; begin Result := -1; case fDriverType of mkInterBase: Result := IB_GetNextAutoinc(GeneratorName, GetDatasetClass.Create(Self)); mkOracle: Result := Oracle_GetNextAutoinc(GeneratorName, GetDatasetClass.Create(Self)); end; end; {------------------------------------------------------------------------------} // IDACanQueryGeneratorsNames function TDAEAnyDACConnection.GetGeneratorNames: IROStrings; begin case fDriverType of mkInterBase: Result := IB_GetGeneratorNames(GetDatasetClass.Create(Self)); else Result := NewROStrings; end; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACConnection.SetupOptions(AOptions: IADStanOptions; AFetchMeta: Boolean); begin with AOptions do begin if not fBiDirectionalDataSets then FetchOptions.Unidirectional := True; if not AFetchMeta then FetchOptions.Items := FetchOptions.Items - [fiMeta]; end; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACConnection.SetupDataset(ADataSet: TADRdbmsDataSet; AFetchMeta: Boolean); begin TADQuery(ADataSet).Connection := FADConnection; SetupOptions(IADStanOptions(TADQuery(ADataSet).Command), AFetchMeta); end; {------------------------------------------------------------------------------} { TDAEAnyDACQuery } {------------------------------------------------------------------------------} function TDAEAnyDACQuery.CreateDataset(aConnection: TDAEConnection): TDataset; begin result := TADQuery.Create(nil); TDAEAnyDACConnection(aConnection).SetupDataset(TADQuery(result), False); end; {------------------------------------------------------------------------------} procedure TDAEAnyDACQuery.DoPrepare(AValue: boolean); var i: integer; oPar: TADParam; begin if AValue and not TADQuery(Dataset).Prepared and (TADQuery(Dataset).ParamCount <> 0) then for I := 0 to GetParams.Count - 1 do begin oPar := TADQuery(Dataset).ParamByName(GetParams[i].Name); oPar.DataType := DATypeToVCLType(GetParams[i].DataType); if oPar.DataType = ftAutoInc then oPar.DataType := ftInteger; end; TADQuery(Dataset).Prepared := AValue; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACQuery.ClearParams; begin inherited; TADQuery(Dataset).Params.Clear; end; {------------------------------------------------------------------------------} function TDAEAnyDACQuery.DoExecute: integer; begin with TADQuery(Dataset) do begin // 1) SELECT command on MSSQL, etc may be without result set, for example: // SELECT :CUSTOMERS_CNT = count(*) from customers // 2) On Oracle skExecute is handled specially (PL/SQL) and commands as // above are not possible if PointedConnection.RDBMSKind <> mkOracle then Command.CommandKind := skExecute; ExecSQL; Result := RowsAffected; end; end; {------------------------------------------------------------------------------} function TDAEAnyDACQuery.DoGetSQL: string; begin Result := TADQuery(Dataset).SQL.Text; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACQuery.DoSetSQL(const AValue: string); begin with TADQuery(Dataset).SQL do begin BeginUpdate; try Clear; Add(AValue); finally EndUpdate; end; end; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACQuery.SetParamValues(AParams: TDAParamCollection); begin SetADParamValuesFromDA(AParams, TADQuery(Dataset).Params, True); end; {------------------------------------------------------------------------------} procedure TDAEAnyDACQuery.GetParamValues(AParams: TDAParamCollection); begin GetDAParamValuesFromAD(GetParams, TADQuery(Dataset).Params); end; {------------------------------------------------------------------------------} { TDAEAnyDACStoredProcedure } {------------------------------------------------------------------------------} function TDAEAnyDACStoredProcedure.CreateDataset(AConnection: TDAEConnection): TDataset; begin Result := TADStoredProc.Create(nil); TDAEAnyDACConnection(aConnection).SetupDataset(TADStoredProc(Result), True); end; {------------------------------------------------------------------------------} function TDAEAnyDACStoredProcedure.GetStoredProcedureName: string; begin Result := TADStoredProc(DataSet).StoredProcName; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACStoredProcedure.SetStoredProcedureName(const Name: string); begin TADStoredProc(DataSet).StoredProcName := Name; end; {------------------------------------------------------------------------------} function TDAEAnyDACStoredProcedure.DoExecute: integer; begin TADStoredProc(Dataset).ExecProc; result := TADStoredProc(Dataset).RowsAffected; end; {------------------------------------------------------------------------------} function TDAEAnyDACStoredProcedure.Execute: integer; var oADParams: TADParams; oDAParams: TDAParamCollection; begin oADParams := TADStoredProc(Dataset).Params; oDAParams := GetParams; if oADParams.Count <> oDAParams.Count then TADStoredProc(Dataset).Prepare; SetADParamValuesFromDA(oDAParams, oADParams, False); Result := DoExecute; // in case of SP the reference to params may be invalid after execution oADParams := TADStoredProc(Dataset).Params; GetDAParamValuesFromAD(oDAParams, oADParams); end; {------------------------------------------------------------------------------} procedure TDAEAnyDACStoredProcedure.RefreshParams; var oDAParams: TDAParamCollection; oDAParam: TDAParam; i: Integer; begin TADStoredProc(Dataset).Prepare; oDAParams := GetParams; oDAParams.Clear; with TADStoredProc(Dataset) do for i := 0 to Params.Count - 1 do begin oDAParam := oDAParams.Add; oDAParam.Name := Params[i].Name; oDAParam.DataType := VCLTypeToDAType(Params[i].DataType); oDAParam.ParamType := TDAParamType(Params[i].ParamType); oDAParam.Size := Params[i].Size; end; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACStoredProcedure.SetParamValues(AParams: TDAParamCollection); begin SetADParamValuesFromDA(AParams, TADStoredProc(Dataset).Params, False); end; {------------------------------------------------------------------------------} procedure TDAEAnyDACStoredProcedure.GetParamValues(AParams: TDAParamCollection); begin GetDAParamValuesFromAD(AParams, TADStoredProc(Dataset).Params); end; {------------------------------------------------------------------------------} { TDAEAnyDACNativeField } {------------------------------------------------------------------------------} constructor TDAEAnyDACNativeField.Create(ACol: TADDatSColumn; const ACmd: IADPhysCommand; AParent: TDAEAnyDACNativeDatabaseAccess); begin inherited Create; FCol := ACol; FCmd := ACmd; fParent:= AParent; end; {------------------------------------------------------------------------------} function TDAEAnyDACNativeField.GetDataType: TFieldType; var iDestSize: Longword; iDestPrec,iDescScale: Integer; begin FCmd.Options.FormatOptions.ColumnDef2FieldDef(FCol.DataType, FCol.Size, FCol.Precision, FCol.Scale, FCol.Attributes, Result, iDestSize, iDestPrec, iDescScale); end; {------------------------------------------------------------------------------} function TDAEAnyDACNativeField.GetDecimalPrecision: Integer; begin Result := FCol.Precision; end; {------------------------------------------------------------------------------} function TDAEAnyDACNativeField.GetDecimalScale: Integer; begin Result := FCol.Scale; end; {------------------------------------------------------------------------------} function TDAEAnyDACNativeField.GetFieldIndex: integer; begin Result := FCol.Index; end; function TDAEAnyDACNativeField.GetFieldName: string; begin Result := FCol.Name; end; {------------------------------------------------------------------------------} function TDAEAnyDACNativeField.GetNativeObject: TObject; begin Result := Self; end; {------------------------------------------------------------------------------} function TDAEAnyDACNativeField.GetSize: integer; begin Result := FCol.Size; end; {------------------------------------------------------------------------------} function TDAEAnyDACNativeField.GetValue: Variant; begin Result := FParent.GetNativeFieldValue(FCol.Index); end; function TDAEAnyDACNativeField.IsNull: Boolean; begin Result := fParent.IsNull(FCol.Index); end; function TDAEAnyDACNativeField.isTFieldCompatible: Boolean; begin Result := False; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACNativeField.SetDataType(Value: TFieldType); var eDestType: TADDataType; iDestScale: Integer; iDestPrec: Integer; iDestSize: LongWord; iDestAttrs: TADDataAttributes; begin FCmd.Options.FormatOptions.FieldDef2ColumnDef(Value, FCol.Size, FCol.Precision,FCol.Scale, eDestType, iDestSize, iDestPrec, iDestScale, iDestAttrs); FCol.DataType := eDestType; FCol.Attributes := iDestAttrs; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACNativeField.SetDecimalPrecision(Value: integer); begin FCol.Precision := Value; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACNativeField.SetDecimalScale(Value: integer); begin FCol.Scale := Value; end; {------------------------------------------------------------------------------} { TDAEAnyDACNativeDatabaseAccess } {------------------------------------------------------------------------------} constructor TDAEAnyDACNativeDatabaseAccess.Create(ADAEConnection: TDAEAnyDACConnection); begin inherited Create; ADAEConnection.FADConnection.Connected:=True; ADAEConnection.FADConnection.ConnectionIntf.CreateCommand(FCmd); FTab := TADDatSTable.Create; end; {------------------------------------------------------------------------------} destructor TDAEAnyDACNativeDatabaseAccess.Destroy; begin FCmd := nil; FreeAndNil(FTab); inherited Destroy; end; {------------------------------------------------------------------------------} function TDAEAnyDACNativeDatabaseAccess._AddRef: Integer; begin Result := 1; end; {------------------------------------------------------------------------------} function TDAEAnyDACNativeDatabaseAccess._Release: Integer; begin Result := 1; end; {------------------------------------------------------------------------------} function TDAEAnyDACNativeDatabaseAccess.QueryInterface(const IID: TGUID; out Obj): HResult; begin if GetInterface(IID, Obj) then Result := 0 else Result := E_NOINTERFACE; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACNativeDatabaseAccess.CheckActive; begin if not (nfActive in FFlags) then raise Exception.Create('Dataset must be active'); end; {------------------------------------------------------------------------------} procedure TDAEAnyDACNativeDatabaseAccess.CheckBidir; begin if FCmd.Options.FetchOptions.Unidirectional then raise Exception.Create('Dataset must be bidirectional'); end; {------------------------------------------------------------------------------} procedure TDAEAnyDACNativeDatabaseAccess.ClearFieldDefs; begin FTab.Reset; end; {------------------------------------------------------------------------------} function TDAEAnyDACNativeDatabaseAccess.GetRecordCount: Integer; begin Result := FRowsPurged + FTab.Rows.Count; end; {------------------------------------------------------------------------------} function TDAEAnyDACNativeDatabaseAccess.GetBOF: Boolean; begin Result := nfBOF in FFlags; end; {------------------------------------------------------------------------------} function TDAEAnyDACNativeDatabaseAccess.GetEOF: Boolean; begin Result := nfEOF in FFlags; end; {------------------------------------------------------------------------------} function TDAEAnyDACNativeDatabaseAccess.GetActive: Boolean; begin Result := nfActive in FFlags; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACNativeDatabaseAccess.SetActive(const aValue: Boolean); var i: Integer; begin if (nfActive in FFlags) <> aValue then if aValue then begin FCmd.Open; FCmd.Define(FTab); FCmd.Fetch(FTab, False); FRowIndex := 0; FRowsPurged := 0; if FTab.Rows.Count = 0 then Include(FFlags, nfEOF) else Exclude(FFlags, nfEOF); Include(FFlags, nfBOF); Include(FFlags, nfActive); SetLength(FBuffs, FTab.Columns.Count); for i := 0 to FTab.Columns.Count - 1 do case FTab.Columns[i].DataType of dtDateTimeStamp, dtTime, dtDate: GetMem(FBuffs[i], SizeOf(TDateTime)); dtGUID: GetMem(FBuffs[i], 39); dtCurrency: GetMem(FBuffs[i], SizeOf(Double)); dtBCD: GetMem(FBuffs[i], SizeOf(Currency)); else FBuffs[i] := nil; end; end else begin FCmd.AbortJob(True); FCmd.CloseAll; FTab.Clear; FRowIndex := 0; FRowsPurged := 0; Exclude(FFlags, nfActive); for i := 0 to FTab.Columns.Count - 1 do if FBuffs[i] <> nil then FreeMem(FBuffs[i]); SetLength(FBuffs, 0); end; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACNativeDatabaseAccess.First; begin CheckActive; CheckBidir; FRowIndex := 0; if FTab.Rows.Count = 0 then Include(FFlags, nfEOF); Include(FFlags, nfBOF); end; {------------------------------------------------------------------------------} procedure TDAEAnyDACNativeDatabaseAccess.Next; begin CheckActive; Exclude(FFlags, nfEOF); if FRowIndex >= FTab.Rows.Count - 1 then begin if FCmd.State = csOpen then begin if FCmd.Options.FetchOptions.Unidirectional then begin Inc(FRowsPurged, FTab.Rows.Count); FTab.Clear; FRowIndex := -1; end; FCmd.Fetch(FTab, False); if FCmd.RowsAffected = 0 then Include(FFlags, nfEOF); end else Include(FFlags, nfEOF); end; if FRowIndex < FTab.Rows.Count - 1 then Inc(FRowIndex); if FRowIndex <= 0 then Include(FFlags, nfBOF) else Exclude(FFlags, nfBOF); end; {------------------------------------------------------------------------------} function TDAEAnyDACNativeDatabaseAccess.LocateRecord(const KeyFields: string; const KeyValues: Variant; Options: TLocateOptions; AChangePos: Boolean): Integer; var oCols: TADDatSColumnSublist; iPrevRowIndex: Integer; ePrevFlags: TDAEAnyDACNativeDatabaseAccessFlags; lSimple: Boolean; lEQ: Boolean; i: Integer; V1, V2: Variant; begin Result := -1; oCols := TADDatSColumnSublist.Create; iPrevRowIndex := FRowIndex; ePrevFlags := FFlags; try oCols.Fill(FTab, KeyFields); lSimple := (oCols.Count = 1) and not VarIsArray(KeyValues); First; while not (nfEOF in FFlags) do begin lEQ := False; for i := 0 to oCols.Count - 1 do begin V1 := FTab.Rows[FRowIndex].GetData(oCols[i]); if lSimple then V2 := KeyValues else V2 := KeyValues[i]; if VarIsNull(V1) and VarIsNull(V2) then lEQ := True else if VarIsNull(V1) xor VarIsNull(V2) then lEQ := False else if oCols[i].DataType in [dtAnsiString, dtWideString, dtMemo, dtWideMemo, dtHMemo, dtWideHMemo] then if loCaseInsensitive in Options then begin if loPartialKey in Options then lEQ := Pos(AnsiLowerCase(VarToStr(V2)), AnsiLowerCase(VarToStr(V1))) = 1 else lEQ := AnsiCompareText(VarToStr(V2), VarToStr(V1)) = 0; end else if loPartialKey in Options then lEQ := Pos(VarToStr(V2), VarToStr(V1)) = 1 else lEQ := CompareStr(VarToStr(V2), VarToStr(V1)) = 0 else try lEQ := V1 = V2; except lEQ := False; end; if not lEQ then Break; end; if lEQ then begin Result := FRowIndex; Break; end; Next; end; finally oCols.Free; if (Result = -1) or not AChangePos then begin FRowIndex := iPrevRowIndex; FFlags := ePrevFlags; end; end; end; {------------------------------------------------------------------------------} function TDAEAnyDACNativeDatabaseAccess.Locate(const KeyFields: string; const KeyValues: Variant; Options: TLocateOptions): Boolean; begin Result := LocateRecord(KeyFields, KeyValues, Options, True) <> -1; end; {------------------------------------------------------------------------------} function TDAEAnyDACNativeDatabaseAccess.Lookup(const KeyFields: string; const KeyValues: Variant; const ResultFields: string): Variant; var iRowIndex, i: Integer; oCols: TADDatSColumnSublist; begin iRowIndex := LocateRecord(KeyFields, KeyValues, [], False); if iRowIndex <> -1 then begin oCols := TADDatSColumnSublist.Create; try if oCols.Count = 1 then Result := FTab.Rows[iRowIndex].GetData(oCols[0]) else begin Result := VarArrayCreate([0, oCols.Count - 1], varVariant); for i := 0 to oCols.Count - 1 do Result[i] := FTab.Rows[iRowIndex].GetData(oCols[i]); end; finally oCols.Free; end end else Result := Null; end; {------------------------------------------------------------------------------} function TDAEAnyDACNativeDatabaseAccess.GetFieldName(Index: Integer): string; begin Result := FTab.Columns[Index].Name; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACNativeDatabaseAccess.DisableControls; begin // nothing end; {------------------------------------------------------------------------------} procedure TDAEAnyDACNativeDatabaseAccess.EnableControls; begin // nothing end; {------------------------------------------------------------------------------} function TDAEAnyDACNativeDatabaseAccess.ControlsDisabled: Boolean; begin // nothing Result := True; end; {------------------------------------------------------------------------------} function TDAEAnyDACNativeDatabaseAccess.GetIsEmpty: boolean; begin Result := (FRowsPurged + FTab.Rows.Count) = 0; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACNativeDatabaseAccess.FreeBookmark(Bookmark: TBookmark); begin // nothing end; {------------------------------------------------------------------------------} function TDAEAnyDACNativeDatabaseAccess.GetBookMark: pointer; begin CheckActive; CheckBidir; Result := Pointer(FRowIndex); end; {------------------------------------------------------------------------------} procedure TDAEAnyDACNativeDatabaseAccess.GotoBookmark(Bookmark: TBookmark); begin CheckActive; CheckBidir; FRowIndex := Integer(Bookmark); end; {------------------------------------------------------------------------------} function TDAEAnyDACNativeDatabaseAccess.GetState: TDatasetState; begin if FCmd.State = csExecuting then Result := dsOpening else if nfActive in FFlags then Result := dsBrowse else Result := dsInactive; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACNativeDatabaseAccess.Prepare(const AValue: Boolean); begin if AValue then FCmd.Prepare else FCmd.Unprepare; end; {------------------------------------------------------------------------------} function TDAEAnyDACNativeDatabaseAccess.GetFields(Index: integer): IDANativeField; begin Result := TDAEAnyDACNativeField.Create(FTab.Columns[Index], FCmd, Self) as IDANativeField; end; {------------------------------------------------------------------------------} function TDAEAnyDACNativeDatabaseAccess.FieldCount: Integer; begin Result := FTab.Columns.Count; end; {------------------------------------------------------------------------------} function TDAEAnyDACNativeDatabaseAccess.FindField(const FieldName: string): IDANativeField; var i: Integer; begin i := FTab.Columns.IndexOfName(FieldName); if i = -1 then Result := nil else Result := GetFields(i); end; {------------------------------------------------------------------------------} function TDAEAnyDACNativeDatabaseAccess.IsTDatasetCompatible: Boolean; begin Result := False; end; {------------------------------------------------------------------------------} function TDAEAnyDACNativeDatabaseAccess.GetNativeFieldData(Index: Integer; var Data: pointer; var DataSize: cardinal): Boolean; procedure CvtGUID(ABuff: PChar; AGuid: PGUID); begin with AGuid^ do StrLFmt(ABuff, 38, '{%.8x-%.4x-%.4x-%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x}', [D1, D2, D3, D4[0], D4[1], D4[2], D4[3], D4[4], D4[5], D4[6], D4[7]]); end; procedure ErrNotSupported(AType: TADDataType); begin raise Exception.CreateFmt('AnyDAC data type [%s] is not supported by DataAbstract', [C_AD_DataTypeNames[AType]]); end; begin CheckActive; if (FRowIndex >= 0) and (FRowIndex < FTab.Rows.Count) then begin Result := FTab.Rows[FRowIndex].GetData(Index, rvDefault, Data, 0, DataSize, False); if Result then case FTab.Columns[Index].DataType of dtWideString, dtWideMemo, dtWideHMemo: DataSize := DataSize * SizeOf(WideChar); dtDateTimeStamp: begin PDateTime(FBuffs[Index])^ := ADSQLTimeStampToDateTime(PADSQLTimeStamp(Data)^); DataSize := SizeOf(TDateTime); Data := FBuffs[Index]; end; dtTime: begin PDateTime(FBuffs[Index])^ := ADTime2DateTime(PLongint(Data)^); DataSize := SizeOf(TDateTime); Data := FBuffs[Index]; end; dtDate: begin PDateTime(FBuffs[Index])^ := ADDate2DateTime(PLongint(Data)^); DataSize := SizeOf(TDateTime); Data := FBuffs[Index]; end; dtGUID: begin CvtGUID(PChar(FBuffs[Index]), PGuid(Data)); DataSize := 38; Data := FBuffs[Index]; end; dtCurrency: begin PDouble(FBuffs[Index])^ := PCurrency(Data)^; DataSize := SizeOf(Double); Data := FBuffs[Index]; end; dtBCD: begin BCDToCurr(PBCD(Data)^, PCurrency(FBuffs[Index])^); DataSize := SizeOf(Currency); Data := FBuffs[Index]; end; dtFmtBCD: begin PBCD(FBuffs[Index])^ := PBCD(Data)^; DataSize := SizeOf(TBCD); Data := FBuffs[Index]; end; dtRowSetRef, dtCursorRef, dtRowRef, dtArrayRef, dtParentRowRef, dtObject: ErrNotSupported(FTab.Columns[Index].DataType); end; end else Result := False; if not Result then begin DataSize := 0; Data := nil; end; end; {------------------------------------------------------------------------------} function TDAEAnyDACNativeDatabaseAccess.GetNativeFieldValue(Index: Integer): Variant; var data: pointer; DataSize: cardinal; c: Currency; begin CheckActive; if (FRowIndex >= 0) and (FRowIndex < FTab.Rows.Count) then begin case FTab.Columns[Index].DataType of dtDateTimeStamp: if FTab.Rows[FRowIndex].GetData(Index, rvDefault, Data, 0, DataSize, False) then Result := VarFromDateTime(ADSQLTimeStampToDateTime(PADSQLTimeStamp(Data)^)) else Result := Null; dtBCD: if FTab.Rows[FRowIndex].GetData(Index, rvDefault, Data, 0, DataSize, False) then begin BCDToCurr(PBCD(Data)^, c); Result := c; end else begin Result := Null; end; dtFmtBCD: if FTab.Rows[FRowIndex].GetData(Index, rvDefault, Data, 0, DataSize, False) then Result := DecimalToString(BCDToDecimal(PBCD(Data)^),DecimalSeparator) else Result := Null; dtTime, dtDate: if FTab.Rows[FRowIndex].GetData(Index, rvDefault, Data, 0, DataSize, False) then Result := VarFromDateTime(ADTime2DateTime(PLongint(Data)^)) else Result := Null; dtCurrency: if FTab.Rows[FRowIndex].GetData(Index, rvDefault, Data, 0, DataSize, False) then Result := PCurrency(Data)^ else Result := Null; dtGUID: if FTab.Rows[FRowIndex].GetData(Index, rvDefault, Data, 0, DataSize, False) then Result := GUIDToString(PGuid(Data)^) else Result := Null; else Result := FTab.Rows[FRowIndex].GetData(Index); end; end else Result := Null; end; {------------------------------------------------------------------------------} function TDAEAnyDACNativeDatabaseAccess.CanFreeNativeFieldData: Boolean; begin Result := False; end; {------------------------------------------------------------------------------} { TDAEAnyDACQueryNative } {------------------------------------------------------------------------------} function TDAEAnyDACQueryNative.GetNativeObject: TDAEAnyDACNativeDatabaseAccess; begin Result := TDAEAnyDACNativeDatabaseAccess(inherited NativeObject); end; {------------------------------------------------------------------------------} function TDAEAnyDACQueryNative.CreateDataset(aConnection: TDAEConnection): TDataset; begin Result := nil; end; {------------------------------------------------------------------------------} function TDAEAnyDACQueryNative.CreateNativeDatabaseAccess: IDANativeDatabaseAccess; begin Supports(NativeObject, IDANativeDatabaseAccess, Result); end; {------------------------------------------------------------------------------} function TDAEAnyDACQueryNative.CreateNativeObject(aConnection: TDAEConnection): TObject; begin Result := TDAEAnyDACNativeDatabaseAccess.Create(TDAEAnyDACConnection(aConnection)); TDAEAnyDACConnection(aConnection).SetupOptions(TDAEAnyDACNativeDatabaseAccess(Result).FCmd.Options, False); end; {------------------------------------------------------------------------------} procedure TDAEAnyDACQueryNative.DoPrepare(AValue: boolean); var i: integer; oPar: TADParam; begin if AValue and (NativeObject.FCmd.State <> csPrepared) and (NativeObject.FCmd.Params.Count <> 0) then for I := 0 to GetParams.Count - 1 do begin oPar := NativeObject.FCmd.Params.ParamByName(GetParams[i].Name); oPar.DataType := DATypeToVCLType(GetParams[i].DataType); if oPar.DataType = ftAutoInc then oPar.DataType := ftInteger; end; if AValue then NativeObject.FCmd.Prepare else NativeObject.FCmd.Unprepare; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACQueryNative.ClearParams; begin inherited; NativeObject.FCmd.Params.Clear; end; {------------------------------------------------------------------------------} function TDAEAnyDACQueryNative.DoExecute: integer; var oConnMeta: IADPhysConnectionMetadata; begin with NativeObject.FCmd do begin // 1) SELECT command on MSSQL, etc may be without result set, for example: // SELECT :CUSTOMERS_CNT = count(*) from customers // 2) On Oracle skExecute is handled specially (PL/SQL) and commands as // above are not possible Connection.CreateMetadata(oConnMeta); if oConnMeta.Kind <> mkOracle then CommandKind := skExecute; Execute; if RowsAffectedReal then Result := RowsAffected else Result := 0; end; end; {------------------------------------------------------------------------------} function TDAEAnyDACQueryNative.DoGetSQL: string; begin Result := NativeObject.FCmd.CommandText; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACQueryNative.DoSetSQL(const AValue: string); begin NativeObject.FCmd.CommandText := AValue; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACQueryNative.SetParamValues(AParams: TDAParamCollection); begin SetADParamValuesFromDA(AParams, NativeObject.FCmd.Params, True); end; {------------------------------------------------------------------------------} procedure TDAEAnyDACQueryNative.GetParamValues(AParams: TDAParamCollection); begin GetDAParamValuesFromAD(GetParams, NativeObject.FCmd.Params); end; {------------------------------------------------------------------------------} { TDAEAnyDACStoredProcedureNative } {------------------------------------------------------------------------------} function TDAEAnyDACStoredProcedureNative.GetNativeObject: TDAEAnyDACNativeDatabaseAccess; begin Result := TDAEAnyDACNativeDatabaseAccess(inherited NativeObject); end; {------------------------------------------------------------------------------} function TDAEAnyDACStoredProcedureNative.CreateDataset(aConnection: TDAEConnection): TDataset; begin Result := nil; end; {------------------------------------------------------------------------------} function TDAEAnyDACStoredProcedureNative.CreateNativeDatabaseAccess: IDANativeDatabaseAccess; begin Supports(NativeObject, IDANativeDatabaseAccess, Result); end; {------------------------------------------------------------------------------} function TDAEAnyDACStoredProcedureNative.CreateNativeObject(aConnection: TDAEConnection): TObject; begin Result := TDAEAnyDACNativeDatabaseAccess.Create(TDAEAnyDACConnection(aConnection)); TDAEAnyDACNativeDatabaseAccess(Result).FCmd.CommandKind := skStoredProc; TDAEAnyDACConnection(aConnection).SetupOptions(TDAEAnyDACNativeDatabaseAccess(Result).FCmd.Options, False); end; {------------------------------------------------------------------------------} function TDAEAnyDACStoredProcedureNative.GetStoredProcedureName: string; begin Result := NativeObject.FCmd.CommandText; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACStoredProcedureNative.SetStoredProcedureName(const Name: string); begin NativeObject.FCmd.CommandText := Name; end; {------------------------------------------------------------------------------} function TDAEAnyDACStoredProcedureNative.DoExecute: integer; begin with NativeObject.FCmd do begin Execute(); if RowsAffectedReal then Result := RowsAffected else Result := 0; end; end; {------------------------------------------------------------------------------} function TDAEAnyDACStoredProcedureNative.Execute: integer; var oADParams: TADParams; oDAParams: TDAParamCollection; begin oADParams := NativeObject.FCmd.Params; oDAParams := GetParams; if oADParams.Count <> oDAParams.Count then NativeObject.FCmd.Prepare; SetADParamValuesFromDA(oDAParams, oADParams, False); Result := DoExecute; // in case of SP the reference to params may be invalid after execution oADParams := NativeObject.FCmd.Params; GetDAParamValuesFromAD(oDAParams, oADParams); end; {------------------------------------------------------------------------------} procedure TDAEAnyDACStoredProcedureNative.RefreshParams; var oDAParams: TDAParamCollection; oDAParam: TDAParam; i: Integer; begin NativeObject.FCmd.Prepare; oDAParams := GetParams; oDAParams.Clear; with NativeObject.FCmd do for i := 0 to Params.Count - 1 do begin oDAParam := oDAParams.Add; oDAParam.Name := Params[i].Name; oDAParam.DataType := VCLTypeToDAType(Params[i].DataType); oDAParam.ParamType := TDAParamType(Params[i].ParamType); oDAParam.Size := Params[i].Size; end; end; {------------------------------------------------------------------------------} procedure TDAEAnyDACStoredProcedureNative.GetParamValues(AParams: TDAParamCollection); begin SetADParamValuesFromDA(AParams, NativeObject.FCmd.Params, False); end; {------------------------------------------------------------------------------} procedure TDAEAnyDACStoredProcedureNative.SetParamValues(AParams: TDAParamCollection); begin GetDAParamValuesFromAD(AParams, NativeObject.FCmd.Params); end; {------------------------------------------------------------------------------} { Registration and factory code } {------------------------------------------------------------------------------} var _driver: TDAEDriver = nil; {------------------------------------------------------------------------------} procedure Register; begin RegisterComponents(DAPalettePageName, [TDAAnyDACDriver]); end; {------------------------------------------------------------------------------} function GetDriverObject: IDADriver; begin {$IFDEF DataAbstract_SchemaModelerOnly} if not RunningInSchemaModeler then begin result := nil; exit; end; {$ENDIF} if _driver = nil then _driver := TDAEAnyDACDriver.Create(nil); result := _driver; end; {------------------------------------------------------------------------------} exports GetDriverObject name func_GetDriverObject; function TDAEAnyDACConnection.GetMySQLVersion: integer; begin if FMySQLVersion = -1 then FMySQLVersion := MYSQL_GetVersion(GetDatasetClass.Create(Self)); Result := FMySQLVersion; end; function TDAEAnyDACNativeDatabaseAccess.IsNull(Index: integer): Boolean; var Data: pointer; DataSize: Cardinal; begin Result := not FTab.Rows[FRowIndex].GetData(Index, rvDefault, Data, 0, DataSize, False); end; initialization {$IFDEF FPC} {$I DataAbstract_AnyDACDriver_Glyphs.lrs} {$ENDIF} _driver := nil; RegisterDriverProc(GetDriverObject); finalization UnregisterDriverProc(GetDriverObject); FreeAndNil(_driver); end.