ZF-2375: Zend_Db_Statement_Mysqli::_execute() causes too much memory to be allocated.


Zend_Db_Statement_Mysqli::_execute() calls mysqli_stmt_bind_result() *before* calling mysqli_stmt_execute(), and it does not call mysqli_stmt_store_result() or mysqli_stmt_free_result().

See these two links for reference: *… *

Modify the following test case to set the library path and to use the correct database connection parameters.


set_include_path(implode(PATH_SEPARATOR, array(
,   get_include_path()

require_once 'Zend/Loader.php';

try {
    $dbh = Zend_Db::factory('mysqli', array(
        'host'     => '',
        'username' => 'phpunit',
        'password' => 'phpunit',
        'dbname'   => 'test'
} catch (Zend_Exception $e) {
    echo $e->getMessage();

$dbh->query("DROP TABLE IF EXISTS `zend_testcase`");
    CREATE TABLE `zend_testcase` (
        `column_a` tinytext
    ,   `column_b` text
    ,   `column_c` mediumtext
$dbh->query("INSERT INTO `zend_testcase` VALUES('a', 'b', 'c')");

$mem = memory_get_usage();
$dbh->query("SELECT `column_a` FROM `zend_testcase`");
echo "Memory Used(TINYTEXT  ): " . (memory_get_usage() - $mem) . "\n";

$mem = memory_get_usage();
$dbh->query("SELECT `column_b` FROM `zend_testcase`");
echo "Memory Used(TEXT      ): " . (memory_get_usage() - $mem) . "\n";

$mem = memory_get_usage();
$dbh->query("SELECT `column_c` FROM `zend_testcase`");
echo "Memory Used(MEDIUMTEXT): " . (memory_get_usage() - $mem) . "\n";

$dbh->query('DROP TABLE IF EXISTS `zend_testcase`');


The output shows that the memory used corresponds roughly to the maximum size of the data-type being selected, which is what can be expected when not using mysqli_stmt_store_result() based on the bug report linked above.

Memory Used(TINYTEXT  ): 1516
Memory Used(TEXT      ): 65324
Memory Used(MEDIUMTEXT): 16711680

If the sequence of events in Zend_Db_Statement_Mysqli::_execute is updated, and a call to mysqli_stmt_store_result() is added, the memory usage drops significantly:

Memory Used(TINYTEXT  ): 1296
Memory Used(TEXT      ): 20
Memory Used(MEDIUMTEXT): 0

If this approach is used, calls to mysqli_stmt_free_result will also have to be added in the appropriate places.


Please categorize/fix as needed.

Changed the order of code in _execute method and added a call to mysqli_store_result. Changed to _closeCursor added a call to mysqli_free_result.

Fixed 1.5 branch at 9146, and trunk at 9138 and 9139.

Updating for the 1.6.0 release.