New test.
[mono.git] / mcs / class / Mono.Data.SqliteClient / Mono.Data.SqliteClient / SqliteParameterCollection.cs
index e778c1e5116db6ecaff995d2e6d069e310963a8a..928ee232aa1777afd150fa11533db95b8e507a3b 100644 (file)
@@ -4,8 +4,11 @@
 // Represents a collection of parameters relevant to a SqliteCommand as well as 
 // their respective mappings to columns in a DataSet.
 //
-// Author(s): Vladimir Vukicevic  <vladimir@pobox.com>
-//            Everaldo Canuto  <everaldo_canuto@yahoo.com.br>
+//Author(s):           Vladimir Vukicevic  <vladimir@pobox.com>
+//                     Everaldo Canuto  <everaldo_canuto@yahoo.com.br>
+//                     Chris Turchin <chris@turchin.net>
+//                     Jeroen Zwartepoorte <jeroen@xs4all.nl>
+//                     Thomas Zoechling <thomas.zoechling@gmx.at>
 //
 // Copyright (C) 2002  Vladimir Vukicevic
 //
@@ -46,85 +49,157 @@ namespace Mono.Data.SqliteClient
                #endregion
 
                #region Private Methods
-               
+
                private void CheckSqliteParam (object value)
                {
                        if (!(value is SqliteParameter))
-                               throw new InvalidCastException("Can only use SqliteParameter objects");
-               }
+                               throw new InvalidCastException ("Can only use SqliteParameter objects");
+                       SqliteParameter sqlp = value as SqliteParameter;
+                       if (sqlp.ParameterName == null || sqlp.ParameterName.Length == 0)
+                               sqlp.ParameterName = this.GenerateParameterName();
+                 }
 
                private void RecreateNamedHash ()
                {
-                       for (int i = 0; i < numeric_param_list.Count; i++) {
+                       for (int i = 0; i < numeric_param_list.Count; i++) 
+                       {
                                named_param_hash[((SqliteParameter) numeric_param_list[i]).ParameterName] = i;
                        }
                }
-               
+
+               //FIXME: if the user is calling Insert at various locations with unnamed parameters, this is not going to work....
+               private string GenerateParameterName()
+               {
+                       int             index   = this.Count + 1;
+                       string  name    = String.Empty;
+
+                       while (index > 0)
+                       {
+                               name = ":" + index.ToString();
+                                       if (this.IndexOf(name) == -1)
+                                       index = -1;
+                               else
+                               index++;
+                       }
+                       return name;
+               }
+
                #endregion
 
                #region Properties
                
                object IList.this[int index] {
-                       get {
+                       get 
+                       {
                                return this[index];
                        }
-                       set {
+                       set 
+                       {
                                CheckSqliteParam (value);
                                this[index] = (SqliteParameter) value;
                        }
                }
                
                object IDataParameterCollection.this[string parameterName] {
-                       get {
+                       get 
+                       {
                                return this[parameterName];
                        }
-                       set {
+                       set 
+                       {
                                CheckSqliteParam (value);
                                this[parameterName] = (SqliteParameter) value;
                        }
                }
                
-               public SqliteParameter this[string parameterName] {
-                       get {
-                               return this[(int) named_param_hash[parameterName]];
+               private bool isPrefixed (string parameterName)
+               {
+                       return parameterName.Length > 1 && (parameterName[0] == ':' || parameterName[0] == '$');
+               }
+               
+               public SqliteParameter this[string parameterName] 
+               {
+                       get 
+                       {
+                               if (this.Contains(parameterName))
+                                       return this[(int) named_param_hash[parameterName]];
+                               else if (isPrefixed(parameterName) && this.Contains(parameterName.Substring(1)))
+                                       return this[(int) named_param_hash[parameterName.Substring(1)]];
+                               else
+                                       throw new IndexOutOfRangeException("The specified name does not exist: " + parameterName);
                        }
-                       set {
-                               if (this.Contains (parameterName))
+                       set
+                       {
+                               if (this.Contains(parameterName))
                                        numeric_param_list[(int) named_param_hash[parameterName]] = value;
-                               else          // uhm, do we add it if it doesn't exist? what does ms do?
-                                       Add (value);
+                               else if (parameterName.Length > 1 && this.Contains(parameterName.Substring(1)))
+                                       numeric_param_list[(int) named_param_hash[parameterName.Substring(1)]] = value;
+                               else
+                                       throw new IndexOutOfRangeException("The specified name does not exist: " + parameterName);
                        }
                }
-               
-               public SqliteParameter this[int parameterIndex] {
-                       get {
-                               return (SqliteParameter) numeric_param_list[parameterIndex];
+
+               public SqliteParameter this[int parameterIndex]
+               {
+                       get
+                       {
+                               if (this.Count >= parameterIndex+1)
+                                       return (SqliteParameter) numeric_param_list[parameterIndex];
+                               else          
+                                       throw new IndexOutOfRangeException("The specified parameter index does not exist: " + parameterIndex.ToString());
                        }
-                       set {
-                               numeric_param_list[parameterIndex] = value;
+                       set
+                       {
+                               if (this.Count >= parameterIndex+1)
+                                       numeric_param_list[parameterIndex] = value;
+                               else          
+                                       throw new IndexOutOfRangeException("The specified parameter index does not exist: " + parameterIndex.ToString());
                        }
                }
-               
-               public int Count {
-                       get { return numeric_param_list.Count; }
+
+
+               public int Count 
+               {
+                       get
+                       {
+                               return this.numeric_param_list.Count;
+                       }
                }
-               
-               public bool IsFixedSize {
-                       get { return false; }
+
+               bool IList.IsFixedSize
+               {
+                       get
+                       {
+                               return this.numeric_param_list.IsFixedSize;
+                       }
                }
-               
-               public bool IsReadOnly {
-                       get { return false; }
+
+               bool IList.IsReadOnly
+               {
+                       get
+                       {
+                               return this.numeric_param_list.IsReadOnly;
+                       }
                }
-               
-               public bool IsSynchronized {
-                       get { return false; }
+
+
+               bool ICollection.IsSynchronized 
+               {
+                       get
+                       {
+                               return this.numeric_param_list.IsSynchronized;
+                       }
                }
                
-               public object SyncRoot {
-                       get { return null; }
+
+               object ICollection.SyncRoot 
+               {
+                       get
+                       {
+                               return this.numeric_param_list.SyncRoot;
+                       }
                }
-               
+
                #endregion
 
                #region Public Methods
@@ -132,15 +207,13 @@ namespace Mono.Data.SqliteClient
                public int Add (object value)
                {
                        CheckSqliteParam (value);
-                       SqliteParameter sqlp = (SqliteParameter) value;
+                       SqliteParameter sqlp = value as SqliteParameter;
                        if (named_param_hash.Contains (sqlp.ParameterName))
-                               throw new DuplicateNameException ("Parameter collection already contains given value.");
-                       
-                       named_param_hash[value] = numeric_param_list.Add (value);
-                       
-                       return (int) named_param_hash[value];
+                               throw new DuplicateNameException ("Parameter collection already contains the a SqliteParameter with the given ParameterName.");
+                       named_param_hash[sqlp.ParameterName] = numeric_param_list.Add(value);
+                               return (int) named_param_hash[sqlp.ParameterName];
                }
-               
+
                public SqliteParameter Add (SqliteParameter param)
                {
                        Add ((object)param);
@@ -165,7 +238,7 @@ namespace Mono.Data.SqliteClient
                
                public void CopyTo (Array array, int index)
                {
-                       throw new NotImplementedException ();
+                       this.numeric_param_list.CopyTo(array, index);
                }
                
                bool IList.Contains (object value)
@@ -185,7 +258,7 @@ namespace Mono.Data.SqliteClient
                
                public IEnumerator GetEnumerator ()
                {
-                       throw new NotImplementedException ();
+                       return this.numeric_param_list.GetEnumerator();
                }
                
                int IList.IndexOf (object param)
@@ -195,7 +268,10 @@ namespace Mono.Data.SqliteClient
                
                public int IndexOf (string parameterName)
                {
-                       return (int) named_param_hash[parameterName];
+                       if (named_param_hash.Contains(parameterName))
+                               return (int) named_param_hash[parameterName];
+                       else
+                               return -1;
                }
                
                public int IndexOf (SqliteParameter param)
@@ -206,7 +282,8 @@ namespace Mono.Data.SqliteClient
                public void Insert (int index, object value)
                {
                        CheckSqliteParam (value);
-                       if (numeric_param_list.Count == index) {
+                       if (numeric_param_list.Count == index) 
+                       {
                                Add (value);
                                return;
                        }
@@ -245,4 +322,3 @@ namespace Mono.Data.SqliteClient
                #endregion
        }
 }
-