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
186static char const rcsid[]= "$RCSfile: SQLGetDiagRec.c,v $ $Revision: 1.21 $";
187
188int __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
197DMHDBC __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
229int __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
269DRV_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
301static SQLRETURN extract_sql_error_rec( 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
535SQLRETURN 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
554SQLRETURN 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