|
@@ -21,10 +21,10 @@ type
|
|
|
|
|
|
TPQTrans = Class(TSQLHandle)
|
|
TPQTrans = Class(TSQLHandle)
|
|
protected
|
|
protected
|
|
- PGConn : PPGConn;
|
|
|
|
- FList : TThreadList;
|
|
|
|
- Procedure RegisterCursor(S : TPQCursor);
|
|
|
|
- Procedure UnRegisterCursor(S : TPQCursor);
|
|
|
|
|
|
+ PGConn : PPGConn;
|
|
|
|
+ FList : TThreadList;
|
|
|
|
+ Procedure RegisterCursor(Cursor : TPQCursor);
|
|
|
|
+ Procedure UnRegisterCursor(Cursor : TPQCursor);
|
|
Public
|
|
Public
|
|
Constructor Create;
|
|
Constructor Create;
|
|
Destructor Destroy; override;
|
|
Destructor Destroy; override;
|
|
@@ -60,6 +60,8 @@ type
|
|
Destructor Destroy; override;
|
|
Destructor Destroy; override;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+ { EPQDatabaseError }
|
|
|
|
+
|
|
EPQDatabaseError = class(EDatabaseError)
|
|
EPQDatabaseError = class(EDatabaseError)
|
|
public
|
|
public
|
|
SEVERITY:string;
|
|
SEVERITY:string;
|
|
@@ -70,6 +72,8 @@ type
|
|
STATEMENT_POSITION:string;
|
|
STATEMENT_POSITION:string;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+ { TPQTranConnection }
|
|
|
|
+
|
|
TPQTranConnection = class
|
|
TPQTranConnection = class
|
|
protected
|
|
protected
|
|
FPGConn : PPGConn;
|
|
FPGConn : PPGConn;
|
|
@@ -125,7 +129,7 @@ type
|
|
function RowsAffected(cursor: TSQLCursor): TRowsCount; override;
|
|
function RowsAffected(cursor: TSQLCursor): TRowsCount; override;
|
|
public
|
|
public
|
|
constructor Create(AOwner : TComponent); override;
|
|
constructor Create(AOwner : TComponent); override;
|
|
- destructor destroy; override;
|
|
|
|
|
|
+ destructor Destroy; override;
|
|
function GetConnectionInfo(InfoType:TConnInfoType): string; override;
|
|
function GetConnectionInfo(InfoType:TConnInfoType): string; override;
|
|
procedure CreateDB; override;
|
|
procedure CreateDB; override;
|
|
procedure DropDB; override;
|
|
procedure DropDB; override;
|
|
@@ -189,23 +193,12 @@ const Oid_Bool = 16;
|
|
oid_numeric = 1700;
|
|
oid_numeric = 1700;
|
|
Oid_uuid = 2950;
|
|
Oid_uuid = 2950;
|
|
|
|
|
|
-{ TPQTrans }
|
|
|
|
|
|
|
|
-procedure TPQTrans.RegisterCursor(S: TPQCursor);
|
|
|
|
-begin
|
|
|
|
- FList.Add(S);
|
|
|
|
- S.tr:=Self;
|
|
|
|
-end;
|
|
|
|
-
|
|
|
|
-procedure TPQTrans.UnRegisterCursor(S: TPQCursor);
|
|
|
|
-begin
|
|
|
|
- S.tr:=Nil;
|
|
|
|
- FList.Remove(S);
|
|
|
|
-end;
|
|
|
|
|
|
+{ TPQTrans }
|
|
|
|
|
|
constructor TPQTrans.Create;
|
|
constructor TPQTrans.Create;
|
|
begin
|
|
begin
|
|
- Flist:=TThreadList.Create;
|
|
|
|
|
|
+ FList:=TThreadList.Create;
|
|
FList.Duplicates:=dupIgnore;
|
|
FList.Duplicates:=dupIgnore;
|
|
end;
|
|
end;
|
|
|
|
|
|
@@ -216,19 +209,39 @@ Var
|
|
I : integer;
|
|
I : integer;
|
|
|
|
|
|
begin
|
|
begin
|
|
- L:=Flist.LockList;
|
|
|
|
|
|
+ L:=FList.LockList;
|
|
try
|
|
try
|
|
For I:=0 to L.Count-1 do
|
|
For I:=0 to L.Count-1 do
|
|
TPQCursor(L[i]).tr:=Nil;
|
|
TPQCursor(L[i]).tr:=Nil;
|
|
finally
|
|
finally
|
|
- Flist.UnlockList;
|
|
|
|
|
|
+ FList.UnlockList;
|
|
end;
|
|
end;
|
|
FreeAndNil(FList);
|
|
FreeAndNil(FList);
|
|
inherited Destroy;
|
|
inherited Destroy;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+procedure TPQTrans.RegisterCursor(Cursor: TPQCursor);
|
|
|
|
+begin
|
|
|
|
+ FList.Add(Cursor);
|
|
|
|
+ Cursor.tr:=Self;
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+procedure TPQTrans.UnRegisterCursor(Cursor: TPQCursor);
|
|
|
|
+begin
|
|
|
|
+ Cursor.tr:=Nil;
|
|
|
|
+ FList.Remove(Cursor);
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+
|
|
{ TPQCursor }
|
|
{ TPQCursor }
|
|
|
|
|
|
|
|
+destructor TPQCursor.Destroy;
|
|
|
|
+begin
|
|
|
|
+ if Assigned(tr) then
|
|
|
|
+ tr.UnRegisterCursor(Self);
|
|
|
|
+ inherited Destroy;
|
|
|
|
+end;
|
|
|
|
+
|
|
function TPQCursor.GetFieldBinding(F: TFieldDef): PFieldBinding;
|
|
function TPQCursor.GetFieldBinding(F: TFieldDef): PFieldBinding;
|
|
|
|
|
|
Var
|
|
Var
|
|
@@ -252,13 +265,8 @@ begin
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
-destructor TPQCursor.Destroy;
|
|
|
|
-begin
|
|
|
|
- if Assigned(tr) then
|
|
|
|
- Tr.UnRegisterCursor(Self);
|
|
|
|
- inherited Destroy;
|
|
|
|
-end;
|
|
|
|
|
|
|
|
|
|
+{ TPQConnection }
|
|
|
|
|
|
constructor TPQConnection.Create(AOwner : TComponent);
|
|
constructor TPQConnection.Create(AOwner : TComponent);
|
|
|
|
|
|
@@ -270,7 +278,7 @@ begin
|
|
FConnectionPool:=TThreadlist.Create;
|
|
FConnectionPool:=TThreadlist.Create;
|
|
end;
|
|
end;
|
|
|
|
|
|
-destructor TPQConnection.destroy;
|
|
|
|
|
|
+destructor TPQConnection.Destroy;
|
|
begin
|
|
begin
|
|
// We must disconnect here. If it is done in inherited, then connection pool is gone.
|
|
// We must disconnect here. If it is done in inherited, then connection pool is gone.
|
|
Connected:=False;
|
|
Connected:=False;
|
|
@@ -432,6 +440,7 @@ var
|
|
begin
|
|
begin
|
|
result := false;
|
|
result := false;
|
|
tr := trans as TPQTrans;
|
|
tr := trans as TPQTrans;
|
|
|
|
+ // unprepare statements associated with given transaction
|
|
L:=tr.FList.LockList;
|
|
L:=tr.FList.LockList;
|
|
try
|
|
try
|
|
For I:=0 to L.Count-1 do
|
|
For I:=0 to L.Count-1 do
|
|
@@ -441,8 +450,9 @@ begin
|
|
end;
|
|
end;
|
|
L.Clear;
|
|
L.Clear;
|
|
finally
|
|
finally
|
|
- tr.flist.UnlockList;
|
|
|
|
|
|
+ tr.FList.UnlockList;
|
|
end;
|
|
end;
|
|
|
|
+
|
|
res := PQexec(tr.PGConn, 'ROLLBACK');
|
|
res := PQexec(tr.PGConn, 'ROLLBACK');
|
|
CheckResultError(res,tr.PGConn,SErrRollbackFailed);
|
|
CheckResultError(res,tr.PGConn,SErrRollbackFailed);
|
|
PQclear(res);
|
|
PQclear(res);
|
|
@@ -465,22 +475,50 @@ begin
|
|
result := true;
|
|
result := true;
|
|
end;
|
|
end;
|
|
|
|
|
|
-function TPQConnection.StartImplicitTransaction(trans : TSQLHandle; AParams : string) : boolean;
|
|
|
|
|
|
+procedure TPQConnection.RollBackRetaining(trans : TSQLHandle);
|
|
var
|
|
var
|
|
|
|
+ res : PPGresult;
|
|
tr : TPQTrans;
|
|
tr : TPQTrans;
|
|
- i : Integer;
|
|
|
|
- t : TPQTranConnection;
|
|
|
|
- L : TList;
|
|
|
|
begin
|
|
begin
|
|
- result:=false;
|
|
|
|
tr := trans as TPQTrans;
|
|
tr := trans as TPQTrans;
|
|
|
|
+ res := PQexec(tr.PGConn, 'ROLLBACK');
|
|
|
|
+ CheckResultError(res,tr.PGConn,SErrRollbackFailed);
|
|
|
|
|
|
|
|
+ PQclear(res);
|
|
|
|
+ res := PQexec(tr.PGConn, 'BEGIN');
|
|
|
|
+ CheckResultError(res,tr.PGConn,sErrTransactionFailed);
|
|
|
|
+
|
|
|
|
+ PQclear(res);
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+procedure TPQConnection.CommitRetaining(trans : TSQLHandle);
|
|
|
|
+var
|
|
|
|
+ res : PPGresult;
|
|
|
|
+ tr : TPQTrans;
|
|
|
|
+begin
|
|
|
|
+ tr := trans as TPQTrans;
|
|
|
|
+ res := PQexec(tr.PGConn, 'COMMIT');
|
|
|
|
+ CheckResultError(res,tr.PGConn,SErrCommitFailed);
|
|
|
|
+
|
|
|
|
+ PQclear(res);
|
|
|
|
+ res := PQexec(tr.PGConn, 'BEGIN');
|
|
|
|
+ CheckResultError(res,tr.PGConn,sErrTransactionFailed);
|
|
|
|
+
|
|
|
|
+ PQclear(res);
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+function TPQConnection.StartImplicitTransaction(trans : TSQLHandle; AParams : string) : boolean;
|
|
|
|
+var
|
|
|
|
+ i : Integer;
|
|
|
|
+ T : TPQTranConnection;
|
|
|
|
+ L : TList;
|
|
|
|
+begin
|
|
//find an unused connection in the pool
|
|
//find an unused connection in the pool
|
|
i:=0;
|
|
i:=0;
|
|
- t:=Nil;
|
|
|
|
|
|
+ T:=Nil;
|
|
L:=FConnectionPool.LockList;
|
|
L:=FConnectionPool.LockList;
|
|
try
|
|
try
|
|
- while (I<L.Count) do
|
|
|
|
|
|
+ while (i<L.Count) do
|
|
begin
|
|
begin
|
|
T:=TPQTranConnection(L[i]);
|
|
T:=TPQTranConnection(L[i]);
|
|
if (T.FPGConn=nil) or not T.FTranActive then
|
|
if (T.FPGConn=nil) or not T.FTranActive then
|
|
@@ -496,55 +534,24 @@ begin
|
|
finally
|
|
finally
|
|
FConnectionPool.UnLockList;
|
|
FConnectionPool.UnLockList;
|
|
end;
|
|
end;
|
|
|
|
+
|
|
if (T=Nil) then
|
|
if (T=Nil) then
|
|
begin
|
|
begin
|
|
T:=TPQTranConnection.Create;
|
|
T:=TPQTranConnection.Create;
|
|
T.FTranActive:=True;
|
|
T.FTranActive:=True;
|
|
AddConnection(T);
|
|
AddConnection(T);
|
|
end;
|
|
end;
|
|
- if (T.FPGConn<>nil) then
|
|
|
|
- tr.PGConn:=T.FPGConn
|
|
|
|
- else
|
|
|
|
|
|
+
|
|
|
|
+ if (T.FPGConn=nil) then
|
|
begin
|
|
begin
|
|
- tr.PGConn := PQconnectdb(pchar(FConnectString));
|
|
|
|
- T.FPGConn:=tr.PGConn;
|
|
|
|
- CheckConnectionStatus(tr.PGConn);
|
|
|
|
|
|
+ T.FPGConn := PQconnectdb(pchar(FConnectString));
|
|
|
|
+ CheckConnectionStatus(T.FPGConn);
|
|
if CharSet <> '' then
|
|
if CharSet <> '' then
|
|
- PQsetClientEncoding(tr.PGConn, pchar(CharSet));
|
|
|
|
|
|
+ PQsetClientEncoding(T.FPGConn, pchar(CharSet));
|
|
end;
|
|
end;
|
|
- result := true;
|
|
|
|
-end;
|
|
|
|
|
|
|
|
-procedure TPQConnection.RollBackRetaining(trans : TSQLHandle);
|
|
|
|
-var
|
|
|
|
- res : PPGresult;
|
|
|
|
- tr : TPQTrans;
|
|
|
|
-begin
|
|
|
|
- tr := trans as TPQTrans;
|
|
|
|
- res := PQexec(tr.PGConn, 'ROLLBACK');
|
|
|
|
- CheckResultError(res,tr.PGConn,SErrRollbackFailed);
|
|
|
|
-
|
|
|
|
- PQclear(res);
|
|
|
|
- res := PQexec(tr.PGConn, 'BEGIN');
|
|
|
|
- CheckResultError(res,tr.PGConn,sErrTransactionFailed);
|
|
|
|
-
|
|
|
|
- PQclear(res);
|
|
|
|
-end;
|
|
|
|
-
|
|
|
|
-procedure TPQConnection.CommitRetaining(trans : TSQLHandle);
|
|
|
|
-var
|
|
|
|
- res : PPGresult;
|
|
|
|
- tr : TPQTrans;
|
|
|
|
-begin
|
|
|
|
- tr := trans as TPQTrans;
|
|
|
|
- res := PQexec(tr.PGConn, 'COMMIT');
|
|
|
|
- CheckResultError(res,tr.PGConn,SErrCommitFailed);
|
|
|
|
-
|
|
|
|
- PQclear(res);
|
|
|
|
- res := PQexec(tr.PGConn, 'BEGIN');
|
|
|
|
- CheckResultError(res,tr.PGConn,sErrTransactionFailed);
|
|
|
|
-
|
|
|
|
- PQclear(res);
|
|
|
|
|
|
+ TPQTrans(trans).PGConn := T.FPGConn;
|
|
|
|
+ Result := true;
|
|
end;
|
|
end;
|
|
|
|
|
|
function TPQConnection.StartDBTransaction(trans: TSQLHandle;
|
|
function TPQConnection.StartDBTransaction(trans: TSQLHandle;
|
|
@@ -866,7 +873,6 @@ var
|
|
i : integer;
|
|
i : integer;
|
|
P : TParam;
|
|
P : TParam;
|
|
PQ : TSQLDBParam;
|
|
PQ : TSQLDBParam;
|
|
- r : PPGresult;
|
|
|
|
|
|
|
|
begin
|
|
begin
|
|
with (cursor as TPQCursor) do
|
|
with (cursor as TPQCursor) do
|
|
@@ -1029,7 +1035,7 @@ begin
|
|
end
|
|
end
|
|
else
|
|
else
|
|
begin
|
|
begin
|
|
- // Registercursor sets tr
|
|
|
|
|
|
+ // RegisterCursor sets tr
|
|
TPQTrans(aTransaction.Handle).RegisterCursor(Cursor as TPQCursor);
|
|
TPQTrans(aTransaction.Handle).RegisterCursor(Cursor as TPQCursor);
|
|
|
|
|
|
if Assigned(AParams) and (AParams.Count > 0) then
|
|
if Assigned(AParams) and (AParams.Count > 0) then
|
|
@@ -1119,7 +1125,7 @@ begin
|
|
end
|
|
end
|
|
else
|
|
else
|
|
if ErrorOnUnknownType then
|
|
if ErrorOnUnknownType then
|
|
- DatabaseError('unhandled field type :'+FB^.TypeName,Self);
|
|
|
|
|
|
+ DatabaseError('Unhandled field type :'+FB^.TypeName,Self);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|