Skip to content

Commit 0e65d53

Browse files
committed
Fix connection timeout for stored procedures. Fixes #672
1 parent 7cf22fd commit 0e65d53

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed

src/MySqlConnector/Core/CommandExecutor.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,13 @@ public static async Task<DbDataReader> ExecuteReaderAsync(IReadOnlyList<IMySqlCo
3636
cachedProcedures = new Dictionary<string, CachedProcedure?>();
3737
var commandText = command2.CommandText!;
3838
if (!cachedProcedures.ContainsKey(commandText))
39+
{
3940
cachedProcedures.Add(commandText, await connection.GetCachedProcedure(ioBehavior, commandText, cancellationToken).ConfigureAwait(false));
41+
42+
// because the connection was used to execute a MySqlDataReader with the connection's DefaultCommandTimeout,
43+
// we need to reapply the command's CommandTimeout (even if some of the time has elapsed)
44+
command.CancellableCommand.ResetCommandTimeout();
45+
}
4046
}
4147
}
4248

tests/SideBySide/CommandTimeoutTests.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,48 @@ public async Task CommandTimeoutWithSleepAsync()
113113
Assert.Equal(ConnectionState.Closed, m_connection.State);
114114
}
115115

116+
[SkippableTheory(ServerFeatures.Timeout)]
117+
[InlineData(true)]
118+
[InlineData(false)]
119+
public void CommandTimeoutWithStoredProcedureSleepSync(bool pooling)
120+
{
121+
using (var cmd = new MySqlCommand(@"drop procedure if exists sleep_sproc;
122+
create procedure sleep_sproc(IN seconds INT)
123+
begin
124+
select sleep(seconds);
125+
end;", m_connection))
126+
{
127+
cmd.ExecuteNonQuery();
128+
}
129+
130+
var csb = AppConfig.CreateConnectionStringBuilder();
131+
csb.Pooling = pooling;
132+
using (var connection = new MySqlConnection(csb.ConnectionString))
133+
using (var cmd = new MySqlCommand("sleep_sproc", connection))
134+
{
135+
connection.Open();
136+
cmd.CommandType = CommandType.StoredProcedure;
137+
cmd.Parameters.AddWithValue("seconds", 10);
138+
cmd.CommandTimeout = 2;
139+
140+
var sw = Stopwatch.StartNew();
141+
try
142+
{
143+
using (var reader = cmd.ExecuteReader())
144+
{
145+
// shouldn't get here
146+
Assert.True(false);
147+
}
148+
}
149+
catch (MySqlException ex)
150+
{
151+
sw.Stop();
152+
Assert.Contains(c_timeoutMessage, ex.Message, StringComparison.OrdinalIgnoreCase);
153+
TestUtilities.AssertDuration(sw, ((int) cmd.CommandTimeout) * 1000 - 100, 500);
154+
}
155+
}
156+
}
157+
116158
[SkippableFact(ServerFeatures.Timeout, Baseline = "https://bugs.mysql.com/bug.php?id=87307")]
117159
public void MultipleCommandTimeoutWithSleepSync()
118160
{

0 commit comments

Comments
 (0)