1099 lines
31 KiB
C
1099 lines
31 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: SQLGetDiagField.c,v 1.17 2009/02/18 17:59:08 lurcher Exp $
|
|
*
|
|
* $Log: SQLGetDiagField.c,v $
|
|
* Revision 1.17 2009/02/18 17:59:08 lurcher
|
|
* Shift to using config.h, the compile lines were making it hard to spot warnings
|
|
*
|
|
* Revision 1.16 2009/02/17 09:47:44 lurcher
|
|
* Clear up a number of bugs
|
|
*
|
|
* Revision 1.15 2009/02/04 09:30:01 lurcher
|
|
* Fix some SQLINTEGER/SQLLEN conflicts
|
|
*
|
|
* Revision 1.14 2008/09/29 14:02:45 lurcher
|
|
* Fix missing dlfcn group option
|
|
*
|
|
* Revision 1.13 2007/03/05 09:49:24 lurcher
|
|
* Get it to build on VMS again
|
|
*
|
|
* Revision 1.12 2006/11/27 14:08:33 lurcher
|
|
* Sync up dirs
|
|
*
|
|
* Revision 1.11 2006/05/31 17:35:34 lurcher
|
|
* Add unicode ODBCINST entry points
|
|
*
|
|
* Revision 1.10 2006/03/08 09:18:41 lurcher
|
|
* fix silly typo that was using sizeof( SQL_WCHAR ) instead of SQLWCHAR
|
|
*
|
|
* Revision 1.9 2005/12/19 18:43:26 lurcher
|
|
* Add new parts to contrib and alter how the errors are returned from the driver
|
|
*
|
|
* Revision 1.8 2003/02/27 12:19:39 lurcher
|
|
*
|
|
* Add the A functions as well as the W
|
|
*
|
|
* Revision 1.7 2002/12/05 17:44:30 lurcher
|
|
*
|
|
* Display unknown return values in return logging
|
|
*
|
|
* Revision 1.6 2002/11/11 17:10:12 lurcher
|
|
*
|
|
* VMS changes
|
|
*
|
|
* Revision 1.5 2002/07/24 08:49:52 lurcher
|
|
*
|
|
* Alter UNICODE support to use iconv for UNICODE-ANSI conversion
|
|
*
|
|
* Revision 1.4 2002/01/30 12:20:02 lurcher
|
|
*
|
|
* Add MyODBC 3 driver source
|
|
*
|
|
* Revision 1.3 2002/01/21 18:00:51 lurcher
|
|
*
|
|
* Assorted fixed and changes, mainly UNICODE/bug fixes
|
|
*
|
|
* Revision 1.2 2001/12/13 13:00:32 lurcher
|
|
*
|
|
* Remove most if not all warnings on 64 bit platforms
|
|
* Add support for new MS 3.52 64 bit changes
|
|
* Add override to disable the stopping of tracing
|
|
* Add MAX_ROWS support in postgres driver
|
|
*
|
|
* Revision 1.1.1.1 2001/10/17 16:40:05 lurcher
|
|
*
|
|
* First upload to SourceForge
|
|
*
|
|
* Revision 1.4 2001/07/03 09:30:41 nick
|
|
*
|
|
* Add ability to alter size of displayed message in the log
|
|
*
|
|
* Revision 1.3 2001/04/12 17:43:36 nick
|
|
*
|
|
* Change logging and added autotest to odbctest
|
|
*
|
|
* Revision 1.2 2000/12/31 20:30:54 nick
|
|
*
|
|
* Add UNICODE support
|
|
*
|
|
* Revision 1.1.1.1 2000/09/04 16:42:52 nick
|
|
* Imported Sources
|
|
*
|
|
* Revision 1.15 2000/08/22 22:56:27 ngorham
|
|
*
|
|
* Add fix to SQLGetDiagField to return the server name on statements and
|
|
* descriptors
|
|
*
|
|
* Revision 1.14 2000/08/21 10:31:58 ngorham
|
|
*
|
|
* Add missing line continuation char
|
|
*
|
|
* Revision 1.13 2000/08/09 08:48:18 ngorham
|
|
*
|
|
* Fix for SQLGetDiagField(SQL_DIAG_SUBCLASS_ORIGIN) returning a null string
|
|
*
|
|
* Revision 1.12 2000/08/03 10:49:34 ngorham
|
|
*
|
|
* Fix buffer overrun problem in GetDiagField
|
|
*
|
|
* Revision 1.11 2000/07/31 20:48:01 ngorham
|
|
*
|
|
* Fix bugs in SQLGetDiagField and with SQLColAttributes
|
|
*
|
|
* Revision 1.10 2000/06/23 16:11:35 ngorham
|
|
*
|
|
* Map ODBC 2 SQLSTATE values to ODBC 3
|
|
*
|
|
* Revision 1.9 2000/05/21 21:49:19 ngorham
|
|
*
|
|
* Assorted fixes
|
|
*
|
|
* Revision 1.8 1999/11/17 21:08:58 ngorham
|
|
*
|
|
* Fix Bug with the ODBC 3 error handling
|
|
*
|
|
* Revision 1.7 1999/11/13 23:40:59 ngorham
|
|
*
|
|
* Alter the way DM logging works
|
|
* Upgrade the Postgres driver to 6.4.6
|
|
*
|
|
* Revision 1.6 1999/11/10 03:51:33 ngorham
|
|
*
|
|
* Update the error reporting in the DM to enable ODBC 3 and 2 calls to
|
|
* work at the same time
|
|
*
|
|
* Revision 1.5 1999/09/21 22:34:25 ngorham
|
|
*
|
|
* Improve performance by removing unneeded logging calls when logging is
|
|
* disabled
|
|
*
|
|
* Revision 1.4 1999/07/12 19:42:06 ngorham
|
|
*
|
|
* Finished off SQLGetDiagField.c and fixed a but that caused SQLError to
|
|
* fail with Perl and PHP, connect errors were not being returned because
|
|
* I was checking to the environment being set, they were setting the
|
|
* statement and the environment. The order of checking has been changed.
|
|
*
|
|
* 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.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/04 22:41:12 nick
|
|
* and another night ends
|
|
*
|
|
* Revision 1.3 1999/05/03 19:50:43 nick
|
|
* Another check point
|
|
*
|
|
* Revision 1.2 1999/04/30 16:22:47 nick
|
|
* Another checkpoint
|
|
*
|
|
* Revision 1.1 1999/04/25 23:06:11 nick
|
|
* Initial revision
|
|
*
|
|
*
|
|
**********************************************************************/
|
|
|
|
#include <config.h>
|
|
#include "drivermanager.h"
|
|
|
|
static char const rcsid[]= "$RCSfile: SQLGetDiagField.c,v $ $Revision: 1.17 $";
|
|
|
|
#define ODBC30_SUBCLASS "01S00,01S01,01S02,01S06,01S07,07S01,08S01,21S01,\
|
|
21S02,25S01,25S02,25S03,42S01,42S02,42S11,42S12,42S21,42S22,HY095,HY097,HY098,\
|
|
HY099,HY100,HY101,HY105,HY107,HY109,HY110,HY111,HYT00,HYT01,IM001,IM002,IM003,\
|
|
IM004,IM005,IM006,IM007,IM008,IM010,IM011,IM012"
|
|
|
|
extern int __is_env( EHEAD * head );
|
|
|
|
/*
|
|
* is it a diag identifier that we have to convert from unicode to ansi
|
|
*/
|
|
|
|
static int is_char_diag( int diag_identifier )
|
|
{
|
|
switch( diag_identifier ) {
|
|
case SQL_DIAG_CLASS_ORIGIN:
|
|
case SQL_DIAG_CONNECTION_NAME:
|
|
case SQL_DIAG_DYNAMIC_FUNCTION:
|
|
case SQL_DIAG_MESSAGE_TEXT:
|
|
case SQL_DIAG_SERVER_NAME:
|
|
case SQL_DIAG_SQLSTATE:
|
|
case SQL_DIAG_SUBCLASS_ORIGIN:
|
|
return 1;
|
|
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static SQLRETURN extract_sql_error_field( EHEAD *head,
|
|
SQLSMALLINT rec_number,
|
|
SQLSMALLINT diag_identifier,
|
|
SQLPOINTER diag_info_ptr,
|
|
SQLSMALLINT buffer_length,
|
|
SQLSMALLINT *string_length_ptr )
|
|
{
|
|
ERROR *ptr;
|
|
|
|
if ( is_char_diag( diag_identifier ) && buffer_length < 0 )
|
|
{
|
|
return SQL_ERROR;
|
|
}
|
|
|
|
/*
|
|
* check the header fields first
|
|
*/
|
|
|
|
switch( diag_identifier )
|
|
{
|
|
case SQL_DIAG_CURSOR_ROW_COUNT:
|
|
case SQL_DIAG_ROW_COUNT:
|
|
{
|
|
SQLLEN val;
|
|
SQLRETURN ret;
|
|
|
|
if ( rec_number > 0 || head -> handle_type != SQL_HANDLE_STMT )
|
|
{
|
|
return SQL_ERROR;
|
|
}
|
|
else if ( head -> header_set )
|
|
{
|
|
switch( diag_identifier )
|
|
{
|
|
case SQL_DIAG_CURSOR_ROW_COUNT:
|
|
if ( SQL_SUCCEEDED( head -> diag_cursor_row_count_ret ) && diag_info_ptr )
|
|
{
|
|
*((SQLLEN*)diag_info_ptr) = head -> diag_cursor_row_count;
|
|
}
|
|
return head -> diag_cursor_row_count_ret;
|
|
|
|
case SQL_DIAG_ROW_COUNT:
|
|
if ( SQL_SUCCEEDED( head -> diag_row_count_ret ) && diag_info_ptr )
|
|
{
|
|
*((SQLLEN*)diag_info_ptr) = head -> diag_row_count;
|
|
}
|
|
return head -> diag_row_count_ret;
|
|
}
|
|
}
|
|
else if ( __get_connection( head ) -> unicode_driver &&
|
|
CHECK_SQLGETDIAGFIELDW( __get_connection( head )))
|
|
{
|
|
ret = SQLGETDIAGFIELDW( __get_connection( head ),
|
|
SQL_HANDLE_STMT,
|
|
__get_driver_handle( head ),
|
|
0,
|
|
diag_identifier,
|
|
diag_info_ptr,
|
|
buffer_length,
|
|
string_length_ptr );
|
|
|
|
return ret;
|
|
}
|
|
else if ( !__get_connection( head ) -> unicode_driver &&
|
|
CHECK_SQLGETDIAGFIELD( __get_connection( head )))
|
|
{
|
|
ret = SQLGETDIAGFIELD( __get_connection( head ),
|
|
SQL_HANDLE_STMT,
|
|
__get_driver_handle( head ),
|
|
0,
|
|
diag_identifier,
|
|
diag_info_ptr,
|
|
buffer_length,
|
|
string_length_ptr );
|
|
|
|
return ret;
|
|
}
|
|
else if ( CHECK_SQLROWCOUNT( __get_connection( head )))
|
|
{
|
|
ret = DEF_SQLROWCOUNT( __get_connection( head ),
|
|
__get_driver_handle( head ),
|
|
&val );
|
|
|
|
if ( !SQL_SUCCEEDED( ret ))
|
|
{
|
|
return ret;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
val = 0;
|
|
}
|
|
|
|
if ( diag_info_ptr )
|
|
{
|
|
memcpy( diag_info_ptr, &val, sizeof( val ));
|
|
}
|
|
}
|
|
return SQL_SUCCESS;
|
|
|
|
case SQL_DIAG_DYNAMIC_FUNCTION:
|
|
{
|
|
SQLRETURN ret;
|
|
|
|
if ( rec_number > 0 )
|
|
{
|
|
return SQL_ERROR;
|
|
}
|
|
else if ( head -> handle_type != SQL_HANDLE_STMT )
|
|
{
|
|
if ( diag_info_ptr )
|
|
{
|
|
strcpy( diag_info_ptr, "" );
|
|
}
|
|
if ( string_length_ptr )
|
|
{
|
|
*string_length_ptr = 0;
|
|
}
|
|
return SQL_SUCCESS;
|
|
}
|
|
else if ( head -> header_set )
|
|
{
|
|
if ( SQL_SUCCEEDED( head -> diag_dynamic_function_ret ) && diag_info_ptr )
|
|
{
|
|
unicode_to_ansi_copy( diag_info_ptr, buffer_length, head -> diag_dynamic_function, SQL_NTS, __get_connection( head ), NULL );
|
|
if ( string_length_ptr )
|
|
{
|
|
*string_length_ptr = wide_strlen( head -> diag_dynamic_function );
|
|
}
|
|
}
|
|
return head -> diag_dynamic_function_ret;
|
|
}
|
|
else if ( __get_connection( head ) -> unicode_driver &&
|
|
CHECK_SQLGETDIAGFIELDW( __get_connection( head )))
|
|
{
|
|
SQLWCHAR *s1 = NULL;
|
|
|
|
if ( buffer_length > 0 )
|
|
{
|
|
s1 = malloc( sizeof( SQLWCHAR ) * ( buffer_length + 1 ));
|
|
}
|
|
|
|
ret = SQLGETDIAGFIELDW( __get_connection( head ),
|
|
SQL_HANDLE_STMT,
|
|
__get_driver_handle( head ),
|
|
0,
|
|
diag_identifier,
|
|
s1 ? s1 : diag_info_ptr,
|
|
buffer_length * sizeof ( SQLWCHAR ),
|
|
string_length_ptr );
|
|
|
|
if ( SQL_SUCCEEDED( ret ) && diag_info_ptr && s1 )
|
|
{
|
|
unicode_to_ansi_copy( diag_info_ptr, buffer_length, s1, buffer_length, __get_connection( head ), NULL );
|
|
}
|
|
|
|
if ( string_length_ptr && *string_length_ptr > 0 )
|
|
{
|
|
*string_length_ptr /= sizeof ( SQLWCHAR );
|
|
}
|
|
|
|
if ( s1 )
|
|
{
|
|
free( s1 );
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
else if ( !__get_connection( head ) -> unicode_driver &&
|
|
CHECK_SQLGETDIAGFIELD( __get_connection( head )))
|
|
{
|
|
ret = SQLGETDIAGFIELD( __get_connection( head ),
|
|
SQL_HANDLE_STMT,
|
|
__get_driver_handle( head ),
|
|
0,
|
|
diag_identifier,
|
|
diag_info_ptr,
|
|
buffer_length,
|
|
string_length_ptr );
|
|
|
|
return ret;
|
|
}
|
|
if ( diag_info_ptr )
|
|
{
|
|
strcpy( diag_info_ptr, "" );
|
|
}
|
|
}
|
|
return SQL_SUCCESS;
|
|
|
|
case SQL_DIAG_DYNAMIC_FUNCTION_CODE:
|
|
{
|
|
SQLINTEGER val;
|
|
SQLRETURN ret;
|
|
|
|
if ( rec_number > 0 )
|
|
{
|
|
return SQL_ERROR;
|
|
}
|
|
else if ( head -> handle_type != SQL_HANDLE_STMT )
|
|
{
|
|
*((SQLINTEGER*)diag_info_ptr) = 0;
|
|
return SQL_SUCCESS;
|
|
}
|
|
else if ( head -> header_set )
|
|
{
|
|
if ( SQL_SUCCEEDED( head -> diag_dynamic_function_code_ret ) && diag_info_ptr )
|
|
{
|
|
*((SQLINTEGER*)diag_info_ptr) = head -> diag_dynamic_function_code;
|
|
}
|
|
return head -> diag_dynamic_function_code_ret;
|
|
}
|
|
else if ( __get_connection( head ) -> unicode_driver &&
|
|
CHECK_SQLGETDIAGFIELDW( __get_connection( head )))
|
|
{
|
|
ret = SQLGETDIAGFIELDW( __get_connection( head ),
|
|
SQL_HANDLE_STMT,
|
|
__get_driver_handle( head ),
|
|
0,
|
|
diag_identifier,
|
|
diag_info_ptr,
|
|
buffer_length,
|
|
string_length_ptr );
|
|
|
|
return ret;
|
|
}
|
|
else if ( !__get_connection( head ) -> unicode_driver &&
|
|
CHECK_SQLGETDIAGFIELD( __get_connection( head )))
|
|
{
|
|
ret = SQLGETDIAGFIELD( __get_connection( head ),
|
|
SQL_HANDLE_STMT,
|
|
__get_driver_handle( head ),
|
|
0,
|
|
diag_identifier,
|
|
diag_info_ptr,
|
|
buffer_length,
|
|
string_length_ptr );
|
|
|
|
return ret;
|
|
}
|
|
else
|
|
{
|
|
val = SQL_DIAG_UNKNOWN_STATEMENT;
|
|
}
|
|
|
|
if ( diag_info_ptr )
|
|
{
|
|
memcpy( diag_info_ptr, &val, sizeof( val ));
|
|
}
|
|
}
|
|
return SQL_SUCCESS;
|
|
|
|
case SQL_DIAG_NUMBER:
|
|
{
|
|
SQLINTEGER val;
|
|
|
|
if ( rec_number > 0 )
|
|
{
|
|
return SQL_ERROR;
|
|
}
|
|
val = head -> sql_diag_head.internal_count +
|
|
head -> sql_diag_head.error_count;
|
|
|
|
if ( diag_info_ptr )
|
|
{
|
|
memcpy( diag_info_ptr, &val, sizeof( val ));
|
|
}
|
|
}
|
|
return SQL_SUCCESS;
|
|
|
|
case SQL_DIAG_RETURNCODE:
|
|
{
|
|
if ( diag_info_ptr )
|
|
{
|
|
memcpy( diag_info_ptr, &head -> return_code,
|
|
sizeof( head -> return_code ));
|
|
}
|
|
}
|
|
return SQL_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* else check the records
|
|
*/
|
|
|
|
if ( rec_number < 1 ||
|
|
( diag_identifier == SQL_DIAG_COLUMN_NUMBER ||
|
|
diag_identifier == SQL_DIAG_ROW_NUMBER ) && head -> handle_type != SQL_HANDLE_STMT )
|
|
{
|
|
return SQL_ERROR;
|
|
}
|
|
|
|
if ( rec_number <= head -> sql_diag_head.internal_count )
|
|
{
|
|
/*
|
|
* local errors
|
|
*/
|
|
|
|
ptr = head -> sql_diag_head.internal_list_head;
|
|
while( rec_number > 1 )
|
|
{
|
|
ptr = ptr -> next;
|
|
rec_number --;
|
|
}
|
|
if ( !ptr )
|
|
{
|
|
return SQL_NO_DATA;
|
|
}
|
|
}
|
|
else if ( !__is_env( head ) && __get_connection( head ) -> state != STATE_C2 )
|
|
{
|
|
rec_number -= head -> sql_diag_head.internal_count;
|
|
|
|
if ( __get_connection( head ) -> unicode_driver &&
|
|
CHECK_SQLGETDIAGFIELDW( __get_connection( head )))
|
|
{
|
|
SQLRETURN ret;
|
|
SQLWCHAR *s1 = NULL;
|
|
|
|
if ( diag_info_ptr && buffer_length > 0 )
|
|
{
|
|
s1 = malloc( ( buffer_length + 1 ) * sizeof( SQLWCHAR ));
|
|
}
|
|
|
|
ret = SQLGETDIAGFIELDW( __get_connection( head ),
|
|
head -> handle_type,
|
|
__get_driver_handle( head ),
|
|
rec_number,
|
|
diag_identifier,
|
|
s1 ? s1 : diag_info_ptr,
|
|
s1 ? ( buffer_length + 1 ) * sizeof( SQLWCHAR ) : buffer_length,
|
|
string_length_ptr );
|
|
|
|
if ( SQL_SUCCEEDED( ret ) && s1 && diag_info_ptr )
|
|
{
|
|
unicode_to_ansi_copy( diag_info_ptr, buffer_length, s1, SQL_NTS, __get_connection( head ), NULL );
|
|
|
|
if ( string_length_ptr && *string_length_ptr > 0 )
|
|
{
|
|
*string_length_ptr /= sizeof( SQLWCHAR );
|
|
}
|
|
}
|
|
|
|
if ( s1 )
|
|
{
|
|
free( s1 );
|
|
}
|
|
|
|
if ( SQL_SUCCEEDED( ret ) && diag_identifier == SQL_DIAG_SQLSTATE )
|
|
{
|
|
/*
|
|
* map 3 to 2 if required
|
|
*/
|
|
if ( diag_info_ptr )
|
|
{
|
|
if ( diag_info_ptr )
|
|
__map_error_state( diag_info_ptr, __get_version( head ));
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
else if ( !__get_connection( head ) -> unicode_driver &&
|
|
CHECK_SQLGETDIAGFIELD( __get_connection( head )))
|
|
{
|
|
SQLRETURN ret;
|
|
|
|
ret = SQLGETDIAGFIELD( __get_connection( head ),
|
|
head -> handle_type,
|
|
__get_driver_handle( head ),
|
|
rec_number,
|
|
diag_identifier,
|
|
diag_info_ptr,
|
|
buffer_length,
|
|
string_length_ptr );
|
|
|
|
if ( SQL_SUCCEEDED( ret ) && diag_identifier == SQL_DIAG_SQLSTATE )
|
|
{
|
|
/*
|
|
* map 3 to 2 if required
|
|
*/
|
|
if ( diag_info_ptr )
|
|
{
|
|
if ( diag_info_ptr )
|
|
__map_error_state( diag_info_ptr, __get_version( head ));
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
else
|
|
{
|
|
ptr = head -> sql_diag_head.error_list_head;
|
|
while( rec_number > 1 )
|
|
{
|
|
ptr = ptr -> next;
|
|
rec_number --;
|
|
}
|
|
if ( !ptr )
|
|
{
|
|
return SQL_NO_DATA;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return SQL_NO_DATA;
|
|
}
|
|
|
|
/*
|
|
* if we are here ptr should point to the local error
|
|
* record
|
|
*/
|
|
|
|
switch( diag_identifier )
|
|
{
|
|
case SQL_DIAG_CLASS_ORIGIN:
|
|
{
|
|
if ( SQL_SUCCEEDED( ptr -> diag_class_origin_ret ))
|
|
{
|
|
unicode_to_ansi_copy( diag_info_ptr, buffer_length, ptr -> diag_class_origin, SQL_NTS, __get_connection( head ), NULL );
|
|
if ( string_length_ptr )
|
|
{
|
|
*string_length_ptr = wide_strlen( ptr -> diag_class_origin );
|
|
}
|
|
return ptr -> diag_class_origin_ret;
|
|
}
|
|
else
|
|
{
|
|
return ptr -> diag_class_origin_ret;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SQL_DIAG_COLUMN_NUMBER:
|
|
{
|
|
if ( diag_info_ptr )
|
|
{
|
|
memcpy( diag_info_ptr, &ptr -> diag_column_number, sizeof( SQLINTEGER ));
|
|
}
|
|
return SQL_SUCCESS;
|
|
}
|
|
break;
|
|
|
|
case SQL_DIAG_CONNECTION_NAME:
|
|
{
|
|
if ( SQL_SUCCEEDED( ptr -> diag_connection_name_ret ))
|
|
{
|
|
unicode_to_ansi_copy( diag_info_ptr, buffer_length, ptr -> diag_connection_name, SQL_NTS, __get_connection( head ), NULL );
|
|
if ( string_length_ptr )
|
|
{
|
|
*string_length_ptr = wide_strlen( ptr -> diag_connection_name );
|
|
}
|
|
return ptr -> diag_connection_name_ret;
|
|
}
|
|
else
|
|
{
|
|
return ptr -> diag_connection_name_ret;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SQL_DIAG_MESSAGE_TEXT:
|
|
{
|
|
char *str;
|
|
int ret = SQL_SUCCESS;
|
|
|
|
str = unicode_to_ansi_alloc( ptr -> msg, SQL_NTS, __get_connection( head ), NULL );
|
|
|
|
if ( diag_info_ptr )
|
|
{
|
|
if ( buffer_length >= strlen( str ) + 1 )
|
|
{
|
|
strcpy( diag_info_ptr, str );
|
|
}
|
|
else
|
|
{
|
|
ret = SQL_SUCCESS_WITH_INFO;
|
|
memcpy( diag_info_ptr, str, buffer_length - 1 );
|
|
(( char * ) diag_info_ptr )[ buffer_length - 1 ] = '\0';
|
|
}
|
|
}
|
|
if ( string_length_ptr )
|
|
{
|
|
*string_length_ptr = strlen( str );
|
|
}
|
|
|
|
if ( str )
|
|
{
|
|
free( str );
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
break;
|
|
|
|
case SQL_DIAG_NATIVE:
|
|
{
|
|
if ( diag_info_ptr )
|
|
{
|
|
memcpy( diag_info_ptr, &ptr -> native_error, sizeof( SQLINTEGER ));
|
|
}
|
|
return SQL_SUCCESS;
|
|
}
|
|
break;
|
|
|
|
case SQL_DIAG_ROW_NUMBER:
|
|
{
|
|
if ( diag_info_ptr )
|
|
{
|
|
memcpy( diag_info_ptr, &ptr -> diag_row_number, sizeof( SQLLEN ));
|
|
}
|
|
return SQL_SUCCESS;
|
|
}
|
|
break;
|
|
|
|
case SQL_DIAG_SERVER_NAME:
|
|
{
|
|
if ( SQL_SUCCEEDED( ptr -> diag_server_name_ret ))
|
|
{
|
|
unicode_to_ansi_copy( diag_info_ptr, buffer_length, ptr -> diag_server_name, SQL_NTS, __get_connection( head ), NULL );
|
|
if ( string_length_ptr )
|
|
{
|
|
*string_length_ptr = wide_strlen( ptr -> diag_server_name );
|
|
}
|
|
return ptr -> diag_server_name_ret;
|
|
}
|
|
else
|
|
{
|
|
return ptr -> diag_server_name_ret;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SQL_DIAG_SQLSTATE:
|
|
{
|
|
char *str;
|
|
int ret = SQL_SUCCESS;
|
|
|
|
str = unicode_to_ansi_alloc( ptr -> sqlstate, SQL_NTS, __get_connection( head ), NULL );
|
|
|
|
if ( diag_info_ptr )
|
|
{
|
|
if ( buffer_length >= strlen( str ) + 1 )
|
|
{
|
|
strcpy( diag_info_ptr, str );
|
|
}
|
|
else
|
|
{
|
|
ret = SQL_SUCCESS_WITH_INFO;
|
|
memcpy( diag_info_ptr, str, buffer_length - 1 );
|
|
(( char * ) diag_info_ptr )[ buffer_length - 1 ] = '\0';
|
|
}
|
|
|
|
/*
|
|
* map 3 to 2 if required
|
|
*/
|
|
|
|
if ( diag_info_ptr )
|
|
__map_error_state( diag_info_ptr, __get_version( head ));
|
|
}
|
|
if ( string_length_ptr )
|
|
{
|
|
*string_length_ptr = strlen( str );
|
|
}
|
|
|
|
if ( str )
|
|
{
|
|
free( str );
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
break;
|
|
|
|
case SQL_DIAG_SUBCLASS_ORIGIN:
|
|
{
|
|
if ( SQL_SUCCEEDED( ptr -> diag_subclass_origin_ret ))
|
|
{
|
|
unicode_to_ansi_copy( diag_info_ptr, buffer_length, ptr -> diag_subclass_origin, SQL_NTS, __get_connection( head ), NULL );
|
|
if ( string_length_ptr )
|
|
{
|
|
*string_length_ptr = wide_strlen( ptr -> diag_subclass_origin );
|
|
}
|
|
return ptr -> diag_subclass_origin_ret;
|
|
}
|
|
else
|
|
{
|
|
return ptr -> diag_subclass_origin_ret;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return SQL_SUCCESS;
|
|
}
|
|
|
|
SQLRETURN SQLGetDiagFieldA( SQLSMALLINT handle_type,
|
|
SQLHANDLE handle,
|
|
SQLSMALLINT rec_number,
|
|
SQLSMALLINT diag_identifier,
|
|
SQLPOINTER diag_info_ptr,
|
|
SQLSMALLINT buffer_length,
|
|
SQLSMALLINT *string_length_ptr )
|
|
{
|
|
return SQLGetDiagField( handle_type,
|
|
handle,
|
|
rec_number,
|
|
diag_identifier,
|
|
diag_info_ptr,
|
|
buffer_length,
|
|
string_length_ptr );
|
|
}
|
|
|
|
SQLRETURN SQLGetDiagField( SQLSMALLINT handle_type,
|
|
SQLHANDLE handle,
|
|
SQLSMALLINT rec_number,
|
|
SQLSMALLINT diag_identifier,
|
|
SQLPOINTER diag_info_ptr,
|
|
SQLSMALLINT buffer_length,
|
|
SQLSMALLINT *string_length_ptr )
|
|
{
|
|
SQLRETURN ret;
|
|
SQLCHAR s1[ 100 + LOG_MESSAGE_LEN ];
|
|
|
|
if ( handle_type == SQL_HANDLE_ENV )
|
|
{
|
|
DMHENV environment = ( DMHENV ) handle;
|
|
|
|
if ( !__validate_env( environment ))
|
|
{
|
|
dm_log_write( __FILE__,
|
|
__LINE__,
|
|
LOG_INFO,
|
|
LOG_INFO,
|
|
"Error: SQL_INVALID_HANDLE" );
|
|
|
|
return SQL_INVALID_HANDLE;
|
|
}
|
|
|
|
thread_protect( SQL_HANDLE_ENV, environment );
|
|
|
|
if ( log_info.log_flag )
|
|
{
|
|
sprintf( environment -> msg,
|
|
"\n\t\tEntry:\
|
|
\n\t\t\tEnvironment = %p\
|
|
\n\t\t\tRec Number = %d\
|
|
\n\t\t\tDiag Ident = %d\
|
|
\n\t\t\tDiag Info Ptr = %p\
|
|
\n\t\t\tBuffer Length = %d\
|
|
\n\t\t\tString Len Ptr = %p",
|
|
environment,
|
|
rec_number,
|
|
diag_identifier,
|
|
diag_info_ptr,
|
|
buffer_length,
|
|
string_length_ptr );
|
|
|
|
dm_log_write( __FILE__,
|
|
__LINE__,
|
|
LOG_INFO,
|
|
LOG_INFO,
|
|
environment -> msg );
|
|
}
|
|
|
|
ret = extract_sql_error_field( &environment -> error,
|
|
rec_number,
|
|
diag_identifier,
|
|
diag_info_ptr,
|
|
buffer_length,
|
|
string_length_ptr );
|
|
|
|
if ( log_info.log_flag )
|
|
{
|
|
sprintf( environment -> msg,
|
|
"\n\t\tExit:[%s]",
|
|
__get_return_status( ret, s1 ));
|
|
|
|
dm_log_write( __FILE__,
|
|
__LINE__,
|
|
LOG_INFO,
|
|
LOG_INFO,
|
|
environment -> msg );
|
|
}
|
|
|
|
thread_release( SQL_HANDLE_ENV, environment );
|
|
|
|
return ret;
|
|
}
|
|
else if ( handle_type == SQL_HANDLE_DBC )
|
|
{
|
|
DMHDBC connection = ( DMHDBC ) handle;
|
|
|
|
if ( !__validate_dbc( connection ))
|
|
{
|
|
return SQL_INVALID_HANDLE;
|
|
}
|
|
|
|
thread_protect( SQL_HANDLE_DBC, connection );
|
|
|
|
if ( log_info.log_flag )
|
|
{
|
|
sprintf( connection -> msg,
|
|
"\n\t\tEntry:\
|
|
\n\t\t\tConnection = %p\
|
|
\n\t\t\tRec Number = %d\
|
|
\n\t\t\tDiag Ident = %d\
|
|
\n\t\t\tDiag Info Ptr = %p\
|
|
\n\t\t\tBuffer Length = %d\
|
|
\n\t\t\tString Len Ptr = %p",
|
|
connection,
|
|
rec_number,
|
|
diag_identifier,
|
|
diag_info_ptr,
|
|
buffer_length,
|
|
string_length_ptr );
|
|
|
|
dm_log_write( __FILE__,
|
|
__LINE__,
|
|
LOG_INFO,
|
|
LOG_INFO,
|
|
connection -> msg );
|
|
}
|
|
|
|
ret = extract_sql_error_field( &connection -> error,
|
|
rec_number,
|
|
diag_identifier,
|
|
diag_info_ptr,
|
|
buffer_length,
|
|
string_length_ptr );
|
|
|
|
if ( log_info.log_flag )
|
|
{
|
|
sprintf( connection -> msg,
|
|
"\n\t\tExit:[%s]",
|
|
__get_return_status( ret, s1 ));
|
|
|
|
dm_log_write( __FILE__,
|
|
__LINE__,
|
|
LOG_INFO,
|
|
LOG_INFO,
|
|
connection -> msg );
|
|
}
|
|
|
|
thread_release( SQL_HANDLE_DBC, connection );
|
|
|
|
return ret;
|
|
}
|
|
else if ( handle_type == SQL_HANDLE_STMT )
|
|
{
|
|
DMHSTMT statement = ( DMHSTMT ) handle;
|
|
|
|
if ( !__validate_stmt( statement ))
|
|
{
|
|
return SQL_INVALID_HANDLE;
|
|
}
|
|
|
|
thread_protect( SQL_HANDLE_STMT, statement );
|
|
|
|
if ( log_info.log_flag )
|
|
{
|
|
sprintf( statement -> msg,
|
|
"\n\t\tEntry:\
|
|
\n\t\t\tStatement = %p\
|
|
\n\t\t\tRec Number = %d\
|
|
\n\t\t\tDiag Ident = %d\
|
|
\n\t\t\tDiag Info Ptr = %p\
|
|
\n\t\t\tBuffer Length = %d\
|
|
\n\t\t\tString Len Ptr = %p",
|
|
statement,
|
|
rec_number,
|
|
diag_identifier,
|
|
diag_info_ptr,
|
|
buffer_length,
|
|
string_length_ptr );
|
|
|
|
dm_log_write( __FILE__,
|
|
__LINE__,
|
|
LOG_INFO,
|
|
LOG_INFO,
|
|
statement -> msg );
|
|
}
|
|
|
|
ret = extract_sql_error_field( &statement -> error,
|
|
rec_number,
|
|
diag_identifier,
|
|
diag_info_ptr,
|
|
buffer_length,
|
|
string_length_ptr );
|
|
|
|
if ( log_info.log_flag )
|
|
{
|
|
sprintf( statement -> msg,
|
|
"\n\t\tExit:[%s]",
|
|
__get_return_status( ret, s1 ));
|
|
|
|
dm_log_write( __FILE__,
|
|
__LINE__,
|
|
LOG_INFO,
|
|
LOG_INFO,
|
|
statement -> msg );
|
|
}
|
|
|
|
thread_release( SQL_HANDLE_STMT, statement );
|
|
|
|
return ret;
|
|
}
|
|
else if ( handle_type == SQL_HANDLE_DESC )
|
|
{
|
|
DMHDESC descriptor = ( DMHDESC ) handle;
|
|
|
|
if ( !__validate_desc( descriptor ))
|
|
{
|
|
return SQL_INVALID_HANDLE;
|
|
}
|
|
|
|
thread_protect( SQL_HANDLE_DESC, descriptor );
|
|
|
|
if ( log_info.log_flag )
|
|
{
|
|
sprintf( descriptor -> msg,
|
|
"\n\t\tEntry:\
|
|
\n\t\t\tDescriptor = %p\
|
|
\n\t\t\tRec Number = %d\
|
|
\n\t\t\tDiag Ident = %d\
|
|
\n\t\t\tDiag Info Ptr = %p\
|
|
\n\t\t\tBuffer Length = %d\
|
|
\n\t\t\tString Len Ptr = %p",
|
|
descriptor,
|
|
rec_number,
|
|
diag_identifier,
|
|
diag_info_ptr,
|
|
buffer_length,
|
|
string_length_ptr );
|
|
|
|
dm_log_write( __FILE__,
|
|
__LINE__,
|
|
LOG_INFO,
|
|
LOG_INFO,
|
|
descriptor -> msg );
|
|
}
|
|
|
|
ret = extract_sql_error_field( &descriptor -> error,
|
|
rec_number,
|
|
diag_identifier,
|
|
diag_info_ptr,
|
|
buffer_length,
|
|
string_length_ptr );
|
|
|
|
if ( log_info.log_flag )
|
|
{
|
|
sprintf( descriptor -> msg,
|
|
"\n\t\tExit:[%s]",
|
|
__get_return_status( ret, s1 ));
|
|
|
|
dm_log_write( __FILE__,
|
|
__LINE__,
|
|
LOG_INFO,
|
|
LOG_INFO,
|
|
descriptor -> msg );
|
|
}
|
|
|
|
thread_release( SQL_HANDLE_DESC, descriptor );
|
|
|
|
return ret;
|
|
}
|
|
return SQL_NO_DATA;
|
|
}
|
|
|