@@ -36,7 +36,6 @@ enum_func_status mysqlnd_stmt_execute_generate_request(MYSQLND_STMT * const s, z
36
36
enum_func_status mysqlnd_stmt_execute_batch_generate_request (MYSQLND_STMT * const s , zend_uchar * * request , size_t * request_len , zend_bool * free_buffer );
37
37
38
38
static void mysqlnd_stmt_separate_result_bind (MYSQLND_STMT * const stmt );
39
- static void mysqlnd_stmt_separate_one_result_bind (MYSQLND_STMT * const stmt , const unsigned int param_no );
40
39
41
40
/* {{{ mysqlnd_stmt::store_result */
42
41
static MYSQLND_RES *
@@ -542,7 +541,27 @@ mysqlnd_stmt_execute_parse_response(MYSQLND_STMT * const s, enum_mysqlnd_parse_e
542
541
stmt -> result -> conn = conn -> m -> get_reference (conn );
543
542
}
544
543
545
- /* Update stmt->field_count as SHOW sets it to 0 at prepare */
544
+ /* If the field count changed, update the result_bind structure. Ideally result_bind
545
+ * would only ever be created after execute, in which case the size cannot change anymore,
546
+ * but at least in mysqli this does not seem enforceable. */
547
+ if (stmt -> result_bind && conn -> field_count != stmt -> field_count ) {
548
+ if (conn -> field_count < stmt -> field_count ) {
549
+ /* Number of columns decreased, free bindings. */
550
+ for (unsigned i = conn -> field_count ; i < stmt -> field_count ; i ++ ) {
551
+ zval_ptr_dtor (& stmt -> result_bind [i ].zv );
552
+ }
553
+ }
554
+ stmt -> result_bind =
555
+ mnd_erealloc (stmt -> result_bind , conn -> field_count * sizeof (MYSQLND_RESULT_BIND ));
556
+ if (conn -> field_count > stmt -> field_count ) {
557
+ /* Number of columns increase, initialize new ones. */
558
+ for (unsigned i = stmt -> field_count ; i < conn -> field_count ; i ++ ) {
559
+ ZVAL_UNDEF (& stmt -> result_bind [i ].zv );
560
+ stmt -> result_bind [i ].bound = false;
561
+ }
562
+ }
563
+ }
564
+
546
565
stmt -> field_count = stmt -> result -> field_count = conn -> field_count ;
547
566
if (stmt -> result -> stored_data ) {
548
567
stmt -> result -> stored_data -> lengths = NULL ;
@@ -1577,22 +1596,13 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_one_result)(MYSQLND_STMT * const s, unsigned i
1577
1596
SET_EMPTY_ERROR (conn -> error_info );
1578
1597
1579
1598
if (stmt -> field_count ) {
1580
- mysqlnd_stmt_separate_one_result_bind (s , param_no );
1581
- /* Guaranteed is that stmt->result_bind is NULL */
1582
1599
if (!stmt -> result_bind ) {
1583
1600
stmt -> result_bind = mnd_ecalloc (stmt -> field_count , sizeof (MYSQLND_RESULT_BIND ));
1584
- } else {
1585
- stmt -> result_bind = mnd_erealloc (stmt -> result_bind , stmt -> field_count * sizeof (MYSQLND_RESULT_BIND ));
1586
1601
}
1587
- if (! stmt -> result_bind ) {
1588
- DBG_RETURN ( FAIL );
1602
+ if (stmt -> result_bind [ param_no ]. bound ) {
1603
+ zval_ptr_dtor ( & stmt -> result_bind [ param_no ]. zv );
1589
1604
}
1590
1605
ZVAL_NULL (& stmt -> result_bind [param_no ].zv );
1591
- /*
1592
- Don't update is_ref !!! it's not our job
1593
- Otherwise either 009.phpt or mysqli_stmt_bind_result.phpt
1594
- will fail.
1595
- */
1596
1606
stmt -> result_bind [param_no ].bound = TRUE;
1597
1607
}
1598
1608
DBG_INF ("PASS" );
@@ -1968,37 +1978,6 @@ mysqlnd_stmt_separate_result_bind(MYSQLND_STMT * const s)
1968
1978
/* }}} */
1969
1979
1970
1980
1971
- /* {{{ mysqlnd_stmt_separate_one_result_bind */
1972
- static void
1973
- mysqlnd_stmt_separate_one_result_bind (MYSQLND_STMT * const s , const unsigned int param_no )
1974
- {
1975
- MYSQLND_STMT_DATA * stmt = s ? s -> data : NULL ;
1976
- DBG_ENTER ("mysqlnd_stmt_separate_one_result_bind" );
1977
- if (!stmt ) {
1978
- DBG_VOID_RETURN ;
1979
- }
1980
- DBG_INF_FMT ("stmt=%lu result_bind=%p field_count=%u param_no=%u" , stmt -> stmt_id , stmt -> result_bind , stmt -> field_count , param_no );
1981
-
1982
- if (!stmt -> result_bind ) {
1983
- DBG_VOID_RETURN ;
1984
- }
1985
-
1986
- /*
1987
- Because only the bound variables can point to our internal buffers, then
1988
- separate or free only them. Free is possible because the user could have
1989
- lost reference.
1990
- */
1991
- /* Let's try with no cache */
1992
- if (stmt -> result_bind [param_no ].bound == TRUE) {
1993
- DBG_INF_FMT ("%u has refcount=%u" , param_no , Z_REFCOUNTED (stmt -> result_bind [param_no ].zv )? Z_REFCOUNT (stmt -> result_bind [param_no ].zv ) : 0 );
1994
- zval_ptr_dtor (& stmt -> result_bind [param_no ].zv );
1995
- }
1996
-
1997
- DBG_VOID_RETURN ;
1998
- }
1999
- /* }}} */
2000
-
2001
-
2002
1981
/* {{{ mysqlnd_stmt::free_stmt_result */
2003
1982
static void
2004
1983
MYSQLND_METHOD (mysqlnd_stmt , free_stmt_result )(MYSQLND_STMT * const s )
0 commit comments