From: Anatol Belski Date: Wed, 24 Feb 2016 10:40:35 +0000 (+0100) Subject: Fixed bug #47803 X-Git-Tag: php-5.6.20RC1~33 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ff115e285ab5192f9e12a43d5dc202d88b01f1ea;p=php Fixed bug #47803 Executing prepared statements is succesfull only for the first two statements The reworked patch descends to the bug #69526 which is fixed by this as well. The broken logic in the current code was, that SQLDescribeParam was executed in odbc_execute every time. This piece is now moved into odbc_prepare and the results are carried on in an additional structure. Since the ext/odbc headers are not being currently installed and the corresponding structs like odbc_result are not used outside ext/odbc, the binary compatibility persists. Executing SQLDescribeParam only once in odbc_prepare is also an optimization as the filds usually won't change that fast and thus requestind the descriptions on every execution is not required. --- diff --git a/ext/odbc/php_odbc.c b/ext/odbc/php_odbc.c index 33ef0c229a..bde6c1ed14 100644 --- a/ext/odbc/php_odbc.c +++ b/ext/odbc/php_odbc.c @@ -442,6 +442,9 @@ static void _free_odbc_result(zend_rsrc_list_entry *rsrc TSRMLS_DC) * zend_list_delete(res->conn_ptr->id); */ } + if (res->param_info) { + efree(res->param_info); + } efree(res); } } @@ -1183,6 +1186,7 @@ PHP_FUNCTION(odbc_prepare) odbc_result *result = NULL; odbc_connection *conn; RETCODE rc; + int i; #ifdef HAVE_SQL_EXTENDED_FETCH SQLUINTEGER scrollopts; #endif @@ -1196,6 +1200,7 @@ PHP_FUNCTION(odbc_prepare) result = (odbc_result *)ecalloc(1, sizeof(odbc_result)); result->numparams = 0; + result->param_info = NULL; rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt)); if (rc == SQL_INVALID_HANDLE) { @@ -1252,6 +1257,19 @@ PHP_FUNCTION(odbc_prepare) zend_list_addref(conn->id); result->conn_ptr = conn; result->fetched = 0; + + result->param_info = (odbc_param_info *) safe_emalloc(sizeof(odbc_param_info), result->numparams, 0); + for (i=0;inumparams;i++) { + rc = SQLDescribeParam(result->stmt, (SQLUSMALLINT)(i+1), &result->param_info[i].sqltype, &result->param_info[i].precision, + &result->param_info[i].scale, &result->param_info[i].nullable); + if (rc == SQL_ERROR) { + odbc_sql_error(result->conn_ptr, result->stmt, "SQLDescribeParameter"); + SQLFreeStmt(result->stmt, SQL_RESET_PARAMS); + efree(result->param_info); + efree(result); + RETURN_FALSE; + } + } ZEND_REGISTER_RESOURCE(return_value, result, le_result); } /* }}} */ @@ -1272,9 +1290,7 @@ PHP_FUNCTION(odbc_execute) params_t *params = NULL; char *filename; unsigned char otype; - SQLSMALLINT sqltype, ctype, scale; - SQLSMALLINT nullable; - SQLULEN precision; + SQLSMALLINT ctype; odbc_result *result; int numArgs, i, ne; RETCODE rc; @@ -1332,22 +1348,10 @@ PHP_FUNCTION(odbc_execute) RETURN_FALSE; } - rc = SQLDescribeParam(result->stmt, (SQLUSMALLINT)i, &sqltype, &precision, &scale, &nullable); params[i-1].vallen = Z_STRLEN_PP(tmp); params[i-1].fp = -1; - if (rc == SQL_ERROR) { - odbc_sql_error(result->conn_ptr, result->stmt, "SQLDescribeParameter"); - SQLFreeStmt(result->stmt, SQL_RESET_PARAMS); - for (i = 0; i < result->numparams; i++) { - if (params[i].fp != -1) { - close(params[i].fp); - } - } - efree(params); - RETURN_FALSE; - } - if (IS_SQL_BINARY(sqltype)) { + if (IS_SQL_BINARY(result->param_info[i-1].sqltype)) { ctype = SQL_C_BINARY; } else { ctype = SQL_C_CHAR; @@ -1394,7 +1398,7 @@ PHP_FUNCTION(odbc_execute) params[i-1].vallen = SQL_LEN_DATA_AT_EXEC(0); rc = SQLBindParameter(result->stmt, (SQLUSMALLINT)i, SQL_PARAM_INPUT, - ctype, sqltype, precision, scale, + ctype, result->param_info[i-1].sqltype, result->param_info[i-1].precision, result->param_info[i-1].scale, (void *)params[i-1].fp, 0, ¶ms[i-1].vallen); } else { @@ -1406,7 +1410,7 @@ PHP_FUNCTION(odbc_execute) } rc = SQLBindParameter(result->stmt, (SQLUSMALLINT)i, SQL_PARAM_INPUT, - ctype, sqltype, precision, scale, + ctype, result->param_info[i-1].sqltype, result->param_info[i-1].precision, result->param_info[i-1].scale, Z_STRVAL_PP(tmp), 0, ¶ms[i-1].vallen); } diff --git a/ext/odbc/php_odbc_includes.h b/ext/odbc/php_odbc_includes.h index 8ba8d7cc80..7dd6167d43 100644 --- a/ext/odbc/php_odbc_includes.h +++ b/ext/odbc/php_odbc_includes.h @@ -233,6 +233,13 @@ typedef struct odbc_result_value { SQLLEN coltype; } odbc_result_value; +typedef struct odbc_param_info { + SQLSMALLINT sqltype; + SQLSMALLINT scale; + SQLSMALLINT nullable; + SQLULEN precision; +} odbc_param_info; + typedef struct odbc_result { ODBC_SQL_STMT_T stmt; odbc_result_value *values; @@ -244,6 +251,7 @@ typedef struct odbc_result { long longreadlen; int binmode; int fetched; + odbc_param_info * param_info; odbc_connection *conn_ptr; } odbc_result;