Bug #80586 [Com]: PDO constructor overrides dblib timeout
| From: | tannaowens6 at googlemail dot com | Date: | Wed, 27 Sep 2023 10:21:19 +0000 |
| Subject: | Bug #80586 [Com]: PDO constructor overrides dblib timeout | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-245441@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=80586&edit=1
ID: 80586
Comment by: tannaowens6 at googlemail dot com
Reported by: jeremys at ha dot com
Summary: PDO constructor overrides dblib timeout
Status: Open
Type: Bug
Package: PDO DBlib
Operating System: RHEL 7.8
PHP Version: 7.3.25
Block user comment: N
Private report: N
New Comment:
Wish to see much more like this. Thanks for sharing your information
(https://github.com)(https://www.attprepaid.online/)
Previous Comments:
------------------------------------------------------------------------
[2021-01-11 14:57:33] jeremys at ha dot com
It's possible, but due to the bug in #80587 it doesn't work when using multiple PDO
objects in the same script.
But I suppose the point of this bug report is, if I pass PDO::ATTR_ERRMODE to the constructor, only
the error mode should be changed. Not timeouts, not datetime conversion, etc.
https://github.com/php/php-src/blob/caa710037e663fd78f67533b29611183090068b2/ext/pdo_dblib/dblib_driver.c#L481
I'm not too familiar with C but I presume the "if (driver_options)" block needs to be
changed to only set the appropriate driver option if that particular driver option is passed and is
not null.
Example:
if(driver_options) {
zval *connect_timeout_value;
zval *query_timeout_value;
zval *datetime_convert_value;
/* ignoring PDO_ATTR_TIMEOUT for this example */
if(connect_timeout_value = zend_hash_index_find(Z_ARRVAL_P(driver_options),
PDO_DBLIB_ATTR_CONNECTION_TIMEOUT)) {
dbsetlogintime(zval_get_long(connect_timeout_value));
}
if(query_timeout_value = zend_hash_index_find(Z_ARRVAL_P(driver_options),
PDO_DBLIB_ATTR_QUERY_TIMEOUT)) {
dbsettime(zval_get_long(query_timeout_value));
}
/* more driver option checks here */
if(datetime_convert_value = zend_hash_index_find(Z_ARRVAL_P(driver_options),
PDO_DBLIB_ATTR_DATETIME_CONVERT)) {
H->datetime_convert = zval_get_long(datetime_convert_value);
}
}
It doesn't make sense for the driver options to be set when $options in the PDO constructor is
an empty array, but not when $options is null.
------------------------------------------------------------------------
[2021-01-10 21:47:19] adambaratz@php.net
This behavior is certainly awkward, but it was intended as a compromise between PDO's generic
timeout attribute and the two timeouts that dblib can set. We could certainly come up with new logic
for getting to the values to send to dbsetlogintime and dbsettime, but it would require some thought
(and likely break a fair bit of existing code in the wild). Is it an option for you to set a timeout
value in your PHP userland code instead of relying on freetds.conf?
------------------------------------------------------------------------
[2021-01-04 15:21:40] jeremys at ha dot com
Description:
------------
When instantiating a new PDO instance with dblib as the driver, passing a non-null value to $options
causes PDO_DBLIB to override the configured timeout and default it to 30 seconds for both connects
and queries.
For example, when using FreeTDS with a defined query timeout of 300 seconds in freetds.conf
("timeout = 300"), passing an empty array or an array with options that have nothing to do
with timeouts sets the query timeout to 30 seconds.
The gist is, passing $options to PDO::__construct() should only set the driver options specifically
defined in $options, not every driver option.
https://github.com/php/php-src/blob/caa710037e663fd78f67533b29611183090068b2/ext/pdo_dblib/dblib_driver.c#L481
Test script:
---------------
test-1.php:
<?php
$pdo = new PDO( 'dblib:dbname=northwinds;host=contoso', 'username',
'password' );
try
{
$pdo->query( "WAITFOR DELAY '00:00:35'" );
var_dump( $pdo->query( "SELECT 'output' AS Output"
)->fetch()['Output'] );
}
catch( Throwable $e )
{
var_dump( stripos( $pdo->errorInfo()[2], 'DBPROCESS is dead or not enabled' ) === 0 );
}
?>
test-2.php:
<?php
$pdo = new PDO( 'dblib:dbname=northwinds;host=contoso', 'username',
'password', [] );
try
{
$pdo->query( "WAITFOR DELAY '00:00:35'" );
var_dump( $pdo->query( "SELECT 'output' AS Output"
)->fetch()['Output'] );
}
catch( Throwable $e )
{
var_dump( stripos( $pdo->errorInfo()[2], 'DBPROCESS is dead or not enabled' ) === 0 );
}
Expected result:
----------------
test-1.php:
string(6) "output"
test-2.php:
string(6) "output"
Actual result:
--------------
test-1.php:
string(6) "output"
test-2.php:
bool(true)
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=80586&edit=1