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