git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.RemObjects@46 b6239004-a887-0f4b-9937-50029ccdca16
233 lines
6.2 KiB
ObjectPascal
233 lines
6.2 KiB
ObjectPascal
unit uDAHETDriver;
|
|
|
|
{----------------------------------------------------------------------------}
|
|
{ Data Abstract Library - 'Rosetta' Library - HIGHLY CONFIDENTIAL
|
|
{
|
|
{ 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.
|
|
{----------------------------------------------------------------------------}
|
|
|
|
{$I DataAbstract.inc}
|
|
|
|
interface
|
|
|
|
// {$R DataAbstract_Rosetta_Glyphs.res}
|
|
|
|
uses
|
|
Classes, SysUtils,
|
|
uDAInterfaces, uDAClasses, uDAEngine, uDARes, uDADriverManager,
|
|
uDAHETConnections, DB;
|
|
|
|
type
|
|
TDAHETDriver = class(TDADriverReference)
|
|
end;
|
|
|
|
TDAEHETDriver = class(TDAEDriver)
|
|
protected
|
|
function GetConnectionClass: TDAEConnectionClass; override;
|
|
|
|
function GetDriverID: string; override;
|
|
function GetDescription: string; override;
|
|
public
|
|
end;
|
|
|
|
TDAEHETConnection = class(TDAEConnection, IDAHETConnection)
|
|
private
|
|
fInTransaction: boolean;
|
|
fActiveConnections: TStringList;
|
|
function GetConnectionByName(const aConnectionName: string; aOpenConnection: boolean = false): IDAConnection;
|
|
protected
|
|
function DoBeginTransaction: Integer; override;
|
|
procedure DoCommitTransaction; override;
|
|
procedure DoRollbackTransaction; override;
|
|
function DoGetInTransaction: Boolean; override;
|
|
|
|
function CreateCustomConnection: TCustomConnection; override;
|
|
function GetConnected: Boolean; override; {$IFNDEF FPC_SAFECALL_BUG}safecall;{$ENDIF}
|
|
public
|
|
constructor Create(aDriver: TDAEDriver; aName: string = ''); override;
|
|
destructor Destroy; override;
|
|
|
|
{ IDAHETConnection }
|
|
function GetConnectionForObject(const aObjectName: string; aOpenConnection: boolean = false): IDAConnection;
|
|
|
|
end;
|
|
|
|
TDAHETConnectionContainer = class
|
|
private
|
|
fConnection: IDAConnection;
|
|
constructor Create(aConnection: IDAConnection);
|
|
end;
|
|
|
|
procedure Register;
|
|
function GetDriverObject: IDADriver; stdcall;
|
|
|
|
implementation
|
|
|
|
{ TDAEHETDriver }
|
|
|
|
function TDAEHETDriver.GetConnectionClass: TDAEConnectionClass;
|
|
begin
|
|
result := TDAEHETConnection;
|
|
end;
|
|
|
|
function TDAEHETDriver.GetDescription: string;
|
|
begin
|
|
result := 'Connection for Heterogenous Queries across multiple databases';
|
|
end;
|
|
|
|
function TDAEHETDriver.GetDriverID: string;
|
|
begin
|
|
result := 'HET';
|
|
end;
|
|
|
|
{ TDAEHETConnection }
|
|
|
|
constructor TDAEHETConnection.Create(aDriver: TDAEDriver; aName: string = '');
|
|
begin
|
|
inherited;
|
|
fActiveConnections := TStringList.Create();
|
|
fActiveConnections.Sorted := true;
|
|
fActiveConnections.Duplicates := dupError;
|
|
end;
|
|
|
|
function TDAEHETConnection.CreateCustomConnection: TCustomConnection;
|
|
begin
|
|
result := nil;
|
|
end;
|
|
|
|
destructor TDAEHETConnection.Destroy;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
for i := 0 to fActiveConnections.Count-1 do
|
|
fActiveConnections.Objects[i].Free();
|
|
FreeAndNil(fActiveConnections);
|
|
|
|
//ToDo: auto-transacton handling?
|
|
|
|
inherited;
|
|
end;
|
|
|
|
function TDAEHETConnection.DoBeginTransaction: Integer;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
if fInTransaction then
|
|
raise Exception.Create('Already in a transaction');
|
|
|
|
for i := 0 to fActiveConnections.Count-1 do
|
|
(fActiveConnections.Objects[i] as TDAHETConnectionContainer).fConnection.BeginTransaction();
|
|
|
|
fInTransaction := true;
|
|
result := 0;
|
|
end;
|
|
|
|
procedure TDAEHETConnection.DoCommitTransaction;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
inherited;
|
|
|
|
try
|
|
for i := 0 to fActiveConnections.Count-1 do
|
|
(fActiveConnections.Objects[i] as TDAHETConnectionContainer).fConnection.CommitTransaction();
|
|
except
|
|
// ToDo: we need to use a two-phase commit here, to properly handle any single commit failing
|
|
// to roll back ALL transactons (inclusing those already (tentatively) comitted.
|
|
DoRollbackTransaction();
|
|
raise;
|
|
end;
|
|
|
|
fInTransaction := false;
|
|
end;
|
|
|
|
procedure TDAEHETConnection.DoRollbackTransaction;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
inherited;
|
|
|
|
for i := 0 to fActiveConnections.Count-1 do
|
|
(fActiveConnections.Objects[i] as TDAHETConnectionContainer).fConnection.RollbackTransaction();
|
|
|
|
fInTransaction := false;
|
|
end;
|
|
|
|
function TDAEHETConnection.DoGetInTransaction: Boolean;
|
|
begin
|
|
result := fInTransaction;
|
|
end;
|
|
|
|
function TDAEHETConnection.GetConnected: Boolean;
|
|
begin
|
|
result := true;
|
|
end;
|
|
|
|
function TDAEHETConnection.GetConnectionForObject(const aObjectName: string; aOpenConnection: boolean = false): IDAConnection;
|
|
var
|
|
lConnectionName: string;
|
|
begin
|
|
lConnectionName := (ConnectionDefinition as TDAHETConnection).ObjectMappings.Values[aObjectName];
|
|
if lConnectionName = '' then
|
|
raise Exception.CreateFmt('HET Connection "%s" does not contain an object mapping for "%s".', [ConnectionName, aObjectName]);
|
|
result := GetConnectionByName(lConnectionName);
|
|
end;
|
|
|
|
function TDAEHETConnection.GetConnectionByName(const aConnectionName: string; aOpenConnection: boolean = false): IDAConnection;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
if aConnectionName = self.ConnectionName then
|
|
raise Exception.CreateFmt('Cannot use HET Connection "%s" nested within itself.', [ConnectionName]);
|
|
|
|
i := fActiveConnections.IndexOf(aConnectionName);
|
|
if i >= 0 then begin
|
|
result := (fActiveConnections.Objects[i] as TDAHETConnectionContainer).fConnection
|
|
end
|
|
else begin
|
|
result := ConnectionManager.NewConnection(aConnectionName, true); //todo: aOpenConnection
|
|
if fInTransaction then result.BeginTransaction;
|
|
fActiveConnections.AddObject(aConnectionName, TDAHETConnectionContainer.Create(result));
|
|
end;
|
|
end;
|
|
|
|
{ TDAHETConnectionContainer }
|
|
|
|
constructor TDAHETConnectionContainer.Create(aConnection: IDAConnection);
|
|
begin
|
|
fConnection := aConnection;
|
|
end;
|
|
|
|
{ global driver registration }
|
|
|
|
var
|
|
_driver: TDAEDriver = nil;
|
|
|
|
procedure Register;
|
|
begin
|
|
RegisterComponents(DAPalettePageName, [TDAHETDriver]);
|
|
end;
|
|
|
|
function GetDriverObject: IDADriver;
|
|
begin
|
|
if (_driver = nil) then _driver := TDAEHETDriver.Create(nil);
|
|
result := _driver;
|
|
end;
|
|
|
|
exports
|
|
GetDriverObject name func_GetDriverObject;
|
|
|
|
initialization
|
|
_driver := nil;
|
|
RegisterDriverProc(GetDriverObject);
|
|
finalization
|
|
UnregisterDriverProc(GetDriverObject);
|
|
FreeAndNIL(_driver);
|
|
end.
|