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