List:Commits« Previous MessageNext Message »
From:Reggie Burnett Date:April 22 2010 3:37pm
Subject:bzr commit into connector-net-trunk branch (reggie.burnett:864)
View as plain text  
#At file:///C:/work/connector-net/trunk/ based on revid:reggie.burnett@stripped

  864 Reggie Burnett	2010-04-22 [merge]
      merged

    modified:
      CHANGES
      MySql.Data/Provider/Source/CommandBuilder.cs
      MySql.Data/Provider/Source/ProcedureCache.cs
      MySql.Data/Provider/Source/StoredProcedure.cs
      MySql.Data/Tests/Source/StoredProcedure.cs
=== modified file 'CHANGES'
=== modified file 'CHANGES'
--- a/CHANGES	2010-04-21 17:47:38 +0000
+++ b/CHANGES	2010-04-22 15:36:59 +0000
@@ -16,7 +16,8 @@
 - SessionProvider : Avoid SQLNullValueException if lockId returned by select is 
   NULL (bug#52175)
 - changed how we respond when the user selects 'functions return string=true'.  Now we no longer force the type to var string but just let the underlying type come through but we strip the binary flag (bug #52187)
-
+- improved our procedure caching so that if you drop and recreate a proc with a different number of parameters
+  it will find the new proc as long as your are actually using the right number of parameters (bug #52562)
 
 Version 6.3.1
 - fixed bug where giving a connection string option like (option=) and then trying to read

=== modified file 'MySql.Data/Provider/Source/CommandBuilder.cs'
--- a/MySql.Data/Provider/Source/CommandBuilder.cs	2009-11-25 15:16:10 +0000
+++ b/MySql.Data/Provider/Source/CommandBuilder.cs	2010-04-22 15:36:59 +0000
@@ -80,7 +80,7 @@
             string spName = command.CommandText;
             if (spName.IndexOf(".") == -1)
                 spName = command.Connection.Database + "." + spName;
-            DataSet ds = command.Connection.ProcedureCache.GetProcedure(command.Connection, spName);
+            DataSet ds = command.Connection.ProcedureCache.GetProcedure(command.Connection, spName, null);
             if (!ds.Tables.Contains("Procedure Parameters"))
                 throw new MySqlException(Resources.UnableToDeriveParameters);
 

=== modified file 'MySql.Data/Provider/Source/ProcedureCache.cs'
--- a/MySql.Data/Provider/Source/ProcedureCache.cs	2010-04-15 23:36:52 +0000
+++ b/MySql.Data/Provider/Source/ProcedureCache.cs	2010-04-22 15:35:07 +0000
@@ -24,6 +24,8 @@
 using System.Collections.Generic;
 using MySql.Data.MySqlClient.Properties;
 using System.Diagnostics;
+using System.Text;
+using System.Globalization;
 
 namespace MySql.Data.MySqlClient
 {
@@ -40,14 +42,18 @@
             procHash = new Hashtable(maxSize);
         }
 
-        public DataSet GetProcedure(MySqlConnection conn, string spName)
+        public DataSet GetProcedure(MySqlConnection conn, string spName, string cacheKey)
         {
-            int hash = spName.GetHashCode();
-
             DataSet ds = null;
-            lock (procHash.SyncRoot)
+
+            if (cacheKey != null)
             {
-                ds = (DataSet)procHash[hash];
+                int hash = cacheKey.GetHashCode();
+
+                lock (procHash.SyncRoot)
+                {
+                    ds = (DataSet)procHash[hash];
+                }
             }
             if (ds == null)
             {
@@ -71,12 +77,36 @@
             return ds;
         }
 
+        internal string GetCacheKey(string spName, DataSet procData)
+        {
+            string retValue = String.Empty;
+            StringBuilder key = new StringBuilder(spName);
+            key.Append("(");
+            string delimiter = "";
+            if (procData.Tables.Contains("Procedure Parameters"))
+            {
+                foreach (DataRow row in procData.Tables["Procedure Parameters"].Rows)
+                {
+                    if (row["ORDINAL_POSITION"].Equals(0))
+                        retValue = "?=";
+                    else
+                    {
+                        key.AppendFormat(CultureInfo.InvariantCulture, "{0}?", delimiter);
+                        delimiter = ",";
+                    }
+                }
+            }
+            key.Append(")");
+            return retValue + key.ToString();
+        }
+
         private DataSet AddNew(MySqlConnection connection, string spName)
         {
             DataSet procData = GetProcData(connection, spName);
             if (maxSize > 0)
             {
-                int hash = spName.GetHashCode();
+                string cacheKey = GetCacheKey(spName, procData);
+                int hash = cacheKey.GetHashCode();
                 lock (procHash.SyncRoot)
                 {
                     if (procHash.Keys.Count >= maxSize)

=== modified file 'MySql.Data/Provider/Source/StoredProcedure.cs'
--- a/MySql.Data/Provider/Source/StoredProcedure.cs	2010-04-10 01:40:44 +0000
+++ b/MySql.Data/Provider/Source/StoredProcedure.cs	2010-04-22 15:36:59 +0000
@@ -58,11 +58,30 @@
             get { return resolvedCommandText; }
         }
 
+        internal string GetCacheKey(string spName)
+        {
+            string retValue = String.Empty;
+            StringBuilder key = new StringBuilder(spName);
+            key.Append("(");
+            string delimiter = "";
+            foreach (MySqlParameter p in command.Parameters)
+            {
+                if (p.Direction == ParameterDirection.ReturnValue)
+                    retValue = "?=";
+                else
+                {
+                    key.AppendFormat(CultureInfo.InvariantCulture, "{0}?", delimiter);
+                    delimiter = ",";
+                }
+            }
+            key.Append(")");
+            return retValue + key.ToString();
+        }
+
         private DataSet GetParameters(string procName)
         {
-            // if we can use mysql.proc, then do so
-            //if (Connection.Settings.UseProcedureBodies)
-            DataSet ds = Connection.ProcedureCache.GetProcedure(Connection, procName);
+            string procCacheKey = GetCacheKey(procName);
+            DataSet ds = Connection.ProcedureCache.GetProcedure(Connection, procName, procCacheKey);
 
             if(ds.Tables.Count == 2)
             {

=== modified file 'MySql.Data/Tests/Source/StoredProcedure.cs'
--- a/MySql.Data/Tests/Source/StoredProcedure.cs	2010-04-21 17:38:12 +0000
+++ b/MySql.Data/Tests/Source/StoredProcedure.cs	2010-04-22 15:35:07 +0000
@@ -1288,5 +1288,31 @@
             MySqlCommandBuilder.DeriveParameters(cmd);
             Assert.AreEqual(2, cmd.Parameters.Count);
         }
+
+        /// <summary>
+        /// Bug #52562 Sometimes we need to reload cached function parameters 
+        /// </summary>
+        [Test]
+        public void ProcedureCacheMiss()
+        {
+            execSQL("CREATE PROCEDURE spTest(id INT) BEGIN SELECT 1; END");
+
+            string connStr = GetConnectionString(true) + ";procedure cache size=25";
+            using (MySqlConnection c = new MySqlConnection(connStr))
+            {
+                c.Open();
+                MySqlCommand cmd = new MySqlCommand("spTest", c);
+                cmd.Parameters.AddWithValue("@id", 1);
+                cmd.CommandType = CommandType.StoredProcedure;
+                cmd.ExecuteScalar();
+
+                execSQL("DROP PROCEDURE spTest");
+                execSQL("CREATE PROCEDURE spTest(id INT, id2 INT, id3 INT) BEGIN SELECT 1; END");
+
+                cmd.Parameters.AddWithValue("@id2", 2);
+                cmd.Parameters.AddWithValue("@id3", 3);
+                cmd.ExecuteScalar();
+            }
+        }
     }
 }


Attachment: [text/bzr-bundle]
Thread
bzr commit into connector-net-trunk branch (reggie.burnett:864)Reggie Burnett22 Apr