📄 connection.c
字号:
/* Module: connection.c * * Description: This module contains routines related to * connecting to and disconnecting from the Postgres DBMS. * * Classes: ConnectionClass (Functions prefix: "CC_") * * API functions: SQLAllocConnect, SQLConnect, SQLDisconnect, SQLFreeConnect, * SQLBrowseConnect(NI) * * Comments: See "notice.txt" for copyright and license information. * */#include "environ.h"#include "connection.h"#include "socket.h"#include "statement.h"#include "qresult.h"#include "lobj.h"#include "dlg_specific.h"#include <stdio.h>#include <string.h>#ifdef WIN32#include <odbcinst.h>#endif#define STMT_INCREMENT 16 /* how many statement holders to allocate at a time */extern GLOBAL_VALUES globals;RETCODE SQL_API SQLAllocConnect( HENV henv, HDBC FAR *phdbc){EnvironmentClass *env = (EnvironmentClass *)henv;ConnectionClass *conn;static char *func="SQLAllocConnect"; mylog( "%s: entering...\n", func); conn = CC_Constructor(); mylog("**** %s: henv = %u, conn = %u\n", func, henv, conn); if( ! conn) { env->errormsg = "Couldn't allocate memory for Connection object."; env->errornumber = ENV_ALLOC_ERROR; *phdbc = SQL_NULL_HDBC; EN_log_error(func, "", env); return SQL_ERROR; } if ( ! EN_add_connection(env, conn)) { env->errormsg = "Maximum number of connections exceeded."; env->errornumber = ENV_ALLOC_ERROR; CC_Destructor(conn); *phdbc = SQL_NULL_HDBC; EN_log_error(func, "", env); return SQL_ERROR; } *phdbc = (HDBC) conn; return SQL_SUCCESS;}// - - - - - - - - -RETCODE SQL_API SQLConnect( HDBC hdbc, UCHAR FAR *szDSN, SWORD cbDSN, UCHAR FAR *szUID, SWORD cbUID, UCHAR FAR *szAuthStr, SWORD cbAuthStr){ConnectionClass *conn = (ConnectionClass *) hdbc;ConnInfo *ci;static char *func = "SQLConnect"; mylog( "%s: entering...\n", func); if ( ! conn) { CC_log_error(func, "", NULL); return SQL_INVALID_HANDLE; } ci = &conn->connInfo; make_string(szDSN, cbDSN, ci->dsn); /* get the values for the DSN from the registry */ getDSNinfo(ci, CONN_OVERWRITE); /* override values from DSN info with UID and authStr(pwd) This only occurs if the values are actually there. */ make_string(szUID, cbUID, ci->username); make_string(szAuthStr, cbAuthStr, ci->password); /* fill in any defaults */ getDSNdefaults(ci); qlog("conn = %u, %s(DSN='%s', UID='%s', PWD='%s')\n", conn, func, ci->dsn, ci->username, ci->password); if ( CC_connect(conn, FALSE) <= 0) { // Error messages are filled in CC_log_error(func, "Error on CC_connect", conn); return SQL_ERROR; } mylog( "%s: returning...\n", func); return SQL_SUCCESS;}// - - - - - - - - -RETCODE SQL_API SQLBrowseConnect( HDBC hdbc, UCHAR FAR *szConnStrIn, SWORD cbConnStrIn, UCHAR FAR *szConnStrOut, SWORD cbConnStrOutMax, SWORD FAR *pcbConnStrOut){static char *func="SQLBrowseConnect"; mylog( "%s: entering...\n", func); return SQL_SUCCESS;}// - - - - - - - - -/* Drop any hstmts open on hdbc and disconnect from database */RETCODE SQL_API SQLDisconnect( HDBC hdbc){ConnectionClass *conn = (ConnectionClass *) hdbc;static char *func = "SQLDisconnect"; mylog( "%s: entering...\n", func); if ( ! conn) { CC_log_error(func, "", NULL); return SQL_INVALID_HANDLE; } qlog("conn=%u, %s\n", conn, func); if (conn->status == CONN_EXECUTING) { conn->errornumber = CONN_IN_USE; conn->errormsg = "A transaction is currently being executed"; CC_log_error(func, "", conn); return SQL_ERROR; } mylog("%s: about to CC_cleanup\n", func); /* Close the connection and free statements */ CC_cleanup(conn); mylog("%s: done CC_cleanup\n", func); mylog("%s: returning...\n", func); return SQL_SUCCESS;}// - - - - - - - - -RETCODE SQL_API SQLFreeConnect( HDBC hdbc){ConnectionClass *conn = (ConnectionClass *) hdbc;static char *func = "SQLFreeConnect"; mylog( "%s: entering...\n", func); mylog("**** in %s: hdbc=%u\n", func, hdbc); if ( ! conn) { CC_log_error(func, "", NULL); return SQL_INVALID_HANDLE; } /* Remove the connection from the environment */ if ( ! EN_remove_connection(conn->henv, conn)) { conn->errornumber = CONN_IN_USE; conn->errormsg = "A transaction is currently being executed"; CC_log_error(func, "", conn); return SQL_ERROR; } CC_Destructor(conn); mylog("%s: returning...\n", func); return SQL_SUCCESS;}/*** IMPLEMENTATION CONNECTION CLASS**/ConnectionClass *CC_Constructor(){ConnectionClass *rv; rv = (ConnectionClass *)malloc(sizeof(ConnectionClass)); if (rv != NULL) { rv->henv = NULL; /* not yet associated with an environment */ rv->errormsg = NULL; rv->errornumber = 0; rv->errormsg_created = FALSE; rv->status = CONN_NOT_CONNECTED; rv->transact_status = CONN_IN_AUTOCOMMIT; // autocommit by default memset(&rv->connInfo, 0, sizeof(ConnInfo)); rv->sock = SOCK_Constructor(); if ( ! rv->sock) return NULL; rv->stmts = (StatementClass **) malloc( sizeof(StatementClass *) * STMT_INCREMENT); if ( ! rv->stmts) return NULL; memset(rv->stmts, 0, sizeof(StatementClass *) * STMT_INCREMENT); rv->num_stmts = STMT_INCREMENT; rv->lobj_type = PG_TYPE_LO; rv->ntables = 0; rv->col_info = NULL; rv->translation_option = 0; rv->translation_handle = NULL; rv->DataSourceToDriver = NULL; rv->DriverToDataSource = NULL; /* Initialize statement options to defaults */ /* Statements under this conn will inherit these options */ InitializeStatementOptions(&rv->stmtOptions); } return rv;}charCC_Destructor(ConnectionClass *self){ mylog("enter CC_Destructor, self=%u\n", self); if (self->status == CONN_EXECUTING) return 0; CC_cleanup(self); /* cleanup socket and statements */ mylog("after CC_Cleanup\n"); /* Free up statement holders */ if (self->stmts) { free(self->stmts); self->stmts = NULL; } mylog("after free statement holders\n"); /* Free cached table info */ if (self->col_info) { int i; for (i = 0; i < self->ntables; i++) { if (self->col_info[i]->result) /* Free the SQLColumns result structure */ QR_Destructor(self->col_info[i]->result); free(self->col_info[i]); } free(self->col_info); } free(self); mylog("exit CC_Destructor\n"); return 1;}/* Return how many cursors are opened on this connection */intCC_cursor_count(ConnectionClass *self){StatementClass *stmt;int i, count = 0; mylog("CC_cursor_count: self=%u, num_stmts=%d\n", self, self->num_stmts); for (i = 0; i < self->num_stmts; i++) { stmt = self->stmts[i]; if (stmt && stmt->result && stmt->result->cursor) count++; } mylog("CC_cursor_count: returning %d\n", count); return count;}void CC_clear_error(ConnectionClass *self){ self->errornumber = 0; self->errormsg = NULL; self->errormsg_created = FALSE;}// Used to cancel a transaction// We are almost always in the middle of a transaction.charCC_abort(ConnectionClass *self){QResultClass *res; if ( CC_is_in_trans(self)) { res = NULL; mylog("CC_abort: sending ABORT!\n"); res = CC_send_query(self, "ABORT", NULL); CC_set_no_trans(self); if (res != NULL) QR_Destructor(res); else return FALSE; } return TRUE;}/* This is called by SQLDisconnect also */charCC_cleanup(ConnectionClass *self){int i;StatementClass *stmt; if (self->status == CONN_EXECUTING) return FALSE; mylog("in CC_Cleanup, self=%u\n", self); // Cancel an ongoing transaction // We are always in the middle of a transaction, // even if we are in auto commit. if (self->sock) CC_abort(self); mylog("after CC_abort\n"); /* This actually closes the connection to the dbase */ if (self->sock) { SOCK_Destructor(self->sock); self->sock = NULL; } mylog("after SOCK destructor\n"); /* Free all the stmts on this connection */ for (i = 0; i < self->num_stmts; i++) { stmt = self->stmts[i]; if (stmt) { stmt->hdbc = NULL; /* prevent any more dbase interactions */ SC_Destructor(stmt); self->stmts[i] = NULL; } } /* Check for translation dll */#ifdef WIN32 if ( self->translation_handle) { FreeLibrary (self->translation_handle); self->translation_handle = NULL; }#endif mylog("exit CC_Cleanup\n"); return TRUE;}intCC_set_translation (ConnectionClass *self){#ifdef WIN32 if (self->translation_handle != NULL) { FreeLibrary (self->translation_handle); self->translation_handle = NULL; } if (self->connInfo.translation_dll[0] == 0) return TRUE; self->translation_option = atoi (self->connInfo.translation_option); self->translation_handle = LoadLibrary (self->connInfo.translation_dll); if (self->translation_handle == NULL) { self->errornumber = CONN_UNABLE_TO_LOAD_DLL; self->errormsg = "Could not load the translation DLL."; return FALSE; } self->DataSourceToDriver = (DataSourceToDriverProc) GetProcAddress (self->translation_handle, "SQLDataSourceToDriver"); self->DriverToDataSource = (DriverToDataSourceProc) GetProcAddress (self->translation_handle, "SQLDriverToDataSource"); if (self->DataSourceToDriver == NULL || self->DriverToDataSource == NULL) { self->errornumber = CONN_UNABLE_TO_LOAD_DLL; self->errormsg = "Could not find translation DLL functions."; return FALSE; }#endif return TRUE;}char CC_connect(ConnectionClass *self, char do_password){StartupPacket sp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -