unixodbc/DriverManager/SQLFreeHandle.c

632 lines
19 KiB
C

/*********************************************************************
*
* This is based on code created by Peter Harvey,
* (pharvey@codebydesign.com).
*
* Modified and extended by Nick Gorham
* (nick@lurcher.org).
*
* Any bugs or problems should be considered the fault of Nick and not
* Peter.
*
* copyright (c) 1999 Nick Gorham
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
**********************************************************************
*
* $Id: SQLFreeHandle.c,v 1.12 2009/02/18 17:59:08 lurcher Exp $
*
* $Log: SQLFreeHandle.c,v $
* Revision 1.12 2009/02/18 17:59:08 lurcher
* Shift to using config.h, the compile lines were making it hard to spot warnings
*
* Revision 1.11 2009/02/17 09:47:44 lurcher
* Clear up a number of bugs
*
* Revision 1.10 2007/12/17 13:13:03 lurcher
* Fix a couple of descriptor typo's
*
* Revision 1.9 2007/01/02 10:27:50 lurcher
* Fix descriptor leak with unicode only driver
*
* Revision 1.8 2006/04/18 10:24:47 lurcher
* Add a couple of changes from Mark Vanderwiel
*
* Revision 1.7 2003/10/30 18:20:45 lurcher
*
* Fix broken thread protection
* Remove SQLNumResultCols after execute, lease S4/S% to driver
* Fix string overrun in SQLDriverConnect
* Add initial support for Interix
*
* Revision 1.6 2003/05/14 09:42:25 lurcher
*
* Fix bug in stats collection
*
* Revision 1.5 2003/04/09 08:42:18 lurcher
*
* Allow setting of odbcinstQ lib from odbcinst.ini and Environment
*
* Revision 1.4 2002/09/18 14:49:32 lurcher
*
* DataManagerII additions and some more threading fixes
*
* Revision 1.1.1.1 2001/10/17 16:40:05 lurcher
*
* First upload to SourceForge
*
* Revision 1.7 2001/08/08 17:05:17 nick
*
* Add support for attribute setting in the ini files
*
* Revision 1.6 2001/06/04 15:24:49 nick
*
* Add port to MAC OSX and QT3 changes
*
* Revision 1.5 2001/05/15 13:33:44 jason
*
* Wrapped calls to stats with COLLECT_STATS
*
* Revision 1.4 2001/04/12 17:43:36 nick
*
* Change logging and added autotest to odbctest
*
* Revision 1.3 2000/12/19 10:28:29 martin
*
* Return "not built with stats" in uodbc_error() if stats function called
* when stats not built.
* Add uodbc_update_stats() calls to SQLFreeHandle.
*
* Revision 1.2 2000/11/23 09:43:29 nick
*
* Fix deadlock posibility
*
* Revision 1.1.1.1 2000/09/04 16:42:52 nick
* Imported Sources
*
* Revision 1.12 2000/06/27 17:34:10 ngorham
*
* Fix a problem when the second part of the connect failed a seg fault
* was generated in the error reporting
*
* Revision 1.11 2000/05/21 21:49:19 ngorham
*
* Assorted fixes
*
* Revision 1.10 1999/11/17 21:11:59 ngorham
*
* Fix bug where the check for a valid handle was after the code had
* used it.
*
* Revision 1.9 1999/11/13 23:40:59 ngorham
*
* Alter the way DM logging works
* Upgrade the Postgres driver to 6.4.6
*
* Revision 1.8 1999/10/24 23:54:18 ngorham
*
* First part of the changes to the error reporting
*
* Revision 1.7 1999/10/09 00:15:58 ngorham
*
* Add mapping from SQL_TYPE_X to SQL_X and SQL_C_TYPE_X to SQL_C_X
* when the driver is a ODBC 2 one
*
* Revision 1.6 1999/09/21 22:34:24 ngorham
*
* Improve performance by removing unneeded logging calls when logging is
* disabled
*
* Revision 1.5 1999/08/03 21:47:39 shandyb
* Moving to automake: changed files in DriverManager
*
* Revision 1.4 1999/07/10 21:10:16 ngorham
*
* Adjust error sqlstate from driver manager, depending on requested
* version (ODBC2/3)
*
* Revision 1.3 1999/07/04 21:05:07 ngorham
*
* Add LGPL Headers to code
*
* Revision 1.2 1999/06/30 23:56:55 ngorham
*
* Add initial thread safety code
*
* Revision 1.1.1.1 1999/05/29 13:41:07 sShandyb
* first go at it
*
* Revision 1.2 1999/06/07 01:29:31 pharvey
* *** empty log message ***
*
* Revision 1.1.1.1 1999/05/27 18:23:17 pharvey
* Imported sources
*
* Revision 1.5 1999/05/09 23:27:11 nick
* All the API done now
*
* Revision 1.4 1999/05/03 19:50:43 nick
* Another check point
*
* Revision 1.3 1999/04/30 16:22:47 nick
* Another checkpoint
*
* Revision 1.2 1999/04/29 20:47:37 nick
* Another checkpoint
*
* Revision 1.1 1999/04/25 23:06:11 nick
* Initial revision
*
*
**********************************************************************/
#include <config.h>
#include "drivermanager.h"
#if defined ( COLLECT_STATS ) && defined( HAVE_SYS_SEM_H )
#include "__stats.h"
#include <uodbc_stats.h>
#endif
static char const rcsid[]= "$RCSfile: SQLFreeHandle.c,v $ $Revision: 1.12 $";
SQLRETURN __SQLFreeHandle( SQLSMALLINT handle_type,
SQLHANDLE handle )
{
switch( handle_type )
{
case SQL_HANDLE_ENV:
case SQL_HANDLE_SENV:
{
DMHENV environment = (DMHENV)handle;
/*
* check environment
*/
if ( !__validate_env( environment ))
{
dm_log_write( __FILE__,
__LINE__,
LOG_INFO,
LOG_INFO,
"Error: SQL_INVALID_HANDLE" );
return SQL_INVALID_HANDLE;
}
function_entry( environment );
if ( log_info.log_flag )
{
sprintf( environment -> msg,
"\n\t\tEntry:\n\t\t\tHandle Type = %d\n\t\t\tInput Handle = %p",
handle_type,
(void*)handle );
dm_log_write( __FILE__,
__LINE__,
LOG_INFO,
LOG_INFO,
environment -> msg );
}
thread_protect( SQL_HANDLE_ENV, environment );
/*
* check states
*/
if ( environment -> state != STATE_E1 )
{
dm_log_write( __FILE__,
__LINE__,
LOG_INFO,
LOG_INFO,
"Error: HY010" );
__post_internal_error( &environment -> error,
ERROR_HY010, NULL,
environment -> requested_version );
return function_return_nodrv( SQL_HANDLE_ENV, environment, SQL_ERROR );
}
thread_release( SQL_HANDLE_ENV, environment );
/*
* release any pooled connections that are using this environment
*/
__strip_from_pool( environment );
__release_env( environment );
return SQL_SUCCESS;
}
break;
case SQL_HANDLE_DBC:
{
DMHDBC connection = (DMHDBC)handle;
DMHENV environment;
/*
* check connection
*/
if ( !__validate_dbc( connection ))
{
dm_log_write( __FILE__,
__LINE__,
LOG_INFO,
LOG_INFO,
"Error: SQL_INVALID_HANDLE" );
return SQL_INVALID_HANDLE;
}
function_entry( connection );
environment = connection -> environment;
if ( log_info.log_flag )
{
sprintf( connection -> msg,
"\n\t\tEntry:\n\t\t\tHandle Type = %d\n\t\t\tInput Handle = %p",
handle_type,
(void*)handle );
dm_log_write( __FILE__,
__LINE__,
LOG_INFO,
LOG_INFO,
connection -> msg );
}
thread_protect( SQL_HANDLE_ENV, environment );
/*
* check states
*/
if ( connection -> state != STATE_C2 )
{
dm_log_write( __FILE__,
__LINE__,
LOG_INFO,
LOG_INFO,
"Error: HY010" );
__post_internal_error( &connection -> error,
ERROR_HY010, NULL,
connection -> environment -> requested_version );
return function_return_nodrv( SQL_HANDLE_ENV, environment, SQL_ERROR );
}
environment -> connection_count --;
if ( environment -> connection_count == 0 )
{
environment -> state = STATE_E1;
}
environment = connection -> environment;
__release_attr_str( &connection -> env_attribute );
__release_attr_str( &connection -> dbc_attribute );
__release_attr_str( &connection -> stmt_attribute );
__disconnect_part_one( connection );
__release_dbc( connection );
if ( log_info.log_flag )
{
sprintf( environment -> msg,
"\n\t\tExit:[SQL_SUCCESS]" );
dm_log_write( __FILE__,
__LINE__,
LOG_INFO,
LOG_INFO,
environment -> msg );
}
#if defined ( COLLECT_STATS ) && defined( HAVE_SYS_SEM_H )
uodbc_update_stats(environment->sh, UODBC_STATS_TYPE_HDBC,
(void *)-1);
#endif
thread_release( SQL_HANDLE_ENV, environment );
return SQL_SUCCESS;
}
break;
case SQL_HANDLE_STMT:
{
DMHSTMT statement = (DMHSTMT)handle;
DMHDBC connection;
SQLRETURN ret;
/*
* check statement
*/
if ( !__validate_stmt( statement ))
{
dm_log_write( __FILE__,
__LINE__,
LOG_INFO,
LOG_INFO,
"Error: SQL_INVALID_HANDLE" );
return SQL_INVALID_HANDLE;
}
function_entry( statement );
connection = statement -> connection;
if ( log_info.log_flag )
{
sprintf( statement -> msg,
"\n\t\tEntry:\n\t\t\tHandle Type = %d\n\t\t\tInput Handle = %p",
handle_type,
(void*)handle );
dm_log_write( __FILE__,
__LINE__,
LOG_INFO,
LOG_INFO,
statement -> msg );
}
thread_protect( SQL_HANDLE_STMT, statement );
/*
* check states
*/
if ( statement -> state == STATE_S8 ||
statement -> state == STATE_S9 ||
statement -> state == STATE_S10 ||
statement -> state == STATE_S11 ||
statement -> state == STATE_S12 ||
statement -> state == STATE_S13 ||
statement -> state == STATE_S14 ||
statement -> state == STATE_S15 )
{
dm_log_write( __FILE__,
__LINE__,
LOG_INFO,
LOG_INFO,
"Error: HY010" );
__post_internal_error( &statement -> error,
ERROR_HY010, NULL,
statement -> connection -> environment -> requested_version );
return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
}
if ( !CHECK_SQLFREEHANDLE( statement -> connection ))
{
if ( !CHECK_SQLFREESTMT( statement -> connection ))
{
dm_log_write( __FILE__,
__LINE__,
LOG_INFO,
LOG_INFO,
"Error: IM001" );
__post_internal_error( &statement -> error,
ERROR_IM001, NULL,
statement -> connection -> environment -> requested_version );
return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
}
else
{
ret = SQLFREESTMT( statement -> connection,
statement -> driver_stmt,
SQL_DROP );
}
}
else
{
ret = SQLFREEHANDLE( statement -> connection,
handle_type,
statement -> driver_stmt );
}
if ( SQL_SUCCEEDED( ret ))
{
/*
* release the implicit descriptors,
* this matches the tests in SQLAllocHandle
*/
if (( statement -> connection -> driver_act_ver == 3 &&
CHECK_SQLGETSTMTATTR( connection )) ||
CHECK_SQLGETSTMTATTRW( connection ))
{
if ( statement -> implicit_ard )
__release_desc( statement -> implicit_ard );
if ( statement -> implicit_apd )
__release_desc( statement -> implicit_apd );
if ( statement -> implicit_ird )
__release_desc( statement -> implicit_ird );
if ( statement -> implicit_ipd )
__release_desc( statement -> implicit_ipd );
}
statement -> connection -> statement_count --;
thread_release( SQL_HANDLE_STMT, statement );
#if defined ( COLLECT_STATS ) && defined( HAVE_SYS_SEM_H )
uodbc_update_stats(connection->environment->sh,
UODBC_STATS_TYPE_HSTMT, (void *)-1);
#endif
__release_stmt( statement );
}
else
{
thread_release( SQL_HANDLE_STMT, statement );
}
if ( log_info.log_flag )
{
sprintf( connection -> msg,
"\n\t\tExit:[SQL_SUCCESS]" );
dm_log_write( __FILE__,
__LINE__,
LOG_INFO,
LOG_INFO,
connection -> msg );
}
return function_return( IGNORE_THREAD, connection, ret );
}
break;
case SQL_HANDLE_DESC:
{
DMHDESC descriptor = (DMHDESC)handle;
DMHDBC connection;
SQLRETURN ret;
/*
* check descriptor
*/
if ( !__validate_desc( descriptor ))
{
return SQL_INVALID_HANDLE;
}
function_entry( descriptor );
connection = descriptor -> connection;
if ( log_info.log_flag )
{
sprintf( descriptor -> msg,
"\n\t\tEntry:\n\t\t\tHandle Type = %d\n\t\t\tInput Handle = %p",
handle_type,
(void*)handle );
dm_log_write( __FILE__,
__LINE__,
LOG_INFO,
LOG_INFO,
descriptor -> msg );
}
if ( descriptor -> implicit )
{
dm_log_write( __FILE__,
__LINE__,
LOG_INFO,
LOG_INFO,
"Error: HY017" );
__post_internal_error( &descriptor -> error,
ERROR_HY017, NULL,
connection -> environment -> requested_version );
return function_return_nodrv( IGNORE_THREAD, descriptor, SQL_ERROR );
}
thread_protect( SQL_HANDLE_DESC, descriptor );
if ( !CHECK_SQLFREEHANDLE( connection ))
{
dm_log_write( __FILE__,
__LINE__,
LOG_INFO,
LOG_INFO,
"Error: IM001" );
__post_internal_error( &descriptor -> error,
ERROR_IM001, NULL,
connection -> environment -> requested_version );
return function_return_nodrv( SQL_HANDLE_DESC, descriptor, SQL_ERROR );
}
else
{
ret = SQLFREEHANDLE( connection,
handle_type,
descriptor -> driver_desc );
}
/*
* check status of statements associated with this descriptor
*/
if( __check_stmt_from_desc( descriptor, STATE_S8 ) ||
__check_stmt_from_desc( descriptor, STATE_S9 ) ||
__check_stmt_from_desc( descriptor, STATE_S10 ) ||
__check_stmt_from_desc( descriptor, STATE_S11 ) ||
__check_stmt_from_desc( descriptor, STATE_S12 )) {
dm_log_write( __FILE__,
__LINE__,
LOG_INFO,
LOG_INFO,
"Error: HY010" );
__post_internal_error( &descriptor -> error,
ERROR_HY010, NULL,
descriptor -> connection -> environment -> requested_version );
return function_return( SQL_HANDLE_DESC, descriptor, SQL_ERROR );
}
thread_release( SQL_HANDLE_DESC, descriptor );
__release_desc( descriptor );
if ( log_info.log_flag )
{
sprintf( connection -> msg,
"\n\t\tExit:[SQL_SUCCESS]" );
dm_log_write( __FILE__,
__LINE__,
LOG_INFO,
LOG_INFO,
connection -> msg );
}
#if defined ( COLLECT_STATS ) && defined( HAVE_SYS_SEM_H )
uodbc_update_stats(connection->environment->sh,
UODBC_STATS_TYPE_HDESC, (void *)-1);
#endif
return function_return( IGNORE_THREAD, connection, SQL_SUCCESS );
}
break;
default:
/*
* there is nothing to report a error on
*/
return SQL_INVALID_HANDLE;
}
}
SQLRETURN SQLFreeHandle( SQLSMALLINT handle_type,
SQLHANDLE handle )
{
return __SQLFreeHandle( handle_type,
handle );
}