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 | |
97 | static char const rcsid[]= "$RCSfile: SQLGetDiagFieldW.c,v $" ; |
98 | |
99 | #define ODBC30_SUBCLASS "01S00,01S01,01S02,01S06,01S07,07S01,08S01,21S01,\ |
100 | 21S02,25S01,25S02,25S03,42S01,42S02,42S11,42S12,42S21,42S22,HY095,HY097,HY098,\ |
101 | HY099,HY100,HY101,HY105,HY107,HY109,HY110,HY111,HYT00,HYT01,IM001,IM002,IM003,\ |
102 | IM004,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 | |
108 | static 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 | |
125 | static SQLRETURN ( 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 | |
700 | SQLRETURN 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 | |