From: Date: March 19 2007 11:34pm Subject: Connector/NET commit: r638 - in branches/5.0: . Driver/Source TestSuite List-Archive: http://lists.mysql.com/commits/22314 X-Bug: 27187 Message-Id: <200703192234.l2JMYWOZ032320@bk-internal.mysql.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modified: branches/5.0/CHANGES branches/5.0/Driver/Source/parameter_collection.cs branches/5.0/TestSuite/ParameterTests.cs Log: Bug #27187 cmd.Parameters.RemoveAt("Id") will cause an error if the last item is requested Refactored the parameter collection code to update the hashes when a parameter is removed or inserted at a specific location. Modified: branches/5.0/CHANGES =================================================================== --- branches/5.0/CHANGES 2007-03-19 18:09:37 UTC (rev 637) +++ branches/5.0/CHANGES 2007-03-19 22:34:31 UTC (rev 638) @@ -4,6 +4,7 @@ ---------- Bug #27135 MySqlParameterCollection and parameters added with Insert Method Bug #27253 Installer : Company info is different + Bug #27187 cmd.Parameters.RemoveAt("Id") will cause an error if the last item is requested Version 5.0.5 3/5/2007 Modified: branches/5.0/Driver/Source/parameter_collection.cs =================================================================== --- branches/5.0/Driver/Source/parameter_collection.cs 2007-03-19 18:09:37 UTC (rev 637) +++ branches/5.0/Driver/Source/parameter_collection.cs 2007-03-19 22:34:31 UTC (rev 638) @@ -36,20 +36,17 @@ #endif public sealed class MySqlParameterCollection : DbParameterCollection { - private ArrayList items = new ArrayList(); + private ArrayList items = new ArrayList(); + private Hashtable indexHash; private char paramMarker = '?'; - private Hashtable ciHash; - private Hashtable hash; - private int returnParameterIndex; internal MySqlParameterCollection() { - hash = new Hashtable(); #if NET20 - ciHash = new Hashtable(StringComparer.CurrentCultureIgnoreCase); + indexHash = new Hashtable(StringComparer.CurrentCultureIgnoreCase); #else - ciHash = new Hashtable(new CaseInsensitiveHashCodeProvider(), - new CaseInsensitiveComparer()); + indexHash = new Hashtable(new CaseInsensitiveHashCodeProvider(), + new CaseInsensitiveComparer()); #endif Clear(); } @@ -93,18 +90,6 @@ return InternalAdd(value, -1); } - private MySqlParameter AddReturnParameter(MySqlParameter value) - { - if (returnParameterIndex != -1) - { - items[returnParameterIndex] = value; - return value; - } - - returnParameterIndex = items.Add(value); - return value; - } - /// /// Adds a to the given the specified parameter name and value. /// @@ -174,7 +159,7 @@ void CheckIndex(int index) { - if (index < 0 || index >= items.Count) + if (index < 0 || index >= Count) throw new IndexOutOfRangeException("Parameter index is out of range."); } @@ -194,7 +179,7 @@ { string newParameterName = parameterName.Substring(1); index = IndexOf(newParameterName); - if (index != -1) + if (index == -1) return (DbParameter)items[index]; } throw new ArgumentException("Parameter '" + parameterName + "' not found in the collection."); @@ -220,23 +205,10 @@ { CheckIndex(index); MySqlParameter p = (MySqlParameter)items[index]; - if (p.Direction == ParameterDirection.ReturnValue) - returnParameterIndex = -1; - else - { - hash.Remove(p.ParameterName); - ciHash.Remove(p.ParameterName); - } - + + indexHash.Remove(p.ParameterName); items[index] = (MySqlParameter)value; - p = (MySqlParameter)value; - if (p.Direction == ParameterDirection.ReturnValue) - returnParameterIndex = index; - else - { - hash.Add(p.ParameterName, index); - ciHash.Add(p.ParameterName, index); - } + indexHash.Add(value.ParameterName, index); } /// @@ -266,9 +238,7 @@ foreach (MySqlParameter p in items) p.Collection = null; items.Clear(); - hash.Clear(); - ciHash.Clear(); - returnParameterIndex = -1; + indexHash.Clear(); } /// @@ -326,21 +296,10 @@ /// The zero-based location of the in the collection. public override int IndexOf(string parameterName) { - object o = hash[parameterName]; - if (o != null) - return (int)o; - - o = ciHash[parameterName]; - if (o != null) - return (int)o; - - if (returnParameterIndex != -1) - { - MySqlParameter p = (MySqlParameter)items[returnParameterIndex]; - if (String.Compare(parameterName, p.ParameterName, true) == 0) - return returnParameterIndex; - } - return -1; + object o = indexHash[parameterName]; + if (o == null) + return -1; + return (int)o; } /// @@ -399,14 +358,12 @@ /// public override void Remove(object value) { - items.Remove(value); - MySqlParameter p = (value as MySqlParameter); - hash.Remove(p.ParameterName); - ciHash.Remove(p.ParameterName); p.Collection = null; - if (p.Direction == ParameterDirection.ReturnValue) - returnParameterIndex = -1; + int index = IndexOf(p); + items.Remove(p); + indexHash.Remove(p.ParameterName); + AdjustHash(index, false); } /// @@ -443,13 +400,9 @@ internal void ParameterNameChanged(MySqlParameter p, string oldName, string newName) { - if (p.Direction == ParameterDirection.ReturnValue) - return; int index = IndexOf(oldName); - hash.Remove(oldName); - ciHash.Remove(oldName); - hash.Add(newName, index); - ciHash.Add(newName, index); + indexHash.Remove(oldName); + indexHash.Add(newName, index); } private MySqlParameter InternalAdd(MySqlParameter value, int index) @@ -457,34 +410,44 @@ if (value == null) throw new ArgumentException("The MySqlParameterCollection only accepts non-null MySqlParameter type objects.", "value"); - if (value.Direction == ParameterDirection.ReturnValue) - return AddReturnParameter(value); - - string inComingName = value.ParameterName.ToLower(); + // make sure we don't already have a parameter with this name + string inComingName = value.ParameterName; + if (indexHash.ContainsKey(inComingName)) + throw new MySqlException( + String.Format(Resources.ParameterAlreadyDefined, value.ParameterName)); if (inComingName[0] == paramMarker) inComingName = inComingName.Substring(1, inComingName.Length - 1); + if (indexHash.ContainsKey(inComingName)) + throw new MySqlException( + String.Format(Resources.ParameterAlreadyDefined, value.ParameterName)); - for (int i = 0; i < items.Count; i++) - { - MySqlParameter p = (MySqlParameter)items[i]; - string name = p.ParameterName.ToLower(); - if (name[0] == paramMarker) - name = name.Substring(1, name.Length - 1); - if (name == inComingName) - { - throw new MySqlException( - String.Format(Resources.ParameterAlreadyDefined, value.ParameterName)); - } - } - if (index == -1) + { index = items.Add(value); + indexHash.Add(value.ParameterName, index); + } else + { items.Insert(index, value); - hash.Add(value.ParameterName, index); - ciHash.Add(value.ParameterName, index); + AdjustHash(index, true); + indexHash.Add(value.ParameterName, index); + } + value.Collection = this; return value; } + + private void AdjustHash(int keyIndex, bool addEntry) + { + for (int i=0; i < Count; i++) + { + MySqlParameter p = (MySqlParameter)items[i]; + if (!indexHash.ContainsKey(p.ParameterName)) + return; + int index = (int)indexHash[p.ParameterName]; + if (index < keyIndex) continue; + indexHash[p.ParameterName] = addEntry ? ++index : --index; + } + } } } Modified: branches/5.0/TestSuite/ParameterTests.cs =================================================================== --- branches/5.0/TestSuite/ParameterTests.cs 2007-03-19 18:09:37 UTC (rev 637) +++ branches/5.0/TestSuite/ParameterTests.cs 2007-03-19 22:34:31 UTC (rev 638) @@ -490,5 +490,23 @@ MySqlParameter p = cmd.Parameters["?id"]; Assert.AreEqual("?id", p.ParameterName); } + + /// + /// Bug #27187 cmd.Parameters.RemoveAt("Id") will cause an error if the last item is requested + /// + [Test] + public void FindParameterAfterRemoval() + { + MySqlCommand cmd = new MySqlCommand(); + + cmd.Parameters.Add("?id1", MySqlDbType.Int32); + cmd.Parameters.Add("?id2", MySqlDbType.Int32); + cmd.Parameters.Add("?id3", MySqlDbType.Int32); + cmd.Parameters.Add("?id4", MySqlDbType.Int32); + cmd.Parameters.Add("?id5", MySqlDbType.Int32); + cmd.Parameters.Add("?id6", MySqlDbType.Int32); + cmd.Parameters.RemoveAt("?id1"); + MySqlParameter p = cmd.Parameters["?id6"]; + } } }