Sqlite migration. Stage 2
[mono.git] / mcs / class / Mono.Data.Sqlite / Mono.Data.Sqlite_2.0 / SQLiteParameterCollection.cs
1 //
2 // Mono.Data.Sqlite.SQLiteParameterCollection.cs
3 //
4 // Author(s):
5 //   Robert Simpson (robert@blackcastlesoft.com)
6 //
7 // Adapted and modified for the Mono Project by
8 //   Marek Habersack (grendello@gmail.com)
9 //
10 //
11 // Copyright (C) 2006 Novell, Inc (http://www.novell.com)
12 // Copyright (C) 2007 Marek Habersack
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 // 
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 // 
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 //
33
34 /********************************************************
35  * ADO.NET 2.0 Data Provider for Sqlite Version 3.X
36  * Written by Robert Simpson (robert@blackcastlesoft.com)
37  * 
38  * Released to the public domain, use at your own risk!
39  ********************************************************/
40 #if NET_2_0
41 namespace Mono.Data.Sqlite
42 {
43   using System;
44   using System.Data;
45   using System.Data.Common;
46   using System.Collections.Generic;
47   using System.Globalization;
48   using System.ComponentModel;
49   using System.Reflection;
50
51   /// <summary>
52   /// Sqlite implementation of DbParameterCollection.
53   /// </summary>
54 #if !PLATFORM_COMPACTFRAMEWORK
55   [Editor("Microsoft.VSDesigner.Data.Design.DBParametersEditor, Microsoft.VSDesigner, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Drawing.Design.UITypeEditor, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"), ListBindable(false)]
56 #endif
57   public class SqliteParameterCollection : DbParameterCollection
58   {
59     /// <summary>
60     /// The underlying command to which this collection belongs
61     /// </summary>
62     private SqliteCommand         _command;
63     /// <summary>
64     /// The internal array of parameters in this collection
65     /// </summary>
66     private List<SqliteParameter> _parameterList;
67     /// <summary>
68     /// Determines whether or not all parameters have been bound to their statement(s)
69     /// </summary>
70     private bool                  _unboundFlag;
71
72     /// <summary>
73     /// Initializes the collection
74     /// </summary>
75     /// <param name="cmd">The command to which the collection belongs</param>
76     internal SqliteParameterCollection(SqliteCommand cmd)
77     {
78       _command = cmd;
79       _parameterList = new List<SqliteParameter>();
80       _unboundFlag = true;
81     }
82
83     /// <summary>
84     /// Returns true
85     /// </summary>
86     public override bool IsSynchronized
87     {
88       get { return true; }
89     }
90
91     /// <summary>
92     /// Returns false
93     /// </summary>
94     public override bool IsFixedSize
95     {
96       get { return false; }
97     }
98
99     /// <summary>
100     /// Returns false
101     /// </summary>
102     public override bool IsReadOnly
103     {
104       get { return false; }
105     }
106
107     /// <summary>
108     /// Returns null
109     /// </summary>
110     public override object SyncRoot
111     {
112       get { return null; }
113     }
114
115     /// <summary>
116     /// Retrieves an enumerator for the collection
117     /// </summary>
118     /// <returns>An enumerator for the underlying array</returns>
119     public override System.Collections.IEnumerator GetEnumerator()
120     {
121       return _parameterList.GetEnumerator();
122     }
123
124     /// <summary>
125     /// Adds a parameter to the collection
126     /// </summary>
127     /// <param name="parameterName">The parameter name</param>
128     /// <param name="parameterType">The data type</param>
129     /// <param name="parameterSize">The size of the value</param>
130     /// <param name="sourceColumn">The source column</param>
131     /// <returns>A SqliteParameter object</returns>
132     public SqliteParameter Add(string parameterName, DbType parameterType, int parameterSize, string sourceColumn)
133     {
134       SqliteParameter param = new SqliteParameter(parameterName, parameterType, parameterSize, sourceColumn);
135       Add(param);
136
137       return param;
138     }
139
140     /// <summary>
141     /// Adds a parameter to the collection
142     /// </summary>
143     /// <param name="parameterName">The parameter name</param>
144     /// <param name="parameterType">The data type</param>
145     /// <param name="parameterSize">The size of the value</param>
146     /// <returns>A SqliteParameter object</returns>
147     public SqliteParameter Add(string parameterName, DbType parameterType, int parameterSize)
148     {
149       SqliteParameter param = new SqliteParameter(parameterName, parameterType, parameterSize);
150       Add(param);
151
152       return param;
153     }
154
155     /// <summary>
156     /// Adds a parameter to the collection
157     /// </summary>
158     /// <param name="parameterName">The parameter name</param>
159     /// <param name="parameterType">The data type</param>
160     /// <returns>A SqliteParameter object</returns>
161     public SqliteParameter Add(string parameterName, DbType parameterType)
162     {
163       SqliteParameter param = new SqliteParameter(parameterName, parameterType);
164       Add(param);
165
166       return param;
167     }
168
169     /// <summary>
170     /// Adds a parameter to the collection
171     /// </summary>
172     /// <param name="parameter">The parameter to add</param>
173     /// <returns>A zero-based index of where the parameter is located in the array</returns>
174     public int Add(SqliteParameter parameter)
175     {
176       int n = -1;
177
178       if (parameter.ParameterName != null)
179       {
180         n = IndexOf(parameter.ParameterName);
181       }
182
183       if (n == -1)
184       {
185         n = _parameterList.Count;
186         _parameterList.Add((SqliteParameter)parameter);
187       }
188
189       SetParameter(n, parameter);
190
191       return n;
192     }
193
194     /// <summary>
195     /// Adds a parameter to the collection
196     /// </summary>
197     /// <param name="value">The parameter to add</param>
198     /// <returns>A zero-based index of where the parameter is located in the array</returns>
199 #if !PLATFORM_COMPACTFRAMEWORK
200     [EditorBrowsable(EditorBrowsableState.Never)]
201 #endif
202     public override int Add(object value)
203     {
204       return Add((SqliteParameter)value);
205     }
206
207     /// <summary>
208     /// Adds a named/unnamed parameter and its value to the parameter collection.
209     /// </summary>
210     /// <param name="parameterName">Name of the parameter, or null to indicate an unnamed parameter</param>
211     /// <param name="value">The initial value of the parameter</param>
212     /// <returns>Returns the SqliteParameter object created during the call.</returns>
213     public SqliteParameter AddWithValue(string parameterName, object value)
214     {
215       SqliteParameter param = new SqliteParameter(parameterName, value);
216       Add(param);
217
218       return param;
219     }
220
221     /// <summary>
222     /// Adds an array of parameters to the collection
223     /// </summary>
224     /// <param name="values">The array of parameters to add</param>
225     public void AddRange(SqliteParameter[] values)
226     {
227       int x = values.Length;
228       for (int n = 0; n < x; n++)
229         Add(values[n]);
230     }
231
232     /// <summary>
233     /// Adds an array of parameters to the collection
234     /// </summary>
235     /// <param name="values">The array of parameters to add</param>
236     public override void AddRange(Array values)
237     {
238       int x = values.Length;
239       for (int n = 0; n < x; n++)
240         Add((SqliteParameter)(values.GetValue(n)));
241     }
242
243     /// <summary>
244     /// Clears the array and resets the collection
245     /// </summary>
246     public override void Clear()
247     {
248       _unboundFlag = true;
249       _parameterList.Clear();
250     }
251
252     /// <summary>
253     /// Determines if the named parameter exists in the collection
254     /// </summary>
255     /// <param name="parameterName">The name of the parameter to check</param>
256     /// <returns>True if the parameter is in the collection</returns>
257     public override bool Contains(string parameterName)
258     {
259       return (IndexOf(parameterName) != -1);
260     }
261
262     /// <summary>
263     /// Determines if the parameter exists in the collection
264     /// </summary>
265     /// <param name="value">The SqliteParameter to check</param>
266     /// <returns>True if the parameter is in the collection</returns>
267     public override bool Contains(object value)
268     {
269       return _parameterList.Contains((SqliteParameter)value);
270     }
271
272     /// <summary>
273     /// Not implemented
274     /// </summary>
275     /// <param name="array"></param>
276     /// <param name="index"></param>
277     public override void CopyTo(Array array, int index)
278     {
279       throw new NotImplementedException();
280     }
281
282     /// <summary>
283     /// Returns a count of parameters in the collection
284     /// </summary>
285     public override int Count
286     {
287       get { return _parameterList.Count; }
288     }
289
290     /// <summary>
291     /// Overloaded to specialize the return value of the default indexer
292     /// </summary>
293     /// <param name="parameterName">Name of the parameter to get/set</param>
294     /// <returns>The specified named Sqlite parameter</returns>
295     public new SqliteParameter this[string parameterName]
296     {
297       get
298       {
299         return (SqliteParameter)GetParameter(parameterName);
300       }
301       set
302       {
303         SetParameter(parameterName, value);
304       }
305     }
306
307     /// <summary>
308     /// Overloaded to specialize the return value of the default indexer
309     /// </summary>
310     /// <param name="index">The index of the parameter to get/set</param>
311     /// <returns>The specified Sqlite parameter</returns>
312     public new SqliteParameter this[int index]
313     {
314       get
315       {
316         return (SqliteParameter)GetParameter(index);
317       }
318       set
319       {
320         SetParameter(index, value);
321       }
322     }
323     /// <summary>
324     /// Retrieve a parameter by name from the collection
325     /// </summary>
326     /// <param name="parameterName">The name of the parameter to fetch</param>
327     /// <returns>A DbParameter object</returns>
328     protected override DbParameter GetParameter(string parameterName)
329     {
330       return GetParameter(IndexOf(parameterName));
331     }
332
333     /// <summary>
334     /// Retrieves a parameter by its index in the collection
335     /// </summary>
336     /// <param name="index">The index of the parameter to retrieve</param>
337     /// <returns>A DbParameter object</returns>
338     protected override DbParameter GetParameter(int index)
339     {
340       return _parameterList[index];
341     }
342
343     /// <summary>
344     /// Returns the index of a parameter given its name
345     /// </summary>
346     /// <param name="parameterName">The name of the parameter to find</param>
347     /// <returns>-1 if not found, otherwise a zero-based index of the parameter</returns>
348     public override int IndexOf(string parameterName)
349     {
350       int x = _parameterList.Count;
351       for (int n = 0; n < x; n++)
352       {
353         if (String.Compare(parameterName, _parameterList[n].ParameterName, true, CultureInfo.InvariantCulture) == 0)
354           return n;
355       }
356       return -1;
357     }
358
359     /// <summary>
360     /// Returns the index of a parameter
361     /// </summary>
362     /// <param name="value">The parameter to find</param>
363     /// <returns>-1 if not found, otherwise a zero-based index of the parameter</returns>
364     public override int IndexOf(object value)
365     {
366       return _parameterList.IndexOf((SqliteParameter)value);
367     }
368
369     /// <summary>
370     /// Inserts a parameter into the array at the specified location
371     /// </summary>
372     /// <param name="index">The zero-based index to insert the parameter at</param>
373     /// <param name="value">The parameter to insert</param>
374     public override void Insert(int index, object value)
375     {
376       _unboundFlag = true;
377       _parameterList.Insert(index, (SqliteParameter)value);
378     }
379
380     /// <summary>
381     /// Removes a parameter from the collection
382     /// </summary>
383     /// <param name="value">The parameter to remove</param>
384     public override void Remove(object value)
385     {
386       _unboundFlag = true;
387       _parameterList.Remove((SqliteParameter)value);
388     }
389
390     /// <summary>
391     /// Removes a parameter from the collection given its name
392     /// </summary>
393     /// <param name="parameterName">The name of the parameter to remove</param>
394     public override void RemoveAt(string parameterName)
395     {
396       RemoveAt(IndexOf(parameterName));
397     }
398
399     /// <summary>
400     /// Removes a parameter from the collection given its index
401     /// </summary>
402     /// <param name="index">The zero-based parameter index to remove</param>
403     public override void RemoveAt(int index)
404     {
405       _unboundFlag = true;
406       _parameterList.RemoveAt(index);
407     }
408
409     /// <summary>
410     /// Re-assign the named parameter to a new parameter object
411     /// </summary>
412     /// <param name="parameterName">The name of the parameter to replace</param>
413     /// <param name="value">The new parameter</param>
414     protected override void SetParameter(string parameterName, DbParameter value)
415     {
416       SetParameter(IndexOf(parameterName), value);
417     }
418
419     /// <summary>
420     /// Re-assign a parameter at the specified index
421     /// </summary>
422     /// <param name="index">The zero-based index of the parameter to replace</param>
423     /// <param name="value">The new parameter</param>
424     protected override void SetParameter(int index, DbParameter value)
425     {
426       _unboundFlag = true;
427       _parameterList[index] = (SqliteParameter)value;
428     }
429
430     /// <summary>
431     /// Un-binds all parameters from their statements
432     /// </summary>
433     internal void Unbind()
434     {
435       _unboundFlag = true;
436     }
437
438     /// <summary>
439     /// This function attempts to map all parameters in the collection to all statements in a Command.
440     /// Since named parameters may span multiple statements, this function makes sure all statements are bound
441     /// to the same named parameter.  Unnamed parameters are bound in sequence.
442     /// </summary>
443     internal void MapParameters(SqliteStatement activeStatement)
444     {
445       if (_unboundFlag == false || _parameterList.Count == 0 || _command._statementList == null) return;
446
447       int nUnnamed = 0;
448       string s;
449       int n;
450       int y = -1;
451       SqliteStatement stmt;
452
453       foreach(SqliteParameter p in _parameterList)
454       {
455         y ++;
456         s = p.ParameterName;
457         if (s == null)
458         {
459           s = String.Format(CultureInfo.InvariantCulture, ";{0}", nUnnamed);
460           nUnnamed++;
461         }
462
463         int x;
464         bool isMapped = false;
465
466         if (activeStatement == null)
467           x = _command._statementList.Count;
468         else
469           x = 1;
470
471         stmt = activeStatement;
472         for (n = 0; n < x; n++)
473         {
474           isMapped = false;
475           if (stmt == null) stmt = _command._statementList[n];
476           if (stmt._paramNames != null)
477           {
478             if (stmt.MapParameter(s, p) == true)
479               isMapped = true;
480           }
481           stmt = null;
482         }
483
484         // If the parameter has a name, but the SQL statement uses unnamed references, this can happen -- attempt to map
485         // the parameter by its index in the collection
486         if (isMapped == false)
487         {
488           s = String.Format(CultureInfo.InvariantCulture, ";{0}", y);
489
490           stmt = activeStatement;
491           for (n = 0; n < x; n++)
492           {
493             if (stmt == null) stmt = _command._statementList[n];
494             if (stmt._paramNames != null)
495             {
496               if (stmt.MapParameter(s, p) == true)
497                 isMapped = true;
498             }
499             stmt = null;
500           }
501         }
502       }
503       if (activeStatement == null) _unboundFlag = false;
504     }
505   }
506 }
507 #endif