Implement mysqli_fetch_column (#6798)

* Implement mysqli_fetch_column
This commit is contained in:
Kamil Tekiela 2021-05-01 20:11:47 +01:00 committed by GitHub
parent 810fb59f66
commit 54222a6fe4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 200 additions and 1 deletions

View File

@ -226,6 +226,9 @@ PHP 8.1 UPGRADE NOTES
. Binding in execute has been added to mysqli prepared statements.
Parameters can now be passed to mysqli_stmt::execute as an array.
RFC: https://wiki.php.net/rfc/mysqli_bind_in_execute
. A new function has been added to mysqli_result called mysqli_fetch_column().
It allows for fetching single scalar values from the result set.
RFC: https://wiki.php.net/rfc/mysqli_fetch_column
- PDO MySQL:
. The PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY attribute has been added, which

View File

@ -426,6 +426,11 @@ class mysqli_result implements IteratorAggregate
*/
public function fetch_row() {}
/**
* @alias mysqli_fetch_column
*/
public function fetch_column(int $column = 0): null|int|float|string|false {}
/**
* @return bool
* @alias mysqli_field_seek
@ -664,6 +669,8 @@ function mysqli_fetch_object(mysqli_result $result, string $class = "stdClass",
function mysqli_fetch_row(mysqli_result $result): array|null|false {}
function mysqli_fetch_column(mysqli_result $result, int $column = 0): null|int|float|string|false {}
function mysqli_field_count(mysqli $mysql): int {}
function mysqli_field_seek(mysqli_result $result, int $index): bool {}

View File

@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: b0232d18f570208d673ad7535ca60997e038acb8 */
* Stub hash: 42fdb807a547cfa3ba35bb2b8a4ee0f0d556a18c */
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_mysqli_affected_rows, 0, 1, MAY_BE_LONG|MAY_BE_STRING)
ZEND_ARG_OBJ_INFO(0, mysql, mysqli, 0)
@ -115,6 +115,11 @@ ZEND_END_ARG_INFO()
#define arginfo_mysqli_fetch_row arginfo_mysqli_fetch_assoc
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_mysqli_fetch_column, 0, 1, MAY_BE_NULL|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_STRING|MAY_BE_FALSE)
ZEND_ARG_OBJ_INFO(0, result, mysqli_result, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, column, IS_LONG, 0, "0")
ZEND_END_ARG_INFO()
#define arginfo_mysqli_field_count arginfo_mysqli_errno
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mysqli_field_seek, 0, 2, _IS_BOOL, 0)
@ -609,6 +614,10 @@ ZEND_END_ARG_INFO()
#define arginfo_class_mysqli_result_fetch_row arginfo_class_mysqli_character_set_name
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_mysqli_result_fetch_column, 0, 0, MAY_BE_NULL|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_STRING|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, column, IS_LONG, 0, "0")
ZEND_END_ARG_INFO()
#define arginfo_class_mysqli_result_field_seek arginfo_class_mysqli_result_fetch_field_direct
#define arginfo_class_mysqli_result_free_result arginfo_class_mysqli_character_set_name
@ -709,6 +718,7 @@ ZEND_FUNCTION(mysqli_fetch_array);
ZEND_FUNCTION(mysqli_fetch_assoc);
ZEND_FUNCTION(mysqli_fetch_object);
ZEND_FUNCTION(mysqli_fetch_row);
ZEND_FUNCTION(mysqli_fetch_column);
ZEND_FUNCTION(mysqli_field_count);
ZEND_FUNCTION(mysqli_field_seek);
ZEND_FUNCTION(mysqli_field_tell);
@ -833,6 +843,7 @@ static const zend_function_entry ext_functions[] = {
ZEND_FE(mysqli_fetch_assoc, arginfo_mysqli_fetch_assoc)
ZEND_FE(mysqli_fetch_object, arginfo_mysqli_fetch_object)
ZEND_FE(mysqli_fetch_row, arginfo_mysqli_fetch_row)
ZEND_FE(mysqli_fetch_column, arginfo_mysqli_fetch_column)
ZEND_FE(mysqli_field_count, arginfo_mysqli_field_count)
ZEND_FE(mysqli_field_seek, arginfo_mysqli_field_seek)
ZEND_FE(mysqli_field_tell, arginfo_mysqli_field_tell)
@ -998,6 +1009,7 @@ static const zend_function_entry class_mysqli_result_methods[] = {
ZEND_ME_MAPPING(fetch_assoc, mysqli_fetch_assoc, arginfo_class_mysqli_result_fetch_assoc, ZEND_ACC_PUBLIC)
ZEND_ME_MAPPING(fetch_object, mysqli_fetch_object, arginfo_class_mysqli_result_fetch_object, ZEND_ACC_PUBLIC)
ZEND_ME_MAPPING(fetch_row, mysqli_fetch_row, arginfo_class_mysqli_result_fetch_row, ZEND_ACC_PUBLIC)
ZEND_ME_MAPPING(fetch_column, mysqli_fetch_column, arginfo_class_mysqli_result_fetch_column, ZEND_ACC_PUBLIC)
ZEND_ME_MAPPING(field_seek, mysqli_field_seek, arginfo_class_mysqli_result_field_seek, ZEND_ACC_PUBLIC)
ZEND_ME_MAPPING(free_result, mysqli_free_result, arginfo_class_mysqli_result_free_result, ZEND_ACC_PUBLIC)
ZEND_ME(mysqli_result, getIterator, arginfo_class_mysqli_result_getIterator, ZEND_ACC_PUBLIC)

View File

@ -436,6 +436,39 @@ PHP_FUNCTION(mysqli_fetch_assoc)
}
/* }}} */
/* {{{ Fetch a column from the result row */
PHP_FUNCTION(mysqli_fetch_column)
{
MYSQL_RES *result;
zval *mysql_result;
zval row_array;
zend_long col_no = 0;
if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|l", &mysql_result, mysqli_result_class_entry, &col_no) == FAILURE) {
RETURN_THROWS();
}
MYSQLI_FETCH_RESOURCE(result, MYSQL_RES*, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
if (col_no < 0) {
zend_argument_value_error(ERROR_ARG_POS(2), "must be greater than or equal to 0");
RETURN_THROWS();
}
if (col_no >= mysql_num_fields(result)) {
zend_argument_value_error(ERROR_ARG_POS(2), "must be less than the number of fields for this result set");
RETURN_THROWS();
}
php_mysqli_fetch_into_hash_aux(&row_array, result, MYSQLI_NUM);
if (Z_TYPE(row_array) != IS_ARRAY) {
zval_ptr_dtor_nogc(&row_array);
RETURN_FALSE;
}
ZVAL_COPY(return_value, zend_hash_index_find(Z_ARR(row_array), col_no));
zval_ptr_dtor_nogc(&row_array);
}
/* }}} */
/* {{{ Fetches all result rows as an associative array, a numeric array, or both */
PHP_FUNCTION(mysqli_fetch_all)
{

View File

@ -35,6 +35,7 @@ require_once('skipifconnectfailure.inc');
'fetch_fields' => true,
'fetch_object' => true,
'fetch_row' => true,
'fetch_column' => true,
'field_seek' => true,
'free' => true,
'free_result' => true,

View File

@ -0,0 +1,143 @@
--TEST--
mysqli_fetch_column()
--SKIPIF--
<?php
require_once 'skipif.inc';
require_once 'skipifconnectfailure.inc';
?>
--FILE--
<?php
require_once "connect.inc";
require 'table.inc';
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$res = mysqli_query($link, "SELECT id, label FROM test ORDER BY id LIMIT 1");
print "[001]\n";
var_dump(mysqli_fetch_column($res));
print "[002]\n";
var_dump(mysqli_fetch_column($res));
$link->options(MYSQLI_OPT_INT_AND_FLOAT_NATIVE, true);
$res = mysqli_query($link, "SELECT
1 AS a,
2 AS a
");
print "[003]\n";
var_dump(mysqli_fetch_column($res, 0));
$res = mysqli_query($link, "SELECT
1 AS a,
2 AS a
");
print "[004]\n";
var_dump(mysqli_fetch_column($res, 1));
$res = mysqli_query($link, "SELECT
1 AS a,
2 AS a,
3
");
print "[005]\n";
var_dump(mysqli_fetch_column($res, 2));
$res = mysqli_query($link, "SELECT
1 AS a,
2 AS a,
3,
NULL AS d
");
print "[006]\n";
var_dump(mysqli_fetch_column($res, 3));
$res = mysqli_query($link, "SELECT
1 AS a,
2 AS a,
3,
NULL AS d,
true AS e
");
print "[007]\n";
var_dump(mysqli_fetch_column($res, 4));
$res = mysqli_query($link, "SELECT
1.42 AS a
");
print "[008]\n";
var_dump(mysqli_fetch_column($res, 0));
$res = mysqli_query($link, "SELECT
1.42E0 AS a
");
print "[009]\n";
var_dump(mysqli_fetch_column($res, 0));
$res = mysqli_query($link, "SELECT id, label FROM test ORDER BY id LIMIT 1");
print "[010]\n";
try {
var_dump(mysqli_fetch_column($res, -1));
} catch (\ValueError $e) {
echo $e->getMessage(), \PHP_EOL;
}
$res = mysqli_query($link, "SELECT id, label FROM test ORDER BY id LIMIT 1");
print "[011]\n";
try {
var_dump(mysqli_fetch_column($res, 2));
} catch (\ValueError $e) {
echo $e->getMessage(), \PHP_EOL;
}
mysqli_free_result($res);
try {
mysqli_fetch_column($res);
} catch (Error $exception) {
echo $exception->getMessage() . "\n";
}
$res = $link->query("SELECT id, label FROM test ORDER BY id LIMIT 2");
print "[012]\n";
var_dump($res->fetch_column());
print "[013]\n";
var_dump($res->fetch_column(1));
mysqli_close($link);
?>
--CLEAN--
<?php
require_once "clean_table.inc";
?>
--EXPECT--
[001]
string(1) "1"
[002]
bool(false)
[003]
int(1)
[004]
int(2)
[005]
int(3)
[006]
NULL
[007]
int(1)
[008]
string(4) "1.42"
[009]
float(1.42)
[010]
mysqli_fetch_column(): Argument #2 ($column) must be greater than or equal to 0
[011]
mysqli_fetch_column(): Argument #2 ($column) must be less than the number of fields for this result set
mysqli_result object is already closed
[012]
int(1)
[013]
string(1) "b"