Skip to content

Commit e1e0108

Browse files
authored
Dropped the use of LOCK TIMEOUT (#1165)
1 parent 460d9aa commit e1e0108

File tree

8 files changed

+90
-44
lines changed

8 files changed

+90
-44
lines changed

source/pdo_sqlsrv/pdo_stmt.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1523,12 +1523,3 @@ sqlsrv_phptype pdo_sqlsrv_stmt::sql_type_to_php_type( _In_ SQLINTEGER sql_type,
15231523

15241524
return sqlsrv_phptype;
15251525
}
1526-
1527-
void pdo_sqlsrv_stmt::set_query_timeout()
1528-
{
1529-
if (query_timeout == QUERY_TIMEOUT_INVALID || query_timeout < 0) {
1530-
return;
1531-
}
1532-
1533-
core::SQLSetStmtAttr(this, SQL_ATTR_QUERY_TIMEOUT, reinterpret_cast<SQLPOINTER>((SQLLEN)query_timeout), SQL_IS_UINTEGER);
1534-
}

source/pdo_sqlsrv/php_pdo_sqlsrv_int.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -260,9 +260,6 @@ struct pdo_sqlsrv_stmt : public sqlsrv_stmt {
260260
// for PDO, everything is a string, so we return SQLSRV_PHPTYPE_STRING for all SQL types
261261
virtual sqlsrv_phptype sql_type_to_php_type( _In_ SQLINTEGER sql_type, _In_ SQLUINTEGER size, _In_ bool prefer_string_to_stream );
262262

263-
// driver specific way to set query timeout
264-
virtual void set_query_timeout();
265-
266263
bool direct_query; // flag set if the query should be executed directly or prepared
267264
const char* direct_query_subst_string; // if the query is direct, hold the substitution string if using named parameters
268265
size_t direct_query_subst_string_len; // length of query string used for direct queries

source/shared/core_sqlsrv.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1520,6 +1520,8 @@ struct sqlsrv_stmt : public sqlsrv_context {
15201520

15211521
// free sensitivity classification metadata
15221522
void clean_up_sensitivity_metadata();
1523+
// set query timeout
1524+
void set_query_timeout();
15231525

15241526
sqlsrv_conn* conn; // Connection that created this statement
15251527

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

1574-
// driver specific way to set query timeout
1575-
virtual void set_query_timeout() = 0;
15761576
};
15771577

15781578
// *** field metadata struct ***

source/shared/core_stmt.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,15 @@ void sqlsrv_stmt::clean_up_sensitivity_metadata()
275275
}
276276
}
277277

278+
void sqlsrv_stmt::set_query_timeout()
279+
{
280+
if (query_timeout == QUERY_TIMEOUT_INVALID || query_timeout < 0) {
281+
return;
282+
}
283+
284+
core::SQLSetStmtAttr(this, SQL_ATTR_QUERY_TIMEOUT, reinterpret_cast<SQLPOINTER>((SQLLEN)query_timeout), SQL_IS_UINTEGER);
285+
}
286+
278287
// core_sqlsrv_create_stmt
279288
// Common code to allocate a statement from either driver. Returns a valid driver statement object or
280289
// throws an exception if an error occurs.

source/sqlsrv/php_sqlsrv_int.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,6 @@ struct ss_sqlsrv_stmt : public sqlsrv_stmt {
130130
// driver specific conversion rules from a SQL Server/ODBC type to one of the SQLSRV_PHPTYPE_* constants
131131
sqlsrv_phptype sql_type_to_php_type( _In_ SQLINTEGER sql_type, _In_ SQLUINTEGER size, _In_ bool prefer_string_to_stream );
132132

133-
// driver specific way to set query timeout
134-
virtual void set_query_timeout();
135-
136133
bool prepared; // whether the statement has been prepared yet (used for error messages)
137134
zend_ulong conn_index; // index into the connection hash that contains this statement structure
138135
zval* params_z; // hold parameters passed to sqlsrv_prepare but not used until sqlsrv_execute

source/sqlsrv/stmt.cpp

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -261,29 +261,6 @@ sqlsrv_phptype ss_sqlsrv_stmt::sql_type_to_php_type( _In_ SQLINTEGER sql_type, _
261261
return ss_phptype;
262262
}
263263

264-
void ss_sqlsrv_stmt::set_query_timeout()
265-
{
266-
if (query_timeout == QUERY_TIMEOUT_INVALID || query_timeout < 0) {
267-
return;
268-
}
269-
270-
// set the statement attribute
271-
core::SQLSetStmtAttr(this, SQL_ATTR_QUERY_TIMEOUT, reinterpret_cast<SQLPOINTER>( (SQLLEN)query_timeout ), SQL_IS_UINTEGER );
272-
273-
// a query timeout of 0 indicates "no timeout", which means that lock_timeout should also be set to "no timeout" which
274-
// is represented by -1.
275-
int lock_timeout = (( query_timeout == 0 ) ? -1 : query_timeout * 1000 /*convert to milliseconds*/ );
276-
277-
// set the LOCK_TIMEOUT on the server.
278-
char lock_timeout_sql[32] = {'\0'};
279-
280-
int written = snprintf( lock_timeout_sql, sizeof( lock_timeout_sql ), "SET LOCK_TIMEOUT %d", lock_timeout );
281-
SQLSRV_ASSERT( (written != -1 && written != sizeof( lock_timeout_sql )),
282-
"stmt_option_query_timeout: snprintf failed. Shouldn't ever fail." );
283-
284-
core::SQLExecDirect(this, lock_timeout_sql );
285-
}
286-
287264
// statement specific parameter proccessing. Uses the generic function specialised to return a statement
288265
// resource.
289266
#define PROCESS_PARAMS( rsrc, param_spec, calling_func, param_count, ... ) \
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
--TEST--
2+
GitHub issue 1100 - PDO::SQLSRV_ATTR_QUERY_TIMEOUT had no effect when reconnecting
3+
--DESCRIPTION--
4+
This test verifies that setting PDO::SQLSRV_ATTR_QUERY_TIMEOUT should work when reconnecting after disconnecting
5+
--ENV--
6+
PHPT_EXEC=true
7+
--SKIPIF--
8+
<?php require('skipif_mid-refactor.inc'); ?>
9+
--FILE--
10+
<?php
11+
require_once("MsSetup.inc");
12+
require_once("MsCommon_mid-refactor.inc");
13+
14+
function checkTimeElapsed($t0, $t1, $expectedDelay)
15+
{
16+
$elapsed = $t1 - $t0;
17+
$diff = abs($elapsed - $expectedDelay);
18+
$leeway = 1.0;
19+
$missed = ($diff > $leeway);
20+
trace("$elapsed secs elapsed\n");
21+
22+
if ($missed) {
23+
echo "Expected $expectedDelay but $elapsed secs elapsed\n";
24+
}
25+
}
26+
27+
function testTimeout($conn, $timeout)
28+
{
29+
$delay = 5;
30+
$query = "WAITFOR DELAY '00:00:$delay'; SELECT 1";
31+
$error = '*Query timeout expired';
32+
33+
$t0 = microtime(true);
34+
try {
35+
$conn->exec($query);
36+
$elapsed = microtime(true) - $t0;
37+
echo "Should have failed after $timeout secs but $elapsed secs have elapsed" . PHP_EOL;
38+
} catch (PDOException $e) {
39+
$t1 = microtime(true);
40+
41+
$message = '*Query timeout expired';
42+
if (!fnmatch($message, $e->getMessage())) {
43+
var_dump($e->getMessage());
44+
}
45+
checkTimeElapsed($t0, $t1, $timeout);
46+
}
47+
}
48+
49+
try {
50+
$keywords = 'MultipleActiveResultSets=false;';
51+
$timeout = 1;
52+
53+
$options = array(PDO::SQLSRV_ATTR_QUERY_TIMEOUT => $timeout);
54+
$conn = connect($keywords, $options);
55+
56+
testTimeout($conn, $timeout);
57+
unset($conn);
58+
59+
$conn = connect($keywords);
60+
$conn->setAttribute(PDO::SQLSRV_ATTR_QUERY_TIMEOUT, $timeout);
61+
62+
testTimeout($conn, $timeout);
63+
unset($conn);
64+
65+
echo "Done\n";
66+
} catch (PdoException $e) {
67+
echo $e->getMessage() . PHP_EOL;
68+
}
69+
70+
?>
71+
--EXPECT--
72+
Done

test/functional/sqlsrv/test_timeout.phpt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,23 @@ sqlsrv_configure( 'LogSeverity', SQLSRV_LOG_SEVERITY_ALL );
1010

1111
require( 'MsCommon.inc' );
1212

13-
$throwaway = Connect(array( 'ConnectionPooling' => 1 ));
13+
// MARS allows applications to have more than one pending request per connection and to have more
14+
// than one active default result set per connection, which is not required for this test.
15+
$options = array('ConnectionPooling' => 1, 'MultipleActiveResultSets' => 0);
16+
17+
$throwaway = Connect();
1418
if( !$throwaway ) {
1519
die( print_r( sqlsrv_errors(), true ));
1620
}
1721

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

20-
$conn = Connect(array( 'ConnectionPooling' => 1 ));
24+
$conn = Connect($options);
2125
if( !$conn ) {
2226
die( print_r( sqlsrv_errors(), true ));
2327
}
2428

25-
$conn2 = Connect(array( 'ConnectionPooling' => 1 ));
29+
$conn2 = Connect($options);
2630
if( !$conn2 ) {
2731
die( print_r( sqlsrv_errors(), true ));
2832
}
@@ -47,7 +51,6 @@ for( $i = 1; $i <= 3; ++$i ) {
4751
die( print_r( sqlsrv_errors(), true ));
4852
}
4953

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

0 commit comments

Comments
 (0)