Skip to content

Commit 495c092

Browse files
committed
Revalidate missing stored procedures in DeriveParameters. Fixes #730
1 parent 8749627 commit 495c092

File tree

4 files changed

+36
-4
lines changed

4 files changed

+36
-4
lines changed

src/MySqlConnector/Core/CommandExecutor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public static async Task<DbDataReader> ExecuteReaderAsync(IReadOnlyList<IMySqlCo
3636
var commandText = command2.CommandText!;
3737
if (!cachedProcedures.ContainsKey(commandText))
3838
{
39-
cachedProcedures.Add(commandText, await connection.GetCachedProcedure(ioBehavior, commandText, cancellationToken).ConfigureAwait(false));
39+
cachedProcedures.Add(commandText, await connection.GetCachedProcedure(commandText, revalidateMissing: false, ioBehavior, cancellationToken).ConfigureAwait(false));
4040

4141
// because the connection was used to execute a MySqlDataReader with the connection's DefaultCommandTimeout,
4242
// we need to reapply the command's CommandTimeout (even if some of the time has elapsed)

src/MySqlConnector/MySql.Data.MySqlClient/MySqlCommandBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ private static async Task DeriveParametersAsync(IOBehavior ioBehavior, MySqlComm
3232
if (command.Connection.Session.ServerVersion.Version < ServerVersions.SupportsProcedureCache)
3333
throw new NotSupportedException("MySQL Server {0} doesn't support INFORMATION_SCHEMA".FormatInvariant(command.Connection.Session.ServerVersion.OriginalString));
3434

35-
var cachedProcedure = await command.Connection.GetCachedProcedure(ioBehavior, command.CommandText!, cancellationToken).ConfigureAwait(false);
35+
var cachedProcedure = await command.Connection.GetCachedProcedure(command.CommandText!, revalidateMissing: true, ioBehavior, cancellationToken).ConfigureAwait(false);
3636
if (cachedProcedure is null)
3737
{
3838
var name = NormalizedSchema.MustNormalize(command.CommandText!, command.Connection.Database);

src/MySqlConnector/MySql.Data.MySqlClient/MySqlConnection.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@ internal void Cancel(ICancellableCommand command)
494494
}
495495
}
496496

497-
internal async Task<CachedProcedure?> GetCachedProcedure(IOBehavior ioBehavior, string name, CancellationToken cancellationToken)
497+
internal async Task<CachedProcedure?> GetCachedProcedure(string name, bool revalidateMissing, IOBehavior ioBehavior, CancellationToken cancellationToken)
498498
{
499499
if (Log.IsDebugEnabled())
500500
Log.Debug("Session{0} getting cached procedure Name={1}", m_session!.Id, name);
@@ -519,7 +519,7 @@ internal void Cancel(ICancellableCommand command)
519519
bool foundProcedure;
520520
lock (cachedProcedures)
521521
foundProcedure = cachedProcedures.TryGetValue(normalized.FullyQualified, out cachedProcedure);
522-
if (!foundProcedure)
522+
if (!foundProcedure || (cachedProcedure is null && revalidateMissing))
523523
{
524524
cachedProcedure = await CachedProcedure.FillAsync(ioBehavior, this, normalized.Schema!, normalized.Component!, cancellationToken).ConfigureAwait(false);
525525
if (Log.IsWarnEnabled())

tests/SideBySide/StoredProcedureTests.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,38 @@ public void DeriveParametersDoesNotExist()
545545
Assert.Throws<MySqlException>(() => MySqlCommandBuilder.DeriveParameters(cmd));
546546
}
547547

548+
[Fact]
549+
public void DeriveParametersDoesNotExistThenIsCreated()
550+
{
551+
using (var cmd = new MySqlCommand("drop procedure if exists xx_does_not_exist_2;", m_database.Connection))
552+
cmd.ExecuteNonQuery();
553+
554+
using (var cmd = new MySqlCommand("xx_does_not_exist_2", m_database.Connection))
555+
{
556+
cmd.CommandType = CommandType.StoredProcedure;
557+
Assert.Throws<MySqlException>(() => MySqlCommandBuilder.DeriveParameters(cmd));
558+
}
559+
560+
using (var cmd = new MySqlCommand(@"create procedure xx_does_not_exist_2(
561+
IN param1 INT,
562+
OUT param2 VARCHAR(100))
563+
BEGIN
564+
SELECT 'test' INTO param2;
565+
END", m_database.Connection))
566+
{
567+
cmd.ExecuteNonQuery();
568+
}
569+
570+
using (var cmd = new MySqlCommand("xx_does_not_exist_2", m_database.Connection))
571+
{
572+
cmd.CommandType = CommandType.StoredProcedure;
573+
MySqlCommandBuilder.DeriveParameters(cmd);
574+
Assert.Collection(cmd.Parameters.Cast<MySqlParameter>(),
575+
AssertParameter("@param1", ParameterDirection.Input, MySqlDbType.Int32),
576+
AssertParameter("@param2", ParameterDirection.Output, MySqlDbType.VarChar));
577+
}
578+
}
579+
548580
[SkippableFact(ServerFeatures.Json, Baseline = "https://bugs.mysql.com/bug.php?id=89335")]
549581
public void DeriveParametersSetJson()
550582
{

0 commit comments

Comments
 (0)