Merge pull request #412 from david-puglielli/fix_failing_tests

Fix failing tests
This commit is contained in:
David Puglielli 2017-06-22 14:04:00 -07:00 committed by GitHub
commit 553ca92fea
22 changed files with 1900 additions and 52 deletions

View file

@ -1,9 +1,10 @@
sudo: required
group: edge
os: linux
dist: trusty
group: edge
services:
- docker
@ -43,3 +44,4 @@ script:
notifications:
email: false

View file

@ -4,32 +4,60 @@ 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 (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') die("Skipped: Test for Linux and Mac");
<?php if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') die("Skipped: Test for Linux and Mac"); ?>
--FILE--
<?php
// On Bamboo we must use sudo to fiddle with odbcinst.ini
// On travis-ci we can't use sudo
$sudo = '';
$user = posix_getpwuid(posix_geteuid());
if (strtolower($user['name']) != 'root')
{
$sudo = 'sudo ';
}
$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];
//back up the odbcinst.ini file
shell_exec($sudo."cp $odbcinst_ini $odbcinst_ini.bak");
//enable pooling by modifying the odbcinst.ini file
$current = file_get_contents($odbcinst_ini);
$current.=$lines_to_add;
file_put_contents($odbcinst_ini, $current);
shell_exec("cp $odbcinst_ini .");
file_put_contents("odbcinst.ini", $current);
shell_exec($sudo."cp odbcinst.ini $odbcinst_ini");
//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"));
print_r(shell_exec(PHP_BINARY." ".dirname(__FILE__)."/isPooled.php"));
//disable pooling by modifying the odbcinst.ini file
$current = file_get_contents($odbcinst_ini);
$current = str_replace($lines_to_add,'',$current);
file_put_contents($odbcinst_ini, $current);
file_put_contents("odbcinst.ini", $current);
shell_exec($sudo."cp odbcinst.ini $odbcinst_ini");
print_r(shell_exec("php ./test/pdo_sqlsrv/isPooled.php"));
print_r(shell_exec(PHP_BINARY." ".dirname(__FILE__)."/isPooled.php"));
?>
--CLEAN--
<?php
$sudo = '';
$user = posix_getpwuid(posix_geteuid());
if (strtolower($user['name']) == 'bamboo')
{
$sudo = 'sudo ';
}
$lines = explode("\n", shell_exec("odbcinst -j"));
$odbcinst_ini = explode(" ", $lines[1])[1];
shell_exec($sudo."cp $odbcinst_ini.bak $odbcinst_ini");
shell_exec($sudo."rm $odbcinst_ini.bak");
?>
--EXPECT--
Pooled
Not Pooled

View file

@ -0,0 +1,82 @@
<?php
require_once("MsSetup.inc");
// Using the tempdb database for two tables specifically constructed
// for the connection resiliency tests
$dbName = "tempdb";
$tableName1 = "test_connres1";
$tableName2 = "test_connres2";
// Generate tables for use with the connection resiliency tests.
// Using generated tables will eventually allow us to put the
// connection resiliency tests on Github, since the integrated testing
// from AppVeyor does not have AdventureWorks.
function GenerateTables( $server, $uid, $pwd, $dbName, $tableName1, $tableName2 )
{
$conn = new PDO( "sqlsrv:server = $server ; Database = $dbName ;", $uid, $pwd );
if ( $conn === false )
{
die ( print_r( sqlsrv_errors() ) );
}
// Create table
$sql = "CREATE TABLE $tableName1 ( c1 INT, c2 VARCHAR(40) )";
$stmt = $conn->query( $sql );
// Insert data
$sql = "INSERT INTO $tableName1 VALUES ( ?, ? )";
for( $t = 100; $t < 116; $t++ )
{
$stmt = $conn->prepare( $sql );
$ts = substr( sha1( $t ),0,5 );
$params = array( $t,$ts );
$stmt->execute( $params );
}
// Create table
$sql = "CREATE TABLE $tableName2 ( c1 INT, c2 VARCHAR(40) )";
$stmt = $conn->query( $sql );
// Insert data
$sql = "INSERT INTO $tableName2 VALUES ( ?, ? )";
for( $t = 200; $t < 209; $t++ )
{
$stmt = $conn->prepare( $sql );
$ts = substr( sha1( $t ),0,5 );
$params = array( $t,$ts );
$stmt->execute( $params );
}
$conn = null;
}
// Break connection by getting the session ID and killing it.
// Note that breaking a connection and testing reconnection requires a
// TCP/IP protocol connection (as opposed to a Shared Memory protocol).
function BreakConnection( $conn, $conn_break )
{
$stmt1 = $conn->query( "SELECT @@SPID" );
$obj = $stmt1->fetch( PDO::FETCH_NUM );
$spid = $obj[0];
$stmt2 = $conn_break->query( "KILL ".$spid );
sleep(1);
}
// Remove any databases previously created by GenerateDatabase
function DropTables( $server, $uid, $pwd, $tableName1, $tableName2 )
{
$conn = new PDO( "sqlsrv:server = $server ; ", $uid, $pwd );
$query="IF OBJECT_ID('tempdb.dbo.$tableName1', 'U') IS NOT NULL DROP TABLE tempdb.dbo.$tableName1";
$stmt=$conn->query( $query );
$query="IF OBJECT_ID('tempdb.dbo.$tableName2', 'U') IS NOT NULL DROP TABLE tempdb.dbo.$tableName2";
$stmt=$conn->query( $query );
}
DropTables( $server, $uid, $pwd, $tableName1, $tableName2 );
GenerateTables( $server, $uid, $pwd, $dbName, $tableName1, $tableName2 );
?>

View file

@ -6,6 +6,7 @@ $conn1 = null;
$conn2 = new PDO("sqlsrv:Server=$server", $uid, $pwd);
$connId2 = ConnectionID($conn2);
$conn2 = null;
if ($connId1 === $connId2){
echo "Pooled\n";

View file

@ -96,4 +96,3 @@ array(2) {
Could not connect with Authentication=ActiveDirectoryIntegrated.
SQLSTATE[IMSSP]: Invalid option for the Authentication keyword. Only SqlPassword or ActiveDirectoryPassword is supported.
%s with Authentication=ActiveDirectoryPassword.

View file

@ -0,0 +1,248 @@
--TEST--
Connection recovery test
--DESCRIPTION--
Connect and execute a command, kill the connection, execute another command.
Then do it again without a buffered result set, by freeing the statement before
killing the connection and then not freeing it. The latter case is the only one
that should fail. Finally, execute two queries in two threads on a recovered
non-MARS connection. This should fail too.
--SKIPIF--
<?php require('skipif_protocol_not_tcp.inc'); ?>
--FILE--
<?php
// There is a lot of repeated code here that could be refactored with helper methods,
// mostly for statement allocation. But that would affect scoping for the $stmt variables,
// which could affect the results when attempting to reconnect. What happens to statements
// when exiting the helper method? Do the associated cursors remain active? It is an
// unnecessary complication, so I have left the code like this.
require_once( "break_pdo.php" );
$conn_break = new PDO( "sqlsrv:server = $server ; Database = $dbName ;", $uid, $pwd );
///////////////////////////////////////////////////////////////////////////////
// Part 1
// Expected to successfully execute second query because buffered cursor for
// first query means connection is idle when broken
///////////////////////////////////////////////////////////////////////////////
$connectionInfo = "ConnectRetryCount = 10; ConnectRetryInterval = 10;";
try
{
$conn = new PDO( "sqlsrv:server = $server ; Database = $dbName ; $connectionInfo", $uid, $pwd );
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
}
catch( PDOException $e )
{
echo "Could not connect.\n";
print_r( $e->getMessage() );
}
$query1 = "SELECT * FROM $tableName1";
try
{
$stmt1 = $conn->prepare( $query1, array( PDO::ATTR_CURSOR=> PDO::CURSOR_SCROLL, PDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE=> PDO::SQLSRV_CURSOR_BUFFERED ) );
if ( $stmt1->execute() ) echo "Statement 1 successful.\n";
$rowcount = $stmt1->rowCount();
echo $rowcount." rows in result set.\n";
}
catch( PDOException $e )
{
echo "Error executing statement 1.\n";
print_r( $e->getMessage() );
}
BreakConnection( $conn, $conn_break );
$query2 = "SELECT * FROM $tableName2";
try
{
$stmt2 = $conn->prepare( $query2, array( PDO::ATTR_CURSOR=> PDO::CURSOR_SCROLL, PDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE=> PDO::SQLSRV_CURSOR_BUFFERED ) );
if ( $stmt2->execute() ) echo "Statement 2 successful.\n";
$rowcount = $stmt2->rowCount();
echo $rowcount." rows in result set.\n";
}
catch( PDOException $e )
{
echo "Error executing statement 2.\n";
print_r( $e->getMessage() );
}
$conn = null;
///////////////////////////////////////////////////////////////////////////////
// Part 2
// Expected to successfully execute second query because first statement is
// freed before breaking connection
///////////////////////////////////////////////////////////////////////////////
try
{
$conn = new PDO( "sqlsrv:server = $server ; Database = $dbName ; $connectionInfo", $uid, $pwd );
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
}
catch( PDOException $e )
{
echo "Could not connect.\n";
print_r( $e->getMessage() );
}
$query1 = "SELECT * FROM $tableName1";
try
{
$stmt3 = $conn->query( $query1 );
if ( $stmt3 ) echo "Statement 3 successful.\n";
$rowcount = $stmt3->rowCount();
echo $rowcount." rows in result set.\n";
}
catch( PDOException $e )
{
echo "Error executing statement 3.\n";
print_r( $e->getMessage() );
}
$stmt3 = null;
BreakConnection( $conn, $conn_break );
$query2 = "SELECT * FROM $tableName2";
try
{
$stmt4 = $conn->query( $query2 );
if ( $stmt4 ) echo "Statement 4 successful.\n";
$rowcount = $stmt4->rowCount();
echo $rowcount." rows in result set.\n";
}
catch( PDOException $e )
{
echo "Error executing statement 4.\n";
print_r( $e->getMessage() );
}
$conn = null;
///////////////////////////////////////////////////////////////////////////////
// Part 3
// Expected to fail executing second query because default cursor for first
// query is still active when connection is broken
///////////////////////////////////////////////////////////////////////////////
try
{
$conn = new PDO( "sqlsrv:server = $server ; Database = $dbName ; $connectionInfo", $uid, $pwd );
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
}
catch( PDOException $e )
{
echo "Could not connect.\n";
print_r( $e->getMessage() );
}
$query1 = "SELECT * FROM $tableName1";
try
{
$stmt5 = $conn->query( $query1 );
if ( $stmt5 ) echo "Statement 5 successful.\n";
$rowcount = $stmt5->rowCount();
echo $rowcount." rows in result set.\n";
}
catch( PDOException $e )
{
echo "Error executing statement 5.\n";
print_r( $e->getMessage() );
}
BreakConnection( $conn, $conn_break );
$query2 = "SELECT * FROM $tableName2";
try
{
$stmt6 = $conn->query( $query2 );
if ( $stmt6 ) echo "Statement 6 successful.\n";
$rowcount = $stmt6->rowCount();
echo $rowcount." rows in result set.\n";
}
catch( PDOException $e )
{
echo "Error executing statement 6.\n";
print_r( $e->getMessage() );
}
$conn = null;
///////////////////////////////////////////////////////////////////////////////
// Part 4
// Expected to trigger an error because there are two active statements with
// pending results and MARS is off
///////////////////////////////////////////////////////////////////////////////
$connectionInfo = "ConnectRetryCount = 10; ConnectRetryInterval = 10; MultipleActiveResultSets = false;";
try
{
$conn = new PDO( "sqlsrv:server = $server ; Database = $dbName ; $connectionInfo", $uid, $pwd );
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
}
catch( PDOException $e )
{
echo "Could not connect.\n";
print_r( $e->getMessage() );
}
BreakConnection( $conn, $conn_break );
try
{
$stmt7 = $conn->query( "SELECT * FROM $tableName1" );
if ( $stmt7 ) echo "Statement 7 successful.\n";
}
catch( PDOException $e )
{
echo "Error executing statement 7.\n";
print_r( $e->getMessage() );
}
try
{
$stmt8 = $conn->query( "SELECT * FROM $tableName2" );
if ( $stmt8 ) echo "Statement 8 successful.\n";
}
catch( PDOException $e )
{
echo "Error executing statement 8.\n";
print_r( $e->getMessage() );
}
$conn = null;
$conn_break = null;
?>
--EXPECTREGEX--
Statement 1 successful.
16 rows in result set.
Statement 2 successful.
9 rows in result set.
Statement 3 successful.
-1 rows in result set.
Statement 4 successful.
-1 rows in result set.
Statement 5 successful.
-1 rows in result set.
Error executing statement 6.
SQLSTATE\[08S02\]: \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]TCP Provider: An existing connection was forcibly closed by the remote host.
Statement 7 successful.
Error executing statement 8.
SQLSTATE\[IMSSP\]: The connection cannot process this operation because there is a statement with pending results. To make the connection available for other queries, either fetch all results or cancel or free the statement. For more information, see the product documentation about the MultipleActiveResultSets connection option.

View file

@ -0,0 +1,216 @@
--TEST--
Test connection resiliency with a prepared statement and transaction.
--DESCRIPTION--
Prepare a statement, break the connection, and execute the statement. Then
test transactions by breaking the connection before beginning a transaction
and in the middle of the transaction. The latter case should fail.
--SKIPIF--
<?php require('skipif_protocol_not_tcp.inc'); ?>
--FILE--
<?php
require_once( "break_pdo.php" );
$conn_break = new PDO( "sqlsrv:server = $server ; Database = $dbName ;", $uid, $pwd );
///////////////////////////////////////////////////////////////////////////////
// Part 1
// Statement expected to be executed because the connection is idle after
// statement has been prepared
///////////////////////////////////////////////////////////////////////////////
$connectionInfo = "ConnectRetryCount = 10; ConnectRetryInterval = 10;";
try
{
$conn = new PDO( "sqlsrv:server = $server ; Database = $dbName ; $connectionInfo", $uid, $pwd );
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
}
catch( PDOException $e )
{
echo "Could not connect.\n";
print_r( $e->getMessage() );
}
try
{
$stmt1 = $conn->prepare( "SELECT * FROM $tableName1" );
if ( $stmt1 ) echo "Statement 1 prepared.\n";
else echo "Error preparing statement 1.\n";
}
catch( PDOException $e )
{
echo "Exception preparing statement 1.\n";
print_r( $e->getMessage() );
}
BreakConnection( $conn, $conn_break );
try
{
if ( $stmt1->execute() ) echo "Statement 1 executed.\n";
else echo "Statement 1 failed.\n";
}
catch( PDOException $e )
{
echo "Exception executing statement 1.\n";
print_r( $e->getMessage() );
}
$conn = null;
///////////////////////////////////////////////////////////////////////////////
// Part 2
// Transaction should be committed because connection is broken before
// transaction begins
///////////////////////////////////////////////////////////////////////////////
try
{
$conn = new PDO( "sqlsrv:server = $server ; Database = $dbName ; $connectionInfo", $uid, $pwd );
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
}
catch( PDOException $e )
{
echo "Could not connect.\n";
print_r( $e->getMessage() );
}
BreakConnection( $conn, $conn_break );
try
{
if ( $conn->beginTransaction() ) echo "Transaction begun.\n";
else echo "Could not begin transaction.\n";
}
catch( PDOException $e )
{
print_r( $e->getMessage() );
echo "Exception: could not begin transaction.\n";
}
$tsql = "INSERT INTO $tableName1 VALUES ( 700, 'zyxwv' )";
try
{
$stmt2 = $conn->query( $tsql );
if ( $stmt2 )
{
if ( $conn->commit() )
{
echo "Transaction was committed.\n";
}
else
{
echo "Statement valid but commit failed.\n";
print_r( sqlsrv_errors() );
}
}
else
{
if ( $conn->rollBack() )
{
echo "Transaction was rolled back.\n";
}
else
{
echo "Statement not valid and rollback failed.\n";
print_r( sqlsrv_errors() );
}
}
}
catch ( PDOException $e )
{
print_r( $e->getMessage() );
}
$conn = null;
///////////////////////////////////////////////////////////////////////////////
// Part 3
// Expected to trigger an error because connection is interrupted in the middle
// of a transaction
///////////////////////////////////////////////////////////////////////////////
try
{
$conn = new PDO( "sqlsrv:server = $server ; Database = $dbName ; $connectionInfo", $uid, $pwd );
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
}
catch( PDOException $e )
{
echo "Could not connect.\n";
print_r( $e->getMessage() );
}
try
{
if ( $conn->beginTransaction() ) echo "Transaction begun.\n";
else echo "Could not begin transaction.\n";
}
catch( PDOException $e )
{
print_r( $e->getMessage() );
echo "Exception: could not begin transaction.\n";
}
BreakConnection( $conn, $conn_break );
$tsql = "INSERT INTO $tableName1 VALUES ( 700, 'zyxwv' )";
try
{
$stmt2 = $conn->query( $tsql );
if ( $stmt2 )
{
if ( $conn->commit() )
{
echo "Transaction was committed.\n";
}
else
{
echo "Statement valid but commit failed.\n";
print_r( sqlsrv_errors() );
}
}
else
{
if ( $conn->rollBack() )
{
echo "Transaction was rolled back.\n";
}
else
{
echo "Statement not valid and rollback failed.\n";
print_r( sqlsrv_errors() );
}
}
}
catch ( PDOException $e )
{
print_r( $e->getMessage() );
}
// This try catch block prevents an Uncaught PDOException error that occurs
// when trying to free the connection.
try
{
$conn = null;
}
catch ( PDOException $e )
{
print_r( $e->getMessage() );
}
$conn_break = null;
?>
--EXPECTREGEX--
Statement 1 prepared.
Statement 1 executed.
Transaction begun.
Transaction was committed.
Transaction begun.
SQLSTATE\[08S02\]: \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]TCP Provider: An existing connection was forcibly closed by the remote host.
SQLSTATE\[08S01\]: \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]Communication link failure

View file

@ -0,0 +1,87 @@
--TEST--
Test connection resiliency timeouts
--DESCRIPTION--
1. Connect with ConnectRetryCount equal to 0.
2. Reconnect with the default value of ConnectRetryCount(1).
--SKIPIF--
<?php require('skipif_protocol_not_tcp.inc'); ?>
--FILE--
<?php
require_once( "break_pdo.php" );
$conn_break = new PDO( "sqlsrv:server = $server ; Database = $dbName ;", $uid, $pwd );
///////////////////////////////////////////////////////////////////////////////
// Part 1
// Expected to error out because ConnectRetryCount equals 0
///////////////////////////////////////////////////////////////////////////////
$connectionInfo = "ConnectRetryCount = 0;";
try
{
$conn = new PDO( "sqlsrv:server = $server ; Database = $dbName ; $connectionInfo", $uid, $pwd );
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
}
catch( PDOException $e )
{
echo "Could not connect.\n";
print_r( $e->getMessage() );
}
BreakConnection( $conn, $conn_break );
try
{
$stmt1 = $conn->query( "SELECT * FROM $tableName1" );
if ( $stmt1 ) echo "Query successfully executed.\n";
}
catch( PDOException $e )
{
echo "Error executing statement 1.\n";
print_r( $e->getMessage() );
}
$conn = null;
///////////////////////////////////////////////////////////////////////////////
// Part 2
// Expected to succeed with a single reconnection attempt
///////////////////////////////////////////////////////////////////////////////
$connectionInfo = "ConnectRetryInterval = 10;";
try
{
$conn = new PDO( "sqlsrv:server = $server ; Database = $dbName ; $connectionInfo", $uid, $pwd );
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
}
catch( PDOException $e )
{
echo "Could not connect.\n";
print_r( $e->getMessage() );
}
BreakConnection( $conn, $conn_break );
try
{
$stmt2 = $conn->query( "SELECT * FROM $tableName1" );
if ( $stmt2 ) echo "Query successfully executed.\n";
}
catch( PDOException $e )
{
echo "Error executing statement 2.\n";
print_r( $e->getMessage() );
}
$conn = null;
$conn_break = null;
DropTables( $server, $uid, $pwd, $tableName1, $tableName2 );
?>
--EXPECTREGEX--
Error executing statement 1.
SQLSTATE\[08S02\]: \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]TCP Provider: An existing connection was forcibly closed by the remote host.
Query successfully executed.

View file

@ -0,0 +1,35 @@
<?php
if ( !( strtoupper( substr( php_uname( 's' ),0,3 ) ) === 'WIN' ) ) die( "Skip Test on windows only." );
if (!extension_loaded("pdo_sqlsrv")) {
die("skip Extension not loaded");
}
require_once( "MsSetup.inc" );
$conn = new PDO( "sqlsrv:server = $server ;", $uid, $pwd );
if( $conn === false )
{
die( "skip Could not connect during SKIPIF." );
}
// Get process ID. Not the same as the one during the actual test, but
// we only need to know the protocol for a particular connection.
$stmt = $conn->query( "SELECT @@SPID" );
if ( $stmt )
{
$spid = $stmt->fetch(PDO::FETCH_NUM)[0];
}
else
{
die( "skip Could not fetch SPID during SKIPIF.");
}
$stmt = $conn->query( "SELECT * FROM sys.dm_exec_connections WHERE session_id = ".$spid);
$prot = $stmt->fetchColumn(3);
if ($prot != 'TCP')
{
die("skip Not using a TCP protocol." );
}
?>

View file

@ -0,0 +1,113 @@
--TEST--
Test UTF8 Encoding with emulate prepare
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
try {
$inValue1 = pack('H*', '3C586D6C54657374446174613E4A65207072C3A966C3A87265206C27C3A974C3A93C2F586D6C54657374446174613E');
$inValueLen = strlen($inValue1);
require_once 'MsSetup.inc';
$dsn = "sqlsrv:Server=$server ; Database = $databaseName";
$conn = new PDO($dsn, $uid, $pwd);
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$conn->setAttribute( PDO::SQLSRV_ATTR_ENCODING, PDO::SQLSRV_ENCODING_SYSTEM);
$stmt1 = $conn->query("IF OBJECT_ID('Table_UTF', 'U') IS NOT NULL DROP TABLE [Table_UTF]");
$stmt1 = null;
$stmt2 = $conn->query("CREATE TABLE [Table_UTF] ([c1_int] int PRIMARY KEY, [c2_char] char(512))");
$stmt2 = null;
$stmt3 = $conn->prepare("INSERT INTO [Table_UTF] (c1_int, c2_char) VALUES (:var1, :var2)");
$stmt3->setAttribute(constant('PDO::SQLSRV_ATTR_ENCODING'), PDO::SQLSRV_ENCODING_UTF8);
$stmt3->bindParam(2, $inValue1);
$stmt3->bindValue(1, 1);
$stmt3->execute();
$stmt3->bindValue(1, 2);
$stmt3->execute();
$stmt3->bindValue(1, 3);
$stmt3->execute();
$stmt3->bindValue(1, 4);
$stmt3->execute();
$stmt3->bindValue(1, 5);
$stmt3->execute();
$stmt3 = null;
$stmt4 = $conn->prepare("SELECT * FROM [Table_UTF]");
$stmt4->setAttribute(constant('PDO::SQLSRV_ATTR_ENCODING'), PDO::SQLSRV_ENCODING_UTF8);
$outValue1 = null;
$stmt4->execute();
$row1 = $stmt4->fetch();
$count1 = count($row1);
echo ("Number of rows: $count1\n");
$v0 = $row1[0];
$outValue1 = $row1[1];
if (strncmp($inValue1, $outValue1, $inValueLen) == 0) {
echo "outValue is the same as inValue.\n";
}
$outValue1 = null;
$value1 = $stmt4->fetchcolumn(1);
$outValue1 = $value1;
if (strncmp($inValue1, $outValue1, $inValueLen) == 0) {
echo "outValue is the same as inValue.\n";
}
$outvalue1 = null;
$value2 = $stmt4->fetchColumn(1);
$outValue1 = $value2;
if (strncmp($inValue1, $outValue1, $inValueLen) == 0) {
echo "outValue is the same as inValue.\n";
}
$outValue1 = null;
$value3 = $stmt4->fetchColumn(1);
$outValue1 = $value3;
if (strncmp($inValue1, $outValue1, $inValueLen) == 0) {
echo "outValue is the same as inValue.\n";
}
$outValue1 = null;
$value4 = $stmt4->fetchColumn(1);
$outValue1 = $value4;
if (strncmp($inValue1, $outValue1, $inValueLen) == 0) {
echo "outValue is the same as inValue.\n";
}
$stmt4 = null;
$stmt5 = $conn->prepare( "SELECT ? = c2_char FROM [Table_UTF]", array(PDO::ATTR_EMULATE_PREPARES => true) );
$stmt5->setAttribute(constant('PDO::SQLSRV_ATTR_ENCODING'), PDO::SQLSRV_ENCODING_UTF8);
$outValue1 = "hello";
$stmt5->bindParam( 1, $outValue1, PDO::PARAM_STR, 1024);
$stmt5->execute();
if (strncmp($inValue1, $outValue1, $inValueLen) == 0) {
echo "outValue is the same as inValue.\n";
} else {
echo "outValue is $outValue1\n";
}
$stmt5 = null;
$stmt6 = $conn->query("DROP TABLE [Table_UTF]");
$stmt6 = null;
$conn = null;
}
catch (PDOexception $e){
print_r( ($e->errorInfo)[2] );
echo "\n";
}
?>
--EXPECT--
Number of rows: 4
outValue is the same as inValue.
outValue is the same as inValue.
outValue is the same as inValue.
outValue is the same as inValue.
outValue is the same as inValue.
Statement with emulate prepare on does not support output or input_output parameters.

88
test/sqlsrv/break.php Normal file
View file

@ -0,0 +1,88 @@
<?php
require_once("MsSetup.inc");
// Using the tempdb database for two tables specifically constructed
// for the connection resiliency tests
$dbName = "tempdb";
$tableName1 = "test_connres1";
$tableName2 = "test_connres2";
// Generate tables for use with the connection resiliency tests.
// Using generated tables will eventually allow us to put the
// connection resiliency tests on Github, since the integrated testing
// from AppVeyor does not have AdventureWorks.
function GenerateTables( $server, $uid, $pwd, $dbName, $tableName1, $tableName2 )
{
$connectionInfo = array( "Database"=>$dbName, "uid"=>$uid, "pwd"=>$pwd );
$conn = sqlsrv_connect( $server, $connectionInfo );
if ( $conn === false )
{
die ( print_r( sqlsrv_errors() ) );
}
// Create table
$sql = "CREATE TABLE $tableName1 ( c1 INT, c2 VARCHAR(40) )";
$stmt = sqlsrv_query( $conn, $sql );
// Insert data
$sql = "INSERT INTO $tableName1 VALUES ( ?, ? )";
for( $t = 100; $t < 116; $t++ )
{
$ts = substr( sha1( $t ),0,5 );
$params = array( $t,$ts );
$stmt = sqlsrv_prepare( $conn, $sql, $params );
sqlsrv_execute( $stmt );
}
// Create table
$sql = "CREATE TABLE $tableName2 ( c1 INT, c2 VARCHAR(40) )";
$stmt = sqlsrv_query( $conn, $sql );
// Insert data
$sql = "INSERT INTO $tableName2 VALUES ( ?, ? )";
for( $t = 200; $t < 209; $t++ )
{
$ts = substr( sha1( $t ),0,5 );
$params = array( $t,$ts );
$stmt = sqlsrv_prepare( $conn, $sql, $params );
sqlsrv_execute( $stmt );
}
sqlsrv_close( $conn );
}
// Break connection by getting the session ID and killing it.
// Note that breaking a connection and testing reconnection requires a
// TCP/IP protocol connection (as opposed to a Shared Memory protocol).
function BreakConnection( $conn, $conn_break )
{
$stmt1 = sqlsrv_query( $conn, "SELECT @@SPID" );
if ( sqlsrv_fetch( $stmt1 ) )
{
$spid=sqlsrv_get_field( $stmt1, 0 );
}
$stmt2 = sqlsrv_prepare( $conn_break, "KILL ".$spid );
sqlsrv_execute( $stmt2 );
sleep(1);
}
// Remove the tables generated by GenerateTables
function DropTables( $server, $uid, $pwd, $tableName1, $tableName2 )
{
$connectionInfo = array( "UID"=>$uid, "PWD"=>$pwd );
$conn = sqlsrv_connect( $server, $connectionInfo );
$query="IF OBJECT_ID('tempdb.dbo.$tableName1', 'U') IS NOT NULL DROP TABLE tempdb.dbo.$tableName1";
$stmt=sqlsrv_query( $conn, $query );
$query="IF OBJECT_ID('tempdb.dbo.$tableName2', 'U') IS NOT NULL DROP TABLE tempdb.dbo.$tableName2";
$stmt=sqlsrv_query( $conn, $query );
}
DropTables( $server, $uid, $pwd, $tableName1, $tableName2 );
GenerateTables( $server, $uid, $pwd, $dbName, $tableName1, $tableName2 );
?>

View file

@ -0,0 +1,262 @@
--TEST--
Connection recovery test
--DESCRIPTION--
Connect and execute a command, kill the connection, execute another command.
Then do it again without a buffered result set, by freeing the statement before
killing the connection and then not freeing it. The latter case is the only one
that should fail. Finally, execute two queries in two threads on a recovered
non-MARS connection. This should fail too.
--SKIPIF--
<?php require('skipif_protocol_not_tcp.inc'); ?>
--FILE--
<?php
// There is a lot of repeated code here that could be refactored with helper methods,
// mostly for statement allocation. But that would affect scoping for the $stmt variables,
// which could affect the results when attempting to reconnect. What happens to statements
// when exiting the helper method? Do the associated cursors remain active? It is an
// unnecessary complication, so I have left the code like this.
require_once( "break.php" );
$conn_break = sqlsrv_connect( $server, array( "Database"=>$dbName, "UID"=>$uid, "PWD"=>$pwd) );
///////////////////////////////////////////////////////////////////////////////
// Part 1
// Expected to successfully execute second query because buffered cursor for
// first query means connection is idle when broken
///////////////////////////////////////////////////////////////////////////////
$connectionInfo = array( "Database"=>$dbName, "UID"=>$uid, "PWD"=>$pwd, "ConnectionPooling"=>false,
"ConnectRetryCount"=>10, "ConnectRetryInterval"=>10 );
$conn = sqlsrv_connect( $server, $connectionInfo );
if( $conn === false )
{
echo "Could not connect.\n";
print_r( sqlsrv_errors() );
}
$stmt1 = sqlsrv_query( $conn, "SELECT * FROM $tableName1", array(), array( "Scrollable"=>"buffered" ) );
if( $stmt1 === false )
{
echo "Error in statement 1.\n";
print_r( sqlsrv_errors() );
}
else
{
echo "Statement 1 successful.\n";
$rowcount = sqlsrv_num_rows( $stmt1 );
echo $rowcount." rows in result set.\n";
}
BreakConnection( $conn, $conn_break );
$stmt2 = sqlsrv_query( $conn, "SELECT * FROM $tableName2", array(), array( "Scrollable"=>"buffered" ) );
if( $stmt2 === false )
{
echo "Error in statement 2.\n";
print_r( sqlsrv_errors() );
}
else
{
echo "Statement 2 successful.\n";
$rowcount = sqlsrv_num_rows( $stmt2 );
echo $rowcount." rows in result set.\n";
}
sqlsrv_close( $conn );
///////////////////////////////////////////////////////////////////////////////
// Part 2
// Expected to successfully execute second query because first statement is
// freed before breaking connection
///////////////////////////////////////////////////////////////////////////////
$conn = sqlsrv_connect( $server, $connectionInfo );
if( $conn === false )
{
echo "Could not connect.\n";
print_r( sqlsrv_errors() );
}
$stmt3 = sqlsrv_query( $conn, "SELECT * FROM $tableName1" );
if( $stmt3 === false )
{
echo "Error in statement 3.\n";
print_r( sqlsrv_errors() );
}
else
{
echo "Statement 3 successful.\n";
$rowcount = sqlsrv_num_rows( $stmt3 );
echo $rowcount." rows in result set.\n";
}
sqlsrv_free_stmt( $stmt3 );
BreakConnection( $conn, $conn_break );
$stmt4 = sqlsrv_query( $conn, "SELECT * FROM $tableName2" );
if( $stmt4 === false )
{
echo "Error in statement 4.\n";
print_r( sqlsrv_errors() );
}
else
{
echo "Statement 4 successful.\n";
$rowcount = sqlsrv_num_rows( $stmt4 );
echo $rowcount." rows in result set.\n";
}
sqlsrv_close( $conn );
///////////////////////////////////////////////////////////////////////////////
// Part 3
// Expected to fail executing second query because default cursor for first
// query is still active when connection is broken
///////////////////////////////////////////////////////////////////////////////
$conn = sqlsrv_connect( $server, $connectionInfo );
if( $conn === false )
{
echo "Could not connect.\n";
print_r( sqlsrv_errors() );
}
$stmt5 = sqlsrv_query( $conn, "SELECT * FROM $tableName1" );
if( $stmt5 === false )
{
echo "Error in statement 5.\n";
print_r( sqlsrv_errors() );
}
else
{
echo "Statement 5 successful.\n";
$rowcount = sqlsrv_num_rows( $stmt5 );
echo $rowcount." rows in result set.\n";
}
BreakConnection( $conn, $conn_break );
$stmt6 = sqlsrv_query( $conn, "SELECT * FROM $tableName2" );
if( $stmt6 === false )
{
echo "Error in statement 6.\n";
print_r( sqlsrv_errors() );
}
else
{
echo "Statement 6 successful.\n";
$rowcount = sqlsrv_num_rows( $stmt6 );
echo $rowcount." rows in result set.\n";
}
sqlsrv_close( $conn );
///////////////////////////////////////////////////////////////////////////////
// Part 4
// Expected to trigger an error because there are two active statements with
// pending results and MARS is off
///////////////////////////////////////////////////////////////////////////////
$connectionInfo = array( "Database"=>$dbName, "UID"=>$uid, "PWD"=>$pwd,
"ConnectRetryCount"=>10, "ConnectRetryInterval"=>10, "MultipleActiveResultSets"=>false );
$conn = sqlsrv_connect( $server, $connectionInfo );
if( $conn === false )
{
echo "Could not connect.\n";
print_r( sqlsrv_errors() );
}
BreakConnection( $conn, $conn_break );
$stmt7 = sqlsrv_query( $conn, "SELECT * FROM $tableName1" );
if( $stmt7 === false )
{
echo "Error in statement 7.\n";
print_r( sqlsrv_errors() );
}
else
{
echo "Statement 7 successful.\n";
}
$stmt8 = sqlsrv_query( $conn, "SELECT * FROM $tableName2" );
if( $stmt8 === false )
{
echo "Error in statement 8.\n";
print_r( sqlsrv_errors() );
}
else
{
echo "Statement 8 successful.\n";
}
sqlsrv_close( $conn );
sqlsrv_close( $conn_break );
?>
--EXPECTREGEX--
Statement 1 successful.
16 rows in result set.
Statement 2 successful.
9 rows in result set.
Statement 3 successful.
rows in result set.
Statement 4 successful.
rows in result set.
Statement 5 successful.
rows in result set.
Error in statement 6.
Array
\(
\[0\] => Array
\(
\[0\] => 08S01
\[SQLSTATE\] => 08S01
\[1\] => 10054
\[code\] => 10054
\[2\] => \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]TCP Provider: An existing connection was forcibly closed by the remote host.
\[message\] => \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]TCP Provider: An existing connection was forcibly closed by the remote host.
\)
\[1\] => Array
\(
\[0\] => 08S01
\[SQLSTATE\] => 08S01
\[1\] => 10054
\[code\] => 10054
\[2\] => \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]Communication link failure
\[message\] => \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]Communication link failure
\)
\)
Statement 7 successful.
Error in statement 8.
Array
\(
\[0\] => Array
\(
\[0\] => IMSSP
\[SQLSTATE\] => IMSSP
\[1\] => -44
\[code\] => -44
\[2\] => The connection cannot process this operation because there is a statement with pending results. To make the connection available for other queries, either fetch all results or cancel or free the statement. For more information, see the product documentation about the MultipleActiveResultSets connection option.
\[message\] => The connection cannot process this operation because there is a statement with pending results. To make the connection available for other queries, either fetch all results or cancel or free the statement. For more information, see the product documentation about the MultipleActiveResultSets connection option.
\)
\[1\] => Array
\(
\[0\] => HY000
\[SQLSTATE\] => HY000
\[1\] => 0
\[code\] => 0
\[2\] => \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]Connection is busy with results for another command
\[message\] => \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]Connection is busy with results for another command
\)
\)

View file

@ -0,0 +1,207 @@
--TEST--
Test connection resiliency with a prepared statement and transaction.
--DESCRIPTION--
Prepare a statement, break the connection, and execute the statement. Then
test transactions by breaking the connection before beginning a transaction
and in the middle of the transaction. The latter case should fail (i.e., the
transaction should be rolled back).
--SKIPIF--
<?php require('skipif_protocol_not_tcp.inc'); ?>
--FILE--
<?php
require_once( "break.php" );
$conn_break = sqlsrv_connect( $server, array( "Database"=>$dbName, "UID"=>$uid, "PWD"=>$pwd) );
///////////////////////////////////////////////////////////////////////////////
// Part 1
// Statement expected to be executed because the connection is idle after
// statement has been prepared
///////////////////////////////////////////////////////////////////////////////
$connectionInfo = array( "Database"=>$dbName, "UID"=>$uid, "PWD"=>$pwd, "ConnectionPooling"=>false,
"ConnectRetryCount"=>10, "ConnectRetryInterval"=>10 );
$conn = sqlsrv_connect( $server, $connectionInfo );
if( $conn === false )
{
echo "Could not connect.\n";
print_r( sqlsrv_errors() );
}
$stmt1 = sqlsrv_prepare( $conn, "SELECT * FROM $tableName1" );
if( $stmt1 === false )
{
echo "Error in statement preparation.\n";
print_r( sqlsrv_errors() );
}
else
{
echo "Statement 1 prepared.\n";
}
BreakConnection( $conn, $conn_break );
if( sqlsrv_execute( $stmt1 ) )
{
echo "Statement 1 executed.\n";
}
else
{
echo "Statement 1 could not be executed.\n";
print_r( sqlsrv_errors() );
}
sqlsrv_close( $conn );
///////////////////////////////////////////////////////////////////////////////
// Part 2
// Transaction should be committed because connection is broken before
// transaction begins
///////////////////////////////////////////////////////////////////////////////
$conn = sqlsrv_connect( $server, $connectionInfo );
if( $conn === false )
{
echo "Could not connect.\n";
print_r( sqlsrv_errors() );
}
BreakConnection( $conn, $conn_break );
if ( sqlsrv_begin_transaction( $conn ) === false )
{
echo "Could not begin transaction.\n";
print_r( sqlsrv_errors() );
}
else
{
echo "Transaction begun.\n";
}
$number = 700;
$string = 'zxywv';
$tsql = "INSERT INTO $tableName1 VALUES ( ?, ? )";
$params = array( $number, $string );
$stmt2 = sqlsrv_query( $conn, $tsql, $params );
if( $stmt2 )
{
if ( sqlsrv_commit( $conn ) )
{
echo "Transaction was committed.\n";
}
else
{
echo "Statement valid but commit failed.\n";
print_r( sqlsrv_errors() );
}
}
else
{
if ( sqlsrv_rollback( $conn ) )
{
echo "Transaction was rolled back.\n";
}
else
{
echo "Statement not valid and rollback failed.\n";
print_r( sqlsrv_errors() );
}
}
sqlsrv_close( $conn );
///////////////////////////////////////////////////////////////////////////////
// Part 3
// Expected to trigger an error because connection is interrupted in the middle
// of a transaction
///////////////////////////////////////////////////////////////////////////////
$conn = sqlsrv_connect( $server, $connectionInfo );
if( $conn === false )
{
echo "Could not connect.\n";
print_r( sqlsrv_errors() );
}
if ( sqlsrv_begin_transaction( $conn ) === false )
{
echo "Could not begin transaction.\n";
print_r( sqlsrv_errors() );
}
else
{
echo "Transaction begun.\n";
}
BreakConnection( $conn, $conn_break );
$number = 700;
$string = 'zxywv';
$tsql = "INSERT INTO $tableName1 VALUES ( ?, ? )";
$params = array( $number, $string );
$stmt2 = sqlsrv_query( $conn, $tsql, $params );
if( $stmt2 )
{
if ( sqlsrv_commit( $conn ) )
{
echo "Transaction was committed.\n";
}
else
{
echo "Statement valid but commit failed.\n";
print_r( sqlsrv_errors() );
}
}
else
{
if ( sqlsrv_rollback( $conn ) )
{
echo "Transaction was rolled back.\n";
}
else
{
echo "Statement not valid and rollback failed.\n";
print_r( sqlsrv_errors() );
}
}
sqlsrv_close( $conn );
sqlsrv_close( $conn_break );
?>
--EXPECTREGEX--
Statement 1 prepared.
Statement 1 executed.
Transaction begun.
Transaction was committed.
Transaction begun.
Statement not valid and rollback failed.
Array
\(
\[0\] => Array
\(
\[0\] => 08S02
\[SQLSTATE\] => 08S02
\[1\] => 10054
\[code\] => 10054
\[2\] => \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]TCP Provider: An existing connection was forcibly closed by the remote host.
\[message\] => \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]TCP Provider: An existing connection was forcibly closed by the remote host.
\)
\[1\] => Array
\(
\[0\] => 08S02
\[SQLSTATE\] => 08S02
\[1\] => 10054
\[code\] => 10054
\[2\] => \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]Unable to open a logical session
\[message\] => \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]Unable to open a logical session
\)
\)

View file

@ -0,0 +1,105 @@
--TEST--
Test connection resiliency timeouts
--DESCRIPTION--
1. Connect with ConnectRetryCount equal to 0.
2. Reconnect with the default value of ConnectRetryCount (the default is 1).
--SKIPIF--
<?php require('skipif_protocol_not_tcp.inc'); ?>
--FILE--
<?php
require_once( "break.php" );
$conn_break = sqlsrv_connect( $server, array( "Database"=>$dbName, "UID"=>$uid, "PWD"=>$pwd) );
///////////////////////////////////////////////////////////////////////////////
// Part 1
// Expected to error out because ConnectRetryCount equals 0
///////////////////////////////////////////////////////////////////////////////
$connectionInfo = array( "Database"=>$dbName, "UID"=>$uid, "PWD"=>$pwd,
"ConnectRetryCount"=>0 );
$conn = sqlsrv_connect( $server, $connectionInfo );
if( $conn === false )
{
echo "Could not connect.\n";
print_r( sqlsrv_errors() );
}
BreakConnection( $conn, $conn_break );
$stmt1 = sqlsrv_query( $conn, "SELECT * FROM $tableName1" );
if( $stmt1 === false )
{
echo "Error in statement 1.\n";
print_r( sqlsrv_errors() );
}
else
{
echo "Statement 1 successful.\n";
}
sqlsrv_close( $conn );
///////////////////////////////////////////////////////////////////////////////
// Part 2
// Expected to succeed with a single reconnection attempt
///////////////////////////////////////////////////////////////////////////////
$connectionInfo = array( "Database"=>$dbName, "UID"=>$uid, "PWD"=>$pwd,
"ConnectRetryInterval"=>10 );
$conn = sqlsrv_connect( $server, $connectionInfo );
if( $conn === false )
{
echo "Could not connect.\n";
print_r( sqlsrv_errors() );
}
BreakConnection( $conn, $conn_break );
$stmt2 = sqlsrv_query( $conn, "SELECT * FROM $tableName1" );
if( $stmt2 === false )
{
echo "Error in statement 2.\n";
print_r( sqlsrv_errors() );
}
else
{
echo "Statement 2 successful.\n";
}
sqlsrv_close( $conn );
sqlsrv_close( $conn_break );
DropTables( $server, $uid, $pwd, $tableName1, $tableName2 )
?>
--EXPECTREGEX--
Error in statement 1.
Array
\(
\[0\] => Array
\(
\[0\] => 08S01
\[SQLSTATE\] => 08S01
\[1\] => 10054
\[code\] => 10054
\[2\] => \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]TCP Provider: An existing connection was forcibly closed by the remote host.
\[message\] => \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]TCP Provider: An existing connection was forcibly closed by the remote host.
\)
\[1\] => Array
\(
\[0\] => 08S01
\[SQLSTATE\] => 08S01
\[1\] => 10054
\[code\] => 10054
\[2\] => \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]Communication link failure
\[message\] => \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]Communication link failure
\)
\)
Statement 2 successful.

View file

@ -6,6 +6,7 @@ sqlsrv_close($conn1);
$conn2 = Connect();
$connId2 = ConnectionID($conn2);
sqlsrv_close($conn2);
if ($connId1 === $connId2){
echo "Pooled\n";

View file

@ -0,0 +1,39 @@
<?php
if ( !( strtoupper( substr( php_uname( 's' ),0,3 ) ) === 'WIN' ) ) die( "Skip Test on windows only." );
if (!extension_loaded("sqlsrv")) {
die("skip Extension not loaded");
}
require_once( "MsSetup.inc" );
$connectionInfo = array( "UID"=>$userName, "PWD"=>$userPassword );
$conn = sqlsrv_connect( $server, $connectionInfo );
if( $conn === false )
{
die( "skip Could not connect during SKIPIF." );
}
// Get process ID. Not the same as the one during the actual test, but
// we only need to know the protocol for a particular connection.
$stmt = sqlsrv_query( $conn, "SELECT @@SPID" );
if ( sqlsrv_fetch( $stmt ) )
{
$spid = sqlsrv_get_field( $stmt, 0 );
}
else
{
die("skip Could not fetch SPID.");
}
$stmt = sqlsrv_query( $conn, "SELECT * FROM sys.dm_exec_connections WHERE session_id = $spid");
if ( sqlsrv_fetch( $stmt ) )
{
$prot = sqlsrv_get_field( $stmt, 3 );
if ($prot != 'TCP')
{
die( "skip Not using a TCP protocol." );
}
}
?>

View file

@ -4,32 +4,60 @@ SQLSRV 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");?>
<?php if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') die("Skipped: Test for Linux and Mac"); ?>
--FILE--
<?php
// On Bamboo we must use sudo to fiddle with odbcinst.ini
// On travis-ci we can't use sudo
$sudo = '';
$user = posix_getpwuid(posix_geteuid());
if (strtolower($user['name']) != 'root')
{
$sudo = 'sudo ';
}
$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];
//back up the odbcinst.ini file
shell_exec($sudo."cp $odbcinst_ini $odbcinst_ini.bak");
//enable pooling by modifying the odbcinst.ini file
$current = file_get_contents($odbcinst_ini);
$current.=$lines_to_add;
file_put_contents($odbcinst_ini, $current);
shell_exec("cp $odbcinst_ini .");
file_put_contents("odbcinst.ini", $current);
shell_exec($sudo."cp odbcinst.ini $odbcinst_ini");
//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/sqlsrv/isPooled.php"));
print_r(shell_exec(PHP_BINARY." ".dirname(__FILE__)."/isPooled.php"));
//disable pooling by modifying the odbcinst.ini file
$current = file_get_contents($odbcinst_ini);
$current = str_replace($lines_to_add,'',$current);
file_put_contents($odbcinst_ini, $current);
file_put_contents("odbcinst.ini", $current);
shell_exec($sudo."cp odbcinst.ini $odbcinst_ini");
print_r(shell_exec("php ./test/sqlsrv/isPooled.php"));
print_r(shell_exec(PHP_BINARY." ".dirname(__FILE__)."/isPooled.php"));
?>
--CLEAN--
<?php
$sudo = '';
$user = posix_getpwuid(posix_geteuid());
if (strtolower($user['name']) == 'bamboo')
{
$sudo = 'sudo ';
}
$lines = explode("\n", shell_exec("odbcinst -j"));
$odbcinst_ini = explode(" ", $lines[1])[1];
shell_exec($sudo."cp $odbcinst_ini.bak $odbcinst_ini");
shell_exec($sudo."rm $odbcinst_ini.bak");
?>
--EXPECT--
Pooled
Not Pooled

View file

@ -107,4 +107,3 @@ Array
[message] => Invalid option for the Authentication keyword. Only SqlPassword or ActiveDirectoryPassword is supported.
)
%s with Authentication=ActiveDirectoryPassword.

View file

@ -23,7 +23,7 @@ sqlsrv_configure( 'WarningsReturnAsErrors', 0 );
sqlsrv_configure( 'LogSeverity', SQLSRV_LOG_SEVERITY_ALL );
// test an invalid encoding
$c = connect(array( 'CharacterSet' => 'jibberish' ));
$c = connect(array( 'CharacterSet' => 'gibberish' ));
if( $c !== false ) {
FatalError( "Should have errored on an invalid encoding." );
}
@ -88,8 +88,8 @@ Array
[SQLSTATE] => IMSSP
[1] => -48
[code] => -48
[2] => The encoding 'jibberish' is not a supported encoding for the CharacterSet connection option.
[message] => The encoding 'jibberish' is not a supported encoding for the CharacterSet connection option.
[2] => The encoding 'gibberish' is not a supported encoding for the CharacterSet connection option.
[message] => The encoding 'gibberish' is not a supported encoding for the CharacterSet connection option.
)
)

View file

@ -0,0 +1,303 @@
--TEST--
variety of connection parameters.
--SKIPIF--
<?php require('skipif_unix.inc'); ?>
--FILE--
<?php
require 'MsSetup.inc';
function connect($options=array()) {
require 'MsSetup.inc';
if (!isset($options['UID']) && !isset($options['uid'])) {
$options['uid'] = $uid;
}
if (!isset($options['pwd']) && !isset($options['PWD'])) {
$options['pwd'] = $pwd;
}
if (!isset($options['Database'])) {
$options['database'] = $databaseName;
}
return sqlsrv_connect($server, $options);
}
sqlsrv_configure( 'WarningsReturnAsErrors', 0 );
sqlsrv_configure( 'LogSeverity', SQLSRV_LOG_SEVERITY_ALL );
echo "Test sqlsrv_connect with integrated authentication\n";
$conn = connect();
if( !$conn ) {
var_dump( sqlsrv_errors() );
}
sqlsrv_close( $conn );
echo "Test sqlsrv_connect with integrated authentication and parameters\n";
$conn = connect(array('UID' => '', 'PWD' => ''));
if( !$conn ) {
var_dump( sqlsrv_errors() );
}
sqlsrv_close( $conn );
echo "Test sqlsrv_connect( <server>, array( 'UID' => 'sa', 'PWD' ))\n";
$conn = connect(array( 'UID' => 'sa' ));
if( !$conn ) {
var_dump( sqlsrv_errors() );
}
sqlsrv_close( $conn );
echo "Test sqlsrv_connect( <server>, array( 'UID' => 'sa', 'PWD', 'Driver' => 'SQL Server Native Client 11.0' ))\n";
$conn = connect(array( 'UID' => 'sa', 'PWD' => '', 'Driver' => 'SQL Server Native Client 11.0' ));
if( !$conn ) {
var_dump( sqlsrv_errors() );
}
else {
sqlsrv_close( $conn );
die( "Shouldn't have opened the connection." );
}
echo "Test sqlsrv_connect with driver injection\n";
$conn = sqlsrv_connect( $server, array( "UID" => "sa", "PWD" => "$pwd;Driver={SQL Server Native Client 11.0}}" ));
if( !$conn ) {
var_dump( sqlsrv_errors() );
}
else {
sqlsrv_close( $conn );
die( "Shouldn't have opened the connection." );
}
echo "Test sqlsrv_connect with driver injection (2)\n";
$conn = sqlsrv_connect( $server, array( "UID" => "sa", "PWD" => "{$pwd};Driver={SQL Server Native Client 11.0}" ));
if( !$conn ) {
var_dump( sqlsrv_errors() );
}
else {
sqlsrv_close( $conn );
die( "Shouldn't have opened the connection." );
}
echo "Test sqlsrv_connect with driver injection (3)\n";
$conn = sqlsrv_connect( $server, array( "UID" => "sa", "PWD" => "{$pwd}};Driver={SQL Server Native Client 11.0}" ));
if( !$conn ) {
var_dump( sqlsrv_errors() );
}
else {
sqlsrv_close( $conn );
die( "Shouldn't have opened the connection." );
}
// Test a bunch of options. The Failover_Partner keyword does not work
// on Unix, so we replace it with MultiSubnetFailover instead.
$conn_options_all = array( "APP" => "PHP Unit Test",
"ConnectionPooling" => true,
"Database" => $databaseName,
"Encrypt" => 0,
"LoginTimeout" => 120,
"MultipleActiveResultSets" => false,
"QuotedId" => false,
"TraceOn" => true,
"TraceFile" => "trace.odbc",
"TransactionIsolation" => SQLSRV_TXN_READ_COMMITTED,
"TrustServerCertificate" => 1,
"WSID" => "JAYKINT1" );
$conn_options_int = array( "APP" => "PHP Unit Test",
"ConnectionPooling" => false,
"Database" => $databaseName,
"Encrypt" => 0,
"LoginTimeout" => 120,
"MultipleActiveResultSets" => false,
"QuotedId" => true,
"TraceOn" => true,
"TraceFile" => "trace.odbc",
"TransactionIsolation" => SQLSRV_TXN_READ_COMMITTED,
"TrustServerCertificate" => 1,
"WSID" => "JAYKINT1" );
if ( strtoupper( substr( php_uname( 's' ),0,3 ) ) === 'WIN' )
{
echo "Test sqlsrv_connect with all options\n";
$conn_options_all['Failover_Partner'] = "(local)";
$conn = connect($conn_options_all);
print_r( sqlsrv_errors()[0] );
print_r( sqlsrv_errors()[1] );
if( $conn === false ) {
die( print_r( sqlsrv_errors(), true ));
}
echo "Test sqlsrv_connect with all options and integrated auth\n";
$conn_options_int['Failover_Partner'] = "(local)";
$conn = connect($conn_options_int);
print_r( sqlsrv_errors()[0] );
print_r( sqlsrv_errors()[1] );
if( $conn === false ) {
die( print_r( sqlsrv_errors(), true ));
}
}
else
{
echo "Test sqlsrv_connect with all options\n";
$conn_options_all['MultiSubnetFailover'] = true;
$conn = connect($conn_options_all);
print_r( sqlsrv_errors()[0] );
print_r( sqlsrv_errors()[1] );
if( $conn === false ) {
die( print_r( sqlsrv_errors(), true ));
}
echo "Test sqlsrv_connect with all options and integrated auth\n";
$conn_options_int['MultiSubnetFailover'] = true;
$conn = connect($conn_options_int);
print_r( sqlsrv_errors()[0] );
print_r( sqlsrv_errors()[1] );
if( $conn === false ) {
die( print_r( sqlsrv_errors(), true ));
}
}
// test brackets around a value
$conn = connect(array( 'APP' => '{Ltm.exe}' ));
if( $conn === false ) {
die( print_r( sqlsrv_errors(), true ));
}
sqlsrv_close( $conn );
echo "Test succeeded.\n";
?>
--EXPECTREGEX--
Test sqlsrv_connect with integrated authentication
Test sqlsrv_connect with integrated authentication and parameters
Test sqlsrv_connect\( .*, array\( 'UID' => '.*', 'PWD' \)\)
Test sqlsrv_connect\( .*, array\( 'UID' => '.*', 'PWD', 'Driver' => '.*' \)\)
array\(1\) \{
\[0\]=>
array\(6\) \{
\[0\]=>
string\(5\) "IMSSP"
\["SQLSTATE"\]=>
string\(5\) "IMSSP"
\[1\]=>
int\(-1\)
\["code"\]=>
int\(-1\)
\[2\]=>
string\([0-9]+\) "Invalid option .* was passed to sqlsrv_connect."
\["message"\]=>
string\([0-9]+\) "Invalid option .* was passed to sqlsrv_connect."
\}
\}
Test sqlsrv_connect with driver injection
array\(2\) \{
\[0\]=>
array\(6\) \{
\[0\]=>
string\(5\) "28000"
\["SQLSTATE"\]=>
string\(5\) "28000"
\[1\]=>
int\(18456\)
\["code"\]=>
int\(18456\)
\[2\]=>
string\(81\) ".*Login failed for user 'sa'."
\["message"\]=>
string\(81\) ".*Login failed for user 'sa'."
\}
\[1\]=>
array\(6\) \{
\[0\]=>
string\(5\) "28000"
\["SQLSTATE"\]=>
string\(5\) "28000"
\[1\]=>
int\(18456\)
\["code"\]=>
int\(18456\)
\[2\]=>
string\(81\) ".*Login failed for user 'sa'."
\["message"\]=>
string\(81\) ".*Login failed for user 'sa'."
}
}
Test sqlsrv_connect with driver injection \(2\)
array\(1\) \{
\[0\]=>
array\(6\) \{
\[0\]=>
string\(5\) "IMSSP"
\["SQLSTATE"\]=>
string\(5\) "IMSSP"
\[1\]=>
int\(-4\)
\["code"\]=>
int\(-4\)
\[2\]=>
string\(140\) "An unescaped right brace \(\}\) was found in either the user name or password. All right braces must be escaped with another right brace \(\}\}\)."
\["message"\]=>
string\(140\) "An unescaped right brace \(\}\) was found in either the user name or password. All right braces must be escaped with another right brace \(\}\}\)."
\}
\}
Test sqlsrv_connect with driver injection \(3\)
array\(1\) \{
\[0\]=>
array\(6\) \{
\[0\]=>
string\(5\) "IMSSP"
\["SQLSTATE"\]=>
string\(5\) "IMSSP"
\[1\]=>
int\(-4\)
\["code"\]=>
int\(-4\)
\[2\]=>
string\(140\) "An unescaped right brace \(\}\) was found in either the user name or password. All right braces must be escaped with another right brace \(\}\}\)."
\["message"\]=>
string\(140\) "An unescaped right brace \(\}\) was found in either the user name or password. All right braces must be escaped with another right brace \(\}\}\)."
\}
\}
Test sqlsrv_connect with all options
Array
\(
\[0\] => 01000
\[SQLSTATE\] => 01000
\[1\] => 5701
\[code\] => 5701
\[2\] => .*Changed database context to '.*'.
\[message\] => .*Changed database context to '.*'.
\)
Array
\(
\[0\] => 01000
\[SQLSTATE\] => 01000
\[1\] => 5703
\[code\] => 5703
\[2\] => .*Changed language setting to us_english.
\[message\] => .*Changed language setting to us_english.
\)
Test sqlsrv_connect with all options and integrated auth
Array
\(
\[0\] => 01000
\[SQLSTATE\] => 01000
\[1\] => 5701
\[code\] => 5701
\[2\] => .*Changed database context to '.*'.
\[message\] => .*Changed database context to '.*'.
\)
Array
\(
\[0\] => 01000
\[SQLSTATE\] => 01000
\[1\] => 5703
\[code\] => 5703
\[2\] => .*Changed language setting to us_english.
\[message\] => .*Changed language setting to us_english.
\)
Test succeeded.

View file

@ -1,7 +1,7 @@
--TEST--
warnings as errors
--SKIPIF--
<?php require('skipif_unix.inc'); ?>
<?php require('skipif.inc'); ?>
--FILE--
<?php
@ -14,8 +14,15 @@ $conn = Connect();
if( $conn === false ) {
die( print_r( sqlsrv_errors(), true ));
}
// Should print connection warnings and not die
// Outputting the first two elements works around a bug in unixODBC that
// duplicates error messages and would otherwise cause the test to fail because
// of the extra output
echo "Warnings from sqlsrv_connect:\n";
print_r( sqlsrv_errors(SQLSRV_ERR_WARNINGS) ); // should print connection warnings and not die
print_r( sqlsrv_errors(SQLSRV_ERR_WARNINGS)[0] );
print_r( sqlsrv_errors(SQLSRV_ERR_WARNINGS)[1] );
echo "Errors from sqlsrv_connect:\n";
print_r( sqlsrv_errors(SQLSRV_ERR_ERRORS) );
$v1 = 1;
@ -34,8 +41,10 @@ if( $stmt === false ) {
echo "Errors from sqlsrv_query with WarningsReturnAsErrors = true:\n";
print_r( sqlsrv_errors(SQLSRV_ERR_ERRORS) ); // should be 1 warning of '3'
}
echo "Warnings from sqlsrv_query with WarningsReturnAsErrors = true:\n";
print_r( sqlsrv_errors(SQLSRV_ERR_WARNINGS) ); // should be nothing
echo "Output:\n$v3\n";
sqlsrv_configure( 'WarningsReturnAsErrors', false );
@ -44,8 +53,10 @@ if( $stmt === false ) {
echo "Errors from sqlsrv_query with WarningsReturnAsErrors = false:\n";
die( print_r( sqlsrv_errors() ));
}
echo "Warnings from sqlsrv_query with WarningsReturnAsErrors = false:\n";
print_r( sqlsrv_errors() );
echo "Output:\n$v3\n";
sqlsrv_close( $conn );
@ -57,26 +68,21 @@ print "Test successful";
Warnings from sqlsrv_connect:
Array
(
[0] => Array
(
[0] => 01000
[SQLSTATE] => 01000
[1] => 5701
[code] => 5701
[2] => %SChanged database context to '%S'.
[message] => %SChanged database context to '%S'.
)
[1] => Array
(
[0] => 01000
[SQLSTATE] => 01000
[1] => 5703
[code] => 5703
[2] => %SChanged language setting to us_english.
[message] => %SChanged language setting to us_english.
)
[0] => 01000
[SQLSTATE] => 01000
[1] => 5701
[code] => 5701
[2] => %SChanged database context to '%S'.
[message] => %SChanged database context to '%S'.
)
Array
(
[0] => 01000
[SQLSTATE] => 01000
[1] => 5703
[code] => 5703
[2] => %SChanged language setting to us_english.
[message] => %SChanged language setting to us_english.
)
Errors from sqlsrv_connect:
Errors from raiserror

View file

@ -1,7 +1,7 @@
--TEST--
warnings as errors
--SKIPIF--
<?php require('skipif_unix.inc'); ?>
<?php require('skipif.inc'); ?>
--FILE--
<?php
@ -50,7 +50,10 @@ $result = sqlsrv_rows_affected( $stmt );
if( $result !== false ) {
die( "sqlsrv_rows_affected should have failed because it wasn't yet executed." );
}
print_r( sqlsrv_errors() );
// Outputting the zero element of the error array works around a bug in the
// ODBC driver for Linux that produces an error message saying 'Cancel treated
// as FreeStmt/Close' on a statement that has not been executed.
print_r( sqlsrv_errors()[0] );
sqlsrv_execute( $stmt );
@ -146,15 +149,11 @@ Array
)
Array
(
[0] => Array
(
[0] => IMSSP
[SQLSTATE] => IMSSP
[1] => -11
[code] => -11
[2] => The statement must be executed before results can be retrieved.
[message] => The statement must be executed before results can be retrieved.
)
[0] => IMSSP
[SQLSTATE] => IMSSP
[1] => -11
[code] => -11
[2] => The statement must be executed before results can be retrieved.
[message] => The statement must be executed before results can be retrieved.
)
Test successful