copied mono-api-diff.cs from mono-2-2 branch so new patch can be applied and history...
[mono.git] / mcs / class / Mono.Data.Sqlite / Mono.Data.Sqlite_2.0 / SQLiteConvert.cs
1 /********************************************************\r
2  * ADO.NET 2.0 Data Provider for SQLite Version 3.X\r
3  * Written by Robert Simpson (robert@blackcastlesoft.com)\r
4  * \r
5  * Released to the public domain, use at your own risk!\r
6  ********************************************************/\r
7 \r
8 namespace Mono.Data.Sqlite\r
9 {\r
10   using System;\r
11   using System.Data;\r
12   using System.Runtime.InteropServices;\r
13   using System.Collections.Generic;\r
14   using System.ComponentModel;\r
15   using System.Globalization;\r
16   using System.Text;\r
17 \r
18 #if !PLATFORM_COMPACTFRAMEWORK \r
19   using System.ComponentModel.Design;\r
20 #endif\r
21 \r
22   /// <summary>\r
23   /// This base class provides datatype conversion services for the SQLite provider.\r
24   /// </summary>\r
25   public abstract class SqliteConvert\r
26   {\r
27     /// <summary>\r
28     /// An array of ISO8601 datetime formats we support conversion from\r
29     /// </summary>\r
30     private static string[] _datetimeFormats = new string[] {\r
31       "THHmmss",\r
32       "THHmm",\r
33       "HH:mm:ss",\r
34       "HH:mm",\r
35       "HH:mm:ss.FFFFFFF",\r
36       "yy-MM-dd",\r
37       "yyyy-MM-dd",\r
38       "yyyy-MM-dd HH:mm:ss.FFFFFFF",\r
39       "yyyy-MM-dd HH:mm:ss",\r
40       "yyyy-MM-dd HH:mm",                               \r
41       "yyyy-MM-ddTHH:mm:ss.FFFFFFF",\r
42       "yyyy-MM-ddTHH:mm",\r
43       "yyyy-MM-ddTHH:mm:ss",\r
44       "yyyyMMddHHmmss",\r
45       "yyyyMMddHHmm",\r
46       "yyyyMMddTHHmmssFFFFFFF",\r
47       "yyyyMMdd"\r
48     };\r
49 \r
50     /// <summary>\r
51     /// An UTF-8 Encoding instance, so we can convert strings to and from UTF-8\r
52     /// </summary>\r
53     private static Encoding _utf8 = new UTF8Encoding();\r
54     /// <summary>\r
55     /// The default DateTime format for this instance\r
56     /// </summary>\r
57     internal SQLiteDateFormats _datetimeFormat;\r
58     /// <summary>\r
59     /// Initializes the conversion class\r
60     /// </summary>\r
61     /// <param name="fmt">The default date/time format to use for this instance</param>\r
62     internal SqliteConvert(SQLiteDateFormats fmt)\r
63     {\r
64       _datetimeFormat = fmt;\r
65     }\r
66 \r
67     #region UTF-8 Conversion Functions\r
68     /// <summary>\r
69     /// Converts a string to a UTF-8 encoded byte array sized to include a null-terminating character.\r
70     /// </summary>\r
71     /// <param name="sourceText">The string to convert to UTF-8</param>\r
72     /// <returns>A byte array containing the converted string plus an extra 0 terminating byte at the end of the array.</returns>\r
73     public static byte[] ToUTF8(string sourceText)\r
74     {\r
75       Byte[] byteArray;\r
76       int nlen = _utf8.GetByteCount(sourceText) + 1;\r
77 \r
78       byteArray = new byte[nlen];\r
79       nlen = _utf8.GetBytes(sourceText, 0, sourceText.Length, byteArray, 0);\r
80       byteArray[nlen] = 0;\r
81 \r
82       return byteArray;\r
83     }\r
84 \r
85     /// <summary>\r
86     /// Convert a DateTime to a UTF-8 encoded, zero-terminated byte array.\r
87     /// </summary>\r
88     /// <remarks>\r
89     /// This function is a convenience function, which first calls ToString() on the DateTime, and then calls ToUTF8() with the\r
90     /// string result.\r
91     /// </remarks>\r
92     /// <param name="dateTimeValue">The DateTime to convert.</param>\r
93     /// <returns>The UTF-8 encoded string, including a 0 terminating byte at the end of the array.</returns>\r
94     public byte[] ToUTF8(DateTime dateTimeValue)\r
95     {\r
96       return ToUTF8(ToString(dateTimeValue));\r
97     }\r
98 \r
99     /// <summary>\r
100     /// Converts a UTF-8 encoded IntPtr of the specified length into a .NET string\r
101     /// </summary>\r
102     /// <param name="nativestring">The pointer to the memory where the UTF-8 string is encoded</param>\r
103     /// <param name="nativestringlen">The number of bytes to decode</param>\r
104     /// <returns>A string containing the translated character(s)</returns>\r
105     public virtual string ToString(IntPtr nativestring, int nativestringlen)\r
106     {\r
107       return UTF8ToString(nativestring, nativestringlen);\r
108     }\r
109 \r
110     /// <summary>\r
111     /// Converts a UTF-8 encoded IntPtr of the specified length into a .NET string\r
112     /// </summary>\r
113     /// <param name="nativestring">The pointer to the memory where the UTF-8 string is encoded</param>\r
114     /// <param name="nativestringlen">The number of bytes to decode</param>\r
115     /// <returns>A string containing the translated character(s)</returns>\r
116     public static string UTF8ToString(IntPtr nativestring, int nativestringlen)\r
117     {\r
118       if (nativestringlen == 0 || nativestring == IntPtr.Zero) return "";\r
119       if (nativestringlen == -1)\r
120       {\r
121         do\r
122         {\r
123           nativestringlen++;\r
124         } while (Marshal.ReadByte(nativestring, nativestringlen) != 0);\r
125       }\r
126 \r
127       byte[] byteArray = new byte[nativestringlen];\r
128       \r
129       Marshal.Copy(nativestring, byteArray, 0, nativestringlen);\r
130 \r
131       return _utf8.GetString(byteArray, 0, nativestringlen);\r
132     }\r
133 \r
134 \r
135     #endregion\r
136 \r
137     #region DateTime Conversion Functions\r
138     /// <summary>\r
139     /// Converts a string into a DateTime, using the current DateTimeFormat specified for the connection when it was opened.\r
140     /// </summary>\r
141     /// <remarks>\r
142     /// Acceptable ISO8601 DateTime formats are:\r
143     ///   yyyy-MM-dd HH:mm:ss\r
144     ///   yyyyMMddHHmmss\r
145     ///   yyyyMMddTHHmmssfffffff\r
146     ///   yyyy-MM-dd\r
147     ///   yy-MM-dd\r
148     ///   yyyyMMdd\r
149     ///   HH:mm:ss\r
150     ///   THHmmss\r
151     /// </remarks>\r
152     /// <param name="dateText">The string containing either a Tick value, a JulianDay double, or an ISO8601-format string</param>\r
153     /// <returns>A DateTime value</returns>\r
154     public DateTime ToDateTime(string dateText)\r
155     {\r
156       switch (_datetimeFormat)\r
157       {\r
158         case SQLiteDateFormats.Ticks:\r
159           return new DateTime(Convert.ToInt64(dateText, CultureInfo.InvariantCulture));\r
160         case SQLiteDateFormats.JulianDay:\r
161           return ToDateTime(Convert.ToDouble(dateText, CultureInfo.InvariantCulture));\r
162         default:\r
163           return DateTime.ParseExact(dateText, _datetimeFormats, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None);\r
164       }\r
165     }\r
166 \r
167     /// <summary>\r
168     /// Converts a julianday value into a DateTime\r
169     /// </summary>\r
170     /// <param name="julianDay">The value to convert</param>\r
171     /// <returns>A .NET DateTime</returns>\r
172     public DateTime ToDateTime(double julianDay)\r
173     {\r
174       return DateTime.FromOADate(julianDay - 2415018.5);\r
175     }\r
176 \r
177     /// <summary>\r
178     /// Converts a DateTime struct to a JulianDay double\r
179     /// </summary>\r
180     /// <param name="value">The DateTime to convert</param>\r
181     /// <returns>The JulianDay value the Datetime represents</returns>\r
182     public double ToJulianDay(DateTime value)\r
183     {\r
184       return value.ToOADate() + 2415018.5;\r
185     }\r
186 \r
187     /// <summary>\r
188     /// Converts a DateTime to a string value, using the current DateTimeFormat specified for the connection when it was opened.\r
189     /// </summary>\r
190     /// <param name="dateValue">The DateTime value to convert</param>\r
191     /// <returns>Either a string consisting of the tick count for DateTimeFormat.Ticks, a JulianDay double, or a date/time in ISO8601 format.</returns>\r
192     public string ToString(DateTime dateValue)\r
193     {\r
194       switch (_datetimeFormat)\r
195       {\r
196         case SQLiteDateFormats.Ticks:\r
197           return dateValue.Ticks.ToString(CultureInfo.InvariantCulture);\r
198         case SQLiteDateFormats.JulianDay:\r
199           return ToJulianDay(dateValue).ToString(CultureInfo.InvariantCulture);\r
200         default:\r
201           return dateValue.ToString(_datetimeFormats[7], CultureInfo.InvariantCulture);\r
202       }\r
203     }\r
204 \r
205     /// <summary>\r
206     /// Internal function to convert a UTF-8 encoded IntPtr of the specified length to a DateTime.\r
207     /// </summary>\r
208     /// <remarks>\r
209     /// This is a convenience function, which first calls ToString() on the IntPtr to convert it to a string, then calls\r
210     /// ToDateTime() on the string to return a DateTime.\r
211     /// </remarks>\r
212     /// <param name="ptr">A pointer to the UTF-8 encoded string</param>\r
213     /// <param name="len">The length in bytes of the string</param>\r
214     /// <returns>The parsed DateTime value</returns>\r
215     internal DateTime ToDateTime(IntPtr ptr, int len)\r
216     {\r
217       return ToDateTime(ToString(ptr, len));\r
218     }\r
219 \r
220     #endregion\r
221 \r
222     /// <summary>\r
223     /// Smart method of splitting a string.  Skips quoted elements, removes the quotes.\r
224     /// </summary>\r
225     /// <remarks>\r
226     /// This split function works somewhat like the String.Split() function in that it breaks apart a string into\r
227     /// pieces and returns the pieces as an array.  The primary differences are:\r
228     /// <list type="bullet">\r
229     /// <item><description>Only one character can be provided as a separator character</description></item>\r
230     /// <item><description>Quoted text inside the string is skipped over when searching for the separator, and the quotes are removed.</description></item>\r
231     /// </list>\r
232     /// Thus, if splitting the following string looking for a comma:<br/>\r
233     /// One,Two, "Three, Four", Five<br/>\r
234     /// <br/>\r
235     /// The resulting array would contain<br/>\r
236     /// [0] One<br/>\r
237     /// [1] Two<br/>\r
238     /// [2] Three, Four<br/>\r
239     /// [3] Five<br/>\r
240     /// <br/>\r
241     /// Note that the leading and trailing spaces were removed from each item during the split.\r
242     /// </remarks>\r
243     /// <param name="source">Source string to split apart</param>\r
244     /// <param name="separator">Separator character</param>\r
245     /// <returns>A string array of the split up elements</returns>\r
246     public static string[] Split(string source, char separator)\r
247     {\r
248       char[] toks = new char[2] { '\"', separator };\r
249       char[] quot = new char[1] { '\"' };\r
250       int n = 0;\r
251       List<string> ls = new List<string>();\r
252       string s;\r
253 \r
254       while (source.Length > 0)\r
255       {\r
256         n = source.IndexOfAny(toks, n);\r
257         if (n == -1) break;\r
258         if (source[n] == toks[0])\r
259         {\r
260           //source = source.Remove(n, 1);\r
261           n = source.IndexOfAny(quot, n + 1);\r
262           if (n == -1)\r
263           {\r
264             //source = "\"" + source;\r
265             break;\r
266           }\r
267           n++;\r
268           //source = source.Remove(n, 1);\r
269         }\r
270         else\r
271         {\r
272           s = source.Substring(0, n).Trim();\r
273           if (s.Length > 1 && s[0] == quot[0] && s[s.Length - 1] == s[0])\r
274             s = s.Substring(1, s.Length - 2);\r
275 \r
276           source = source.Substring(n + 1).Trim();\r
277           if (s.Length > 0) ls.Add(s);\r
278           n = 0;\r
279         }\r
280       }\r
281       if (source.Length > 0)\r
282       {\r
283         s = source.Trim();\r
284         if (s.Length > 1 && s[0] == quot[0] && s[s.Length - 1] == s[0])\r
285           s = s.Substring(1, s.Length - 2);\r
286         ls.Add(s);\r
287       }\r
288 \r
289       string[] ar = new string[ls.Count];\r
290       ls.CopyTo(ar, 0);\r
291 \r
292       return ar;\r
293     }\r
294 \r
295     /// <summary>\r
296     /// Convert a value to true or false.\r
297     /// </summary>\r
298     /// <param name="source">A string or number representing true or false</param>\r
299     /// <returns></returns>\r
300     public static bool ToBoolean(object source)\r
301     {\r
302       if (source is bool) return (bool)source;\r
303 \r
304       return ToBoolean(source.ToString());\r
305     }\r
306 \r
307     /// <summary>\r
308     /// Convert a string to true or false.\r
309     /// </summary>\r
310     /// <param name="source">A string representing true or false</param>\r
311     /// <returns></returns>\r
312     /// <remarks>\r
313     /// "yes", "no", "y", "n", "0", "1", "on", "off" as well as Boolean.FalseString and Boolean.TrueString will all be\r
314     /// converted to a proper boolean value.\r
315     /// </remarks>\r
316     public static bool ToBoolean(string source)\r
317     {\r
318       if (String.Compare(source, bool.TrueString, StringComparison.OrdinalIgnoreCase) == 0) return true;\r
319       else if (String.Compare(source, bool.FalseString, StringComparison.OrdinalIgnoreCase) == 0) return false;\r
320 \r
321       switch(source.ToLower())\r
322       {\r
323         case "yes":\r
324         case "y":\r
325         case "1":\r
326         case "on":\r
327           return true;\r
328         case "no":\r
329         case "n":\r
330         case "0":\r
331         case "off":\r
332           return false;\r
333         default:\r
334           throw new ArgumentException("source");\r
335       }\r
336     }\r
337 \r
338     #region Type Conversions\r
339     /// <summary>\r
340     /// Determines the data type of a column in a statement\r
341     /// </summary>\r
342     /// <param name="stmt">The statement to retrieve information for</param>\r
343     /// <param name="i">The column to retrieve type information on</param>\r
344     /// <param name="typ">The SQLiteType to receive the affinity for the given column</param>\r
345     internal static void ColumnToType(SqliteStatement stmt, int i, SQLiteType typ)\r
346     {\r
347       typ.Type = TypeNameToDbType(stmt._sql.ColumnType(stmt, i, out typ.Affinity));\r
348     }\r
349 \r
350     /// <summary>\r
351     /// Converts a SQLiteType to a .NET Type object\r
352     /// </summary>\r
353     /// <param name="t">The SQLiteType to convert</param>\r
354     /// <returns>Returns a .NET Type object</returns>\r
355     internal static Type SQLiteTypeToType(SQLiteType t)\r
356     {\r
357       if (t.Type == DbType.Object)\r
358         return _affinitytotype[(int)t.Affinity];\r
359       else\r
360         return SqliteConvert.DbTypeToType(t.Type);\r
361     }\r
362 \r
363     private static Type[] _affinitytotype = {\r
364       typeof(object),\r
365       typeof(Int64),\r
366       typeof(Double),\r
367       typeof(string),\r
368       typeof(byte[]),\r
369       typeof(object),\r
370       typeof(DateTime),\r
371       typeof(object)\r
372     };\r
373 \r
374     /// <summary>\r
375     /// For a given intrinsic type, return a DbType\r
376     /// </summary>\r
377     /// <param name="typ">The native type to convert</param>\r
378     /// <returns>The corresponding (closest match) DbType</returns>\r
379     internal static DbType TypeToDbType(Type typ)\r
380     {\r
381       TypeCode tc = Type.GetTypeCode(typ);\r
382       if (tc == TypeCode.Object)\r
383       {\r
384         if (typ == typeof(byte[])) return DbType.Binary;\r
385         if (typ == typeof(Guid)) return DbType.Guid;\r
386         return DbType.String;\r
387       }\r
388       return _typetodbtype[(int)tc];\r
389     }\r
390 \r
391     private static DbType[] _typetodbtype = {\r
392       DbType.Object,\r
393       DbType.Binary,\r
394       DbType.Object,\r
395       DbType.Boolean,\r
396       DbType.SByte,\r
397       DbType.SByte,\r
398       DbType.Byte,\r
399       DbType.Int16, // 7\r
400       DbType.UInt16,\r
401       DbType.Int32,\r
402       DbType.UInt32,\r
403       DbType.Int64, // 11\r
404       DbType.UInt64,\r
405       DbType.Single,\r
406       DbType.Double,\r
407       DbType.Decimal,\r
408       DbType.DateTime,\r
409       DbType.Object,\r
410       DbType.String,\r
411     };\r
412 \r
413     /// <summary>\r
414     /// Returns the ColumnSize for the given DbType\r
415     /// </summary>\r
416     /// <param name="typ">The DbType to get the size of</param>\r
417     /// <returns></returns>\r
418     internal static int DbTypeToColumnSize(DbType typ)\r
419     {\r
420       return _dbtypetocolumnsize[(int)typ];\r
421     }\r
422 \r
423     private static int[] _dbtypetocolumnsize = {\r
424       2147483647,   // 0\r
425       2147483647,   // 1\r
426       1,     // 2\r
427       1,     // 3\r
428       8,  // 4\r
429       8, // 5\r
430       8, // 6\r
431       8,  // 7\r
432       8,   // 8\r
433       16,     // 9\r
434       2,\r
435       4,\r
436       8,\r
437       2147483647,\r
438       1,\r
439       4,\r
440       2147483647,\r
441       8,\r
442       2,\r
443       4,\r
444       8,\r
445       8,\r
446       2147483647,\r
447       2147483647,\r
448       2147483647,\r
449       2147483647,   // 25 (Xml)\r
450     };\r
451 \r
452     internal static object DbTypeToNumericPrecision(DbType typ)\r
453     {\r
454       return _dbtypetonumericprecision[(int)typ];\r
455     }\r
456 \r
457     private static object[] _dbtypetonumericprecision = {\r
458       DBNull.Value, // 0\r
459       DBNull.Value, // 1\r
460       3,\r
461       DBNull.Value,\r
462       19,\r
463       DBNull.Value, // 5\r
464       DBNull.Value, // 6\r
465       53,\r
466       53,\r
467       DBNull.Value,\r
468       5,\r
469       10,\r
470       19,\r
471       DBNull.Value,\r
472       3,\r
473       24,\r
474       DBNull.Value,\r
475       DBNull.Value,\r
476       5,\r
477       10,\r
478       19,\r
479       53,\r
480       DBNull.Value,\r
481       DBNull.Value,\r
482       DBNull.Value\r
483     };\r
484 \r
485     internal static object DbTypeToNumericScale(DbType typ)\r
486     {\r
487       return _dbtypetonumericscale[(int)typ];\r
488     }\r
489 \r
490     private static object[] _dbtypetonumericscale = {\r
491       DBNull.Value, // 0\r
492       DBNull.Value, // 1\r
493       0,\r
494       DBNull.Value,\r
495       4,\r
496       DBNull.Value, // 5\r
497       DBNull.Value, // 6\r
498       DBNull.Value,\r
499       DBNull.Value,\r
500       DBNull.Value,\r
501       0,\r
502       0,\r
503       0,\r
504       DBNull.Value,\r
505       0,\r
506       DBNull.Value,\r
507       DBNull.Value,\r
508       DBNull.Value,\r
509       0,\r
510       0,\r
511       0,\r
512       0,\r
513       DBNull.Value,\r
514       DBNull.Value,\r
515       DBNull.Value\r
516     };\r
517 \r
518     internal static string DbTypeToTypeName(DbType typ)\r
519     {\r
520       for (int n = 0; n < _dbtypeNames.Length; n++)\r
521       {\r
522         if (_dbtypeNames[n].dataType == typ)\r
523           return _dbtypeNames[n].typeName;\r
524       }\r
525 \r
526       return String.Empty;\r
527     }\r
528 \r
529     private static SQLiteTypeNames[] _dbtypeNames = {\r
530       new SQLiteTypeNames("INTEGER", DbType.Int64),\r
531       new SQLiteTypeNames("TINYINT", DbType.Byte),\r
532       new SQLiteTypeNames("INT", DbType.Int32),\r
533       new SQLiteTypeNames("VARCHAR", DbType.AnsiString),\r
534       new SQLiteTypeNames("NVARCHAR", DbType.String),\r
535       new SQLiteTypeNames("CHAR", DbType.AnsiStringFixedLength),\r
536       new SQLiteTypeNames("NCHAR", DbType.StringFixedLength),\r
537       new SQLiteTypeNames("FLOAT", DbType.Double),\r
538       new SQLiteTypeNames("REAL", DbType.Single),          \r
539       new SQLiteTypeNames("BIT", DbType.Boolean),\r
540       new SQLiteTypeNames("DECIMAL", DbType.Decimal),\r
541       new SQLiteTypeNames("DATETIME", DbType.DateTime),\r
542       new SQLiteTypeNames("BLOB", DbType.Binary),\r
543       new SQLiteTypeNames("UNIQUEIDENTIFIER", DbType.Guid),\r
544       new SQLiteTypeNames("SMALLINT", DbType.Int16),\r
545     };\r
546     /// <summary>\r
547     /// Convert a DbType to a Type\r
548     /// </summary>\r
549     /// <param name="typ">The DbType to convert from</param>\r
550     /// <returns>The closest-match .NET type</returns>\r
551     internal static Type DbTypeToType(DbType typ)\r
552     {\r
553       return _dbtypeToType[(int)typ];\r
554     }\r
555 \r
556     private static Type[] _dbtypeToType = {\r
557       typeof(string),   // 0\r
558       typeof(byte[]),   // 1\r
559       typeof(byte),     // 2\r
560       typeof(bool),     // 3\r
561       typeof(decimal),  // 4\r
562       typeof(DateTime), // 5\r
563       typeof(DateTime), // 6\r
564       typeof(decimal),  // 7\r
565       typeof(double),   // 8\r
566       typeof(Guid),     // 9\r
567       typeof(Int16),\r
568       typeof(Int32),\r
569       typeof(Int64),\r
570       typeof(object),\r
571       typeof(sbyte),\r
572       typeof(float),\r
573       typeof(string),\r
574       typeof(DateTime),\r
575       typeof(UInt16),\r
576       typeof(UInt32),\r
577       typeof(UInt64),\r
578       typeof(double),\r
579       typeof(string),\r
580       typeof(string),\r
581       typeof(string),\r
582       typeof(string),   // 25 (Xml)\r
583     };\r
584 \r
585     /// <summary>\r
586     /// For a given type, return the closest-match SQLite TypeAffinity, which only understands a very limited subset of types.\r
587     /// </summary>\r
588     /// <param name="typ">The type to evaluate</param>\r
589     /// <returns>The SQLite type affinity for that type.</returns>\r
590     internal static TypeAffinity TypeToAffinity(Type typ)\r
591     {\r
592       TypeCode tc = Type.GetTypeCode(typ);\r
593       if (tc == TypeCode.Object)\r
594       {\r
595         if (typ == typeof(byte[]) || typ == typeof(Guid))\r
596           return TypeAffinity.Blob;\r
597         else\r
598           return TypeAffinity.Text;\r
599       }\r
600       return _typecodeAffinities[(int)tc];\r
601     }\r
602 \r
603     private static TypeAffinity[] _typecodeAffinities = {\r
604       TypeAffinity.Null,\r
605       TypeAffinity.Blob,\r
606       TypeAffinity.Null,\r
607       TypeAffinity.Int64,\r
608       TypeAffinity.Int64,\r
609       TypeAffinity.Int64,\r
610       TypeAffinity.Int64,\r
611       TypeAffinity.Int64, // 7\r
612       TypeAffinity.Int64,\r
613       TypeAffinity.Int64,\r
614       TypeAffinity.Int64,\r
615       TypeAffinity.Int64, // 11\r
616       TypeAffinity.Int64,\r
617       TypeAffinity.Double,\r
618       TypeAffinity.Double,\r
619       TypeAffinity.Double,\r
620       TypeAffinity.DateTime,\r
621       TypeAffinity.Null,\r
622       TypeAffinity.Text,\r
623     };\r
624 \r
625     /// <summary>\r
626     /// For a given type name, return a closest-match .NET type\r
627     /// </summary>\r
628     /// <param name="Name">The name of the type to match</param>\r
629     /// <returns>The .NET DBType the text evaluates to.</returns>\r
630     internal static DbType TypeNameToDbType(string Name)\r
631     {\r
632       if (String.IsNullOrEmpty(Name)) return DbType.Object;\r
633 \r
634       int x = _typeNames.Length;\r
635       for (int n = 0; n < x; n++)\r
636       {\r
637         if (String.Compare(Name, 0, _typeNames[n].typeName, 0, _typeNames[n].typeName.Length, true, CultureInfo.InvariantCulture) == 0)\r
638           return _typeNames[n].dataType; \r
639       }\r
640       return DbType.Object;\r
641     }\r
642     #endregion\r
643 \r
644     private static SQLiteTypeNames[] _typeNames = {\r
645       new SQLiteTypeNames("COUNTER", DbType.Int64),\r
646       new SQLiteTypeNames("AUTOINCREMENT", DbType.Int64),\r
647       new SQLiteTypeNames("IDENTITY", DbType.Int64),\r
648       new SQLiteTypeNames("LONGTEXT", DbType.String),\r
649       new SQLiteTypeNames("LONGCHAR", DbType.String),\r
650       new SQLiteTypeNames("LONGVARCHAR", DbType.String),\r
651       new SQLiteTypeNames("LONG", DbType.Int64),\r
652       new SQLiteTypeNames("TINYINT", DbType.Byte),\r
653       new SQLiteTypeNames("INTEGER", DbType.Int64),\r
654       new SQLiteTypeNames("INT", DbType.Int32),\r
655       new SQLiteTypeNames("VARCHAR", DbType.String),\r
656       new SQLiteTypeNames("NVARCHAR", DbType.String),\r
657       new SQLiteTypeNames("CHAR", DbType.String),\r
658       new SQLiteTypeNames("NCHAR", DbType.String),\r
659       new SQLiteTypeNames("TEXT", DbType.String),\r
660       new SQLiteTypeNames("NTEXT", DbType.String),\r
661       new SQLiteTypeNames("STRING", DbType.String),\r
662       new SQLiteTypeNames("DOUBLE", DbType.Double),\r
663       new SQLiteTypeNames("FLOAT", DbType.Double),\r
664       new SQLiteTypeNames("REAL", DbType.Single),          \r
665       new SQLiteTypeNames("BIT", DbType.Boolean),\r
666       new SQLiteTypeNames("YESNO", DbType.Boolean),\r
667       new SQLiteTypeNames("LOGICAL", DbType.Boolean),\r
668       new SQLiteTypeNames("BOOL", DbType.Boolean),\r
669       new SQLiteTypeNames("NUMERIC", DbType.Decimal),\r
670       new SQLiteTypeNames("DECIMAL", DbType.Decimal),\r
671       new SQLiteTypeNames("MONEY", DbType.Decimal),\r
672       new SQLiteTypeNames("CURRENCY", DbType.Decimal),\r
673       new SQLiteTypeNames("TIME", DbType.DateTime),\r
674       new SQLiteTypeNames("DATE", DbType.DateTime),\r
675       new SQLiteTypeNames("SMALLDATE", DbType.DateTime),\r
676       new SQLiteTypeNames("BLOB", DbType.Binary),\r
677       new SQLiteTypeNames("BINARY", DbType.Binary),\r
678       new SQLiteTypeNames("VARBINARY", DbType.Binary),\r
679       new SQLiteTypeNames("IMAGE", DbType.Binary),\r
680       new SQLiteTypeNames("GENERAL", DbType.Binary),\r
681       new SQLiteTypeNames("OLEOBJECT", DbType.Binary),\r
682       new SQLiteTypeNames("GUID", DbType.Guid),\r
683       new SQLiteTypeNames("UNIQUEIDENTIFIER", DbType.Guid),\r
684       new SQLiteTypeNames("MEMO", DbType.String),\r
685       new SQLiteTypeNames("NOTE", DbType.String),\r
686       new SQLiteTypeNames("SMALLINT", DbType.Int16),\r
687       new SQLiteTypeNames("BIGINT", DbType.Int64),\r
688     };\r
689   }\r
690 \r
691   /// <summary>\r
692   /// SQLite has very limited types, and is inherently text-based.  The first 5 types below represent the sum of all types SQLite\r
693   /// understands.  The DateTime extension to the spec is for internal use only.\r
694   /// </summary>\r
695   public enum TypeAffinity\r
696   {\r
697     /// <summary>\r
698     /// Not used\r
699     /// </summary>\r
700     Uninitialized = 0,\r
701     /// <summary>\r
702     /// All integers in SQLite default to Int64\r
703     /// </summary>\r
704     Int64 = 1,\r
705     /// <summary>\r
706     /// All floating point numbers in SQLite default to double\r
707     /// </summary>\r
708     Double = 2,\r
709     /// <summary>\r
710     /// The default data type of SQLite is text\r
711     /// </summary>\r
712     Text = 3,\r
713     /// <summary>\r
714     /// Typically blob types are only seen when returned from a function\r
715     /// </summary>\r
716     Blob = 4,\r
717     /// <summary>\r
718     /// Null types can be returned from functions\r
719     /// </summary>\r
720     Null = 5,\r
721     /// <summary>\r
722     /// Used internally by this provider\r
723     /// </summary>\r
724     DateTime = 10,\r
725     /// <summary>\r
726     /// Used internally\r
727     /// </summary>\r
728     None = 11,\r
729   }\r
730 \r
731   /// <summary>\r
732   /// This implementation of SQLite for ADO.NET can process date/time fields in databases in only one of three formats.  Ticks, ISO8601\r
733   /// and JulianDay.\r
734   /// </summary>\r
735   /// <remarks>\r
736   /// ISO8601 is more compatible, readable, fully-processable, but less accurate as it doesn't provide time down to fractions of a second.\r
737   /// JulianDay is the numeric format the SQLite uses internally and is arguably the most compatible with 3rd party tools.  It is\r
738   /// not readable as text without post-processing.\r
739   /// Ticks less compatible with 3rd party tools that query the database, and renders the DateTime field unreadable as text without post-processing.\r
740   /// \r
741   /// The preferred order of choosing a datetime format is JulianDay, ISO8601, and then Ticks.  Ticks is mainly present for legacy \r
742   /// code support.\r
743   /// </remarks>\r
744   public enum SQLiteDateFormats\r
745   {\r
746     /// <summary>\r
747     /// Using ticks is not recommended and is not well supported with LINQ.\r
748     /// </summary>\r
749     Ticks = 0,\r
750     /// <summary>\r
751     /// The default format for this provider.\r
752     /// </summary>\r
753     ISO8601 = 1,\r
754     /// <summary>\r
755     /// JulianDay format, which is what SQLite uses internally\r
756     /// </summary>\r
757     JulianDay = 2\r
758   }\r
759 \r
760   /// <summary>\r
761   /// This enum determines how SQLite treats its journal file.\r
762   /// </summary>\r
763   /// <remarks>\r
764   /// By default SQLite will create and delete the journal file when needed during a transaction.\r
765   /// However, for some computers running certain filesystem monitoring tools, the rapid\r
766   /// creation and deletion of the journal file can cause those programs to fail, or to interfere with SQLite.\r
767   /// \r
768   /// If a program or virus scanner is interfering with SQLite's journal file, you may receive errors like "unable to open database file"\r
769   /// when starting a transaction.  If this is happening, you may want to change the default journal mode to Persist.\r
770   /// </remarks>\r
771   public enum SQLiteJournalModeEnum\r
772   {\r
773     /// <summary>\r
774     /// The default mode, this causes SQLite to create and destroy the journal file as-needed.\r
775     /// </summary>\r
776     Delete = 0,\r
777     /// <summary>\r
778     /// When this is set, SQLite will keep the journal file even after a transaction has completed.  It's contents will be erased,\r
779     /// and the journal re-used as often as needed.  If it is deleted, it will be recreated the next time it is needed.\r
780     /// </summary>\r
781     Persist = 1,\r
782     /// <summary>\r
783     /// This option disables the rollback journal entirely.  Interrupted transactions or a program crash can cause database\r
784     /// corruption in this mode!\r
785     /// </summary>\r
786     Off = 2\r
787   }\r
788 \r
789   /// <summary>\r
790   /// Struct used internally to determine the datatype of a column in a resultset\r
791   /// </summary>\r
792   internal class SQLiteType\r
793   {\r
794     /// <summary>\r
795     /// The DbType of the column, or DbType.Object if it cannot be determined\r
796     /// </summary>\r
797     internal DbType Type;\r
798     /// <summary>\r
799     /// The affinity of a column, used for expressions or when Type is DbType.Object\r
800     /// </summary>\r
801     internal TypeAffinity Affinity;\r
802   }\r
803 \r
804   internal struct SQLiteTypeNames\r
805   {\r
806     internal SQLiteTypeNames(string newtypeName, DbType newdataType)\r
807     {\r
808       typeName = newtypeName;\r
809       dataType = newdataType;\r
810     }\r
811 \r
812     internal string typeName;\r
813     internal DbType dataType;\r
814   }\r
815 }\r