summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnatol Belski <ab@php.net>2016-02-24 12:00:26 +0100
committerAnatol Belski <ab@php.net>2016-02-24 12:03:21 +0100
commitc9778d3eb9a4531dad5df21a0c9b3ddcb9807eff (patch)
treeacf9f2cc10d8deb25b9e6e98da76fea462b05778
parent6e1862d0a864d49b577403ae22fd4a9b64370168 (diff)
downloadphp-git-c9778d3eb9a4531dad5df21a0c9b3ddcb9807eff.tar.gz
Port patch and test for bug #47803 to 7.0
See ff115e285ab5192f9e12a43d5dc202d88b01f1ea
-rw-r--r--ext/odbc/php_odbc.c41
-rw-r--r--ext/odbc/php_odbc_includes.h8
-rw-r--r--ext/odbc/tests/bug47803.phpt185
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,
&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);
}
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);
+
+?>