Modified:
branches/1.0/CHANGES
branches/1.0/TestSuite/StoredProcedure.cs
branches/1.0/mysqlclient/Resources.Designer.cs
branches/1.0/mysqlclient/Resources.resx
branches/1.0/mysqlclient/StoredProcedure.cs
Log:
Bug #25625 Crashes when calling with CommandType set to StoredProcedure
We added some code to detect the case where the user does not have access to mysql.proc and we throw an InvalidOperationException with a better message.
Modified: branches/1.0/CHANGES
===================================================================
--- branches/1.0/CHANGES 2007-01-15 16:59:27 UTC (rev 552)
+++ branches/1.0/CHANGES 2007-01-15 21:39:09 UTC (rev 553)
@@ -20,6 +20,7 @@
Bug #25443 ExecuteScalar() hangs when more than one bad result
Bug #24802 Error Handling
Bug #25614 After connection is closed, and opened again UTF-8 characters are not read well
+ Bug #25625 Crashes when calling with CommandType set to StoredProcedure
Other changes
-------------
Modified: branches/1.0/TestSuite/StoredProcedure.cs
===================================================================
--- branches/1.0/TestSuite/StoredProcedure.cs 2007-01-15 16:59:27 UTC (rev 552)
+++ branches/1.0/TestSuite/StoredProcedure.cs 2007-01-15 21:39:09 UTC (rev 553)
@@ -995,5 +995,57 @@
Assert.AreEqual(1, cmd.Parameters.Count);
Assert.AreEqual("?RETURN_VALUE", cmd.Parameters[0].ParameterName);
}
+
+ /// <summary>
+ /// Bug #25625 Crashes when calling with CommandType set to StoredProcedure
+ /// </summary>
+ [Test]
+ public void RunWithoutSelectPrivsThrowException()
+ {
+ suExecSQL(String.Format(
+ "GRANT ALL ON {0}.* to 'testuser'@'%' identified by 'testuser'",
+ databases[0]));
+ suExecSQL(String.Format(
+ "GRANT ALL ON {0}.* to 'testuser'@'localhost' identified by 'testuser'",
+ databases[0]));
+
+ execSQL("DROP PROCEDURE IF EXISTS spTest");
+ execSQL("CREATE PROCEDURE spTest(id int, OUT outid int, INOUT inoutid int) " +
+ "BEGIN SET outid=id+inoutid; SET inoutid=inoutid+id; END");
+
+ string s = GetConnectionStringEx("testuser", "testuser", true);
+ MySqlConnection c = new MySqlConnection(s);
+ c.Open();
+
+ try
+ {
+
+ MySqlCommand cmd = new MySqlCommand("spTest", c);
+ cmd.CommandType = CommandType.StoredProcedure;
+ cmd.Parameters.Add("?id", 2);
+ cmd.Parameters.Add("?outid", MySqlDbType.Int32);
+ cmd.Parameters[1].Direction = ParameterDirection.Output;
+ cmd.Parameters.Add("?inoutid", 4);
+ cmd.Parameters[2].Direction = ParameterDirection.InputOutput;
+ cmd.ExecuteNonQuery();
+
+ Assert.AreEqual(6, cmd.Parameters[1].Value);
+ Assert.AreEqual(6, cmd.Parameters[2].Value);
+ }
+ catch (InvalidOperationException iex)
+ {
+ Assert.IsTrue(iex.Message.StartsWith("Unable to retrieve"));
+ }
+ catch (Exception ex)
+ {
+ Assert.Fail(ex.Message);
+ }
+ finally
+ {
+ if (c != null)
+ c.Close();
+ suExecSQL("DELETE FROM mysql.user WHERE user = 'testuser'");
+ }
+ }
}
}
Modified: branches/1.0/mysqlclient/Resources.Designer.cs
===================================================================
--- branches/1.0/mysqlclient/Resources.Designer.cs 2007-01-15 16:59:27 UTC (rev 552)
+++ branches/1.0/mysqlclient/Resources.Designer.cs 2007-01-15 21:39:09 UTC (rev 553)
@@ -411,7 +411,14 @@
return ResourceManager.GetString("UnableToExecuteSP", resourceCulture);
}
}
-
+
+ internal static string UnableToRetrieveSProcData
+ {
+ get {
+ return ResourceManager.GetString("UnableToRetrieveSProcData", resourceCulture);
+ }
+ }
+
/// <summary>
/// Looks up a localized string similar to Unix sockets are not supported on Windows.
/// </summary>
Modified: branches/1.0/mysqlclient/Resources.resx
===================================================================
--- branches/1.0/mysqlclient/Resources.resx 2007-01-15 16:59:27 UTC (rev 552)
+++ branches/1.0/mysqlclient/Resources.resx 2007-01-15 21:39:09 UTC (rev 553)
@@ -249,4 +249,7 @@
<data name="UnableToConnectToHost" xml:space="preserve">
<value>Unable to connect to any of the specified MySQL hosts.</value>
</data>
+ <data name="UnableToRetrieveSProcData" xml:space="preserve">
+ <value>Unable to retrieve stored procedure metadata. Either grant SELECTprivilege to mysql.proc for this user or use "noAccessToProcedureBody=true" with your connection string.</value>
+ </data>
</root>
\ No newline at end of file
Modified: branches/1.0/mysqlclient/StoredProcedure.cs
===================================================================
--- branches/1.0/mysqlclient/StoredProcedure.cs 2007-01-15 16:59:27 UTC (rev 552)
+++ branches/1.0/mysqlclient/StoredProcedure.cs 2007-01-15 21:39:09 UTC (rev 553)
@@ -25,6 +25,7 @@
using System.Collections;
using System.Globalization;
using System.Diagnostics;
+using System.Data.SqlTypes;
namespace MySql.Data.MySqlClient
{
@@ -95,21 +96,26 @@
throw new MySqlException("Procedure or function '" + spName + "' does not exist.");
MySqlDataReader reader = null;
- try
- {
- MySqlCommand cmd = new MySqlCommand(String.Format("SHOW CREATE " +
- "{0} {1}", type, spName), connection);
- isFunc = type.ToLower(CultureInfo.InvariantCulture) == "function";
- cmd.CommandText = String.Format("SHOW CREATE {0} {1}", type, spName);
- reader = cmd.ExecuteReader();
- reader.Read();
- sql_mode = reader.GetString(1);
- return reader.GetString(2);
- }
- catch (Exception)
- {
- throw;
- }
+ try
+ {
+ MySqlCommand cmd = new MySqlCommand(String.Format("SHOW CREATE " +
+ "{0} {1}", type, spName), connection);
+ isFunc = type.ToLower(CultureInfo.InvariantCulture) == "function";
+ cmd.CommandText = String.Format("SHOW CREATE {0} {1}", type, spName);
+ reader = cmd.ExecuteReader();
+ reader.Read();
+ sql_mode = reader.GetString(1);
+ return reader.GetString(2);
+ }
+ catch (SqlNullValueException snex)
+ {
+ throw new InvalidOperationException(
+ Resources.UnableToRetrieveSProcData, snex);
+ }
+ catch (Exception)
+ {
+ throw;
+ }
finally
{
if (reader != null)
@@ -258,61 +264,67 @@
{
MySqlParameter returnParameter = GetReturnParameter(cmd);
- try
- {
- ArrayList parameters = connection.ProcedureCache.GetProcedure(
- connection, cmd.CommandText);
+ try
+ {
+ ArrayList parameters = connection.ProcedureCache.GetProcedure(
+ connection, cmd.CommandText);
- string sqlStr = String.Empty;
- string setStr = String.Empty;
- outSelect = String.Empty;
+ string sqlStr = String.Empty;
+ string setStr = String.Empty;
+ outSelect = String.Empty;
- foreach (MySqlParameter serverP in parameters)
- {
- if (serverP.Direction == ParameterDirection.ReturnValue)
- continue;
- int index = cmd.Parameters.IndexOf(serverP.ParameterName);
- if (index == -1)
- throw new MySqlException("Parameter '" + serverP.ParameterName + "' is not defined");
+ foreach (MySqlParameter serverP in parameters)
+ {
+ if (serverP.Direction == ParameterDirection.ReturnValue)
+ continue;
+ int index = cmd.Parameters.IndexOf(serverP.ParameterName);
+ if (index == -1)
+ throw new MySqlException("Parameter '" + serverP.ParameterName + "' is not defined");
- MySqlParameter p = cmd.Parameters[index];
- if (!p.TypeHasBeenSet)
- p.MySqlDbType = serverP.MySqlDbType;
- string cleanName = StripParameterName(p.ParameterName);
- string pName = connection.ParameterMarker + cleanName;
- string vName = "@" + hash + cleanName;
- if (p.Direction == ParameterDirection.Input)
- {
- sqlStr += pName + ", ";
- continue;
- }
- else if (p.Direction == ParameterDirection.InputOutput)
- setStr += "set " + vName + "=" + pName + ";";
- sqlStr += vName + ", ";
- outSelect += vName + ", ";
- }
+ MySqlParameter p = cmd.Parameters[index];
+ if (!p.TypeHasBeenSet)
+ p.MySqlDbType = serverP.MySqlDbType;
+ string cleanName = StripParameterName(p.ParameterName);
+ string pName = connection.ParameterMarker + cleanName;
+ string vName = "@" + hash + cleanName;
+ if (p.Direction == ParameterDirection.Input)
+ {
+ sqlStr += pName + ", ";
+ continue;
+ }
+ else if (p.Direction == ParameterDirection.InputOutput)
+ setStr += "set " + vName + "=" + pName + ";";
+ sqlStr += vName + ", ";
+ outSelect += vName + ", ";
+ }
- if (returnParameter == null)
- sqlStr = "call " + cmd.CommandText + "(" + sqlStr;
- else
- {
- string cleanedName = CleanParameterName(returnParameter.ParameterName, true);
- string vname = "@" + hash + cleanedName;
- sqlStr = "set " + vname + "=" + cmd.CommandText + "(" + sqlStr;
- outSelect = vname + outSelect;
- }
+ if (returnParameter == null)
+ sqlStr = "call " + cmd.CommandText + "(" + sqlStr;
+ else
+ {
+ string cleanedName = CleanParameterName(returnParameter.ParameterName, true);
+ string vname = "@" + hash + cleanedName;
+ sqlStr = "set " + vname + "=" + cmd.CommandText + "(" + sqlStr;
+ outSelect = vname + outSelect;
+ }
- sqlStr = sqlStr.TrimEnd(' ', ',');
- outSelect = outSelect.TrimEnd(' ', ',');
- sqlStr += ")";
- if (setStr.Length > 0)
- sqlStr = setStr + sqlStr;
- return sqlStr;
- }
- catch (Exception ex)
- {
- throw new MySqlException("Exception during execution of '" + cmd.CommandText + "': " + ex.Message, ex);
- }
+ sqlStr = sqlStr.TrimEnd(' ', ',');
+ outSelect = outSelect.TrimEnd(' ', ',');
+ sqlStr += ")";
+ if (setStr.Length > 0)
+ sqlStr = setStr + sqlStr;
+ return sqlStr;
+ }
+ catch (InvalidOperationException)
+ {
+ // this exception is thrown when the user doesn't have access to
+ // mysql.proc
+ throw;
+ }
+ catch (Exception ex)
+ {
+ throw new MySqlException("Exception during execution of '" + cmd.CommandText + "': " + ex.Message, ex);
+ }
}
public void UpdateParameters(MySqlParameterCollection parameters)
| Thread |
|---|
| • Connector/NET commit: r553 - in branches/1.0: . TestSuite mysqlclient | rburnett | 15 Jan |