Connection resiliency changes (#356)

* Connection resiliency changes

* Changed connres test to check appveyor protocol

* Changed connres test to check appveyor protocol

* Changed connres test to check appveyor protocol

* Reverted test because appveyor still won't use the correct protocol

* Removed unnecessary connres #defines from msodbcsql.h
This commit is contained in:
David Puglielli 2017-04-04 13:40:30 -07:00 committed by ulvii
parent 52e05992bd
commit f330830eef
7 changed files with 365 additions and 22 deletions

View file

@ -166,10 +166,14 @@ test_script:
after_test:
- cd %APPVEYOR_BUILD_FOLDER%\test\
- python output.py
- ps: $files = Get-ChildItem sqlsrv\*.diff
- ps: foreach($file in $files){ls $file; more $file; more "$file.out"}
- ps: $files = Get-ChildItem pdo_sqlsrv\*.diff
- ps: foreach($file in $files){ls $file; more $file; more "$file.out"}
- ps: $difffiles = Get-ChildItem sqlsrv\*.diff
- ps: $outfiles = Get-ChildItem sqlsrv\*.out
- ps: foreach($file in $difffiles){ls $file; more $file}
- ps: foreach($file in $outfiles){ls $file; more $file}
- ps: $difffiles = Get-ChildItem pdo_sqlsrv\*.diff
- ps: $outfiles = Get-ChildItem pdo_sqlsrv\*.out
- ps: foreach($file in $difffiles){ls $file; more $file}
- ps: foreach($file in $outfiles){ls $file; more $file}
- ps: (new-object net.webclient).UploadFile("https://ci.appveyor.com/api/testresults/junit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\nativeresult1.xml))
- ps: (new-object net.webclient).UploadFile("https://ci.appveyor.com/api/testresults/junit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\nativeresult2.xml))
- ps: >-

View file

@ -41,6 +41,10 @@ const char APP[] = "APP";
const char ApplicationIntent[] = "ApplicationIntent";
const char AttachDBFileName[] = "AttachDbFileName";
const char ConnectionPooling[] = "ConnectionPooling";
#ifdef _WIN32
const char ConnectRetryCount[] = "ConnectRetryCount";
const char ConnectRetryInterval[] = "ConnectRetryInterval";
#endif // _WIN32
const char Database[] = "Database";
const char Encrypt[] = "Encrypt";
const char Failover_Partner[] = "Failover_Partner";
@ -98,6 +102,24 @@ struct pdo_txn_isolation_conn_attr_func
static void func( connection_option const* /*option*/, zval* value_z, sqlsrv_conn* conn, std::string& /*conn_str*/ TSRMLS_DC );
};
#ifdef _WIN32
struct pdo_int_conn_str_func {
static void func( connection_option const* option, zval* value, sqlsrv_conn* /*conn*/, std::string& conn_str TSRMLS_DC )
{
TSRMLS_C;
SQLSRV_ASSERT( Z_TYPE_P( value ) == IS_STRING, "Wrong zval type for this keyword" )
std::string val_str = Z_STRVAL_P( value );
conn_str += option->odbc_name;
conn_str += "={";
conn_str += val_str;
conn_str += "};";
}
};
#endif // _WIN32
template <unsigned int Attr>
struct pdo_int_conn_attr_func {
@ -187,6 +209,26 @@ const connection_option PDO_CONN_OPTS[] = {
CONN_ATTR_BOOL,
conn_null_func::func
},
#ifdef _WIN32
{
PDOConnOptionNames::ConnectRetryCount,
sizeof( PDOConnOptionNames::ConnectRetryCount ),
SQLSRV_CONN_OPTION_CONN_RETRY_COUNT,
ODBCConnOptions::ConnectRetryCount,
sizeof( ODBCConnOptions::ConnectRetryCount ),
CONN_ATTR_INT,
pdo_int_conn_str_func::func
},
{
PDOConnOptionNames::ConnectRetryInterval,
sizeof( PDOConnOptionNames::ConnectRetryInterval ),
SQLSRV_CONN_OPTION_CONN_RETRY_INTERVAL,
ODBCConnOptions::ConnectRetryInterval,
sizeof( ODBCConnOptions::ConnectRetryInterval ),
CONN_ATTR_INT,
pdo_int_conn_str_func::func
},
#endif // _WIN32
{
PDOConnOptionNames::Database,
sizeof( PDOConnOptionNames::Database ),

View file

@ -1079,6 +1079,10 @@ const char ApplicationIntent[] = "ApplicationIntent";
const char AttachDBFileName[] = "AttachDbFileName";
const char CharacterSet[] = "CharacterSet";
const char ConnectionPooling[] = "ConnectionPooling";
#ifdef _WIN32
const char ConnectRetryCount[] = "ConnectRetryCount";
const char ConnectRetryInterval[] = "ConnectRetryInterval";
#endif // _WIN32
const char Database[] = "Database";
const char Encrypt[] = "Encrypt";
const char Failover_Partner[] = "Failover_Partner";
@ -1099,24 +1103,28 @@ const char SERVER[] = "Server";
enum SQLSRV_CONN_OPTIONS {
SQLSRV_CONN_OPTION_INVALID,
SQLSRV_CONN_OPTION_APP,
SQLSRV_CONN_OPTION_CHARACTERSET,
SQLSRV_CONN_OPTION_CONN_POOLING,
SQLSRV_CONN_OPTION_DATABASE,
SQLSRV_CONN_OPTION_ENCRYPT,
SQLSRV_CONN_OPTION_FAILOVER_PARTNER,
SQLSRV_CONN_OPTION_LOGIN_TIMEOUT,
SQLSRV_CONN_OPTION_MARS,
SQLSRV_CONN_OPTION_QUOTED_ID,
SQLSRV_CONN_OPTION_TRACE_FILE,
SQLSRV_CONN_OPTION_TRACE_ON,
SQLSRV_CONN_OPTION_TRANS_ISOLATION,
SQLSRV_CONN_OPTION_TRUST_SERVER_CERT,
SQLSRV_CONN_OPTION_WSID,
SQLSRV_CONN_OPTION_ATTACHDBFILENAME,
SQLSRV_CONN_OPTION_APPLICATION_INTENT,
SQLSRV_CONN_OPTION_MULTI_SUBNET_FAILOVER,
SQLSRV_CONN_OPTION_INVALID,
SQLSRV_CONN_OPTION_APP,
SQLSRV_CONN_OPTION_CHARACTERSET,
SQLSRV_CONN_OPTION_CONN_POOLING,
SQLSRV_CONN_OPTION_DATABASE,
SQLSRV_CONN_OPTION_ENCRYPT,
SQLSRV_CONN_OPTION_FAILOVER_PARTNER,
SQLSRV_CONN_OPTION_LOGIN_TIMEOUT,
SQLSRV_CONN_OPTION_MARS,
SQLSRV_CONN_OPTION_QUOTED_ID,
SQLSRV_CONN_OPTION_TRACE_FILE,
SQLSRV_CONN_OPTION_TRACE_ON,
SQLSRV_CONN_OPTION_TRANS_ISOLATION,
SQLSRV_CONN_OPTION_TRUST_SERVER_CERT,
SQLSRV_CONN_OPTION_WSID,
SQLSRV_CONN_OPTION_ATTACHDBFILENAME,
SQLSRV_CONN_OPTION_APPLICATION_INTENT,
SQLSRV_CONN_OPTION_MULTI_SUBNET_FAILOVER,
#ifdef _WIN32
SQLSRV_CONN_OPTION_CONN_RETRY_COUNT,
SQLSRV_CONN_OPTION_CONN_RETRY_INTERVAL,
#endif // _WIN32
// Driver specific connection options
SQLSRV_CONN_OPTION_DRIVER_SPECIFIC = 1000,

View file

@ -91,6 +91,7 @@
#define SQL_COPT_SS_AEKEYSTOREDATA (SQL_COPT_SS_BASE_EX+12) /* Communicate with a loaded keystore provider */
#define SQL_COPT_SS_AETRUSTEDCMKPATHS (SQL_COPT_SS_BASE_EX+13) /* List of trusted CMK paths */
#define SQL_COPT_SS_AECEKCACHETTL (SQL_COPT_SS_BASE_EX+14)// Symmetric Key Cache TTL
/*
* SQLColAttributes driver specific defines.
* SQLSetDescField/SQLGetDescField driver specific defines.

View file

@ -95,6 +95,24 @@ struct bool_conn_str_func {
}
};
#ifdef _WIN32
struct int_conn_str_func {
static void func( connection_option const* option, zval* value, sqlsrv_conn* /*conn*/, std::string& conn_str TSRMLS_DC )
{
TSRMLS_C;
SQLSRV_ASSERT( Z_TYPE_P( value ) == IS_LONG, "An integer is expected for this keyword" )
std::string val_str = std::to_string( Z_LVAL_P( value ));
conn_str += option->odbc_name;
conn_str += "={";
conn_str += val_str;
conn_str += "};";
}
};
#endif // _WIN32
template <unsigned int Attr>
struct int_conn_attr_func {
@ -169,6 +187,10 @@ const char ApplicationIntent[] = "ApplicationIntent";
const char AttachDBFileName[] = "AttachDbFileName";
const char CharacterSet[] = "CharacterSet";
const char ConnectionPooling[] = "ConnectionPooling";
#ifdef _WIN32
const char ConnectRetryCount[] = "ConnectRetryCount";
const char ConnectRetryInterval[] = "ConnectRetryInterval";
#endif // _WIN32
const char Database[] = "Database";
const char DateAsString[] = "ReturnDatesAsStrings";
const char Encrypt[] = "Encrypt";
@ -269,6 +291,26 @@ const connection_option SS_CONN_OPTS[] = {
CONN_ATTR_BOOL,
conn_null_func::func
},
#ifdef _WIN32
{
SSConnOptionNames::ConnectRetryCount,
sizeof( SSConnOptionNames::ConnectRetryCount ),
SQLSRV_CONN_OPTION_CONN_RETRY_COUNT,
ODBCConnOptions::ConnectRetryCount,
sizeof( ODBCConnOptions::ConnectRetryCount ),
CONN_ATTR_INT,
int_conn_str_func::func
},
{
SSConnOptionNames::ConnectRetryInterval,
sizeof( SSConnOptionNames::ConnectRetryInterval ),
SQLSRV_CONN_OPTION_CONN_RETRY_INTERVAL,
ODBCConnOptions::ConnectRetryInterval,
sizeof( ODBCConnOptions::ConnectRetryInterval ),
CONN_ATTR_INT,
int_conn_str_func::func
},
#endif // _WIN32
{
SSConnOptionNames::Database,
sizeof( SSConnOptionNames::Database ),

View file

@ -0,0 +1,82 @@
--TEST--
Test the connection resiliency keywords ConnectRetryCount and ConnectRetryInterval and their ranges of acceptable values
--SKIPIF--
<?php if ( !( strtoupper( substr( php_uname( 's' ),0,3 ) ) === 'WIN' ) ) die( "Skip, not running on windows." ); ?>
--FILE--
<?php
require_once( "autonomous_setup.php" );
function TryToConnect( $serverName, $username, $password, $retryCount, $retryInterval, $number )
{
$connectionInfo = "ConnectRetryCount = $retryCount; ConnectRetryInterval = $retryInterval;";
try
{
$conn = new PDO( "sqlsrv:server = $serverName ; $connectionInfo", $username, $password );
echo "Connected successfully on $number attempt.\n";
$conn = null;
}
catch( PDOException $e )
{
echo "Could not connect on $number attempt.\n";
print_r( $e->getMessage() );
echo "\n";
}
}
TryToConnect( $serverName, $username, $password, 10, 30, 'first');
TryToConnect( $serverName, $username, $password, 0, 30, 'second');
TryToConnect( $serverName, $username, $password, 256, 30, 'third');
TryToConnect( $serverName, $username, $password, 5, 70, 'fourth');
TryToConnect( $serverName, $username, $password, -1, 30, 'fifth');
TryToConnect( $serverName, $username, $password, 'thisisnotaninteger', 30, 'sixth');
TryToConnect( $serverName, $username, $password, 5, 3.14159, 'seventh');
$connectionInfo = "ConnectRetryCount;";
try
{
$conn = new PDO( "sqlsrv:server = $serverName ; $connectionInfo", $username, $password );
echo "Connected successfully on eighth attempt.\n";
$conn = null;
}
catch( PDOException $e )
{
echo "Could not connect on eighth attempt.\n";
print_r( $e->getMessage() );
echo "\n";
}
$connectionInfo = "ConnectRetryInterval;";
try
{
$conn = new PDO( "sqlsrv:server = $serverName ; $connectionInfo", $username, $password );
echo "Connected successfully on ninth attempt.\n";
$conn = null;
}
catch( PDOException $e )
{
echo "Could not connect on ninth attempt.\n";
print_r( $e->getMessage() );
echo "\n";
}
?>
--EXPECTREGEX--
Connected successfully on first attempt.
Connected successfully on second attempt.
Could not connect on third attempt.
SQLSTATE\[08001\]: \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]Invalid value specified for connection string attribute 'ConnectRetryCount'
Could not connect on fourth attempt.
SQLSTATE\[08001\]: \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]Invalid value specified for connection string attribute 'ConnectRetryInterval'
Could not connect on fifth attempt.
SQLSTATE\[08001\]: \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]Invalid value specified for connection string attribute 'ConnectRetryCount'
Could not connect on sixth attempt.
SQLSTATE\[08001\]: \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]Invalid value specified for connection string attribute 'ConnectRetryCount'
Could not connect on seventh attempt.
SQLSTATE\[08001\]: \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]Invalid value specified for connection string attribute 'ConnectRetryInterval'
Could not connect on eighth attempt.
SQLSTATE\[IMSSP\]: The DSN string ended unexpectedly.
Could not connect on ninth attempt.
SQLSTATE\[IMSSP\]: The DSN string ended unexpectedly.

View file

@ -0,0 +1,164 @@
--TEST--
Test the connection resiliency keywords ConnectRetryCount and ConnectRetryInterval and their ranges of acceptable values
--SKIPIF--
<?php if ( !( strtoupper( substr( php_uname( 's' ),0,3 ) ) === 'WIN' ) ) die( "Skip, not running on windows." ); ?>
--FILE--
<?php
require_once( "autonomous_setup.php" );
function TryToConnect( $serverName, $username, $password, $retryCount, $retryInterval, $number )
{
$connectionInfo = array( "UID"=>$username, "PWD"=>$password,
"ConnectRetryCount"=>$retryCount, "ConnectRetryInterval"=>$retryInterval );
$conn = sqlsrv_connect( $serverName, $connectionInfo );
if( $conn === false )
{
echo "Could not connect on $number attempt.\n";
print_r( sqlsrv_errors() );
}
else
{
echo "Connected successfully on $number attempt.\n";
sqlsrv_close( $conn );
}
}
TryToConnect( $serverName, $username, $password, 10, 30, 'first');
TryToConnect( $serverName, $username, $password, 0, 30, 'second');
TryToConnect( $serverName, $username, $password, 256, 30, 'third');
TryToConnect( $serverName, $username, $password, 5, 70, 'fourth');
TryToConnect( $serverName, $username, $password, -1, 30, 'fifth');
TryToConnect( $serverName, $username, $password, 'thisisnotaninteger', 30, 'sixth');
TryToConnect( $serverName, $username, $password, 5, 3.14159, 'seventh');
$connectionInfo = array( "UID"=>$username, "PWD"=>$password, "ConnectRetryCount" );
$conn = sqlsrv_connect( $serverName, $connectionInfo );
if( $conn === false )
{
echo "Could not connect on eighth attempt.\n";
print_r( sqlsrv_errors() );
}
else
{
echo "Connected successfully on eighth attempt.\n";
sqlsrv_close( $conn );
}
$connectionInfo = array( "UID"=>$username, "PWD"=>$password, "ConnectRetryInterval" );
$conn = sqlsrv_connect( $serverName, $connectionInfo );
if( $conn === false )
{
echo "Could not connect on ninth attempt.\n";
print_r( sqlsrv_errors() );
}
else
{
echo "Connected successfully on ninth attempt.\n";
sqlsrv_close( $conn );
}
?>
--EXPECTREGEX--
Connected successfully on first attempt.
Connected successfully on second attempt.
Could not connect on third attempt.
Array
\(
\[0\] => Array
\(
\[0\] => 08001
\[SQLSTATE\] => 08001
\[1\] => 0
\[code\] => 0
\[2\] => \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]Invalid value specified for connection string attribute 'ConnectRetryCount'
\[message\] => \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]Invalid value specified for connection string attribute 'ConnectRetryCount'
\)
\)
Could not connect on fourth attempt.
Array
\(
\[0\] => Array
\(
\[0\] => 08001
\[SQLSTATE\] => 08001
\[1\] => 0
\[code\] => 0
\[2\] => \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]Invalid value specified for connection string attribute 'ConnectRetryInterval'
\[message\] => \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]Invalid value specified for connection string attribute 'ConnectRetryInterval'
\)
\)
Could not connect on fifth attempt.
Array
\(
\[0\] => Array
\(
\[0\] => 08001
\[SQLSTATE\] => 08001
\[1\] => 0
\[code\] => 0
\[2\] => \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]Invalid value specified for connection string attribute 'ConnectRetryCount'
\[message\] => \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]Invalid value specified for connection string attribute 'ConnectRetryCount'
\)
\)
Could not connect on sixth attempt.
Array
\(
\[0\] => Array
\(
\[0\] => IMSSP
\[SQLSTATE\] => IMSSP
\[1\] => -33
\[code\] => -33
\[2\] => Invalid value type for option ConnectRetryCount was specified. Integer type was expected.
\[message\] => Invalid value type for option ConnectRetryCount was specified. Integer type was expected.
\)
\)
Could not connect on seventh attempt.
Array
\(
\[0\] => Array
\(
\[0\] => IMSSP
\[SQLSTATE\] => IMSSP
\[1\] => -33
\[code\] => -33
\[2\] => Invalid value type for option ConnectRetryInterval was specified. Integer type was expected.
\[message\] => Invalid value type for option ConnectRetryInterval was specified. Integer type was expected.
\)
\)
Could not connect on eighth attempt.
Array
\(
\[0\] => Array
\(
\[0\] => IMSSP
\[SQLSTATE\] => IMSSP
\[1\] => -8
\[code\] => -8
\[2\] => An invalid connection option key type was received. Option key types must be strings.
\[message\] => An invalid connection option key type was received. Option key types must be strings.
\)
\)
Could not connect on ninth attempt.
Array
\(
\[0\] => Array
\(
\[0\] => IMSSP
\[SQLSTATE\] => IMSSP
\[1\] => -8
\[code\] => -8
\[2\] => An invalid connection option key type was received. Option key types must be strings.
\[message\] => An invalid connection option key type was received. Option key types must be strings.
\)
\)