1/*********************************************************************
2 *
3 * This is based on code created by Peter Harvey,
4 * (pharvey@codebydesign.com).
5 *
6 * Modified and extended by Nick Gorham
7 * (nick@lurcher.org).
8 *
9 * Any bugs or problems should be considered the fault of Nick and not
10 * Peter.
11 *
12 * copyright (c) 1999 Nick Gorham
13 *
14 * This library is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU Lesser General Public
16 * License as published by the Free Software Foundation; either
17 * version 2 of the License, or (at your option) any later version.
18 *
19 * This library is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * Lesser General Public License for more details.
23 *
24 * You should have received a copy of the GNU Lesser General Public
25 * License along with this library; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 *
28 **********************************************************************
29 *
30 * $Id: SQLGetConnectOption.c,v 1.9 2009/02/18 17:59:08 lurcher Exp $
31 *
32 * $Log: SQLGetConnectOption.c,v $
33 * Revision 1.9 2009/02/18 17:59:08 lurcher
34 * Shift to using config.h, the compile lines were making it hard to spot warnings
35 *
36 * Revision 1.8 2009/02/17 09:47:44 lurcher
37 * Clear up a number of bugs
38 *
39 * Revision 1.7 2008/09/29 14:02:45 lurcher
40 * Fix missing dlfcn group option
41 *
42 * Revision 1.6 2003/10/30 18:20:46 lurcher
43 *
44 * Fix broken thread protection
45 * Remove SQLNumResultCols after execute, lease S4/S% to driver
46 * Fix string overrun in SQLDriverConnect
47 * Add initial support for Interix
48 *
49 * Revision 1.5 2003/02/27 12:19:39 lurcher
50 *
51 * Add the A functions as well as the W
52 *
53 * Revision 1.4 2002/12/05 17:44:30 lurcher
54 *
55 * Display unknown return values in return logging
56 *
57 * Revision 1.3 2002/11/11 17:10:10 lurcher
58 *
59 * VMS changes
60 *
61 * Revision 1.2 2002/07/24 08:49:52 lurcher
62 *
63 * Alter UNICODE support to use iconv for UNICODE-ANSI conversion
64 *
65 * Revision 1.1.1.1 2001/10/17 16:40:05 lurcher
66 *
67 * First upload to SourceForge
68 *
69 * Revision 1.5 2001/08/03 15:19:00 nick
70 *
71 * Add changes to set values before connect
72 *
73 * Revision 1.4 2001/07/03 09:30:41 nick
74 *
75 * Add ability to alter size of displayed message in the log
76 *
77 * Revision 1.3 2001/04/12 17:43:36 nick
78 *
79 * Change logging and added autotest to odbctest
80 *
81 * Revision 1.2 2000/12/31 20:30:54 nick
82 *
83 * Add UNICODE support
84 *
85 * Revision 1.1.1.1 2000/09/04 16:42:52 nick
86 * Imported Sources
87 *
88 * Revision 1.8 1999/11/13 23:40:59 ngorham
89 *
90 * Alter the way DM logging works
91 * Upgrade the Postgres driver to 6.4.6
92 *
93 * Revision 1.7 1999/10/24 23:54:18 ngorham
94 *
95 * First part of the changes to the error reporting
96 *
97 * Revision 1.6 1999/09/21 22:34:25 ngorham
98 *
99 * Improve performance by removing unneeded logging calls when logging is
100 * disabled
101 *
102 * Revision 1.5 1999/09/19 22:24:34 ngorham
103 *
104 * Added support for the cursor library
105 *
106 * Revision 1.4 1999/07/10 21:10:16 ngorham
107 *
108 * Adjust error sqlstate from driver manager, depending on requested
109 * version (ODBC2/3)
110 *
111 * Revision 1.3 1999/07/04 21:05:07 ngorham
112 *
113 * Add LGPL Headers to code
114 *
115 * Revision 1.2 1999/06/30 23:56:55 ngorham
116 *
117 * Add initial thread safety code
118 *
119 * Revision 1.1.1.1 1999/05/29 13:41:07 sShandyb
120 * first go at it
121 *
122 * Revision 1.3 1999/06/02 20:12:10 ngorham
123 *
124 * Fixed botched log entry, and removed the dos \r from the sql header files.
125 *
126 * Revision 1.2 1999/06/02 19:57:20 ngorham
127 *
128 * Added code to check if a attempt is being made to compile with a C++
129 * Compiler, and issue a message.
130 * Start work on the ODBC2-3 conversions.
131 *
132 * Revision 1.1.1.1 1999/05/27 18:23:17 pharvey
133 * Imported sources
134 *
135 * Revision 1.2 1999/05/09 23:27:11 nick
136 * All the API done now
137 *
138 * Revision 1.1 1999/04/25 23:06:11 nick
139 * Initial revision
140 *
141 *
142 **********************************************************************/
143
144#include <config.h>
145#include "drivermanager.h"
146
147static char const rcsid[]= "$RCSfile: SQLGetConnectOption.c,v $ $Revision: 1.9 $";
148
149SQLRETURN SQLGetConnectOptionA( SQLHDBC connection_handle,
150 SQLUSMALLINT option,
151 SQLPOINTER value )
152{
153 return SQLGetConnectOption( connection_handle,
154 option,
155 value );
156}
157
158SQLRETURN SQLGetConnectOption( SQLHDBC connection_handle,
159 SQLUSMALLINT option,
160 SQLPOINTER value )
161{
162 DMHDBC connection = (DMHDBC)connection_handle;
163 int type = 0;
164 SQLCHAR s1[ 100 + LOG_MESSAGE_LEN ];
165
166 /*
167 * doesn't require a handle
168 */
169
170 if ( option == SQL_ATTR_TRACE )
171 {
172 if ( value )
173 {
174 if ( log_info.log_flag )
175 {
176 *((SQLINTEGER*)value) = SQL_OPT_TRACE_ON;
177 }
178 else
179 {
180 *((SQLINTEGER*)value) = SQL_OPT_TRACE_ON;
181 }
182 }
183
184 return SQL_SUCCESS;
185 }
186 else if ( option == SQL_ATTR_TRACEFILE )
187 {
188 SQLRETURN ret = SQL_SUCCESS;
189
190 if ( log_info.log_file_name )
191 {
192 strcpy( value, log_info.log_file_name );
193 }
194 else
195 {
196 strcpy( value, "" );
197 }
198 return ret;
199 }
200
201 /*
202 * check connection
203 */
204
205 if ( !__validate_dbc( connection ))
206 {
207 dm_log_write( __FILE__,
208 __LINE__,
209 LOG_INFO,
210 LOG_INFO,
211 "Error: SQL_INVALID_HANDLE" );
212
213 return SQL_INVALID_HANDLE;
214 }
215
216 function_entry( connection );
217
218 if ( log_info.log_flag )
219 {
220 sprintf( connection -> msg, "\n\t\tEntry:\
221\n\t\t\tConnection = %p\
222\n\t\t\tOption = %s\
223\n\t\t\tValue = %p",
224 connection,
225 __con_attr_as_string( s1, option ),
226 value );
227
228 dm_log_write( __FILE__,
229 __LINE__,
230 LOG_INFO,
231 LOG_INFO,
232 connection -> msg );
233 }
234
235 thread_protect( SQL_HANDLE_DBC, connection );
236
237 if ( connection -> state == STATE_C3 )
238 {
239 dm_log_write( __FILE__,
240 __LINE__,
241 LOG_INFO,
242 LOG_INFO,
243 "Error: HY010" );
244
245 __post_internal_error( &connection -> error,
246 ERROR_HY010, NULL,
247 connection -> environment -> requested_version );
248
249 return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
250 }
251
252 if ( connection -> state == STATE_C2 )
253 {
254 switch ( option )
255 {
256 case SQL_ACCESS_MODE:
257 case SQL_AUTOCOMMIT:
258 case SQL_LOGIN_TIMEOUT:
259 case SQL_ODBC_CURSORS:
260 break;
261
262 default:
263 dm_log_write( __FILE__,
264 __LINE__,
265 LOG_INFO,
266 LOG_INFO,
267 "Error: 08003" );
268
269 __post_internal_error( &connection -> error,
270 ERROR_08003, NULL,
271 connection -> environment -> requested_version );
272
273 return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
274 }
275 }
276
277 switch ( option )
278 {
279 case SQL_ACCESS_MODE:
280 /*
281 * if connected, call the driver
282 */
283 if ( connection -> state != STATE_C2 )
284 {
285 type = 0;
286 }
287 else
288 {
289 *((SQLINTEGER*)value) = connection -> access_mode;
290 type = 1;
291 }
292 break;
293
294 case SQL_AUTOCOMMIT:
295 /*
296 * if connected, call the driver
297 */
298 if ( connection -> state != STATE_C2 )
299 {
300 type = 0;
301 }
302 else
303 {
304 *((SQLINTEGER*)value) = connection -> auto_commit;
305 type = 1;
306 }
307 break;
308
309 case SQL_ODBC_CURSORS:
310 *((SQLINTEGER*)value) = connection -> cursors;
311 type = 1;
312 break;
313
314 case SQL_ATTR_LOGIN_TIMEOUT:
315 /*
316 * if connected, call the driver
317 */
318 if ( connection -> state != STATE_C2 )
319 {
320 type = 0;
321 }
322 else
323 {
324 *((SQLINTEGER*)value) = connection -> login_timeout;
325 type = 1;
326 }
327 break;
328
329 default:
330 break;
331 }
332
333 /*
334 * if type has been set we have already set the value,
335 * so just return
336 */
337 if ( type )
338 {
339 sprintf( connection -> msg,
340 "\n\t\tExit:[%s]",
341 __get_return_status( SQL_SUCCESS, s1 ));
342
343 dm_log_write( __FILE__,
344 __LINE__,
345 LOG_INFO,
346 LOG_INFO,
347 connection -> msg );
348
349 return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_SUCCESS );
350 }
351 else
352 {
353 SQLRETURN ret = 0;
354
355 /*
356 * call the driver
357 */
358
359 if ( connection -> unicode_driver )
360 {
361 SQLWCHAR *s1 = NULL;
362
363 if (( ret = CHECK_SQLGETCONNECTOPTIONW( connection )))
364 {
365 switch( option )
366 {
367 case SQL_ATTR_CURRENT_CATALOG:
368 case SQL_ATTR_TRACEFILE:
369 case SQL_ATTR_TRANSLATE_LIB:
370 if ( SQL_SUCCEEDED( ret ) && value )
371 {
372 /*
373 * guess a length
374 */
375 if ( value )
376 {
377 s1 = malloc( sizeof( SQLWCHAR ) * 1024 );
378 }
379 }
380 break;
381 }
382
383 ret = SQLGETCONNECTOPTIONW( connection,
384 connection -> driver_dbc,
385 option,
386 s1 ? s1 : value );
387
388 switch( option )
389 {
390 case SQL_ATTR_CURRENT_CATALOG:
391 case SQL_ATTR_TRACEFILE:
392 case SQL_ATTR_TRANSLATE_LIB:
393 if ( SQL_SUCCEEDED( ret ) && value && s1 )
394 {
395 unicode_to_ansi_copy( value, 1024, s1, SQL_NTS, connection, NULL );
396 }
397 break;
398 }
399
400 if ( s1 )
401 {
402 free( s1 );
403 }
404 }
405 else if ( CHECK_SQLGETCONNECTATTRW( connection ))
406 {
407 SQLINTEGER length, len;
408 void * ptr;
409 SQLWCHAR txt[ 1024 ];
410
411 switch( option )
412 {
413 case SQL_ATTR_CURRENT_CATALOG:
414 case SQL_ATTR_TRACEFILE:
415 case SQL_ATTR_TRANSLATE_LIB:
416 length = sizeof( txt );
417 ptr = txt;
418 break;
419
420 default:
421 length = sizeof( SQLINTEGER );
422 ptr = value;
423 break;
424
425 }
426
427 ret = SQLGETCONNECTATTRW( connection,
428 connection -> driver_dbc,
429 option,
430 ptr,
431 length,
432 &len );
433
434 /*
435 * not much else we can do here, lets assume that
436 * there is enough space
437 */
438
439 if ( ptr != value && SQL_SUCCEEDED( ret ))
440 {
441 unicode_to_ansi_copy( value, 1024, ptr, SQL_NTS, connection, NULL );
442
443 /*
444 * are we still here ? good
445 */
446 }
447 }
448 else
449 {
450 __post_internal_error( &connection -> error,
451 ERROR_IM001, NULL,
452 connection -> environment -> requested_version );
453
454 return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
455 }
456 }
457 else
458 {
459 if ( CHECK_SQLGETCONNECTOPTION( connection ))
460 {
461 ret = SQLGETCONNECTOPTION( connection,
462 connection -> driver_dbc,
463 option,
464 value );
465 }
466 else if ( CHECK_SQLGETCONNECTATTR( connection ))
467 {
468 SQLINTEGER length, len;
469 void * ptr;
470 char txt[ 1024 ];
471
472 switch( option )
473 {
474 case SQL_ATTR_CURRENT_CATALOG:
475 case SQL_ATTR_TRACEFILE:
476 case SQL_ATTR_TRANSLATE_LIB:
477 length = sizeof( txt );
478 ptr = txt;
479 break;
480
481 default:
482 length = sizeof( SQLINTEGER );
483 ptr = value;
484 break;
485
486 }
487
488 ret = SQLGETCONNECTATTR( connection,
489 connection -> driver_dbc,
490 option,
491 ptr,
492 length,
493 &len );
494
495 /*
496 * not much else we can do here, lets assume that
497 * there is enough space
498 */
499
500 if ( ptr != value )
501 {
502 strcpy( value, ptr );
503
504 /*
505 * are we still here ? good
506 */
507 }
508 }
509 else
510 {
511 __post_internal_error( &connection -> error,
512 ERROR_IM001, NULL,
513 connection -> environment -> requested_version );
514
515 return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
516 }
517 }
518
519 if ( log_info.log_flag )
520 {
521 sprintf( connection -> msg,
522 "\n\t\tExit:[%s]",
523 __get_return_status( ret, s1 ));
524
525 dm_log_write( __FILE__,
526 __LINE__,
527 LOG_INFO,
528 LOG_INFO,
529 connection -> msg );
530 }
531
532 return function_return( SQL_HANDLE_DBC, connection, ret );
533 }
534}
535