pqconnection: use also EPQDatabaseError for Execute and UnPrepareStatement to deliver complete error info

git-svn-id: trunk@22610 -
This commit is contained in:
ludob 2012-10-10 18:31:10 +00:00
parent db28583b65
commit 707e19b81d

View File

@ -31,6 +31,16 @@ type
FieldBinding : array of integer;
end;
EPQDatabaseError = class(EDatabaseError)
public
SEVERITY:string;
SQLSTATE: string;
MESSAGE_PRIMARY:string;
MESSAGE_DETAIL:string;
MESSAGE_HINT:string;
STATEMENT_POSITION:string;
end;
{ TPQConnection }
TPQConnection = class (TSQLConnection)
@ -40,6 +50,7 @@ type
FSQLDatabaseHandle : pointer;
FIntegerDateTimes : boolean;
procedure CheckResultError(res: PPGresult; conn:PPGconn; ErrMsg: string);
function GetPQDatabaseError(res : PPGresult;ErrMsg: string):EPQDatabaseError;
function TranslateFldType(res : PPGresult; Tuple : integer; out Size : integer) : TFieldType;
procedure ExecuteDirectPG(const Query : String);
protected
@ -90,16 +101,6 @@ type
Class Function UnLoadFunction : TLibraryUnLoadFunction; override;
end;
EPQDatabaseError = class(EDatabaseError)
public
SEVERITY:string;
SQLSTATE: string;
MESSAGE_PRIMARY:string;
MESSAGE_DETAIL:string;
MESSAGE_HINT:string;
STATEMENT_POSITION:string;
end;
implementation
uses math, strutils, FmtBCD;
@ -347,6 +348,22 @@ end;
procedure TPQConnection.CheckResultError(res: PPGresult; conn: PPGconn;
ErrMsg: string);
var
E: EPQDatabaseError;
begin
if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
begin
E:=GetPQDatabaseError(res,ErrMsg);
pqclear(res);
if assigned(conn) then
PQFinish(conn);
raise E;
end;
end;
function TPQConnection.GetPQDatabaseError(res: PPGresult; ErrMsg: string
): EPQDatabaseError;
var
serr:string;
E: EPQDatabaseError;
@ -357,36 +374,29 @@ var
MESSAGE_DETAIL:string;
MESSAGE_HINT:string;
STATEMENT_POSITION:string;
begin
if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
begin
SEVERITY:=PQresultErrorField(res,ord('S'));
SQLSTATE:=PQresultErrorField(res,ord('C'));
MESSAGE_PRIMARY:=PQresultErrorField(res,ord('M'));
MESSAGE_DETAIL:=PQresultErrorField(res,ord('D'));
MESSAGE_HINT:=PQresultErrorField(res,ord('H'));
STATEMENT_POSITION:=PQresultErrorField(res,ord('P'));
serr:=PQresultErrorMessage(res)+LineEnding+
'Severity: '+ SEVERITY +LineEnding+
'SQL State: '+ SQLSTATE +LineEnding+
'Primary Error: '+ MESSAGE_PRIMARY +LineEnding+
'Error Detail: '+ MESSAGE_DETAIL +LineEnding+
'Hint: '+ MESSAGE_HINT +LineEnding+
'Character: '+ STATEMENT_POSITION +LineEnding;
pqclear(res);
if assigned(conn) then
PQFinish(conn);
if Self.Name = '' then CompName := Self.ClassName else CompName := Self.Name;
E:=EPQDatabaseError.CreateFmt('%s : %s (PostgreSQL: %s)', [CompName,ErrMsg, serr]);
E.SEVERITY:=SEVERITY;
E.SQLSTATE:=SQLSTATE;
E.MESSAGE_PRIMARY:=MESSAGE_PRIMARY;
E.MESSAGE_DETAIL:=MESSAGE_DETAIL;
E.MESSAGE_HINT:=MESSAGE_HINT;
E.STATEMENT_POSITION:=STATEMENT_POSITION;
raise E;
end;
SEVERITY:=PQresultErrorField(res,ord('S'));
SQLSTATE:=PQresultErrorField(res,ord('C'));
MESSAGE_PRIMARY:=PQresultErrorField(res,ord('M'));
MESSAGE_DETAIL:=PQresultErrorField(res,ord('D'));
MESSAGE_HINT:=PQresultErrorField(res,ord('H'));
STATEMENT_POSITION:=PQresultErrorField(res,ord('P'));
serr:=PQresultErrorMessage(res)+LineEnding+
'Severity: '+ SEVERITY +LineEnding+
'SQL State: '+ SQLSTATE +LineEnding+
'Primary Error: '+ MESSAGE_PRIMARY +LineEnding+
'Error Detail: '+ MESSAGE_DETAIL +LineEnding+
'Hint: '+ MESSAGE_HINT +LineEnding+
'Character: '+ STATEMENT_POSITION +LineEnding;
if Self.Name = '' then CompName := Self.ClassName else CompName := Self.Name;
E:=EPQDatabaseError.CreateFmt('%s : %s (PostgreSQL: %s)', [CompName,ErrMsg, serr]);
E.SEVERITY:=SEVERITY;
E.SQLSTATE:=SQLSTATE;
E.MESSAGE_PRIMARY:=MESSAGE_PRIMARY;
E.MESSAGE_DETAIL:=MESSAGE_DETAIL;
E.MESSAGE_HINT:=MESSAGE_HINT;
E.STATEMENT_POSITION:=STATEMENT_POSITION;
result:=E;
end;
function TPQConnection.TranslateFldType(res : PPGresult; Tuple : integer; out Size : integer) : TFieldType;
@ -579,6 +589,8 @@ begin
end;
procedure TPQConnection.UnPrepareStatement(cursor : TSQLCursor);
var
E: EPQDatabaseError;
begin
with (cursor as TPQCursor) do if FPrepared then
@ -589,8 +601,9 @@ begin
res := pqexec(tr.PGConn,pchar('deallocate '+StmtName));
if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
begin
E:=GetPQDatabaseError(res,SErrPrepareFailed);
pqclear(res);
DatabaseError(SErrPrepareFailed + ' (PostgreSQL: ' + PQerrorMessage(tr.PGConn) + ')',self)
raise E;
end
else
pqclear(res);
@ -608,6 +621,7 @@ var ar : array of pchar;
ParamNames,
ParamValues : array of string;
cash: int64;
E: EPQDatabaseError;
begin
with cursor as TPQCursor do
@ -686,14 +700,14 @@ begin
end;
if assigned(res) and not (PQresultStatus(res) in [PGRES_COMMAND_OK,PGRES_TUPLES_OK]) then
begin
s := PQerrorMessage(tr.PGConn);
E:=GetPQDatabaseError(res,SErrExecuteFailed);
pqclear(res);
tr.ErrorOccured := True;
// Don't perform the rollback, only make it possible to do a rollback.
// The other databases also don't do this.
// atransaction.Rollback;
DatabaseError(SErrExecuteFailed + ' (PostgreSQL: ' + s + ')',self);
raise E;
end;
end;
end;