* Fixed ROLLBACK : all statements must be unprepared

git-svn-id: trunk@25250 -
This commit is contained in:
michael 2013-08-12 08:19:00 +00:00
parent abae19b553
commit 75362b0bb8

View File

@ -15,19 +15,33 @@ uses
{$EndIf}
type
TPQCursor = Class;
{ TPQTrans }
TPQTrans = Class(TSQLHandle)
protected
protected
PGConn : PPGConn;
FList : TThreadList;
Procedure RegisterCursor(S : TPQCursor);
Procedure UnRegisterCursor(S : TPQCursor);
Public
Constructor Create;
Destructor Destroy; override;
end;
{ TPQCursor }
TPQCursor = Class(TSQLCursor)
protected
protected
Statement : string;
StmtName : string;
tr : TPQTrans;
res : PPGresult;
CurTuple : integer;
FieldBinding : array of integer;
Public
Destructor Destroy; override;
end;
EPQDatabaseError = class(EDatabaseError)
@ -158,6 +172,53 @@ const Oid_Bool = 16;
oid_numeric = 1700;
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;
constructor TPQTrans.Create;
begin
Flist:=TThreadList.Create;
FList.Duplicates:=dupIgnore;
end;
destructor TPQTrans.Destroy;
Var
L : TList;
I : integer;
begin
L:=Flist.LockList;
try
For I:=0 to L.Count-1 do
TPQCursor(L[i]).tr:=Nil;
finally
Flist.UnlockList;
end;
FreeAndNil(FList);
inherited Destroy;
end;
{ TPQCursor }
destructor TPQCursor.Destroy;
begin
if Assigned(tr) then
Tr.UnRegisterCursor(Self);
inherited Destroy;
end;
constructor TPQConnection.Create(AOwner : TComponent);
@ -171,6 +232,8 @@ end;
destructor TPQConnection.destroy;
begin
// We must disconnect here. If it is done in inherited, then connection pool is gone.
Connected:=False;
FreeAndNil(FConnectionPool);
inherited destroy;
end;
@ -264,15 +327,24 @@ var
res : PPGresult;
tr : TPQTrans;
i : Integer;
L : TList;
begin
result := false;
tr := trans as TPQTrans;
L:=tr.FList.LockList;
try
For I:=0 to L.Count-1 do
begin
UnprepareStatement(TPQCursor(L[i]));
TPQCursor(L[i]).tr:=Nil;
end;
L.Clear;
finally
tr.flist.UnlockList;
end;
res := PQexec(tr.PGConn, 'ROLLBACK');
CheckResultError(res,tr.PGConn,SErrRollbackFailed);
PQclear(res);
ReleaseConnection(tr.PGCOnn,false);
result := true;
@ -285,12 +357,9 @@ var
i : Integer;
begin
result := false;
tr := trans as TPQTrans;
res := PQexec(tr.PGConn, 'COMMIT');
CheckResultError(res,tr.PGConn,SErrCommitFailed);
PQclear(res);
//make connection available in pool
ReleaseConnection(tr.PGConn,false);
@ -672,7 +741,8 @@ begin
begin
StmtName := 'prepst'+inttostr(FCursorCount);
InterlockedIncrement(FCursorCount);
tr := TPQTrans(aTransaction.Handle);
TPQTrans(aTransaction.Handle).RegisterCursor(Cursor as TPQCursor);
// Only available for pq 8.0, so don't use it...
// Res := pqprepare(tr,'prepst'+name+nr,pchar(buf),params.Count,pchar(''));
s := 'prepare '+StmtName+' ';
@ -801,7 +871,8 @@ begin
end
else
begin
tr := TPQTrans(aTransaction.Handle);
// Registercursor sets tr
TPQTrans(aTransaction.Handle).RegisterCursor(Cursor as TPQCursor);
if Assigned(AParams) and (AParams.Count > 0) then
begin