1 /** data source connect object management functions
3 Copyright (C) 1995 by Ke Jin <kejin@empress.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
16 #include <../iodbc/iodbc.h>
18 #include <../iodbc/isql.h>
19 #include <../iodbc/isqlext.h>
21 #include <../iodbc/dlproc.h>
23 #include <../iodbc/herr.h>
24 #include <../iodbc/henv.h>
25 #include <../iodbc/hdbc.h>
26 #include <../iodbc/hstmt.h>
28 #include <../iodbc/itrace.h>
31 extern RETCODE
_iodbcdm_driverunload();
33 RETCODE SQL_API
SQLAllocConnect(
37 GENV_t FAR
* genv
= (GENV_t FAR
*)henv
;
40 #if (ODBCVER >= 0x0300)
41 if( henv
== SQL_NULL_HENV
42 || genv
->type
!= SQL_HANDLE_ENV
)
44 if( henv
== SQL_NULL_HENV
)
47 return SQL_INVALID_HANDLE
;
52 PUSHSQLERR ( genv
->herr
, en_S1009
);
57 pdbc
= (DBC_t FAR
*)MEM_ALLOC (sizeof(DBC_t
));
61 *phdbc
= SQL_NULL_HDBC
;
63 PUSHSQLERR ( genv
->herr
, en_S1001
);
68 #if (ODBCVER >= 0x0300)
69 pdbc
->type
= SQL_HANDLE_DBC
;
71 /* insert this dbc entry into the link list */
72 pdbc
->next
= genv
->hdbc
;
76 pdbc
->henv
= SQL_NULL_HENV
;
77 pdbc
->hstmt
= SQL_NULL_HSTMT
;
78 pdbc
->herr
= SQL_NULL_HERR
;
79 pdbc
->dhdbc
= SQL_NULL_HDBC
;
80 pdbc
->state
= en_dbc_allocated
;
85 /* set connect options to default values */
86 pdbc
->access_mode
= SQL_MODE_DEFAULT
;
87 pdbc
->autocommit
= SQL_AUTOCOMMIT_DEFAULT
;
88 pdbc
->current_qualifier
= NULL
;
89 pdbc
->login_timeout
= 0UL;
90 pdbc
->odbc_cursors
= SQL_CUR_DEFAULT
;
91 pdbc
->packet_size
= 0UL;
92 pdbc
->quiet_mode
= (UDWORD
)NULL
;
93 pdbc
->txn_isolation
= SQL_TXN_READ_UNCOMMITTED
;
94 pdbc
->cb_commit
= (SWORD
)SQL_CB_DELETE
;
95 pdbc
->cb_rollback
= (SWORD
)SQL_CB_DELETE
;
102 RETCODE SQL_API
SQLFreeConnect( HDBC hdbc
)
105 DBC_t FAR
* pdbc
= (DBC_t FAR
*)hdbc
;
108 if( hdbc
== SQL_NULL_HDBC
)
110 return SQL_INVALID_HANDLE
;
114 if( pdbc
->state
!= en_dbc_allocated
)
116 PUSHSQLERR ( pdbc
->herr
, en_S1010
);
121 genv
= (GENV_t FAR
*)pdbc
->genv
;
123 for( tpdbc
= (DBC_t FAR
*)genv
->hdbc
;
125 tpdbc
= tpdbc
->next
)
129 genv
->hdbc
= pdbc
->next
;
133 if( pdbc
== tpdbc
->next
)
135 tpdbc
->next
= pdbc
->next
;
141 _iodbcdm_driverunload(pdbc
);
142 _iodbcdm_freesqlerrlist( pdbc
->herr
);
146 MEM_FREE( pdbc
->tfile
);
149 SQLSetConnectOption( pdbc
, SQL_OPT_TRACE
, SQL_OPT_TRACE_OFF
);
156 RETCODE SQL_API
SQLSetConnectOption(
161 /* GENV_t FAR* genv; */
162 DBC_t FAR
* pdbc
= (DBC_t FAR
*)hdbc
;
164 HPROC hproc
= SQL_NULL_HPROC
;
165 int sqlstat
= en_00000
;
166 RETCODE retcode
= SQL_SUCCESS
;
168 if( hdbc
== SQL_NULL_HDBC
)
170 return SQL_INVALID_HANDLE
;
174 if( fOption
< SQL_CONN_OPT_MIN
175 || ( fOption
> SQL_CONN_OPT_MAX
176 && fOption
< SQL_CONNECT_OPT_DRVR_START
) )
178 PUSHSQLERR ( pdbc
->herr
, en_S1092
);
183 /* check state of connection handle */
184 switch( pdbc
->state
)
186 case en_dbc_allocated
:
187 if( fOption
== SQL_TRANSLATE_DLL
188 || fOption
== SQL_TRANSLATE_OPTION
)
190 /* This two options are only meaningful
191 * for specified driver. So, has to be
192 * set after a dirver has been loaded.
198 if( fOption
>= SQL_CONNECT_OPT_DRVR_START
199 && pdbc
->henv
== SQL_NULL_HENV
)
200 /* An option only meaningful for drivers
201 * is passed before loading a driver.
202 * We classify this as an invalid option error.
203 * This is not documented by MS SDK guide.
211 case en_dbc_needdata
:
215 case en_dbc_connected
:
217 if( fOption
== SQL_ODBC_CURSORS
)
227 /* check state of statement handle(s) */
228 for( pstmt
= (STMT_t FAR
*)pdbc
->hstmt
;
229 pstmt
!= NULL
&& sqlstat
== en_00000
;
230 pstmt
= (STMT_t FAR
*)pstmt
->next
)
232 if( pstmt
->state
>= en_stmt_needdata
233 || pstmt
->asyn_on
!= en_NullProc
)
239 if( sqlstat
!= en_00000
)
241 PUSHSQLERR ( pdbc
->herr
, sqlstat
);
246 if( fOption
== SQL_OPT_TRACE
)
247 /* tracing flag can be set before and after connect
248 * and only meaningful for driver manager(actually
249 * there is only one tracing file under one global
255 case SQL_OPT_TRACE_ON
:
256 if( pdbc
->tfile
== NULL
)
258 pdbc
->tfile
= (char FAR
*)MEM_ALLOC( 1 +
259 STRLEN(SQL_OPT_TRACE_FILE_DEFAULT
) );
261 if( pdbc
->tfile
== NULL
)
263 PUSHSQLERR( pdbc
->herr
, en_S1001
);
268 STRCPY( pdbc
->tfile
, SQL_OPT_TRACE_FILE_DEFAULT
);
271 if( pdbc
->tstm
== NULL
)
273 #if defined(stderr) && defined(stdout)
274 if(STREQ( pdbc
->tfile
, "stderr"))
279 if(STREQ(pdbc
->tfile
, "stdout"))
287 = fopen(pdbc
->tfile
, "a+");
304 case SQL_OPT_TRACE_OFF
:
305 if( pdbc
->trace
&& pdbc
->tstm
)
307 #if defined(stderr) && defined(stdout)
308 if( stderr
!= (FILE FAR
*)(pdbc
->tstm
)
309 && stdout
!= (FILE FAR
*)(pdbc
->tstm
) )
320 PUSHSQLERR (pdbc
->herr
, en_S1009
);
324 if( sqlstat
!= en_00000
)
326 PUSHSQLERR ( pdbc
->herr
, sqlstat
);
332 if( fOption
== SQL_OPT_TRACEFILE
)
333 /* Tracing file can be set before and after connect
334 * and only meaningful for driver manager.
338 || ((char FAR
*)vParam
)[0] == 0 )
340 PUSHSQLERR ( pdbc
->herr
, en_S1009
);
345 if( pdbc
->tfile
&& STREQ (pdbc
->tfile
, vParam
) )
352 PUSHSQLERR ( pdbc
->herr
, en_IM014
);
359 MEM_FREE( pdbc
->tfile
);
362 pdbc
->tfile
= (char FAR
*)MEM_ALLOC( 1 + STRLEN( vParam
) );
364 if( pdbc
->tfile
== NULL
)
366 PUSHSQLERR( pdbc
->herr
, en_S1001
);
371 STRCPY ( pdbc
->tfile
, vParam
);
376 if( pdbc
->state
!= en_dbc_allocated
)
378 /* If already connected, then, driver's odbc call
379 * will be invoked. Otherwise, we only save the options
380 * and delay the setting process until the connection
383 hproc
= _iodbcdm_getproc( hdbc
, en_SetConnectOption
);
385 if( hproc
== SQL_NULL_HPROC
)
387 PUSHSQLERR ( pdbc
->herr
, en_IM001
);
392 CALL_DRIVER ( hdbc
, retcode
, hproc
, en_SetConnectOption
, (
393 pdbc
->dhdbc
, fOption
, vParam
) )
396 retcode
= hproc( pdbc
->dhdbc
, fOption
, vParam
);
399 if( retcode
!= SQL_SUCCESS
400 && retcode
!= SQL_SUCCESS_WITH_INFO
)
407 * Now, either driver's odbc call was successed or
408 * driver has not been loaded yet. In the first case, we
409 * need flip flag for(such as access_mode, autocommit, ...)
410 * for our finit state machine. While in the second case,
411 * we need save option values(such as current_qualifier, ...)
412 * for delaied setting. So, ...
415 /* No matter what state we are(i.e. allocated or connected, ..)
416 * we need to flip the flag.
420 case SQL_ACCESS_MODE
:
421 pdbc
->access_mode
= vParam
;
425 pdbc
->autocommit
= vParam
;
429 /* state transition */
430 if( pdbc
->state
!= en_dbc_allocated
)
435 /* Only 'allocated' state is possible here, and we need to
436 * save the options for delaied setting.
440 case SQL_CURRENT_QUALIFIER
:
441 if( pdbc
->current_qualifier
!= NULL
)
443 MEM_FREE ( pdbc
->current_qualifier
);
448 pdbc
->current_qualifier
= NULL
;
453 pdbc
->current_qualifier
454 = (char FAR
*)MEM_ALLOC (
455 STRLEN (vParam
) + 1 );
457 if( pdbc
->current_qualifier
== NULL
)
459 PUSHSQLERR ( pdbc
->herr
, en_S1001
);
463 STRCPY ( pdbc
->current_qualifier
, vParam
);
466 case SQL_LOGIN_TIMEOUT
:
467 pdbc
->login_timeout
= vParam
;
470 case SQL_ODBC_CURSORS
:
471 pdbc
->odbc_cursors
= vParam
;
474 case SQL_PACKET_SIZE
:
475 pdbc
->packet_size
= vParam
;
479 pdbc
->quiet_mode
= vParam
;
482 case SQL_TXN_ISOLATION
:
483 pdbc
->txn_isolation
= vParam
;
487 /* Since we didn't save the option value for delaied
488 * setting, we should raise an error here.
496 RETCODE SQL_API
SQLGetConnectOption(
501 /* GENV_t FAR* genv; */
502 DBC_t FAR
* pdbc
= (DBC_t FAR
*)hdbc
;
503 int sqlstat
= en_00000
;
504 HPROC hproc
= SQL_NULL_HPROC
;
507 if( hdbc
== SQL_NULL_HDBC
)
509 return SQL_INVALID_HANDLE
;
513 if( fOption
< SQL_CONN_OPT_MIN
514 || ( fOption
> SQL_CONN_OPT_MAX
515 && fOption
< SQL_CONNECT_OPT_DRVR_START
) )
517 PUSHSQLERR ( pdbc
->herr
, en_S1092
);
523 switch( pdbc
->state
)
525 case en_dbc_allocated
:
526 if( fOption
!= SQL_ACCESS_MODE
527 && fOption
!= SQL_AUTOCOMMIT
528 && fOption
!= SQL_LOGIN_TIMEOUT
529 && fOption
!= SQL_OPT_TRACE
530 && fOption
!= SQL_OPT_TRACEFILE
)
534 /* MS ODBC SDK document only
535 * allows SQL_ACCESS_MODE
536 * and SQL_AUTOCOMMIT in this
537 * dbc state. We allow another
538 * two options, because they
539 * are only meaningful for driver
544 case en_dbc_needdata
:
552 if( sqlstat
!= en_00000
)
554 PUSHSQLERR ( pdbc
->herr
, sqlstat
);
559 /* Tracing and tracing file options are only
560 * meaningful for driver manager
562 if( fOption
== SQL_OPT_TRACE
)
565 *((UDWORD
*)pvParam
) = (UDWORD
)SQL_OPT_TRACE_ON
;
567 *((UDWORD
*)pvParam
) = (UDWORD
)SQL_OPT_TRACE_OFF
;
572 if( fOption
== SQL_OPT_TRACEFILE
)
574 STRCPY (pvParam
, pdbc
->tfile
);
579 if( pdbc
->state
!= en_dbc_allocated
)
580 /* if already connected, we will invoke driver's function */
582 hproc
= _iodbcdm_getproc( hdbc
, en_GetConnectOption
);
584 if( hproc
== SQL_NULL_HPROC
)
586 PUSHSQLERR( pdbc
->herr
, en_IM001
);
591 CALL_DRIVER ( hdbc
, retcode
, hproc
, en_GetConnectOption
, (
592 pdbc
->dhdbc
, fOption
, pvParam
) )
595 retcode
= hproc(pdbc
->dhdbc
, fOption
, pvParam
);
601 /* We needn't to handle options which are not allowed
602 * to be *get* at a allocated dbc state(and two tracing
603 * options which has been handled and returned). Thus,
604 * there are only two possible cases.
608 case SQL_ACCESS_MODE
:
609 *((UDWORD
*)pvParam
) = pdbc
->access_mode
;
613 *((UDWORD
*)pvParam
) = pdbc
->autocommit
;
616 case SQL_LOGIN_TIMEOUT
:
617 *((UDWORD
*)pvParam
) = pdbc
->login_timeout
;
627 static RETCODE
_iodbcdm_transact(
631 DBC_t FAR
* pdbc
= (DBC_t FAR
*)hdbc
;
637 switch( pdbc
->state
)
639 case en_dbc_allocated
:
640 case en_dbc_needdata
:
641 PUSHSQLERR ( pdbc
->herr
, en_08003
);
644 case en_dbc_connected
:
652 for( pstmt
= (STMT_t FAR
*)(pdbc
->hstmt
);
654 pstmt
= pstmt
->next
)
656 if( pstmt
->state
>= en_stmt_needdata
657 || pstmt
->asyn_on
!= en_NullProc
)
659 PUSHSQLERR ( pdbc
->herr
, en_S1010
);
665 hproc
= _iodbcdm_getproc( hdbc
, en_Transact
);
667 if( hproc
== SQL_NULL_HPROC
)
669 PUSHSQLERR ( pdbc
->herr
, en_IM001
);
674 CALL_DRIVER ( hdbc
, retcode
, hproc
, en_Transact
, (
675 SQL_NULL_HENV
, pdbc
->dhdbc
, fType
) )
678 retcode
= hproc( SQL_NULL_HENV
, pdbc
->dhdbc
, fType
);
681 /* state transition */
682 if( retcode
!= SQL_SUCCESS
683 && retcode
!= SQL_SUCCESS_WITH_INFO
)
688 pdbc
->state
= en_dbc_hstmt
;
690 for( pstmt
= (STMT_t FAR
*)(pdbc
->hstmt
);
692 pstmt
= pstmt
->next
)
694 switch( pstmt
->state
)
696 case en_stmt_prepared
:
697 if( pdbc
->cb_commit
== SQL_CB_DELETE
698 || pdbc
->cb_rollback
== SQL_CB_DELETE
)
700 pstmt
->state
= en_stmt_allocated
;
701 pstmt
->prep_state
= 0;
706 case en_stmt_executed
:
707 case en_stmt_cursoropen
:
708 case en_stmt_fetched
:
709 case en_stmt_xfetched
:
710 if( ! pstmt
->prep_state
711 && pdbc
->cb_commit
!= SQL_CB_PRESERVE
712 && pdbc
->cb_rollback
!= SQL_CB_PRESERVE
)
714 pstmt
->state
= en_stmt_allocated
;
715 pstmt
->prep_state
= 0;
716 pstmt
->cursor_state
= en_stmt_cursor_no
;
720 if( pstmt
->prep_state
)
722 if( pdbc
->cb_commit
== SQL_CB_DELETE
723 || pdbc
->cb_rollback
== SQL_CB_DELETE
)
725 pstmt
->state
= en_stmt_allocated
;
726 pstmt
->prep_state
= 0;
727 pstmt
->cursor_state
= en_stmt_cursor_no
;
731 if( pdbc
->cb_commit
== SQL_CB_CLOSE
732 || pdbc
->cb_rollback
== SQL_CB_CLOSE
)
752 RETCODE SQL_API
SQLTransact(
757 GENV_t FAR
* genv
= (GENV_t FAR
*)henv
;
758 DBC_t FAR
* pdbc
= (DBC_t FAR
*)hdbc
;
762 if( hdbc
!= SQL_NULL_HDBC
)
766 else if( henv
!= SQL_NULL_HENV
)
772 return SQL_INVALID_HANDLE
;
776 if( fType
!= SQL_COMMIT
777 && fType
!= SQL_ROLLBACK
)
779 PUSHSQLERR ( herr
, en_S1012
);
784 if( hdbc
!= SQL_NULL_HDBC
)
786 retcode
= _iodbcdm_transact( hdbc
, fType
);
790 for( pdbc
= (DBC_t FAR
*)(genv
->hdbc
);
794 retcode
|= _iodbcdm_transact( hdbc
, fType
);
798 if( retcode
!= SQL_SUCCESS
799 && retcode
!= SQL_SUCCESS_WITH_INFO
)
801 /* fail on one of the connection */