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 RETCODE SQL_API
SQLAllocConnect(
35 GENV_t FAR
* genv
= (GENV_t FAR
*)henv
;
38 #if (ODBCVER >= 0x0300)
39 if( henv
== SQL_NULL_HENV
40 || genv
->type
!= SQL_HANDLE_ENV
)
42 if( henv
== SQL_NULL_HENV
)
45 return SQL_INVALID_HANDLE
;
50 PUSHSQLERR ( genv
->herr
, en_S1009
);
55 pdbc
= (DBC_t FAR
*)MEM_ALLOC (sizeof(DBC_t
));
59 *phdbc
= SQL_NULL_HDBC
;
61 PUSHSQLERR ( genv
->herr
, en_S1001
);
66 #if (ODBCVER >= 0x0300)
67 pdbc
->type
= SQL_HANDLE_DBC
;
69 /* insert this dbc entry into the link list */
70 pdbc
->next
= genv
->hdbc
;
74 pdbc
->henv
= SQL_NULL_HENV
;
75 pdbc
->hstmt
= SQL_NULL_HSTMT
;
76 pdbc
->herr
= SQL_NULL_HERR
;
77 pdbc
->dhdbc
= SQL_NULL_HDBC
;
78 pdbc
->state
= en_dbc_allocated
;
83 /* set connect options to default values */
84 pdbc
->access_mode
= SQL_MODE_DEFAULT
;
85 pdbc
->autocommit
= SQL_AUTOCOMMIT_DEFAULT
;
86 pdbc
->current_qualifier
= NULL
;
87 pdbc
->login_timeout
= 0UL;
88 pdbc
->odbc_cursors
= SQL_CUR_DEFAULT
;
89 pdbc
->packet_size
= 0UL;
90 pdbc
->quiet_mode
= (UDWORD
)NULL
;
91 pdbc
->txn_isolation
= SQL_TXN_READ_UNCOMMITTED
;
92 pdbc
->cb_commit
= (SWORD
)SQL_CB_DELETE
;
93 pdbc
->cb_rollback
= (SWORD
)SQL_CB_DELETE
;
100 RETCODE SQL_API
SQLFreeConnect( HDBC hdbc
)
103 DBC_t FAR
* pdbc
= (DBC_t FAR
*)hdbc
;
106 if( hdbc
== SQL_NULL_HDBC
)
108 return SQL_INVALID_HANDLE
;
112 if( pdbc
->state
!= en_dbc_allocated
)
114 PUSHSQLERR ( pdbc
->herr
, en_S1010
);
119 genv
= (GENV_t FAR
*)pdbc
->genv
;
121 for( tpdbc
= (DBC_t FAR
*)genv
->hdbc
;
123 tpdbc
= tpdbc
->next
)
127 genv
->hdbc
= pdbc
->next
;
131 if( pdbc
== tpdbc
->next
)
133 tpdbc
->next
= pdbc
->next
;
139 _iodbcdm_driverunload(pdbc
);
140 _iodbcdm_freesqlerrlist( pdbc
->herr
);
144 MEM_FREE( pdbc
->tfile
);
147 SQLSetConnectOption( pdbc
, SQL_OPT_TRACE
, SQL_OPT_TRACE_OFF
);
154 RETCODE SQL_API
SQLSetConnectOption(
160 DBC_t FAR
* pdbc
= (DBC_t FAR
*)hdbc
;
162 HPROC hproc
= SQL_NULL_HPROC
;
163 int sqlstat
= en_00000
;
164 RETCODE retcode
= SQL_SUCCESS
;
166 if( hdbc
== SQL_NULL_HDBC
)
168 return SQL_INVALID_HANDLE
;
172 if( fOption
< SQL_CONN_OPT_MIN
173 || ( fOption
> SQL_CONN_OPT_MAX
174 && fOption
< SQL_CONNECT_OPT_DRVR_START
) )
176 PUSHSQLERR ( pdbc
->herr
, en_S1092
);
181 /* check state of connection handle */
182 switch( pdbc
->state
)
184 case en_dbc_allocated
:
185 if( fOption
== SQL_TRANSLATE_DLL
186 || fOption
== SQL_TRANSLATE_OPTION
)
188 /* This two options are only meaningful
189 * for specified driver. So, has to be
190 * set after a dirver has been loaded.
196 if( fOption
>= SQL_CONNECT_OPT_DRVR_START
197 && pdbc
->henv
== SQL_NULL_HENV
)
198 /* An option only meaningful for drivers
199 * is passed before loading a driver.
200 * We classify this as an invalid option error.
201 * This is not documented by MS SDK guide.
209 case en_dbc_needdata
:
213 case en_dbc_connected
:
215 if( fOption
== SQL_ODBC_CURSORS
)
225 /* check state of statement handle(s) */
226 for( pstmt
= (STMT_t FAR
*)pdbc
->hstmt
;
227 pstmt
!= NULL
&& sqlstat
== en_00000
;
228 pstmt
= (STMT_t FAR
*)pstmt
->next
)
230 if( pstmt
->state
>= en_stmt_needdata
231 || pstmt
->asyn_on
!= en_NullProc
)
237 if( sqlstat
!= en_00000
)
239 PUSHSQLERR ( pdbc
->herr
, sqlstat
);
244 if( fOption
== SQL_OPT_TRACE
)
245 /* tracing flag can be set before and after connect
246 * and only meaningful for driver manager(actually
247 * there is only one tracing file under one global
253 case SQL_OPT_TRACE_ON
:
254 if( pdbc
->tfile
== NULL
)
256 pdbc
->tfile
= (char FAR
*)MEM_ALLOC( 1 +
257 STRLEN(SQL_OPT_TRACE_FILE_DEFAULT
) );
259 if( pdbc
->tfile
== NULL
)
261 PUSHSQLERR( pdbc
->herr
, en_S1001
);
266 STRCPY( pdbc
->tfile
, SQL_OPT_TRACE_FILE_DEFAULT
);
269 if( pdbc
->tstm
== NULL
)
271 #if defined(stderr) && defined(stdout)
272 if(STREQ( pdbc
->tfile
, "stderr"))
277 if(STREQ(pdbc
->tfile
, "stdout"))
285 = fopen(pdbc
->tfile
, "a+");
302 case SQL_OPT_TRACE_OFF
:
303 if( pdbc
->trace
&& pdbc
->tstm
)
305 #if defined(stderr) && defined(stdout)
306 if( stderr
!= (FILE FAR
*)(pdbc
->tstm
)
307 && stdout
!= (FILE FAR
*)(pdbc
->tstm
) )
318 PUSHSQLERR (pdbc
->herr
, en_S1009
);
322 if( sqlstat
!= en_00000
)
324 PUSHSQLERR ( pdbc
->herr
, sqlstat
);
330 if( fOption
== SQL_OPT_TRACEFILE
)
331 /* Tracing file can be set before and after connect
332 * and only meaningful for driver manager.
336 || ((char FAR
*)vParam
)[0] == 0 )
338 PUSHSQLERR ( pdbc
->herr
, en_S1009
);
343 if( pdbc
->tfile
&& STREQ (pdbc
->tfile
, vParam
) )
350 PUSHSQLERR ( pdbc
->herr
, en_IM014
);
357 MEM_FREE( pdbc
->tfile
);
360 pdbc
->tfile
= (char FAR
*)MEM_ALLOC( 1 + STRLEN( vParam
) );
362 if( pdbc
->tfile
== NULL
)
364 PUSHSQLERR( pdbc
->herr
, en_S1001
);
369 STRCPY ( pdbc
->tfile
, vParam
);
374 if( pdbc
->state
!= en_dbc_allocated
)
376 /* If already connected, then, driver's odbc call
377 * will be invoked. Otherwise, we only save the options
378 * and delay the setting process until the connection
381 hproc
= _iodbcdm_getproc( hdbc
, en_SetConnectOption
);
383 if( hproc
== SQL_NULL_HPROC
)
385 PUSHSQLERR ( pdbc
->herr
, en_IM001
);
390 CALL_DRIVER ( hdbc
, retcode
, hproc
, en_SetConnectOption
, (
391 pdbc
->dhdbc
, fOption
, vParam
) )
394 retcode
= hproc( pdbc
->dhdbc
, fOption
, vParam
);
397 if( retcode
!= SQL_SUCCESS
398 && retcode
!= SQL_SUCCESS_WITH_INFO
)
405 * Now, either driver's odbc call was successed or
406 * driver has not been loaded yet. In the first case, we
407 * need flip flag for(such as access_mode, autocommit, ...)
408 * for our finit state machine. While in the second case,
409 * we need save option values(such as current_qualifier, ...)
410 * for delaied setting. So, ...
413 /* No matter what state we are(i.e. allocated or connected, ..)
414 * we need to flip the flag.
418 case SQL_ACCESS_MODE
:
419 pdbc
->access_mode
= vParam
;
423 pdbc
->autocommit
= vParam
;
427 /* state transition */
428 if( pdbc
->state
!= en_dbc_allocated
)
433 /* Only 'allocated' state is possible here, and we need to
434 * save the options for delaied setting.
438 case SQL_CURRENT_QUALIFIER
:
439 if( pdbc
->current_qualifier
!= NULL
)
441 MEM_FREE ( pdbc
->current_qualifier
);
446 pdbc
->current_qualifier
= NULL
;
451 pdbc
->current_qualifier
452 = (char FAR
*)MEM_ALLOC (
453 STRLEN (vParam
) + 1 );
455 if( pdbc
->current_qualifier
== NULL
)
457 PUSHSQLERR ( pdbc
->herr
, en_S1001
);
461 STRCPY ( pdbc
->current_qualifier
, vParam
);
464 case SQL_LOGIN_TIMEOUT
:
465 pdbc
->login_timeout
= vParam
;
468 case SQL_ODBC_CURSORS
:
469 pdbc
->odbc_cursors
= vParam
;
472 case SQL_PACKET_SIZE
:
473 pdbc
->packet_size
= vParam
;
477 pdbc
->quiet_mode
= vParam
;
480 case SQL_TXN_ISOLATION
:
481 pdbc
->txn_isolation
= vParam
;
485 /* Since we didn't save the option value for delaied
486 * setting, we should raise an error here.
494 RETCODE SQL_API
SQLGetConnectOption(
500 DBC_t FAR
* pdbc
= (DBC_t FAR
*)hdbc
;
501 int sqlstat
= en_00000
;
502 HPROC hproc
= SQL_NULL_HPROC
;
505 if( hdbc
== SQL_NULL_HDBC
)
507 return SQL_INVALID_HANDLE
;
511 if( fOption
< SQL_CONN_OPT_MIN
512 || ( fOption
> SQL_CONN_OPT_MAX
513 && fOption
< SQL_CONNECT_OPT_DRVR_START
) )
515 PUSHSQLERR ( pdbc
->herr
, en_S1092
);
521 switch( pdbc
->state
)
523 case en_dbc_allocated
:
524 if( fOption
!= SQL_ACCESS_MODE
525 && fOption
!= SQL_AUTOCOMMIT
526 && fOption
!= SQL_LOGIN_TIMEOUT
527 && fOption
!= SQL_OPT_TRACE
528 && fOption
!= SQL_OPT_TRACEFILE
)
532 /* MS ODBC SDK document only
533 * allows SQL_ACCESS_MODE
534 * and SQL_AUTOCOMMIT in this
535 * dbc state. We allow another
536 * two options, because they
537 * are only meaningful for driver
542 case en_dbc_needdata
:
550 if( sqlstat
!= en_00000
)
552 PUSHSQLERR ( pdbc
->herr
, sqlstat
);
557 /* Tracing and tracing file options are only
558 * meaningful for driver manager
560 if( fOption
== SQL_OPT_TRACE
)
563 *((UDWORD
*)pvParam
) = (UDWORD
)SQL_OPT_TRACE_ON
;
565 *((UDWORD
*)pvParam
) = (UDWORD
)SQL_OPT_TRACE_OFF
;
570 if( fOption
== SQL_OPT_TRACEFILE
)
572 STRCPY (pvParam
, pdbc
->tfile
);
577 if( pdbc
->state
!= en_dbc_allocated
)
578 /* if already connected, we will invoke driver's function */
580 hproc
= _iodbcdm_getproc( hdbc
, en_GetConnectOption
);
582 if( hproc
== SQL_NULL_HPROC
)
584 PUSHSQLERR( pdbc
->herr
, en_IM001
);
589 CALL_DRIVER ( hdbc
, retcode
, hproc
, en_GetConnectOption
, (
590 pdbc
->dhdbc
, fOption
, pvParam
) )
593 retcode
= hproc(pdbc
->dhdbc
, fOption
, pvParam
);
599 /* We needn't to handle options which are not allowed
600 * to be *get* at a allocated dbc state(and two tracing
601 * options which has been handled and returned). Thus,
602 * there are only two possible cases.
606 case SQL_ACCESS_MODE
:
607 *((UDWORD
*)pvParam
) = pdbc
->access_mode
;
611 *((UDWORD
*)pvParam
) = pdbc
->autocommit
;
614 case SQL_LOGIN_TIMEOUT
:
615 *((UDWORD
*)pvParam
) = pdbc
->login_timeout
;
625 static RETCODE
_iodbcdm_transact(
629 DBC_t FAR
* pdbc
= (DBC_t FAR
*)hdbc
;
635 switch( pdbc
->state
)
637 case en_dbc_allocated
:
638 case en_dbc_needdata
:
639 PUSHSQLERR ( pdbc
->herr
, en_08003
);
642 case en_dbc_connected
:
650 for( pstmt
= (STMT_t FAR
*)(pdbc
->hstmt
);
652 pstmt
= pstmt
->next
)
654 if( pstmt
->state
>= en_stmt_needdata
655 || pstmt
->asyn_on
!= en_NullProc
)
657 PUSHSQLERR ( pdbc
->herr
, en_S1010
);
663 hproc
= _iodbcdm_getproc( hdbc
, en_Transact
);
665 if( hproc
== SQL_NULL_HPROC
)
667 PUSHSQLERR ( pdbc
->herr
, en_IM001
);
672 CALL_DRIVER ( hdbc
, retcode
, hproc
, en_Transact
, (
673 SQL_NULL_HENV
, pdbc
->dhdbc
, fType
) )
676 retcode
= hproc( SQL_NULL_HENV
, pdbc
->dhdbc
, fType
);
679 /* state transition */
680 if( retcode
!= SQL_SUCCESS
681 && retcode
!= SQL_SUCCESS_WITH_INFO
)
686 pdbc
->state
= en_dbc_hstmt
;
688 for( pstmt
= (STMT_t FAR
*)(pdbc
->hstmt
);
690 pstmt
= pstmt
->next
)
692 switch( pstmt
->state
)
694 case en_stmt_prepared
:
695 if( pdbc
->cb_commit
== SQL_CB_DELETE
696 || pdbc
->cb_rollback
== SQL_CB_DELETE
)
698 pstmt
->state
= en_stmt_allocated
;
699 pstmt
->prep_state
= 0;
704 case en_stmt_executed
:
705 case en_stmt_cursoropen
:
706 case en_stmt_fetched
:
707 case en_stmt_xfetched
:
708 if( ! pstmt
->prep_state
709 && pdbc
->cb_commit
!= SQL_CB_PRESERVE
710 && pdbc
->cb_rollback
!= SQL_CB_PRESERVE
)
712 pstmt
->state
= en_stmt_allocated
;
713 pstmt
->prep_state
= 0;
714 pstmt
->cursor_state
= en_stmt_cursor_no
;
718 if( pstmt
->prep_state
)
720 if( pdbc
->cb_commit
== SQL_CB_DELETE
721 || pdbc
->cb_rollback
== SQL_CB_DELETE
)
723 pstmt
->state
= en_stmt_allocated
;
724 pstmt
->prep_state
= 0;
725 pstmt
->cursor_state
= en_stmt_cursor_no
;
729 if( pdbc
->cb_commit
== SQL_CB_CLOSE
730 || pdbc
->cb_rollback
== SQL_CB_CLOSE
)
750 RETCODE SQL_API
SQLTransact(
755 GENV_t FAR
* genv
= (GENV_t FAR
*)henv
;
756 DBC_t FAR
* pdbc
= (DBC_t FAR
*)hdbc
;
760 if( hdbc
!= SQL_NULL_HDBC
)
764 else if( henv
!= SQL_NULL_HENV
)
770 return SQL_INVALID_HANDLE
;
774 if( fType
!= SQL_COMMIT
775 && fType
!= SQL_ROLLBACK
)
777 PUSHSQLERR ( herr
, en_S1012
);
782 if( hdbc
!= SQL_NULL_HDBC
)
784 retcode
= _iodbcdm_transact( hdbc
, fType
);
788 for( pdbc
= (DBC_t FAR
*)(genv
->hdbc
);
792 retcode
|= _iodbcdm_transact( hdbc
, fType
);
796 if( retcode
!= SQL_SUCCESS
797 && retcode
!= SQL_SUCCESS_WITH_INFO
)
799 /* fail on one of the connection */