git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.RemObjects@2 b6239004-a887-0f4b-9937-50029ccdca16
494 lines
14 KiB
ObjectPascal
494 lines
14 KiB
ObjectPascal
unit uDAIBXDriver;
|
|
|
|
{----------------------------------------------------------------------------}
|
|
{ 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.
|
|
{----------------------------------------------------------------------------}
|
|
|
|
{$IFDEF MSWINDOWS}
|
|
{$I ..\DataAbstract.inc}
|
|
{$ENDIF MSWINDOWS}
|
|
{$IFDEF LINUX}
|
|
{$I ../DataAbstract.inc}
|
|
{$ENDIF LINUX}
|
|
|
|
{$R DataAbstract_IBXDriver_Glyphs.res}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, DB, uDAEngine, uDAInterfaces, uDAIBInterfaces, IBDatabase,
|
|
uROClasses, IBQuery, IBStoredProc, IBSQLMonitor, IB, uDAUtils;
|
|
|
|
type
|
|
{ TDAIBXDriver }
|
|
TDAIBXDriver = class(TDADriverReference)
|
|
end;
|
|
|
|
{ TIBXConnection }
|
|
TIBXConnection = class(TDAConnectionWrapper)
|
|
private
|
|
fDatabase: TIBDatabase;
|
|
fTransaction: TIBTransaction;
|
|
|
|
protected
|
|
function GetConnected: Boolean; override;
|
|
procedure SetConnected(Value: boolean); override;
|
|
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
|
|
property Database: TIBDatabase read fDatabase;
|
|
property Transaction: TIBTransaction read fTransaction;
|
|
end;
|
|
|
|
{ TDAEIBXDriver }
|
|
TDAEIBXDriver = class(TDAIBDriver)
|
|
private
|
|
fIBTraceOptions: TTraceFlags;
|
|
fTraceCallback: TDALogTraceEvent;
|
|
fMonitor: TIBSQLMonitor;
|
|
|
|
procedure OnIBXTrace(EventText: string; EventTime: TDateTime);
|
|
protected
|
|
function GetConnectionClass: TDAEConnectionClass; override;
|
|
procedure CustomizeConnectionObject(aConnection: TDAEConnection); override;
|
|
procedure DoSetTraceOptions(TraceActive: boolean; TraceOptions: TDATraceOptions; Callback: TDALogTraceEvent); override;
|
|
|
|
// IDADriver
|
|
function GetDriverID: string; override;
|
|
function GetDescription: string; override;
|
|
public
|
|
end;
|
|
|
|
{ TDAEIBXConnection }
|
|
TDAEIBXConnection = class(TDAIBConnection, IDAInterbaseConnection, IDAIBTransactionAccess, IDAIBConnectionProperties, IDAUseGenerators, IDAFileBasedDatabase)
|
|
private
|
|
fConnection: TIBXConnection;
|
|
|
|
protected
|
|
// IIBTransactionAccess
|
|
function GetTransaction: TObject; safecall;
|
|
|
|
procedure Commit; safecall;
|
|
procedure CommitRetaining; safecall;
|
|
procedure Rollback; safecall;
|
|
procedure RollbackRetaining; safecall;
|
|
|
|
// IIBConnectionProperties
|
|
function GetRole: string; safecall;
|
|
procedure SetRole(const Value: string); safecall;
|
|
function GetSQLDialect: integer; override;safecall;
|
|
procedure SetSQLDialect(Value: integer); safecall;
|
|
function GetCharset: string; safecall;
|
|
procedure SetCharset(const Value: string); safecall;
|
|
|
|
|
|
// IDAConnection
|
|
function CreateCustomConnection: TCustomConnection; override;
|
|
|
|
function GetDatasetClass: TDAEDatasetClass; override;
|
|
function GetStoredProcedureClass: TDAEStoredProcedureClass; override;
|
|
|
|
procedure DoApplyConnectionString(aConnStrParser: TDAConnectionStringParser;
|
|
aConnectionObject: TCustomConnection); override;
|
|
|
|
function DoBeginTransaction: integer; override;
|
|
procedure DoCommitTransaction; override;
|
|
procedure DoRollbackTransaction; override;
|
|
function DoGetInTransaction: boolean; override;
|
|
|
|
end;
|
|
|
|
{ TDAEIBXQuery }
|
|
TDAEIBXQuery = class(TDAEDataset)
|
|
|
|
protected
|
|
function DoGetRecordCount: integer; override;
|
|
function CreateDataset(aConnection: TDAEConnection): TDataset; override;
|
|
|
|
function DoExecute: integer; override;
|
|
function DoGetSQL: string; override;
|
|
procedure DoSetSQL(const Value: string); override;
|
|
procedure DoPrepare(Value: boolean); override;
|
|
|
|
public
|
|
end;
|
|
|
|
{ TDAEIBXStoredProcedure }
|
|
TDAEIBXStoredProcedure = class(TDAEStoredProcedure, IDAMustSetParams)
|
|
protected
|
|
function CreateDataset(aConnection: TDAEConnection): TDataset; override;
|
|
|
|
procedure RefreshParams; override;
|
|
function GetStoredProcedureName: string; override;
|
|
procedure SetStoredProcedureName(const Name: string); override;
|
|
function Execute: integer; override;
|
|
procedure SetParamValues(Params: TDAParamCollection); safecall;
|
|
procedure GetParamValues(Params: TDAParamCollection); safecall;
|
|
end;
|
|
|
|
procedure Register;
|
|
|
|
function GetDriverObject: IDADriver; stdcall;
|
|
|
|
implementation
|
|
|
|
uses SysUtils, uDADriverManager, uDARes, IBCustomDataSet, IBSQL,uROBinaryHelpers;
|
|
|
|
var
|
|
_driver: TDAEDriver = nil;
|
|
|
|
procedure Register;
|
|
begin
|
|
RegisterComponents(DAPalettePageName, [TDAIBXDriver]);
|
|
end;
|
|
|
|
function GetDriverObject: IDADriver;
|
|
begin
|
|
if (_driver = nil) then _driver := TDAEIBXDriver.Create(nil);
|
|
result := _driver;
|
|
end;
|
|
|
|
{ TIBXConnection }
|
|
|
|
constructor TIBXConnection.Create(AOwner: TComponent);
|
|
begin
|
|
inherited;
|
|
|
|
fDatabase := TIBDatabase.Create(Self);
|
|
fTransaction := TIBTransaction.Create(Self);
|
|
fTransaction.AutoStopAction := saNone;
|
|
//fTransaction.AutoStopAction := saCommit;
|
|
// ^ new per recommendation from Andy Gibson, to fix the "Transaction in progress" error.
|
|
|
|
fDatabase.LoginPrompt := FALSE;
|
|
fDatabase.DefaultTransaction := fTransaction;
|
|
end;
|
|
|
|
function TIBXConnection.GetConnected: Boolean;
|
|
begin
|
|
result := fDatabase.Connected
|
|
end;
|
|
|
|
procedure TIBXConnection.SetConnected(Value: boolean);
|
|
begin
|
|
// This first check is required.
|
|
// I think there's a bug in the IBX destroying sequence and the notification. TCustomConnection gets to this point *after*
|
|
// the owned components are destroyed. Only happens with IBX...
|
|
|
|
if (csDestroying in ComponentState) then Exit;
|
|
fDatabase.Connected := Value
|
|
end;
|
|
|
|
{ TDAEIBXConnection }
|
|
|
|
procedure TDAEIBXConnection.DoApplyConnectionString(
|
|
aConnStrParser: TDAConnectionStringParser; aConnectionObject: TCustomConnection);
|
|
begin
|
|
inherited;
|
|
|
|
with aConnStrParser do begin
|
|
if (Self.UserID <> '') then
|
|
fConnection.Database.Params.Add('user_name=' + Self.UserID)
|
|
else
|
|
fConnection.Database.Params.Add('user_name=' + UserID);
|
|
|
|
if (Self.Password <> '') then
|
|
fConnection.Database.Params.Add('password=' + Self.Password)
|
|
else
|
|
fConnection.Database.Params.Add('password=' + Password);
|
|
|
|
if Server <> '' then { Change: Aleksander Oven, 27. july 2003 }
|
|
fConnection.Database.DatabaseName := Server + ':' + Database
|
|
else
|
|
fConnection.Database.DatabaseName := Database;
|
|
|
|
if AuxParams['Dialect'] <> '' then
|
|
SetSQLDialect(StrToInt(AuxParams['Dialect']))
|
|
else if AuxParams['SQLDialect'] <> '' then
|
|
SetSQLDialect(StrToInt(AuxParams['SQLDialect']));
|
|
|
|
if AuxParams['Role'] <> '' then
|
|
SetRole(AuxParams['Role']);
|
|
|
|
if AuxParams['Charset'] <> '' then
|
|
SetCharset(AuxParams['Charset']);
|
|
|
|
end;
|
|
end;
|
|
|
|
function TDAEIBXConnection.DoBeginTransaction: integer;
|
|
begin
|
|
result := -1;
|
|
fConnection.Database.DefaultTransaction.StartTransaction;
|
|
end;
|
|
|
|
procedure TDAEIBXConnection.DoCommitTransaction;
|
|
begin
|
|
fConnection.Database.DefaultTransaction.Commit;
|
|
end;
|
|
|
|
function TDAEIBXConnection.CreateCustomConnection: TCustomConnection;
|
|
begin
|
|
fConnection := TIBXConnection.Create(nil);
|
|
result := fConnection;
|
|
end;
|
|
|
|
function TDAEIBXConnection.GetDatasetClass: TDAEDatasetClass;
|
|
begin
|
|
result := TDAEIBXQuery
|
|
end;
|
|
|
|
function TDAEIBXConnection.GetStoredProcedureClass: TDAEStoredProcedureClass;
|
|
begin
|
|
result := TDAEIBXStoredProcedure
|
|
end;
|
|
|
|
function TDAEIBXConnection.GetTransaction: TObject;
|
|
begin
|
|
result := fConnection.fTransaction;
|
|
end;
|
|
|
|
procedure TDAEIBXConnection.DoRollbackTransaction;
|
|
begin
|
|
fConnection.Database.DefaultTransaction.Rollback;
|
|
end;
|
|
|
|
function TDAEIBXConnection.GetRole: string;
|
|
begin
|
|
result := fConnection.Database.Params.Values['sql_role_name']
|
|
end;
|
|
|
|
function TDAEIBXConnection.GetSQLDialect: integer;
|
|
begin
|
|
result := fConnection.Database.SQLDialect
|
|
end;
|
|
|
|
function TDAEIBXConnection.GetCharset: string;
|
|
begin
|
|
result := fConnection.Database.Params.Values['lc_ctype']
|
|
end;
|
|
|
|
procedure TDAEIBXConnection.SetRole(const Value: string);
|
|
begin
|
|
fConnection.Database.Params.Values['sql_role_name'] := Value
|
|
end;
|
|
|
|
procedure TDAEIBXConnection.SetSQLDialect(Value: integer);
|
|
begin
|
|
fConnection.Database.SQLDialect := Value
|
|
end;
|
|
|
|
procedure TDAEIBXConnection.SetCharset(const Value: string);
|
|
begin
|
|
fConnection.Database.Params.Values['lc_ctype'] := Value;
|
|
end;
|
|
|
|
procedure TDAEIBXConnection.Commit;
|
|
begin
|
|
fConnection.fTransaction.Commit
|
|
end;
|
|
|
|
procedure TDAEIBXConnection.CommitRetaining;
|
|
begin
|
|
fConnection.fTransaction.CommitRetaining
|
|
end;
|
|
|
|
procedure TDAEIBXConnection.Rollback;
|
|
begin
|
|
fConnection.fTransaction.Rollback
|
|
end;
|
|
|
|
procedure TDAEIBXConnection.RollbackRetaining;
|
|
begin
|
|
fConnection.fTransaction.RollbackRetaining
|
|
end;
|
|
|
|
function TDAEIBXConnection.DoGetInTransaction: boolean;
|
|
begin
|
|
result := fConnection.fTransaction.InTransaction
|
|
end;
|
|
|
|
{ TDAEIBXDriver }
|
|
|
|
procedure TDAEIBXDriver.CustomizeConnectionObject(aConnection: TDAEConnection);
|
|
begin
|
|
TDAEIBXConnection(aConnection).fConnection.Database.TraceFlags := fIBTraceOptions;
|
|
end;
|
|
|
|
function TDAEIBXDriver.GetConnectionClass: TDAEConnectionClass;
|
|
begin
|
|
result := TDAEIBXConnection;
|
|
end;
|
|
|
|
function TDAEIBXDriver.GetDescription: string;
|
|
begin
|
|
result := 'Borland Interbase Express Driver';
|
|
end;
|
|
|
|
function TDAEIBXDriver.GetDriverID: string;
|
|
begin
|
|
result := 'IBX';
|
|
end;
|
|
|
|
procedure TDAEIBXDriver.OnIBXTrace(EventText: string; EventTime: TDateTime);
|
|
begin
|
|
if Assigned(fTraceCallback) then fTraceCallback(fMonitor, EventText, 0);
|
|
end;
|
|
|
|
procedure TDAEIBXDriver.DoSetTraceOptions(TraceActive: boolean; TraceOptions: TDATraceOptions; Callback: TDALogTraceEvent);
|
|
begin
|
|
inherited;
|
|
|
|
if TraceActive then begin
|
|
if (fMonitor = nil) then fMonitor := TIBSQLMonitor.Create(Self);
|
|
|
|
fMonitor.Enabled := FALSE;
|
|
fMonitor.OnSQL := OnIBXTrace;
|
|
|
|
fIBTraceOptions := [];
|
|
if (toPrepare in TraceOptions) then fIBTraceOptions := fIBTraceOptions + [tfQPrepare];
|
|
if (toExecute in TraceOptions) then fIBTraceOptions := fIBTraceOptions + [tfQExecute];
|
|
if (toFetch in TraceOptions) then fIBTraceOptions := fIBTraceOptions + [tfQFetch];
|
|
if (toError in TraceOptions) then fIBTraceOptions := fIBTraceOptions + [tfError];
|
|
if (toStmt in TraceOptions) then fIBTraceOptions := fIBTraceOptions + [tfStmt];
|
|
if (toConnect in TraceOptions) then fIBTraceOptions := fIBTraceOptions + [tfConnect];
|
|
if (toTransact in TraceOptions) then fIBTraceOptions := fIBTraceOptions + [tfTransact];
|
|
if (toBlob in TraceOptions) then fIBTraceOptions := fIBTraceOptions + [tfBlob];
|
|
if (toService in TraceOptions) then fIBTraceOptions := fIBTraceOptions + [tfService];
|
|
if (toMisc in TraceOptions) then fIBTraceOptions := fIBTraceOptions + [tfMisc];
|
|
|
|
fTraceCallBack := Callback;
|
|
|
|
fMonitor.TraceFlags := fIBTraceOptions;
|
|
fMonitor.Enabled := TRUE;
|
|
end
|
|
else begin
|
|
FreeAndNIL(fMonitor);
|
|
fTraceCallback := nil;
|
|
end;
|
|
end;
|
|
|
|
{ TDAEIBXQuery }
|
|
|
|
function TDAEIBXQuery.CreateDataset(aConnection: TDAEConnection): TDataset;
|
|
begin
|
|
result := TIBQuery.Create(nil);
|
|
TIBQuery(result).UniDirectional := true;
|
|
TIBQuery(result).Database := TDAEIBXConnection(aConnection).fConnection.Database;
|
|
end;
|
|
|
|
function TDAEIBXQuery.DoExecute: integer;
|
|
begin
|
|
inherited DoExecute;
|
|
|
|
result := TIBQuery(Dataset).RowsAffected;
|
|
end;
|
|
|
|
function TDAEIBXQuery.DoGetRecordCount: integer;
|
|
begin
|
|
TIBQuery(Dataset).FetchAll;
|
|
Result := inherited DoGetRecordCount;
|
|
end;
|
|
|
|
function TDAEIBXQuery.DoGetSQL: string;
|
|
begin
|
|
result := TIBQuery(Dataset).SQL.Text
|
|
end;
|
|
|
|
procedure TDAEIBXQuery.DoPrepare(Value: boolean);
|
|
begin
|
|
TIBQuery(Dataset).Prepared := Value
|
|
end;
|
|
|
|
procedure TDAEIBXQuery.DoSetSQL(const Value: string);
|
|
begin
|
|
TIBQuery(Dataset).SQL.Text := Value;
|
|
end;
|
|
|
|
|
|
{ TDAEIBXStoredProcedure }
|
|
|
|
function TDAEIBXStoredProcedure.CreateDataset(
|
|
aConnection: TDAEConnection): TDataset;
|
|
begin
|
|
result := TIBStoredProc.Create(nil);
|
|
TIBStoredProc(result).Database := TDAEIBXConnection(aConnection).fConnection.Database;
|
|
end;
|
|
|
|
function TDAEIBXStoredProcedure.Execute: integer;
|
|
begin
|
|
SetParamValues(GetParams);
|
|
TIBStoredProc(Dataset).ExecProc;
|
|
result := TIBStoredProc(Dataset).RowsAffected;
|
|
GetParamValues(GetParams);
|
|
end;
|
|
|
|
procedure TDAEIBXStoredProcedure.SetParamValues(Params: TDAParamCollection); safecall;
|
|
var
|
|
i: integer;
|
|
sqPar: TParam;
|
|
begin
|
|
for i := 0 to (Params.Count - 1) do
|
|
if (Params[i].ParamType in [daptInput, daptInputOutput, daptUnknown]) then begin
|
|
sqPar := TIBStoredProc(Dataset).ParamByName(Params[i].Name);
|
|
if (Params[i].DataType <> datBlob) then
|
|
sqPar.Value := params[i].Value
|
|
else begin
|
|
sqPar.AsBlob:=VariantBinaryToString(params[i].Value);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TDAEIBXStoredProcedure.GetParamValues(Params: TDAParamCollection); safecall;
|
|
var
|
|
i: integer;
|
|
sqPar: TParam;
|
|
begin
|
|
for i := 0 to (Params.Count - 1) do
|
|
if (Params[i].ParamType in [daptOutput, daptInputOutput, daptResult]) then begin
|
|
sqPar := TIBStoredProc(Dataset).ParamByName(Params[i].Name);
|
|
params[i].Value := sqPar.Value
|
|
end;
|
|
end;
|
|
|
|
function TDAEIBXStoredProcedure.GetStoredProcedureName: string;
|
|
begin
|
|
result := TIBStoredProc(Dataset).StoredProcName
|
|
end;
|
|
|
|
procedure TDAEIBXStoredProcedure.SetStoredProcedureName(
|
|
const Name: string);
|
|
begin
|
|
TIBStoredProc(Dataset).StoredProcName := Name;
|
|
end;
|
|
|
|
procedure TDAEIBXStoredProcedure.RefreshParams;
|
|
begin
|
|
// Apparently a bug in IBX requires to do so... Automatic gathering only works at runtime
|
|
TIBStoredProc(Dataset).Prepare;
|
|
|
|
inherited;
|
|
end;
|
|
|
|
exports
|
|
GetDriverObject name func_GetDriverObject;
|
|
|
|
initialization
|
|
_driver := nil;
|
|
RegisterDriverProc(GetDriverObject);
|
|
|
|
finalization
|
|
UnregisterDriverProc(GetDriverObject);
|
|
FreeAndNIL(_driver);
|
|
|
|
end.
|