Merge branch 'PHP-7.0' into PHP-7.1

This commit is contained in:
Christopher Jones 2016-10-17 12:40:54 +11:00
commit 23e2c356b7
8 changed files with 261 additions and 33 deletions

View file

@ -1387,6 +1387,11 @@ void php_oci_bind_hash_dtor(zval *data)
{ {
php_oci_bind *bind = (php_oci_bind *) Z_PTR_P(data); php_oci_bind *bind = (php_oci_bind *) Z_PTR_P(data);
if (!Z_ISUNDEF(bind->parameter)) {
zval_ptr_dtor(&bind->parameter);
ZVAL_UNDEF(&bind->parameter);
}
if (bind->array.elements) { if (bind->array.elements) {
efree(bind->array.elements); efree(bind->array.elements);
bind->array.elements = NULL; bind->array.elements = NULL;

View file

@ -110,7 +110,7 @@ PHP_FUNCTION(oci_bind_by_name)
zval *bind_var = NULL; zval *bind_var = NULL;
php_oci_statement *statement; php_oci_statement *statement;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsz/|ll", &z_statement, &name, &name_len, &bind_var, &maxlen, &type) == FAILURE) { if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsz|ll", &z_statement, &name, &name_len, &bind_var, &maxlen, &type) == FAILURE) {
return; return;
} }

View file

@ -1094,13 +1094,20 @@ int php_oci_bind_by_name(php_oci_statement *statement, char *name, size_t name_l
int mode = OCI_DATA_AT_EXEC; int mode = OCI_DATA_AT_EXEC;
sb4 value_sz = -1; sb4 value_sz = -1;
sword errstatus; sword errstatus;
zval *param = NULL;
if (!Z_ISREF_P(var)) {
param = var;
} else {
param = Z_REFVAL_P(var);
}
switch (type) { switch (type) {
case SQLT_NTY: case SQLT_NTY:
{ {
zval *tmp; zval *tmp;
if (Z_TYPE_P(var) != IS_OBJECT || (tmp = zend_hash_str_find(Z_OBJPROP_P(var), "collection", sizeof("collection")-1)) == NULL) { if (Z_TYPE_P(param) != IS_OBJECT || (tmp = zend_hash_str_find(Z_OBJPROP_P(param), "collection", sizeof("collection")-1)) == NULL) {
php_error_docref(NULL, E_WARNING, "Unable to find collection property"); php_error_docref(NULL, E_WARNING, "Unable to find collection property");
return 1; return 1;
} }
@ -1122,7 +1129,7 @@ int php_oci_bind_by_name(php_oci_statement *statement, char *name, size_t name_l
{ {
zval *tmp; zval *tmp;
if (Z_TYPE_P(var) != IS_OBJECT || (tmp = zend_hash_str_find(Z_OBJPROP_P(var), "descriptor", sizeof("descriptor")-1)) == NULL) { if (Z_TYPE_P(param) != IS_OBJECT || (tmp = zend_hash_str_find(Z_OBJPROP_P(param), "descriptor", sizeof("descriptor")-1)) == NULL) {
php_error_docref(NULL, E_WARNING, "Unable to find descriptor property"); php_error_docref(NULL, E_WARNING, "Unable to find descriptor property");
return 1; return 1;
} }
@ -1141,17 +1148,17 @@ int php_oci_bind_by_name(php_oci_statement *statement, char *name, size_t name_l
case SQLT_INT: case SQLT_INT:
case SQLT_NUM: case SQLT_NUM:
if (Z_TYPE_P(var) == IS_RESOURCE || Z_TYPE_P(var) == IS_OBJECT) { if (Z_TYPE_P(param) == IS_RESOURCE || Z_TYPE_P(param) == IS_OBJECT) {
php_error_docref(NULL, E_WARNING, "Invalid variable used for bind"); php_error_docref(NULL, E_WARNING, "Invalid variable used for bind");
return 1; return 1;
} }
convert_to_long(var); convert_to_long(param);
#if defined(OCI_MAJOR_VERSION) && (OCI_MAJOR_VERSION > 10) && \ #if defined(OCI_MAJOR_VERSION) && (OCI_MAJOR_VERSION > 10) && \
(defined(__x86_64__) || defined(__LP64__) || defined(_LP64) || defined(_WIN64)) (defined(__x86_64__) || defined(__LP64__) || defined(_LP64) || defined(_WIN64))
bind_data = (ub8 *)&Z_LVAL_P(var); bind_data = (ub8 *)&Z_LVAL_P(param);
value_sz = sizeof(ub8); value_sz = sizeof(ub8);
#else #else
bind_data = (ub4 *)&Z_LVAL_P(var); bind_data = (ub4 *)&Z_LVAL_P(param);
value_sz = sizeof(ub4); value_sz = sizeof(ub4);
#endif #endif
mode = OCI_DEFAULT; mode = OCI_DEFAULT;
@ -1162,18 +1169,18 @@ int php_oci_bind_by_name(php_oci_statement *statement, char *name, size_t name_l
case SQLT_LNG: case SQLT_LNG:
case SQLT_AFC: case SQLT_AFC:
case SQLT_CHR: /* SQLT_CHR is the default value when type was not specified */ case SQLT_CHR: /* SQLT_CHR is the default value when type was not specified */
if (Z_TYPE_P(var) == IS_RESOURCE || Z_TYPE_P(var) == IS_OBJECT) { if (Z_TYPE_P(param) == IS_RESOURCE || Z_TYPE_P(param) == IS_OBJECT) {
php_error_docref(NULL, E_WARNING, "Invalid variable used for bind"); php_error_docref(NULL, E_WARNING, "Invalid variable used for bind");
return 1; return 1;
} }
if (Z_TYPE_P(var) != IS_NULL) { if (Z_TYPE_P(param) != IS_NULL) {
convert_to_string(var); convert_to_string(param);
} }
if ((maxlength == -1) || (maxlength == 0)) { if ((maxlength == -1) || (maxlength == 0)) {
if (type == SQLT_LNG) { if (type == SQLT_LNG) {
value_sz = SB4MAXVAL; value_sz = SB4MAXVAL;
} else if (Z_TYPE_P(var) == IS_STRING) { } else if (Z_TYPE_P(param) == IS_STRING) {
value_sz = (sb4) Z_STRLEN_P(var); value_sz = (sb4) Z_STRLEN_P(param);
} else { } else {
/* Bug-72524: revert value_sz from PHP_OCI_PIECE_SIZE to 0. This restores PHP 5.6 behavior */ /* Bug-72524: revert value_sz from PHP_OCI_PIECE_SIZE to 0. This restores PHP 5.6 behavior */
value_sz = 0; value_sz = 0;
@ -1184,11 +1191,11 @@ int php_oci_bind_by_name(php_oci_statement *statement, char *name, size_t name_l
break; break;
case SQLT_RSET: case SQLT_RSET:
if (Z_TYPE_P(var) != IS_RESOURCE) { if (Z_TYPE_P(param) != IS_RESOURCE) {
php_error_docref(NULL, E_WARNING, "Invalid variable used for bind"); php_error_docref(NULL, E_WARNING, "Invalid variable used for bind");
return 1; return 1;
} }
PHP_OCI_ZVAL_TO_STATEMENT_EX(var, bind_statement); PHP_OCI_ZVAL_TO_STATEMENT_EX(param, bind_statement);
value_sz = sizeof(void*); value_sz = sizeof(void*);
oci_stmt = bind_statement->stmt; oci_stmt = bind_statement->stmt;
@ -1200,15 +1207,15 @@ int php_oci_bind_by_name(php_oci_statement *statement, char *name, size_t name_l
#if defined(OCI_MAJOR_VERSION) && OCI_MAJOR_VERSION >= 12 #if defined(OCI_MAJOR_VERSION) && OCI_MAJOR_VERSION >= 12
case SQLT_BOL: case SQLT_BOL:
if (Z_TYPE_P(var) == IS_RESOURCE || Z_TYPE_P(var) == IS_OBJECT) { if (Z_TYPE_P(param) == IS_RESOURCE || Z_TYPE_P(param) == IS_OBJECT) {
php_error_docref(NULL, E_WARNING, "Invalid variable used for bind"); php_error_docref(NULL, E_WARNING, "Invalid variable used for bind");
return 1; return 1;
} }
convert_to_boolean(var); convert_to_boolean(param);
bind_data = (zend_long *)&Z_LVAL_P(var); bind_data = (zend_long *)&Z_LVAL_P(param);
if (Z_TYPE_P(var) == IS_TRUE) if (Z_TYPE_P(param) == IS_TRUE)
*(zend_long *)bind_data = 1; *(zend_long *)bind_data = 1;
else if (Z_TYPE_P(var) == IS_FALSE) else if (Z_TYPE_P(param) == IS_FALSE)
*(zend_long *)bind_data = 0; *(zend_long *)bind_data = 0;
else { else {
php_error_docref(NULL, E_WARNING, "Invalid variable used for bind"); php_error_docref(NULL, E_WARNING, "Invalid variable used for bind");
@ -1234,6 +1241,10 @@ int php_oci_bind_by_name(php_oci_statement *statement, char *name, size_t name_l
if ((old_bind = zend_hash_str_find_ptr(statement->binds, name, name_len)) != NULL) { if ((old_bind = zend_hash_str_find_ptr(statement->binds, name, name_len)) != NULL) {
bindp = old_bind; bindp = old_bind;
if (!Z_ISUNDEF(bindp->parameter)) {
zval_ptr_dtor(&bindp->parameter);
ZVAL_UNDEF(&bindp->parameter);
}
} else { } else {
zend_string *zvtmp; zend_string *zvtmp;
zvtmp = zend_string_init(name, name_len, 0); zvtmp = zend_string_init(name, name_len, 0);
@ -1241,6 +1252,10 @@ int php_oci_bind_by_name(php_oci_statement *statement, char *name, size_t name_l
bindp = zend_hash_update_ptr(statement->binds, zvtmp, bindp); bindp = zend_hash_update_ptr(statement->binds, zvtmp, bindp);
zend_string_release(zvtmp); zend_string_release(zvtmp);
} }
/* Keep a copy of bound variable in the bind hash */
ZVAL_COPY(&bindp->parameter, var);
/* Make sure the minimum of value_sz is 1 to avoid ORA-3149 /* Make sure the minimum of value_sz is 1 to avoid ORA-3149
* when both in/out parameters are bound with empty strings * when both in/out parameters are bound with empty strings
*/ */
@ -1250,7 +1265,7 @@ int php_oci_bind_by_name(php_oci_statement *statement, char *name, size_t name_l
bindp->descriptor = oci_desc; bindp->descriptor = oci_desc;
bindp->statement = oci_stmt; bindp->statement = oci_stmt;
bindp->parent_statement = statement; bindp->parent_statement = statement;
bindp->zval = var; bindp->zval = param;
bindp->type = type; bindp->type = type;
/* Storing max length set in OCIBindByName() to check it later in /* Storing max length set in OCIBindByName() to check it later in
* php_oci_bind_in_callback() function to avoid ORA-1406 error while * php_oci_bind_in_callback() function to avoid ORA-1406 error while

View file

@ -46,12 +46,12 @@ Interoperability Support" (ID 207303.1) for details.
<active>no</active> <active>no</active>
</lead> </lead>
<date>2016-08-18</date> <date>2016-10-17</date>
<time>12:00:00</time> <time>12:00:00</time>
<version> <version>
<release>2.1.2</release> <release>2.1.3</release>
<api>2.1.2</api> <api>2.1.3</api>
</version> </version>
<stability> <stability>
<release>stable</release> <release>stable</release>
@ -60,8 +60,7 @@ Interoperability Support" (ID 207303.1) for details.
<license uri="http://www.php.net/license">PHP</license> <license uri="http://www.php.net/license">PHP</license>
<notes> <notes>
This version is for PHP 7 only. This version is for PHP 7 only.
Fixed invalid handle error with Implicit Result Sets Fixed bug #71148 (Bind reference overwritten on PHP 7)
Fixed bug #72524 (Binding null values triggers ORA-24816 error)
</notes> </notes>
<contents> <contents>
<dir name="/"> <dir name="/">
@ -469,6 +468,23 @@ Fixed bug #72524 (Binding null values triggers ORA-24816 error)
</extsrcrelease> </extsrcrelease>
<changelog> <changelog>
<release>
<version>
<release>2.1.2</release>
<api>2.1.2</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="http://www.php.net/license">PHP</license>
<notes>
This version is for PHP 7 only.
Fixed invalid handle error with Implicit Result Sets
Fixed bug #72524 (Binding null values triggers ORA-24816 error)
</notes>
</release>
<release> <release>
<version> <version>
<release>2.1.1</release> <release>2.1.1</release>

View file

@ -43,7 +43,7 @@
*/ */
#undef PHP_OCI8_VERSION #undef PHP_OCI8_VERSION
#endif #endif
#define PHP_OCI8_VERSION "2.1.2" #define PHP_OCI8_VERSION "2.1.3"
extern zend_module_entry oci8_module_entry; extern zend_module_entry oci8_module_entry;
#define phpext_oci8_ptr &oci8_module_entry #define phpext_oci8_ptr &oci8_module_entry

View file

@ -243,6 +243,7 @@ typedef struct {
typedef struct { typedef struct {
OCIBind *bind; /* bind handle */ OCIBind *bind; /* bind handle */
zval *zval; /* value */ zval *zval; /* value */
zval parameter; /* a copy of bound variable used for oci_bind_by_name */
dvoid *descriptor; /* used for binding of LOBS etc */ dvoid *descriptor; /* used for binding of LOBS etc */
OCIStmt *statement; /* used for binding REFCURSORs */ OCIStmt *statement; /* used for binding REFCURSORs */
php_oci_statement *parent_statement; /* pointer to the parent statement */ php_oci_statement *parent_statement; /* pointer to the parent statement */

View file

@ -0,0 +1,191 @@
--TEST--
Bug #71448 (Binding reference overwritten on php7)
--SKIPIF--
<?php
$target_dbs = array('oracledb' => true, 'timesten' => true); // test runs on these DBs
require(dirname(__FILE__).'/skipif.inc');
?>
--FILE--
<?php
require(dirname(__FILE__).'/connect.inc');
// Initialize
$stmtarray = array(
"CREATE OR REPLACE FUNCTION bindfunc(var1 varchar2, var2 varchar2)
RETURN varchar2
AS var3 VARCHAR2(20);
BEGIN
var3 := CONCAT(var1, var2);
RETURN var3;
END;",
"CREATE OR REPLACE PROCEDURE bindproc(var1 IN string, var2 IN string, var3 IN OUT string) IS
BEGIN
var3 := CONCAT(var1, var3);
var3 := CONCAT(var3, var2);
END;"
);
oci8_test_sql_execute($c, $stmtarray);
// Run test
function bindvar($stmt, $name, $var)
{
oci_bind_by_name($stmt, $name, $var);
}
// Test 1: Bind input parameter in a local function
$sql = "select :var1, :var2 from dual";
$cache1 = "INSTR1";
$cache2 = "INSTR2";
echo "Test 1: Bind input parameter in a local function\n";
$stmt = oci_parse($c, $sql);
bindvar($stmt, ':var1', $cache1);
bindvar($stmt, ':var2', $cache2);
oci_execute($stmt);
var_dump(oci_fetch_assoc($stmt));
oci_free_statement($stmt);
// Test 2: Bind output parameter in a local function
$sql = "begin :output1 := 'OUTSTR1'; :output2 := 'OUTSTR2'; end;";
$cache1 = "xxxxxx";
$cache2 = "xxxxxx";
echo "\nTest 2: Bind output parameter in a local function\n";
$stmt = oci_parse($c, $sql);
bindvar($stmt, ':output1', $cache1);
bindvar($stmt, ':output2', $cache2);
oci_execute($stmt);
var_dump($cache1);
var_dump($cache2);
oci_free_statement($stmt);
// Test 3: Bind output parameter within the same scope of execute
$sql = "begin :output1 := 'OUTSTR1'; :output2 := 'OUTSTR2'; end;";
$cache1 = "xxxxxx";
$cache2 = "xxxxxx";
echo "\nTest 3: Bind output parameter within the same scope of execute\n";
$stmt = oci_parse($c, $sql);
oci_bind_by_name($stmt, ":output1", $cache1);
oci_bind_by_name($stmt, ":output2", $cache2);
oci_execute($stmt);
var_dump($cache1);
var_dump($cache2);
oci_free_statement($stmt);
// Test 4: Bind output parameter within the same scope of execute
$sql= "begin :output := bindfunc(:var1, :var2); end;";
$cache1 = "STR1";
$cache2 = "STR2";
echo "\nTest 4: Bind output parameter within the same scope of execute\n";
$stmt = oci_parse($c, $sql);
oci_bind_by_name($stmt, ":var1", $cache1, -1);
oci_bind_by_name($stmt, ":var2", $cache2, -1);
oci_bind_by_name($stmt, ":output", $cache3, 100);
oci_execute($stmt);
var_dump($cache3);
// Test 5: Bind IN OUT parameter in a local function
$sql = "call bindproc(:var1, :var2, :var3)";
$cache1 = 'STR1';
$cache2 = 'STR2';
$cache3 = ' ';
echo "\nTest 5: Bind IN OUT parameter in a local function\n";
$stmt = oci_parse($c, $sql);
bindvar($stmt, ':var1', $cache1);
bindvar($stmt, ':var2', $cache2);
bindvar($stmt, ':var3', $cache3);
oci_execute($stmt);
var_dump($cache1);
var_dump($cache2);
var_dump($cache3);
oci_free_statement($stmt);
// Test 6: Bind IN OUT parameter within the same scope of execute
$sql = "call bindproc(:var1, :var2, :var3)";
$cache1 = 'STR1';
$cache2 = 'STR2';
$cache3 = ' ';
echo "\nTest 6: Bind IN OUT parameter within the same scope of execute\n";
$stmt = oci_parse($c, $sql);
oci_bind_by_name($stmt, ":var1", $cache1, -1);
oci_bind_by_name($stmt, ":var2", $cache2, -1);
oci_bind_by_name($stmt, ":var3", $cache3, 100);
oci_execute($stmt);
var_dump($cache1);
var_dump($cache2);
var_dump($cache3);
// Cleanup
$stmtarray = array(
"DROP FUNCTION bindfunc",
"DROP PROCEDURE bindproc"
);
oci8_test_sql_execute($c, $stmtarray);
?>
===DONE===
<?php exit(0); ?>
--EXPECT--
Test 1: Bind input parameter in a local function
array(2) {
[":VAR1"]=>
string(6) "INSTR1"
[":VAR2"]=>
string(6) "INSTR2"
}
Test 2: Bind output parameter in a local function
string(6) "xxxxxx"
string(6) "xxxxxx"
Test 3: Bind output parameter within the same scope of execute
string(7) "OUTSTR1"
string(7) "OUTSTR2"
Test 4: Bind output parameter within the same scope of execute
string(8) "STR1STR2"
Test 5: Bind IN OUT parameter in a local function
string(4) "STR1"
string(4) "STR2"
string(1) " "
Test 6: Bind IN OUT parameter within the same scope of execute
string(4) "STR1"
string(4) "STR2"
string(9) "STR1 STR2"
===DONE===

View file

@ -57,11 +57,11 @@ function get_attr($conn)
?> ?>
--EXPECT-- --EXPECT--
**Test 1.1 - Default values for the attribute ************** **Test 1.1 - Default values for the attribute **************
The value of DRIVER_NAME is PHP OCI8 : 2.1.2 The value of DRIVER_NAME is PHP OCI8 : 2.1.3
***Test 1.2 - Get the values from different connections ************** ***Test 1.2 - Get the values from different connections **************
Testing with oci_pconnect() Testing with oci_pconnect()
The value of DRIVER_NAME is PHP OCI8 : 2.1.2 The value of DRIVER_NAME is PHP OCI8 : 2.1.3
Testing with oci_new_connect() Testing with oci_new_connect()
The value of DRIVER_NAME is PHP OCI8 : 2.1.2 The value of DRIVER_NAME is PHP OCI8 : 2.1.3
Done Done