diff options
Diffstat (limited to 'src/interfaces/odbc/environ.c')
-rw-r--r-- | src/interfaces/odbc/environ.c | 416 |
1 files changed, 416 insertions, 0 deletions
diff --git a/src/interfaces/odbc/environ.c b/src/interfaces/odbc/environ.c new file mode 100644 index 00000000000..b7d808476fe --- /dev/null +++ b/src/interfaces/odbc/environ.c @@ -0,0 +1,416 @@ +
+/* Module: environ.c
+ *
+ * Description: This module contains routines related to
+ * the environment, such as storing connection handles,
+ * and returning errors.
+ *
+ * Classes: EnvironmentClass (Functions prefix: "EN_")
+ *
+ * API functions: SQLAllocEnv, SQLFreeEnv, SQLError
+ *
+ * Comments: See "notice.txt" for copyright and license information.
+ *
+ */
+ +#include "environ.h" +#include "connection.h" +#include "statement.h" +#include <stdlib.h> +#include <malloc.h> + +/* The one instance of the handles */ +ConnectionClass *conns[MAX_CONNECTIONS]; + + +RETCODE SQL_API SQLAllocEnv(HENV FAR *phenv) +{ +mylog("**** in SQLAllocEnv ** \n"); + + *phenv = (HENV) EN_Constructor(); + if ( ! *phenv) { + *phenv = SQL_NULL_HENV; + return SQL_ERROR; + } + + mylog("** exit SQLAllocEnv: phenv = %u **\n", *phenv); + return SQL_SUCCESS; +} + +RETCODE SQL_API SQLFreeEnv(HENV henv) +{ +EnvironmentClass *env = (EnvironmentClass *) henv; + +mylog("**** in SQLFreeEnv: env = %u ** \n", env); + + if (env && EN_Destructor(env)) { + mylog(" ok\n"); + return SQL_SUCCESS; + } + + mylog(" error\n"); + return SQL_ERROR; +} + +// Returns the next SQL error information. + +RETCODE SQL_API SQLError( + HENV henv, + HDBC hdbc, + HSTMT hstmt, + UCHAR FAR *szSqlState, + SDWORD FAR *pfNativeError, + UCHAR FAR *szErrorMsg, + SWORD cbErrorMsgMax, + SWORD FAR *pcbErrorMsg) +{ +char *msg; +int status; + + mylog("**** SQLError: henv=%u, hdbc=%u, hstmt=%u\n", henv, hdbc, hstmt); + + if (SQL_NULL_HSTMT != hstmt) { + // CC: return an error of a hstmt + StatementClass *stmt = (StatementClass *) hstmt; + + if (NULL == stmt) + return SQL_INVALID_HANDLE; + + if (SC_get_error(stmt, &status, &msg)) { + mylog("SC_get_error: status = %d, msg = #%s#\n", status, msg); + if (NULL == msg) { + if (NULL != szSqlState) + strcpy(szSqlState, "00000"); + if (NULL != pcbErrorMsg) + *pcbErrorMsg = 0; + if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0)) + szErrorMsg[0] = '\0'; + + return SQL_NO_DATA_FOUND; + } + if (NULL != pcbErrorMsg) + *pcbErrorMsg = (SWORD)strlen(msg); + + if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0)) + strncpy_null(szErrorMsg, msg, cbErrorMsgMax); + + if (NULL != pfNativeError) + *pfNativeError = status; + + if (NULL != szSqlState) + + switch (status) { + // now determine the SQLSTATE to be returned + case STMT_TRUNCATED: + strcpy(szSqlState, "01004"); + // data truncated + break; + case STMT_INFO_ONLY: + strcpy(szSqlState, "00000"); + // just information that is returned, no error + break; + case STMT_EXEC_ERROR: + strcpy(szSqlState, "08S01"); + // communication link failure + break; + case STMT_STATUS_ERROR: + case STMT_SEQUENCE_ERROR: + strcpy(szSqlState, "S1010"); + // Function sequence error + break; + case STMT_NO_MEMORY_ERROR: + strcpy(szSqlState, "S1001"); + // memory allocation failure + break; + case STMT_COLNUM_ERROR: + strcpy(szSqlState, "S1002"); + // invalid column number + break; + case STMT_NO_STMTSTRING: + strcpy(szSqlState, "S1001"); + // having no stmtstring is also a malloc problem + break; + case STMT_ERROR_TAKEN_FROM_BACKEND: + strcpy(szSqlState, "S1000"); + // general error + break; + case STMT_INTERNAL_ERROR: + strcpy(szSqlState, "S1000"); + // general error + break; + case STMT_NOT_IMPLEMENTED_ERROR: + strcpy(szSqlState, "S1C00"); // == 'driver not capable' + break; + case STMT_OPTION_OUT_OF_RANGE_ERROR: + strcpy(szSqlState, "S1092"); + break; + case STMT_BAD_PARAMETER_NUMBER_ERROR: + strcpy(szSqlState, "S1093"); + break; + case STMT_INVALID_COLUMN_NUMBER_ERROR: + strcpy(szSqlState, "S1002"); + break; + case STMT_RESTRICTED_DATA_TYPE_ERROR: + strcpy(szSqlState, "07006"); + break; + case STMT_INVALID_CURSOR_STATE_ERROR: + strcpy(szSqlState, "24000"); + break; + case STMT_OPTION_VALUE_CHANGED: + strcpy(szSqlState, "01S02"); + break; + default: + strcpy(szSqlState, "S1000"); + // also a general error + break; + } + + mylog(" szSqlState = '%s', szError='%s'\n", szSqlState, szErrorMsg); + + } else { + if (NULL != szSqlState) + strcpy(szSqlState, "00000"); + if (NULL != pcbErrorMsg) + *pcbErrorMsg = 0; + if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0)) + szErrorMsg[0] = '\0'; + + mylog(" returning NO_DATA_FOUND\n"); + return SQL_NO_DATA_FOUND; + } + return SQL_SUCCESS; + + } else if (SQL_NULL_HDBC != hdbc) { + ConnectionClass *conn = (ConnectionClass *) hdbc; + + mylog("calling CC_get_error\n"); + if (CC_get_error(conn, &status, &msg)) { + mylog("CC_get_error: status = %d, msg = #%s#\n", status, msg); + if (NULL == msg) { + if (NULL != szSqlState) + strcpy(szSqlState, "00000"); + if (NULL != pcbErrorMsg) + *pcbErrorMsg = 0; + if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0)) + szErrorMsg[0] = '\0'; + + return SQL_NO_DATA_FOUND; + } + + if (NULL != pcbErrorMsg) + *pcbErrorMsg = (SWORD)strlen(msg); + if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0)) + strncpy_null(szErrorMsg, msg, cbErrorMsgMax); + if (NULL != pfNativeError) + *pfNativeError = status; + + if (NULL != szSqlState) + switch(status) { + case CONN_INIREAD_ERROR: + strcpy(szSqlState, "IM002"); + // data source not found + break; + case CONN_OPENDB_ERROR: + strcpy(szSqlState, "08001"); + // unable to connect to data source + break;
+ case CONN_INVALID_AUTHENTICATION:
+ case CONN_AUTH_TYPE_UNSUPPORTED:
+ strcpy(szSqlState, "28000");
+ break; + case CONN_STMT_ALLOC_ERROR: + strcpy(szSqlState, "S1001"); + // memory allocation failure + break; + case CONN_IN_USE: + strcpy(szSqlState, "S1000"); + // general error + break; + case CONN_UNSUPPORTED_OPTION: + strcpy(szSqlState, "IM001"); + // driver does not support this function + case CONN_INVALID_ARGUMENT_NO: + strcpy(szSqlState, "S1009"); + // invalid argument value + break; + case CONN_TRANSACT_IN_PROGRES: + strcpy(szSqlState, "S1010"); + // when the user tries to switch commit mode in a transaction + // -> function sequence error + break; + case CONN_NO_MEMORY_ERROR: + strcpy(szSqlState, "S1001"); + break; + case CONN_NOT_IMPLEMENTED_ERROR: + strcpy(szSqlState, "S1C00"); + break; + default: + strcpy(szSqlState, "S1000"); + // general error + break; + } + + } else { + mylog("CC_Get_error returned nothing.\n"); + if (NULL != szSqlState) + strcpy(szSqlState, "00000"); + if (NULL != pcbErrorMsg) + *pcbErrorMsg = 0; + if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0)) + szErrorMsg[0] = '\0'; + + return SQL_NO_DATA_FOUND; + } + return SQL_SUCCESS; + + } else if (SQL_NULL_HENV != henv) { + EnvironmentClass *env = (EnvironmentClass *)henv; + if(EN_get_error(env, &status, &msg)) { + mylog("EN_get_error: status = %d, msg = #%s#\n", status, msg); + if (NULL == msg) { + if (NULL != szSqlState) + strcpy(szSqlState, "00000"); + if (NULL != pcbErrorMsg) + *pcbErrorMsg = 0; + if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0)) + szErrorMsg[0] = '\0'; + + return SQL_NO_DATA_FOUND; + } + + if (NULL != pcbErrorMsg) + *pcbErrorMsg = (SWORD)strlen(msg); + if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0)) + strncpy_null(szErrorMsg, msg, cbErrorMsgMax); + if (NULL != pfNativeError) + *pfNativeError = status; + + if(szSqlState) { + switch(status) { + case ENV_ALLOC_ERROR: + // memory allocation failure + strcpy(szSqlState, "S1001"); + break; + default: + strcpy(szSqlState, "S1000"); + // general error + break; + } + } + } else { + if (NULL != szSqlState) + strcpy(szSqlState, "00000"); + if (NULL != pcbErrorMsg) + *pcbErrorMsg = 0; + if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0)) + szErrorMsg[0] = '\0'; + + return SQL_NO_DATA_FOUND; + } + + return SQL_SUCCESS; + } + + if (NULL != szSqlState) + strcpy(szSqlState, "00000"); + if (NULL != pcbErrorMsg) + *pcbErrorMsg = 0; + if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0)) + szErrorMsg[0] = '\0'; + + return SQL_NO_DATA_FOUND; +} + + +/*********************************************************************/ +/* + * EnvironmentClass implementation + */ + + + +EnvironmentClass +*EN_Constructor(void) +{ +EnvironmentClass *rv; + + rv = (EnvironmentClass *) malloc(sizeof(EnvironmentClass)); + if( rv) { + rv->errormsg = 0; + rv->errornumber = 0; + } +
+ return rv; +} + + +char +EN_Destructor(EnvironmentClass *self) +{ +int lf; +char rv = 1; + + mylog("in EN_Destructor, self=%u\n", self); + + // the error messages are static strings distributed throughout + // the source--they should not be freed + + /* Free any connections belonging to this environment */ + for (lf = 0; lf < MAX_CONNECTIONS; lf++) {
+ if (conns[lf] && conns[lf]->henv == self) + rv = rv && CC_Destructor(conns[lf]); + } + + mylog("exit EN_Destructor: rv = %d\n", rv); + return rv; +} + +char +EN_get_error(EnvironmentClass *self, int *number, char **message) +{ + if(self && self->errormsg && self->errornumber) { + *message = self->errormsg; + *number = self->errornumber; + self->errormsg = 0; + self->errornumber = 0; + return 1; + } else { + return 0; + } +} + +char +EN_add_connection(EnvironmentClass *self, ConnectionClass *conn) +{ +int i; +
+mylog("EN_add_connection: self = %u, conn = %u\n", self, conn);
+ + for (i = 0; i < MAX_CONNECTIONS; i++) { + if ( ! conns[i]) {
+ conn->henv = self; + conns[i] = conn;
+
+ mylog(" added at i =%d, conn->henv = %u, conns[i]->henv = %u\n",
+ i, conn->henv, conns[i]->henv);
+ + return TRUE; + } + } + + return FALSE; +} + +char +EN_remove_connection(EnvironmentClass *self, ConnectionClass *conn) +{ +int i; + + for (i = 0; i < MAX_CONNECTIONS; i++) + if (conns[i] == conn && conns[i]->status != CONN_EXECUTING) { + conns[i] = NULL; + return TRUE; + } + + return FALSE; +} |