List:Commits« Previous MessageNext Message »
From:Vladislav Vaintroub Date:August 11 2009 12:59am
Subject:bzr commit into connector-net-6.0 branch (vvaintroub:741) Bug#36027
View as plain text  
#At file:///H:/connector_net/6.0/ based on revid:vvaintroub@stripped

  741 Vladislav Vaintroub	2009-08-11
      Bug #36027 Memory leak when using output parameter in stored procedure
      
      The reason for the memory leak was that we Connector/Net created a session
      variable with unique name for each stored procedure call.  Each session variable takes 
      some memoryon the server, hence the leak.
      
      The fix is not using unique names for stored procedure, instead we give all output 
      variables a common prefix.
      
       It would be nice to get rid of the prefix too, however
      1 ) there is a complicated logic inside resolve/bind that makes it not possible at the
       moment.
      2) stored procedure parameter names could in theory might collide with user 
      variables names.

    modified:
      MySql.Data/Provider/Source/Statement.cs
      MySql.Data/Provider/Source/StoredProcedure.cs
      MySql.Data/Provider/Source/command.cs
=== modified file 'MySql.Data/Provider/Source/Statement.cs'
--- a/MySql.Data/Provider/Source/Statement.cs	2009-04-21 18:02:13 +0000
+++ b/MySql.Data/Provider/Source/Statement.cs	2009-08-11 00:59:23 +0000
@@ -201,7 +201,7 @@ namespace MySql.Data.MySqlClient
         {
             if (Connection.Settings.AllowUserVariables)
                 return true;
-            if (command.parameterHash != null && parameterName.StartsWith("@" + command.parameterHash))
+            if (parameterName.StartsWith("@" +StoredProcedure.ParameterPrefix))
                 return true;
             if (parameterName.Length > 1 &&
                 (parameterName[1] == '`' || parameterName[1] == '\''))

=== modified file 'MySql.Data/Provider/Source/StoredProcedure.cs'
--- a/MySql.Data/Provider/Source/StoredProcedure.cs	2009-07-30 01:47:48 +0000
+++ b/MySql.Data/Provider/Source/StoredProcedure.cs	2009-08-11 00:59:23 +0000
@@ -36,12 +36,12 @@ namespace MySql.Data.MySqlClient
         private DataTable parametersTable;
         private string resolvedCommandText;
 
+        // Prefix used for to generate inout or output parameters names
+        internal const string ParameterPrefix = "_cnet_param_";
+
         public StoredProcedure(MySqlCommand cmd, string text)
             : base(cmd, text)
         {
-            // set our parameter hash to something very unique
-            uint code = (uint) DateTime.Now.GetHashCode();
-            cmd.parameterHash = code.ToString();
         }
 
         private string GetReturnParameter()
@@ -51,7 +51,7 @@ namespace MySql.Data.MySqlClient
                     if (p.Direction == ParameterDirection.ReturnValue)
                     {
                         string pName = p.ParameterName.Substring(1);
-                        return command.parameterHash + pName;
+                        return ParameterPrefix + pName;
                     }
             return null;
         }
@@ -136,7 +136,6 @@ namespace MySql.Data.MySqlClient
             // first retrieve the procedure definition from our
             // procedure cache
             string spName = commandText;
-            string parameterHash = command.parameterHash;
             if (spName.IndexOf(".") == -1 && !String.IsNullOrEmpty(Connection.Database))
                 spName = Connection.Database + "." + spName;
             spName = FixProcedureName(spName);
@@ -174,7 +173,7 @@ namespace MySql.Data.MySqlClient
                 string basePName = pName;
                 if (pName.StartsWith("@") || pName.StartsWith("?"))
                     basePName = pName.Substring(1);
-                string vName = string.Format("@{0}{1}", parameterHash, basePName);
+                string vName = string.Format("@{0}{1}", ParameterPrefix, basePName);
 
                 // if our parameter doesn't have a leading marker then we need to give it one
                 pName = p.ParameterName;
@@ -207,7 +206,7 @@ namespace MySql.Data.MySqlClient
             else
             {
                 if (retParm == null)
-                    retParm = parameterHash + "dummy";
+                    retParm = ParameterPrefix + "dummy";
                 else
                     outSelect = String.Format("@{0}", retParm);
                 sqlCmd = String.Format("SET @{0}={1}({2})", retParm, spName, sqlCmd);
@@ -227,11 +226,7 @@ namespace MySql.Data.MySqlClient
 
             MySqlCommand cmd = new MySqlCommand("SELECT " + outSelect, Connection);
 
-            // set the parameter hash for this new command to our current parameter hash
-            // so the inout and out parameters won't cause a problem
-            string parameterHash = command.parameterHash;
-            cmd.parameterHash = parameterHash;
-
+            // Read output parameters
             using (MySqlDataReader reader = cmd.ExecuteReader())
             {
                 // since MySQL likes to return user variables as strings
@@ -241,7 +236,7 @@ namespace MySql.Data.MySqlClient
                 for (int i = 0; i < reader.FieldCount; i++)
                 {
                     string fieldName = reader.GetName(i);
-                    fieldName = fieldName.Remove(0, parameterHash.Length + 1);
+                    fieldName = fieldName.Remove(0, ParameterPrefix.Length + 1);
                     MySqlParameter parameter = Parameters.GetParameterFlexible(fieldName, true);
                     reader.values[i] = MySqlField.GetIMySqlValue(parameter.MySqlDbType);
                 }
@@ -251,7 +246,7 @@ namespace MySql.Data.MySqlClient
                     for (int i = 0; i < reader.FieldCount; i++)
                     {
                         string fieldName = reader.GetName(i);
-                        fieldName = fieldName.Remove(0, parameterHash.Length + 1);
+                        fieldName = fieldName.Remove(0, ParameterPrefix.Length + 1);
                         MySqlParameter parameter = Parameters.GetParameterFlexible(fieldName, true);
                         parameter.Value = reader.GetValue(i);
                     }

=== modified file 'MySql.Data/Provider/Source/command.cs'
--- a/MySql.Data/Provider/Source/command.cs	2009-07-31 22:36:40 +0000
+++ b/MySql.Data/Provider/Source/command.cs	2009-08-11 00:59:23 +0000
@@ -58,7 +58,6 @@ namespace MySql.Data.MySqlClient
         private bool resetSqlSelect;
         List<MySqlCommand> batch;
         private string batchableCommandText;
-        internal string parameterHash;
         internal bool EFCrap;
 
 		/// <include file='docs/mysqlcommand.xml' path='docs/ctor1/*'/>


Attachment: [text/bzr-bundle] bzr/vvaintroub@mysql.com-20090811005923-n8mxfxq02qep7v70.bundle
Thread
bzr commit into connector-net-6.0 branch (vvaintroub:741) Bug#36027Vladislav Vaintroub11 Aug