summaryrefslogtreecommitdiff
path: root/packages/fcl-db/src/sqldb/postgres/pqconnection.pp
diff options
context:
space:
mode:
Diffstat (limited to 'packages/fcl-db/src/sqldb/postgres/pqconnection.pp')
-rw-r--r--packages/fcl-db/src/sqldb/postgres/pqconnection.pp205
1 files changed, 120 insertions, 85 deletions
diff --git a/packages/fcl-db/src/sqldb/postgres/pqconnection.pp b/packages/fcl-db/src/sqldb/postgres/pqconnection.pp
index 48c24e8b58..bcf43828a1 100644
--- a/packages/fcl-db/src/sqldb/postgres/pqconnection.pp
+++ b/packages/fcl-db/src/sqldb/postgres/pqconnection.pp
@@ -21,10 +21,10 @@ type
TPQTrans = Class(TSQLHandle)
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
Constructor Create;
Destructor Destroy; override;
@@ -60,6 +60,8 @@ type
Destructor Destroy; override;
end;
+ { EPQDatabaseError }
+
EPQDatabaseError = class(EDatabaseError)
public
SEVERITY:string;
@@ -70,6 +72,8 @@ type
STATEMENT_POSITION:string;
end;
+ { TPQTranConnection }
+
TPQTranConnection = class
protected
FPGConn : PPGConn;
@@ -116,6 +120,7 @@ type
function RollBack(trans : TSQLHandle) : boolean; override;
function Commit(trans : TSQLHandle) : boolean; override;
procedure CommitRetaining(trans : TSQLHandle); override;
+ function StartImplicitTransaction(trans : TSQLHandle; AParams : string) : boolean; override;
function StartdbTransaction(trans : TSQLHandle; AParams : string) : boolean; override;
procedure RollBackRetaining(trans : TSQLHandle); override;
procedure UpdateIndexDefs(IndexDefs : TIndexDefs;TableName : string); override;
@@ -124,7 +129,7 @@ type
function RowsAffected(cursor: TSQLCursor): TRowsCount; override;
public
constructor Create(AOwner : TComponent); override;
- destructor destroy; override;
+ destructor Destroy; override;
function GetConnectionInfo(InfoType:TConnInfoType): string; override;
procedure CreateDB; override;
procedure DropDB; override;
@@ -188,23 +193,12 @@ 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;
+{ TPQTrans }
constructor TPQTrans.Create;
begin
- Flist:=TThreadList.Create;
+ FList:=TThreadList.Create;
FList.Duplicates:=dupIgnore;
end;
@@ -215,19 +209,39 @@ Var
I : integer;
begin
- L:=Flist.LockList;
+ L:=FList.LockList;
try
For I:=0 to L.Count-1 do
TPQCursor(L[i]).tr:=Nil;
finally
- Flist.UnlockList;
+ FList.UnlockList;
end;
FreeAndNil(FList);
inherited Destroy;
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 }
+destructor TPQCursor.Destroy;
+begin
+ if Assigned(tr) then
+ tr.UnRegisterCursor(Self);
+ inherited Destroy;
+end;
+
function TPQCursor.GetFieldBinding(F: TFieldDef): PFieldBinding;
Var
@@ -251,25 +265,20 @@ begin
end;
end;
-destructor TPQCursor.Destroy;
-begin
- if Assigned(tr) then
- Tr.UnRegisterCursor(Self);
- inherited Destroy;
-end;
+{ TPQConnection }
constructor TPQConnection.Create(AOwner : TComponent);
begin
inherited;
- FConnOptions := FConnOptions + [sqSupportParams, sqSupportEmptyDatabaseName, sqEscapeRepeat, sqEscapeSlash];
+ FConnOptions := FConnOptions + [sqSupportParams, sqSupportEmptyDatabaseName, sqEscapeRepeat, sqEscapeSlash, sqImplicitTransaction];
FieldNameQuoteChars:=DoubleQuotes;
VerboseErrors:=True;
FConnectionPool:=TThreadlist.Create;
end;
-destructor TPQConnection.destroy;
+destructor TPQConnection.Destroy;
begin
// We must disconnect here. If it is done in inherited, then connection pool is gone.
Connected:=False;
@@ -322,7 +331,8 @@ begin
{$EndIf}
end;
-procedure TPQConnection.GetExtendedFieldInfo(cursor: TPQCursor; Bindings: TFieldBindings);
+Procedure TPQConnection.GetExtendedFieldInfo(cursor: TPQCursor;
+ Bindings: TFieldBindings);
Var
tt,tc,Tn,S : String;
@@ -376,7 +386,7 @@ begin
P.SQLDBData:=TPQCursor(C).GetFieldBinding(F.FieldDef);
end;
-function TPQConnection.ErrorOnUnknownType: Boolean;
+Function TPQConnection.ErrorOnUnknownType: Boolean;
begin
Result:=False;
end;
@@ -430,6 +440,7 @@ var
begin
result := false;
tr := trans as TPQTrans;
+ // unprepare statements associated with given transaction
L:=tr.FList.LockList;
try
For I:=0 to L.Count-1 do
@@ -439,8 +450,9 @@ begin
end;
L.Clear;
finally
- tr.flist.UnlockList;
+ tr.FList.UnlockList;
end;
+
res := PQexec(tr.PGConn, 'ROLLBACK');
CheckResultError(res,tr.PGConn,SErrRollbackFailed);
PQclear(res);
@@ -463,23 +475,50 @@ begin
result := true;
end;
-function TPQConnection.StartdbTransaction(trans : TSQLHandle; AParams : string) : boolean;
+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;
- i : Integer;
- t : TPQTranConnection;
- L : TList;
begin
- result:=false;
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
i:=0;
- t:=Nil;
+ T:=Nil;
L:=FConnectionPool.LockList;
try
- while (I<L.Count) do
+ while (i<L.Count) do
begin
T:=TPQTranConnection(L[i]);
if (T.FPGConn=nil) or not T.FTranActive then
@@ -495,60 +534,42 @@ begin
finally
FConnectionPool.UnLockList;
end;
+
if (T=Nil) then
begin
T:=TPQTranConnection.Create;
T.FTranActive:=True;
AddConnection(T);
end;
- if (T.FPGConn<>nil) then
- tr.PGConn:=T.FPGConn
- else
+
+ if (T.FPGConn=nil) then
begin
- tr.PGConn := PQconnectdb(pchar(FConnectString));
- T.FPGConn:=tr.PGConn;
- CheckConnectionStatus(tr.PGConn);
+ T.FPGConn := PQconnectdb(pchar(FConnectString));
+ CheckConnectionStatus(T.FPGConn);
if CharSet <> '' then
- PQsetClientEncoding(tr.PGConn, pchar(CharSet));
+ PQsetClientEncoding(T.FPGConn, pchar(CharSet));
end;
- res := PQexec(tr.PGConn, 'BEGIN');
- CheckResultError(res,tr.PGConn,sErrTransactionFailed);
-
- PQclear(res);
- result := true;
+ TPQTrans(trans).PGConn := T.FPGConn;
+ 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;
+function TPQConnection.StartDBTransaction(trans: TSQLHandle;
+ AParams: string): boolean;
-procedure TPQConnection.CommitRetaining(trans : TSQLHandle);
-var
+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);
+begin
+ Result:=StartImplicitTransaction(trans, AParams);
+ if Result then
+ begin
+ tr := trans as TPQTrans;
+ res := PQexec(tr.PGConn, 'BEGIN');
+ CheckResultError(res,tr.PGConn,sErrTransactionFailed);
+ PQclear(res);
+ end;
end;
@@ -648,9 +669,21 @@ var
MESSAGE_DETAIL: string;
MESSAGE_HINT: string;
STATEMENT_POSITION: string;
+ P : Pchar;
+ haveError : Boolean;
+
begin
- if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
+ HaveError:=False;
+ if (Res=Nil) then
+ begin
+ HaveError:=True;
+ P:=PQerrorMessage(conn);
+ If Assigned(p) then
+ ErrMsg:=StrPas(P);
+ end
+ else if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
begin
+ HaveError:=True;
SEVERITY:=PQresultErrorField(res,ord('S'));
SQLSTATE:=PQresultErrorField(res,ord('C'));
MESSAGE_PRIMARY:=PQresultErrorField(res,ord('M'));
@@ -667,6 +700,9 @@ begin
MaybeAdd(sErr,'Hint',MESSAGE_HINT);
MaybeAdd(sErr,'Character',STATEMENT_POSITION);
end;
+ end;
+ if HaveError then
+ begin
if (Self.Name='') then CompName := Self.ClassName else CompName := Self.Name;
E:=EPQDatabaseError.CreateFmt('%s : %s (PostgreSQL: %s)', [CompName, ErrMsg, sErr]);
E.SEVERITY:=SEVERITY;
@@ -675,7 +711,6 @@ begin
E.MESSAGE_DETAIL:=MESSAGE_DETAIL;
E.MESSAGE_HINT:=MESSAGE_HINT;
E.STATEMENT_POSITION:=STATEMENT_POSITION;
-
PQclear(res);
res:=nil;
if assigned(conn) then
@@ -688,7 +723,7 @@ begin
end;
function TPQConnection.TranslateFldType(res: PPGresult; Tuple: integer; out
- Size: integer; out ATypeOID: oid): TFieldType;
+ Size: integer; Out ATypeOID: oid): TFieldType;
const
VARHDRSZ=sizeof(longint);
@@ -769,18 +804,18 @@ begin
end;
end;
-function TPQConnection.AllocateCursorHandle: TSQLCursor;
+Function TPQConnection.AllocateCursorHandle: TSQLCursor;
begin
result := TPQCursor.create;
end;
-procedure TPQConnection.DeAllocateCursorHandle(var cursor: TSQLCursor);
+Procedure TPQConnection.DeAllocateCursorHandle(var cursor: TSQLCursor);
begin
FreeAndNil(cursor);
end;
-function TPQConnection.AllocateTransactionHandle: TSQLHandle;
+Function TPQConnection.AllocateTransactionHandle: TSQLHandle;
begin
result := TPQTrans.create;
@@ -918,7 +953,7 @@ begin
res:=nil;
if FPrepared then
begin
- if PQtransactionStatus(tr.PGConn) <> PQTRANS_INERROR then
+ if assigned(tr) and (PQtransactionStatus(tr.PGConn) <> PQTRANS_INERROR) then
begin
res := PQexec(tr.PGConn,pchar('deallocate '+StmtName));
CheckResultError(res,nil,SErrUnPrepareFailed);
@@ -1000,7 +1035,7 @@ begin
end
else
begin
- // Registercursor sets tr
+ // RegisterCursor sets tr
TPQTrans(aTransaction.Handle).RegisterCursor(Cursor as TPQCursor);
if Assigned(AParams) and (AParams.Count > 0) then
@@ -1090,7 +1125,7 @@ begin
end
else
if ErrorOnUnknownType then
- DatabaseError('unhandled field type :'+FB^.TypeName,Self);
+ DatabaseError('Unhandled field type :'+FB^.TypeName,Self);
end;
end;
end;