diff options
author | tdonovan <tdonovan@13f79535-47bb-0310-9956-ffa450edef68> | 2008-10-24 12:22:57 +0000 |
---|---|---|
committer | tdonovan <tdonovan@13f79535-47bb-0310-9956-ffa450edef68> | 2008-10-24 12:22:57 +0000 |
commit | eaaf88eed137e94a13702ef9d0fcad2096786892 (patch) | |
tree | f6eb29eaa073e0dead80d9cf2450aa8d5188e6c8 | |
parent | 0eedd015e920ac5d5f0f7032f130d31f5ca5f065 (diff) | |
download | libapr-util-eaaf88eed137e94a13702ef9d0fcad2096786892.tar.gz |
dbd odbc driver - don't segfault when params is NULL.
Empty params are now OK. connect will fail with a more useful message.
Changed transaction processing to be like the other dbd drivers.
After an error in a transaction, all queries/selects will fail until
end_transaction unless mode is set to APR_DBD_TRANSACTION_IGNORE_ERRORS
git-svn-id: http://svn.apache.org/repos/asf/apr/apr-util/trunk@707611 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | dbd/apr_dbd_odbc.c | 67 |
1 files changed, 52 insertions, 15 deletions
diff --git a/dbd/apr_dbd_odbc.c b/dbd/apr_dbd_odbc.c index 9f0e1703..4797d12c 100644 --- a/dbd/apr_dbd_odbc.c +++ b/dbd/apr_dbd_odbc.c @@ -808,6 +808,11 @@ static apr_status_t odbc_parse_params(apr_pool_t *pool, const char *params, *nattrs = 0; seps = DEFAULTSEPS; name[nparams] = apr_strtok(apr_pstrdup(pool, params), seps, &last); + + /* no params is OK here - let connect return a more useful error msg */ + if (!name[nparams]) + return SQL_SUCCESS; + do { if (last[strspn(last, seps)] == CSINGLEQUOTE) { last += strspn(last, seps); @@ -899,8 +904,11 @@ static void check_error(apr_dbd_t *dbc, const char *step, SQLRETURN rc, default : { res = "unrecognized SQL return code"; } } /* these two returns are expected during normal execution */ - if (rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA) - dbc->can_commit = 0; + if (rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA + && dbc->can_commit != APR_DBD_TRANSACTION_IGNORE_ERRORS) + { + dbc->can_commit = APR_DBD_TRANSACTION_ROLLBACK; + } p = dbc->lastError; end = p + sizeof(dbc->lastError); dbc->lasterrorcode = rc; @@ -923,6 +931,15 @@ static void check_error(apr_dbd_t *dbc, const char *step, SQLRETURN rc, } } +static APR_INLINE int odbc_check_rollback(apr_dbd_t *handle) +{ + if (handle->can_commit == APR_DBD_TRANSACTION_ROLLBACK) { + handle->lasterrorcode = SQL_ERROR; + strcpy(handle->lastError, "[dbd_odbc] Rollback pending "); + return 1; + } + return 0; +} /* * public functions per DBD driver API */ @@ -1043,6 +1060,7 @@ static apr_dbd_t* odbc_open(apr_pool_t *pool, const char *params, const char **e handle->defaultBufferSize = defaultBufferSize; CHECK_ERROR(handle, "SQLConnect", rc, SQL_HANDLE_DBC, handle->dbc); handle->default_transaction_mode = 0; + handle->can_commit = APR_DBD_TRANSACTION_IGNORE_ERRORS; SQLGetInfo(hdbc, SQL_DEFAULT_TXN_ISOLATION, &(handle->default_transaction_mode), sizeof(int), NULL); handle->transaction_mode = handle->default_transaction_mode; @@ -1117,8 +1135,8 @@ static int odbc_start_transaction(apr_pool_t *pool, apr_dbd_t *handle, *trans = apr_palloc(pool, sizeof(apr_dbd_transaction_t)); (*trans)->dbc = handle->dbc; (*trans)->apr_dbd = handle; - handle->can_commit = 1; } + handle->can_commit = APR_DBD_TRANSACTION_COMMIT; return APR_FROM_SQL_RESULT(rc); }; @@ -1127,8 +1145,10 @@ static int odbc_start_transaction(apr_pool_t *pool, apr_dbd_t *handle, static int odbc_end_transaction(apr_dbd_transaction_t *trans) { SQLRETURN rc; + int action = (trans->apr_dbd->can_commit != APR_DBD_TRANSACTION_ROLLBACK) + ? SQL_COMMIT : SQL_ROLLBACK; - rc = SQLEndTran(SQL_HANDLE_DBC, trans->dbc, SQL_COMMIT); + rc = SQLEndTran(SQL_HANDLE_DBC, trans->dbc, action); CHECK_ERROR(trans->apr_dbd, "SQLEndTran", rc, SQL_HANDLE_DBC, trans->dbc); if SQL_SUCCEEDED(rc) { rc = SQLSetConnectAttr(trans->dbc, SQL_ATTR_AUTOCOMMIT, @@ -1136,6 +1156,7 @@ static int odbc_end_transaction(apr_dbd_transaction_t *trans) CHECK_ERROR(trans->apr_dbd, "SQLSetConnectAttr (SQL_ATTR_AUTOCOMMIT)", rc, SQL_HANDLE_DBC, trans->dbc); } + trans->apr_dbd->can_commit = APR_DBD_TRANSACTION_IGNORE_ERRORS; return APR_FROM_SQL_RESULT(rc); } @@ -1146,6 +1167,9 @@ static int odbc_query(apr_dbd_t *handle, int *nrows, const char *statement) SQLHANDLE hstmt = NULL; size_t len = strlen(statement); + if (odbc_check_rollback(handle)) + return APR_EGENERAL; + rc = SQLAllocHandle(SQL_HANDLE_STMT, handle->dbc, &hstmt); CHECK_ERROR(handle, "SQLAllocHandle (STMT)", rc, SQL_HANDLE_DBC, handle->dbc); @@ -1174,6 +1198,9 @@ static int odbc_select(apr_pool_t *pool, apr_dbd_t *handle, apr_dbd_prepared_t *stmt; size_t len = strlen(statement); + if (odbc_check_rollback(handle)) + return APR_EGENERAL; + rc = SQLAllocHandle(SQL_HANDLE_STMT, handle->dbc, &hstmt); CHECK_ERROR(handle, "SQLAllocHandle (STMT)", rc, SQL_HANDLE_DBC, handle->dbc); @@ -1357,6 +1384,9 @@ static int odbc_prepare(apr_pool_t * pool, apr_dbd_t * handle, SQLRETURN rc; size_t len = strlen(query); + if (odbc_check_rollback(handle)) + return APR_EGENERAL; + *statement = apr_pcalloc(pool, sizeof(apr_dbd_prepared_t)); (*statement)->dbc = handle->dbc; (*statement)->apr_dbd = handle; @@ -1382,6 +1412,9 @@ static int odbc_pquery(apr_pool_t * pool, apr_dbd_t * handle, int *nrows, SQLRETURN rc = SQL_SUCCESS; int i, argp; + if (odbc_check_rollback(handle)) + return APR_EGENERAL; + for (i = argp = 0; i < statement->nargs && SQL_SUCCEEDED(rc); i++) { rc = odbc_bind_param(pool, statement, i + 1, statement->types[i], &argp, (const void **) args, TEXTMODE); @@ -1419,6 +1452,9 @@ int odbc_pselect(apr_pool_t * pool, apr_dbd_t * handle, SQLRETURN rc = SQL_SUCCESS; int i, argp; + if (odbc_check_rollback(handle)) + return APR_EGENERAL; + if (random) { rc = SQLSetStmtAttr(statement->stmt, SQL_ATTR_CURSOR_SCROLLABLE, (SQLPOINTER) SQL_SCROLLABLE, 0); @@ -1482,26 +1518,21 @@ static const char *odbc_get_name(const apr_dbd_results_t * res, int col) /** transaction_mode_get: get the mode of transaction **/ static int odbc_transaction_mode_get(apr_dbd_transaction_t * trans) { - return (int) trans->apr_dbd->transaction_mode; + return (int) trans->apr_dbd->can_commit; } /** transaction_mode_set: set the mode of transaction **/ static int odbc_transaction_mode_set(apr_dbd_transaction_t * trans, int mode) { - SQLRETURN rc; - - int legal = (SQL_TXN_READ_UNCOMMITTED | SQL_TXN_READ_COMMITTED - | SQL_TXN_REPEATABLE_READ | SQL_TXN_SERIALIZABLE); + int legal = ( APR_DBD_TRANSACTION_IGNORE_ERRORS + | APR_DBD_TRANSACTION_COMMIT + | APR_DBD_TRANSACTION_ROLLBACK); if ((mode & legal) != mode) return APR_EGENERAL; - trans->apr_dbd->transaction_mode = mode; - rc = SQLSetConnectAttr(trans->dbc, SQL_ATTR_TXN_ISOLATION, - (void *) mode, 0); - CHECK_ERROR(trans->apr_dbd, "SQLSetConnectAttr (SQL_ATTR_TXN_ISOLATION)", - rc, SQL_HANDLE_DBC, trans->dbc); - return APR_FROM_SQL_RESULT(rc); + trans->apr_dbd->can_commit = mode; + return APR_SUCCESS; } /** pbquery: query using a prepared statement + binary args **/ @@ -1511,6 +1542,9 @@ static int odbc_pbquery(apr_pool_t * pool, apr_dbd_t * handle, int *nrows, SQLRETURN rc = SQL_SUCCESS; int i, argp; + if (odbc_check_rollback(handle)) + return APR_EGENERAL; + for (i = argp = 0; i < statement->nargs && SQL_SUCCEEDED(rc); i++) rc = odbc_bind_param(pool, statement, i + 1, statement->types[i], &argp, args, BINARYMODE); @@ -1537,6 +1571,9 @@ static int odbc_pbselect(apr_pool_t * pool, apr_dbd_t * handle, SQLRETURN rc = SQL_SUCCESS; int i, argp; + if (odbc_check_rollback(handle)) + return APR_EGENERAL; + if (random) { rc = SQLSetStmtAttr(statement->stmt, SQL_ATTR_CURSOR_SCROLLABLE, (SQLPOINTER) SQL_SCROLLABLE, 0); |