mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Update ext/mysql's and ext/mysqli's tests
Add mysqli_stmt_more_result()/mysqli_stmt_next_result(), but only in mysqlnd builds as libmysql doesn't support this feature.
This commit is contained in:
parent
2667f76d7b
commit
f4e659d2af
23 changed files with 603 additions and 200 deletions
|
@ -184,9 +184,9 @@ func_mysql_fetch_array($link, $engine, "BIGINT", NULL, NULL, 260);
|
|||
// func_mysql_fetch_array($link, $engine, "BIGINT UNSIGNED", 18446744073709551615, "1.84467e+019", 270, "/1\.84467e\+[0]?19/iu");
|
||||
func_mysql_fetch_array($link, $engine, "BIGINT UNSIGNED", NULL, NULL, 280);
|
||||
|
||||
func_mysql_fetch_array($link, $engine, "FLOAT", -9223372036854775808 - 1.1, "-9.22337e+18", 290, "/-9\.22337e\+[0]?18/iu");
|
||||
func_mysql_fetch_array($link, $engine, "FLOAT", -9223372036854775808 - 1.1, "-9.22337e+18", 290, "/-9\.22337e\+?[0]?18/iu");
|
||||
func_mysql_fetch_array($link, $engine, "FLOAT", NULL, NULL, 300);
|
||||
func_mysql_fetch_array($link, $engine, "FLOAT UNSIGNED", 18446744073709551615 + 1.1, "1.84467e+19", 310, "/1\.84467e\+[0]?19/iu");
|
||||
func_mysql_fetch_array($link, $engine, "FLOAT UNSIGNED", 18446744073709551615 + 1.1, "1.84467e+19", 310, "/1\.84467e\+?[0]?19/iu");
|
||||
func_mysql_fetch_array($link, $engine, "FLOAT UNSIGNED ", NULL, NULL, 320);
|
||||
|
||||
func_mysql_fetch_array($link, $engine, "DOUBLE(10,2)", -99999999.99, "-99999999.99", 330);
|
||||
|
|
|
@ -19,6 +19,9 @@ ob_end_clean();
|
|||
if (!stristr($phpinfo, "mysql support"))
|
||||
printf("[001] ext/mysql should have exposed itself.\n");
|
||||
|
||||
if (!stristr($phpinfo, "client api library version"))
|
||||
printf("[002] ext/mysql should have exposed the library version.\n");
|
||||
|
||||
if (!stristr($phpinfo, "mysql.default_host"))
|
||||
printf("[003] php.ini setting mysql.default_host not shown.\n");
|
||||
|
||||
|
@ -70,4 +73,4 @@ if ($IS_MYSQLND) {
|
|||
print "done!";
|
||||
?>
|
||||
--EXPECTF--
|
||||
done!
|
||||
done!
|
|
@ -1471,6 +1471,48 @@ PHP_FUNCTION(mysqli_next_result) {
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
#ifdef MYSQLI_USE_MYSQLND
|
||||
/* {{{ proto bool mysqli_stmt_next_result(object link)
|
||||
check if there any more query results from a multi query */
|
||||
PHP_FUNCTION(mysqli_stmt_more_results)
|
||||
{
|
||||
MY_STMT *stmt;
|
||||
zval *mysql_stmt;
|
||||
|
||||
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &mysql_stmt, "mysqli_stmt", MYSQLI_STATUS_VALID);
|
||||
|
||||
RETURN_BOOL(mysqlnd_stmt_more_results(stmt->stmt));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ proto bool mysqli_stmt_next_result(object link)
|
||||
read next result from multi_query */
|
||||
PHP_FUNCTION(mysqli_stmt_next_result) {
|
||||
MY_STMT *stmt;
|
||||
zval *mysql_stmt;
|
||||
|
||||
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &mysql_stmt, "mysqli_stmt", MYSQLI_STATUS_VALID);
|
||||
|
||||
if (!mysqlnd_stmt_more_results(stmt->stmt)) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_STRICT, "There is no next result set. "
|
||||
"Please, call mysqli_stmt_more_results()/mysqli_stmt::more_results() to check "
|
||||
"whether to call this function/method");
|
||||
}
|
||||
|
||||
RETURN_BOOL(!mysqlnd_stmt_next_result(stmt->stmt));
|
||||
}
|
||||
/* }}} */
|
||||
#endif
|
||||
|
||||
|
||||
/* {{{ proto int mysqli_num_fields(object result)
|
||||
Get number of fields in result */
|
||||
PHP_FUNCTION(mysqli_num_fields)
|
||||
|
|
|
@ -155,6 +155,10 @@ const zend_function_entry mysqli_functions[] = {
|
|||
PHP_FE(mysqli_stmt_data_seek, NULL)
|
||||
PHP_FE(mysqli_stmt_errno, NULL)
|
||||
PHP_FE(mysqli_stmt_error, NULL)
|
||||
#if defined(MYSQLI_USE_MYSQLND)
|
||||
PHP_FE(mysqli_stmt_more_results, NULL)
|
||||
PHP_FE(mysqli_stmt_next_result, NULL)
|
||||
#endif
|
||||
PHP_FE(mysqli_stmt_num_rows, NULL)
|
||||
PHP_FE(mysqli_stmt_sqlstate, NULL)
|
||||
PHP_FE(mysqli_stmt_store_result, NULL)
|
||||
|
@ -280,6 +284,10 @@ const zend_function_entry mysqli_stmt_methods[] = {
|
|||
PHP_FALIAS(get_warnings, mysqli_stmt_get_warnings, NULL)
|
||||
PHP_FALIAS(result_metadata, mysqli_stmt_result_metadata,NULL)
|
||||
PHP_FALIAS(num_rows, mysqli_stmt_num_rows,NULL)
|
||||
#if defined(MYSQLI_USE_MYSQLND)
|
||||
PHP_FALIAS(more_results, mysqli_stmt_more_results, NULL)
|
||||
PHP_FALIAS(next_result, mysqli_stmt_next_result, NULL)
|
||||
#endif
|
||||
PHP_FALIAS(send_long_data,mysqli_stmt_send_long_data,NULL)
|
||||
PHP_FALIAS(stmt,mysqli_prepare,NULL)
|
||||
PHP_FALIAS(free_result,mysqli_stmt_free_result,NULL)
|
||||
|
|
|
@ -409,8 +409,8 @@ PHP_FUNCTION(mysqli_fetch_all)
|
|||
Returns statistics about the zval cache */
|
||||
PHP_FUNCTION(mysqli_get_cache_stats)
|
||||
{
|
||||
if (ZEND_NUM_ARGS()) {
|
||||
WRONG_PARAM_COUNT;
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
mysqlnd_palloc_stats(mysqli_mysqlnd_zval_cache, return_value);
|
||||
}
|
||||
|
@ -421,8 +421,8 @@ PHP_FUNCTION(mysqli_get_cache_stats)
|
|||
Returns statistics about the zval cache */
|
||||
PHP_FUNCTION(mysqli_get_client_stats)
|
||||
{
|
||||
if (ZEND_NUM_ARGS()) {
|
||||
WRONG_PARAM_COUNT;
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
mysqlnd_get_client_stats(return_value);
|
||||
}
|
||||
|
@ -665,7 +665,7 @@ PHP_FUNCTION(mysqli_set_charset)
|
|||
MY_MYSQL *mysql;
|
||||
zval *mysql_link;
|
||||
char *cs_name;
|
||||
int csname_len;
|
||||
int csname_len;
|
||||
|
||||
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &mysql_link, mysqli_link_class_entry, &cs_name, &csname_len) == FAILURE) {
|
||||
return;
|
||||
|
|
|
@ -463,6 +463,8 @@ PHP_FUNCTION(mysqli_stmt_get_result);
|
|||
PHP_FUNCTION(mysqli_stmt_get_warnings);
|
||||
PHP_FUNCTION(mysqli_stmt_reset);
|
||||
PHP_FUNCTION(mysqli_stmt_insert_id);
|
||||
PHP_FUNCTION(mysqli_stmt_more_results);
|
||||
PHP_FUNCTION(mysqli_stmt_next_result);
|
||||
PHP_FUNCTION(mysqli_stmt_num_rows);
|
||||
PHP_FUNCTION(mysqli_stmt_sqlstate);
|
||||
PHP_FUNCTION(mysqli_stmt_store_result);
|
||||
|
|
|
@ -41,8 +41,11 @@ Interface of the class mysqli_stmt
|
|||
'store_result' => true,
|
||||
);
|
||||
|
||||
if ($IS_MYSQLND)
|
||||
if ($IS_MYSQLND) {
|
||||
$expected_methods['get_result'] = true;
|
||||
$expected_methods['more_results'] = true;
|
||||
$expected_methods['next_result'] = true;
|
||||
}
|
||||
|
||||
foreach ($methods as $k => $method) {
|
||||
if (isset($expected_methods[$method])) {
|
||||
|
|
|
@ -198,9 +198,9 @@ if (!function_exists('mysqli_fetch_all'))
|
|||
func_mysqli_fetch_all($link, $engine, "BIGINT UNSIGNED", 18446744073709551615, "18446744073709551615", 270);
|
||||
func_mysqli_fetch_all($link, $engine, "BIGINT UNSIGNED", NULL, NULL, 280);
|
||||
|
||||
func_mysqli_fetch_all($link, $engine, "FLOAT", -9223372036854775808 - 1.1, "-9.22337e+18", 290, "/-9\.22337e\+[0]?18/iu");
|
||||
func_mysqli_fetch_all($link, $engine, "FLOAT", -9223372036854775808 - 1.1, "-9.22337e+18", 290, "/-9\.22337e\+?[0]?18/iu");
|
||||
func_mysqli_fetch_all($link, $engine, "FLOAT", NULL, NULL, 300);
|
||||
func_mysqli_fetch_all($link, $engine, "FLOAT UNSIGNED", 18446744073709551615 + 1.1, "1.84467e+19", 310, "/1\.84467e\+[0]?19/iu");
|
||||
func_mysqli_fetch_all($link, $engine, "FLOAT UNSIGNED", 18446744073709551615 + 1.1, "1.84467e+19", 310, "/1\.84467e\+?[0]?19/iu");
|
||||
func_mysqli_fetch_all($link, $engine, "FLOAT UNSIGNED ", NULL, NULL, 320);
|
||||
|
||||
func_mysqli_fetch_all($link, $engine, "DOUBLE(10,2)", -99999999.99, "-99999999.99", 330);
|
||||
|
|
|
@ -198,9 +198,9 @@ if (!function_exists('mysqli_fetch_all'))
|
|||
func_mysqli_fetch_all_oo($link, $engine, "BIGINT UNSIGNED", 18446744073709551615, "18446744073709551615", 270);
|
||||
func_mysqli_fetch_all_oo($link, $engine, "BIGINT UNSIGNED", NULL, NULL, 280);
|
||||
|
||||
func_mysqli_fetch_all_oo($link, $engine, "FLOAT", -9223372036854775808 - 1.1, "-9.22337e+18", 290, "/-9\.22337e\+[0]?18/iu");
|
||||
func_mysqli_fetch_all_oo($link, $engine, "FLOAT", -9223372036854775808 - 1.1, "-9.22337e+18", 290, "/-9\.22337e\+?[0]?18/iu");
|
||||
func_mysqli_fetch_all_oo($link, $engine, "FLOAT", NULL, NULL, 300);
|
||||
func_mysqli_fetch_all_oo($link, $engine, "FLOAT UNSIGNED", 18446744073709551615 + 1.1, "1.84467e+19", 310, "/1\.84467e\+[0]?19/iu");
|
||||
func_mysqli_fetch_all_oo($link, $engine, "FLOAT UNSIGNED", 18446744073709551615 + 1.1, "1.84467e+?19", 310, "/1\.84467e\+?[0]?19/iu");
|
||||
func_mysqli_fetch_all_oo($link, $engine, "FLOAT UNSIGNED ", NULL, NULL, 320);
|
||||
|
||||
func_mysqli_fetch_all_oo($link, $engine, "DOUBLE(10,2)", -99999999.99, "-99999999.99", 330);
|
||||
|
|
|
@ -191,9 +191,9 @@ require_once('skipifconnectfailure.inc');
|
|||
func_mysqli_fetch_array($link, $engine, "BIGINT UNSIGNED", NULL, NULL, 280);
|
||||
}
|
||||
|
||||
func_mysqli_fetch_array($link, $engine, "FLOAT", -9223372036854775808 - 1.1, "-9.22337e+18", 290, "/-9\.22337e\+[0]?18/iu");
|
||||
func_mysqli_fetch_array($link, $engine, "FLOAT", -9223372036854775808 - 1.1, "-9.22337e+18", 290, "/-9\.22337e\+?[0]?18/iu");
|
||||
func_mysqli_fetch_array($link, $engine, "FLOAT", NULL, NULL, 300);
|
||||
func_mysqli_fetch_array($link, $engine, "FLOAT UNSIGNED", 18446744073709551615 + 1.1, "1.84467e+19", 310, "/1\.84467e\+[0]?19/iu");
|
||||
func_mysqli_fetch_array($link, $engine, "FLOAT UNSIGNED", 18446744073709551615 + 1.1, "1.84467e+?19", 310, "/1\.84467e\+?[0]?19/iu");
|
||||
func_mysqli_fetch_array($link, $engine, "FLOAT UNSIGNED ", NULL, NULL, 320);
|
||||
|
||||
func_mysqli_fetch_array($link, $engine, "DOUBLE(10,2)", -99999999.99, "-99999999.99", 330);
|
||||
|
|
|
@ -175,9 +175,9 @@ require_once('skipifconnectfailure.inc');
|
|||
func_mysqli_fetch_array($mysqli, $engine, "BIGINT UNSIGNED", NULL, NULL, 280);
|
||||
}
|
||||
|
||||
func_mysqli_fetch_array($mysqli, $engine, "FLOAT", -9223372036854775808 - 1.1, "-9.22337e+18", 290, "/-9\.22337e\+[0]?18/iu");
|
||||
func_mysqli_fetch_array($mysqli, $engine, "FLOAT", -9223372036854775808 - 1.1, "-9.22337e+18", 290, "/-9\.22337e\+?[0]?18/iu");
|
||||
func_mysqli_fetch_array($mysqli, $engine, "FLOAT", NULL, NULL, 300);
|
||||
func_mysqli_fetch_array($mysqli, $engine, "FLOAT UNSIGNED", 18446744073709551615 + 1.1, "1.84467e+19", 310, "/1\.84467e\+[0]?19/iu");
|
||||
func_mysqli_fetch_array($mysqli, $engine, "FLOAT UNSIGNED", 18446744073709551615 + 1.1, "1.84467e+?19", 310, "/1\.84467e\+?[0]?19/iu");
|
||||
func_mysqli_fetch_array($mysqli, $engine, "FLOAT UNSIGNED ", NULL, NULL, 320);
|
||||
|
||||
func_mysqli_fetch_array($mysqli, $engine, "DOUBLE(10,2)", -99999999.99, "-99999999.99", 330);
|
||||
|
|
|
@ -5,11 +5,22 @@ mysqli_fetch_field() - flags/field->flags
|
|||
require_once('skipif.inc');
|
||||
require_once('skipifemb.inc');
|
||||
require_once('skipifconnectfailure.inc');
|
||||
|
||||
require_once('connect.inc');
|
||||
if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
|
||||
die(printf("skip: [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()));
|
||||
|
||||
if (mysqli_get_server_version($link) < 50041)
|
||||
die("skip: Due to many MySQL Server differences, the test requires 5.0.41+");
|
||||
|
||||
mysqli_close($link);
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
include "connect.inc";
|
||||
|
||||
/* TODO: mysqli.c needs to export a few more constants - see all the defined() calls! */
|
||||
|
||||
$flags = array(
|
||||
MYSQLI_NOT_NULL_FLAG => 'NOT_NULL',
|
||||
MYSQLI_PRI_KEY_FLAG => 'PRI_KEY',
|
||||
|
@ -23,12 +34,19 @@ require_once('skipifconnectfailure.inc');
|
|||
MYSQLI_SET_FLAG => 'SET',
|
||||
MYSQLI_NUM_FLAG => 'NUM',
|
||||
MYSQLI_PART_KEY_FLAG => 'PART_KEY',
|
||||
MYSQLI_GROUP_FLAG => 'MYSQLI_GROUP_FLAG'
|
||||
// MYSQLI_NO_DEFAULT_VALUE_FLAG
|
||||
// MYSQLI_BINARY_FLAG
|
||||
// MYSQLI_ENUM_FLAG
|
||||
// MYSQLI_GROUP_FLAG => 'MYSQLI_GROUP_FLAG' - internal usage only
|
||||
(defined('MYSQLI_NO_DEFAULT_VALUE_FLAG') ? MYSQLI_NO_DEFAULT_VALUE_FLAG : 4096) => 'NO_DEFAULT_VALUE',
|
||||
(defined('MYSQLI_BINARY_FLAG') ? MYSQLI_BINARY_FLAG : 128) => 'BINARY',
|
||||
(defined('MYSQLI_ENUM_FLAG') ? MYSQLI_ENUM_FLAG : 256) => 'ENUM',
|
||||
// MYSQLI_BINCMP_FLAG
|
||||
);
|
||||
|
||||
// 5.1.24 / 6.0.4+
|
||||
if (defined('MYSQLI_ON_UPDATE_NOW'))
|
||||
$flags[MYSQLI_ON_UPDATE_NOW] = 'ON_UPDATE_NOW';
|
||||
else
|
||||
$flags[8192] = 'ON_UPDATE_NOW';
|
||||
|
||||
krsort($flags);
|
||||
|
||||
$columns = array(
|
||||
|
@ -37,13 +55,13 @@ require_once('skipifconnectfailure.inc');
|
|||
'INT NOT NULL DEFAULT 1' => 'NOT_NULL NUM',
|
||||
'INT UNSIGNED DEFAULT NULL' => 'UNSIGNED NUM',
|
||||
'INT UNSIGNED NOT NULL' => 'NOT_NULL UNSIGNED NO_DEFAULT_VALUE NUM',
|
||||
'INT UNSIGNED NOT NULL DEFAULT 1' => 'NOT_NULL UNSIGNED NULL',
|
||||
'INT UNSIGNED NOT NULL DEFAULT 1' => 'NOT_NULL UNSIGNED NUM',
|
||||
'INT UNSIGNED ZEROFILL DEFAULT NULL' => 'UNSIGNED ZEROFILL NUM',
|
||||
'INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY' => 'NOT_NULL PRI_KEY UNSIGNED AUTO_INCREMENT NUM PART_KEY',
|
||||
'CHAR(1) DEFAULT NULL' => '',
|
||||
'CHAR(1) NOT NULL' => 'NOT_NULL NO_DEFAULT_VALUE',
|
||||
'TIMESTAMP NOT NULL' => 'NOT_NULL UNSIGNED ZEROFILL BINARY TIMESTAMP',
|
||||
'VARBINARY(127) DEFAULT NULL' => 'NOT_NULL BINARY',
|
||||
'VARBINARY(127) DEFAULT NULL' => 'BINARY',
|
||||
'BLOB' => 'BLOB BINARY',
|
||||
'TINYBLOB' => 'BLOB BINARY',
|
||||
'MEDIUMBLOB' => 'BLOB BINARY',
|
||||
|
@ -67,10 +85,9 @@ require_once('skipifconnectfailure.inc');
|
|||
);
|
||||
|
||||
function checkFlags($reported_flags, $expected_flags, $flags) {
|
||||
|
||||
$found_flags = $unexpected_flags = '';
|
||||
foreach ($flags as $code => $name) {
|
||||
if ($code >= $reported_flags) {
|
||||
if ($reported_flags >= $code) {
|
||||
$reported_flags -= $code;
|
||||
$found_flags .= $name . ' ';
|
||||
if (stristr($expected_flags, $name)) {
|
||||
|
@ -118,13 +135,57 @@ require_once('skipifconnectfailure.inc');
|
|||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
TODO
|
||||
Unfortunately different server versions give you slightly different
|
||||
results.The test does not yet fully reflect all server changes/bugs etc.
|
||||
*/
|
||||
switch ($column_def) {
|
||||
case 'TIMESTAMP NOT NULL':
|
||||
// http://bugs.mysql.com/bug.php?id=30081 - new flag introduced in 5.1.24/6.0.4
|
||||
$version = mysqli_get_server_version($link);
|
||||
if ((($version > 50122) && ($version < 60000)) ||
|
||||
($version >= 60004)) {
|
||||
// new flag ON_UPDATE_NOW_FLAG (8192)
|
||||
$expected_flags .= ' ON_UPDATE_NOW';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'INT UNSIGNED NOT NULL':
|
||||
case 'INT NOT NULL':
|
||||
case 'CHAR(1) NOT NULL':
|
||||
case 'SET("one", "two") NOT NULL':
|
||||
case 'ENUM("one", "two") NOT NULL':
|
||||
$version = mysqli_get_server_version($link);
|
||||
if ($version < 50000) {
|
||||
// TODO - check exact version!
|
||||
$expected_flags = trim(str_replace('NO_DEFAULT_VALUE', '', $expected_flags));
|
||||
}
|
||||
break;
|
||||
|
||||
case 'BIT':
|
||||
$version = mysqli_get_server_version($link);
|
||||
if ($version <= 50105) {
|
||||
// TODO - check exact version!
|
||||
$expected_flags = trim(str_replace('UNSIGNED', '', $expected_flags));
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
list($missing_flags, $unexpected_flags, $flags_found) = checkFlags($field->flags, $expected_flags, $flags);
|
||||
if ($unexpected_flags)
|
||||
if ($unexpected_flags) {
|
||||
printf("[006] Found unexpected flags '%s' for %s, found '%s'\n",
|
||||
$unexpected_flags, $column_def, $flags_found);
|
||||
if ($missing_flags)
|
||||
}
|
||||
if ($missing_flags) {
|
||||
printf("[007] The flags '%s' have not been reported for %s, found '%s'\n",
|
||||
$missing_flags, $column_def, $flags_found);
|
||||
var_dump($create);
|
||||
var_dump(mysqli_get_server_version($link));
|
||||
die($missing_flags);
|
||||
}
|
||||
|
||||
mysqli_free_result($res);
|
||||
}
|
||||
|
|
|
@ -57,15 +57,61 @@ require_once('skipifconnectfailure.inc');
|
|||
if (true !== ($tmp = mysqli_stmt_execute($stmt)))
|
||||
printf("[012] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
|
||||
|
||||
// calling reset between executions
|
||||
mysqli_stmt_close($stmt);
|
||||
if (!$stmt = mysqli_stmt_init($link))
|
||||
printf("[013] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
|
||||
|
||||
if (!mysqli_stmt_prepare($stmt, "SELECT id FROM test ORDER BY id LIMIT 1"))
|
||||
printf("[014] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
|
||||
|
||||
if (true !== ($tmp = mysqli_stmt_execute($stmt)))
|
||||
printf("[015] Expecting boolean/true, got %s/%s. [%d] %s\n",
|
||||
gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
|
||||
|
||||
$id = null;
|
||||
if (!mysqli_stmt_bind_result($stmt, $id) || !mysqli_stmt_fetch($stmt))
|
||||
printf("[016] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
|
||||
|
||||
if ($id !== 1)
|
||||
printf("[017] Expecting int/1 got %s/%s\n", gettype($id), $id);
|
||||
|
||||
if (true !== ($tmp = mysqli_stmt_reset($stmt)))
|
||||
printf("[018] Expecting boolean/true, got %s/%s. [%d] %s\n",
|
||||
gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
|
||||
|
||||
printf("Don't know what we should expect\n");
|
||||
var_dump(mysqli_stmt_execute($stmt));
|
||||
var_dump(mysqli_stmt_fetch($stmt));
|
||||
|
||||
mysqli_stmt_close($stmt);
|
||||
if (!$stmt = mysqli_stmt_init($link))
|
||||
printf("[019] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
|
||||
|
||||
if (!mysqli_stmt_prepare($stmt, "SELECT id FROM test ORDER BY id LIMIT 1"))
|
||||
printf("[020] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
|
||||
|
||||
if (true !== ($tmp = mysqli_stmt_execute($stmt)))
|
||||
printf("[021] Expecting boolean/true, got %s/%s. [%d] %s\n",
|
||||
gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
|
||||
|
||||
if (true !== ($tmp = mysqli_stmt_reset($stmt)))
|
||||
printf("[022] Expecting boolean/true, got %s/%s. [%d] %s\n",
|
||||
gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
|
||||
|
||||
printf("Don't know what we should expect\n");
|
||||
var_dump(mysqli_stmt_execute($stmt));
|
||||
var_dump(mysqli_stmt_fetch($stmt));
|
||||
|
||||
mysqli_kill($link, mysqli_thread_id($link));
|
||||
|
||||
if (false !== ($tmp = mysqli_stmt_execute($stmt)))
|
||||
printf("[014] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
|
||||
printf("[023] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
|
||||
|
||||
mysqli_stmt_close($stmt);
|
||||
|
||||
if (NULL !== ($tmp = mysqli_stmt_execute($stmt)))
|
||||
printf("[015] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
|
||||
printf("[024] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
|
||||
|
||||
mysqli_close($link);
|
||||
print "done!";
|
||||
|
|
|
@ -1274,10 +1274,12 @@ MYSQLND_METHOD(mysqlnd_conn, close)(MYSQLND * conn, enum_connection_close_type c
|
|||
|
||||
/* {{{ mysqlnd_conn::get_reference */
|
||||
static MYSQLND *
|
||||
MYSQLND_METHOD_PRIVATE(mysqlnd_conn, get_reference)(MYSQLND * const conn)
|
||||
MYSQLND_METHOD_PRIVATE(mysqlnd_conn, get_reference)(MYSQLND * const conn TSRMLS_DC)
|
||||
{
|
||||
DBG_ENTER("mysqlnd_conn::get_reference");
|
||||
++conn->refcount;
|
||||
return conn;
|
||||
DBG_INF_FMT("conn=%llu new_refcount=%u", conn->thread_id, conn->refcount);
|
||||
DBG_RETURN(conn);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -1288,7 +1290,7 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_conn, free_reference)(MYSQLND * const conn TSRMLS
|
|||
{
|
||||
enum_func_status ret = PASS;
|
||||
DBG_ENTER("mysqlnd_conn::free_reference");
|
||||
DBG_INF_FMT("conn=%llu conn->refcount=%u", conn->thread_id, conn->refcount);
|
||||
DBG_INF_FMT("conn=%llu old_refcount=%u", conn->thread_id, conn->refcount);
|
||||
if (!(--conn->refcount)) {
|
||||
/*
|
||||
No multithreading issues as we don't share the connection :)
|
||||
|
@ -1474,10 +1476,11 @@ MYSQLND_METHOD(mysqlnd_conn, get_server_version)(const MYSQLND * const conn)
|
|||
|
||||
/* {{{ mysqlnd_conn::more_results */
|
||||
static zend_bool
|
||||
MYSQLND_METHOD(mysqlnd_conn,more_results)(const MYSQLND * const conn)
|
||||
MYSQLND_METHOD(mysqlnd_conn, more_results)(const MYSQLND * const conn TSRMLS_DC)
|
||||
{
|
||||
DBG_ENTER("mysqlnd_conn::more_results");
|
||||
/* (conn->state == CONN_NEXT_RESULT_PENDING) too */
|
||||
return conn->upsert_status.server_status & SERVER_MORE_RESULTS_EXISTS? TRUE:FALSE;
|
||||
DBG_RETURN(conn->upsert_status.server_status & SERVER_MORE_RESULTS_EXISTS? TRUE:FALSE);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -1792,7 +1795,7 @@ MYSQLND_METHOD(mysqlnd_conn, use_result)(MYSQLND * const conn TSRMLS_DC)
|
|||
|
||||
result = conn->current_result;
|
||||
conn->current_result = NULL;
|
||||
result->conn = conn->m->get_reference(conn);
|
||||
result->conn = conn->m->get_reference(conn TSRMLS_CC);
|
||||
|
||||
result = result->m.use_result(result, FALSE TSRMLS_CC);
|
||||
DBG_RETURN(result);
|
||||
|
@ -1956,7 +1959,7 @@ PHPAPI MYSQLND *_mysqlnd_init(zend_bool persistent TSRMLS_DC)
|
|||
ret->persistent = persistent;
|
||||
|
||||
ret->m = & mysqlnd_mysqlnd_conn_methods;
|
||||
ret->m->get_reference(ret);
|
||||
ret->m->get_reference(ret TSRMLS_CC);
|
||||
|
||||
#ifdef MYSQLND_THREADED
|
||||
ret->LOCK_state = tsrm_mutex_alloc();
|
||||
|
|
|
@ -112,7 +112,7 @@ PHPAPI void _mysqlnd_debug(const char *mode TSRMLS_DC);
|
|||
#define mysqlnd_store_result(conn) (conn)->m->store_result((conn) TSRMLS_CC)
|
||||
#define mysqlnd_bg_store_result(conn) (conn)->m->background_store_result((conn) TSRMLS_CC)
|
||||
#define mysqlnd_next_result(conn) (conn)->m->next_result((conn) TSRMLS_CC)
|
||||
#define mysqlnd_more_results(conn) (conn)->m->more_results((conn))
|
||||
#define mysqlnd_more_results(conn) (conn)->m->more_results((conn) TSRMLS_CC)
|
||||
#define mysqlnd_free_result(r,e_or_i) ((MYSQLND_RES*)r)->m.free_result(((MYSQLND_RES*)(r)), (e_or_i) TSRMLS_CC)
|
||||
#define mysqlnd_data_seek(result, row) (result)->m.seek_data((result), (row) TSRMLS_CC)
|
||||
|
||||
|
@ -262,6 +262,8 @@ PHPAPI ulong mysqlnd_old_escape_string(char *newstr, const char *escapestr, size
|
|||
#define mysqlnd_stmt_store_result(stmt) (!mysqlnd_stmt_field_count((stmt)) ? PASS:((stmt)->m->store_result((stmt) TSRMLS_CC)? PASS:FAIL))
|
||||
#define mysqlnd_stmt_bg_store_result(stmt) (!mysqlnd_stmt_field_count((stmt)) ? PASS:((stmt)->m->background_store_result((stmt) TSRMLS_CC)? PASS:FAIL))
|
||||
#define mysqlnd_stmt_get_result(stmt) (stmt)->m->get_result((stmt) TSRMLS_CC)
|
||||
#define mysqlnd_stmt_more_results(stmt) (stmt)->m->more_results((stmt) TSRMLS_CC)
|
||||
#define mysqlnd_stmt_next_result(stmt) (stmt)->m->next_result((stmt) TSRMLS_CC)
|
||||
#define mysqlnd_stmt_data_seek(stmt, row) (stmt)->m->seek_data((stmt), (row) TSRMLS_CC)
|
||||
#define mysqlnd_stmt_prepare(stmt, q, qlen) (stmt)->m->prepare((stmt), (q), (qlen) TSRMLS_CC)
|
||||
#define mysqlnd_stmt_execute(stmt) (stmt)->m->execute((stmt) TSRMLS_CC)
|
||||
|
@ -271,6 +273,7 @@ PHPAPI ulong mysqlnd_old_escape_string(char *newstr, const char *escapestr, size
|
|||
#define mysqlnd_stmt_refresh_bind_param(s) (s)->m->refresh_bind_param((s) TSRMLS_CC)
|
||||
#define mysqlnd_stmt_set_param_bind_dtor(s,d) (s)->m->set_param_bind_dtor((s), (d) TSRMLS_CC)
|
||||
#define mysqlnd_stmt_bind_result(stmt,bind) (stmt)->m->bind_result((stmt), (bind) TSRMLS_CC)
|
||||
#define mysqlnd_stmt_bind_one_result(s,no) (s)->m->bind_one_result((s), (no) TSRMLS_CC)
|
||||
#define mysqlnd_stmt_set_result_bind_dtor(s,d) (s)->m->set_result_bind_dtor((s), (d) TSRMLS_CC)
|
||||
#define mysqlnd_stmt_param_metadata(stmt) (stmt)->m->get_parameter_metadata((stmt))
|
||||
#define mysqlnd_stmt_result_metadata(stmt) (stmt)->m->get_result_metadata((stmt) TSRMLS_CC)
|
||||
|
@ -305,9 +308,10 @@ PHPAPI void _mysqlnd_palloc_rshutdown(MYSQLND_THD_ZVAL_PCACHE * cache TSRM
|
|||
|
||||
#define mysqlnd_palloc_init_thd_cache(cache) _mysqlnd_palloc_init_thd_cache((cache) TSRMLS_CC)
|
||||
#define mysqlnd_palloc_free_thd_cache_reference(cache) _mysqlnd_palloc_free_thd_cache_reference((cache) TSRMLS_CC)
|
||||
#define mysqlnd_palloc_get_thd_cache_reference(cache) _mysqlnd_palloc_get_thd_cache_reference((cache) TSRMLS_CC)
|
||||
|
||||
PHPAPI MYSQLND_THD_ZVAL_PCACHE* _mysqlnd_palloc_init_thd_cache(MYSQLND_ZVAL_PCACHE * const cache TSRMLS_DC);
|
||||
MYSQLND_THD_ZVAL_PCACHE* mysqlnd_palloc_get_thd_cache_reference(MYSQLND_THD_ZVAL_PCACHE * const cache);
|
||||
MYSQLND_THD_ZVAL_PCACHE* _mysqlnd_palloc_get_thd_cache_reference(MYSQLND_THD_ZVAL_PCACHE * const cache TSRMLS_DC);
|
||||
PHPAPI void _mysqlnd_palloc_free_thd_cache_reference(MYSQLND_THD_ZVAL_PCACHE **cache TSRMLS_DC);
|
||||
|
||||
|
||||
|
|
|
@ -28,8 +28,26 @@
|
|||
#define MYSQLND_SQLSTATE_LENGTH 5
|
||||
#define MYSQLND_SQLSTATE_NULL "00000"
|
||||
|
||||
#define SERVER_STATUS_IN_TRANS 1 /* Transaction has started */
|
||||
#define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */
|
||||
#define SERVER_MORE_RESULTS_EXISTS 8 /* Multi query - next query exists */
|
||||
#define MYSQLND_SERVER_QUERY_NO_GOOD_INDEX_USED 16
|
||||
#define MYSQLND_SERVER_QUERY_NO_INDEX_USED 32
|
||||
/*
|
||||
The server was able to fulfill the clients request and opened a
|
||||
read-only non-scrollable cursor for a query. This flag comes
|
||||
in reply to COM_STMT_EXECUTE and COM_STMT_FETCH commands.
|
||||
*/
|
||||
#define SERVER_STATUS_CURSOR_EXISTS 64
|
||||
/*
|
||||
This flag is sent when a read-only cursor is exhausted, in reply to
|
||||
COM_STMT_FETCH command.
|
||||
*/
|
||||
#define SERVER_STATUS_LAST_ROW_SENT 128
|
||||
#define SERVER_STATUS_DB_DROPPED 256 /* A database was dropped */
|
||||
#define SERVER_STATUS_NO_BACKSLASH_ESCAPES 512
|
||||
#define SERVER_QUERY_WAS_SLOW 1024
|
||||
|
||||
|
||||
#define MYSQLND_NO_DATA 100
|
||||
#define MYSQLND_DATA_TRUNCATED 101
|
||||
|
|
|
@ -151,14 +151,16 @@ PHPAPI MYSQLND_THD_ZVAL_PCACHE* _mysqlnd_palloc_init_thd_cache(MYSQLND_ZVAL_PCAC
|
|||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_palloc_get_thd_cache_reference */
|
||||
MYSQLND_THD_ZVAL_PCACHE* mysqlnd_palloc_get_thd_cache_reference(MYSQLND_THD_ZVAL_PCACHE * const cache)
|
||||
/* {{{ _mysqlnd_palloc_get_thd_cache_reference */
|
||||
MYSQLND_THD_ZVAL_PCACHE* _mysqlnd_palloc_get_thd_cache_reference(MYSQLND_THD_ZVAL_PCACHE * const cache TSRMLS_DC)
|
||||
{
|
||||
DBG_ENTER("_mysqlnd_palloc_get_thd_cache_reference");
|
||||
if (cache) {
|
||||
++cache->references;
|
||||
DBG_INF_FMT("cache=%p new_refc=%d", *cache, cache->references);
|
||||
mysqlnd_palloc_get_cache_reference(cache->parent);
|
||||
}
|
||||
return cache;
|
||||
DBG_RETURN(cache);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -190,8 +192,8 @@ PHPAPI void _mysqlnd_palloc_free_thd_cache_reference(MYSQLND_THD_ZVAL_PCACHE **c
|
|||
{
|
||||
DBG_ENTER("_mysqlnd_palloc_free_thd_cache_reference");
|
||||
if (*cache) {
|
||||
DBG_INF_FMT("cache=%p refs=%d", *cache, (*cache)->references);
|
||||
--(*cache)->parent->references;
|
||||
DBG_INF_FMT("cache=%p references_left=%d", *cache, (*cache)->references);
|
||||
|
||||
if (--(*cache)->references == 0) {
|
||||
mysqlnd_palloc_free_thd_cache(*cache TSRMLS_CC);
|
||||
|
@ -493,7 +495,7 @@ PHPAPI void _mysqlnd_palloc_rshutdown(MYSQLND_THD_ZVAL_PCACHE * thd_cache TSRMLS
|
|||
++cache->free_items;
|
||||
#ifdef ZTS
|
||||
memset(&((*p)->thread_id), 0, sizeof(THREAD_T));
|
||||
#endif
|
||||
#endif
|
||||
p++;
|
||||
}
|
||||
UNLOCK_PCACHE(cache);
|
||||
|
|
|
@ -74,23 +74,6 @@
|
|||
|
||||
|
||||
|
||||
#define SERVER_STATUS_IN_TRANS 1 /* Transaction has started */
|
||||
#define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */
|
||||
#define SERVER_MORE_RESULTS_EXISTS 8 /* Multi query - next query exists */
|
||||
/*
|
||||
The server was able to fulfill the clients request and opened a
|
||||
read-only non-scrollable cursor for a query. This flag comes
|
||||
in reply to COM_STMT_EXECUTE and COM_STMT_FETCH commands.
|
||||
*/
|
||||
#define SERVER_STATUS_CURSOR_EXISTS 64
|
||||
/*
|
||||
This flag is sent when a read-only cursor is exhausted, in reply to
|
||||
COM_STMT_FETCH command.
|
||||
*/
|
||||
#define SERVER_STATUS_LAST_ROW_SENT 128
|
||||
#define SERVER_STATUS_DB_DROPPED 256 /* A database was dropped */
|
||||
#define SERVER_STATUS_NO_BACKSLASH_ESCAPES 512
|
||||
#define SERVER_QUERY_WAS_SLOW 1024
|
||||
|
||||
|
||||
/* Client Error codes */
|
||||
|
|
|
@ -57,7 +57,10 @@ enum_func_status mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param,
|
|||
zend_bool *fetched_anything TSRMLS_DC);
|
||||
|
||||
static void mysqlnd_stmt_separate_result_bind(MYSQLND_STMT * const stmt TSRMLS_DC);
|
||||
static void mysqlnd_stmt_separate_one_result_bind(MYSQLND_STMT * const stmt, uint param_no TSRMLS_DC);
|
||||
|
||||
static void mysqlnd_internal_free_stmt_content(MYSQLND_STMT * const stmt TSRMLS_DC);
|
||||
static enum_func_status mysqlnd_stmt_execute_parse_response(MYSQLND_STMT * const stmt TSRMLS_DC);
|
||||
|
||||
/* {{{ mysqlnd_stmt::store_result */
|
||||
static MYSQLND_RES *
|
||||
|
@ -100,7 +103,9 @@ MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const stmt TSRMLS_DC)
|
|||
result->type = MYSQLND_RES_PS_BUF;
|
||||
result->m.fetch_row = mysqlnd_fetch_stmt_row_buffered;
|
||||
result->m.fetch_lengths = NULL;/* makes no sense */
|
||||
result->zval_cache = mysqlnd_palloc_get_thd_cache_reference(conn->zval_cache);
|
||||
if (!result->zval_cache) {
|
||||
result->zval_cache = mysqlnd_palloc_get_thd_cache_reference(conn->zval_cache);
|
||||
}
|
||||
|
||||
/* Create room for 'next_extend' rows */
|
||||
|
||||
|
@ -167,7 +172,9 @@ MYSQLND_METHOD(mysqlnd_stmt, background_store_result)(MYSQLND_STMT * const stmt
|
|||
result->type = MYSQLND_RES_PS_BUF;
|
||||
result->m.fetch_row = mysqlnd_fetch_stmt_row_buffered;
|
||||
result->m.fetch_lengths = NULL;/* makes no sense */
|
||||
result->zval_cache = mysqlnd_palloc_get_thd_cache_reference(conn->zval_cache);
|
||||
if (!result->zval_cache) {
|
||||
result->zval_cache = mysqlnd_palloc_get_thd_cache_reference(conn->zval_cache);
|
||||
}
|
||||
|
||||
/* Create room for 'next_extend' rows */
|
||||
|
||||
|
@ -248,6 +255,45 @@ MYSQLND_METHOD(mysqlnd_stmt, get_result)(MYSQLND_STMT * const stmt TSRMLS_DC)
|
|||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_stmt::more_results */
|
||||
static zend_bool
|
||||
MYSQLND_METHOD(mysqlnd_stmt, more_results)(const MYSQLND_STMT * stmt TSRMLS_DC)
|
||||
{
|
||||
DBG_ENTER("mysqlnd_stmt::more_results");
|
||||
/* (conn->state == CONN_NEXT_RESULT_PENDING) too */
|
||||
DBG_RETURN((stmt->conn && (stmt->conn->upsert_status.server_status &
|
||||
SERVER_MORE_RESULTS_EXISTS))?
|
||||
TRUE:
|
||||
FALSE);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_stmt::next_result */
|
||||
static enum_func_status
|
||||
MYSQLND_METHOD(mysqlnd_stmt, next_result)(MYSQLND_STMT * stmt TSRMLS_DC)
|
||||
{
|
||||
MYSQLND *conn = stmt->conn;
|
||||
|
||||
DBG_ENTER("mysqlnd_stmt::next_result");
|
||||
DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
|
||||
|
||||
if (!conn ||
|
||||
CONN_GET_STATE(conn) != CONN_NEXT_RESULT_PENDING ||
|
||||
!(conn->upsert_status.server_status & SERVER_MORE_RESULTS_EXISTS) ||
|
||||
!stmt->result)
|
||||
{
|
||||
DBG_RETURN(FAIL);
|
||||
}
|
||||
|
||||
/* Free space for next result */
|
||||
mysqlnd_internal_free_stmt_content(stmt TSRMLS_CC);
|
||||
|
||||
DBG_RETURN(mysqlnd_stmt_execute_parse_response(stmt TSRMLS_CC));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_stmt_skip_metadata */
|
||||
static enum_func_status
|
||||
mysqlnd_stmt_skip_metadata(MYSQLND_STMT *stmt TSRMLS_DC)
|
||||
|
@ -399,7 +445,7 @@ MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const stmt, const char * co
|
|||
/* Allocate the result now as it is needed for the reading of metadata */
|
||||
stmt_to_prepare->result = result;
|
||||
|
||||
result->conn = stmt_to_prepare->conn->m->get_reference(stmt_to_prepare->conn);
|
||||
result->conn = stmt_to_prepare->conn->m->get_reference(stmt_to_prepare->conn TSRMLS_CC);
|
||||
|
||||
result->type = MYSQLND_RES_PS_BUF;
|
||||
|
||||
|
@ -411,7 +457,7 @@ MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const stmt, const char * co
|
|||
|
||||
if (stmt_to_prepare != stmt) {
|
||||
/* Free old buffers, binding and resources on server */
|
||||
stmt->m->close(stmt, TRUE TSRMLS_CC);
|
||||
stmt->m->net_close(stmt, TRUE TSRMLS_CC);
|
||||
|
||||
memcpy(stmt, stmt_to_prepare, sizeof(MYSQLND_STMT));
|
||||
|
||||
|
@ -434,6 +480,92 @@ fail:
|
|||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_stmt_execute_parse_response */
|
||||
static enum_func_status
|
||||
mysqlnd_stmt_execute_parse_response(MYSQLND_STMT * const stmt TSRMLS_DC)
|
||||
{
|
||||
enum_func_status ret;
|
||||
MYSQLND *conn = stmt->conn;
|
||||
|
||||
DBG_ENTER("mysqlnd_stmt_execute_parse_response");
|
||||
|
||||
CONN_SET_STATE(conn, CONN_QUERY_SENT);
|
||||
|
||||
ret = mysqlnd_query_read_result_set_header(stmt->conn, stmt TSRMLS_CC);
|
||||
if (ret == FAIL) {
|
||||
stmt->error_info = conn->error_info;
|
||||
stmt->upsert_status.affected_rows = conn->upsert_status.affected_rows;
|
||||
if (CONN_GET_STATE(conn) == CONN_QUIT_SENT) {
|
||||
/* close the statement here, the connection has been closed */
|
||||
}
|
||||
stmt->state = MYSQLND_STMT_PREPARED;
|
||||
} else {
|
||||
SET_EMPTY_ERROR(stmt->error_info);
|
||||
SET_EMPTY_ERROR(stmt->conn->error_info);
|
||||
stmt->send_types_to_server = 0;
|
||||
stmt->upsert_status = conn->upsert_status;
|
||||
stmt->state = MYSQLND_STMT_EXECUTED;
|
||||
if (conn->last_query_type == QUERY_UPSERT || conn->last_query_type == QUERY_LOAD_LOCAL) {
|
||||
DBG_INF("PASS");
|
||||
DBG_RETURN(PASS);
|
||||
}
|
||||
|
||||
stmt->result->type = MYSQLND_RES_PS_BUF;
|
||||
if (!stmt->result->conn) {
|
||||
/*
|
||||
For SHOW we don't create (bypasses PS in server)
|
||||
a result set at prepare and thus a connection was missing
|
||||
*/
|
||||
stmt->result->conn = stmt->conn->m->get_reference(stmt->conn TSRMLS_CC);
|
||||
}
|
||||
|
||||
/* Update stmt->field_count as SHOW sets it to 0 at prepare */
|
||||
stmt->field_count = stmt->result->field_count = conn->field_count;
|
||||
stmt->result->lengths = NULL;
|
||||
if (stmt->field_count) {
|
||||
stmt->state = MYSQLND_STMT_WAITING_USE_OR_STORE;
|
||||
/*
|
||||
We need to set this because the user might not call
|
||||
use_result() or store_result() and we should be able to scrap the
|
||||
data on the line, if he just decides to close the statement.
|
||||
*/
|
||||
DBG_INF_FMT("server_status=%d cursor=%d", stmt->upsert_status.server_status,
|
||||
stmt->upsert_status.server_status & SERVER_STATUS_CURSOR_EXISTS);
|
||||
|
||||
if (stmt->upsert_status.server_status & SERVER_STATUS_CURSOR_EXISTS) {
|
||||
stmt->cursor_exists = TRUE;
|
||||
CONN_SET_STATE(conn, CONN_READY);
|
||||
/* Only cursor read */
|
||||
stmt->default_rset_handler = stmt->m->use_result;
|
||||
DBG_INF("use_result");
|
||||
} else if (stmt->flags & CURSOR_TYPE_READ_ONLY) {
|
||||
/*
|
||||
We have asked for CURSOR but got no cursor, because the condition
|
||||
above is not fulfilled. Then...
|
||||
|
||||
This is a single-row result set, a result set with no rows, EXPLAIN,
|
||||
SHOW VARIABLES, or some other command which either a) bypasses the
|
||||
cursors framework in the server and writes rows directly to the
|
||||
network or b) is more efficient if all (few) result set rows are
|
||||
precached on client and server's resources are freed.
|
||||
*/
|
||||
/* preferred is buffered read */
|
||||
stmt->default_rset_handler = stmt->m->store_result;
|
||||
DBG_INF("store_result");
|
||||
} else {
|
||||
/* preferred is unbuffered read */
|
||||
stmt->default_rset_handler = stmt->m->use_result;
|
||||
DBG_INF("use_result");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DBG_INF(ret == PASS? "PASS":"FAIL");
|
||||
DBG_RETURN(ret);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_stmt::execute */
|
||||
static enum_func_status
|
||||
MYSQLND_METHOD(mysqlnd_stmt, execute)(MYSQLND_STMT * const stmt TSRMLS_DC)
|
||||
|
@ -451,6 +583,12 @@ MYSQLND_METHOD(mysqlnd_stmt, execute)(MYSQLND_STMT * const stmt TSRMLS_DC)
|
|||
SET_ERROR_AFF_ROWS(stmt->conn);
|
||||
|
||||
if (stmt->state > MYSQLND_STMT_PREPARED && stmt->field_count) {
|
||||
/*
|
||||
We don need to copy the data from the buffers which we will clean.
|
||||
Because it has already been copied. See
|
||||
#ifndef WE_DONT_COPY_IN_BUFFERED_AND_UNBUFFERED_BECAUSEOF_IS_REF
|
||||
*/
|
||||
#ifdef WE_DONT_COPY_IN_BUFFERED_AND_UNBUFFERED_BECAUSEOF_IS_REF
|
||||
if (stmt->result_bind &&
|
||||
stmt->result_zvals_separated_once == TRUE &&
|
||||
stmt->state >= MYSQLND_STMT_USER_FETCHING)
|
||||
|
@ -474,6 +612,29 @@ MYSQLND_METHOD(mysqlnd_stmt, execute)(MYSQLND_STMT * const stmt TSRMLS_DC)
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
If right after execute() we have to call the appropriate
|
||||
use_result() or store_result() and clean.
|
||||
*/
|
||||
if (stmt->state == MYSQLND_STMT_WAITING_USE_OR_STORE) {
|
||||
DBG_INF("fetching result set header");
|
||||
/* Do implicit use_result and then flush the result */
|
||||
stmt->default_rset_handler = stmt->m->use_result;
|
||||
stmt->default_rset_handler(stmt TSRMLS_CC);
|
||||
}
|
||||
|
||||
if (stmt->state > MYSQLND_STMT_WAITING_USE_OR_STORE) {
|
||||
DBG_INF("skipping result");
|
||||
/* Flush if anything is left and unbuffered set */
|
||||
stmt->result->m.skip_result(stmt->result TSRMLS_CC);
|
||||
}
|
||||
|
||||
if (stmt->state > MYSQLND_STMT_PREPARED) {
|
||||
/* As the buffers have been freed, we should go back to PREPARED */
|
||||
stmt->state = MYSQLND_STMT_PREPARED;
|
||||
}
|
||||
|
||||
/*
|
||||
Executed, but the user hasn't started to fetch
|
||||
|
@ -534,79 +695,7 @@ MYSQLND_METHOD(mysqlnd_stmt, execute)(MYSQLND_STMT * const stmt TSRMLS_DC)
|
|||
}
|
||||
stmt->execute_count++;
|
||||
|
||||
CONN_SET_STATE(conn, CONN_QUERY_SENT);
|
||||
|
||||
ret = mysqlnd_query_read_result_set_header(stmt->conn, stmt TSRMLS_CC);
|
||||
if (ret == FAIL) {
|
||||
stmt->error_info = conn->error_info;
|
||||
stmt->upsert_status.affected_rows = conn->upsert_status.affected_rows;
|
||||
if (CONN_GET_STATE(conn) == CONN_QUIT_SENT) {
|
||||
/* close the statement here, the connection has been closed */
|
||||
}
|
||||
stmt->state = MYSQLND_STMT_PREPARED;
|
||||
} else {
|
||||
SET_EMPTY_ERROR(stmt->error_info);
|
||||
SET_EMPTY_ERROR(stmt->conn->error_info);
|
||||
stmt->send_types_to_server = 0;
|
||||
stmt->upsert_status = conn->upsert_status;
|
||||
stmt->state = MYSQLND_STMT_EXECUTED;
|
||||
if (conn->last_query_type == QUERY_UPSERT || conn->last_query_type == QUERY_LOAD_LOCAL) {
|
||||
DBG_INF("PASS");
|
||||
DBG_RETURN(PASS);
|
||||
}
|
||||
|
||||
stmt->result->type = MYSQLND_RES_PS_BUF;
|
||||
if (!stmt->result->conn) {
|
||||
/*
|
||||
For SHOW we don't create (bypasses PS in server)
|
||||
a result set at prepare and thus a connection was missing
|
||||
*/
|
||||
stmt->result->conn = stmt->conn->m->get_reference(stmt->conn);
|
||||
}
|
||||
|
||||
/* Update stmt->field_count as SHOW sets it to 0 at prepare */
|
||||
stmt->field_count = stmt->result->field_count = conn->field_count;
|
||||
stmt->result->lengths = NULL;
|
||||
if (stmt->field_count) {
|
||||
stmt->state = MYSQLND_STMT_WAITING_USE_OR_STORE;
|
||||
/*
|
||||
We need to set this because the user might not call
|
||||
use_result() or store_result() and we should be able to scrap the
|
||||
data on the line, if he just decides to close the statement.
|
||||
*/
|
||||
DBG_INF_FMT("server_status=%d cursor=%d", stmt->upsert_status.server_status,
|
||||
stmt->upsert_status.server_status & SERVER_STATUS_CURSOR_EXISTS);
|
||||
|
||||
if (stmt->upsert_status.server_status & SERVER_STATUS_CURSOR_EXISTS) {
|
||||
stmt->cursor_exists = TRUE;
|
||||
CONN_SET_STATE(conn, CONN_READY);
|
||||
/* Only cursor read */
|
||||
stmt->default_rset_handler = stmt->m->use_result;
|
||||
DBG_INF("use_result");
|
||||
} else if (stmt->flags & CURSOR_TYPE_READ_ONLY) {
|
||||
/*
|
||||
We have asked for CURSOR but got no cursor, because the condition
|
||||
above is not fulfilled. Then...
|
||||
|
||||
This is a single-row result set, a result set with no rows, EXPLAIN,
|
||||
SHOW VARIABLES, or some other command which either a) bypasses the
|
||||
cursors framework in the server and writes rows directly to the
|
||||
network or b) is more efficient if all (few) result set rows are
|
||||
precached on client and server's resources are freed.
|
||||
*/
|
||||
/* preferred is buffered read */
|
||||
stmt->default_rset_handler = stmt->m->store_result;
|
||||
DBG_INF("store_result");
|
||||
} else {
|
||||
/* preferred is unbuffered read */
|
||||
stmt->default_rset_handler = stmt->m->use_result;
|
||||
DBG_INF("use_result");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DBG_INF(ret == PASS? "PASS":"FAIL");
|
||||
DBG_RETURN(ret);
|
||||
DBG_RETURN(mysqlnd_stmt_execute_parse_response(stmt TSRMLS_CC));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -661,7 +750,9 @@ mysqlnd_fetch_stmt_row_buffered(MYSQLND_RES *result, void *param, unsigned int f
|
|||
for (i = 0; i < result->field_count; i++) {
|
||||
/* Clean what we copied last time */
|
||||
#ifndef WE_DONT_COPY_IN_BUFFERED_AND_UNBUFFERED_BECAUSEOF_IS_REF
|
||||
zval_dtor(stmt->result_bind[i].zv);
|
||||
if (stmt->result_bind[i].zv) {
|
||||
zval_dtor(stmt->result_bind[i].zv);
|
||||
}
|
||||
#endif
|
||||
/* copy the type */
|
||||
if (stmt->result_bind[i].bound == TRUE) {
|
||||
|
@ -978,7 +1069,7 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param, unsigned int fla
|
|||
stmt->conn->upsert_status.server_status =
|
||||
row_packet->server_status;
|
||||
|
||||
DBG_INF_FMT("ret=%s fetched=%d s_status=%d warns=%d eof=%d",
|
||||
DBG_INF_FMT("ret=%s fetched=%d server_status=%d warnings=%d eof=%d",
|
||||
ret == PASS? "PASS":"FAIL", *fetched_anything,
|
||||
row_packet->server_status, row_packet->warning_count,
|
||||
result->unbuf->eof_reached);
|
||||
|
@ -1079,8 +1170,13 @@ MYSQLND_METHOD(mysqlnd_stmt, reset)(MYSQLND_STMT * const stmt TSRMLS_DC)
|
|||
DBG_INF("skipping result");
|
||||
stmt->result->m.skip_result(stmt->result TSRMLS_CC);
|
||||
}
|
||||
|
||||
/* Now the line should be free, if it wasn't */
|
||||
|
||||
DBG_INF("freeing result");
|
||||
/* free_result() doesn't actually free stmt->result but only the buffers */
|
||||
stmt->m->free_result(stmt TSRMLS_CC);
|
||||
|
||||
int4store(cmd_buf, stmt->stmt_id);
|
||||
if (CONN_GET_STATE(conn) == CONN_READY &&
|
||||
FAIL == (ret = mysqlnd_simple_command(conn, COM_STMT_RESET, (char *)cmd_buf,
|
||||
|
@ -1365,8 +1461,6 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_result)(MYSQLND_STMT * const stmt,
|
|||
DBG_ENTER("mysqlnd_stmt::bind_result");
|
||||
DBG_INF_FMT("stmt=%lu field_count=%u", stmt->stmt_id, stmt->field_count);
|
||||
|
||||
SET_EMPTY_ERROR(stmt->error_info);
|
||||
SET_EMPTY_ERROR(stmt->conn->error_info);
|
||||
|
||||
if (stmt->state < MYSQLND_STMT_PREPARED) {
|
||||
SET_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared);
|
||||
|
@ -1377,6 +1471,9 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_result)(MYSQLND_STMT * const stmt,
|
|||
DBG_RETURN(FAIL);
|
||||
}
|
||||
|
||||
SET_EMPTY_ERROR(stmt->error_info);
|
||||
SET_EMPTY_ERROR(stmt->conn->error_info);
|
||||
|
||||
if (stmt->field_count) {
|
||||
uint i = 0;
|
||||
|
||||
|
@ -1386,7 +1483,7 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_result)(MYSQLND_STMT * const stmt,
|
|||
}
|
||||
|
||||
mysqlnd_stmt_separate_result_bind(stmt TSRMLS_CC);
|
||||
|
||||
stmt->result_zvals_separated_once = FALSE;
|
||||
stmt->result_bind = result_bind;
|
||||
for (i = 0; i < stmt->field_count; i++) {
|
||||
/* Prevent from freeing */
|
||||
|
@ -1407,6 +1504,50 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_result)(MYSQLND_STMT * const stmt,
|
|||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_stmt::bind_result */
|
||||
static enum_func_status
|
||||
MYSQLND_METHOD(mysqlnd_stmt, bind_one_result)(MYSQLND_STMT * const stmt, uint param_no TSRMLS_DC)
|
||||
{
|
||||
DBG_ENTER("mysqlnd_stmt::bind_result");
|
||||
DBG_INF_FMT("stmt=%lu field_count=%u", stmt->stmt_id, stmt->field_count);
|
||||
|
||||
if (stmt->state < MYSQLND_STMT_PREPARED) {
|
||||
SET_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared);
|
||||
DBG_ERR("not prepared");
|
||||
DBG_RETURN(FAIL);
|
||||
}
|
||||
|
||||
if (param_no < 0 || param_no >= stmt->field_count) {
|
||||
SET_STMT_ERROR(stmt, CR_INVALID_PARAMETER_NO, UNKNOWN_SQLSTATE, "Invalid parameter number");
|
||||
DBG_ERR("invalid param_no");
|
||||
DBG_RETURN(FAIL);
|
||||
}
|
||||
|
||||
SET_EMPTY_ERROR(stmt->error_info);
|
||||
SET_EMPTY_ERROR(stmt->conn->error_info);
|
||||
|
||||
if (stmt->field_count) {
|
||||
mysqlnd_stmt_separate_one_result_bind(stmt, param_no TSRMLS_CC);
|
||||
/* Guaranteed is that stmt->result_bind is NULL */
|
||||
if (!stmt->result_bind) {
|
||||
stmt->result_bind = ecalloc(stmt->field_count, sizeof(MYSQLND_RESULT_BIND));
|
||||
} else {
|
||||
stmt->result_bind = erealloc(stmt->result_bind, stmt->field_count * sizeof(MYSQLND_RESULT_BIND));
|
||||
}
|
||||
ALLOC_INIT_ZVAL(stmt->result_bind[param_no].zv);
|
||||
/*
|
||||
Don't update is_ref !!! it's not our job
|
||||
Otherwise either 009.phpt or mysqli_stmt_bind_result.phpt
|
||||
will fail.
|
||||
*/
|
||||
stmt->result_bind[param_no].bound = TRUE;
|
||||
}
|
||||
DBG_INF("PASS");
|
||||
DBG_RETURN(PASS);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_stmt::set_bind_result_dtor */
|
||||
static void
|
||||
MYSQLND_METHOD(mysqlnd_stmt, set_result_bind_dtor)(MYSQLND_STMT * const stmt,
|
||||
|
@ -1613,7 +1754,7 @@ MYSQLND_METHOD(mysqlnd_stmt, attr_set)(MYSQLND_STMT * const stmt,
|
|||
|
||||
/* {{{ mysqlnd_stmt::attr_get */
|
||||
static enum_func_status
|
||||
MYSQLND_METHOD(mysqlnd_stmt, attr_get)(MYSQLND_STMT * const stmt,
|
||||
MYSQLND_METHOD(mysqlnd_stmt, attr_get)(const MYSQLND_STMT * const stmt,
|
||||
enum mysqlnd_stmt_attr attr_type,
|
||||
void * const value TSRMLS_DC)
|
||||
{
|
||||
|
@ -1638,7 +1779,7 @@ MYSQLND_METHOD(mysqlnd_stmt, attr_get)(MYSQLND_STMT * const stmt,
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* free_result() doesn't actually free stmt->result but only the buffers */
|
||||
/* {{{ mysqlnd_stmt::free_result */
|
||||
static enum_func_status
|
||||
MYSQLND_METHOD(mysqlnd_stmt, free_result)(MYSQLND_STMT * const stmt TSRMLS_DC)
|
||||
|
@ -1651,6 +1792,10 @@ MYSQLND_METHOD(mysqlnd_stmt, free_result)(MYSQLND_STMT * const stmt TSRMLS_DC)
|
|||
DBG_RETURN(PASS);
|
||||
}
|
||||
|
||||
/*
|
||||
If right after execute() we have to call the appropriate
|
||||
use_result() or store_result() and clean.
|
||||
*/
|
||||
if (stmt->state == MYSQLND_STMT_WAITING_USE_OR_STORE) {
|
||||
DBG_INF("fetching result set header");
|
||||
/* Do implicit use_result and then flush the result */
|
||||
|
@ -1672,8 +1817,10 @@ MYSQLND_METHOD(mysqlnd_stmt, free_result)(MYSQLND_STMT * const stmt TSRMLS_DC)
|
|||
stmt->result->m.free_result_buffers(stmt->result TSRMLS_CC);
|
||||
}
|
||||
|
||||
/* As the buffers have been freed, we should go back to PREPARED */
|
||||
stmt->state = MYSQLND_STMT_PREPARED;
|
||||
if (stmt->state > MYSQLND_STMT_PREPARED) {
|
||||
/* As the buffers have been freed, we should go back to PREPARED */
|
||||
stmt->state = MYSQLND_STMT_PREPARED;
|
||||
}
|
||||
|
||||
/* Line is free! */
|
||||
CONN_SET_STATE(stmt->conn, CONN_READY);
|
||||
|
@ -1737,9 +1884,55 @@ void mysqlnd_stmt_separate_result_bind(MYSQLND_STMT * const stmt TSRMLS_DC)
|
|||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_stmt_separate_one_result_bind */
|
||||
void mysqlnd_stmt_separate_one_result_bind(MYSQLND_STMT * const stmt, uint param_no TSRMLS_DC)
|
||||
{
|
||||
DBG_ENTER("mysqlnd_stmt_separate_one_result_bind");
|
||||
DBG_INF_FMT("stmt=%lu result_bind=%p field_count=%u param_no=%d",
|
||||
stmt->stmt_id, stmt->result_bind, stmt->field_count, param_no);
|
||||
|
||||
if (!stmt->result_bind) {
|
||||
DBG_VOID_RETURN;
|
||||
}
|
||||
|
||||
/*
|
||||
Because only the bound variables can point to our internal buffers, then
|
||||
separate or free only them. Free is possible because the user could have
|
||||
lost reference.
|
||||
*/
|
||||
/* Let's try with no cache */
|
||||
if (stmt->result_bind[param_no].bound == TRUE) {
|
||||
DBG_INF_FMT("%d has refcount=%u", param_no, Z_REFCOUNT_P(stmt->result_bind[param_no].zv));
|
||||
/*
|
||||
We have to separate the actual zval value of the bound
|
||||
variable from our allocated zvals or we will face double-free
|
||||
*/
|
||||
if (Z_REFCOUNT_P(stmt->result_bind[param_no].zv) > 1) {
|
||||
#ifdef WE_DONT_COPY_IN_BUFFERED_AND_UNBUFFERED_BECAUSEOF_IS_REF
|
||||
zval_copy_ctor(stmt->result_bind[param_no].zv);
|
||||
#endif
|
||||
zval_ptr_dtor(&stmt->result_bind[param_no].zv);
|
||||
} else {
|
||||
/*
|
||||
If it is a string, what is pointed will be freed
|
||||
later in free_result(). We need to remove the variable to
|
||||
which the user has lost reference.
|
||||
*/
|
||||
#ifdef WE_DONT_COPY_IN_BUFFERED_AND_UNBUFFERED_BECAUSEOF_IS_REF
|
||||
ZVAL_NULL(stmt->result_bind[param_no].zv);
|
||||
#endif
|
||||
zval_ptr_dtor(&stmt->result_bind[param_no].zv);
|
||||
}
|
||||
}
|
||||
|
||||
DBG_VOID_RETURN;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_internal_free_stmt_content */
|
||||
static
|
||||
void mysqlnd_internal_free_stmt_content(MYSQLND_STMT *stmt TSRMLS_DC)
|
||||
void mysqlnd_internal_free_stmt_content(MYSQLND_STMT * const stmt TSRMLS_DC)
|
||||
{
|
||||
DBG_ENTER("mysqlnd_internal_free_stmt_content");
|
||||
DBG_INF_FMT("stmt=%lu param_bind=%p param_count=%u",
|
||||
|
@ -1778,24 +1971,15 @@ void mysqlnd_internal_free_stmt_content(MYSQLND_STMT *stmt TSRMLS_DC)
|
|||
stmt->result->m.free_result_internal(stmt->result TSRMLS_CC);
|
||||
stmt->result = NULL;
|
||||
}
|
||||
if (stmt->cmd_buffer.buffer) {
|
||||
mnd_efree(stmt->cmd_buffer.buffer);
|
||||
stmt->cmd_buffer.buffer = NULL;
|
||||
}
|
||||
|
||||
if (stmt->conn) {
|
||||
stmt->conn->m->free_reference(stmt->conn TSRMLS_CC);
|
||||
stmt->conn = NULL;
|
||||
}
|
||||
|
||||
DBG_VOID_RETURN;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_stmt::close */
|
||||
/* {{{ mysqlnd_stmt::net_close */
|
||||
static enum_func_status
|
||||
MYSQLND_METHOD(mysqlnd_stmt, close)(MYSQLND_STMT * const stmt, zend_bool implicit TSRMLS_DC)
|
||||
MYSQLND_METHOD_PRIVATE(mysqlnd_stmt, net_close)(MYSQLND_STMT * const stmt, zend_bool implicit TSRMLS_DC)
|
||||
{
|
||||
MYSQLND * conn = stmt->conn;
|
||||
zend_uchar cmd_buf[STMT_ID_LENGTH /* statement id */];
|
||||
|
@ -1854,16 +2038,25 @@ MYSQLND_METHOD(mysqlnd_stmt, close)(MYSQLND_STMT * const stmt, zend_bool implici
|
|||
MYSQLND_INC_CONN_STATISTIC(&conn->stats, stat);
|
||||
}
|
||||
|
||||
if (stmt->execute_cmd_buffer.buffer) {
|
||||
mnd_efree(stmt->execute_cmd_buffer.buffer);
|
||||
stmt->execute_cmd_buffer.buffer = NULL;
|
||||
}
|
||||
|
||||
mysqlnd_internal_free_stmt_content(stmt TSRMLS_CC);
|
||||
|
||||
if (stmt->conn) {
|
||||
stmt->conn->m->free_reference(stmt->conn TSRMLS_CC);
|
||||
stmt->conn = NULL;
|
||||
}
|
||||
|
||||
DBG_RETURN(PASS);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_stmt::dtor */
|
||||
static enum_func_status
|
||||
MYSQLND_METHOD_PRIVATE(mysqlnd_stmt, dtor)(MYSQLND_STMT * const stmt, zend_bool implicit TSRMLS_DC)
|
||||
MYSQLND_METHOD(mysqlnd_stmt, dtor)(MYSQLND_STMT * const stmt, zend_bool implicit TSRMLS_DC)
|
||||
{
|
||||
enum_func_status ret;
|
||||
|
||||
|
@ -1873,9 +2066,8 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_stmt, dtor)(MYSQLND_STMT * const stmt, zend_bool
|
|||
MYSQLND_INC_GLOBAL_STATISTIC(implicit == TRUE? STAT_STMT_CLOSE_IMPLICIT:
|
||||
STAT_STMT_CLOSE_EXPLICIT);
|
||||
|
||||
if (PASS == (ret = stmt->m->close(stmt, implicit TSRMLS_CC))) {
|
||||
mnd_efree(stmt);
|
||||
}
|
||||
ret = stmt->m->net_close(stmt, implicit TSRMLS_CC);
|
||||
mnd_efree(stmt);
|
||||
|
||||
DBG_INF(ret == PASS? "PASS":"FAIL");
|
||||
DBG_RETURN(ret);
|
||||
|
@ -1891,11 +2083,13 @@ struct st_mysqlnd_stmt_methods mysqlnd_stmt_methods = {
|
|||
MYSQLND_METHOD(mysqlnd_stmt, store_result),
|
||||
MYSQLND_METHOD(mysqlnd_stmt, background_store_result),
|
||||
MYSQLND_METHOD(mysqlnd_stmt, get_result),
|
||||
MYSQLND_METHOD(mysqlnd_stmt, more_results),
|
||||
MYSQLND_METHOD(mysqlnd_stmt, next_result),
|
||||
MYSQLND_METHOD(mysqlnd_stmt, free_result),
|
||||
MYSQLND_METHOD(mysqlnd_stmt, data_seek),
|
||||
MYSQLND_METHOD(mysqlnd_stmt, reset),
|
||||
MYSQLND_METHOD(mysqlnd_stmt, close),
|
||||
MYSQLND_METHOD_PRIVATE(mysqlnd_stmt, dtor),
|
||||
MYSQLND_METHOD_PRIVATE(mysqlnd_stmt, net_close),
|
||||
MYSQLND_METHOD(mysqlnd_stmt, dtor),
|
||||
|
||||
MYSQLND_METHOD(mysqlnd_stmt, fetch),
|
||||
|
||||
|
@ -1904,6 +2098,7 @@ struct st_mysqlnd_stmt_methods mysqlnd_stmt_methods = {
|
|||
MYSQLND_METHOD(mysqlnd_stmt, refresh_bind_param),
|
||||
MYSQLND_METHOD(mysqlnd_stmt, set_param_bind_dtor),
|
||||
MYSQLND_METHOD(mysqlnd_stmt, bind_result),
|
||||
MYSQLND_METHOD(mysqlnd_stmt, bind_one_result),
|
||||
MYSQLND_METHOD(mysqlnd_stmt, set_result_bind_dtor),
|
||||
MYSQLND_METHOD(mysqlnd_stmt, send_long_data),
|
||||
MYSQLND_METHOD(mysqlnd_stmt, param_metadata),
|
||||
|
@ -1936,8 +2131,8 @@ MYSQLND_STMT * _mysqlnd_stmt_init(MYSQLND * const conn TSRMLS_DC)
|
|||
|
||||
stmt->m = &mysqlnd_stmt_methods;
|
||||
stmt->state = MYSQLND_STMT_INITTED;
|
||||
stmt->cmd_buffer.length = 4096;
|
||||
stmt->cmd_buffer.buffer = mnd_emalloc(stmt->cmd_buffer.length);
|
||||
stmt->execute_cmd_buffer.length = 4096;
|
||||
stmt->execute_cmd_buffer.buffer = mnd_emalloc(stmt->execute_cmd_buffer.length);
|
||||
|
||||
stmt->prefetch_rows = MYSQLND_DEFAULT_PREFETCH_ROWS;
|
||||
/*
|
||||
|
@ -1945,7 +2140,7 @@ MYSQLND_STMT * _mysqlnd_stmt_init(MYSQLND * const conn TSRMLS_DC)
|
|||
be destructed till there is open statements. The last statement
|
||||
or normal query result will close it then.
|
||||
*/
|
||||
stmt->conn = conn->m->get_reference(conn);
|
||||
stmt->conn = conn->m->get_reference(conn TSRMLS_CC);
|
||||
|
||||
stmt->m->set_param_bind_dtor(stmt, mysqlnd_efree_param_bind_dtor TSRMLS_CC);
|
||||
stmt->m->set_result_bind_dtor(stmt, mysqlnd_efree_result_bind_dtor TSRMLS_CC);
|
||||
|
|
|
@ -771,9 +771,9 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT *stmt, zend_uchar **buf, zend_uch
|
|||
zend_uchar* mysqlnd_stmt_execute_generate_request(MYSQLND_STMT *stmt, size_t *request_len,
|
||||
zend_bool *free_buffer TSRMLS_DC)
|
||||
{
|
||||
zend_uchar *p = stmt->cmd_buffer.buffer,
|
||||
*cmd_buffer = stmt->cmd_buffer.buffer;
|
||||
size_t cmd_buffer_length = stmt->cmd_buffer.length;
|
||||
zend_uchar *p = stmt->execute_cmd_buffer.buffer,
|
||||
*cmd_buffer = stmt->execute_cmd_buffer.buffer;
|
||||
size_t cmd_buffer_length = stmt->execute_cmd_buffer.length;
|
||||
unsigned int null_byte_offset,
|
||||
null_count= (stmt->param_count + 7) / 8;
|
||||
|
||||
|
@ -801,7 +801,7 @@ zend_uchar* mysqlnd_stmt_execute_generate_request(MYSQLND_STMT *stmt, size_t *re
|
|||
|
||||
mysqlnd_stmt_execute_store_params(stmt, &cmd_buffer, &p, &cmd_buffer_length, null_byte_offset TSRMLS_CC);
|
||||
|
||||
*free_buffer = (cmd_buffer != stmt->cmd_buffer.buffer);
|
||||
*free_buffer = (cmd_buffer != stmt->execute_cmd_buffer.buffer);
|
||||
*request_len = (p - cmd_buffer);
|
||||
return cmd_buffer;
|
||||
}
|
||||
|
|
|
@ -177,6 +177,7 @@ void mysqlnd_unbuffered_free_last_data(MYSQLND_RES *result TSRMLS_DC)
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_free_buffered_data */
|
||||
void mysqlnd_free_buffered_data(MYSQLND_RES *result TSRMLS_DC)
|
||||
{
|
||||
|
@ -231,6 +232,7 @@ void mysqlnd_free_buffered_data(MYSQLND_RES *result TSRMLS_DC)
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
#ifdef MYSQLND_THREADED
|
||||
/* {{{ mysqlnd_free_background_buffered_data */
|
||||
void mysqlnd_free_background_buffered_data(MYSQLND_RES *result TSRMLS_DC)
|
||||
|
@ -309,8 +311,9 @@ void mysqlnd_free_background_buffered_data(MYSQLND_RES *result TSRMLS_DC)
|
|||
/* }}} */
|
||||
#endif /* MYSQL_THREADING */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_res::free_result_buffers */
|
||||
void
|
||||
static void
|
||||
MYSQLND_METHOD(mysqlnd_res, free_result_buffers)(MYSQLND_RES *result TSRMLS_DC)
|
||||
{
|
||||
DBG_ENTER("mysqlnd_res::free_result_buffers");
|
||||
|
@ -580,8 +583,15 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC
|
|||
stmt->state = MYSQLND_STMT_INITTED;
|
||||
}
|
||||
} else {
|
||||
DBG_INF_FMT("warns=%u status=%u", fields_eof.warning_count, fields_eof.server_status);
|
||||
DBG_INF_FMT("warnings=%u server_status=%u", fields_eof.warning_count, fields_eof.server_status);
|
||||
conn->upsert_status.warning_count = fields_eof.warning_count;
|
||||
/*
|
||||
If SERVER_MORE_RESULTS_EXISTS is set then this is either MULTI_QUERY or a CALL()
|
||||
The first packet after sending the query/com_execute has the bit set only
|
||||
in this cases. Not sure why it's a needed but it marks that the whole stream
|
||||
will include many result sets. What actually matters are the bits set at the end
|
||||
of every result set (the EOF packet).
|
||||
*/
|
||||
conn->upsert_status.server_status = fields_eof.server_status;
|
||||
if (fields_eof.server_status & MYSQLND_SERVER_QUERY_NO_GOOD_INDEX_USED) {
|
||||
stat = STAT_BAD_INDEX_USED;
|
||||
|
@ -789,7 +799,7 @@ mysqlnd_fetch_row_unbuffered_c(MYSQLND_RES *result TSRMLS_DC)
|
|||
result->unbuf->eof_reached = TRUE; /* so next time we won't get an error */
|
||||
} else if (row_packet->eof) {
|
||||
/* Mark the connection as usable again */
|
||||
DBG_INF_FMT("warns=%u status=%u", row_packet->warning_count, row_packet->server_status);
|
||||
DBG_INF_FMT("warningss=%u server_status=%u", row_packet->warning_count, row_packet->server_status);
|
||||
result->unbuf->eof_reached = TRUE;
|
||||
result->conn->upsert_status.warning_count = row_packet->warning_count;
|
||||
result->conn->upsert_status.server_status = row_packet->server_status;
|
||||
|
@ -929,7 +939,7 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int flag
|
|||
result->unbuf->eof_reached = TRUE; /* so next time we won't get an error */
|
||||
} else if (row_packet->eof) {
|
||||
/* Mark the connection as usable again */
|
||||
DBG_INF_FMT("warns=%u status=%u", row_packet->warning_count, row_packet->server_status);
|
||||
DBG_INF_FMT("warnings=%u server_status=%u", row_packet->warning_count, row_packet->server_status);
|
||||
result->unbuf->eof_reached = TRUE;
|
||||
result->conn->upsert_status.warning_count = row_packet->warning_count;
|
||||
result->conn->upsert_status.server_status = row_packet->server_status;
|
||||
|
@ -1261,7 +1271,7 @@ mysqlnd_store_result_fetch_data(MYSQLND * const conn, MYSQLND_RES *result,
|
|||
}
|
||||
PACKET_FREE(row_packet);
|
||||
|
||||
DBG_INF_FMT("ret=%s row_count=%u warns=%u status=%u", ret == PASS? "PASS":"FAIL",
|
||||
DBG_INF_FMT("ret=%s row_count=%u warnings=%u server_status=%u", ret == PASS? "PASS":"FAIL",
|
||||
set->row_count, conn->upsert_status.warning_count, conn->upsert_status.server_status);
|
||||
DBG_RETURN(ret);
|
||||
}
|
||||
|
@ -1281,7 +1291,7 @@ MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result,
|
|||
DBG_INF_FMT("conn=%d ps_protocol=%d", conn->thread_id, ps_protocol);
|
||||
|
||||
/* We need the conn because we are doing lazy zval initialization in buffered_fetch_row */
|
||||
result->conn = conn->m->get_reference(conn);
|
||||
result->conn = conn->m->get_reference(conn TSRMLS_CC);
|
||||
result->type = MYSQLND_RES_NORMAL;
|
||||
result->m.fetch_row = result->m.fetch_row_normal_buffered;
|
||||
result->m.fetch_lengths = mysqlnd_fetch_lengths_buffered;
|
||||
|
@ -1305,6 +1315,7 @@ MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result,
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
#ifdef MYSQLND_THREADED
|
||||
/* {{{ mysqlnd_fetch_row_async_buffered */
|
||||
static enum_func_status
|
||||
|
@ -1432,6 +1443,7 @@ mysqlnd_fetch_row_async_buffered(MYSQLND_RES *result, void *param, unsigned int
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_background_store_result_fetch_data */
|
||||
enum_func_status
|
||||
mysqlnd_background_store_result_fetch_data(MYSQLND_RES *result TSRMLS_DC)
|
||||
|
@ -1465,7 +1477,9 @@ mysqlnd_background_store_result_fetch_data(MYSQLND_RES *result TSRMLS_DC)
|
|||
old_size = set->data_size;
|
||||
set->data_size = total_rows;
|
||||
set->data = mnd_perealloc(set->data, set->data_size * sizeof(zval **), set->persistent);
|
||||
// memset(set->data + old_size, 0, (set->data_size - old_size) * sizeof(zval **));
|
||||
#if 0
|
||||
memset(set->data + old_size, 0, (set->data_size - old_size) * sizeof(zval **));
|
||||
#endif
|
||||
set->row_buffers = mnd_perealloc(set->row_buffers,
|
||||
total_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *),
|
||||
set->persistent);
|
||||
|
@ -1511,11 +1525,12 @@ mysqlnd_background_store_result_fetch_data(MYSQLND_RES *result TSRMLS_DC)
|
|||
transfered above.
|
||||
*/
|
||||
}
|
||||
// MYSQLND_INC_CONN_STATISTIC_W_VALUE(&conn->stats,
|
||||
// binary_protocol? STAT_ROWS_BUFFERED_FROM_CLIENT_PS:
|
||||
// STAT_ROWS_BUFFERED_FROM_CLIENT_NORMAL,
|
||||
// set->row_count);
|
||||
|
||||
#if 0
|
||||
MYSQLND_INC_CONN_STATISTIC_W_VALUE(&conn->stats,
|
||||
binary_protocol? STAT_ROWS_BUFFERED_FROM_CLIENT_PS:
|
||||
STAT_ROWS_BUFFERED_FROM_CLIENT_NORMAL,
|
||||
set->row_count);
|
||||
#endif
|
||||
tsrm_mutex_lock(set->LOCK);
|
||||
/* Finally clean */
|
||||
if (row_packet->eof) {
|
||||
|
@ -1551,7 +1566,7 @@ mysqlnd_background_store_result_fetch_data(MYSQLND_RES *result TSRMLS_DC)
|
|||
} else {
|
||||
CONN_SET_STATE(conn, CONN_READY);
|
||||
}
|
||||
DBG_INF_FMT("ret=%s row_count=%u warns=%u status=%u", ret == PASS? "PASS":"FAIL",
|
||||
DBG_INF_FMT("ret=%s row_count=%u warnings=%u server_status=%u", ret == PASS? "PASS":"FAIL",
|
||||
set->row_count, conn->upsert_status.warning_count, conn->upsert_status.server_status);
|
||||
DBG_RETURN(ret);
|
||||
}
|
||||
|
@ -1560,7 +1575,7 @@ mysqlnd_background_store_result_fetch_data(MYSQLND_RES *result TSRMLS_DC)
|
|||
|
||||
|
||||
/* {{{ mysqlnd_res::background_store_result */
|
||||
MYSQLND_RES *
|
||||
static MYSQLND_RES *
|
||||
MYSQLND_METHOD(mysqlnd_res, background_store_result)(MYSQLND_RES * result, MYSQLND * const conn, zend_bool ps TSRMLS_DC)
|
||||
{
|
||||
#ifndef MYSQLND_THREADED
|
||||
|
@ -1573,7 +1588,7 @@ MYSQLND_METHOD(mysqlnd_res, background_store_result)(MYSQLND_RES * result, MYSQL
|
|||
DBG_INF_FMT("conn=%d ps_protocol=%d", conn->thread_id, ps);
|
||||
|
||||
/* We need the conn because we are doing lazy zval initialization in buffered_fetch_row */
|
||||
result->conn = conn->m->get_reference(conn);
|
||||
result->conn = conn->m->get_reference(conn TSRMLS_CC);
|
||||
result->type = MYSQLND_RES_NORMAL;
|
||||
result->m.fetch_row = mysqlnd_fetch_row_async_buffered;
|
||||
result->m.fetch_lengths = mysqlnd_fetch_lengths_async_buffered;
|
||||
|
|
|
@ -241,7 +241,7 @@ struct st_mysqlnd_conn_methods
|
|||
MYSQLND_RES * (*store_result)(MYSQLND * const conn TSRMLS_DC);
|
||||
MYSQLND_RES * (*background_store_result)(MYSQLND * const conn TSRMLS_DC);
|
||||
enum_func_status (*next_result)(MYSQLND * const conn TSRMLS_DC);
|
||||
zend_bool (*more_results)(const MYSQLND * const conn);
|
||||
zend_bool (*more_results)(const MYSQLND * const conn TSRMLS_DC);
|
||||
|
||||
MYSQLND_STMT * (*stmt_init)(MYSQLND * const conn TSRMLS_DC);
|
||||
|
||||
|
@ -282,7 +282,7 @@ struct st_mysqlnd_conn_methods
|
|||
enum_func_status (*close)(MYSQLND *conn, enum_connection_close_type close_type TSRMLS_DC);
|
||||
void (*dtor)(MYSQLND *conn TSRMLS_DC); /* private */
|
||||
|
||||
MYSQLND * (*get_reference)(MYSQLND * const conn);
|
||||
MYSQLND * (*get_reference)(MYSQLND * const conn TSRMLS_DC);
|
||||
enum_func_status (*free_reference)(MYSQLND * const conn TSRMLS_DC);
|
||||
enum mysqlnd_connection_state (*get_state)(MYSQLND * const conn TSRMLS_DC);
|
||||
void (*set_state)(MYSQLND * const conn, enum mysqlnd_connection_state new_state TSRMLS_DC);
|
||||
|
@ -344,10 +344,12 @@ struct st_mysqlnd_stmt_methods
|
|||
MYSQLND_RES * (*store_result)(MYSQLND_STMT * const stmt TSRMLS_DC);
|
||||
MYSQLND_RES * (*background_store_result)(MYSQLND_STMT * const stmt TSRMLS_DC);
|
||||
MYSQLND_RES * (*get_result)(MYSQLND_STMT * const stmt TSRMLS_DC);
|
||||
zend_bool (*more_results)(const MYSQLND_STMT * const stmt TSRMLS_DC);
|
||||
enum_func_status (*next_result)(MYSQLND_STMT * const stmt TSRMLS_DC);
|
||||
enum_func_status (*free_result)(MYSQLND_STMT * const stmt TSRMLS_DC);
|
||||
enum_func_status (*seek_data)(const MYSQLND_STMT * const stmt, uint64 row TSRMLS_DC);
|
||||
enum_func_status (*reset)(MYSQLND_STMT * const stmt TSRMLS_DC);
|
||||
enum_func_status (*close)(MYSQLND_STMT * const stmt, zend_bool implicit TSRMLS_DC); /* private */
|
||||
enum_func_status (*net_close)(MYSQLND_STMT * const stmt, zend_bool implicit TSRMLS_DC); /* private */
|
||||
enum_func_status (*dtor)(MYSQLND_STMT * const stmt, zend_bool implicit TSRMLS_DC); /* use this for mysqlnd_stmt_close */
|
||||
|
||||
enum_func_status (*fetch)(MYSQLND_STMT * const stmt, zend_bool * const fetched_anything TSRMLS_DC);
|
||||
|
@ -357,6 +359,7 @@ struct st_mysqlnd_stmt_methods
|
|||
enum_func_status (*refresh_bind_param)(MYSQLND_STMT * const stmt TSRMLS_DC);
|
||||
void (*set_param_bind_dtor)(MYSQLND_STMT * const stmt, void (*param_bind_dtor)(MYSQLND_PARAM_BIND *) TSRMLS_DC);
|
||||
enum_func_status (*bind_result)(MYSQLND_STMT * const stmt, MYSQLND_RESULT_BIND * const result_bind TSRMLS_DC);
|
||||
enum_func_status (*bind_one_result)(MYSQLND_STMT * const stmt, uint param_no TSRMLS_DC);
|
||||
void (*set_result_bind_dtor)(MYSQLND_STMT * const stmt, void (*result_bind_dtor)(MYSQLND_RESULT_BIND *) TSRMLS_DC);
|
||||
enum_func_status (*send_long_data)(MYSQLND_STMT * const stmt, unsigned int param_num,
|
||||
const char * const data, unsigned long length TSRMLS_DC);
|
||||
|
@ -375,7 +378,7 @@ struct st_mysqlnd_stmt_methods
|
|||
const char * (*get_error_str)(const MYSQLND_STMT * const stmt);
|
||||
const char * (*get_sqlstate)(const MYSQLND_STMT * const stmt);
|
||||
|
||||
enum_func_status (*get_attribute)(MYSQLND_STMT * const stmt, enum mysqlnd_stmt_attr attr_type, void * const value TSRMLS_DC);
|
||||
enum_func_status (*get_attribute)(const MYSQLND_STMT * const stmt, enum mysqlnd_stmt_attr attr_type, void * const value TSRMLS_DC);
|
||||
enum_func_status (*set_attribute)(MYSQLND_STMT * const stmt, enum mysqlnd_stmt_attr attr_type, const void * const value TSRMLS_DC);
|
||||
};
|
||||
|
||||
|
@ -587,7 +590,6 @@ struct st_mysqlnd_param_bind
|
|||
struct st_mysqlnd_result_bind
|
||||
{
|
||||
zval *zv;
|
||||
zend_uchar original_type;
|
||||
zend_bool bound;
|
||||
};
|
||||
|
||||
|
@ -617,7 +619,7 @@ struct st_mysqlnd_stmt
|
|||
zend_bool cursor_exists;
|
||||
mysqlnd_stmt_use_or_store_func default_rset_handler;
|
||||
|
||||
MYSQLND_CMD_BUFFER cmd_buffer;
|
||||
MYSQLND_CMD_BUFFER execute_cmd_buffer;
|
||||
unsigned int execute_count;/* count how many times the stmt was executed */
|
||||
|
||||
void (*param_bind_dtor)(MYSQLND_PARAM_BIND *);
|
||||
|
|
|
@ -587,6 +587,13 @@ php_mysqlnd_greet_read(void *_packet, MYSQLND *conn TSRMLS_DC)
|
|||
} else {
|
||||
packet->pre41 = TRUE;
|
||||
}
|
||||
|
||||
DBG_INF_FMT("proto=%d server=%s thread_id=%ld",
|
||||
packet->protocol_version, packet->server_version, packet->thread_id);
|
||||
|
||||
DBG_INF_FMT("server_capabilities=%d charset_no=%d server_status=%d",
|
||||
packet->server_capabilities, packet->charset_no, packet->server_status);
|
||||
|
||||
if (p - begin > packet->header.size) {
|
||||
DBG_ERR_FMT("GREET packet %d bytes shorter than expected", p - begin - packet->header.size);
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "GREET packet %d bytes shorter than expected. PID=%d",
|
||||
|
@ -783,8 +790,8 @@ php_mysqlnd_ok_read(void *_packet, MYSQLND *conn TSRMLS_DC)
|
|||
}
|
||||
|
||||
DBG_INF_FMT("OK packet: aff_rows=%lld last_ins_id=%ld server_status=%d warnings=%d",
|
||||
packet->affected_rows, packet->last_insert_id, packet->server_status,
|
||||
packet->warning_count);
|
||||
packet->affected_rows, packet->last_insert_id, packet->server_status,
|
||||
packet->warning_count);
|
||||
|
||||
if (p - begin > packet->header.size) {
|
||||
DBG_ERR_FMT("OK packet %d bytes shorter than expected", p - begin - packet->header.size);
|
||||
|
@ -865,7 +872,8 @@ php_mysqlnd_eof_read(void *_packet, MYSQLND *conn TSRMLS_DC)
|
|||
p - begin - packet->header.size, getpid());
|
||||
}
|
||||
|
||||
DBG_INF_FMT("EOF packet: status=%d warnings=%d", packet->server_status, packet->warning_count);
|
||||
DBG_INF_FMT("EOF packet: fields=%d status=%d warnings=%d",
|
||||
packet->field_count, packet->server_status, packet->warning_count);
|
||||
|
||||
DBG_RETURN(PASS);
|
||||
}
|
||||
|
@ -986,6 +994,7 @@ php_mysqlnd_rset_header_read(void *_packet, MYSQLND *conn TSRMLS_DC)
|
|||
packet->field_count= php_mysqlnd_net_field_length(&p);
|
||||
switch (packet->field_count) {
|
||||
case MYSQLND_NULL_LENGTH:
|
||||
DBG_INF("LOAD LOCAL");
|
||||
/*
|
||||
First byte in the packet is the field count.
|
||||
Thus, the name is size - 1. And we add 1 for a trailing \0.
|
||||
|
@ -997,6 +1006,7 @@ php_mysqlnd_rset_header_read(void *_packet, MYSQLND *conn TSRMLS_DC)
|
|||
packet->info_or_local_file_len = len;
|
||||
break;
|
||||
case 0x00:
|
||||
DBG_INF("UPSERT");
|
||||
packet->affected_rows = php_mysqlnd_net_field_length_ll(&p);
|
||||
packet->last_insert_id= php_mysqlnd_net_field_length_ll(&p);
|
||||
packet->server_status = uint2korr(p);
|
||||
|
@ -1010,13 +1020,17 @@ php_mysqlnd_rset_header_read(void *_packet, MYSQLND *conn TSRMLS_DC)
|
|||
packet->info_or_local_file[len] = '\0';
|
||||
packet->info_or_local_file_len = len;
|
||||
}
|
||||
DBG_INF_FMT("affected_rows=%llu last_insert_id=%llu server_status=%d warning_count=%d",
|
||||
packet->affected_rows, packet->last_insert_id,
|
||||
packet->server_status, packet->warning_count);
|
||||
break;
|
||||
default:
|
||||
DBG_INF("SELECT");
|
||||
/* Result set */
|
||||
break;
|
||||
}
|
||||
if (p - begin > packet->header.size) {
|
||||
DBG_ERR_FMT("GREET packet %d bytes shorter than expected", p - begin - packet->header.size);
|
||||
DBG_ERR_FMT("RSET_HEADER packet %d bytes shorter than expected", p - begin - packet->header.size);
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "GREET packet %d bytes shorter than expected. PID=%d",
|
||||
p - begin - packet->header.size, getpid());
|
||||
}
|
||||
|
@ -1097,7 +1111,7 @@ php_mysqlnd_rset_field_read(void *_packet, MYSQLND *conn TSRMLS_DC)
|
|||
*(unsigned int *)(((char*)meta) + rset_field_offsets[i+1]) = 0;
|
||||
break;
|
||||
case MYSQLND_NULL_LENGTH:
|
||||
goto faulty_fake;
|
||||
goto faulty_or_fake;
|
||||
default:
|
||||
*(char **)(((char *)meta) + rset_field_offsets[i]) = (char *)p;
|
||||
*(unsigned int *)(((char*)meta) + rset_field_offsets[i+1]) = len;
|
||||
|
@ -1156,7 +1170,7 @@ php_mysqlnd_rset_field_read(void *_packet, MYSQLND *conn TSRMLS_DC)
|
|||
}
|
||||
|
||||
if (p - begin > packet->header.size) {
|
||||
DBG_ERR_FMT("Result set field packet %d bytes shorter than expected", p - begin - packet->header.size);
|
||||
DBG_ERR_FMT("RSET field packet %d bytes shorter than expected", p - begin - packet->header.size);
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Result set field packet %d bytes "
|
||||
"shorter than expected. PID=%d", p - begin - packet->header.size, getpid());
|
||||
}
|
||||
|
@ -1210,7 +1224,7 @@ php_mysqlnd_rset_field_read(void *_packet, MYSQLND *conn TSRMLS_DC)
|
|||
*/
|
||||
DBG_RETURN(PASS);
|
||||
|
||||
faulty_fake:
|
||||
faulty_or_fake:
|
||||
DBG_ERR_FMT("Protocol error. Server sent NULL_LENGTH. The server is faulty");
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Protocol error. Server sent NULL_LENGTH."
|
||||
" The server is faulty");
|
||||
|
@ -1629,6 +1643,8 @@ php_mysqlnd_rowp_read(void *_packet, MYSQLND *conn TSRMLS_DC)
|
|||
p += 2;
|
||||
packet->server_status = uint2korr(p);
|
||||
/* Seems we have 3 bytes reserved for future use */
|
||||
DBG_INF_FMT("server_status=%d warning_count=%d",
|
||||
packet->server_status, packet->warning_count);
|
||||
}
|
||||
} else {
|
||||
MYSQLND_INC_CONN_STATISTIC(&conn->stats,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue