Skip to content

Commit

Permalink
Fix parsing of ENUM procedure parameters. Fixes #812
Browse files Browse the repository at this point in the history
  • Loading branch information
bgrainger committed May 7, 2020
1 parent 73532d9 commit b0b97a0
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 1 deletion.
4 changes: 4 additions & 0 deletions src/MySqlConnector/Core/CachedProcedure.cs
Expand Up @@ -157,6 +157,9 @@ internal static List<CachedParameter> ParseParameters(string parametersSql)
// strip precision specifier containing comma
parametersSql = Regex.Replace(parametersSql, @"(DECIMAL|DEC|FIXED|NUMERIC|FLOAT|DOUBLE PRECISION|DOUBLE|REAL)\s*\(\d+(,\s*\d+)\)", @"$1", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);

// strip enum values containing commas (these would have been stripped by ParseDataType anyway)
parametersSql = Regex.Replace(parametersSql, @"ENUM\s*\([^)]+\)", "ENUM", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);

var parameters = parametersSql.Split(',');
var cachedParameters = new List<CachedParameter>(parameters.Length);
for (var i = 0; i < parameters.Length; i++)
Expand Down Expand Up @@ -202,6 +205,7 @@ internal static string ParseDataType(string sql, out bool unsigned, out int leng
}
sql = Regex.Replace(sql, " (CHARSET|CHARACTER SET) [A-Za-z0-9_]+", "", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
sql = Regex.Replace(sql, " (COLLATE) [A-Za-z0-9_]+", "", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
sql = Regex.Replace(sql, @"ENUM\s*\([^)]+\)", "ENUM", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);

length = 0;
var match = Regex.Match(sql, @"\s*\(\s*(\d+)\s*(?:,\s*\d+\s*)?\)");
Expand Down
8 changes: 8 additions & 0 deletions tests/MySqlConnector.Tests/CachedProcedureTests.cs
Expand Up @@ -121,6 +121,13 @@ public static IEnumerable<object[]> CreateParseableParameters()
}
},
new object[]
{
"IN input enum ('One', 'Two', 'Three')", new object[]
{
new CachedParameter(1, "IN", "input", "ENUM", false, 0),
}
},
new object[]
{
"OUT param DECIMAL(10,5)", new object[]
{
Expand Down Expand Up @@ -190,6 +197,7 @@ param4 INTEGER(3)
[InlineData("VARCHAR(300) COLLATE ascii_general_ci", "VARCHAR", false, 300)]
[InlineData("BINARY(16)", "BINARY", false, 16)]
[InlineData("CHAR(36)", "CHAR", false, 36)]
[InlineData("ENUM('a','b','c')", "ENUM", false, 0)]
public void ParseDataType(string sql, string expectedDataType, bool expectedUnsigned, int expectedLength)
{
var dataType = CachedProcedure.ParseDataType(sql, out var unsigned, out var length);
Expand Down
9 changes: 8 additions & 1 deletion tests/SideBySide/StoredProcedureFixture.cs
Expand Up @@ -124,7 +124,14 @@ RETURNS DECIMAL(10,5)
CREATE PROCEDURE `GetTime`(OUT OutTime TIME)
BEGIN
SET OutTime = CURTIME();
END;");
END;
DROP PROCEDURE IF EXISTS EnumProcedure;
CREATE PROCEDURE EnumProcedure(IN input enum ('One', 'Two', 'Three'))
BEGIN
SELECT input;
END;
");

if (AppConfig.SupportsJson)
{
Expand Down
12 changes: 12 additions & 0 deletions tests/SideBySide/StoredProcedureTests.cs
Expand Up @@ -669,6 +669,18 @@ public void OutputTimeParameter()
Assert.IsType<TimeSpan>(parameter.Value);
}

[Fact]
public void EnumProcedure()
{
using var command = new MySqlCommand("EnumProcedure", m_database.Connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue("@input", "One");
using var reader = command.ExecuteReader();
Assert.True(reader.Read());
Assert.Equal("One", reader.GetString(0));
Assert.False(reader.Read());
}

private static string NormalizeSpaces(string input)
{
input = input.Replace('\r', ' ');
Expand Down

0 comments on commit b0b97a0

Please sign in to comment.