Workaround for a bug in unixODBC 2.3.4 (#334)

* Adding a workaround for the error handling issue with unixODBC 2.3.4 when conneciton pooling is enabled

* Adding a check to apply the workaround only to PDO SQLSRV

* Update core_util.cpp

* Unix Conn Pool test

* Modifying the test to use autonomous_setup.php

* Updating path to isPooled.php
This commit is contained in:
ulvii 2017-03-27 14:07:43 -07:00 committed by GitHub
parent 6bd361c1ef
commit 6809f0f7ea
3 changed files with 70 additions and 0 deletions

View file

@ -247,6 +247,17 @@ bool core_sqlsrv_get_odbc_error( sqlsrv_context& ctx, int record_number, sqlsrv_
r = SQLGetDiagRecW( h_type, h, record_number, wsqlstate, &error->native_code, wnative_message,
SQL_MAX_MESSAGE_LENGTH + 1, &wmessage_len );
// don't use the CHECK* macros here since it will trigger reentry into the error handling system
// Workaround for a bug in unixODBC 2.3.4 when connection pooling is enabled (PDO SQLSRV).
// Instead of returning false, we return an empty error message to prevent the driver from throwing an exception.
// To reproduce:
// Create a connection and close it (return it to the pool)
// Create a new connection from the pool.
// Prepare and execute a statement that generates an info message (such as 'USE tempdb;')
#ifdef __APPLE__
if( r == SQL_NO_DATA && ctx.driver() != NULL /*PDO SQLSRV*/ ) {
r = SQL_SUCCESS;
}
#endif // __APPLE__
if( !SQL_SUCCEEDED( r ) || r == SQL_NO_DATA ) {
return false;
}

View file

@ -0,0 +1,34 @@
--TEST--
PDO Connection Pooling Test on Unix
This test assumes odbcinst.ini has not been modified.
This test also requires root privileges to modify odbcinst.ini file on Linux.
--SKIPIF--
<?php if(PHP_OS === "WINNT") die("Skipped: Test for Linux and Mac");
--FILE--
<?php
$lines_to_add="CPTimeout=5\n[ODBC]\nPooling=Yes\n";
//get odbcinst.ini location
$lines = explode("\n", shell_exec("odbcinst -j"));
$odbcinst_ini = explode(" ", $lines[1])[1];
//enable pooling by modifying the odbcinst.ini file
$current = file_get_contents($odbcinst_ini);
$current.=$lines_to_add;
file_put_contents($odbcinst_ini, $current);
//Creating a new php process, because for changes in odbcinst.ini file to affect pooling, drivers must be reloaded.
print_r(shell_exec("php ./test/pdo_sqlsrv/isPooled.php"));
//disable pooling by modifying the odbcinst.ini file
$current = file_get_contents($odbcinst_ini);
$current = str_replace("CPTimeout=5\n[ODBC]\nPooling=Yes\n",'',$current);
file_put_contents($odbcinst_ini, $current);
print_r(shell_exec("php ./test/pdo_sqlsrv/isPooled.php"));
?>
--EXPECT--
Pooled
Not Pooled

View file

@ -0,0 +1,25 @@
<?php
include_once 'autonomous_setup.php';
$conn1 = new PDO("sqlsrv:Server=$serverName", $username, $password);
$connId1 = ConnectionID($conn1);
$conn1 = null;
$conn2 = new PDO("sqlsrv:Server=$serverName", $username, $password);
$connId2 = ConnectionID($conn2);
if ($connId1 === $connId2){
echo "Pooled\n";
}else{
echo "Not Pooled\n";
}
function ConnectionID($conn)
{
$tsql = "SELECT [connection_id] FROM [sys].[dm_exec_connections] where session_id = @@SPID";
$stmt = $conn->query($tsql);
$connID = $stmt->fetchColumn(0);
$stmt->closeCursor();
$stmt = null;
return ($connID);
}
?>