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: SQLGetDiagRec.c,v 1.21 2009/02/18 17:59:08 lurcher Exp $ |
31 | * |
32 | * $Log: SQLGetDiagRec.c,v $ |
33 | * Revision 1.21 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.20 2009/02/17 09:47:44 lurcher |
37 | * Clear up a number of bugs |
38 | * |
39 | * Revision 1.19 2009/02/04 09:30:02 lurcher |
40 | * Fix some SQLINTEGER/SQLLEN conflicts |
41 | * |
42 | * Revision 1.18 2008/09/29 14:02:45 lurcher |
43 | * Fix missing dlfcn group option |
44 | * |
45 | * Revision 1.17 2008/05/20 13:43:47 lurcher |
46 | * Vms fixes |
47 | * |
48 | * Revision 1.16 2007/02/12 11:49:34 lurcher |
49 | * Add QT4 support to existing GUI parts |
50 | * |
51 | * Revision 1.15 2006/11/27 14:08:34 lurcher |
52 | * Sync up dirs |
53 | * |
54 | * Revision 1.14 2006/05/31 17:35:34 lurcher |
55 | * Add unicode ODBCINST entry points |
56 | * |
57 | * Revision 1.13 2006/04/24 08:42:10 lurcher |
58 | * Handle resetting statement descriptors to implicit values, by passing in NULL or the implicit descrptor to SQLSetStmtAttr with the attribute SQL_ATTR_APP_PARAM_DESC or SQL_ATTR_APP_ROW_DESC. Also catch trying to call SQLGetDescField on a closed connection |
59 | * |
60 | * Revision 1.12 2005/12/19 18:43:26 lurcher |
61 | * Add new parts to contrib and alter how the errors are returned from the driver |
62 | * |
63 | * Revision 1.11 2003/02/27 12:19:39 lurcher |
64 | * |
65 | * Add the A functions as well as the W |
66 | * |
67 | * Revision 1.10 2003/02/25 13:28:30 lurcher |
68 | * |
69 | * Allow errors on the drivers AllocHandle to be reported |
70 | * Fix a problem that caused errors to not be reported in the log |
71 | * Remove a redundant line from the spec file |
72 | * |
73 | * Revision 1.9 2002/12/05 17:44:31 lurcher |
74 | * |
75 | * Display unknown return values in return logging |
76 | * |
77 | * Revision 1.8 2002/11/13 15:59:20 lurcher |
78 | * |
79 | * More VMS changes |
80 | * |
81 | * Revision 1.7 2002/11/11 17:10:15 lurcher |
82 | * |
83 | * VMS changes |
84 | * |
85 | * Revision 1.6 2002/10/14 09:46:10 lurcher |
86 | * |
87 | * Remove extra return |
88 | * |
89 | * Revision 1.5 2002/10/08 13:36:07 lurcher |
90 | * |
91 | * Fix memory leak |
92 | * |
93 | * Revision 1.4 2002/08/23 09:42:37 lurcher |
94 | * |
95 | * Fix some build warnings with casts, and a AIX linker mod, to include |
96 | * deplib's on the link line, but not the libtool generated ones |
97 | * |
98 | * Revision 1.3 2002/07/24 08:49:52 lurcher |
99 | * |
100 | * Alter UNICODE support to use iconv for UNICODE-ANSI conversion |
101 | * |
102 | * Revision 1.2 2001/12/13 13:00:32 lurcher |
103 | * |
104 | * Remove most if not all warnings on 64 bit platforms |
105 | * Add support for new MS 3.52 64 bit changes |
106 | * Add override to disable the stopping of tracing |
107 | * Add MAX_ROWS support in postgres driver |
108 | * |
109 | * Revision 1.1.1.1 2001/10/17 16:40:05 lurcher |
110 | * |
111 | * First upload to SourceForge |
112 | * |
113 | * Revision 1.4 2001/07/03 09:30:41 nick |
114 | * |
115 | * Add ability to alter size of displayed message in the log |
116 | * |
117 | * Revision 1.3 2001/04/12 17:43:36 nick |
118 | * |
119 | * Change logging and added autotest to odbctest |
120 | * |
121 | * Revision 1.2 2000/12/31 20:30:54 nick |
122 | * |
123 | * Add UNICODE support |
124 | * |
125 | * Revision 1.1.1.1 2000/09/04 16:42:52 nick |
126 | * Imported Sources |
127 | * |
128 | * Revision 1.11 2000/06/23 16:11:38 ngorham |
129 | * |
130 | * Map ODBC 2 SQLSTATE values to ODBC 3 |
131 | * |
132 | * Revision 1.10 1999/12/01 09:20:07 ngorham |
133 | * |
134 | * Fix some threading problems |
135 | * |
136 | * Revision 1.9 1999/11/17 21:08:58 ngorham |
137 | * |
138 | * Fix Bug with the ODBC 3 error handling |
139 | * |
140 | * Revision 1.8 1999/11/13 23:40:59 ngorham |
141 | * |
142 | * Alter the way DM logging works |
143 | * Upgrade the Postgres driver to 6.4.6 |
144 | * |
145 | * Revision 1.7 1999/11/10 22:15:48 ngorham |
146 | * |
147 | * Fix some bugs with the DM and error reporting. |
148 | * |
149 | * Revision 1.6 1999/11/10 03:51:33 ngorham |
150 | * |
151 | * Update the error reporting in the DM to enable ODBC 3 and 2 calls to |
152 | * work at the same time |
153 | * |
154 | * Revision 1.5 1999/09/21 22:34:25 ngorham |
155 | * |
156 | * Improve performance by removing unneeded logging calls when logging is |
157 | * disabled |
158 | * |
159 | * Revision 1.4 1999/07/14 19:46:04 ngorham |
160 | * |
161 | * Fix the error logging when SQLError or SQLGetDiagRec returns SQL_NO_DATA |
162 | * |
163 | * Revision 1.3 1999/07/04 21:05:07 ngorham |
164 | * |
165 | * Add LGPL Headers to code |
166 | * |
167 | * Revision 1.2 1999/06/30 23:56:55 ngorham |
168 | * |
169 | * Add initial thread safety code |
170 | * |
171 | * Revision 1.1.1.1 1999/05/29 13:41:07 sShandyb |
172 | * first go at it |
173 | * |
174 | * Revision 1.1.1.1 1999/05/27 18:23:17 pharvey |
175 | * Imported sources |
176 | * |
177 | * Revision 1.1 1999/04/30 16:22:47 nick |
178 | * Another checkpoint |
179 | * |
180 | * |
181 | **********************************************************************/ |
182 | |
183 | #include <config.h> |
184 | #include "drivermanager.h" |
185 | |
186 | static char const rcsid[]= "$RCSfile: SQLGetDiagRec.c,v $ $Revision: 1.21 $" ; |
187 | |
188 | int __is_env( EHEAD * head ) |
189 | { |
190 | int type; |
191 | |
192 | memcpy( &type, head -> owning_handle, sizeof( type )); |
193 | |
194 | return type == HENV_MAGIC; |
195 | } |
196 | |
197 | DMHDBC __get_connection( EHEAD * head ) |
198 | { |
199 | int type; |
200 | |
201 | memcpy( &type, head -> owning_handle, sizeof( type )); |
202 | |
203 | switch ( type ) |
204 | { |
205 | case HDBC_MAGIC: |
206 | { |
207 | DMHDBC connection = ( DMHDBC ) head -> owning_handle; |
208 | |
209 | return connection; |
210 | } |
211 | |
212 | case HSTMT_MAGIC: |
213 | { |
214 | DMHSTMT statement = ( DMHSTMT ) head -> owning_handle; |
215 | |
216 | return statement -> connection; |
217 | } |
218 | |
219 | case HDESC_MAGIC: |
220 | { |
221 | DMHDESC descriptor = ( DMHDESC ) head -> owning_handle; |
222 | |
223 | return descriptor -> connection; |
224 | } |
225 | } |
226 | return NULL; |
227 | } |
228 | |
229 | int __get_version( EHEAD * head ) |
230 | { |
231 | int type; |
232 | |
233 | memcpy( &type, head -> owning_handle, sizeof( type )); |
234 | |
235 | switch ( type ) |
236 | { |
237 | case HENV_MAGIC: |
238 | { |
239 | DMHENV environment = ( DMHENV ) head -> owning_handle; |
240 | |
241 | return environment -> requested_version; |
242 | } |
243 | |
244 | case HDBC_MAGIC: |
245 | { |
246 | DMHDBC connection = ( DMHDBC ) head -> owning_handle; |
247 | |
248 | return connection -> environment -> requested_version; |
249 | } |
250 | |
251 | case HSTMT_MAGIC: |
252 | { |
253 | DMHSTMT statement = ( DMHSTMT ) head -> owning_handle; |
254 | |
255 | return statement -> connection -> environment -> requested_version; |
256 | } |
257 | |
258 | case HDESC_MAGIC: |
259 | { |
260 | DMHDESC descriptor = ( DMHDESC ) head -> owning_handle; |
261 | |
262 | return descriptor -> connection -> environment -> requested_version; |
263 | } |
264 | } |
265 | return 0; |
266 | } |
267 | |
268 | |
269 | DRV_SQLHANDLE __get_driver_handle( EHEAD * head ) |
270 | { |
271 | int type; |
272 | |
273 | memcpy( &type, head -> owning_handle, sizeof( type )); |
274 | |
275 | switch ( type ) |
276 | { |
277 | case HDBC_MAGIC: |
278 | { |
279 | DMHDBC connection = ( DMHDBC ) head -> owning_handle; |
280 | |
281 | return connection -> driver_dbc; |
282 | } |
283 | |
284 | case HSTMT_MAGIC: |
285 | { |
286 | DMHSTMT statement = ( DMHSTMT ) head -> owning_handle; |
287 | |
288 | return statement -> driver_stmt; |
289 | } |
290 | |
291 | case HDESC_MAGIC: |
292 | { |
293 | DMHDESC descriptor = ( DMHDESC ) head -> owning_handle; |
294 | |
295 | return descriptor -> driver_desc; |
296 | } |
297 | } |
298 | return ( SQLHANDLE ) 0; |
299 | } |
300 | |
301 | static SQLRETURN ( EHEAD *head, |
302 | SQLCHAR *sqlstate, |
303 | SQLINTEGER rec_number, |
304 | SQLINTEGER *native_error, |
305 | SQLCHAR *message_text, |
306 | SQLSMALLINT buffer_length, |
307 | SQLSMALLINT *text_length ) |
308 | { |
309 | SQLRETURN ret; |
310 | |
311 | if ( sqlstate ) |
312 | strcpy((char*) sqlstate, "00000" ); |
313 | |
314 | if ( rec_number <= head -> sql_diag_head.internal_count ) |
315 | { |
316 | ERROR *ptr; |
317 | SQLCHAR *as1 = NULL; |
318 | |
319 | ptr = head -> sql_diag_head.internal_list_head; |
320 | while( rec_number > 1 ) |
321 | { |
322 | ptr = ptr -> next; |
323 | rec_number --; |
324 | } |
325 | |
326 | if ( !ptr ) |
327 | { |
328 | return SQL_NO_DATA; |
329 | } |
330 | |
331 | as1 = (SQLCHAR*) unicode_to_ansi_alloc( ptr -> msg, SQL_NTS, __get_connection( head ), NULL ); |
332 | |
333 | if ( sqlstate ) |
334 | { |
335 | unicode_to_ansi_copy((char*) sqlstate, 6, ptr -> sqlstate, SQL_NTS, __get_connection( head ), NULL ); |
336 | } |
337 | if ( buffer_length < strlen((char*) as1 ) + 1 ) |
338 | { |
339 | ret = SQL_SUCCESS_WITH_INFO; |
340 | } |
341 | else |
342 | { |
343 | ret = SQL_SUCCESS; |
344 | } |
345 | |
346 | if ( message_text && as1 ) |
347 | { |
348 | if ( ret == SQL_SUCCESS ) |
349 | { |
350 | strcpy((char*) message_text, (char*) as1 ); |
351 | } |
352 | else |
353 | { |
354 | memcpy( message_text, as1, buffer_length ); |
355 | message_text[ buffer_length - 1 ] = '\0'; |
356 | } |
357 | } |
358 | |
359 | if ( text_length && as1 ) |
360 | { |
361 | *text_length = strlen((char*) as1 ); |
362 | } |
363 | |
364 | if ( native_error ) |
365 | { |
366 | *native_error = ptr -> native_error; |
367 | } |
368 | |
369 | /* |
370 | * map 3 to 2 if required |
371 | */ |
372 | |
373 | if ( SQL_SUCCEEDED( ret ) && sqlstate ) |
374 | __map_error_state( (char*) sqlstate, __get_version( head )); |
375 | |
376 | if ( as1 ) |
377 | { |
378 | free( as1 ); |
379 | } |
380 | return ret; |
381 | } |
382 | else if ( !__is_env( head ) && __get_connection( head ) -> state != STATE_C2 |
383 | && head->sql_diag_head.error_count ) |
384 | { |
385 | ERROR *ptr; |
386 | SQLWCHAR *s1 = NULL, *s2 = NULL; |
387 | |
388 | rec_number -= head -> sql_diag_head.internal_count; |
389 | |
390 | s1 = malloc( sizeof( SQLWCHAR ) * ( 6 + 1 )); |
391 | |
392 | if ( buffer_length > 0 ) |
393 | { |
394 | s2 = malloc( sizeof( SQLWCHAR ) * ( buffer_length + 1 )); |
395 | } |
396 | |
397 | if ( __get_connection( head ) -> unicode_driver && |
398 | CHECK_SQLGETDIAGRECW( __get_connection( head ))) |
399 | { |
400 | ret = SQLGETDIAGRECW( __get_connection( head ), |
401 | head -> handle_type, |
402 | __get_driver_handle( head ), |
403 | rec_number, |
404 | s1, |
405 | native_error, |
406 | s2, |
407 | buffer_length, |
408 | text_length ); |
409 | |
410 | /* |
411 | * map 3 to 2 if required |
412 | */ |
413 | |
414 | if ( SQL_SUCCEEDED( ret ) && sqlstate ) |
415 | { |
416 | if ( sqlstate ) |
417 | { |
418 | unicode_to_ansi_copy((char*) sqlstate, 6, s1, SQL_NTS, __get_connection( head ), NULL ); |
419 | __map_error_state((char*) sqlstate, __get_version( head )); |
420 | } |
421 | if ( message_text ) |
422 | { |
423 | unicode_to_ansi_copy((char*) message_text, buffer_length, s2, SQL_NTS, __get_connection( head ), NULL ); |
424 | } |
425 | } |
426 | |
427 | } |
428 | else if ( !__get_connection( head ) -> unicode_driver && |
429 | CHECK_SQLGETDIAGREC( __get_connection( head ))) |
430 | { |
431 | ret = SQLGETDIAGREC( __get_connection( head ), |
432 | head -> handle_type, |
433 | __get_driver_handle( head ), |
434 | rec_number, |
435 | sqlstate, |
436 | native_error, |
437 | message_text, |
438 | buffer_length, |
439 | text_length ); |
440 | |
441 | /* |
442 | * map 3 to 2 if required |
443 | */ |
444 | |
445 | if ( SQL_SUCCEEDED( ret ) && sqlstate ) |
446 | __map_error_state((char*) sqlstate, __get_version( head )); |
447 | } |
448 | else |
449 | { |
450 | SQLCHAR *as1 = NULL; |
451 | |
452 | ptr = head -> sql_diag_head.error_list_head; |
453 | while( rec_number > 1 ) |
454 | { |
455 | ptr = ptr -> next; |
456 | rec_number --; |
457 | } |
458 | |
459 | if ( !ptr ) |
460 | { |
461 | if ( s1 ) |
462 | free( s1 ); |
463 | |
464 | if ( s2 ) |
465 | free( s2 ); |
466 | |
467 | return SQL_NO_DATA; |
468 | } |
469 | |
470 | as1 = (SQLCHAR*) unicode_to_ansi_alloc( ptr -> msg, SQL_NTS, __get_connection( head ), NULL ); |
471 | |
472 | if ( sqlstate ) |
473 | { |
474 | unicode_to_ansi_copy((char*) sqlstate, 6, ptr -> sqlstate, SQL_NTS, __get_connection( head ), NULL ); |
475 | } |
476 | if ( as1 && buffer_length < strlen((char*) as1 ) + 1 ) |
477 | { |
478 | ret = SQL_SUCCESS_WITH_INFO; |
479 | } |
480 | else |
481 | { |
482 | ret = SQL_SUCCESS; |
483 | } |
484 | |
485 | if ( message_text && as1 ) |
486 | { |
487 | if ( ret == SQL_SUCCESS ) |
488 | { |
489 | strcpy((char*) message_text,(char*) as1 ); |
490 | } |
491 | else |
492 | { |
493 | memcpy( message_text, as1, buffer_length ); |
494 | message_text[ buffer_length - 1 ] = '\0'; |
495 | } |
496 | } |
497 | |
498 | if ( text_length && as1 ) |
499 | { |
500 | *text_length = strlen((char*) as1 ); |
501 | } |
502 | |
503 | if ( native_error ) |
504 | { |
505 | *native_error = ptr -> native_error; |
506 | } |
507 | |
508 | /* |
509 | * map 3 to 2 if required |
510 | */ |
511 | |
512 | if ( SQL_SUCCEEDED( ret ) && sqlstate ) |
513 | __map_error_state((char*) sqlstate, __get_version( head )); |
514 | |
515 | if ( as1 ) |
516 | { |
517 | free( as1 ); |
518 | } |
519 | } |
520 | |
521 | if ( s1 ) |
522 | free( s1 ); |
523 | |
524 | if ( s2 ) |
525 | free( s2 ); |
526 | |
527 | return ret; |
528 | } |
529 | else |
530 | { |
531 | return SQL_NO_DATA; |
532 | } |
533 | } |
534 | |
535 | SQLRETURN SQLGetDiagRecA( SQLSMALLINT handle_type, |
536 | SQLHANDLE handle, |
537 | SQLSMALLINT rec_number, |
538 | SQLCHAR *sqlstate, |
539 | SQLINTEGER *native, |
540 | SQLCHAR *message_text, |
541 | SQLSMALLINT buffer_length, |
542 | SQLSMALLINT *text_length_ptr ) |
543 | { |
544 | return SQLGetDiagRec( handle_type, |
545 | handle, |
546 | rec_number, |
547 | sqlstate, |
548 | native, |
549 | message_text, |
550 | buffer_length, |
551 | text_length_ptr ); |
552 | } |
553 | |
554 | SQLRETURN SQLGetDiagRec( SQLSMALLINT handle_type, |
555 | SQLHANDLE handle, |
556 | SQLSMALLINT rec_number, |
557 | SQLCHAR *sqlstate, |
558 | SQLINTEGER *native, |
559 | SQLCHAR *message_text, |
560 | SQLSMALLINT buffer_length, |
561 | SQLSMALLINT *text_length_ptr ) |
562 | { |
563 | SQLRETURN ret; |
564 | SQLCHAR s0[ 32 ], s1[ 100 + LOG_MESSAGE_LEN ]; |
565 | SQLCHAR s2[ 100 + LOG_MESSAGE_LEN ]; |
566 | |
567 | if ( rec_number < 1 ) |
568 | { |
569 | return SQL_ERROR; |
570 | } |
571 | |
572 | if ( handle_type == SQL_HANDLE_ENV ) |
573 | { |
574 | DMHENV environment = ( DMHENV ) handle; |
575 | |
576 | if ( !__validate_env( environment )) |
577 | { |
578 | dm_log_write( __FILE__, |
579 | __LINE__, |
580 | LOG_INFO, |
581 | LOG_INFO, |
582 | "Error: SQL_INVALID_HANDLE" ); |
583 | |
584 | return SQL_INVALID_HANDLE; |
585 | } |
586 | |
587 | thread_protect( SQL_HANDLE_ENV, environment ); |
588 | |
589 | if ( log_info.log_flag ) |
590 | { |
591 | sprintf( environment -> msg, |
592 | "\n\t\tEntry:\ |
593 | \n\t\t\tEnvironment = %p\ |
594 | \n\t\t\tRec Number = %d\ |
595 | \n\t\t\tSQLState = %p\ |
596 | \n\t\t\tNative = %p\ |
597 | \n\t\t\tMessage Text = %p\ |
598 | \n\t\t\tBuffer Length = %d\ |
599 | \n\t\t\tText Len Ptr = %p" , |
600 | environment, |
601 | rec_number, |
602 | sqlstate, |
603 | native, |
604 | message_text, |
605 | buffer_length, |
606 | text_length_ptr ); |
607 | |
608 | dm_log_write( __FILE__, |
609 | __LINE__, |
610 | LOG_INFO, |
611 | LOG_INFO, |
612 | environment -> msg ); |
613 | } |
614 | |
615 | ret = extract_sql_error_rec( &environment -> error, |
616 | sqlstate, |
617 | rec_number, |
618 | native, |
619 | message_text, |
620 | buffer_length, |
621 | text_length_ptr ); |
622 | |
623 | if ( log_info.log_flag ) |
624 | { |
625 | if ( SQL_SUCCEEDED( ret )) |
626 | { |
627 | sprintf( environment -> msg, |
628 | "\n\t\tExit:[%s]\ |
629 | \n\t\t\tSQLState = %s\ |
630 | \n\t\t\tNative = %s\ |
631 | \n\t\t\tMessage Text = %s" , |
632 | __get_return_status( ret, s2 ), |
633 | sqlstate ? sqlstate : (SQLCHAR*)"NULL" , |
634 | __iptr_as_string( s0, native ), |
635 | __sdata_as_string( s1, SQL_CHAR, |
636 | text_length_ptr, message_text )); |
637 | } |
638 | else |
639 | { |
640 | sprintf( environment -> msg, |
641 | "\n\t\tExit:[%s]" , |
642 | __get_return_status( ret, s1 )); |
643 | } |
644 | |
645 | dm_log_write( __FILE__, |
646 | __LINE__, |
647 | LOG_INFO, |
648 | LOG_INFO, |
649 | environment -> msg ); |
650 | } |
651 | |
652 | thread_release( SQL_HANDLE_ENV, environment ); |
653 | |
654 | return ret; |
655 | } |
656 | else if ( handle_type == SQL_HANDLE_DBC ) |
657 | { |
658 | DMHDBC connection = ( DMHDBC ) handle; |
659 | |
660 | if ( !__validate_dbc( connection )) |
661 | { |
662 | return SQL_INVALID_HANDLE; |
663 | } |
664 | |
665 | thread_protect( SQL_HANDLE_DBC, connection ); |
666 | |
667 | if ( log_info.log_flag ) |
668 | { |
669 | sprintf( connection -> msg, |
670 | "\n\t\tEntry:\ |
671 | \n\t\t\tConnection = %p\ |
672 | \n\t\t\tRec Number = %d\ |
673 | \n\t\t\tSQLState = %p\ |
674 | \n\t\t\tNative = %p\ |
675 | \n\t\t\tMessage Text = %p\ |
676 | \n\t\t\tBuffer Length = %d\ |
677 | \n\t\t\tText Len Ptr = %p" , |
678 | connection, |
679 | rec_number, |
680 | sqlstate, |
681 | native, |
682 | message_text, |
683 | buffer_length, |
684 | text_length_ptr ); |
685 | |
686 | dm_log_write( __FILE__, |
687 | __LINE__, |
688 | LOG_INFO, |
689 | LOG_INFO, |
690 | connection -> msg ); |
691 | } |
692 | |
693 | ret = extract_sql_error_rec( &connection -> error, |
694 | sqlstate, |
695 | rec_number, |
696 | native, |
697 | message_text, |
698 | buffer_length, |
699 | text_length_ptr ); |
700 | |
701 | if ( log_info.log_flag ) |
702 | { |
703 | if ( SQL_SUCCEEDED( ret )) |
704 | { |
705 | sprintf( connection -> msg, |
706 | "\n\t\tExit:[%s]\ |
707 | \n\t\t\tSQLState = %s\ |
708 | \n\t\t\tNative = %s\ |
709 | \n\t\t\tMessage Text = %s" , |
710 | __get_return_status( ret, s2 ), |
711 | sqlstate ? sqlstate : (SQLCHAR*)"NULL" , |
712 | __iptr_as_string( s0, native ), |
713 | __sdata_as_string( s1, SQL_CHAR, |
714 | text_length_ptr, message_text )); |
715 | } |
716 | else |
717 | { |
718 | sprintf( connection -> msg, |
719 | "\n\t\tExit:[%s]" , |
720 | __get_return_status( ret, s1 )); |
721 | } |
722 | |
723 | dm_log_write( __FILE__, |
724 | __LINE__, |
725 | LOG_INFO, |
726 | LOG_INFO, |
727 | connection -> msg ); |
728 | } |
729 | |
730 | thread_release( SQL_HANDLE_DBC, connection ); |
731 | |
732 | return ret; |
733 | } |
734 | else if ( handle_type == SQL_HANDLE_STMT ) |
735 | { |
736 | DMHSTMT statement = ( DMHSTMT ) handle; |
737 | |
738 | if ( !__validate_stmt( statement )) |
739 | { |
740 | return SQL_INVALID_HANDLE; |
741 | } |
742 | |
743 | thread_protect( SQL_HANDLE_STMT, statement ); |
744 | |
745 | if ( log_info.log_flag ) |
746 | { |
747 | sprintf( statement -> msg, |
748 | "\n\t\tEntry:\ |
749 | \n\t\t\tStatement = %p\ |
750 | \n\t\t\tRec Number = %d\ |
751 | \n\t\t\tSQLState = %p\ |
752 | \n\t\t\tNative = %p\ |
753 | \n\t\t\tMessage Text = %p\ |
754 | \n\t\t\tBuffer Length = %d\ |
755 | \n\t\t\tText Len Ptr = %p" , |
756 | statement, |
757 | rec_number, |
758 | sqlstate, |
759 | native, |
760 | message_text, |
761 | buffer_length, |
762 | text_length_ptr ); |
763 | |
764 | dm_log_write( __FILE__, |
765 | __LINE__, |
766 | LOG_INFO, |
767 | LOG_INFO, |
768 | statement -> msg ); |
769 | } |
770 | |
771 | ret = extract_sql_error_rec( &statement -> error, |
772 | sqlstate, |
773 | rec_number, |
774 | native, |
775 | message_text, |
776 | buffer_length, |
777 | text_length_ptr ); |
778 | |
779 | if ( log_info.log_flag ) |
780 | { |
781 | if ( SQL_SUCCEEDED( ret )) |
782 | { |
783 | sprintf( statement -> msg, |
784 | "\n\t\tExit:[%s]\ |
785 | \n\t\t\tSQLState = %s\ |
786 | \n\t\t\tNative = %s\ |
787 | \n\t\t\tMessage Text = %s" , |
788 | __get_return_status( ret, s2 ), |
789 | sqlstate ? sqlstate : (SQLCHAR*)"NULL" , |
790 | __iptr_as_string( s0, native ), |
791 | __sdata_as_string( s1, SQL_CHAR, |
792 | text_length_ptr, message_text )); |
793 | } |
794 | else |
795 | { |
796 | sprintf( statement -> msg, |
797 | "\n\t\tExit:[%s]" , |
798 | __get_return_status( ret, s1 )); |
799 | } |
800 | |
801 | dm_log_write( __FILE__, |
802 | __LINE__, |
803 | LOG_INFO, |
804 | LOG_INFO, |
805 | statement -> msg ); |
806 | } |
807 | |
808 | thread_release( SQL_HANDLE_STMT, statement ); |
809 | |
810 | return ret; |
811 | } |
812 | else if ( handle_type == SQL_HANDLE_DESC ) |
813 | { |
814 | DMHDESC descriptor = ( DMHDESC ) handle; |
815 | |
816 | if ( !__validate_desc( descriptor )) |
817 | { |
818 | return SQL_INVALID_HANDLE; |
819 | } |
820 | |
821 | thread_protect( SQL_HANDLE_DESC, descriptor ); |
822 | |
823 | if ( log_info.log_flag ) |
824 | { |
825 | sprintf( descriptor -> msg, |
826 | "\n\t\tEntry:\ |
827 | \n\t\t\tDescriptor = %p\ |
828 | \n\t\t\tRec Number = %d\ |
829 | \n\t\t\tSQLState = %p\ |
830 | \n\t\t\tNative = %p\ |
831 | \n\t\t\tMessage Text = %p\ |
832 | \n\t\t\tBuffer Length = %d\ |
833 | \n\t\t\tText Len Ptr = %p" , |
834 | descriptor, |
835 | rec_number, |
836 | sqlstate, |
837 | native, |
838 | message_text, |
839 | buffer_length, |
840 | text_length_ptr ); |
841 | |
842 | dm_log_write( __FILE__, |
843 | __LINE__, |
844 | LOG_INFO, |
845 | LOG_INFO, |
846 | descriptor -> msg ); |
847 | } |
848 | |
849 | ret = extract_sql_error_rec( &descriptor -> error, |
850 | sqlstate, |
851 | rec_number, |
852 | native, |
853 | message_text, |
854 | buffer_length, |
855 | text_length_ptr ); |
856 | |
857 | if ( log_info.log_flag ) |
858 | { |
859 | if ( SQL_SUCCEEDED( ret )) |
860 | { |
861 | sprintf( descriptor -> msg, |
862 | "\n\t\tExit:[%s]\ |
863 | \n\t\t\tSQLState = %s\ |
864 | \n\t\t\tNative = %s\ |
865 | \n\t\t\tMessage Text = %s" , |
866 | __get_return_status( ret, s2 ), |
867 | sqlstate ? sqlstate : (SQLCHAR*)"NULL" , |
868 | __iptr_as_string( s0, native ), |
869 | __sdata_as_string( s1, SQL_CHAR, |
870 | text_length_ptr, message_text )); |
871 | } |
872 | else |
873 | { |
874 | sprintf( descriptor -> msg, |
875 | "\n\t\tExit:[%s]" , |
876 | __get_return_status( ret, s1 )); |
877 | } |
878 | |
879 | dm_log_write( __FILE__, |
880 | __LINE__, |
881 | LOG_INFO, |
882 | LOG_INFO, |
883 | descriptor -> msg ); |
884 | } |
885 | |
886 | thread_release( SQL_HANDLE_DESC, descriptor ); |
887 | |
888 | return ret; |
889 | } |
890 | return SQL_NO_DATA; |
891 | } |
892 | |
893 | |