]> granicus.if.org Git - php/commitdiff
Port patch and test for bug #47803 to 7.0
authorAnatol Belski <ab@php.net>
Wed, 24 Feb 2016 11:00:26 +0000 (12:00 +0100)
committerAnatol Belski <ab@php.net>
Wed, 24 Feb 2016 11:03:21 +0000 (12:03 +0100)
See ff115e285ab5192f9e12a43d5dc202d88b01f1ea

ext/odbc/php_odbc.c
ext/odbc/php_odbc_includes.h
ext/odbc/tests/bug47803.phpt [new file with mode: 0644]

index a91d7b783d7e6030ea8f247fd140a41efda48d8c..d835dfb9a08a6704da718fcb34748da1d3e5722c 100644 (file)
@@ -445,6 +445,9 @@ static void _free_odbc_result(zend_resource *rsrc)
                         * zend_list_delete(res->conn_ptr->id);
                         */
                }
+               if (res->param_info) {
+                       efree(res->param_info);
+               }
                efree(res);
        }
 }
@@ -1184,6 +1187,7 @@ PHP_FUNCTION(odbc_prepare)
        odbc_result *result = NULL;
        odbc_connection *conn;
        RETCODE rc;
+       int i;
 #ifdef HAVE_SQL_EXTENDED_FETCH
        SQLUINTEGER      scrollopts;
 #endif
@@ -1199,6 +1203,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) {
@@ -1255,6 +1260,20 @@ PHP_FUNCTION(odbc_prepare)
        Z_ADDREF_P(pv_conn);
        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;
+               }
+       }
+
        RETURN_RES(zend_register_resource(result, le_result));
 }
 /* }}} */
@@ -1275,9 +1294,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;
@@ -1337,22 +1354,10 @@ PHP_FUNCTION(odbc_execute)
                                RETURN_FALSE;
                        }
                        
-                       rc = SQLDescribeParam(result->stmt, (SQLUSMALLINT)i, &sqltype, &precision, &scale, &nullable);
                        params[i-1].vallen = Z_STRLEN_P(tmp);
                        params[i-1].fp = -1;
-                       if (rc == SQL_ERROR) {
-                               odbc_sql_error(result->conn_ptr, result->stmt, "SQLDescribeParam");
-                               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;
@@ -1399,7 +1404,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 *)(intptr_t)params[i-1].fp, 0,
                                                                          &params[i-1].vallen);
                        } else {
@@ -1411,7 +1416,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_P(tmp), 0,
                                                                          &params[i-1].vallen);
                        }
index dad7ff1c9553557109745d1e1e5c26789f596326..fa525ed4adc7e4b0cedf3171bcb471dcc50c73f2 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 {
        zend_long longreadlen;
        int binmode;
        int fetched;
+       odbc_param_info * param_info;
        odbc_connection *conn_ptr;
 } odbc_result;
 
diff --git a/ext/odbc/tests/bug47803.phpt b/ext/odbc/tests/bug47803.phpt
new file mode 100644 (file)
index 0000000..9a2600d
--- /dev/null
@@ -0,0 +1,185 @@
+--TEST--
+Bug #47803 Executing prepared statements is succesfull only for the first two statements
+--SKIPIF--
+<?php include 'skipif.inc'; ?>
+--FILE--
+<?php
+
+include dirname(__FILE__) . "/config.inc";
+
+$create_table = "CREATE TABLE FOO(
+               [PAR_ID] [int] NOT NULL,
+               [PAR_INT] [int] NULL,
+               [PAR_CHR] [varchar](500) NULL
+)";
+
+$inserts = "INSERT INTO FOO
+           ([PAR_ID]
+           ,[PAR_INT]
+           ,[PAR_CHR])
+     VALUES
+        (1,14,''),
+               (2,30,''),
+               (3,7,''),
+               (4,7,''),
+               (5,0,''),
+               (6,0,''),
+               (7,20130901,''),
+               (8,20140201,''),
+               (9,20140201,''),
+               (10,20140620,''),
+               (11,221,'')";
+
+
+date_default_timezone_set('Europe/Warsaw');
+
+$link = odbc_connect($dsn, $user, $pass);
+
+odbc_exec($link, 'CREATE DATABASE odbcTEST');
+odbc_exec($link, $create_table);
+odbc_exec($link, $inserts);
+
+$upd_params = array(
+       array('id'=>1, 'name'=>'test 1'),
+       array('id'=>2, 'name'=>'test 2'),
+       array('id'=>3, 'name'=>'test 3'),
+       array('id'=>4, 'name'=>'test 4'),
+       array('id'=>5, 'name'=>'test 5'),
+       array('id'=>10, 'name'=>'test 10'),
+       array('id'=>9, 'name'=>'test 9'),
+       array('id'=>8, 'name'=>'test 8'),
+       array('id'=>7, 'name'=>'test 7'),
+       array('id'=>6, 'name'=>'test 6'),
+);
+$sql = "UPDATE FOO
+     SET [PAR_CHR] = ?
+     WHERE [PAR_ID] = ?";
+$result = odbc_prepare($link, $sql);
+if (!$result) {
+       print ('[sql] prep: '.$sql);
+       goto out;
+}
+foreach ($upd_params as &$k) {
+       if(!odbc_execute($result, array($k['name'], $k['id']))) {
+               print ('[sql] exec: '."array({$k['name']}, {$k['id']})");
+               goto out;
+       }
+}
+odbc_free_result($result);
+
+$sql = "SELECT * FROM FOO WHERE [PAR_ID] = ?";
+$result = odbc_prepare($link, $sql);
+if (!$result) {
+       print ('[sql] prep: '.$sql);
+       goto out;
+}
+foreach ($upd_params as $k) { 
+       if(!odbc_execute($result, array($k['id']))) {
+               print ('[sql] exec: '."array({$k['id']})");
+               goto out;
+       }
+       while (($r = odbc_fetch_array($result)) !== false) {
+               var_dump($r);
+       }
+}
+
+out:
+if ($result) odbc_free_result($result);
+odbc_close($link);
+
+?>
+==DONE==
+--EXPECT--
+array(3) {
+  ["PAR_ID"]=>
+  string(1) "1"
+  ["PAR_INT"]=>
+  string(2) "14"
+  ["PAR_CHR"]=>
+  string(6) "test 1"
+}
+array(3) {
+  ["PAR_ID"]=>
+  string(1) "2"
+  ["PAR_INT"]=>
+  string(2) "30"
+  ["PAR_CHR"]=>
+  string(6) "test 2"
+}
+array(3) {
+  ["PAR_ID"]=>
+  string(1) "3"
+  ["PAR_INT"]=>
+  string(1) "7"
+  ["PAR_CHR"]=>
+  string(6) "test 3"
+}
+array(3) {
+  ["PAR_ID"]=>
+  string(1) "4"
+  ["PAR_INT"]=>
+  string(1) "7"
+  ["PAR_CHR"]=>
+  string(6) "test 4"
+}
+array(3) {
+  ["PAR_ID"]=>
+  string(1) "5"
+  ["PAR_INT"]=>
+  string(1) "0"
+  ["PAR_CHR"]=>
+  string(6) "test 5"
+}
+array(3) {
+  ["PAR_ID"]=>
+  string(2) "10"
+  ["PAR_INT"]=>
+  string(8) "20140620"
+  ["PAR_CHR"]=>
+  string(7) "test 10"
+}
+array(3) {
+  ["PAR_ID"]=>
+  string(1) "9"
+  ["PAR_INT"]=>
+  string(8) "20140201"
+  ["PAR_CHR"]=>
+  string(6) "test 9"
+}
+array(3) {
+  ["PAR_ID"]=>
+  string(1) "8"
+  ["PAR_INT"]=>
+  string(8) "20140201"
+  ["PAR_CHR"]=>
+  string(6) "test 8"
+}
+array(3) {
+  ["PAR_ID"]=>
+  string(1) "7"
+  ["PAR_INT"]=>
+  string(8) "20130901"
+  ["PAR_CHR"]=>
+  string(6) "test 7"
+}
+array(3) {
+  ["PAR_ID"]=>
+  string(1) "7"
+  ["PAR_INT"]=>
+  string(8) "20130901"
+  ["PAR_CHR"]=>
+  string(6) "test 7"
+}
+==DONE==
+--CLEAN--
+<?php
+include 'config.inc';
+
+$conn = odbc_connect($dsn, $user, $pass);
+
+odbc_exec($conn, 'DROP TABLE FOO');
+odbc_exec($conn, 'DROP DATABASE odbcTEST');
+
+odbc_close($conn);
+
+?>