Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ PHP NEWS
- MySQLnd:
. Fixed bug GH-24293 (Segfault on connect with an empty password to a
MariaDB PAM account). (lazerg)
. Fixed bug GH-16910 (Fractional seconds truncated in prepared statements
if decimals is AUTO_SEC_PART_DIGITS). (Ojus Chugh)

- Opcache:
. Fixed bug GH-20890 (Segfault in zval_undefined_cv with non-simple property
Expand Down
42 changes: 42 additions & 0 deletions ext/mysqli/tests/gh16910.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
--TEST--
GH-16910 (Fractional seconds truncated in prepared statements if decimals is AUTO_SEC_PART_DIGITS)
--EXTENSIONS--
mysqli
--SKIPIF--
<?php
require_once 'connect.inc';
if (!$link = @my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
die(sprintf("SKIP Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
$host, $user, $db, $port, $socket));
$stmt = $link->prepare("SELECT FROM_UNIXTIME('1992.1')");
if (!$stmt || $stmt->result_metadata()->fetch_field_direct(0)->decimals !== 39)
die("SKIP Server does not report AUTO_SEC_PART_DIGITS for FROM_UNIXTIME()");
?>
--FILE--
<?php
require_once 'connect.inc';

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$link = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
$link->query("SET time_zone = '+00:00'");

$sql = "SELECT FROM_UNIXTIME('1992.1'), FROM_UNIXTIME('1992.0')";
var_dump($link->query($sql)->fetch_row());

$stmt = $link->prepare($sql);
$stmt->execute();
var_dump($stmt->get_result()->fetch_row());
?>
--EXPECT--
array(2) {
[0]=>
string(26) "1970-01-01 00:33:12.100000"
[1]=>
string(19) "1970-01-01 00:33:12"
}
array(2) {
[0]=>
string(26) "1970-01-01 00:33:12.100000"
[1]=>
string(19) "1970-01-01 00:33:12"
}
14 changes: 8 additions & 6 deletions ext/mysqlnd/mysqlnd_ps_codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -305,10 +305,11 @@ ps_fetch_time(zval * zv, const MYSQLND_FIELD * const field, const unsigned int p
t.time_type = MYSQLND_TIMESTAMP_TIME;
}

if (field->decimals > 0 && field->decimals < 7) {
unsigned int decimals = field->decimals > 6 ? (t.second_part ? 6 : 0) : field->decimals;
if (decimals > 0) {
ZVAL_STR(zv, zend_strpprintf(0, "%s%02u:%02u:%02u.%0*u",
(t.neg ? "-" : ""), t.hour, t.minute, t.second, field->decimals,
(uint32_t) (t.second_part / pow(10, 6 - field->decimals))));
(t.neg ? "-" : ""), t.hour, t.minute, t.second, decimals,
(uint32_t) (t.second_part / pow(10, 6 - decimals))));
} else {
ZVAL_STR(zv, zend_strpprintf(0, "%s%02u:%02u:%02u",
(t.neg ? "-" : ""), t.hour, t.minute, t.second));
Expand Down Expand Up @@ -401,10 +402,11 @@ ps_fetch_datetime(zval * zv, const MYSQLND_FIELD * const field, const unsigned i
t.time_type = MYSQLND_TIMESTAMP_DATETIME;
}

if (field->decimals > 0 && field->decimals < 7) {
unsigned int decimals = field->decimals > 6 ? (t.second_part ? 6 : 0) : field->decimals;
if (decimals > 0) {
ZVAL_STR(zv, zend_strpprintf(0, "%04u-%02u-%02u %02u:%02u:%02u.%0*u",
t.year, t.month, t.day, t.hour, t.minute, t.second, field->decimals,
(uint32_t) (t.second_part / pow(10, 6 - field->decimals))));
t.year, t.month, t.day, t.hour, t.minute, t.second, decimals,
(uint32_t) (t.second_part / pow(10, 6 - decimals))));
} else {
ZVAL_STR(zv, zend_strpprintf(0, "%04u-%02u-%02u %02u:%02u:%02u",
t.year, t.month, t.day, t.hour, t.minute, t.second));
Expand Down
Loading