+ Fix for the postgresql transaction becoming invalid

git-svn-id: trunk@3833 -
This commit is contained in:
joost 2006-06-09 20:59:06 +00:00
parent 01edb71190
commit 22982a127d

View File

@ -17,13 +17,14 @@ uses
type type
TPQTrans = Class(TSQLHandle) TPQTrans = Class(TSQLHandle)
protected protected
TransactionHandle : PPGConn; PGConn : PPGConn;
ErrorOccured : boolean;
end; end;
TPQCursor = Class(TSQLCursor) TPQCursor = Class(TSQLCursor)
protected protected
Statement : string; Statement : string;
tr : Pointer; tr : TPQTrans;
res : PPGresult; res : PPGresult;
CurTuple : integer; CurTuple : integer;
Nr : string; Nr : string;
@ -112,7 +113,7 @@ end;
function TPQConnection.GetTransactionHandle(trans : TSQLHandle): pointer; function TPQConnection.GetTransactionHandle(trans : TSQLHandle): pointer;
begin begin
Result := (trans as TPQtrans).TransactionHandle; Result := trans;
end; end;
function TPQConnection.RollBack(trans : TSQLHandle) : boolean; function TPQConnection.RollBack(trans : TSQLHandle) : boolean;
@ -124,17 +125,17 @@ begin
tr := trans as TPQTrans; tr := trans as TPQTrans;
res := PQexec(tr.TransactionHandle, 'ROLLBACK'); res := PQexec(tr.PGConn, 'ROLLBACK');
if (PQresultStatus(res) <> PGRES_COMMAND_OK) then if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
begin begin
PQclear(res); PQclear(res);
result := false; result := false;
DatabaseError(SErrRollbackFailed + ' (PostgreSQL: ' + PQerrorMessage(tr.transactionhandle) + ')',self); DatabaseError(SErrRollbackFailed + ' (PostgreSQL: ' + PQerrorMessage(tr.PGConn) + ')',self);
end end
else else
begin begin
PQclear(res); PQclear(res);
PQFinish(tr.TransactionHandle); PQFinish(tr.PGConn);
result := true; result := true;
end; end;
end; end;
@ -148,17 +149,17 @@ begin
tr := trans as TPQTrans; tr := trans as TPQTrans;
res := PQexec(tr.TransactionHandle, 'COMMIT'); res := PQexec(tr.PGConn, 'COMMIT');
if (PQresultStatus(res) <> PGRES_COMMAND_OK) then if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
begin begin
PQclear(res); PQclear(res);
result := false; result := false;
DatabaseError(SErrCommitFailed + ' (PostgreSQL: ' + PQerrorMessage(tr.transactionhandle) + ')',self); DatabaseError(SErrCommitFailed + ' (PostgreSQL: ' + PQerrorMessage(tr.PGConn) + ')',self);
end end
else else
begin begin
PQclear(res); PQclear(res);
PQFinish(tr.TransactionHandle); PQFinish(tr.PGConn);
result := true; result := true;
end; end;
end; end;
@ -173,23 +174,24 @@ begin
tr := trans as TPQTrans; tr := trans as TPQTrans;
tr.TransactionHandle := PQconnectdb(pchar(FConnectString)); tr.PGConn := PQconnectdb(pchar(FConnectString));
if (PQstatus(tr.TransactionHandle) = CONNECTION_BAD) then if (PQstatus(tr.PGConn) = CONNECTION_BAD) then
begin begin
result := false; result := false;
PQFinish(tr.TransactionHandle); PQFinish(tr.PGConn);
DatabaseError(SErrConnectionFailed + ' (PostgreSQL: ' + PQerrorMessage(tr.transactionhandle) + ')',self); DatabaseError(SErrConnectionFailed + ' (PostgreSQL: ' + PQerrorMessage(tr.PGConn) + ')',self);
end end
else else
begin begin
res := PQexec(tr.TransactionHandle, 'BEGIN'); tr.ErrorOccured := False;
res := PQexec(tr.PGConn, 'BEGIN');
if (PQresultStatus(res) <> PGRES_COMMAND_OK) then if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
begin begin
result := false; result := false;
PQclear(res); PQclear(res);
msg := PQerrorMessage(tr.transactionhandle); msg := PQerrorMessage(tr.PGConn);
PQFinish(tr.TransactionHandle); PQFinish(tr.PGConn);
DatabaseError(sErrTransactionFailed + ' (PostgreSQL: ' + msg + ')',self); DatabaseError(sErrTransactionFailed + ' (PostgreSQL: ' + msg + ')',self);
end end
else else
@ -207,21 +209,21 @@ var
msg : string; msg : string;
begin begin
tr := trans as TPQTrans; tr := trans as TPQTrans;
res := PQexec(tr.TransactionHandle, 'ROLLBACK'); res := PQexec(tr.PGConn, 'ROLLBACK');
if (PQresultStatus(res) <> PGRES_COMMAND_OK) then if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
begin begin
PQclear(res); PQclear(res);
DatabaseError(SErrRollbackFailed + ' (PostgreSQL: ' + PQerrorMessage(tr.transactionhandle) + ')',self); DatabaseError(SErrRollbackFailed + ' (PostgreSQL: ' + PQerrorMessage(tr.PGConn) + ')',self);
end end
else else
begin begin
PQclear(res); PQclear(res);
res := PQexec(tr.TransactionHandle, 'BEGIN'); res := PQexec(tr.PGConn, 'BEGIN');
if (PQresultStatus(res) <> PGRES_COMMAND_OK) then if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
begin begin
PQclear(res); PQclear(res);
msg := PQerrorMessage(tr.transactionhandle); msg := PQerrorMessage(tr.PGConn);
PQFinish(tr.TransactionHandle); PQFinish(tr.PGConn);
DatabaseError(sErrTransactionFailed + ' (PostgreSQL: ' + msg + ')',self); DatabaseError(sErrTransactionFailed + ' (PostgreSQL: ' + msg + ')',self);
end end
else else
@ -236,21 +238,21 @@ var
msg : string; msg : string;
begin begin
tr := trans as TPQTrans; tr := trans as TPQTrans;
res := PQexec(tr.TransactionHandle, 'COMMIT'); res := PQexec(tr.PGConn, 'COMMIT');
if (PQresultStatus(res) <> PGRES_COMMAND_OK) then if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
begin begin
PQclear(res); PQclear(res);
DatabaseError(SErrCommitFailed + ' (PostgreSQL: ' + PQerrorMessage(tr.transactionhandle) + ')',self); DatabaseError(SErrCommitFailed + ' (PostgreSQL: ' + PQerrorMessage(tr.PGConn) + ')',self);
end end
else else
begin begin
PQclear(res); PQclear(res);
res := PQexec(tr.TransactionHandle, 'BEGIN'); res := PQexec(tr.PGConn, 'BEGIN');
if (PQresultStatus(res) <> PGRES_COMMAND_OK) then if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
begin begin
PQclear(res); PQclear(res);
msg := PQerrorMessage(tr.transactionhandle); msg := PQerrorMessage(tr.PGConn);
PQFinish(tr.TransactionHandle); PQFinish(tr.PGConn);
DatabaseError(sErrTransactionFailed + ' (PostgreSQL: ' + msg + ')',self); DatabaseError(sErrTransactionFailed + ' (PostgreSQL: ' + msg + ')',self);
end end
else else
@ -396,7 +398,7 @@ begin
// So that's not supported. // So that's not supported.
if FStatementType in [stInsert,stUpdate,stDelete, stSelect] then if FStatementType in [stInsert,stUpdate,stDelete, stSelect] then
begin begin
tr := aTransaction.Handle; tr := TPQTrans(aTransaction.Handle);
// Only available for pq 8.0, so don't use it... // Only available for pq 8.0, so don't use it...
// Res := pqprepare(tr,'prepst'+name+nr,pchar(buf),params.Count,pchar('')); // Res := pqprepare(tr,'prepst'+name+nr,pchar(buf),params.Count,pchar(''));
s := 'prepare prepst'+nr+' '; s := 'prepare prepst'+nr+' ';
@ -414,11 +416,11 @@ begin
buf := AParams.ParseSQL(buf,false,psPostgreSQL); buf := AParams.ParseSQL(buf,false,psPostgreSQL);
end; end;
s := s + ' as ' + buf; s := s + ' as ' + buf;
res := pqexec(tr,pchar(s)); res := pqexec(tr.PGConn,pchar(s));
if (PQresultStatus(res) <> PGRES_COMMAND_OK) then if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
begin begin
pqclear(res); pqclear(res);
DatabaseError(SErrPrepareFailed + ' (PostgreSQL: ' + PQerrorMessage(tr) + ')',self) DatabaseError(SErrPrepareFailed + ' (PostgreSQL: ' + PQerrorMessage(tr.PGConn) + ')',self)
end; end;
FPrepared := True; FPrepared := True;
end end
@ -432,13 +434,16 @@ procedure TPQConnection.UnPrepareStatement(cursor : TSQLCursor);
begin begin
with (cursor as TPQCursor) do if FPrepared then with (cursor as TPQCursor) do if FPrepared then
begin begin
res := pqexec(tr,pchar('deallocate prepst'+nr)); if not tr.ErrorOccured then
if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
begin begin
res := pqexec(tr.PGConn,pchar('deallocate prepst'+nr));
if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
begin
pqclear(res);
DatabaseError(SErrPrepareFailed + ' (PostgreSQL: ' + PQerrorMessage(tr.PGConn) + ')',self)
end;
pqclear(res); pqclear(res);
DatabaseError(SErrPrepareFailed + ' (PostgreSQL: ' + PQerrorMessage(tr) + ')',self)
end; end;
pqclear(res);
FPrepared := False; FPrepared := False;
end; end;
end; end;
@ -475,27 +480,31 @@ begin
end end
else else
FreeAndNil(ar[i]); FreeAndNil(ar[i]);
res := PQexecPrepared(tr,pchar('prepst'+nr),Aparams.count,@Ar[0],nil,nil,0); res := PQexecPrepared(tr.PGConn,pchar('prepst'+nr),Aparams.count,@Ar[0],nil,nil,0);
for i := 0 to AParams.count -1 do for i := 0 to AParams.count -1 do
FreeMem(ar[i]); FreeMem(ar[i]);
end end
else else
res := PQexecPrepared(tr,pchar('prepst'+nr),0,nil,nil,nil,1); res := PQexecPrepared(tr.PGConn,pchar('prepst'+nr),0,nil,nil,nil,1);
end end
else else
begin begin
tr := aTransaction.Handle; tr := TPQTrans(aTransaction.Handle);
s := statement; s := statement;
//Should be altered, just like in TSQLQuery.ApplyRecUpdate //Should be altered, just like in TSQLQuery.ApplyRecUpdate
if assigned(AParams) then for i := 0 to AParams.count-1 do if assigned(AParams) then for i := 0 to AParams.count-1 do
s := stringreplace(s,':'+AParams[i].Name,AParams[i].asstring,[rfReplaceAll,rfIgnoreCase]); s := stringreplace(s,':'+AParams[i].Name,AParams[i].asstring,[rfReplaceAll,rfIgnoreCase]);
res := pqexec(tr,pchar(s)); res := pqexec(tr.PGConn,pchar(s));
end; end;
if not (PQresultStatus(res) in [PGRES_COMMAND_OK,PGRES_TUPLES_OK]) then if not (PQresultStatus(res) in [PGRES_COMMAND_OK,PGRES_TUPLES_OK]) then
begin begin
s := PQerrorMessage(tr.PGConn);
pqclear(res); pqclear(res);
DatabaseError(SErrExecuteFailed + ' (PostgreSQL: ' + PQerrorMessage(tr) + ')',self);
tr.ErrorOccured := True;
atransaction.Rollback;
DatabaseError(SErrExecuteFailed + ' (PostgreSQL: ' + s + ')',self);
end; end;
end; end;
end; end;