RETCODE SQL_API SQLFreeConnect (HDBC hdbc) { GENV_t FAR *genv; DBC_t FAR *pdbc = (DBC_t FAR *) hdbc; DBC_t FAR *tpdbc; if (hdbc == SQL_NULL_HDBC) { return SQL_INVALID_HANDLE; } /* check state */ if (pdbc->state != en_dbc_allocated) { PUSHSQLERR (pdbc->herr, en_S1010); return SQL_ERROR; } genv = (GENV_t FAR *) pdbc->genv; for (tpdbc = (DBC_t FAR *) genv->hdbc; tpdbc != NULL; tpdbc = tpdbc->next) { if (pdbc == tpdbc) { genv->hdbc = pdbc->next; break; } if (pdbc == tpdbc->next) { tpdbc->next = pdbc->next; break; } } /* free this dbc */ _iodbcdm_driverunload (pdbc); _iodbcdm_freesqlerrlist (pdbc->herr); if (pdbc->tfile) { MEM_FREE (pdbc->tfile); } SQLSetConnectOption (pdbc, SQL_OPT_TRACE, SQL_OPT_TRACE_OFF); MEM_FREE (pdbc); return SQL_SUCCESS; }
/* - Load driver share library( or increase its reference count * if it has already been loaded by another active connection) * - Call driver's SQLAllocEnv() (for the first reference only) * - Call driver's SQLAllocConnect() * - Call driver's SQLSetConnectOption() (set login time out) * - Increase the bookkeeping reference count */ static RETCODE _iodbcdm_driverload ( char FAR * path, HDBC hdbc) { DBC_t FAR *pdbc = (DBC_t FAR *) hdbc; GENV_t FAR *genv; ENV_t FAR *penv = NULL; HDLL hdll; HPROC hproc; RETCODE retcode = SQL_SUCCESS; int sqlstat = en_00000; if (path == NULL || path[0] == '\0') { PUSHSQLERR (pdbc->herr, en_IM002); return SQL_ERROR; } if (hdbc == SQL_NULL_HDBC || pdbc->genv == SQL_NULL_HENV) { return SQL_INVALID_HANDLE; } genv = (GENV_t FAR *) pdbc->genv; /* This will either load the driver dll or increase its reference count */ hdll = _iodbcdm_dllopen ((char FAR *) path); if (hdll == SQL_NULL_HDLL) { PUSHSYSERR (pdbc->herr, _iodbcdm_dllerror ()); PUSHSQLERR (pdbc->herr, en_IM003); return SQL_ERROR; } penv = (ENV_t FAR *) (pdbc->henv); if (penv != NULL) { if (penv->hdll != hdll) { _iodbcdm_driverunload (hdbc); } else { /* * this will not unload the driver but only decrease its internal * reference count */ _iodbcdm_dllclose (hdll); } } if (penv == NULL) { /* * find out whether this dll has already been loaded on another * connection */ for (penv = (ENV_t FAR *) genv->henv; penv != NULL; penv = (ENV_t FAR *) penv->next) { if (penv->hdll == hdll) { /* * this will not unload the driver but only decrease its internal * reference count */ _iodbcdm_dllclose (hdll); break; } } if (penv == NULL) /* no connection attaching with this dll */ { int i; /* create a new dll env instance */ penv = (ENV_t FAR *) MEM_ALLOC (sizeof (ENV_t)); if (penv == NULL) { _iodbcdm_dllclose (hdll); PUSHSQLERR (pdbc->herr, en_S1001); return SQL_ERROR; } for (i = 0; i < SQL_EXT_API_LAST + 1; i++) { (penv->dllproc_tab)[i] = SQL_NULL_HPROC; } pdbc->henv = penv; penv->hdll = hdll; /* call driver's SQLAllocHandle() or SQLAllocEnv() */ #if (ODBCVER >= 0x0300) hproc = _iodbcdm_getproc (hdbc, en_AllocHandle); if (hproc) { CALL_DRIVER (hdbc, retcode, hproc, en_AllocHandle, (SQL_HANDLE_ENV, SQL_NULL_HANDLE, &(penv->dhenv))) } else /* try driver's SQLAllocEnv() */ #endif { hproc = _iodbcdm_getproc (hdbc, en_AllocEnv); if (hproc == SQL_NULL_HPROC) { sqlstat = en_IM004; } else { CALL_DRIVER (hdbc, retcode, hproc, en_AllocEnv, (&(penv->dhenv))) } } if (retcode == SQL_ERROR) { sqlstat = en_IM004; } if (sqlstat != en_00000) { _iodbcdm_dllclose (hdll); MEM_FREE (penv); PUSHSQLERR (pdbc->herr, en_IM004); return SQL_ERROR; } /* insert into dll env list */ penv->next = (ENV_t FAR *) genv->henv; genv->henv = penv; /* initiate this new env entry */ penv->refcount = 0; /* we will increase it after * driver's SQLAllocConnect() * success */ }