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: SQLFreeHandle.c,v 1.12 2009/02/18 17:59:08 lurcher Exp $
31 *
32 * $Log: SQLFreeHandle.c,v $
33 * Revision 1.12 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.11 2009/02/17 09:47:44 lurcher
37 * Clear up a number of bugs
38 *
39 * Revision 1.10 2007/12/17 13:13:03 lurcher
40 * Fix a couple of descriptor typo's
41 *
42 * Revision 1.9 2007/01/02 10:27:50 lurcher
43 * Fix descriptor leak with unicode only driver
44 *
45 * Revision 1.8 2006/04/18 10:24:47 lurcher
46 * Add a couple of changes from Mark Vanderwiel
47 *
48 * Revision 1.7 2003/10/30 18:20:45 lurcher
49 *
50 * Fix broken thread protection
51 * Remove SQLNumResultCols after execute, lease S4/S% to driver
52 * Fix string overrun in SQLDriverConnect
53 * Add initial support for Interix
54 *
55 * Revision 1.6 2003/05/14 09:42:25 lurcher
56 *
57 * Fix bug in stats collection
58 *
59 * Revision 1.5 2003/04/09 08:42:18 lurcher
60 *
61 * Allow setting of odbcinstQ lib from odbcinst.ini and Environment
62 *
63 * Revision 1.4 2002/09/18 14:49:32 lurcher
64 *
65 * DataManagerII additions and some more threading fixes
66 *
67 * Revision 1.1.1.1 2001/10/17 16:40:05 lurcher
68 *
69 * First upload to SourceForge
70 *
71 * Revision 1.7 2001/08/08 17:05:17 nick
72 *
73 * Add support for attribute setting in the ini files
74 *
75 * Revision 1.6 2001/06/04 15:24:49 nick
76 *
77 * Add port to MAC OSX and QT3 changes
78 *
79 * Revision 1.5 2001/05/15 13:33:44 jason
80 *
81 * Wrapped calls to stats with COLLECT_STATS
82 *
83 * Revision 1.4 2001/04/12 17:43:36 nick
84 *
85 * Change logging and added autotest to odbctest
86 *
87 * Revision 1.3 2000/12/19 10:28:29 martin
88 *
89 * Return "not built with stats" in uodbc_error() if stats function called
90 * when stats not built.
91 * Add uodbc_update_stats() calls to SQLFreeHandle.
92 *
93 * Revision 1.2 2000/11/23 09:43:29 nick
94 *
95 * Fix deadlock posibility
96 *
97 * Revision 1.1.1.1 2000/09/04 16:42:52 nick
98 * Imported Sources
99 *
100 * Revision 1.12 2000/06/27 17:34:10 ngorham
101 *
102 * Fix a problem when the second part of the connect failed a seg fault
103 * was generated in the error reporting
104 *
105 * Revision 1.11 2000/05/21 21:49:19 ngorham
106 *
107 * Assorted fixes
108 *
109 * Revision 1.10 1999/11/17 21:11:59 ngorham
110 *
111 * Fix bug where the check for a valid handle was after the code had
112 * used it.
113 *
114 * Revision 1.9 1999/11/13 23:40:59 ngorham
115 *
116 * Alter the way DM logging works
117 * Upgrade the Postgres driver to 6.4.6
118 *
119 * Revision 1.8 1999/10/24 23:54:18 ngorham
120 *
121 * First part of the changes to the error reporting
122 *
123 * Revision 1.7 1999/10/09 00:15:58 ngorham
124 *
125 * Add mapping from SQL_TYPE_X to SQL_X and SQL_C_TYPE_X to SQL_C_X
126 * when the driver is a ODBC 2 one
127 *
128 * Revision 1.6 1999/09/21 22:34:24 ngorham
129 *
130 * Improve performance by removing unneeded logging calls when logging is
131 * disabled
132 *
133 * Revision 1.5 1999/08/03 21:47:39 shandyb
134 * Moving to automake: changed files in DriverManager
135 *
136 * Revision 1.4 1999/07/10 21:10:16 ngorham
137 *
138 * Adjust error sqlstate from driver manager, depending on requested
139 * version (ODBC2/3)
140 *
141 * Revision 1.3 1999/07/04 21:05:07 ngorham
142 *
143 * Add LGPL Headers to code
144 *
145 * Revision 1.2 1999/06/30 23:56:55 ngorham
146 *
147 * Add initial thread safety code
148 *
149 * Revision 1.1.1.1 1999/05/29 13:41:07 sShandyb
150 * first go at it
151 *
152 * Revision 1.2 1999/06/07 01:29:31 pharvey
153 * *** empty log message ***
154 *
155 * Revision 1.1.1.1 1999/05/27 18:23:17 pharvey
156 * Imported sources
157 *
158 * Revision 1.5 1999/05/09 23:27:11 nick
159 * All the API done now
160 *
161 * Revision 1.4 1999/05/03 19:50:43 nick
162 * Another check point
163 *
164 * Revision 1.3 1999/04/30 16:22:47 nick
165 * Another checkpoint
166 *
167 * Revision 1.2 1999/04/29 20:47:37 nick
168 * Another checkpoint
169 *
170 * Revision 1.1 1999/04/25 23:06:11 nick
171 * Initial revision
172 *
173 *
174 **********************************************************************/
175
176#include <config.h>
177#include "drivermanager.h"
178#if defined ( COLLECT_STATS ) && defined( HAVE_SYS_SEM_H )
179#include "__stats.h"
180#include <uodbc_stats.h>
181#endif
182
183static char const rcsid[]= "$RCSfile: SQLFreeHandle.c,v $ $Revision: 1.12 $";
184
185SQLRETURN __SQLFreeHandle( SQLSMALLINT handle_type,
186 SQLHANDLE handle )
187{
188 switch( handle_type )
189 {
190 case SQL_HANDLE_ENV:
191 case SQL_HANDLE_SENV:
192 {
193 DMHENV environment = (DMHENV)handle;
194
195 /*
196 * check environment
197 */
198
199 if ( !__validate_env( environment ))
200 {
201 dm_log_write( __FILE__,
202 __LINE__,
203 LOG_INFO,
204 LOG_INFO,
205 "Error: SQL_INVALID_HANDLE" );
206
207 return SQL_INVALID_HANDLE;
208 }
209
210 function_entry( environment );
211
212 if ( log_info.log_flag )
213 {
214 sprintf( environment -> msg,
215 "\n\t\tEntry:\n\t\t\tHandle Type = %d\n\t\t\tInput Handle = %p",
216 handle_type,
217 (void*)handle );
218
219 dm_log_write( __FILE__,
220 __LINE__,
221 LOG_INFO,
222 LOG_INFO,
223 environment -> msg );
224 }
225
226 thread_protect( SQL_HANDLE_ENV, environment );
227
228 /*
229 * check states
230 */
231 if ( environment -> state != STATE_E1 )
232 {
233 dm_log_write( __FILE__,
234 __LINE__,
235 LOG_INFO,
236 LOG_INFO,
237 "Error: HY010" );
238
239 __post_internal_error( &environment -> error,
240 ERROR_HY010, NULL,
241 environment -> requested_version );
242
243 return function_return_nodrv( SQL_HANDLE_ENV, environment, SQL_ERROR );
244 }
245
246 thread_release( SQL_HANDLE_ENV, environment );
247
248 /*
249 * release any pooled connections that are using this environment
250 */
251 __strip_from_pool( environment );
252
253 __release_env( environment );
254 return SQL_SUCCESS;
255 }
256 break;
257
258 case SQL_HANDLE_DBC:
259 {
260 DMHDBC connection = (DMHDBC)handle;
261 DMHENV environment;
262
263 /*
264 * check connection
265 */
266
267 if ( !__validate_dbc( connection ))
268 {
269 dm_log_write( __FILE__,
270 __LINE__,
271 LOG_INFO,
272 LOG_INFO,
273 "Error: SQL_INVALID_HANDLE" );
274
275 return SQL_INVALID_HANDLE;
276 }
277
278 function_entry( connection );
279
280 environment = connection -> environment;
281
282 if ( log_info.log_flag )
283 {
284 sprintf( connection -> msg,
285 "\n\t\tEntry:\n\t\t\tHandle Type = %d\n\t\t\tInput Handle = %p",
286 handle_type,
287 (void*)handle );
288
289 dm_log_write( __FILE__,
290 __LINE__,
291 LOG_INFO,
292 LOG_INFO,
293 connection -> msg );
294 }
295
296 thread_protect( SQL_HANDLE_ENV, environment );
297
298 /*
299 * check states
300 */
301 if ( connection -> state != STATE_C2 )
302 {
303 dm_log_write( __FILE__,
304 __LINE__,
305 LOG_INFO,
306 LOG_INFO,
307 "Error: HY010" );
308
309 __post_internal_error( &connection -> error,
310 ERROR_HY010, NULL,
311 connection -> environment -> requested_version );
312
313 return function_return_nodrv( SQL_HANDLE_ENV, environment, SQL_ERROR );
314 }
315
316 environment -> connection_count --;
317
318 if ( environment -> connection_count == 0 )
319 {
320 environment -> state = STATE_E1;
321 }
322
323 environment = connection -> environment;
324
325 __release_attr_str( &connection -> env_attribute );
326 __release_attr_str( &connection -> dbc_attribute );
327 __release_attr_str( &connection -> stmt_attribute );
328
329 __disconnect_part_one( connection );
330
331 __release_dbc( connection );
332
333 if ( log_info.log_flag )
334 {
335 sprintf( environment -> msg,
336 "\n\t\tExit:[SQL_SUCCESS]" );
337
338 dm_log_write( __FILE__,
339 __LINE__,
340 LOG_INFO,
341 LOG_INFO,
342 environment -> msg );
343 }
344#if defined ( COLLECT_STATS ) && defined( HAVE_SYS_SEM_H )
345 uodbc_update_stats(environment->sh, UODBC_STATS_TYPE_HDBC,
346 (void *)-1);
347#endif
348
349 thread_release( SQL_HANDLE_ENV, environment );
350
351 return SQL_SUCCESS;
352 }
353 break;
354
355 case SQL_HANDLE_STMT:
356 {
357 DMHSTMT statement = (DMHSTMT)handle;
358 DMHDBC connection;
359 SQLRETURN ret;
360
361 /*
362 * check statement
363 */
364 if ( !__validate_stmt( statement ))
365 {
366 dm_log_write( __FILE__,
367 __LINE__,
368 LOG_INFO,
369 LOG_INFO,
370 "Error: SQL_INVALID_HANDLE" );
371
372 return SQL_INVALID_HANDLE;
373 }
374
375 function_entry( statement );
376
377 connection = statement -> connection;
378
379 if ( log_info.log_flag )
380 {
381 sprintf( statement -> msg,
382 "\n\t\tEntry:\n\t\t\tHandle Type = %d\n\t\t\tInput Handle = %p",
383 handle_type,
384 (void*)handle );
385
386 dm_log_write( __FILE__,
387 __LINE__,
388 LOG_INFO,
389 LOG_INFO,
390 statement -> msg );
391 }
392
393 thread_protect( SQL_HANDLE_STMT, statement );
394
395 /*
396 * check states
397 */
398 if ( statement -> state == STATE_S8 ||
399 statement -> state == STATE_S9 ||
400 statement -> state == STATE_S10 ||
401 statement -> state == STATE_S11 ||
402 statement -> state == STATE_S12 ||
403 statement -> state == STATE_S13 ||
404 statement -> state == STATE_S14 ||
405 statement -> state == STATE_S15 )
406 {
407 dm_log_write( __FILE__,
408 __LINE__,
409 LOG_INFO,
410 LOG_INFO,
411 "Error: HY010" );
412
413 __post_internal_error( &statement -> error,
414 ERROR_HY010, NULL,
415 statement -> connection -> environment -> requested_version );
416
417 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
418 }
419
420 if ( !CHECK_SQLFREEHANDLE( statement -> connection ))
421 {
422 if ( !CHECK_SQLFREESTMT( statement -> connection ))
423 {
424 dm_log_write( __FILE__,
425 __LINE__,
426 LOG_INFO,
427 LOG_INFO,
428 "Error: IM001" );
429
430 __post_internal_error( &statement -> error,
431 ERROR_IM001, NULL,
432 statement -> connection -> environment -> requested_version );
433
434 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
435 }
436 else
437 {
438 ret = SQLFREESTMT( statement -> connection,
439 statement -> driver_stmt,
440 SQL_DROP );
441 }
442 }
443 else
444 {
445 ret = SQLFREEHANDLE( statement -> connection,
446 handle_type,
447 statement -> driver_stmt );
448 }
449
450 if ( SQL_SUCCEEDED( ret ))
451 {
452 /*
453 * release the implicit descriptors,
454 * this matches the tests in SQLAllocHandle
455 */
456 if (( statement -> connection -> driver_act_ver == 3 &&
457 CHECK_SQLGETSTMTATTR( connection )) ||
458 CHECK_SQLGETSTMTATTRW( connection ))
459 {
460 if ( statement -> implicit_ard )
461 __release_desc( statement -> implicit_ard );
462 if ( statement -> implicit_apd )
463 __release_desc( statement -> implicit_apd );
464 if ( statement -> implicit_ird )
465 __release_desc( statement -> implicit_ird );
466 if ( statement -> implicit_ipd )
467 __release_desc( statement -> implicit_ipd );
468 }
469 statement -> connection -> statement_count --;
470
471 thread_release( SQL_HANDLE_STMT, statement );
472#if defined ( COLLECT_STATS ) && defined( HAVE_SYS_SEM_H )
473 uodbc_update_stats(connection->environment->sh,
474 UODBC_STATS_TYPE_HSTMT, (void *)-1);
475#endif
476
477 __release_stmt( statement );
478 }
479 else
480 {
481 thread_release( SQL_HANDLE_STMT, statement );
482 }
483
484 if ( log_info.log_flag )
485 {
486 sprintf( connection -> msg,
487 "\n\t\tExit:[SQL_SUCCESS]" );
488
489 dm_log_write( __FILE__,
490 __LINE__,
491 LOG_INFO,
492 LOG_INFO,
493 connection -> msg );
494 }
495
496 return function_return( IGNORE_THREAD, connection, ret );
497 }
498 break;
499
500 case SQL_HANDLE_DESC:
501 {
502 DMHDESC descriptor = (DMHDESC)handle;
503 DMHDBC connection;
504 SQLRETURN ret;
505
506 /*
507 * check descriptor
508 */
509 if ( !__validate_desc( descriptor ))
510 {
511 return SQL_INVALID_HANDLE;
512 }
513
514 function_entry( descriptor );
515
516 connection = descriptor -> connection;
517
518 if ( log_info.log_flag )
519 {
520 sprintf( descriptor -> msg,
521 "\n\t\tEntry:\n\t\t\tHandle Type = %d\n\t\t\tInput Handle = %p",
522 handle_type,
523 (void*)handle );
524
525 dm_log_write( __FILE__,
526 __LINE__,
527 LOG_INFO,
528 LOG_INFO,
529 descriptor -> msg );
530 }
531
532 if ( descriptor -> implicit )
533 {
534 dm_log_write( __FILE__,
535 __LINE__,
536 LOG_INFO,
537 LOG_INFO,
538 "Error: HY017" );
539
540 __post_internal_error( &descriptor -> error,
541 ERROR_HY017, NULL,
542 connection -> environment -> requested_version );
543
544 return function_return_nodrv( IGNORE_THREAD, descriptor, SQL_ERROR );
545 }
546
547 thread_protect( SQL_HANDLE_DESC, descriptor );
548
549 if ( !CHECK_SQLFREEHANDLE( connection ))
550 {
551 dm_log_write( __FILE__,
552 __LINE__,
553 LOG_INFO,
554 LOG_INFO,
555 "Error: IM001" );
556
557 __post_internal_error( &descriptor -> error,
558 ERROR_IM001, NULL,
559 connection -> environment -> requested_version );
560
561 return function_return_nodrv( SQL_HANDLE_DESC, descriptor, SQL_ERROR );
562 }
563 else
564 {
565 ret = SQLFREEHANDLE( connection,
566 handle_type,
567 descriptor -> driver_desc );
568 }
569
570 /*
571 * check status of statements associated with this descriptor
572 */
573
574 if( __check_stmt_from_desc( descriptor, STATE_S8 ) ||
575 __check_stmt_from_desc( descriptor, STATE_S9 ) ||
576 __check_stmt_from_desc( descriptor, STATE_S10 ) ||
577 __check_stmt_from_desc( descriptor, STATE_S11 ) ||
578 __check_stmt_from_desc( descriptor, STATE_S12 )) {
579
580 dm_log_write( __FILE__,
581 __LINE__,
582 LOG_INFO,
583 LOG_INFO,
584 "Error: HY010" );
585
586 __post_internal_error( &descriptor -> error,
587 ERROR_HY010, NULL,
588 descriptor -> connection -> environment -> requested_version );
589
590 return function_return( SQL_HANDLE_DESC, descriptor, SQL_ERROR );
591 }
592
593 thread_release( SQL_HANDLE_DESC, descriptor );
594
595 __release_desc( descriptor );
596
597 if ( log_info.log_flag )
598 {
599 sprintf( connection -> msg,
600 "\n\t\tExit:[SQL_SUCCESS]" );
601
602 dm_log_write( __FILE__,
603 __LINE__,
604 LOG_INFO,
605 LOG_INFO,
606 connection -> msg );
607 }
608#if defined ( COLLECT_STATS ) && defined( HAVE_SYS_SEM_H )
609 uodbc_update_stats(connection->environment->sh,
610 UODBC_STATS_TYPE_HDESC, (void *)-1);
611#endif
612
613 return function_return( IGNORE_THREAD, connection, SQL_SUCCESS );
614 }
615 break;
616
617 default:
618 /*
619 * there is nothing to report a error on
620 */
621 return SQL_INVALID_HANDLE;
622 }
623}
624
625SQLRETURN SQLFreeHandle( SQLSMALLINT handle_type,
626 SQLHANDLE handle )
627{
628 return __SQLFreeHandle( handle_type,
629 handle );
630}
631
632