Skip to content

Dropped the use of LOCK TIMEOUT #1165

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 23, 2020
Merged
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
9 changes: 0 additions & 9 deletions source/pdo_sqlsrv/pdo_stmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1523,12 +1523,3 @@ sqlsrv_phptype pdo_sqlsrv_stmt::sql_type_to_php_type( _In_ SQLINTEGER sql_type,

return sqlsrv_phptype;
}

void pdo_sqlsrv_stmt::set_query_timeout()
{
if (query_timeout == QUERY_TIMEOUT_INVALID || query_timeout < 0) {
return;
}

core::SQLSetStmtAttr(this, SQL_ATTR_QUERY_TIMEOUT, reinterpret_cast<SQLPOINTER>((SQLLEN)query_timeout), SQL_IS_UINTEGER);
}
3 changes: 0 additions & 3 deletions source/pdo_sqlsrv/php_pdo_sqlsrv_int.h
Original file line number Diff line number Diff line change
Expand Up @@ -260,9 +260,6 @@ struct pdo_sqlsrv_stmt : public sqlsrv_stmt {
// for PDO, everything is a string, so we return SQLSRV_PHPTYPE_STRING for all SQL types
virtual sqlsrv_phptype sql_type_to_php_type( _In_ SQLINTEGER sql_type, _In_ SQLUINTEGER size, _In_ bool prefer_string_to_stream );

// driver specific way to set query timeout
virtual void set_query_timeout();

bool direct_query; // flag set if the query should be executed directly or prepared
const char* direct_query_subst_string; // if the query is direct, hold the substitution string if using named parameters
size_t direct_query_subst_string_len; // length of query string used for direct queries
Expand Down
4 changes: 2 additions & 2 deletions source/shared/core_sqlsrv.h
Original file line number Diff line number Diff line change
Expand Up @@ -1520,6 +1520,8 @@ struct sqlsrv_stmt : public sqlsrv_context {

// free sensitivity classification metadata
void clean_up_sensitivity_metadata();
// set query timeout
void set_query_timeout();

sqlsrv_conn* conn; // Connection that created this statement

Expand Down Expand Up @@ -1571,8 +1573,6 @@ struct sqlsrv_stmt : public sqlsrv_context {
// driver specific conversion rules from a SQL Server/ODBC type to one of the SQLSRV_PHPTYPE_* constants
virtual sqlsrv_phptype sql_type_to_php_type( _In_ SQLINTEGER sql_type, _In_ SQLUINTEGER size, _In_ bool prefer_string_to_stream ) = 0;

// driver specific way to set query timeout
virtual void set_query_timeout() = 0;
};

// *** field metadata struct ***
Expand Down
9 changes: 9 additions & 0 deletions source/shared/core_stmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,15 @@ void sqlsrv_stmt::clean_up_sensitivity_metadata()
}
}

void sqlsrv_stmt::set_query_timeout()
{
if (query_timeout == QUERY_TIMEOUT_INVALID || query_timeout < 0) {
return;
}

core::SQLSetStmtAttr(this, SQL_ATTR_QUERY_TIMEOUT, reinterpret_cast<SQLPOINTER>((SQLLEN)query_timeout), SQL_IS_UINTEGER);
}

// core_sqlsrv_create_stmt
// Common code to allocate a statement from either driver. Returns a valid driver statement object or
// throws an exception if an error occurs.
Expand Down
3 changes: 0 additions & 3 deletions source/sqlsrv/php_sqlsrv_int.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,6 @@ struct ss_sqlsrv_stmt : public sqlsrv_stmt {
// driver specific conversion rules from a SQL Server/ODBC type to one of the SQLSRV_PHPTYPE_* constants
sqlsrv_phptype sql_type_to_php_type( _In_ SQLINTEGER sql_type, _In_ SQLUINTEGER size, _In_ bool prefer_string_to_stream );

// driver specific way to set query timeout
virtual void set_query_timeout();

bool prepared; // whether the statement has been prepared yet (used for error messages)
zend_ulong conn_index; // index into the connection hash that contains this statement structure
zval* params_z; // hold parameters passed to sqlsrv_prepare but not used until sqlsrv_execute
Expand Down
23 changes: 0 additions & 23 deletions source/sqlsrv/stmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,29 +261,6 @@ sqlsrv_phptype ss_sqlsrv_stmt::sql_type_to_php_type( _In_ SQLINTEGER sql_type, _
return ss_phptype;
}

void ss_sqlsrv_stmt::set_query_timeout()
{
if (query_timeout == QUERY_TIMEOUT_INVALID || query_timeout < 0) {
return;
}

// set the statement attribute
core::SQLSetStmtAttr(this, SQL_ATTR_QUERY_TIMEOUT, reinterpret_cast<SQLPOINTER>( (SQLLEN)query_timeout ), SQL_IS_UINTEGER );

// a query timeout of 0 indicates "no timeout", which means that lock_timeout should also be set to "no timeout" which
// is represented by -1.
int lock_timeout = (( query_timeout == 0 ) ? -1 : query_timeout * 1000 /*convert to milliseconds*/ );

// set the LOCK_TIMEOUT on the server.
char lock_timeout_sql[32] = {'\0'};

int written = snprintf( lock_timeout_sql, sizeof( lock_timeout_sql ), "SET LOCK_TIMEOUT %d", lock_timeout );
SQLSRV_ASSERT( (written != -1 && written != sizeof( lock_timeout_sql )),
"stmt_option_query_timeout: snprintf failed. Shouldn't ever fail." );

core::SQLExecDirect(this, lock_timeout_sql );
}

// statement specific parameter proccessing. Uses the generic function specialised to return a statement
// resource.
#define PROCESS_PARAMS( rsrc, param_spec, calling_func, param_count, ... ) \
Expand Down
72 changes: 72 additions & 0 deletions test/functional/pdo_sqlsrv/pdo_1100_query_timeout_disconnect.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
--TEST--
GitHub issue 1100 - PDO::SQLSRV_ATTR_QUERY_TIMEOUT had no effect when reconnecting
--DESCRIPTION--
This test verifies that setting PDO::SQLSRV_ATTR_QUERY_TIMEOUT should work when reconnecting after disconnecting
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif_mid-refactor.inc'); ?>
--FILE--
<?php
require_once("MsSetup.inc");
require_once("MsCommon_mid-refactor.inc");

function checkTimeElapsed($t0, $t1, $expectedDelay)
{
$elapsed = $t1 - $t0;
$diff = abs($elapsed - $expectedDelay);
$leeway = 1.0;
$missed = ($diff > $leeway);
trace("$elapsed secs elapsed\n");

if ($missed) {
echo "Expected $expectedDelay but $elapsed secs elapsed\n";
}
}

function testTimeout($conn, $timeout)
{
$delay = 5;
$query = "WAITFOR DELAY '00:00:$delay'; SELECT 1";
$error = '*Query timeout expired';

$t0 = microtime(true);
try {
$conn->exec($query);
$elapsed = microtime(true) - $t0;
echo "Should have failed after $timeout secs but $elapsed secs have elapsed" . PHP_EOL;
} catch (PDOException $e) {
$t1 = microtime(true);

$message = '*Query timeout expired';
if (!fnmatch($message, $e->getMessage())) {
var_dump($e->getMessage());
}
checkTimeElapsed($t0, $t1, $timeout);
}
}

try {
$keywords = 'MultipleActiveResultSets=false;';
$timeout = 1;

$options = array(PDO::SQLSRV_ATTR_QUERY_TIMEOUT => $timeout);
$conn = connect($keywords, $options);

testTimeout($conn, $timeout);
unset($conn);

$conn = connect($keywords);
$conn->setAttribute(PDO::SQLSRV_ATTR_QUERY_TIMEOUT, $timeout);

testTimeout($conn, $timeout);
unset($conn);

echo "Done\n";
} catch (PdoException $e) {
echo $e->getMessage() . PHP_EOL;
}

?>
--EXPECT--
Done
11 changes: 7 additions & 4 deletions test/functional/sqlsrv/test_timeout.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,23 @@ sqlsrv_configure( 'LogSeverity', SQLSRV_LOG_SEVERITY_ALL );

require( 'MsCommon.inc' );

$throwaway = Connect(array( 'ConnectionPooling' => 1 ));
// MARS allows applications to have more than one pending request per connection and to have more
// than one active default result set per connection, which is not required for this test.
$options = array('ConnectionPooling' => 1, 'MultipleActiveResultSets' => 0);

$throwaway = Connect();
if( !$throwaway ) {
die( print_r( sqlsrv_errors(), true ));
}

for( $i = 1; $i <= 3; ++$i ) {

$conn = Connect(array( 'ConnectionPooling' => 1 ));
$conn = Connect($options);
if( !$conn ) {
die( print_r( sqlsrv_errors(), true ));
}

$conn2 = Connect(array( 'ConnectionPooling' => 1 ));
$conn2 = Connect($options);
if( !$conn2 ) {
die( print_r( sqlsrv_errors(), true ));
}
Expand All @@ -47,7 +51,6 @@ for( $i = 1; $i <= 3; ++$i ) {
die( print_r( sqlsrv_errors(), true ));
}


$stmt2 = sqlsrv_query( $conn2, "WAITFOR DELAY '00:00:05'; SELECT * FROM [test_query_timeout]", array(null), array( 'QueryTimeout' => 1 ));
if( $stmt2 === false ) {
print_r( sqlsrv_errors() );
Expand Down