mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-14 06:29:16 +02:00
* fcl-db: Oracle connection: don't leak resources client side and server side on failed connection. Patch by Al Popov. Thank you very much. Solves issue #26868
git-svn-id: trunk@28833 -
This commit is contained in:
parent
123b9f789a
commit
d69d25432a
@ -384,11 +384,10 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TOracleConnection.DoInternalConnect;
|
procedure TOracleConnection.DoInternalConnect;
|
||||||
|
|
||||||
var
|
var
|
||||||
ConnectString : string;
|
ConnectString : string;
|
||||||
TempServiceContext : POCISvcCtx;
|
TempServiceContext : POCISvcCtx;
|
||||||
|
IsConnected : boolean;
|
||||||
begin
|
begin
|
||||||
{$IfDef LinkDynamically}
|
{$IfDef LinkDynamically}
|
||||||
InitialiseOCI;
|
InitialiseOCI;
|
||||||
@ -397,42 +396,78 @@ begin
|
|||||||
inherited DoInternalConnect;
|
inherited DoInternalConnect;
|
||||||
//todo: get rid of FUserMem, as it isn't used
|
//todo: get rid of FUserMem, as it isn't used
|
||||||
FUserMem := nil;
|
FUserMem := nil;
|
||||||
|
IsConnected := false;
|
||||||
|
|
||||||
// Create environment handle
|
try
|
||||||
if OCIEnvCreate(FOciEnvironment,oci_default,nil,nil,nil,nil,0,FUserMem) <> OCI_SUCCESS then
|
// Create environment handle
|
||||||
DatabaseError(SErrEnvCreateFailed,self);
|
if OCIEnvCreate(FOciEnvironment,OCI_DEFAULT,nil,nil,nil,nil,0,FUserMem) <> OCI_SUCCESS then
|
||||||
// Create error handle
|
DatabaseError(SErrEnvCreateFailed,self);
|
||||||
if OciHandleAlloc(FOciEnvironment,FOciError,OCI_HTYPE_ERROR,0,FUserMem) <> OCI_SUCCESS then
|
// Create error handle
|
||||||
DatabaseError(SErrHandleAllocFailed,self);
|
if OciHandleAlloc(FOciEnvironment,FOciError,OCI_HTYPE_ERROR,0,FUserMem) <> OCI_SUCCESS then
|
||||||
// Create Server handle
|
DatabaseError(SErrHandleAllocFailed,self);
|
||||||
if OciHandleAlloc(FOciEnvironment,FOciServer,OCI_HTYPE_SERVER,0,FUserMem) <> OCI_SUCCESS then
|
// Create server handle
|
||||||
DatabaseError(SErrHandleAllocFailed,self);
|
if OciHandleAlloc(FOciEnvironment,FOciServer,OCI_HTYPE_SERVER,0,FUserMem) <> OCI_SUCCESS then
|
||||||
// Initialize Server handle
|
DatabaseError(SErrHandleAllocFailed,self);
|
||||||
if hostname='' then connectstring := databasename
|
|
||||||
else connectstring := '//'+hostname+'/'+databasename;
|
|
||||||
if OCIServerAttach(FOciServer,FOciError,@(ConnectString[1]),Length(ConnectString),OCI_DEFAULT) <> OCI_SUCCESS then
|
|
||||||
HandleError();
|
|
||||||
|
|
||||||
// Create temporary service-context handle for user authentication
|
// Initialize server handle
|
||||||
if OciHandleAlloc(FOciEnvironment,TempServiceContext,OCI_HTYPE_SVCCTX,0,FUserMem) <> OCI_SUCCESS then
|
if hostname='' then
|
||||||
DatabaseError(SErrHandleAllocFailed,self);
|
connectstring := databasename
|
||||||
|
else
|
||||||
|
connectstring := '//'+hostname+'/'+databasename;
|
||||||
|
if OCIServerAttach(FOciServer,FOciError,@(ConnectString[1]),Length(ConnectString),OCI_DEFAULT) <> OCI_SUCCESS then
|
||||||
|
HandleError();
|
||||||
|
|
||||||
// Create user-session handle
|
try
|
||||||
if OciHandleAlloc(FOciEnvironment,FOciUserSession,OCI_HTYPE_SESSION,0,FUserMem) <> OCI_SUCCESS then
|
// Create temporary service-context handle for user authentication
|
||||||
DatabaseError(SErrHandleAllocFailed,self);
|
if OciHandleAlloc(FOciEnvironment,TempServiceContext,OCI_HTYPE_SVCCTX,0,FUserMem) <> OCI_SUCCESS then
|
||||||
// Set the server-handle in the service-context handle
|
DatabaseError(SErrHandleAllocFailed,self);
|
||||||
if OCIAttrSet(TempServiceContext,OCI_HTYPE_SVCCTX,FOciServer,0,OCI_ATTR_SERVER,FOciError) <> OCI_SUCCESS then
|
|
||||||
HandleError();
|
try
|
||||||
// Set username and password in the user-session handle
|
// Create user-session handle
|
||||||
if OCIAttrSet(FOciUserSession,OCI_HTYPE_SESSION,@(Self.UserName[1]),Length(Self.UserName),OCI_ATTR_USERNAME,FOciError) <> OCI_SUCCESS then
|
if OciHandleAlloc(FOciEnvironment,FOciUserSession,OCI_HTYPE_SESSION,0,FUserMem) <> OCI_SUCCESS then
|
||||||
HandleError();
|
DatabaseError(SErrHandleAllocFailed,self);
|
||||||
if OCIAttrSet(FOciUserSession,OCI_HTYPE_SESSION,@(Self.Password[1]),Length(Self.Password),OCI_ATTR_PASSWORD,FOciError) <> OCI_SUCCESS then
|
try
|
||||||
HandleError();
|
// Set the server-handle in the service-context handle
|
||||||
// Authenticate
|
if OCIAttrSet(TempServiceContext,OCI_HTYPE_SVCCTX,FOciServer,0,OCI_ATTR_SERVER,FOciError) <> OCI_SUCCESS then
|
||||||
if OCISessionBegin(TempServiceContext,FOciError,FOcIUserSession,OCI_CRED_RDBMS,OCI_DEFAULT) <> OCI_SUCCESS then
|
HandleError();
|
||||||
HandleError();
|
// Set username and password in the user-session handle
|
||||||
// Free temporary service-context handle
|
if OCIAttrSet(FOciUserSession,OCI_HTYPE_SESSION,@(Self.UserName[1]),Length(Self.UserName),OCI_ATTR_USERNAME,FOciError) <> OCI_SUCCESS then
|
||||||
OCIHandleFree(TempServiceContext,OCI_HTYPE_SVCCTX);
|
HandleError();
|
||||||
|
if OCIAttrSet(FOciUserSession,OCI_HTYPE_SESSION,@(Self.Password[1]),Length(Self.Password),OCI_ATTR_PASSWORD,FOciError) <> OCI_SUCCESS then
|
||||||
|
HandleError();
|
||||||
|
// Authenticate
|
||||||
|
if OCISessionBegin(TempServiceContext,FOciError,FOcIUserSession,OCI_CRED_RDBMS,OCI_DEFAULT) <> OCI_SUCCESS then
|
||||||
|
HandleError();
|
||||||
|
IsConnected := true;
|
||||||
|
finally
|
||||||
|
if not IsConnected then
|
||||||
|
begin
|
||||||
|
OCIHandleFree(FOciUserSession,OCI_HTYPE_SESSION);
|
||||||
|
FOciUserSession := nil;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
// Free temporary service-context handle
|
||||||
|
OCIHandleFree(TempServiceContext,OCI_HTYPE_SVCCTX);
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
if not IsConnected then
|
||||||
|
OCIServerDetach(FOciServer,FOciError,OCI_DEFAULT);
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
if not IsConnected then
|
||||||
|
begin
|
||||||
|
if assigned(FOciServer) then
|
||||||
|
OCIHandleFree(FOciServer,OCI_HTYPE_SERVER);
|
||||||
|
if assigned(FOciError) then
|
||||||
|
OCIHandleFree(FOciError,OCI_HTYPE_ERROR);
|
||||||
|
if assigned(FOciEnvironment) then
|
||||||
|
OCIHandleFree(FOciEnvironment,OCI_HTYPE_ENV);
|
||||||
|
FOciEnvironment := nil;
|
||||||
|
FOciError := nil;
|
||||||
|
FOciServer := nil;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TOracleConnection.DoInternalDisconnect;
|
procedure TOracleConnection.DoInternalDisconnect;
|
||||||
@ -441,36 +476,56 @@ var
|
|||||||
begin
|
begin
|
||||||
inherited DoInternalDisconnect;
|
inherited DoInternalDisconnect;
|
||||||
|
|
||||||
// Create temporary service-context handle for user-disconnect
|
if assigned(FOciEnvironment) then
|
||||||
if OciHandleAlloc(FOciEnvironment,TempServiceContext,OCI_HTYPE_SVCCTX,0,FUserMem) <> OCI_SUCCESS then
|
begin
|
||||||
DatabaseError(SErrHandleAllocFailed,self);
|
if assigned(FOciError) then
|
||||||
|
begin
|
||||||
|
if assigned(FOciServer) then
|
||||||
|
begin
|
||||||
|
if assigned(FOciUserSession) then
|
||||||
|
begin
|
||||||
|
try
|
||||||
|
// Create temporary service-context handle for user-disconnect
|
||||||
|
if OciHandleAlloc(FOciEnvironment,TempServiceContext,OCI_HTYPE_SVCCTX,0,FUserMem) <> OCI_SUCCESS then
|
||||||
|
DatabaseError(SErrHandleAllocFailed,self);
|
||||||
|
|
||||||
// Set the server handle in the service-context handle
|
// Set the server handle in the service-context handle
|
||||||
if OCIAttrSet(TempServiceContext,OCI_HTYPE_SVCCTX,FOciServer,0,OCI_ATTR_SERVER,FOciError) <> OCI_SUCCESS then
|
if OCIAttrSet(TempServiceContext,OCI_HTYPE_SVCCTX,FOciServer,0,OCI_ATTR_SERVER,FOciError) <> OCI_SUCCESS then
|
||||||
HandleError();
|
HandleError();
|
||||||
// Set the user session handle in the service-context handle
|
// Set the user session handle in the service-context handle
|
||||||
if OCIAttrSet(TempServiceContext,OCI_HTYPE_SVCCTX,FOciUserSession,0,OCI_ATTR_SESSION,FOciError) <> OCI_SUCCESS then
|
if OCIAttrSet(TempServiceContext,OCI_HTYPE_SVCCTX,FOciUserSession,0,OCI_ATTR_SESSION,FOciError) <> OCI_SUCCESS then
|
||||||
HandleError();
|
HandleError();
|
||||||
// Disconnect uses-session handle
|
// Disconnect uses-session handle
|
||||||
if OCISessionEnd(TempServiceContext,FOciError,FOcIUserSession,OCI_DEFAULT) <> OCI_SUCCESS then
|
if OCISessionEnd(TempServiceContext,FOciError,FOcIUserSession,OCI_DEFAULT) <> OCI_SUCCESS then
|
||||||
HandleError();
|
HandleError();
|
||||||
// Free user-session handle
|
finally
|
||||||
OCIHandleFree(FOciUserSession,OCI_HTYPE_SESSION);
|
// Free user-session handle
|
||||||
// Free temporary service-context handle
|
OCIHandleFree(FOciUserSession,OCI_HTYPE_SESSION);
|
||||||
OCIHandleFree(TempServiceContext,OCI_HTYPE_SVCCTX);
|
// Free temporary service-context handle
|
||||||
|
OCIHandleFree(TempServiceContext,OCI_HTYPE_SVCCTX);
|
||||||
|
FOciUserSession := nil;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
// Disconnect server handle
|
try
|
||||||
if OCIServerDetach(FOciServer,FOciError,OCI_DEFAULT) <> OCI_SUCCESS then
|
// Disconnect server handle
|
||||||
HandleError();
|
if OCIServerDetach(FOciServer,FOciError,OCI_DEFAULT) <> OCI_SUCCESS then
|
||||||
|
HandleError();
|
||||||
// Free connection handles
|
finally
|
||||||
OCIHandleFree(FOciServer,OCI_HTYPE_SERVER);
|
// Free connection handles
|
||||||
OCIHandleFree(FOciError,OCI_HTYPE_ERROR);
|
OCIHandleFree(FOciServer,OCI_HTYPE_SERVER);
|
||||||
OCIHandleFree(FOciEnvironment,OCI_HTYPE_ENV);
|
FOciServer := nil;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
OCIHandleFree(FOciError,OCI_HTYPE_ERROR);
|
||||||
|
FOciError := nil;
|
||||||
|
end;
|
||||||
|
OCIHandleFree(FOciEnvironment,OCI_HTYPE_ENV);
|
||||||
|
FOciEnvironment := nil;
|
||||||
|
end;
|
||||||
{$IfDef LinkDynamically}
|
{$IfDef LinkDynamically}
|
||||||
ReleaseOCI;
|
ReleaseOCI;
|
||||||
{$EndIf}
|
{$EndIf}
|
||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TOracleConnection.AllocateCursorHandle: TSQLCursor;
|
function TOracleConnection.AllocateCursorHandle: TSQLCursor;
|
||||||
|
Loading…
Reference in New Issue
Block a user