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: SQLGetDiagFieldW.c,v 1.10 2009/02/18 17:59:08 lurcher Exp $
31 *
32 * $Log: SQLGetDiagFieldW.c,v $
33 * Revision 1.10 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.9 2009/02/04 09:30:02 lurcher
37 * Fix some SQLINTEGER/SQLLEN conflicts
38 *
39 * Revision 1.8 2007/02/28 15:37:48 lurcher
40 * deal with drivers that call internal W functions and end up in the driver manager. controlled by the --enable-handlemap configure arg
41 *
42 * Revision 1.7 2002/12/05 17:44:30 lurcher
43 *
44 * Display unknown return values in return logging
45 *
46 * Revision 1.6 2002/11/11 17:10:14 lurcher
47 *
48 * VMS changes
49 *
50 * Revision 1.5 2002/08/23 09:42:37 lurcher
51 *
52 * Fix some build warnings with casts, and a AIX linker mod, to include
53 * deplib's on the link line, but not the libtool generated ones
54 *
55 * Revision 1.4 2002/07/24 08:49:52 lurcher
56 *
57 * Alter UNICODE support to use iconv for UNICODE-ANSI conversion
58 *
59 * Revision 1.3 2002/01/21 18:00:51 lurcher
60 *
61 * Assorted fixed and changes, mainly UNICODE/bug fixes
62 *
63 * Revision 1.2 2001/12/13 13:00:32 lurcher
64 *
65 * Remove most if not all warnings on 64 bit platforms
66 * Add support for new MS 3.52 64 bit changes
67 * Add override to disable the stopping of tracing
68 * Add MAX_ROWS support in postgres driver
69 *
70 * Revision 1.1.1.1 2001/10/17 16:40:05 lurcher
71 *
72 * First upload to SourceForge
73 *
74 * Revision 1.4 2001/07/03 09:30:41 nick
75 *
76 * Add ability to alter size of displayed message in the log
77 *
78 * Revision 1.3 2001/04/12 17:43:36 nick
79 *
80 * Change logging and added autotest to odbctest
81 *
82 * Revision 1.2 2001/01/04 13:16:25 nick
83 *
84 * Add support for GNU portable threads and tidy up some UNICODE compile
85 * warnings
86 *
87 * Revision 1.1 2000/12/31 20:30:54 nick
88 *
89 * Add UNICODE support
90 *
91 *
92 **********************************************************************/
93
94#include <config.h>
95#include "drivermanager.h"
96
97static char const rcsid[]= "$RCSfile: SQLGetDiagFieldW.c,v $";
98
99#define ODBC30_SUBCLASS "01S00,01S01,01S02,01S06,01S07,07S01,08S01,21S01,\
10021S02,25S01,25S02,25S03,42S01,42S02,42S11,42S12,42S21,42S22,HY095,HY097,HY098,\
101HY099,HY100,HY101,HY105,HY107,HY109,HY110,HY111,HYT00,HYT01,IM001,IM002,IM003,\
102IM004,IM005,IM006,IM007,IM008,IM010,IM011,IM012"
103
104/*
105 * is it a diag identifier that we have to convert from unicode to ansi
106 */
107
108static int is_char_diag( int diag_identifier )
109{
110 switch( diag_identifier ) {
111 case SQL_DIAG_CLASS_ORIGIN:
112 case SQL_DIAG_CONNECTION_NAME:
113 case SQL_DIAG_DYNAMIC_FUNCTION:
114 case SQL_DIAG_MESSAGE_TEXT:
115 case SQL_DIAG_SERVER_NAME:
116 case SQL_DIAG_SQLSTATE:
117 case SQL_DIAG_SUBCLASS_ORIGIN:
118 return 1;
119
120 default:
121 return 0;
122 }
123}
124
125static SQLRETURN extract_sql_error_field_w( EHEAD *head,
126 SQLSMALLINT rec_number,
127 SQLSMALLINT diag_identifier,
128 SQLPOINTER diag_info_ptr,
129 SQLSMALLINT buffer_length,
130 SQLSMALLINT *string_length_ptr )
131{
132 ERROR *ptr;
133
134 if ( is_char_diag( diag_identifier ) && buffer_length < 0 )
135 {
136 return SQL_ERROR;
137 }
138
139 /*
140 * check the header fields first
141 */
142
143 switch( diag_identifier )
144 {
145 case SQL_DIAG_CURSOR_ROW_COUNT:
146 case SQL_DIAG_ROW_COUNT:
147 {
148 SQLINTEGER val;
149 SQLRETURN ret;
150
151 if ( rec_number > 0 || head -> handle_type != SQL_HANDLE_STMT )
152 {
153 return SQL_ERROR;
154 }
155 else if ( head -> header_set )
156 {
157 switch( diag_identifier )
158 {
159 case SQL_DIAG_CURSOR_ROW_COUNT:
160 if ( SQL_SUCCEEDED( head -> diag_cursor_row_count_ret ) && diag_info_ptr )
161 {
162 *((SQLINTEGER*)diag_info_ptr) = head -> diag_cursor_row_count;
163 }
164 return head -> diag_cursor_row_count_ret;
165
166 case SQL_DIAG_ROW_COUNT:
167 if ( SQL_SUCCEEDED( head -> diag_row_count_ret ) && diag_info_ptr )
168 {
169 *((SQLINTEGER*)diag_info_ptr) = head -> diag_row_count;
170 }
171 return head -> diag_row_count_ret;
172 }
173 }
174 else if ( __get_connection( head ) -> unicode_driver &&
175 CHECK_SQLGETDIAGFIELDW( __get_connection( head )))
176 {
177 ret = SQLGETDIAGFIELDW( __get_connection( head ),
178 SQL_HANDLE_STMT,
179 __get_driver_handle( head ),
180 0,
181 diag_identifier,
182 diag_info_ptr,
183 buffer_length,
184 string_length_ptr );
185
186 return ret;
187 }
188 else if ( !__get_connection( head ) -> unicode_driver &&
189 CHECK_SQLGETDIAGFIELD( __get_connection( head )))
190 {
191 ret = SQLGETDIAGFIELD( __get_connection( head ),
192 SQL_HANDLE_STMT,
193 __get_driver_handle( head ),
194 0,
195 diag_identifier,
196 diag_info_ptr,
197 buffer_length,
198 string_length_ptr );
199
200 return ret;
201 }
202 else if ( CHECK_SQLROWCOUNT( __get_connection( head )))
203 {
204 ret = DEF_SQLROWCOUNT( __get_connection( head ),
205 __get_driver_handle( head ),
206 &val );
207
208 if ( !SQL_SUCCEEDED( ret ))
209 {
210 return ret;
211 }
212 }
213 else
214 {
215 val = 0;
216 }
217
218 if ( diag_info_ptr )
219 {
220 memcpy( diag_info_ptr, &val, sizeof( val ));
221 }
222 }
223 return SQL_SUCCESS;
224
225 case SQL_DIAG_DYNAMIC_FUNCTION:
226 {
227 SQLRETURN ret;
228
229 if ( rec_number > 0 )
230 {
231 return SQL_ERROR;
232 }
233 else if ( head -> handle_type != SQL_HANDLE_STMT )
234 {
235 if ( diag_info_ptr )
236 {
237 *((SQLWCHAR*)diag_info_ptr) = 0;
238 }
239 if ( string_length_ptr )
240 {
241 *string_length_ptr = 0;
242 }
243 return SQL_SUCCESS;
244 }
245 else if ( head -> header_set )
246 {
247 if ( SQL_SUCCEEDED( head -> diag_dynamic_function_ret ) && diag_info_ptr )
248 {
249 wide_strncpy( diag_info_ptr, head -> diag_dynamic_function, buffer_length );
250 if ( string_length_ptr )
251 {
252 *string_length_ptr = wide_strlen( head -> diag_dynamic_function ) * sizeof( SQLWCHAR );
253 }
254 }
255 return head -> diag_dynamic_function_ret;
256 }
257 else if ( __get_connection( head ) -> unicode_driver &&
258 CHECK_SQLGETDIAGFIELDW( __get_connection( head )))
259 {
260 ret = SQLGETDIAGFIELDW( __get_connection( head ),
261 SQL_HANDLE_STMT,
262 __get_driver_handle( head ),
263 0,
264 diag_identifier,
265 diag_info_ptr,
266 buffer_length,
267 string_length_ptr );
268
269 return ret;
270 }
271 else if ( !__get_connection( head ) -> unicode_driver &&
272 CHECK_SQLGETDIAGFIELD( __get_connection( head )))
273 {
274 SQLCHAR *as1 = NULL;
275
276 if ( buffer_length > 0 && diag_info_ptr )
277 {
278 as1 = malloc( buffer_length + 1 );
279 }
280
281 ret = SQLGETDIAGFIELD( __get_connection( head ),
282 SQL_HANDLE_STMT,
283 __get_driver_handle( head ),
284 0,
285 diag_identifier,
286 as1 ? as1 : diag_info_ptr,
287 buffer_length / 2,
288 string_length_ptr );
289
290 if ( SQL_SUCCEEDED( ret ) && as1 && diag_info_ptr )
291 {
292 ansi_to_unicode_copy( diag_info_ptr, (char*) as1, SQL_NTS, __get_connection( head ), NULL);
293 }
294 if ( SQL_SUCCEEDED( ret ) && string_length_ptr )
295 {
296 *string_length_ptr *= sizeof( SQLWCHAR );
297 }
298
299 if ( as1 )
300 {
301 free( as1 );
302 }
303
304 return ret;
305 }
306 if ( diag_info_ptr )
307 {
308 strcpy( diag_info_ptr, "" );
309 }
310 }
311 return SQL_SUCCESS;
312
313 case SQL_DIAG_DYNAMIC_FUNCTION_CODE:
314 {
315 SQLINTEGER val;
316 SQLRETURN ret;
317
318 if ( rec_number > 0 )
319 {
320 return SQL_ERROR;
321 }
322 else if ( head -> handle_type != SQL_HANDLE_STMT )
323 {
324 *((SQLINTEGER*)diag_info_ptr) = 0;
325 return SQL_SUCCESS;
326 }
327 else if ( head -> header_set )
328 {
329 if ( SQL_SUCCEEDED( head -> diag_dynamic_function_code_ret ) && diag_info_ptr )
330 {
331 *((SQLINTEGER*)diag_info_ptr) = head -> diag_dynamic_function_code;
332 }
333 return head -> diag_dynamic_function_code_ret;
334 }
335 else if ( __get_connection( head ) -> unicode_driver &&
336 CHECK_SQLGETDIAGFIELDW( __get_connection( head )))
337 {
338 ret = SQLGETDIAGFIELDW( __get_connection( head ),
339 SQL_HANDLE_STMT,
340 __get_driver_handle( head ),
341 0,
342 diag_identifier,
343 diag_info_ptr,
344 buffer_length,
345 string_length_ptr );
346
347 return ret;
348 }
349 else if ( !__get_connection( head ) -> unicode_driver &&
350 CHECK_SQLGETDIAGFIELD( __get_connection( head )))
351 {
352 ret = SQLGETDIAGFIELD( __get_connection( head ),
353 SQL_HANDLE_STMT,
354 __get_driver_handle( head ),
355 0,
356 diag_identifier,
357 diag_info_ptr,
358 buffer_length,
359 string_length_ptr );
360
361 return ret;
362 }
363 else
364 {
365 val = SQL_DIAG_UNKNOWN_STATEMENT;
366 }
367
368 if ( diag_info_ptr )
369 {
370 memcpy( diag_info_ptr, &val, sizeof( val ));
371 }
372 }
373 return SQL_SUCCESS;
374
375 case SQL_DIAG_NUMBER:
376 {
377 SQLINTEGER val;
378
379 if ( rec_number > 0 )
380 {
381 return SQL_ERROR;
382 }
383 val = head -> sql_diag_head.internal_count +
384 head -> sql_diag_head.error_count;
385
386 if ( diag_info_ptr )
387 {
388 memcpy( diag_info_ptr, &val, sizeof( val ));
389 }
390 }
391 return SQL_SUCCESS;
392
393 case SQL_DIAG_RETURNCODE:
394 {
395 if ( diag_info_ptr )
396 {
397 memcpy( diag_info_ptr, &head -> return_code,
398 sizeof( head -> return_code ));
399 }
400 }
401 return SQL_SUCCESS;
402 }
403
404 /*
405 * else check the records
406 */
407
408 if ( rec_number < 1 ||
409 ( diag_identifier == SQL_DIAG_COLUMN_NUMBER ||
410 diag_identifier == SQL_DIAG_ROW_NUMBER ) && head -> handle_type != SQL_HANDLE_STMT )
411 {
412 return SQL_ERROR;
413 }
414
415 if ( rec_number <= head -> sql_diag_head.internal_count )
416 {
417 /*
418 * local errors
419 */
420
421 ptr = head -> sql_diag_head.internal_list_head;
422 while( rec_number > 1 )
423 {
424 ptr = ptr -> next;
425 rec_number --;
426 }
427 if ( !ptr )
428 {
429 return SQL_NO_DATA;
430 }
431 }
432 else if ( rec_number <= head -> sql_diag_head.internal_count +
433 head -> sql_diag_head.error_count )
434 {
435 rec_number -= head -> sql_diag_head.internal_count;
436
437 if ( __get_connection( head ) -> unicode_driver &&
438 CHECK_SQLGETDIAGFIELDW( __get_connection( head )))
439 {
440 SQLRETURN ret;
441
442 ret = SQLGETDIAGFIELDW( __get_connection( head ),
443 head -> handle_type,
444 __get_driver_handle( head ),
445 rec_number,
446 diag_identifier,
447 diag_info_ptr,
448 buffer_length,
449 string_length_ptr );
450
451 if ( SQL_SUCCEEDED( ret ) && diag_identifier == SQL_DIAG_SQLSTATE )
452 {
453 /*
454 * map 3 to 2 if required
455 */
456
457 if ( diag_info_ptr )
458 __map_error_state_w( diag_info_ptr, __get_version( head ));
459 }
460
461 return ret;
462 }
463 else if ( !__get_connection( head ) -> unicode_driver &&
464 CHECK_SQLGETDIAGFIELD( __get_connection( head )))
465 {
466 SQLRETURN ret;
467 SQLCHAR *as1 = NULL;
468
469 if ( is_char_diag( diag_identifier ) && diag_info_ptr && buffer_length > 0 )
470 {
471 as1 = malloc( buffer_length + 1 );
472 }
473
474 ret = SQLGETDIAGFIELD( __get_connection( head ),
475 head -> handle_type,
476 __get_driver_handle( head ),
477 rec_number,
478 diag_identifier,
479 as1 ? as1 : diag_info_ptr,
480 buffer_length,
481 string_length_ptr );
482
483 if ( SQL_SUCCEEDED( ret ) && diag_identifier == SQL_DIAG_SQLSTATE )
484 {
485 /*
486 * map 3 to 2 if required
487 */
488
489 if ( diag_info_ptr && as1 )
490 {
491 __map_error_state( (char*) as1, __get_version( head ));
492 ansi_to_unicode_copy( diag_info_ptr, (char*) as1, SQL_NTS, __get_connection( head ), NULL );
493 }
494 }
495
496 if ( as1 )
497 {
498 free( as1 );
499 }
500
501 return ret;
502 }
503 else
504 {
505 ptr = head -> sql_diag_head.error_list_head;
506 while( rec_number > 1 )
507 {
508 ptr = ptr -> next;
509 rec_number --;
510 }
511
512 if ( !ptr )
513 {
514 return SQL_NO_DATA;
515 }
516 }
517 }
518 else
519 {
520 return SQL_NO_DATA;
521 }
522
523 /*
524 * if we are here ptr should point to the error
525 * record
526 */
527
528 switch( diag_identifier )
529 {
530 case SQL_DIAG_CLASS_ORIGIN:
531 {
532 if ( SQL_SUCCEEDED( ptr -> diag_class_origin_ret ))
533 {
534 wide_strncpy( diag_info_ptr, ptr -> diag_class_origin, buffer_length );
535 if ( string_length_ptr )
536 {
537 *string_length_ptr = wide_strlen( ptr -> diag_class_origin ) * sizeof( SQLWCHAR );
538 }
539 return ptr -> diag_class_origin_ret;
540 }
541 else
542 {
543 return ptr -> diag_class_origin_ret;
544 }
545 }
546 break;
547
548 case SQL_DIAG_COLUMN_NUMBER:
549 {
550 if ( diag_info_ptr )
551 {
552 memcpy( diag_info_ptr, &ptr -> diag_column_number, sizeof( SQLINTEGER ));
553 }
554 return SQL_SUCCESS;
555 }
556 break;
557
558 case SQL_DIAG_CONNECTION_NAME:
559 {
560 if ( SQL_SUCCEEDED( ptr -> diag_connection_name_ret ))
561 {
562 wide_strcpy( diag_info_ptr, ptr -> diag_connection_name );
563 if ( string_length_ptr )
564 {
565 *string_length_ptr = wide_strlen( ptr -> diag_connection_name ) * sizeof( SQLWCHAR );
566 }
567 return ptr -> diag_connection_name_ret;
568 }
569 else
570 {
571 return ptr -> diag_connection_name_ret;
572 }
573 }
574 break;
575
576 case SQL_DIAG_MESSAGE_TEXT:
577 {
578 SQLWCHAR *str;
579 int ret = SQL_SUCCESS;
580
581 str = ptr -> msg;
582
583 if ( diag_info_ptr )
584 {
585 if ( buffer_length >= wide_strlen( str ) + 1 )
586 {
587 wide_strcpy( diag_info_ptr, str );
588 }
589 else
590 {
591 ret = SQL_SUCCESS_WITH_INFO;
592 memcpy( diag_info_ptr, str, ( buffer_length - 1 ) * 2 );
593 (( SQLWCHAR * ) diag_info_ptr )[ buffer_length - 1 ] = '\0';
594 }
595 }
596 if ( string_length_ptr )
597 {
598 *string_length_ptr = wide_strlen( str ) * sizeof( SQLWCHAR );
599 }
600
601 return ret;
602 }
603 break;
604
605 case SQL_DIAG_NATIVE:
606 {
607 if ( diag_info_ptr )
608 {
609 memcpy( diag_info_ptr, &ptr -> native_error, sizeof( SQLINTEGER ));
610 }
611 return SQL_SUCCESS;
612 }
613 break;
614
615 case SQL_DIAG_ROW_NUMBER:
616 {
617 if ( diag_info_ptr )
618 {
619 memcpy( diag_info_ptr, &ptr -> diag_row_number, sizeof( SQLINTEGER ));
620 }
621 return SQL_SUCCESS;
622 }
623 break;
624
625 case SQL_DIAG_SERVER_NAME:
626 {
627 if ( SQL_SUCCEEDED( ptr -> diag_server_name_ret ))
628 {
629 wide_strcpy( diag_info_ptr, ptr -> diag_server_name );
630 if ( string_length_ptr )
631 {
632 *string_length_ptr = wide_strlen( ptr -> diag_server_name ) * sizeof( SQLWCHAR );
633 }
634 return ptr -> diag_server_name_ret;
635 }
636 else
637 {
638 return ptr -> diag_server_name_ret;
639 }
640 }
641 break;
642
643 case SQL_DIAG_SQLSTATE:
644 {
645 SQLWCHAR *str;
646 int ret = SQL_SUCCESS;
647
648 str = ptr -> sqlstate;
649
650 if ( diag_info_ptr )
651 {
652 if ( buffer_length >= wide_strlen( str ) + 1 )
653 {
654 wide_strcpy( diag_info_ptr, str );
655 }
656 else
657 {
658 ret = SQL_SUCCESS_WITH_INFO;
659 memcpy( diag_info_ptr, str, ( buffer_length - 1 ) * 2 );
660 (( SQLWCHAR * ) diag_info_ptr )[ buffer_length - 1 ] = '\0';
661 }
662
663 /*
664 * map 3 to 2 if required
665 */
666
667 if ( diag_info_ptr )
668 __map_error_state_w( diag_info_ptr, __get_version( head ));
669 }
670 if ( string_length_ptr )
671 {
672 *string_length_ptr = wide_strlen( str ) * sizeof( SQLWCHAR );
673 }
674 return ret;
675 }
676 break;
677
678 case SQL_DIAG_SUBCLASS_ORIGIN:
679 {
680 if ( SQL_SUCCEEDED( ptr -> diag_subclass_origin_ret ))
681 {
682 wide_strcpy( diag_info_ptr, ptr -> diag_subclass_origin );
683 if ( string_length_ptr )
684 {
685 *string_length_ptr = wide_strlen( ptr -> diag_subclass_origin ) * sizeof( SQLWCHAR );
686 }
687 return ptr -> diag_subclass_origin_ret;
688 }
689 else
690 {
691 return ptr -> diag_subclass_origin_ret;
692 }
693 }
694 break;
695 }
696
697 return SQL_SUCCESS;
698}
699
700SQLRETURN SQLGetDiagFieldW( SQLSMALLINT handle_type,
701 SQLHANDLE handle,
702 SQLSMALLINT rec_number,
703 SQLSMALLINT diag_identifier,
704 SQLPOINTER diag_info_ptr,
705 SQLSMALLINT buffer_length,
706 SQLSMALLINT *string_length_ptr )
707{
708 SQLRETURN ret;
709 SQLCHAR s1[ 100 + LOG_MESSAGE_LEN ];
710
711 if ( handle_type == SQL_HANDLE_ENV )
712 {
713 DMHENV environment = ( DMHENV ) handle;
714
715 if ( !__validate_env( environment ))
716 {
717 dm_log_write( __FILE__,
718 __LINE__,
719 LOG_INFO,
720 LOG_INFO,
721 "Error: SQL_INVALID_HANDLE" );
722
723 return SQL_INVALID_HANDLE;
724 }
725
726 thread_protect( SQL_HANDLE_ENV, environment );
727
728 if ( log_info.log_flag )
729 {
730 sprintf( environment -> msg,
731 "\n\t\tEntry:\
732\n\t\t\tEnvironment = %p\
733\n\t\t\tRec Number = %d\
734\n\t\t\tDiag Ident = %d\
735\n\t\t\tDiag Info Ptr = %p\
736\n\t\t\tBuffer Length = %d\
737\n\t\t\tString Len Ptr = %p",
738 environment,
739 rec_number,
740 diag_identifier,
741 diag_info_ptr,
742 buffer_length,
743 string_length_ptr );
744
745 dm_log_write( __FILE__,
746 __LINE__,
747 LOG_INFO,
748 LOG_INFO,
749 environment -> msg );
750 }
751
752 ret = extract_sql_error_field_w( &environment -> error,
753 rec_number,
754 diag_identifier,
755 diag_info_ptr,
756 buffer_length,
757 string_length_ptr );
758
759 if ( log_info.log_flag )
760 {
761 sprintf( environment -> msg,
762 "\n\t\tExit:[%s]",
763 __get_return_status( ret, s1 ));
764
765 dm_log_write( __FILE__,
766 __LINE__,
767 LOG_INFO,
768 LOG_INFO,
769 environment -> msg );
770 }
771
772 thread_release( SQL_HANDLE_ENV, environment );
773
774 return ret;
775 }
776 else if ( handle_type == SQL_HANDLE_DBC )
777 {
778 DMHDBC connection = ( DMHDBC ) handle;
779
780 if ( !__validate_dbc( connection ))
781 {
782 dm_log_write( __FILE__,
783 __LINE__,
784 LOG_INFO,
785 LOG_INFO,
786 "Error: SQL_INVALID_HANDLE" );
787
788#ifdef WITH_HANDLE_REDIRECT
789 {
790 DMHDBC parent_connection;
791
792 parent_connection = find_parent_handle( connection, SQL_HANDLE_DBC );
793
794 if ( parent_connection ) {
795 dm_log_write( __FILE__,
796 __LINE__,
797 LOG_INFO,
798 LOG_INFO,
799 "Info: found parent handle" );
800
801 if ( CHECK_SQLGETDIAGFIELDW( parent_connection ))
802 {
803 dm_log_write( __FILE__,
804 __LINE__,
805 LOG_INFO,
806 LOG_INFO,
807 "Info: calling redirected driver function" );
808
809 return SQLGETDIAGFIELDW( parent_connection,
810 handle_type,
811 connection,
812 rec_number,
813 diag_identifier,
814 diag_info_ptr,
815 buffer_length,
816 string_length_ptr );
817 }
818 }
819 }
820#endif
821 return SQL_INVALID_HANDLE;
822 }
823
824 thread_protect( SQL_HANDLE_DBC, connection );
825
826 if ( log_info.log_flag )
827 {
828 sprintf( connection -> msg,
829 "\n\t\tEntry:\
830\n\t\t\tConnection = %p\
831\n\t\t\tRec Number = %d\
832\n\t\t\tDiag Ident = %d\
833\n\t\t\tDiag Info Ptr = %p\
834\n\t\t\tBuffer Length = %d\
835\n\t\t\tString Len Ptr = %p",
836 connection,
837 rec_number,
838 diag_identifier,
839 diag_info_ptr,
840 buffer_length,
841 string_length_ptr );
842
843 dm_log_write( __FILE__,
844 __LINE__,
845 LOG_INFO,
846 LOG_INFO,
847 connection -> msg );
848 }
849
850 ret = extract_sql_error_field_w( &connection -> error,
851 rec_number,
852 diag_identifier,
853 diag_info_ptr,
854 buffer_length,
855 string_length_ptr );
856
857 if ( log_info.log_flag )
858 {
859 sprintf( connection -> msg,
860 "\n\t\tExit:[%s]",
861 __get_return_status( ret, s1 ));
862
863 dm_log_write( __FILE__,
864 __LINE__,
865 LOG_INFO,
866 LOG_INFO,
867 connection -> msg );
868 }
869
870 thread_release( SQL_HANDLE_DBC, connection );
871
872 return ret;
873 }
874 else if ( handle_type == SQL_HANDLE_STMT )
875 {
876 DMHSTMT statement = ( DMHSTMT ) handle;
877
878 if ( !__validate_stmt( statement ))
879 {
880 dm_log_write( __FILE__,
881 __LINE__,
882 LOG_INFO,
883 LOG_INFO,
884 "Error: SQL_INVALID_HANDLE" );
885
886#ifdef WITH_HANDLE_REDIRECT
887 {
888 DMHSTMT parent_statement;
889
890 parent_statement = find_parent_handle( statement, SQL_HANDLE_STMT );
891
892 if ( parent_statement ) {
893 dm_log_write( __FILE__,
894 __LINE__,
895 LOG_INFO,
896 LOG_INFO,
897 "Info: found parent handle" );
898
899 if ( CHECK_SQLGETDIAGFIELDW( parent_statement -> connection ))
900 {
901 dm_log_write( __FILE__,
902 __LINE__,
903 LOG_INFO,
904 LOG_INFO,
905 "Info: calling redirected driver function" );
906
907 return SQLGETDIAGFIELDW( parent_statement -> connection,
908 handle_type,
909 statement,
910 rec_number,
911 diag_identifier,
912 diag_info_ptr,
913 buffer_length,
914 string_length_ptr );
915 }
916 }
917 }
918#endif
919 return SQL_INVALID_HANDLE;
920 }
921
922 thread_protect( SQL_HANDLE_STMT, statement );
923
924 if ( log_info.log_flag )
925 {
926 sprintf( statement -> msg,
927 "\n\t\tEntry:\
928\n\t\t\tStatement = %p\
929\n\t\t\tRec Number = %d\
930\n\t\t\tDiag Ident = %d\
931\n\t\t\tDiag Info Ptr = %p\
932\n\t\t\tBuffer Length = %d\
933\n\t\t\tString Len Ptr = %p",
934 statement,
935 rec_number,
936 diag_identifier,
937 diag_info_ptr,
938 buffer_length,
939 string_length_ptr );
940
941 dm_log_write( __FILE__,
942 __LINE__,
943 LOG_INFO,
944 LOG_INFO,
945 statement -> msg );
946 }
947
948 ret = extract_sql_error_field_w( &statement -> error,
949 rec_number,
950 diag_identifier,
951 diag_info_ptr,
952 buffer_length,
953 string_length_ptr );
954
955 if ( log_info.log_flag )
956 {
957 sprintf( statement -> msg,
958 "\n\t\tExit:[%s]",
959 __get_return_status( ret, s1 ));
960
961 dm_log_write( __FILE__,
962 __LINE__,
963 LOG_INFO,
964 LOG_INFO,
965 statement -> msg );
966 }
967
968 thread_release( SQL_HANDLE_STMT, statement );
969
970 return ret;
971 }
972 else if ( handle_type == SQL_HANDLE_DESC )
973 {
974 DMHDESC descriptor = ( DMHDESC ) handle;
975
976 if ( !__validate_desc( descriptor ))
977 {
978 dm_log_write( __FILE__,
979 __LINE__,
980 LOG_INFO,
981 LOG_INFO,
982 "Error: SQL_INVALID_HANDLE" );
983
984#ifdef WITH_HANDLE_REDIRECT
985 {
986 DMHDESC parent_desc;
987
988 parent_desc = find_parent_handle( descriptor, SQL_HANDLE_DESC );
989
990 if ( parent_desc ) {
991 dm_log_write( __FILE__,
992 __LINE__,
993 LOG_INFO,
994 LOG_INFO,
995 "Info: found parent handle" );
996
997 if ( CHECK_SQLGETDIAGFIELDW( parent_desc -> connection ))
998 {
999 dm_log_write( __FILE__,
1000 __LINE__,
1001 LOG_INFO,
1002 LOG_INFO,
1003 "Info: calling redirected driver function" );
1004
1005 return SQLGETDIAGFIELDW( parent_desc -> connection,
1006 handle_type,
1007 descriptor,
1008 rec_number,
1009 diag_identifier,
1010 diag_info_ptr,
1011 buffer_length,
1012 string_length_ptr );
1013 }
1014 }
1015 }
1016#endif
1017 return SQL_INVALID_HANDLE;
1018 }
1019
1020 thread_protect( SQL_HANDLE_DESC, descriptor );
1021
1022 if ( log_info.log_flag )
1023 {
1024 sprintf( descriptor -> msg,
1025 "\n\t\tEntry:\
1026\n\t\t\tDescriptor = %p\
1027\n\t\t\tRec Number = %d\
1028\n\t\t\tDiag Ident = %d\
1029\n\t\t\tDiag Info Ptr = %p\
1030\n\t\t\tBuffer Length = %d\
1031\n\t\t\tString Len Ptr = %p",
1032 descriptor,
1033 rec_number,
1034 diag_identifier,
1035 diag_info_ptr,
1036 buffer_length,
1037 string_length_ptr );
1038
1039 dm_log_write( __FILE__,
1040 __LINE__,
1041 LOG_INFO,
1042 LOG_INFO,
1043 descriptor -> msg );
1044 }
1045
1046 ret = extract_sql_error_field_w( &descriptor -> error,
1047 rec_number,
1048 diag_identifier,
1049 diag_info_ptr,
1050 buffer_length,
1051 string_length_ptr );
1052
1053 if ( log_info.log_flag )
1054 {
1055 sprintf( descriptor -> msg,
1056 "\n\t\tExit:[%s]",
1057 __get_return_status( ret, s1 ));
1058
1059 dm_log_write( __FILE__,
1060 __LINE__,
1061 LOG_INFO,
1062 LOG_INFO,
1063 descriptor -> msg );
1064 }
1065
1066 thread_release( SQL_HANDLE_DESC, descriptor );
1067
1068 return ret;
1069 }
1070 return SQL_NO_DATA;
1071}
1072
1073