Index: dbd/apr_dbd.c =================================================================== --- dbd/apr_dbd.c (revision 668348) +++ dbd/apr_dbd.c (revision 719450) @@ -101,6 +101,7 @@ /* deprecate in 2.0 - permit implicit initialization */ apu_dso_init(pool); #endif + drivers = apr_hash_make(pool); #if APR_HAS_THREADS @@ -109,6 +110,7 @@ #endif #if !APU_DSO_BUILD + /* Load statically-linked drivers: */ #if APU_HAVE_MYSQL DRIVER_LOAD("mysql", apr_dbd_mysql_driver, pool); @@ -182,18 +184,16 @@ #endif apr_snprintf(symname, sizeof(symname), "apr_dbd_%s_driver", name); rv = apu_dso_load(&symbol, modname, symname, pool); - if (rv != APR_SUCCESS) { /* APR_EDSOOPEN or APR_ESYMNOTFOUND? */ - if (rv == APR_EINIT) { /* previously loaded?!? */ - name = apr_pstrdup(pool, name); - apr_hash_set(drivers, name, APR_HASH_KEY_STRING, *driver); - rv = APR_SUCCESS; + if (rv == APR_SUCCESS || rv == APR_EINIT) { /* previously loaded?!? */ + *driver = symbol; + name = apr_pstrdup(pool, name); + apr_hash_set(drivers, name, APR_HASH_KEY_STRING, *driver); + rv = APR_SUCCESS; + if ((*driver)->init) { + (*driver)->init(pool); } goto unlock; } - *driver = symbol; - if ((*driver)->init) { - (*driver)->init(pool); - } name = apr_pstrdup(pool, name); apr_hash_set(drivers, name, APR_HASH_KEY_STRING, *driver); Index: dbd/apr_dbd_mysql.c =================================================================== --- dbd/apr_dbd_mysql.c (revision 679235) +++ dbd/apr_dbd_mysql.c (revision 747626) @@ -25,6 +25,16 @@ #include <ctype.h> #include <stdlib.h> +#ifdef HAVE_MY_GLOBAL_H +#include <my_global.h> +#elif defined(HAVE_MYSQL_MY_GLOBAL_H) +#include <mysql/my_global.h> +#endif +#ifdef HAVE_MY_SYS_H +#include <my_sys.h> +#elif defined(HAVE_MYSQL_MY_SYS_H) +#include <mysql/my_sys.h> +#endif #ifdef HAVE_MYSQL_H #include <mysql.h> #include <errmsg.h> Index: dbd/apr_dbd_odbc.c =================================================================== --- dbd/apr_dbd_odbc.c (revision 669063) +++ dbd/apr_dbd_odbc.c (revision 747632) @@ -500,9 +500,9 @@ SQLRETURN rc; SQLSMALLINT baseType, cType; void *ptr; - SQLUINTEGER len; - SQLINTEGER *indicator; - static SQLINTEGER nullValue = SQL_NULL_DATA; + SQLULEN len; + SQLLEN *indicator; + static SQLLEN nullValue = SQL_NULL_DATA; static SQLSMALLINT inOut = SQL_PARAM_INPUT; /* only input params */ /* bind a NULL data value */ @@ -522,7 +522,7 @@ /* LOBs */ if (IS_LOB(cType)) { ptr = (void *) args[*argp]; - len = (SQLUINTEGER) * (apr_size_t *) args[*argp + 1]; + len = (SQLULEN) * (apr_size_t *) args[*argp + 1]; cType = (IS_CLOB(cType)) ? SQL_C_CHAR : SQL_C_DEFAULT; (*argp) += 4; /* LOBs consume 4 args (last two are unused) */ } @@ -534,7 +534,7 @@ case SQL_TIME: case SQL_TIMESTAMP: ptr = (void *) args[*argp]; - len = (SQLUINTEGER) strlen(ptr); + len = (SQLULEN) strlen(ptr); break; case SQL_TINYINT: ptr = apr_palloc(pool, sizeof(unsigned char)); @@ -619,7 +619,7 @@ apr_size_t *len, apr_read_type_e block) { SQLRETURN rc; - SQLINTEGER len_indicator; + SQLLEN len_indicator; SQLSMALLINT type; odbc_bucket *bd = (odbc_bucket *) e->data; apr_bucket *nxt; @@ -666,8 +666,8 @@ * We try to handle both interpretations. */ *len = (len_indicator > bufsize - && len_indicator >= (SQLINTEGER) e->start) - ? (len_indicator - (SQLINTEGER) e->start) : len_indicator; + && len_indicator >= (SQLLEN) e->start) + ? (len_indicator - (SQLLEN) e->start) : len_indicator; eos = 1; } @@ -731,7 +731,7 @@ const SQLSMALLINT sqltype) { SQLRETURN rc; - SQLINTEGER indicator; + SQLLEN indicator; int state = row->res->colstate[col]; int options = row->res->apr_dbd->dboptions; @@ -808,7 +808,13 @@ *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 { + /* XXX: segfault on last=NULL, assumption from above we have parms */ if (last[strspn(last, seps)] == CSINGLEQUOTE) { last += strspn(last, seps); seps=SSINGLEQUOTE; @@ -899,8 +905,11 @@ 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 +932,15 @@ } } +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 */ @@ -1011,7 +1029,7 @@ err_step="SQLSetConnectAttr (from DBD Parameters)"; err_htype = SQL_HANDLE_DBC; err_h = hdbc; - rc = SQLSetConnectAttr(hdbc, attrs[i], (void *) attrvals[i], 0); + rc = SQLSetConnectAttr(hdbc, attrs[i], (SQLPOINTER) attrvals[i], 0); } } if (SQL_SUCCEEDED(rc)) { @@ -1043,6 +1061,7 @@ 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; @@ -1101,8 +1120,8 @@ SQLRETURN rc = SQL_SUCCESS; if (handle->transaction_mode) { - rc = SQLSetConnectAttr(handle->dbc, SQL_ATTR_TXN_ISOLATION, (void *) - handle->transaction_mode, 0); + rc = SQLSetConnectAttr(handle->dbc, SQL_ATTR_TXN_ISOLATION, + (SQLPOINTER) handle->transaction_mode, 0); CHECK_ERROR(handle, "SQLSetConnectAttr (SQL_ATTR_TXN_ISOLATION)", rc, SQL_HANDLE_DBC, handle->dbc); } @@ -1117,8 +1136,8 @@ *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 +1146,10 @@ 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 +1157,7 @@ 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 +1168,9 @@ 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); @@ -1156,7 +1181,10 @@ CHECK_ERROR(handle, "SQLExecDirect", rc, SQL_HANDLE_STMT, hstmt); if SQL_SUCCEEDED(rc) { - rc = SQLRowCount(hstmt, (SQLINTEGER *) nrows); + SQLLEN rowcount; + + rc = SQLRowCount(hstmt, &rowcount); + *nrows = (int) rowcount; CHECK_ERROR(handle, "SQLRowCount", rc, SQL_HANDLE_STMT, hstmt); } @@ -1174,6 +1202,9 @@ 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); @@ -1215,7 +1246,7 @@ static int odbc_num_tuples(apr_dbd_results_t *res) { SQLRETURN rc; - SQLINTEGER nrows; + SQLLEN nrows; rc = SQLRowCount(res->stmt, &nrows); CHECK_ERROR(res->apr_dbd, "SQLRowCount", rc, SQL_HANDLE_STMT, res->stmt); @@ -1357,6 +1388,9 @@ 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 +1416,9 @@ 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); @@ -1392,7 +1429,10 @@ statement->stmt); } if (SQL_SUCCEEDED(rc)) { - rc = SQLRowCount(statement->stmt, (SQLINTEGER *) nrows); + SQLLEN rowcount; + + rc = SQLRowCount(statement->stmt, &rowcount); + *nrows = (int) rowcount; CHECK_ERROR(handle, "SQLRowCount", rc, SQL_HANDLE_STMT, statement->stmt); } @@ -1419,6 +1459,9 @@ 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); @@ -1464,7 +1507,7 @@ SQLRETURN rc; char buffer[MAX_COLUMN_NAME]; SQLSMALLINT colnamelength, coltype, coldecimal, colnullable; - SQLUINTEGER colsize; + SQLULEN colsize; if (col >= res->ncols) return NULL; /* bogus column number */ @@ -1482,26 +1525,21 @@ /** 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 = ( APR_DBD_TRANSACTION_IGNORE_ERRORS + | APR_DBD_TRANSACTION_COMMIT + | APR_DBD_TRANSACTION_ROLLBACK); - int legal = (SQL_TXN_READ_UNCOMMITTED | SQL_TXN_READ_COMMITTED - | SQL_TXN_REPEATABLE_READ | SQL_TXN_SERIALIZABLE); - 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 +1549,9 @@ 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); @@ -1521,7 +1562,10 @@ statement->stmt); } if (SQL_SUCCEEDED(rc)) { - rc = SQLRowCount(statement->stmt, (SQLINTEGER *) nrows); + SQLLEN rowcount; + + rc = SQLRowCount(statement->stmt, &rowcount); + *nrows = (int) rowcount; CHECK_ERROR(handle, "SQLRowCount", rc, SQL_HANDLE_STMT, statement->stmt); } @@ -1537,6 +1581,9 @@ 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); Index: dbd/apr_dbd_freetds.c =================================================================== --- dbd/apr_dbd_freetds.c (revision 669058) +++ dbd/apr_dbd_freetds.c (revision 744001) @@ -36,7 +36,13 @@ #include "apr_pools.h" #include "apr_dbd_internal.h" +#ifdef HAVE_FREETDS_SYBDB_H +#include <freetds/sybdb.h> +#endif +#ifdef HAVE_SYBDB_H #include <sybdb.h> +#endif + #include <stdio.h> #include <sys/types.h> #include <regex.h>