]> granicus.if.org Git - php/commitdiff
Fixed bug #47803
authorAnatol Belski <ab@php.net>
Wed, 24 Feb 2016 10:40:35 +0000 (11:40 +0100)
committerAnatol Belski <ab@php.net>
Wed, 24 Feb 2016 10:40:35 +0000 (11:40 +0100)
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.

ext/odbc/php_odbc.c
ext/odbc/php_odbc_includes.h

index 33ef0c229ad0aa20d748e530653c75d314d3ce5a..bde6c1ed147eb659831d36928f8940169387cb84 100644 (file)
@@ -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;i<result->numparams;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,
                                                                          &params[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,
                                                                          &params[i-1].vallen);
                        }
index 8ba8d7cc80b7e9f4fc0292b31622252b19c9e387..7dd6167d438a534184728fe8478adfe76902f462 100644 (file)
@@ -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;