]> git.saurik.com Git - wxWidgets.git/blob - src/iodbc/connect.c
Guess what: ODBC updates and build fixes.
[wxWidgets.git] / src / iodbc / connect.c
1 /** Connect(load) driver
2
3 Copyright (C) 1995 by Ke Jin <kejin@empress.com>
4
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.
9
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.
14 **/
15
16 #include <../iodbc/iodbc.h>
17
18 #include <../iodbc/isql.h>
19 #include <../iodbc/isqlext.h>
20
21 #include <../iodbc/dlproc.h>
22
23 #include <../iodbc/herr.h>
24 #include <../iodbc/henv.h>
25 #include <../iodbc/hdbc.h>
26 #include <../iodbc/hstmt.h>
27
28 #include <../iodbc/itrace.h>
29
30 #include <strings.h>
31 #include <stdio.h>
32
33 extern char* _iodbcdm_getkeyvalbydsn();
34 extern char* _iodbcdm_getkeyvalinstr();
35 extern RETCODE _iodbcdm_driverunload();
36
37 /*
38 * Following id string is a copyright mark. Removing(i.e. use
39 * souce code of this package without it or make it not appear
40 * in the final object file) or modifing it without permission
41 * from original author(kejin@empress.com) are copyright
42 * violation.
43 */
44 static char sccsid[]
45 = "@(#)iODBC driver manager " "2.12" ", Copyright(c) 1995 by Ke Jin";
46
47 static RETCODE _iodbcdm_driverload(
48 char FAR* path,
49 HDBC hdbc )
50 /* - Load driver share library( or increase its reference count
51 * if it has already been loaded by another active connection)
52 * - Call driver's SQLAllocEnv() (for the first reference only)
53 * - Call driver's SQLAllocConnect()
54 * - Call driver's SQLSetConnectOption() (set login time out)
55 * - Increase the bookkeeping reference count
56 */
57 {
58 DBC_t FAR* pdbc = (DBC_t FAR*)hdbc;
59 GENV_t FAR* genv;
60 ENV_t FAR* penv = NULL;
61 HDLL hdll;
62 HPROC hproc;
63 RETCODE retcode = SQL_SUCCESS;
64 int sqlstat = en_00000;
65
66 if(pdbc->trace)
67 {
68 fprintf(pdbc->tstm, "_iodbcdm_driverload(%s, 0x%x)\n", path, (int)hdbc);
69 }
70
71 if( path == NULL || path[0] == '\0' )
72 {
73 PUSHSQLERR ( pdbc->herr, en_IM002 );
74
75 return SQL_ERROR;
76 }
77
78 if( hdbc == SQL_NULL_HDBC
79 || pdbc->genv == SQL_NULL_HENV )
80 {
81 return SQL_INVALID_HANDLE;
82 }
83
84 genv = (GENV_t FAR*)pdbc->genv;
85
86 hdll = _iodbcdm_dllopen( (char FAR*) path );
87 /* This will either load the
88 * driver dll or increase its
89 * reference count */
90
91 if( hdll == SQL_NULL_HDLL )
92 {
93 if(pdbc->trace)
94 {
95 fprintf(pdbc->tstm, "ERROR: _iodbcdm_driverload cannot load driver - '%s'\n", _iodbcdm_dllerror());
96 }
97
98 PUSHSYSERR ( pdbc->herr, _iodbcdm_dllerror() );
99 PUSHSQLERR ( pdbc->herr, en_IM003 );
100 return SQL_ERROR;
101 }
102
103 penv = (ENV_t FAR*)(pdbc->henv);
104
105 if( penv != NULL )
106 {
107 if( penv->hdll != hdll )
108 {
109 _iodbcdm_driverunload(hdbc);
110 }
111 else
112 {
113 _iodbcdm_dllclose( hdll );
114 /* this will not unload the driver
115 * but only decrease its internal
116 * reference count
117 */
118 }
119 }
120
121 if(penv == NULL )
122 {
123 /* find out whether this dll has already
124 * been loaded on another connection */
125 for( penv = (ENV_t FAR*)genv->henv;
126 penv != NULL;
127 penv = (ENV_t FAR*)penv->next )
128 {
129 if( penv->hdll == hdll )
130 {
131 _iodbcdm_dllclose( hdll );
132 /* this will not unload the driver
133 * but only decrease its internal
134 * reference count
135 */
136 break;
137 }
138 }
139
140 if( penv == NULL )
141 /* no connection attaching with this dll */
142 {
143 int i;
144
145 /* create a new dll env instance */
146 penv = (ENV_t FAR*)MEM_ALLOC ( sizeof(ENV_t) );
147
148 if( penv == NULL )
149 {
150 _iodbcdm_dllclose(hdll);
151
152 PUSHSQLERR ( pdbc->herr, en_S1001 );
153
154 return SQL_ERROR;
155 }
156
157 for( i = 0; i< SQL_EXT_API_LAST + 1; i++)
158 {
159 (penv->dllproc_tab)[i] = SQL_NULL_HPROC;
160 }
161
162 pdbc->henv = penv;
163 penv->hdll = hdll;
164
165 /* call driver's SQLAllocHandle() or SQLAllocEnv() */
166 #if (ODBCVER >= 0x0300)
167 hproc = _iodbcdm_getproc( hdbc, en_AllocHandle );
168
169 if( hproc )
170 {
171 CALL_DRIVER ( hdbc, retcode, hproc, en_AllocHandle,
172 ( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &(penv->dhenv) )
173 }
174 else /* try driver's SQLAllocEnv() */
175 #endif
176 {
177 hproc = _iodbcdm_getproc( hdbc, en_AllocEnv );
178
179 if( hproc == SQL_NULL_HPROC)
180 {
181 sqlstat = en_IM004;
182 }
183 else
184 {
185 CALL_DRIVER ( hdbc, retcode, hproc,
186 en_AllocEnv, (&(penv->dhenv)) )
187 }
188 }
189
190 if( retcode == SQL_ERROR )
191 {
192 sqlstat = en_IM004;
193 }
194
195 if( sqlstat != en_00000 )
196 {
197 _iodbcdm_dllclose ( hdll );
198 MEM_FREE ( penv );
199 PUSHSQLERR ( pdbc->herr, en_IM004 );
200
201 return SQL_ERROR;
202 }
203
204 /* insert into dll env list */
205 penv->next = (ENV_t FAR*)genv->henv;
206 genv->henv = penv;
207
208 /* initiate this new env entry */
209 penv->refcount = 0; /* we will increase it after
210 * driver's SQLAllocConnect()
211 * success
212 */
213 }
214
215 pdbc->henv = penv;
216
217 if( pdbc->dhdbc == SQL_NULL_HDBC )
218 {
219 #if (ODBCVER >= 0x0300)
220 hproc = _iodbcdm_getproc( hdbc, en_AllocHandle );
221
222 if( hproc )
223 {
224 CALL_DRIVER( hdbc, retcode, hproc, en_AllocHandle,
225 (SQL_HANDLE_DBC, penv->dhenv, &(pdbc->dhdbc)) )
226 }
227 else
228 #endif
229 {
230 hproc = _iodbcdm_getproc( hdbc, en_AllocConnect );
231
232 if( hproc == SQL_NULL_HPROC )
233 {
234 sqlstat = en_IM005;
235 }
236 else
237 {
238 CALL_DRIVER ( hdbc, retcode, hproc,
239 en_AllocConnect, (penv->dhenv, &(pdbc->dhdbc)) )
240 }
241 }
242
243 if( retcode == SQL_ERROR )
244 {
245 sqlstat = en_IM005;
246 }
247
248 if( sqlstat != en_00000 )
249 {
250 _iodbcdm_driverunload(hdbc);
251
252 pdbc->dhdbc = SQL_NULL_HDBC;
253 PUSHSQLERR ( pdbc->herr, en_IM005 );
254
255 return SQL_ERROR;
256 }
257 }
258
259 pdbc->henv = penv;
260 penv->refcount ++; /* bookkeeping reference count on this driver */
261 }
262
263 /* driver's login timeout option must been set before
264 * its SQLConnect() call */
265 if( pdbc->login_timeout != 0UL )
266 {
267 hproc = _iodbcdm_getproc( hdbc, en_SetConnectOption );
268
269 if( hproc == SQL_NULL_HPROC )
270 {
271 sqlstat = en_IM004;
272 }
273 else
274 {
275 CALL_DRIVER ( hdbc, retcode, hproc,
276 en_SetConnectOption, (
277 pdbc->dhdbc,
278 SQL_LOGIN_TIMEOUT,
279 pdbc->login_timeout ) )
280
281 if( retcode == SQL_ERROR )
282 {
283 PUSHSQLERR ( pdbc->herr, en_IM006 );
284
285 return SQL_SUCCESS_WITH_INFO;
286 }
287 }
288 }
289
290 return SQL_SUCCESS;
291 }
292
293 RETCODE _iodbcdm_driverunload( HDBC hdbc )
294 /* - Call driver's SQLFreeConnect()
295 * - Call driver's SQLFreeEnv() ( for the last reference only)
296 * - Unload the share library( or decrease its reference
297 * count if it is not the last referenct )
298 * - decrease bookkeeping reference count
299 * - state transition to allocated
300 */
301 {
302 DBC_t FAR* pdbc = (DBC_t FAR*)hdbc;
303 ENV_t FAR* penv;
304 ENV_t FAR* tpenv;
305 GENV_t FAR* genv;
306 HPROC hproc;
307 RETCODE retcode = SQL_SUCCESS;
308 int sqlstat = en_00000;
309
310 if( hdbc == SQL_NULL_HDBC )
311 {
312 return SQL_INVALID_HANDLE;
313 }
314
315 /* no pointer check will be performed in this function */
316 penv = (ENV_t FAR*)pdbc->henv;
317 genv = (GENV_t FAR*)pdbc->genv;
318
319 if( penv == NULL
320 || penv->hdll == SQL_NULL_HDLL )
321 {
322 return SQL_SUCCESS;
323 }
324
325 #if (ODBCVER >= 0x0300)
326 hproc = _iodbcdm_getproc( hdbc, en_FreeHandle );
327
328 if( hproc )
329 {
330 CALL_DRIVER ( hdbc, retcode, hproc, en_FreeHandle,
331 ( SQL_HANDLE_DBC, pdbc->dhdbc ) )
332 }
333 else
334 #endif
335 {
336 hproc = _iodbcdm_getproc( hdbc, en_FreeConnect );
337
338 if( hproc != SQL_NULL_HPROC )
339 {
340 CALL_DRIVER ( hdbc, retcode, hproc,
341 en_FreeConnect, ( pdbc->dhdbc ) )
342
343 pdbc->dhdbc = SQL_NULL_HDBC;
344 }
345 }
346
347 penv->refcount --;
348
349 if( ! penv->refcount )
350 /* no other connections still attaching with this driver */
351 {
352 #if (ODBCVER >= 0x0300)
353 hproc = _iodbcdm_getproc( hdbc, en_FreeHandle );
354
355 if( hproc )
356 {
357 CALL_DRIVER ( hdbc, retcode, hproc, en_FreeHandle,
358 ( SQL_HANDLE_ENV, penv->dhenv ) )
359 }
360 else
361 #endif
362 {
363 hproc = _iodbcdm_getproc( hdbc, en_FreeEnv );
364
365 if( hproc != SQL_NULL_HPROC )
366 {
367 CALL_DRIVER ( hdbc, retcode, hproc, en_FreeEnv,
368 ( penv->dhenv ) )
369
370 penv->dhenv = SQL_NULL_HENV;
371 }
372 }
373
374 _iodbcdm_dllclose ( penv->hdll );
375
376 penv->hdll == SQL_NULL_HDLL;
377
378 for( tpenv = (ENV_t FAR*)genv->henv;
379 tpenv != NULL;
380 tpenv = (ENV_t FAR*)penv->next )
381 {
382 if( tpenv == penv )
383 {
384 genv->henv = penv->next;
385 break;
386 }
387
388 if( tpenv->next == penv )
389 {
390 tpenv->next = penv->next;
391 break;
392 }
393 }
394
395 MEM_FREE( penv );
396 }
397
398 pdbc->henv = SQL_NULL_HENV;
399 pdbc->hstmt= SQL_NULL_HSTMT;
400 /* pdbc->herr = SQL_NULL_HERR;
401 -- delay to DM's SQLFreeConnect() */
402 pdbc->dhdbc= SQL_NULL_HDBC;
403 pdbc->state= en_dbc_allocated;
404
405 /* set connect options to default values */
406 /**********
407 pdbc->access_mode = SQL_MODE_DEFAULT;
408 pdbc->autocommit = SQL_AUTOCOMMIT_DEFAULT;
409 pdbc->login_timeout = 0UL;
410 **********/
411 pdbc->odbc_cursors = SQL_CUR_DEFAULT;
412 pdbc->packet_size = 0UL;
413 pdbc->quiet_mode = (UDWORD)NULL;
414 pdbc->txn_isolation = SQL_TXN_READ_UNCOMMITTED;
415
416 if( pdbc->current_qualifier != NULL )
417 {
418 MEM_FREE ( pdbc->current_qualifier );
419 pdbc->current_qualifier = NULL;
420 }
421
422 return SQL_SUCCESS;
423 }
424
425 static RETCODE _iodbcdm_dbcdelayset( HDBC hdbc )
426 {
427 DBC_t FAR* pdbc = (DBC_t FAR*)hdbc;
428 ENV_t FAR* penv;
429 HPROC hproc;
430 RETCODE retcode = SQL_SUCCESS;
431 RETCODE ret;
432
433 penv = pdbc->henv;
434
435 hproc = _iodbcdm_getproc( hdbc, en_SetConnectOption );
436
437 if( hproc == SQL_NULL_HPROC )
438 {
439 PUSHSQLERR ( pdbc->herr, en_IM006 );
440
441 return SQL_SUCCESS_WITH_INFO;
442 }
443
444 if( pdbc->access_mode != SQL_MODE_DEFAULT )
445 {
446 CALL_DRIVER ( hdbc, ret, hproc,
447 en_SetConnectOption, (
448 SQL_ACCESS_MODE,
449 pdbc->access_mode) )
450
451 retcode |= ret;
452 }
453
454 if( pdbc->autocommit != SQL_AUTOCOMMIT_DEFAULT )
455 {
456 CALL_DRIVER ( hdbc, ret, hproc,
457 en_SetConnectOption, (
458 pdbc->dhdbc,
459 SQL_AUTOCOMMIT,
460 pdbc->autocommit ) )
461
462 retcode |= ret;
463 }
464
465 if( pdbc->current_qualifier != NULL )
466 {
467 CALL_DRIVER ( hdbc, ret, hproc,
468 en_SetConnectOption, (
469 pdbc->dhdbc,
470 SQL_CURRENT_QUALIFIER,
471 pdbc->current_qualifier ) )
472
473 retcode |= ret;
474 }
475
476 if( pdbc->packet_size != 0UL )
477 {
478 CALL_DRIVER ( hdbc, ret, hproc,
479 en_SetConnectOption, (
480 pdbc->dhdbc,
481 SQL_PACKET_SIZE,
482 pdbc->packet_size ) )
483
484 retcode |= ret;
485 }
486
487 if( pdbc->quiet_mode != (UDWORD)NULL )
488 {
489 CALL_DRIVER ( hdbc, ret, hproc,
490 en_SetConnectOption, (
491 pdbc->dhdbc,
492 SQL_QUIET_MODE,
493 pdbc->quiet_mode ) )
494
495 retcode |= ret;
496 }
497
498 if( pdbc->txn_isolation != SQL_TXN_READ_UNCOMMITTED )
499 {
500 CALL_DRIVER ( hdbc, ret, hproc,
501 en_SetConnectOption, (
502 pdbc->dhdbc,
503 SQL_TXN_ISOLATION,
504 pdbc->txn_isolation ) )
505 }
506
507 /* check error code for driver's SQLSetConnectOption() call */
508 if( retcode != SQL_SUCCESS
509 && retcode != SQL_SUCCESS_WITH_INFO )
510 {
511 PUSHSQLERR ( pdbc->herr, en_IM006 );
512
513 retcode = SQL_ERROR;
514 }
515
516 /* get cursor behavior on transaction commit or rollback */
517 hproc = _iodbcdm_getproc( hdbc, en_GetInfo );
518
519 if( hproc == SQL_NULL_HPROC )
520 {
521 PUSHSQLERR ( pdbc->herr, en_01000 );
522
523 return retcode;
524 }
525
526 CALL_DRIVER ( hdbc, ret, hproc,
527 en_GetInfo, (
528 pdbc->dhdbc,
529 SQL_CURSOR_COMMIT_BEHAVIOR,
530 (PTR)&(pdbc->cb_commit),
531 sizeof(pdbc->cb_commit),
532 NULL ) )
533
534 retcode |= ret;
535
536 CALL_DRIVER ( hdbc, ret, hproc,
537 en_GetInfo, (
538 pdbc->dhdbc,
539 SQL_CURSOR_ROLLBACK_BEHAVIOR,
540 (PTR)&(pdbc->cb_rollback),
541 sizeof(pdbc->cb_rollback),
542 NULL ) )
543
544 retcode |= ret;
545
546 if( retcode != SQL_SUCCESS
547 && retcode != SQL_SUCCESS_WITH_INFO )
548 {
549 return SQL_ERROR;
550 }
551
552 return retcode;
553 }
554
555 static RETCODE _iodbcdm_settracing( HDBC hdbc, char* dsn, int dsnlen )
556 {
557 char buf[256];
558 char* ptr;
559 RETCODE setopterr = SQL_SUCCESS;
560
561 /* Get Driver's DLL path from specificed or default dsn section */
562 ptr = _iodbcdm_getkeyvalbydsn( dsn, dsnlen, "TraceFile",
563 (char FAR*)buf, sizeof(buf));
564
565 if( ptr == NULL || ptr[0] == '\0' )
566 {
567 ptr = (char FAR*)(SQL_OPT_TRACE_FILE_DEFAULT);
568 }
569
570 setopterr |= SQLSetConnectOption( hdbc,
571 SQL_OPT_TRACEFILE, (UDWORD)(ptr));
572
573 ptr = _iodbcdm_getkeyvalbydsn( dsn, dsnlen, "Trace",
574 (char FAR*)buf, sizeof(buf));
575
576 if( ptr != NULL )
577 {
578 UDWORD opt = (UDWORD)(-1L);
579
580 if( STREQ(ptr, "ON")
581 || STREQ(ptr, "On")
582 || STREQ(ptr, "on")
583 || STREQ(ptr, "1" ) )
584 {
585 opt = SQL_OPT_TRACE_ON;
586 }
587
588 if( STREQ(ptr, "OFF")
589 || STREQ(ptr, "Off")
590 || STREQ(ptr, "off")
591 || STREQ(ptr, "0" ) )
592 {
593 opt = SQL_OPT_TRACE_OFF;
594 }
595
596 if( opt != (UDWORD)(-1L) )
597 {
598 setopterr |= SQLSetConnectOption( hdbc,
599 SQL_OPT_TRACE, opt);
600 }
601 }
602 return SQL_SUCCESS;
603 }
604
605 RETCODE SQL_API SQLConnect (
606 HDBC hdbc,
607 UCHAR FAR* szDSN,
608 SWORD cbDSN,
609 UCHAR FAR* szUID,
610 SWORD cbUID,
611 UCHAR FAR* szAuthStr,
612 SWORD cbAuthStr)
613 {
614 DBC_t FAR* pdbc = (DBC_t FAR*)hdbc;
615 RETCODE retcode = SQL_SUCCESS;
616 RETCODE setopterr = SQL_SUCCESS;
617 char driver[1024] = { '\0' }; /* MS SDK Guide
618 * specifies driver
619 * path can't longer
620 * than 255. */
621 char szNewDSN[256]; /* OS/2 !!! */
622 char *ptr;
623 HPROC hproc;
624
625 if( hdbc == SQL_NULL_HDBC )
626 {
627 return SQL_INVALID_HANDLE;
628 }
629
630 /* check arguments */
631 if( ( cbDSN < 0 && cbDSN != SQL_NTS )
632 || ( cbUID < 0 && cbUID != SQL_NTS )
633 || ( cbAuthStr < 0 && cbAuthStr != SQL_NTS )
634 || ( cbDSN > SQL_MAX_DSN_LENGTH ) )
635 {
636 PUSHSQLERR ( pdbc->herr, en_S1090 );
637
638 return SQL_ERROR;
639 }
640
641 if( szDSN == NULL || cbDSN == 0 )
642 {
643 PUSHSQLERR ( pdbc->herr, en_IM002 );
644
645 return SQL_ERROR;
646 }
647
648 /* check state */
649 if( pdbc->state != en_dbc_allocated )
650 {
651 PUSHSQLERR ( pdbc->herr, en_08002 );
652
653 return SQL_ERROR;
654 }
655
656 setopterr |= _iodbcdm_settracing( hdbc,
657 (char*)szDSN, cbDSN );
658
659 ptr = _iodbcdm_getkeyvalbydsn( szDSN, cbDSN, "Driver",
660 (char FAR*)driver, sizeof(driver));
661
662 if( ptr == NULL )
663 /* No specified or default dsn section or
664 * no driver specification in this dsn section */
665 {
666 PUSHSQLERR ( pdbc->herr, en_IM002 );
667
668 return SQL_ERROR;
669 }
670
671 /*
672 ** OS/2 !!!
673 **
674 ** get new szDSN from INI file, if existing
675 */
676 if( NULL != _iodbcdm_getkeyvalbydsn( szDSN, cbDSN, "DSN",
677 (char FAR*) &szNewDSN,
678 sizeof(szNewDSN) ) )
679 {
680 szDSN = &szNewDSN[0];
681 cbDSN = SQL_NTS;
682 }
683
684 retcode = _iodbcdm_driverload( driver, hdbc );
685
686 switch( retcode )
687 {
688 case SQL_SUCCESS:
689 break;
690
691 case SQL_SUCCESS_WITH_INFO:
692 setopterr = SQL_ERROR;
693 /* unsuccessed in calling driver's
694 * SQLSetConnectOption() to set login
695 * timeout.
696 */
697 break;
698
699 default:
700 return retcode;
701 }
702
703 hproc = _iodbcdm_getproc( hdbc, en_Connect );
704
705 if( hproc == SQL_NULL_HPROC )
706 {
707 _iodbcdm_driverunload( hdbc );
708
709 PUSHSQLERR ( pdbc->herr, en_IM001 );
710
711 return SQL_ERROR;
712 }
713
714 CALL_DRIVER ( hdbc, retcode, hproc, en_Connect, (
715 pdbc->dhdbc,
716 szDSN, cbDSN,
717 szUID, cbUID,
718 szAuthStr, cbAuthStr ) )
719
720 #if 0
721 retcode = hproc(pdbc->dhdbc,
722 szDSN, cbDSN,
723 szUID, cbUID,
724 szAuthStr, cbAuthStr );
725 #endif
726
727 if( retcode != SQL_SUCCESS
728 && retcode != SQL_SUCCESS_WITH_INFO )
729 {
730 /* not unload driver for retrive error
731 * messge from driver */
732 /*********
733 _iodbcdm_driverunload( hdbc );
734 **********/
735
736 return retcode;
737 }
738
739 /* state transition */
740 pdbc->state = en_dbc_connected;
741
742 /* do delaid option setting */
743 setopterr |= _iodbcdm_dbcdelayset( hdbc );
744
745 if( setopterr != SQL_SUCCESS )
746 {
747 return SQL_SUCCESS_WITH_INFO;
748 }
749
750 return retcode;
751 }
752
753 RETCODE SQL_API SQLDriverConnect (
754 HDBC hdbc,
755 HWND hwnd,
756 UCHAR FAR* szConnStrIn,
757 SWORD cbConnStrIn,
758 UCHAR FAR* szConnStrOut,
759 SWORD cbConnStrOutMax,
760 SWORD FAR* pcbConnStrOut,
761 UWORD fDriverCompletion )
762 {
763 DBC_t FAR* pdbc = (DBC_t FAR*)hdbc;
764 HDLL hdll;
765 char FAR* drv;
766 char drvbuf[1024];
767 char FAR* dsn;
768 char dsnbuf[SQL_MAX_DSN_LENGTH + 1];
769 char szNewDSN[256]; /* OS/2 !!! */
770 UCHAR cnstr2drv[1024];
771
772 HPROC hproc, dialproc;
773
774 int sqlstat = en_00000;
775 RETCODE retcode = SQL_SUCCESS;
776 RETCODE setopterr = SQL_SUCCESS;
777
778 if( hdbc == SQL_NULL_HDBC )
779 {
780 return SQL_INVALID_HANDLE;
781 }
782
783 /* check arguments */
784 if( ( cbConnStrIn < 0 && cbConnStrIn != SQL_NTS )
785 || cbConnStrOutMax < 0 )
786 {
787 PUSHSQLERR (pdbc->herr, en_S1090 );
788
789 return SQL_ERROR;
790 }
791
792 /* check state */
793 if( pdbc->state != en_dbc_allocated )
794 {
795 PUSHSQLERR (pdbc->herr, en_08002 );
796
797 return SQL_ERROR;
798 }
799
800 drv = _iodbcdm_getkeyvalinstr(szConnStrIn, cbConnStrIn,
801 "DRIVER", drvbuf, sizeof(drvbuf));
802
803 dsn = _iodbcdm_getkeyvalinstr(szConnStrIn, cbConnStrIn,
804 "DSN", dsnbuf, sizeof(dsnbuf));
805
806 switch( fDriverCompletion )
807 {
808 case SQL_DRIVER_NOPROMPT:
809 break;
810
811 case SQL_DRIVER_COMPLETE:
812 case SQL_DRIVER_COMPLETE_REQUIRED:
813 if( dsn != NULL )
814 {
815 break;
816 }
817 /* fall to next case */
818 case SQL_DRIVER_PROMPT:
819 /* Get data source dialog box function from
820 * current executable */
821 hdll = _iodbcdm_dllopen((char FAR*)NULL);
822 dialproc = _iodbcdm_dllproc( hdll,
823 "_iodbcdm_drvconn_dialbox");
824
825 if( dialproc == SQL_NULL_HPROC )
826 {
827 sqlstat = en_IM008;
828 break;
829 }
830
831 retcode = dialproc(
832 hwnd, /* window or display handle */
833 dsnbuf, /* input/output dsn buf */
834 sizeof(dsnbuf), /* buf size */
835 &sqlstat); /* error code */
836
837 if( retcode != SQL_SUCCESS )
838 {
839 break;
840 }
841
842 if( cbConnStrIn == SQL_NTS )
843 {
844 cbConnStrIn = STRLEN(szConnStrIn );
845 }
846
847 dsn = dsnbuf;
848
849 if( dsn[0] == '\0' )
850 {
851 dsn = "default";
852 }
853
854 if( cbConnStrIn > sizeof(cnstr2drv)
855 - STRLEN(dsn) - STRLEN("DSN=;") -1 )
856 {
857 sqlstat = en_S1001; /* a lazy way to avoid
858 * using heap memory */
859 break;
860 }
861
862 sprintf(cnstr2drv, "DSN=%s;", dsn);
863 cbConnStrIn += STRLEN(cnstr2drv);
864 STRNCAT( cnstr2drv, szConnStrIn, cbConnStrIn );
865 szConnStrIn = cnstr2drv;
866 break;
867
868 default:
869 sqlstat = en_S1110;
870 break;
871 }
872
873 if( sqlstat != en_00000 )
874 {
875 PUSHSQLERR( pdbc->herr, sqlstat );
876
877 return SQL_ERROR;
878 }
879
880 if( dsn == NULL || dsn[0] == '\0' )
881 {
882 dsn = "default";
883 }
884 else /* if you want tracing, you must use a DSN */
885 {
886 setopterr |= _iodbcdm_settracing( hdbc,
887 (char*)dsn, SQL_NTS );
888 }
889
890 if( drv == NULL || drv[0] == '\0' )
891 {
892 drv = _iodbcdm_getkeyvalbydsn( dsn, SQL_NTS, "Driver",
893 drvbuf, sizeof(drvbuf));
894 }
895
896 if( drv == NULL )
897 {
898 PUSHSQLERR( pdbc->herr, en_IM002 );
899
900 return SQL_ERROR;
901 }
902
903 retcode = _iodbcdm_driverload( drv, hdbc );
904
905 switch( retcode )
906 {
907 case SQL_SUCCESS:
908 break;
909
910 case SQL_SUCCESS_WITH_INFO:
911 setopterr = SQL_ERROR;
912 /* unsuccessed in calling driver's
913 * SQLSetConnectOption() to set login
914 * timeout.
915 */
916 break;
917
918 default:
919 return retcode;
920 }
921
922 hproc = _iodbcdm_getproc( hdbc, en_DriverConnect );
923
924 if( hproc == SQL_NULL_HPROC )
925 {
926 _iodbcdm_driverunload( hdbc );
927
928 PUSHSQLERR ( pdbc->herr, en_IM001 );
929
930 return SQL_ERROR;
931 }
932 /* giovanni */
933 /*
934 ** OS/2 !!!
935 **
936 ** get new szDSN from INI file, if existing
937 */
938 strcpy( szNewDSN, "DSN=" );
939 if( NULL != _iodbcdm_getkeyvalbydsn( dsn, SQL_NTS, "DSN",
940 (char FAR*) &szNewDSN[4],
941 sizeof(szNewDSN) - 4 ) )
942 {
943 char *psz;
944
945 strcat( szNewDSN, ";UID=" );
946 psz = strtok( szNewDSN, "\0" );
947
948
949
950
951 if(NULL == _iodbcdm_getkeyvalinstr( szConnStrIn, cbConnStrIn,
952 /*
953 "UID", psz, sizeof(szNewDSN) ))
954 */
955 "UID", (char FAR*) &szNewDSN[strlen(psz)],
956 (sizeof(szNewDSN) - strlen(psz)) ) )
957 {
958 _iodbcdm_getkeyvalbydsn( dsn, SQL_NTS,
959 "UID", (char FAR*) &szNewDSN[strlen(psz)],
960 (sizeof(szNewDSN) - strlen(psz)) );
961 }
962 strcat( szNewDSN, ";PWD=" );
963 psz = strtok( szNewDSN, "\0" );
964 if(NULL == _iodbcdm_getkeyvalinstr( szConnStrIn, cbConnStrIn,
965 /*
966 "PWD", psz, sizeof(szNewDSN) ))
967 */
968 "PWD", (char FAR*) &szNewDSN[strlen(psz)],
969 (sizeof(szNewDSN) - strlen(psz)) ) )
970 {
971
972 _iodbcdm_getkeyvalbydsn( dsn, SQL_NTS,
973 "PWD", (char FAR*) &szNewDSN[strlen(psz)],
974 (sizeof(szNewDSN) - strlen(psz)) );
975 }
976 /*
977 new from dirk
978 {
979 register char *psz;
980
981 strcat( szNewDSN, ";UID=" );
982 psz = strtok( szNewDSN, "\0" );
983 _iodbcdm_getkeyvalinstr( szConnStrIn, cbConnStrIn,
984 "UID", psz, sizeof(szNewDSN) );
985 strcat( szNewDSN, ";PWD=" );
986 psz = strtok( szNewDSN, "\0" );
987 _iodbcdm_getkeyvalinstr( szConnStrIn, cbConnStrIn,
988 "PWD", psz, sizeof(szNewDSN) );
989 szConnStrIn = &szNewDSN[0];
990 cbConnStrIn = SQL_NTS;
991 }
992
993
994 */
995 /******** giovanni & monty ********/
996 /* Add a lot of optional keywords */
997 {
998 static char *keywords[]= { "SERVER","PORT","SOCKET","OPTION","DB",0 };
999 char buff[80],**key,*end;
1000
1001 psz= szNewDSN+strlen(szNewDSN);
1002 end= szNewDSN+sizeof(szNewDSN);
1003 for (key=keywords ; *key ; key++)
1004 {
1005 if (_iodbcdm_getkeyvalbydsn(dsn, SQL_NTS,
1006 *key, (char FAR*) buff,
1007 sizeof(buff)) &&
1008 strlen(*key)+strlen(buff)+2 < (int) (end - psz))
1009 {
1010 *psz++=';';
1011 strcpy(psz,*key); psz+=strlen(*key);
1012 *psz++='=';
1013 strcpy(psz,buff); psz+=strlen(buff);
1014 }
1015 }
1016 }
1017 *psz=0;
1018 /******** giovanni */
1019 szConnStrIn = szNewDSN; /*giovanni, era &szNewDSN */
1020 cbConnStrIn = SQL_NTS;
1021 }
1022 /* giovanni */
1023 CALL_DRIVER ( hdbc, retcode, hproc, en_DriverConnect, (
1024 pdbc->dhdbc, hwnd,
1025 szConnStrIn, cbConnStrIn,
1026 szConnStrOut, cbConnStrOutMax,
1027 pcbConnStrOut, fDriverCompletion ) )
1028 #if 0
1029 retcode = hproc(pdbc->dhdbc, hwnd,
1030 szConnStrIn, cbConnStrIn,
1031 szConnStrOut, cbConnStrOutMax,
1032 pcbConnStrOut, fDriverCompletion );
1033 #endif
1034
1035 if( retcode != SQL_SUCCESS
1036 && retcode != SQL_SUCCESS_WITH_INFO )
1037 {
1038 /* don't unload driver here for retrive
1039 * error message from driver */
1040 /********
1041 _iodbcdm_driverunload( hdbc );
1042 *********/
1043
1044 return retcode;
1045 }
1046
1047 /* state transition */
1048 pdbc->state = en_dbc_connected;
1049
1050 /* do delaid option setting */
1051 setopterr |= _iodbcdm_dbcdelayset( hdbc );
1052
1053 if( setopterr != SQL_SUCCESS )
1054 {
1055 return SQL_SUCCESS_WITH_INFO;
1056 }
1057
1058 return retcode;
1059 }
1060
1061 RETCODE SQL_API SQLBrowseConnect (
1062 HDBC hdbc,
1063 HWND hwnd,
1064 UCHAR FAR* szConnStrIn,
1065 SWORD cbConnStrIn,
1066 UCHAR FAR* szConnStrOut,
1067 SWORD cbConnStrOutMax,
1068 SWORD FAR* pcbConnStrOut )
1069 {
1070 DBC_t FAR* pdbc = (DBC_t FAR*)hdbc;
1071 HDLL hdll;
1072 char FAR* drv;
1073 char drvbuf[1024];
1074 char FAR* dsn;
1075 char dsnbuf[SQL_MAX_DSN_LENGTH + 1];
1076 UCHAR cnstr2drv[1024];
1077
1078 HPROC hproc, dialproc;
1079
1080 int sqlstat = en_00000;
1081 RETCODE retcode = SQL_SUCCESS;
1082 RETCODE setopterr = SQL_SUCCESS;
1083
1084 if( hdbc == SQL_NULL_HDBC )
1085 {
1086 return SQL_INVALID_HANDLE;
1087 }
1088
1089 /* check arguments */
1090 if( ( cbConnStrIn < 0 && cbConnStrIn != SQL_NTS )
1091 || cbConnStrOutMax < 0 )
1092 {
1093 PUSHSQLERR (pdbc->herr, en_S1090 );
1094
1095 return SQL_ERROR;
1096 }
1097
1098 if( pdbc->state == en_dbc_allocated )
1099 {
1100 drv = _iodbcdm_getkeyvalinstr(szConnStrIn, cbConnStrIn,
1101 "DRIVER", drvbuf, sizeof(drvbuf));
1102
1103 dsn = _iodbcdm_getkeyvalinstr(szConnStrIn, cbConnStrIn,
1104 "DSN", dsnbuf, sizeof(dsnbuf));
1105
1106 if( dsn == NULL || dsn[0] == '\0' )
1107 {
1108 dsn = "default";
1109 }
1110 else /* if you want tracing, you must use a DSN */
1111 {
1112 setopterr |= _iodbcdm_settracing( hdbc,
1113 (char*)dsn, SQL_NTS );
1114 }
1115
1116 if( drv == NULL || drv[0] == '\0' )
1117 {
1118 drv = _iodbcdm_getkeyvalbydsn( dsn, SQL_NTS, "Driver",
1119 drvbuf, sizeof(drvbuf));
1120 }
1121
1122 if( drv == NULL )
1123 {
1124 PUSHSQLERR( pdbc->herr, en_IM002 );
1125
1126 return SQL_ERROR;
1127 }
1128
1129 retcode = _iodbcdm_driverload( drv, hdbc );
1130
1131 switch( retcode )
1132 {
1133 case SQL_SUCCESS:
1134 break;
1135
1136 case SQL_SUCCESS_WITH_INFO:
1137 setopterr = SQL_ERROR;
1138 /* unsuccessed in calling driver's
1139 * SQLSetConnectOption() to set login
1140 * timeout.
1141 */
1142 break;
1143
1144 default:
1145 return retcode;
1146 }
1147 }
1148 else if( pdbc->state != en_dbc_needdata )
1149 {
1150 PUSHSQLERR ( pdbc->herr, en_08002 );
1151
1152 return SQL_ERROR;
1153 }
1154
1155 hproc = _iodbcdm_getproc( hdbc, en_BrowseConnect);
1156
1157 if( hproc == SQL_NULL_HPROC )
1158 {
1159 _iodbcdm_driverunload( hdbc );
1160
1161 pdbc->state = en_dbc_allocated;
1162
1163 PUSHSQLERR( pdbc->herr, en_IM001 );
1164
1165 return SQL_ERROR;
1166 }
1167
1168 CALL_DRIVER ( hdbc, retcode, hproc, en_BrowseConnect, (
1169 pdbc->dhdbc, hwnd,
1170 szConnStrIn, cbConnStrIn,
1171 szConnStrOut, cbConnStrOutMax,
1172 pcbConnStrOut ) )
1173
1174 #if 0
1175 retcode = hproc(pdbc->dhdbc, hwnd,
1176 szConnStrIn, cbConnStrIn,
1177 szConnStrOut, cbConnStrOutMax,
1178 pcbConnStrOut );
1179 #endif
1180
1181 switch( retcode )
1182 {
1183 case SQL_SUCCESS:
1184 case SQL_SUCCESS_WITH_INFO:
1185 pdbc->state = en_dbc_connected;
1186 setopterr |= _iodbcdm_dbcdelayset( hdbc );
1187 if( setopterr != SQL_SUCCESS )
1188 {
1189 retcode = SQL_SUCCESS_WITH_INFO;
1190 }
1191 break;
1192
1193 case SQL_NEED_DATA:
1194 pdbc->state = en_dbc_needdata;
1195 break;
1196
1197 case SQL_ERROR:
1198 pdbc->state = en_dbc_allocated;
1199 /* but the driver will not unloaded
1200 * to allow application retrive err
1201 * message from driver
1202 */
1203 break;
1204
1205 default:
1206 break;
1207 }
1208
1209 return retcode;
1210 }
1211
1212 RETCODE SQL_API SQLDisconnect ( HDBC hdbc )
1213 {
1214 DBC_t FAR* pdbc = (DBC_t*)hdbc;
1215 STMT_t FAR* pstmt;
1216 RETCODE retcode;
1217 HPROC hproc;
1218
1219 int sqlstat = en_00000;
1220
1221 if( hdbc == SQL_NULL_HDBC )
1222 {
1223 return SQL_INVALID_HANDLE;
1224 }
1225
1226 /* check hdbc state */
1227 if ( pdbc->state == en_dbc_allocated )
1228 {
1229 sqlstat = en_08003;
1230 }
1231
1232 /* check stmt(s) state */
1233 for( pstmt = (STMT_t FAR*)pdbc->hstmt;
1234 pstmt != NULL && sqlstat == en_00000;
1235 pstmt = (STMT_t FAR*)pstmt->next )
1236 {
1237 if( pstmt->state >= en_stmt_needdata
1238 || pstmt->asyn_on != en_NullProc )
1239 /* In this case one need to call
1240 * SQLCancel() first */
1241 {
1242 sqlstat = en_S1010;
1243 }
1244 }
1245
1246 if( sqlstat == en_00000 )
1247 {
1248 hproc = _iodbcdm_getproc( hdbc, en_Disconnect );
1249
1250 if( hproc == SQL_NULL_HPROC )
1251 {
1252 sqlstat = en_IM001;
1253 }
1254 }
1255
1256 if( sqlstat != en_00000 )
1257 {
1258 PUSHSQLERR ( pdbc->herr, sqlstat );
1259
1260 return SQL_ERROR;
1261 }
1262
1263 CALL_DRIVER ( hdbc, retcode, hproc, en_Disconnect, (
1264 pdbc->dhdbc ) )
1265
1266 #if 0
1267 retcode = hproc( pdbc->dhdbc );
1268 #endif
1269
1270 if( retcode == SQL_SUCCESS
1271 || retcode == SQL_SUCCESS_WITH_INFO )
1272 {
1273 /* diff from MS specs. We disallow
1274 * driver SQLDisconnect() return
1275 * SQL_SUCCESS_WITH_INFO and post
1276 * error message.
1277 */
1278 retcode = SQL_SUCCESS;
1279 }
1280 else
1281 {
1282 return retcode;
1283 }
1284
1285 /* free all statement handle(s) on this connection */
1286 for(;pdbc->hstmt;)
1287 {
1288 _iodbcdm_dropstmt( pdbc->hstmt );
1289 }
1290
1291 #if 0
1292 retcode = _iodbcdm_driverunload( hdbc );
1293 #endif
1294
1295 /* state transition */
1296 if( retcode == SQL_SUCCESS )
1297 {
1298 pdbc->state = en_dbc_allocated;
1299 }
1300
1301 return retcode;
1302 }
1303
1304 RETCODE SQL_API SQLNativeSql(
1305 HDBC hdbc,
1306 UCHAR FAR* szSqlStrIn,
1307 SDWORD cbSqlStrIn,
1308 UCHAR FAR* szSqlStr,
1309 SDWORD cbSqlStrMax,
1310 SDWORD FAR* pcbSqlStr )
1311 {
1312 DBC_t FAR* pdbc = (DBC_t FAR*)hdbc;
1313 HPROC hproc;
1314 int sqlstat = en_00000;
1315 RETCODE retcode;
1316
1317 if( hdbc == SQL_NULL_HDBC )
1318 {
1319 return SQL_INVALID_HANDLE;
1320 }
1321
1322 /* check argument */
1323 if( szSqlStrIn == NULL )
1324 {
1325 sqlstat = en_S1009;
1326 }
1327 else if( cbSqlStrIn < 0
1328 && cbSqlStrIn != SQL_NTS )
1329 {
1330 sqlstat = en_S1090;
1331 }
1332
1333 if( sqlstat != en_00000 )
1334 {
1335 PUSHSQLERR ( pdbc->herr, sqlstat );
1336
1337 return SQL_ERROR;
1338 }
1339
1340 /* check state */
1341 if( pdbc->state <= en_dbc_needdata )
1342 {
1343 PUSHSQLERR ( pdbc->herr, en_08003 );
1344
1345 return SQL_ERROR;
1346 }
1347
1348 /* call driver */
1349 hproc = _iodbcdm_getproc( hdbc, en_NativeSql );
1350
1351 if( hproc == SQL_NULL_HPROC )
1352 {
1353 PUSHSQLERR ( pdbc->herr, en_IM001 );
1354
1355 return SQL_ERROR;
1356 }
1357
1358 CALL_DRIVER ( hdbc, retcode, hproc, en_NativeSql, (
1359 pdbc->dhdbc,
1360 szSqlStrIn,
1361 cbSqlStrIn,
1362 szSqlStr,
1363 cbSqlStrMax,
1364 pcbSqlStr ) )
1365
1366 #if 0
1367 retcode = hproc(pdbc->dhdbc,
1368 szSqlStrIn,
1369 cbSqlStrIn,
1370 szSqlStr,
1371 cbSqlStrMax,
1372 pcbSqlStr );
1373 #endif
1374
1375 return retcode;
1376 }