mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-14 09:49:35 +02:00
+ Fix for the postgresql transaction becoming invalid
git-svn-id: trunk@3833 -
This commit is contained in:
parent
01edb71190
commit
22982a127d
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user