28
28
**********************************************************************
30
* $Id: SQLConnect.c,v 1.4 2001/12/19 15:55:53 lurcher Exp $
30
* $Id: SQLConnect.c,v 1.20 2002/12/20 11:36:46 lurcher Exp $
32
32
* $Log: SQLConnect.c,v $
33
* Revision 1.20 2002/12/20 11:36:46 lurcher
35
* Update DMEnvAttr code to allow setting in the odbcinst.ini entry
37
* Revision 1.19 2002/12/05 17:44:30 lurcher
39
* Display unknown return values in return logging
41
* Revision 1.18 2002/11/19 18:52:27 lurcher
43
* Alter the cursor lib to not require linking to the driver manager.
45
* Revision 1.17 2002/11/13 15:59:20 lurcher
49
* Revision 1.16 2002/08/27 08:49:02 lurcher
51
* New version number and fix for cursor lib loading
53
* Revision 1.15 2002/08/23 09:42:37 lurcher
55
* Fix some build warnings with casts, and a AIX linker mod, to include
56
* deplib's on the link line, but not the libtool generated ones
58
* Revision 1.14 2002/08/12 13:17:52 lurcher
60
* Replicate the way the MS DM handles loading of driver libs, and allocating
61
* handles in the driver. usage counting in the driver means that dlopen is
62
* only called for the first use, and dlclose for the last. AllocHandle for
63
* the driver environment is only called for the first time per driver
64
* per application environment.
66
* Revision 1.13 2002/07/25 09:30:26 lurcher
68
* Additional unicode and iconv changes
70
* Revision 1.12 2002/07/24 08:49:51 lurcher
72
* Alter UNICODE support to use iconv for UNICODE-ANSI conversion
74
* Revision 1.11 2002/07/12 09:01:37 lurcher
76
* Fix problem, with SAPDB where if the connection specifies ODBC 2, the
77
* don't make use of the ODBC 3 method of SQLGetFunctions
79
* Revision 1.10 2002/07/04 17:27:56 lurcher
83
* Revision 1.8 2002/05/24 12:42:49 lurcher
85
* Alter NEWS and ChangeLog to match their correct usage
86
* Additional UNICODE tweeks
88
* Revision 1.7 2002/03/26 09:35:46 lurcher
90
* Extend naming of cursor lib to work on non linux platforms
93
* Revision 1.6 2002/02/21 18:44:09 lurcher
95
* Fix bug on 32 bit platforms without long long support
96
* Add option to set environment variables from the ini file
98
* Revision 1.5 2002/01/21 18:00:51 lurcher
100
* Assorted fixed and changes, mainly UNICODE/bug fixes
33
102
* Revision 1.4 2001/12/19 15:55:53 lurcher
35
104
* Add option to disable calling of SQLGetFunctions in driver
587
* implement reference counting for driver libs
595
struct lib_count *next;
599
* I hate statics, but there is little option here, there can be multiple envs
600
* so I can't save it in them
603
static struct lib_count *lib_list = NULL;
605
static void *odbc_dlopen( char *libname )
608
struct lib_count *list;
613
* have we already got it ?
619
if ( strcmp( list -> lib_name, libname ) == 0 )
630
hand = list -> handle;
634
hand = lt_dlopen( libname );
638
list = malloc( sizeof( struct lib_count ));
639
list -> next = lib_list;
642
list -> lib_name = strdup( libname );
643
list -> handle = hand;
652
static odbc_dlclose( void *handle )
654
struct lib_count *list, *prev;
659
* look for list entry
666
if ( list -> handle == handle )
676
* it should always be found, but you never know...
683
if ( list -> count < 1 )
685
free( list -> lib_name );
686
lt_dlclose( list -> handle );
689
prev -> next = list -> next;
693
lib_list = list -> next;
700
lt_dlclose( handle );
517
707
* open the library, extract the names, and do setup
518
708
* before the actual connect.
521
int __connect_part_one( DMHDBC connection, char *driver_lib, char *driver_name )
711
int __connect_part_one( DMHDBC connection, char *driver_lib, char *driver_name, int *warnings )
766
* allocate a env handle
989
* check if this is the first time this driver has been loaded under this
990
* lib, if not then reuse the env, else get the env from the driver
769
if ( CHECK_SQLALLOCHANDLE( connection ))
995
env_lib_list = connection -> environment -> env_lib_list;
998
while( env_lib_list )
771
ret = SQLALLOCHANDLE( connection,
774
&connection -> driver_env,
1000
if ( strcmp( driver_lib, env_lib_list -> lib_name ) == 0 )
1004
env_lib_prev = env_lib_list;
1005
env_lib_list = env_lib_list -> next;
777
else if ( CHECK_SQLALLOCENV( connection ))
779
ret = SQLALLOCENV( connection,
780
&connection -> driver_env );
1010
env_lib_list -> count ++;
1011
connection -> driver_env = env_lib_list -> env_handle;
1012
connection -> env_list_ent = env_lib_list;
784
dm_log_write( __FILE__,
790
__post_internal_error( &connection -> error,
792
connection -> environment -> requested_version );
798
dm_log_write( __FILE__,
804
__post_internal_error( &connection -> error,
806
connection -> environment -> requested_version );
811
* if it looks like a 3.x driver, try setting the interface type
814
if ( CHECK_SQLSETENVATTR( connection ))
816
ret = SQLSETENVATTR( connection,
817
connection -> driver_env,
818
SQL_ATTR_ODBC_VERSION,
819
connection -> environment -> requested_version,
1018
env_lib_list = calloc( 1, sizeof( struct env_lib_struct ));
1020
env_lib_list -> count = 1;
1021
env_lib_list -> next = connection -> environment -> env_lib_list;
1022
env_lib_list -> lib_name = strdup( driver_lib );
1023
connection -> env_list_ent = env_lib_list;
1025
connection -> environment -> env_lib_list = env_lib_list;
1029
__set_local_attributes( connection, SQL_HANDLE_ENV );
823
* if it don't set then assume a 2.x driver
1032
* allocate a env handle
1035
if ( CHECK_SQLALLOCHANDLE( connection ))
1037
ret = SQLALLOCHANDLE( connection,
1040
&connection -> driver_env,
1043
else if ( CHECK_SQLALLOCENV( connection ))
1045
ret = SQLALLOCENV( connection,
1046
&connection -> driver_env );
1050
dm_log_write( __FILE__,
1056
__post_internal_error( &connection -> error,
1058
connection -> environment -> requested_version );
1060
if ( env_lib_list -> count == 1 )
1066
env_lib_prev -> next = env_lib_list -> next;
1070
connection -> environment -> env_lib_list = env_lib_list -> next;
1073
free( env_lib_list -> lib_name );
1074
free( env_lib_list );
1082
env_lib_list -> count --;
1090
env_lib_list -> env_handle = connection -> driver_env;
828
connection -> driver_version = SQL_OV_ODBC2;
1094
dm_log_write( __FILE__,
1100
__post_internal_error( &connection -> error,
1102
connection -> environment -> requested_version );
1104
if ( env_lib_list -> count == 1 )
1110
env_lib_prev -> next = env_lib_list -> next;
1114
connection -> environment -> env_lib_list = env_lib_list -> next;
1117
free( env_lib_list -> lib_name );
1118
free( env_lib_list );
1126
env_lib_list -> count --;
1135
* if it looks like a 3.x driver, try setting the interface type
1138
if ( CHECK_SQLSETENVATTR( connection ))
832
if ( CHECK_SQLGETENVATTR( connection ))
834
SQLINTEGER actual_version;
836
ret = SQLGETENVATTR( connection,
1140
ret = SQLSETENVATTR( connection,
837
1141
connection -> driver_env,
838
1142
SQL_ATTR_ODBC_VERSION,
1143
connection -> environment -> requested_version,
1147
* if it don't set then assume a 2.x driver
1152
connection -> driver_version = SQL_OV_ODBC2;
1156
if ( CHECK_SQLGETENVATTR( connection ))
845
connection -> driver_version = actual_version;
1158
SQLINTEGER actual_version;
1160
ret = SQLGETENVATTR( connection,
1161
connection -> driver_env,
1162
SQL_ATTR_ODBC_VERSION,
1169
connection -> driver_version = actual_version;
1173
connection -> driver_version =
1174
connection -> environment -> requested_version;
1502
1827
if ( use_cursor )
1504
int (*cl_connect)(void*);
1506
if ( !(connection -> cl_handle = lt_dlopen( CURSOR_LIB )))
1830
int (*cl_connect)(void*, struct driver_helper_funcs*);
1831
struct driver_helper_funcs dh;
1833
sprintf( name, "%s%s%s", CURSOR_LIB, SHLIBEXT, CURSOR_LIB_VER );
1835
if ( !(connection -> cl_handle = odbc_dlopen( name )))
1510
sprintf( txt, "Can't open cursor lib '%s' : %s",
1511
CURSOR_LIB, lt_dlerror());
1513
dm_log_write( __FILE__,
1519
__post_internal_error( &connection -> error,
1521
connection -> environment -> requested_version );
1842
sprintf( name, "%s:%s%s%s", SYSTEM_LIB_PATH, CURSOR_LIB, SHLIBEXT, CURSOR_LIB_VER );
1844
sprintf( name, "%s/%s%s%s", SYSTEM_LIB_PATH, CURSOR_LIB, SHLIBEXT, CURSOR_LIB_VER );
1846
if ( !(connection -> cl_handle = odbc_dlopen( name )))
1850
sprintf( txt, "Can't open cursor lib '%s' : %s",
1851
CURSOR_LIB, lt_dlerror());
1853
dm_log_write( __FILE__,
1859
__post_internal_error( &connection -> error,
1861
connection -> environment -> requested_version );
1526
if ( !( cl_connect = (int(*)(void*))lt_dlsym( connection -> cl_handle,
1867
if ( !( cl_connect = (int(*)(void*, struct driver_helper_funcs* ))lt_dlsym( connection -> cl_handle,
1527
1868
"CLConnect" )))
1529
1870
dm_log_write( __FILE__,
1536
1877
ERROR_01000, "Unable to load cursor library",
1537
1878
connection -> environment -> requested_version );
1539
lt_dlclose( connection -> cl_handle );
1880
odbc_dlclose( connection -> cl_handle );
1540
1881
connection -> cl_handle = NULL;
1544
if ( cl_connect( connection ) != SQL_SUCCESS )
1887
* setup helper functions
1890
dh.__post_internal_error_ex = __post_internal_error_ex;
1891
dh.__post_internal_error = __post_internal_error;
1892
dh.dm_log_write = dm_log_write;
1894
if ( cl_connect( connection, &dh ) != SQL_SUCCESS )
1546
lt_dlclose( connection -> cl_handle );
1896
odbc_dlclose( connection -> cl_handle );
1547
1897
connection -> cl_handle = NULL;
1602
1953
connection -> driver_dbc = (SQLHANDLE)NULL;
1605
* now disconnect the environment
1956
* now disconnect the environment, if its the last usage on the connection
1608
1959
if ( connection -> driver_env )
1610
if ( connection -> driver_version == SQL_OV_ODBC3 )
1612
if ( CHECK_SQLFREEHANDLE( connection ))
1614
ret = SQLFREEHANDLE( connection,
1961
env_lib_prev = env_lib_list = NULL;
1963
if ( connection -> env_list_ent )
1965
env_lib_list = connection -> environment -> env_lib_list;
1966
while( env_lib_list )
1968
if ( env_lib_list == connection -> env_list_ent )
1972
env_lib_prev = env_lib_list;
1973
env_lib_list = env_lib_list -> next;
1977
if ( env_lib_list && env_lib_list -> count > 1 )
1980
env_lib_list -> count --;
1985
if ( connection -> driver_version == SQL_OV_ODBC3 )
1987
if ( CHECK_SQLFREEHANDLE( connection ))
1989
ret = SQLFREEHANDLE( connection,
1991
connection -> driver_env );
1994
connection -> driver_env = (SQLHANDLE)NULL;
1999
* is it still open ?
2002
if ( CHECK_SQLFREEENV( connection ))
2004
SQLFREEENV( connection,
1616
2005
connection -> driver_env );
1619
connection -> driver_env = (SQLHANDLE)NULL;
1624
* is it still open ?
1627
if ( CHECK_SQLFREEENV( connection ))
1629
SQLFREEENV( connection,
1630
connection -> driver_env );
2010
* not a lot we can do here
1635
* not a lot we can do here
2022
env_lib_prev -> next = env_lib_list -> next;
2026
connection -> environment -> env_lib_list = env_lib_list -> next;
2029
free( env_lib_list -> lib_name );
2030
free( env_lib_list );
1639
2036
connection -> driver_env = (SQLHANDLE)NULL;
2090
void __disconnect_part_three( DMHDBC connection )
2092
struct env_lib_struct *env_lib_list, *env_lib_prev;
2094
if ( connection -> driver_version == SQL_OV_ODBC3 )
2096
if ( CHECK_SQLFREEHANDLE( connection ))
2098
SQLFREEHANDLE( connection,
2100
connection -> driver_dbc );
2102
else if ( CHECK_SQLFREECONNECT( connection ))
2104
SQLFREECONNECT( connection,
2105
connection -> driver_dbc );
2110
if ( CHECK_SQLFREECONNECT( connection ))
2112
SQLFREECONNECT( connection,
2113
connection -> driver_dbc );
2115
else if ( CHECK_SQLFREEHANDLE( connection ))
2117
SQLFREEHANDLE( connection,
2119
connection -> driver_dbc );
2123
connection -> driver_dbc = (SQLHANDLE)NULL;
2126
* now disconnect the environment, if its the last usage on the connection
2129
env_lib_prev = env_lib_list = NULL;
2131
if ( connection -> env_list_ent )
2133
env_lib_list = connection -> environment -> env_lib_list;
2134
while( env_lib_list )
2136
if ( env_lib_list == connection -> env_list_ent )
2140
env_lib_prev = env_lib_list;
2141
env_lib_list = env_lib_list -> next;
2145
if ( env_lib_list && env_lib_list -> count > 1 )
2148
env_lib_list -> count --;
2153
if ( connection -> driver_version == SQL_OV_ODBC3 )
2155
if ( CHECK_SQLFREEHANDLE( connection ))
2157
SQLFREEHANDLE( connection,
2159
connection -> driver_env );
2161
else if ( CHECK_SQLFREEENV( connection ))
2163
SQLFREEENV( connection,
2164
connection -> driver_env );
2169
if ( CHECK_SQLFREEENV( connection ))
2171
SQLFREEENV( connection,
2172
connection -> driver_env );
2174
else if ( CHECK_SQLFREEHANDLE( connection ))
2176
SQLFREEHANDLE( connection,
2178
connection -> driver_env );
2190
env_lib_prev -> next = env_lib_list -> next;
2194
connection -> environment -> env_lib_list = env_lib_list -> next;
2197
free( env_lib_list -> lib_name );
2198
free( env_lib_list );
2203
connection -> driver_env = (SQLHANDLE)NULL;
2209
if ( connection -> cl_handle )
2211
odbc_dlclose( connection -> cl_handle );
2212
connection -> cl_handle = NULL;
2215
if ( connection -> dl_handle )
2218
* this is safe, because the dlopen function will reuse the handle if we
2219
* open the same lib again
2221
if ( !connection -> dont_dlclose )
2223
if ( connection -> fini_func.func )
2225
connection -> fini_func.func();
2228
odbc_dlclose( connection -> dl_handle );
2230
connection -> dl_handle = NULL;
2237
unicode_shutdown( connection );
2243
if ( connection -> functions )
2245
free( connection -> functions );
2246
connection -> functions = NULL;
2248
connection -> state = STATE_C2;
2251
* now clean up any statements that are left about
2254
__clean_stmt_from_dbc( connection );
2255
__clean_desc_from_dbc( connection );
1690
2259
* interface for SQLGetFunctions
2304
2873
mutex_pool_exit();
2307
void __handle_attr_extensions( DMHDBC connection, char *dsn )
2876
void __handle_attr_extensions( DMHDBC connection, char *dsn, char *driver_name )
2309
2878
char txt[ 1024 ];
2311
SQLGetPrivateProfileString( dsn, "DMEnvAttr", "",
2317
__parse_attribute_string( &connection -> env_attribute,
2318
txt, strlen( txt ));
2321
SQLGetPrivateProfileString( dsn, "DMConnAttr", "",
2327
__parse_attribute_string( &connection -> dbc_attribute,
2328
txt, strlen( txt ));
2331
SQLGetPrivateProfileString( dsn, "DMStmtAttr", "",
2337
__parse_attribute_string( &connection -> stmt_attribute,
2338
txt, strlen( txt ));
2880
if ( dsn && strlen( dsn ))
2882
SQLGetPrivateProfileString( dsn, "DMEnvAttr", "",
2888
__parse_attribute_string( &connection -> env_attribute,
2889
txt, strlen( txt ));
2892
SQLGetPrivateProfileString( dsn, "DMConnAttr", "",
2898
__parse_attribute_string( &connection -> dbc_attribute,
2899
txt, strlen( txt ));
2902
SQLGetPrivateProfileString( dsn, "DMStmtAttr", "",
2908
__parse_attribute_string( &connection -> stmt_attribute,
2909
txt, strlen( txt ));
2913
if ( driver_name && strlen( driver_name ))
2915
SQLGetPrivateProfileString( driver_name, "DMEnvAttr", "",
2921
__parse_attribute_string( &connection -> env_attribute,
2922
txt, strlen( txt ));
2622
3208
* do we have any Environment, Connection, or Statement attributes set in the ini ?
2625
__handle_attr_extensions( connection, dsn );
3211
__handle_attr_extensions( connection, dsn, driver_name );
2628
3214
* if necessary change the threading level
2631
if ( !__connect_part_one( connection, lib_name, driver_name ))
3217
if ( !__connect_part_one( connection, lib_name, driver_name, &warnings ))
2633
3219
thread_release( SQL_HANDLE_DBC, connection );
2634
3220
return function_return( connection, SQL_ERROR );
2768
3369
SQLWCHAR * uc_dsn, *uc_user, *uc_auth;
2770
uc_dsn = ansi_to_unicode((SQLCHAR*) dsn, SQL_NTS );
2771
uc_user = ansi_to_unicode( user_name, name_length2 );
2772
uc_auth = ansi_to_unicode( authentication, name_length3 );
3371
uc_dsn = ansi_to_unicode_alloc((SQLCHAR*) dsn, SQL_NTS, connection );
3372
uc_user = ansi_to_unicode_alloc( user_name, name_length2, connection );
3373
uc_auth = ansi_to_unicode_alloc( authentication, name_length3, connection );
3375
if ( CHECK_SQLSETCONNECTATTR( connection ))
3379
lret = SQLSETCONNECTATTR( connection,
3380
connection -> driver_dbc,
2774
3386
ret_from_connect = SQLCONNECTW( connection,
2775
3387
connection -> driver_dbc,
2815
3427
if ( SQL_SUCCEEDED( ret ))
2817
3431
__post_internal_error_ex_w( &connection -> error,
3435
SUBCLASS_ODBC, SUBCLASS_ODBC );
2822
unicode_to_ansi( sqlstate, SQL_NTS );
2823
unicode_to_ansi( message_text, SQL_NTS );
3437
as1 = (SQLCHAR *) unicode_to_ansi_alloc( sqlstate, SQL_NTS, connection );
3438
as2 = (SQLCHAR *) unicode_to_ansi_alloc( message_text, SQL_NTS, connection );
2825
3440
sprintf( connection -> msg, "\t\tDIAG [%s] %s",
2826
sqlstate, message_text );
3443
if ( as1 ) free( as1 );
3444
if ( as2 ) free( as2 );
2828
3446
dm_log_write_diag( connection -> msg );
2849
3468
if ( SQL_SUCCEEDED( ret ))
2851
3472
__post_internal_error_ex_w( &connection -> error,
3476
SUBCLASS_ODBC, SUBCLASS_ODBC );
2856
unicode_to_ansi( sqlstate, SQL_NTS );
2857
unicode_to_ansi( message_text, SQL_NTS );
3478
as1 = (SQLCHAR *) unicode_to_ansi_alloc( sqlstate, SQL_NTS, connection );
3479
as2 = (SQLCHAR *) unicode_to_ansi_alloc( message_text, SQL_NTS, connection );
2859
3481
sprintf( connection -> msg, "\t\tDIAG [%s] %s",
2860
sqlstate, message_text );
3484
if ( as1 ) free( as1 );
3485
if ( as2 ) free( as2 );
2862
3487
dm_log_write_diag( connection -> msg );