diff options
author | Anatol Belski <ab@php.net> | 2016-02-24 12:00:26 +0100 |
---|---|---|
committer | Anatol Belski <ab@php.net> | 2016-02-24 12:03:21 +0100 |
commit | c9778d3eb9a4531dad5df21a0c9b3ddcb9807eff (patch) | |
tree | acf9f2cc10d8deb25b9e6e98da76fea462b05778 | |
parent | 6e1862d0a864d49b577403ae22fd4a9b64370168 (diff) | |
download | php-git-c9778d3eb9a4531dad5df21a0c9b3ddcb9807eff.tar.gz |
Port patch and test for bug #47803 to 7.0
See ff115e285ab5192f9e12a43d5dc202d88b01f1ea
-rw-r--r-- | ext/odbc/php_odbc.c | 41 | ||||
-rw-r--r-- | ext/odbc/php_odbc_includes.h | 8 | ||||
-rw-r--r-- | ext/odbc/tests/bug47803.phpt | 185 |
3 files changed, 216 insertions, 18 deletions
diff --git a/ext/odbc/php_odbc.c b/ext/odbc/php_odbc.c index a91d7b783d..d835dfb9a0 100644 --- a/ext/odbc/php_odbc.c +++ b/ext/odbc/php_odbc.c @@ -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, ¶ms[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, ¶ms[i-1].vallen); } diff --git a/ext/odbc/php_odbc_includes.h b/ext/odbc/php_odbc_includes.h index dad7ff1c95..fa525ed4ad 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 { 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 index 0000000000..9a2600dd18 --- /dev/null +++ b/ext/odbc/tests/bug47803.phpt @@ -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); + +?> |