1 /********************************************************
\r
2 * ADO.NET 2.0 Data Provider for SQLite Version 3.X
\r
3 * Written by Robert Simpson (robert@blackcastlesoft.com)
\r
5 * Released to the public domain, use at your own risk!
\r
6 ********************************************************/
\r
8 namespace Mono.Data.Sqlite
\r
12 using System.Runtime.InteropServices;
\r
13 using System.Collections.Generic;
\r
14 using System.ComponentModel;
\r
15 using System.Globalization;
\r
18 #if !PLATFORM_COMPACTFRAMEWORK
\r
19 using System.ComponentModel.Design;
\r
23 /// This base class provides datatype conversion services for the SQLite provider.
\r
25 public abstract class SqliteConvert
\r
28 /// The value for the Unix epoch (e.g. January 1, 1970 at midnight, in UTC).
\r
30 protected static readonly DateTime UnixEpoch =
\r
31 new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
\r
33 /// An array of ISO8601 datetime formats we support conversion from
\r
35 private static string[] _datetimeFormats = new string[] {
\r
38 "HH:mm:ss.FFFFFFFK",
\r
41 "yyyy-MM-dd HH:mm:ss.FFFFFFFK", /* NOTE: UTC default (5). */
\r
42 "yyyy-MM-dd HH:mm:ssK",
\r
43 "yyyy-MM-dd HH:mmK",
\r
44 "yyyy-MM-ddTHH:mm:ss.FFFFFFFK",
\r
45 "yyyy-MM-ddTHH:mmK",
\r
46 "yyyy-MM-ddTHH:mm:ssK",
\r
49 "yyyyMMddTHHmmssFFFFFFFK",
\r
55 "yyyy-MM-dd HH:mm:ss.FFFFFFF", /* NOTE: Non-UTC default (19). */
\r
56 "yyyy-MM-dd HH:mm:ss",
\r
58 "yyyy-MM-ddTHH:mm:ss.FFFFFFF",
\r
60 "yyyy-MM-ddTHH:mm:ss",
\r
63 "yyyyMMddTHHmmssFFFFFFF",
\r
70 /// An UTF-8 Encoding instance, so we can convert strings to and from UTF-8
\r
72 private static Encoding _utf8 = new UTF8Encoding();
\r
74 /// The default DateTime format for this instance
\r
76 internal SQLiteDateFormats _datetimeFormat;
\r
78 /// Initializes the conversion class
\r
80 /// <param name="fmt">The default date/time format to use for this instance</param>
\r
81 internal SqliteConvert(SQLiteDateFormats fmt)
\r
83 _datetimeFormat = fmt;
\r
86 #region UTF-8 Conversion Functions
\r
88 /// Converts a string to a UTF-8 encoded byte array sized to include a null-terminating character.
\r
90 /// <param name="sourceText">The string to convert to UTF-8</param>
\r
91 /// <returns>A byte array containing the converted string plus an extra 0 terminating byte at the end of the array.</returns>
\r
92 public static byte[] ToUTF8(string sourceText)
\r
95 int nlen = _utf8.GetByteCount(sourceText) + 1;
\r
97 byteArray = new byte[nlen];
\r
98 nlen = _utf8.GetBytes(sourceText, 0, sourceText.Length, byteArray, 0);
\r
99 byteArray[nlen] = 0;
\r
105 /// Convert a DateTime to a UTF-8 encoded, zero-terminated byte array.
\r
108 /// This function is a convenience function, which first calls ToString() on the DateTime, and then calls ToUTF8() with the
\r
111 /// <param name="dateTimeValue">The DateTime to convert.</param>
\r
112 /// <returns>The UTF-8 encoded string, including a 0 terminating byte at the end of the array.</returns>
\r
113 public byte[] ToUTF8(DateTime dateTimeValue)
\r
115 return ToUTF8(ToString(dateTimeValue));
\r
119 /// Converts a UTF-8 encoded IntPtr of the specified length into a .NET string
\r
121 /// <param name="nativestring">The pointer to the memory where the UTF-8 string is encoded</param>
\r
122 /// <param name="nativestringlen">The number of bytes to decode</param>
\r
123 /// <returns>A string containing the translated character(s)</returns>
\r
124 public virtual string ToString(IntPtr nativestring, int nativestringlen)
\r
126 return UTF8ToString(nativestring, nativestringlen);
\r
130 /// Converts a UTF-8 encoded IntPtr of the specified length into a .NET string
\r
132 /// <param name="nativestring">The pointer to the memory where the UTF-8 string is encoded</param>
\r
133 /// <param name="nativestringlen">The number of bytes to decode</param>
\r
134 /// <returns>A string containing the translated character(s)</returns>
\r
135 public static string UTF8ToString(IntPtr nativestring, int nativestringlen)
\r
137 if (nativestringlen == 0 || nativestring == IntPtr.Zero) return "";
\r
138 if (nativestringlen == -1)
\r
143 } while (Marshal.ReadByte(nativestring, nativestringlen) != 0);
\r
146 byte[] byteArray = new byte[nativestringlen];
\r
148 Marshal.Copy(nativestring, byteArray, 0, nativestringlen);
\r
150 return _utf8.GetString(byteArray, 0, nativestringlen);
\r
156 #region DateTime Conversion Functions
\r
158 /// Converts a string into a DateTime, using the current DateTimeFormat specified for the connection when it was opened.
\r
161 /// Acceptable ISO8601 DateTime formats are:
\r
162 /// yyyy-MM-dd HH:mm:ss
\r
164 /// yyyyMMddTHHmmssfffffff
\r
171 /// <param name="dateText">The string containing either a Tick value, a JulianDay double, or an ISO8601-format string</param>
\r
172 /// <returns>A DateTime value</returns>
\r
173 public DateTime ToDateTime(string dateText)
\r
175 switch (_datetimeFormat)
\r
177 case SQLiteDateFormats.Ticks:
\r
178 return new DateTime(Convert.ToInt64(dateText, CultureInfo.InvariantCulture));
\r
179 case SQLiteDateFormats.JulianDay:
\r
180 return ToDateTime(Convert.ToDouble(dateText, CultureInfo.InvariantCulture));
\r
181 case SQLiteDateFormats.UnixEpoch:
\r
182 return UnixEpoch.AddSeconds(Convert.ToInt32(dateText, CultureInfo.InvariantCulture));
\r
184 return DateTime.ParseExact(dateText, _datetimeFormats, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None);
\r
189 /// Converts a julianday value into a DateTime
\r
191 /// <param name="julianDay">The value to convert</param>
\r
192 /// <returns>A .NET DateTime</returns>
\r
193 public DateTime ToDateTime(double julianDay)
\r
195 return DateTime.FromOADate(julianDay - 2415018.5);
\r
199 /// Converts a DateTime struct to a JulianDay double
\r
201 /// <param name="value">The DateTime to convert</param>
\r
202 /// <returns>The JulianDay value the Datetime represents</returns>
\r
203 public double ToJulianDay(DateTime value)
\r
205 return value.ToOADate() + 2415018.5;
\r
209 /// Converts a DateTime to a string value, using the current DateTimeFormat specified for the connection when it was opened.
\r
211 /// <param name="dateValue">The DateTime value to convert</param>
\r
212 /// <returns>Either a string consisting of the tick count for DateTimeFormat.Ticks, a JulianDay double, or a date/time in ISO8601 format.</returns>
\r
213 public string ToString(DateTime dateValue)
\r
215 switch (_datetimeFormat)
\r
217 case SQLiteDateFormats.Ticks:
\r
218 return dateValue.Ticks.ToString(CultureInfo.InvariantCulture);
\r
219 case SQLiteDateFormats.JulianDay:
\r
220 return ToJulianDay(dateValue).ToString(CultureInfo.InvariantCulture);
\r
221 case SQLiteDateFormats.UnixEpoch:
\r
222 return ((long)(dateValue.Subtract(UnixEpoch).Ticks / TimeSpan.TicksPerSecond)).ToString();
\r
224 return dateValue.ToString(_datetimeFormats[5], CultureInfo.InvariantCulture);
\r
229 /// Internal function to convert a UTF-8 encoded IntPtr of the specified length to a DateTime.
\r
232 /// This is a convenience function, which first calls ToString() on the IntPtr to convert it to a string, then calls
\r
233 /// ToDateTime() on the string to return a DateTime.
\r
235 /// <param name="ptr">A pointer to the UTF-8 encoded string</param>
\r
236 /// <param name="len">The length in bytes of the string</param>
\r
237 /// <returns>The parsed DateTime value</returns>
\r
238 internal DateTime ToDateTime(IntPtr ptr, int len)
\r
240 return ToDateTime(ToString(ptr, len));
\r
246 /// Smart method of splitting a string. Skips quoted elements, removes the quotes.
\r
249 /// This split function works somewhat like the String.Split() function in that it breaks apart a string into
\r
250 /// pieces and returns the pieces as an array. The primary differences are:
\r
251 /// <list type="bullet">
\r
252 /// <item><description>Only one character can be provided as a separator character</description></item>
\r
253 /// <item><description>Quoted text inside the string is skipped over when searching for the separator, and the quotes are removed.</description></item>
\r
255 /// Thus, if splitting the following string looking for a comma:<br/>
\r
256 /// One,Two, "Three, Four", Five<br/>
\r
258 /// The resulting array would contain<br/>
\r
261 /// [2] Three, Four<br/>
\r
264 /// Note that the leading and trailing spaces were removed from each item during the split.
\r
266 /// <param name="source">Source string to split apart</param>
\r
267 /// <param name="separator">Separator character</param>
\r
268 /// <returns>A string array of the split up elements</returns>
\r
269 public static string[] Split(string source, char separator)
\r
271 char[] toks = new char[2] { '\"', separator };
\r
272 char[] quot = new char[1] { '\"' };
\r
274 List<string> ls = new List<string>();
\r
277 while (source.Length > 0)
\r
279 n = source.IndexOfAny(toks, n);
\r
280 if (n == -1) break;
\r
281 if (source[n] == toks[0])
\r
283 //source = source.Remove(n, 1);
\r
284 n = source.IndexOfAny(quot, n + 1);
\r
287 //source = "\"" + source;
\r
291 //source = source.Remove(n, 1);
\r
295 s = source.Substring(0, n).Trim();
\r
296 if (s.Length > 1 && s[0] == quot[0] && s[s.Length - 1] == s[0])
\r
297 s = s.Substring(1, s.Length - 2);
\r
299 source = source.Substring(n + 1).Trim();
\r
300 if (s.Length > 0) ls.Add(s);
\r
304 if (source.Length > 0)
\r
307 if (s.Length > 1 && s[0] == quot[0] && s[s.Length - 1] == s[0])
\r
308 s = s.Substring(1, s.Length - 2);
\r
312 string[] ar = new string[ls.Count];
\r
319 /// Convert a value to true or false.
\r
321 /// <param name="source">A string or number representing true or false</param>
\r
322 /// <returns></returns>
\r
323 public static bool ToBoolean(object source)
\r
325 if (source is bool) return (bool)source;
\r
327 return ToBoolean(source.ToString());
\r
331 /// Convert a string to true or false.
\r
333 /// <param name="source">A string representing true or false</param>
\r
334 /// <returns></returns>
\r
336 /// "yes", "no", "y", "n", "0", "1", "on", "off" as well as Boolean.FalseString and Boolean.TrueString will all be
\r
337 /// converted to a proper boolean value.
\r
339 public static bool ToBoolean(string source)
\r
341 if (String.Compare(source, bool.TrueString, StringComparison.OrdinalIgnoreCase) == 0) return true;
\r
342 else if (String.Compare(source, bool.FalseString, StringComparison.OrdinalIgnoreCase) == 0) return false;
\r
344 switch(source.ToLower())
\r
357 throw new ArgumentException("source");
\r
361 #region Type Conversions
\r
363 /// Determines the data type of a column in a statement
\r
365 /// <param name="stmt">The statement to retrieve information for</param>
\r
366 /// <param name="i">The column to retrieve type information on</param>
\r
367 /// <param name="typ">The SQLiteType to receive the affinity for the given column</param>
\r
368 internal static void ColumnToType(SqliteStatement stmt, int i, SQLiteType typ)
\r
370 typ.Type = TypeNameToDbType(stmt._sql.ColumnType(stmt, i, out typ.Affinity));
\r
374 /// Converts a SQLiteType to a .NET Type object
\r
376 /// <param name="t">The SQLiteType to convert</param>
\r
377 /// <returns>Returns a .NET Type object</returns>
\r
378 internal static Type SQLiteTypeToType(SQLiteType t)
\r
380 if (t.Type == DbType.Object)
\r
381 return _affinitytotype[(int)t.Affinity];
\r
383 return SqliteConvert.DbTypeToType(t.Type);
\r
386 private static Type[] _affinitytotype = {
\r
398 /// For a given intrinsic type, return a DbType
\r
400 /// <param name="typ">The native type to convert</param>
\r
401 /// <returns>The corresponding (closest match) DbType</returns>
\r
402 internal static DbType TypeToDbType(Type typ)
\r
404 TypeCode tc = Type.GetTypeCode(typ);
\r
405 if (tc == TypeCode.Object)
\r
407 if (typ == typeof(byte[])) return DbType.Binary;
\r
408 if (typ == typeof(Guid)) return DbType.Guid;
\r
409 return DbType.String;
\r
411 return _typetodbtype[(int)tc];
\r
414 private static DbType[] _typetodbtype = {
\r
426 DbType.Int64, // 11
\r
437 /// Returns the ColumnSize for the given DbType
\r
439 /// <param name="typ">The DbType to get the size of</param>
\r
440 /// <returns></returns>
\r
441 internal static int DbTypeToColumnSize(DbType typ)
\r
443 return _dbtypetocolumnsize[(int)typ];
\r
446 private static int[] _dbtypetocolumnsize = {
\r
472 2147483647, // 25 (Xml)
\r
475 internal static object DbTypeToNumericPrecision(DbType typ)
\r
477 return _dbtypetonumericprecision[(int)typ];
\r
480 private static object[] _dbtypetonumericprecision = {
\r
508 internal static object DbTypeToNumericScale(DbType typ)
\r
510 return _dbtypetonumericscale[(int)typ];
\r
513 private static object[] _dbtypetonumericscale = {
\r
541 internal static string DbTypeToTypeName(DbType typ)
\r
543 for (int n = 0; n < _dbtypeNames.Length; n++)
\r
545 if (_dbtypeNames[n].dataType == typ)
\r
546 return _dbtypeNames[n].typeName;
\r
549 return String.Empty;
\r
552 private static SQLiteTypeNames[] _dbtypeNames = {
\r
553 new SQLiteTypeNames("INTEGER", DbType.Int64),
\r
554 new SQLiteTypeNames("TINYINT", DbType.Byte),
\r
555 new SQLiteTypeNames("INT", DbType.Int32),
\r
556 new SQLiteTypeNames("VARCHAR", DbType.AnsiString),
\r
557 new SQLiteTypeNames("NVARCHAR", DbType.String),
\r
558 new SQLiteTypeNames("CHAR", DbType.AnsiStringFixedLength),
\r
559 new SQLiteTypeNames("NCHAR", DbType.StringFixedLength),
\r
560 new SQLiteTypeNames("FLOAT", DbType.Double),
\r
561 new SQLiteTypeNames("REAL", DbType.Single),
\r
562 new SQLiteTypeNames("BIT", DbType.Boolean),
\r
563 new SQLiteTypeNames("DECIMAL", DbType.Decimal),
\r
564 new SQLiteTypeNames("DATETIME", DbType.DateTime),
\r
565 new SQLiteTypeNames("BLOB", DbType.Binary),
\r
566 new SQLiteTypeNames("UNIQUEIDENTIFIER", DbType.Guid),
\r
567 new SQLiteTypeNames("SMALLINT", DbType.Int16),
\r
570 /// Convert a DbType to a Type
\r
572 /// <param name="typ">The DbType to convert from</param>
\r
573 /// <returns>The closest-match .NET type</returns>
\r
574 internal static Type DbTypeToType(DbType typ)
\r
576 return _dbtypeToType[(int)typ];
\r
579 private static Type[] _dbtypeToType = {
\r
580 typeof(string), // 0
\r
581 typeof(byte[]), // 1
\r
584 typeof(decimal), // 4
\r
585 typeof(DateTime), // 5
\r
586 typeof(DateTime), // 6
\r
587 typeof(decimal), // 7
\r
588 typeof(double), // 8
\r
605 typeof(string), // 25 (Xml)
\r
609 /// For a given type, return the closest-match SQLite TypeAffinity, which only understands a very limited subset of types.
\r
611 /// <param name="typ">The type to evaluate</param>
\r
612 /// <returns>The SQLite type affinity for that type.</returns>
\r
613 internal static TypeAffinity TypeToAffinity(Type typ)
\r
615 TypeCode tc = Type.GetTypeCode(typ);
\r
616 if (tc == TypeCode.Object)
\r
618 if (typ == typeof(byte[]) || typ == typeof(Guid))
\r
619 return TypeAffinity.Blob;
\r
621 return TypeAffinity.Text;
\r
623 return _typecodeAffinities[(int)tc];
\r
626 private static TypeAffinity[] _typecodeAffinities = {
\r
630 TypeAffinity.Int64,
\r
631 TypeAffinity.Int64,
\r
632 TypeAffinity.Int64,
\r
633 TypeAffinity.Int64,
\r
634 TypeAffinity.Int64, // 7
\r
635 TypeAffinity.Int64,
\r
636 TypeAffinity.Int64,
\r
637 TypeAffinity.Int64,
\r
638 TypeAffinity.Int64, // 11
\r
639 TypeAffinity.Int64,
\r
640 TypeAffinity.Double,
\r
641 TypeAffinity.Double,
\r
642 TypeAffinity.Double,
\r
643 TypeAffinity.DateTime,
\r
649 /// For a given type name, return a closest-match .NET type
\r
651 /// <param name="Name">The name of the type to match</param>
\r
652 /// <returns>The .NET DBType the text evaluates to.</returns>
\r
653 internal static DbType TypeNameToDbType(string Name)
\r
655 if (String.IsNullOrEmpty(Name)) return DbType.Object;
\r
657 string nameToCompare = Name;
\r
658 int parenthesis = nameToCompare.IndexOf ('(');
\r
659 if (parenthesis > 0)
\r
660 nameToCompare = nameToCompare.Substring (0, parenthesis);
\r
662 for (int n = 0; n < _typeNames.Length; n++)
\r
664 if (string.Compare(nameToCompare, _typeNames[n].typeName, true, CultureInfo.InvariantCulture) == 0)
\r
665 return _typeNames[n].dataType;
\r
668 /* http://www.sqlite.org/datatype3.html
\r
669 * 2.1 Determination Of Column Affinity
\r
670 * The affinity of a column is determined by the declared type of the column, according to the following rules in the order shown:
\r
671 * 1. If the declared type contains the string "INT" then it is assigned INTEGER affinity.
\r
672 * 2. If the declared type of the column contains any of the strings "CHAR", "CLOB", or "TEXT" then that column has TEXT affinity. Notice that the type VARCHAR contains the string "CHAR" and is thus assigned TEXT affinity.
\r
673 * 3. If the declared type for a column contains the string "BLOB" or if no type is specified then the column has affinity NONE.
\r
674 * 4. If the declared type for a column contains any of the strings "REAL", "FLOA", or "DOUB" then the column has REAL affinity.
\r
675 * 5. Otherwise, the affinity is NUMERIC.
\r
678 if (Name.IndexOf ("INT", StringComparison.OrdinalIgnoreCase) >= 0) {
\r
679 return DbType.Int64;
\r
680 } else if (Name.IndexOf ("CHAR", StringComparison.OrdinalIgnoreCase) >= 0
\r
681 || Name.IndexOf ("CLOB", StringComparison.OrdinalIgnoreCase) >= 0
\r
682 || Name.IndexOf ("TEXT", StringComparison.OrdinalIgnoreCase) >= 0) {
\r
683 return DbType.String;
\r
684 } else if (Name.IndexOf ("BLOB", StringComparison.OrdinalIgnoreCase) >= 0 /* || Name == string.Empty // handled at the top of this functin */) {
\r
685 return DbType.Object;
\r
686 } else if (Name.IndexOf ("REAL", StringComparison.OrdinalIgnoreCase) >= 0
\r
687 || Name.IndexOf ("FLOA", StringComparison.OrdinalIgnoreCase) >= 0
\r
688 || Name.IndexOf ("DOUB", StringComparison.OrdinalIgnoreCase) >= 0) {
\r
689 return DbType.Double;
\r
691 return DbType.Object; // This can be anything, so use Object instead of Decimal (which we use otherwise where the type affinity is NUMERIC)
\r
696 private static SQLiteTypeNames[] _typeNames = {
\r
697 new SQLiteTypeNames("COUNTER", DbType.Int64),
\r
698 new SQLiteTypeNames("AUTOINCREMENT", DbType.Int64),
\r
699 new SQLiteTypeNames("IDENTITY", DbType.Int64),
\r
700 new SQLiteTypeNames("LONGTEXT", DbType.String),
\r
701 new SQLiteTypeNames("LONGCHAR", DbType.String),
\r
702 new SQLiteTypeNames("LONGVARCHAR", DbType.String),
\r
703 new SQLiteTypeNames("LONG", DbType.Int64),
\r
704 new SQLiteTypeNames("TINYINT", DbType.Byte),
\r
705 new SQLiteTypeNames("INTEGER", DbType.Int64),
\r
706 new SQLiteTypeNames("INT", DbType.Int32),
\r
707 new SQLiteTypeNames("VARCHAR", DbType.String),
\r
708 new SQLiteTypeNames("NVARCHAR", DbType.String),
\r
709 new SQLiteTypeNames("CHAR", DbType.String),
\r
710 new SQLiteTypeNames("NCHAR", DbType.String),
\r
711 new SQLiteTypeNames("TEXT", DbType.String),
\r
712 new SQLiteTypeNames("NTEXT", DbType.String),
\r
713 new SQLiteTypeNames("STRING", DbType.String),
\r
714 new SQLiteTypeNames("DOUBLE", DbType.Double),
\r
715 new SQLiteTypeNames("FLOAT", DbType.Double),
\r
716 new SQLiteTypeNames("REAL", DbType.Single),
\r
717 new SQLiteTypeNames("BIT", DbType.Boolean),
\r
718 new SQLiteTypeNames("YESNO", DbType.Boolean),
\r
719 new SQLiteTypeNames("LOGICAL", DbType.Boolean),
\r
720 new SQLiteTypeNames("BOOL", DbType.Boolean),
\r
721 new SQLiteTypeNames("BOOLEAN", DbType.Boolean),
\r
722 new SQLiteTypeNames("NUMERIC", DbType.Decimal),
\r
723 new SQLiteTypeNames("DECIMAL", DbType.Decimal),
\r
724 new SQLiteTypeNames("MONEY", DbType.Decimal),
\r
725 new SQLiteTypeNames("CURRENCY", DbType.Decimal),
\r
726 new SQLiteTypeNames("TIME", DbType.DateTime),
\r
727 new SQLiteTypeNames("DATE", DbType.DateTime),
\r
728 new SQLiteTypeNames("SMALLDATE", DbType.DateTime),
\r
729 new SQLiteTypeNames("BLOB", DbType.Binary),
\r
730 new SQLiteTypeNames("BINARY", DbType.Binary),
\r
731 new SQLiteTypeNames("VARBINARY", DbType.Binary),
\r
732 new SQLiteTypeNames("IMAGE", DbType.Binary),
\r
733 new SQLiteTypeNames("GENERAL", DbType.Binary),
\r
734 new SQLiteTypeNames("OLEOBJECT", DbType.Binary),
\r
735 new SQLiteTypeNames("GUID", DbType.Guid),
\r
736 new SQLiteTypeNames("GUIDBLOB", DbType.Guid),
\r
737 new SQLiteTypeNames("UNIQUEIDENTIFIER", DbType.Guid),
\r
738 new SQLiteTypeNames("MEMO", DbType.String),
\r
739 new SQLiteTypeNames("NOTE", DbType.String),
\r
740 new SQLiteTypeNames("SMALLINT", DbType.Int16),
\r
741 new SQLiteTypeNames("BIGINT", DbType.Int64),
\r
742 new SQLiteTypeNames("TIMESTAMP", DbType.DateTime),
\r
743 new SQLiteTypeNames("DATETIME", DbType.DateTime),
\r
748 /// SQLite has very limited types, and is inherently text-based. The first 5 types below represent the sum of all types SQLite
\r
749 /// understands. The DateTime extension to the spec is for internal use only.
\r
751 public enum TypeAffinity
\r
758 /// All integers in SQLite default to Int64
\r
762 /// All floating point numbers in SQLite default to double
\r
766 /// The default data type of SQLite is text
\r
770 /// Typically blob types are only seen when returned from a function
\r
774 /// Null types can be returned from functions
\r
778 /// Used internally by this provider
\r
782 /// Used internally
\r
788 /// This implementation of SQLite for ADO.NET can process date/time fields in databases in only one of three formats. Ticks, ISO8601
\r
792 /// ISO8601 is more compatible, readable, fully-processable, but less accurate as it doesn't provide time down to fractions of a second.
\r
793 /// JulianDay is the numeric format the SQLite uses internally and is arguably the most compatible with 3rd party tools. It is
\r
794 /// not readable as text without post-processing.
\r
795 /// Ticks less compatible with 3rd party tools that query the database, and renders the DateTime field unreadable as text without post-processing.
\r
797 /// The preferred order of choosing a datetime format is JulianDay, ISO8601, and then Ticks. Ticks is mainly present for legacy
\r
800 public enum SQLiteDateFormats
\r
803 /// Using ticks is not recommended and is not well supported with LINQ.
\r
807 /// The default format for this provider.
\r
811 /// JulianDay format, which is what SQLite uses internally
\r
815 /// The whole number of seconds since the Unix epoch (January 1, 1970).
\r
821 /// This enum determines how SQLite treats its journal file.
\r
824 /// By default SQLite will create and delete the journal file when needed during a transaction.
\r
825 /// However, for some computers running certain filesystem monitoring tools, the rapid
\r
826 /// creation and deletion of the journal file can cause those programs to fail, or to interfere with SQLite.
\r
828 /// If a program or virus scanner is interfering with SQLite's journal file, you may receive errors like "unable to open database file"
\r
829 /// when starting a transaction. If this is happening, you may want to change the default journal mode to Persist.
\r
831 public enum SQLiteJournalModeEnum
\r
834 /// The default mode, this causes SQLite to create and destroy the journal file as-needed.
\r
838 /// When this is set, SQLite will keep the journal file even after a transaction has completed. It's contents will be erased,
\r
839 /// and the journal re-used as often as needed. If it is deleted, it will be recreated the next time it is needed.
\r
843 /// This option disables the rollback journal entirely. Interrupted transactions or a program crash can cause database
\r
844 /// corruption in this mode!
\r
850 /// Struct used internally to determine the datatype of a column in a resultset
\r
852 internal class SQLiteType
\r
855 /// The DbType of the column, or DbType.Object if it cannot be determined
\r
857 internal DbType Type;
\r
859 /// The affinity of a column, used for expressions or when Type is DbType.Object
\r
861 internal TypeAffinity Affinity;
\r
864 internal struct SQLiteTypeNames
\r
866 internal SQLiteTypeNames(string newtypeName, DbType newdataType)
\r
868 typeName = newtypeName;
\r
869 dataType = newdataType;
\r
872 internal string typeName;
\r
873 internal DbType dataType;
\r