System.Data.SQLite

Check-in [e755582cbc]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Clarify and improve type conversion arrays in the SQLiteConvert class.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: e755582cbc327ce1346ac5d0d86f0563f4b498fb
User & Date: mistachkin 2013-01-31 07:38:10.987
Context
2013-01-31
07:39
Merge fix for ticket [c010fa6584] to trunk. check-in: c55ee9c616 user: mistachkin tags: trunk
07:38
Clarify and improve type conversion arrays in the SQLiteConvert class. check-in: e755582cbc user: mistachkin tags: trunk
03:24
Centralize building of the column type name map. Remove AUTOINCREMENT from the column type name map. Add BIGUINT, SMALLUINT, TINYSINT, and ULONG to the column type name map. check-in: c7b39f9c3b user: mistachkin tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to System.Data.SQLite/SQLiteConvert.cs.
1
2
3
4
5
6
7
8
9
10
11
/********************************************************
 * ADO.NET 2.0 Data Provider for SQLite Version 3.X
 * Written by Robert Simpson (robert@blackcastlesoft.com)
 * 
 * Released to the public domain, use at your own risk!
 ********************************************************/

namespace System.Data.SQLite
{
  using System;




|







1
2
3
4
5
6
7
8
9
10
11
/********************************************************
 * ADO.NET 2.0 Data Provider for SQLite Version 3.X
 * Written by Robert Simpson (robert@blackcastlesoft.com)
 *
 * Released to the public domain, use at your own risk!
 ********************************************************/

namespace System.Data.SQLite
{
  using System;

168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
        do
        {
          nativestringlen++;
        } while (Marshal.ReadByte(nativestring, nativestringlen) != 0);
      }

      byte[] byteArray = new byte[nativestringlen];
      
      Marshal.Copy(nativestring, byteArray, 0, nativestringlen);

      return _utf8.GetString(byteArray, 0, nativestringlen);
    }


    #endregion







|







168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
        do
        {
          nativestringlen++;
        } while (Marshal.ReadByte(nativestring, nativestringlen) != 0);
      }

      byte[] byteArray = new byte[nativestringlen];

      Marshal.Copy(nativestring, byteArray, 0, nativestringlen);

      return _utf8.GetString(byteArray, 0, nativestringlen);
    }


    #endregion
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692

693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725

726
727
728
729
730
731
732
733
734
735
      if (t.Type == DbType.Object)
        return _affinitytotype[(int)t.Affinity];
      else
        return SQLiteConvert.DbTypeToType(t.Type);
    }

    private static Type[] _affinitytotype = {
      typeof(object),
      typeof(Int64),
      typeof(Double),
      typeof(string),
      typeof(byte[]),
      typeof(object),
      typeof(DateTime),
      typeof(object)
    };

    /// <summary>
    /// For a given intrinsic type, return a DbType
    /// </summary>
    /// <param name="typ">The native type to convert</param>
    /// <returns>The corresponding (closest match) DbType</returns>
    internal static DbType TypeToDbType(Type typ)
    {
      TypeCode tc = Type.GetTypeCode(typ);
      if (tc == TypeCode.Object)
      {
        if (typ == typeof(byte[])) return DbType.Binary;
        if (typ == typeof(Guid)) return DbType.Guid;
        return DbType.String;
      }
      return _typetodbtype[(int)tc];
    }

    private static DbType[] _typetodbtype = {
      DbType.Object,
      DbType.Binary,
      DbType.Object,
      DbType.Boolean,
      DbType.SByte,
      DbType.SByte,
      DbType.Byte,
      DbType.Int16, // 7
      DbType.UInt16,
      DbType.Int32,
      DbType.UInt32,
      DbType.Int64, // 11
      DbType.UInt64,
      DbType.Single,
      DbType.Double,
      DbType.Decimal,
      DbType.DateTime,
      DbType.Object,
      DbType.String,
    };

    /// <summary>
    /// Returns the ColumnSize for the given DbType
    /// </summary>
    /// <param name="typ">The DbType to get the size of</param>
    /// <returns></returns>
    internal static int DbTypeToColumnSize(DbType typ)
    {
      return _dbtypetocolumnsize[(int)typ];
    }

    private static int[] _dbtypetocolumnsize = {
      2147483647,   // 0
      2147483647,   // 1
      1,     // 2
      1,     // 3
      8,  // 4
      8, // 5
      8, // 6
      8,  // 7
      8,   // 8
      16,     // 9
      2,
      4,
      8,
      2147483647,
      1,
      4,
      2147483647,
      8,
      2,
      4,
      8,
      8,
      2147483647,
      2147483647,
      2147483647,
      2147483647,   // 25 (Xml)
    };

    internal static object DbTypeToNumericPrecision(DbType typ)
    {
      return _dbtypetonumericprecision[(int)typ];
    }

    private static object[] _dbtypetonumericprecision = {
      DBNull.Value, // 0
      DBNull.Value, // 1
      3,
      DBNull.Value,
      19,
      DBNull.Value, // 5
      DBNull.Value, // 6
      53,
      53,
      DBNull.Value,
      5,
      10,
      19,
      DBNull.Value,
      3,
      24,
      DBNull.Value,
      DBNull.Value,
      5,
      10,
      19,
      53,

      DBNull.Value,
      DBNull.Value,
      DBNull.Value
    };

    internal static object DbTypeToNumericScale(DbType typ)
    {
      return _dbtypetonumericscale[(int)typ];
    }

    private static object[] _dbtypetonumericscale = {
      DBNull.Value, // 0
      DBNull.Value, // 1
      0,
      DBNull.Value,
      4,
      DBNull.Value, // 5
      DBNull.Value, // 6
      DBNull.Value,
      DBNull.Value,
      DBNull.Value,
      0,
      0,
      0,
      DBNull.Value,
      0,
      DBNull.Value,
      DBNull.Value,
      DBNull.Value,
      0,
      0,
      0,
      0,

      DBNull.Value,
      DBNull.Value,
      DBNull.Value
    };

    internal static string DbTypeToTypeName(DbType typ)
    {
      for (int n = 0; n < _dbtypeNames.Length; n++)
      {
        if (_dbtypeNames[n].dataType == typ)







|
|
|
|
|
|
|
|




















|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|













|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|








|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
|








|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
|







570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
      if (t.Type == DbType.Object)
        return _affinitytotype[(int)t.Affinity];
      else
        return SQLiteConvert.DbTypeToType(t.Type);
    }

    private static Type[] _affinitytotype = {
      typeof(object),   // Uninitialized (0)
      typeof(Int64),    // Int64 (1)
      typeof(Double),   // Double (2)
      typeof(string),   // Text (3)
      typeof(byte[]),   // Blob (4)
      typeof(DBNull),   // Null (5)
      typeof(DateTime), // DateTime (10)
      typeof(object)    // None (11)
    };

    /// <summary>
    /// For a given intrinsic type, return a DbType
    /// </summary>
    /// <param name="typ">The native type to convert</param>
    /// <returns>The corresponding (closest match) DbType</returns>
    internal static DbType TypeToDbType(Type typ)
    {
      TypeCode tc = Type.GetTypeCode(typ);
      if (tc == TypeCode.Object)
      {
        if (typ == typeof(byte[])) return DbType.Binary;
        if (typ == typeof(Guid)) return DbType.Guid;
        return DbType.String;
      }
      return _typetodbtype[(int)tc];
    }

    private static DbType[] _typetodbtype = {
      DbType.Object,   // Empty (0)
      DbType.Binary,   // Object (1)
      DbType.Object,   // DBNull (2)
      DbType.Boolean,  // Boolean (3)
      DbType.SByte,    // Char (4)
      DbType.SByte,    // SByte (5)
      DbType.Byte,     // Byte (6)
      DbType.Int16,    // Int16 (7)
      DbType.UInt16,   // UInt16 (8)
      DbType.Int32,    // Int32 (9)
      DbType.UInt32,   // UInt32 (10)
      DbType.Int64,    // Int64 (11)
      DbType.UInt64,   // UInt64 (12)
      DbType.Single,   // Single (13)
      DbType.Double,   // Double (14)
      DbType.Decimal,  // Decimal (15)
      DbType.DateTime, // DateTime (16)
      DbType.Object,   // ?? (17)
      DbType.String    // String (18)
    };

    /// <summary>
    /// Returns the ColumnSize for the given DbType
    /// </summary>
    /// <param name="typ">The DbType to get the size of</param>
    /// <returns></returns>
    internal static int DbTypeToColumnSize(DbType typ)
    {
      return _dbtypetocolumnsize[(int)typ];
    }

    private static int[] _dbtypetocolumnsize = {
      int.MaxValue, // AnsiString (0)
      int.MaxValue, // Binary (1)
      1,            // Byte (2)
      1,            // Boolean (3)
      8,            // Currency (4)
      8,            // Date (5)
      8,            // DateTime (6)
      8,            // Decimal (7)
      8,            // Double (8)
      16,           // Guid (9)
      2,            // Int16 (10)
      4,            // Int32 (11)
      8,            // Int64 (12)
      int.MaxValue, // Object (13)
      1,            // SByte (14)
      4,            // Single (15)
      int.MaxValue, // String (16)
      8,            // Time (17)
      2,            // UInt16 (18)
      4,            // UInt32 (19)
      8,            // UInt64 (20)
      8,            // VarNumeric (21)
      int.MaxValue, // AnsiStringFixedLength (22)
      int.MaxValue, // StringFixedLength (23)
      int.MaxValue, // ?? (24)
      int.MaxValue  // Xml (25)
    };

    internal static object DbTypeToNumericPrecision(DbType typ)
    {
      return _dbtypetonumericprecision[(int)typ];
    }

    private static object[] _dbtypetonumericprecision = {
      DBNull.Value, // AnsiString (0)
      DBNull.Value, // Binary (1)
      3,            // Byte (2)
      DBNull.Value, // Boolean (3)
      19,           // Currency (4)
      DBNull.Value, // Date (5)
      DBNull.Value, // DateTime (6)
      53,           // Decimal (7)
      53,           // Double (8)
      DBNull.Value, // Guid (9)
      5,            // Int16 (10)
      10,           // Int32 (11)
      19,           // Int64 (12)
      DBNull.Value, // Object (13)
      3,            // SByte (14)
      24,           // Single (15)
      DBNull.Value, // String (16)
      DBNull.Value, // Time (17)
      5,            // UInt16 (18)
      10,           // UInt32 (19)
      19,           // UInt64 (20)
      53,           // VarNumeric (21)
      DBNull.Value, // AnsiStringFixedLength (22)
      DBNull.Value, // StringFixedLength (23)
      DBNull.Value, // ?? (24)
      DBNull.Value  // Xml (25)
    };

    internal static object DbTypeToNumericScale(DbType typ)
    {
      return _dbtypetonumericscale[(int)typ];
    }

    private static object[] _dbtypetonumericscale = {
      DBNull.Value, // AnsiString (0)
      DBNull.Value, // Binary (1)
      0,            // Byte (2)
      DBNull.Value, // Boolean (3)
      4,            // Currency (4)
      DBNull.Value, // Date (5)
      DBNull.Value, // DateTime (6)
      DBNull.Value, // Decimal (7)
      DBNull.Value, // Double (8)
      DBNull.Value, // Guid (9)
      0,            // Int16 (10)
      0,            // Int32 (11)
      0,            // Int64 (12)
      DBNull.Value, // Object (13)
      0,            // SByte (14)
      DBNull.Value, // Single (15)
      DBNull.Value, // String (16)
      DBNull.Value, // Time (17)
      0,            // UInt16 (18)
      0,            // UInt32 (19)
      0,            // UInt64 (20)
      0,            // VarNumeric (21)
      DBNull.Value, // AnsiStringFixedLength (22)
      DBNull.Value, // StringFixedLength (23)
      DBNull.Value, // ?? (24)
      DBNull.Value  // Xml (25)
    };

    internal static string DbTypeToTypeName(DbType typ)
    {
      for (int n = 0; n < _dbtypeNames.Length; n++)
      {
        if (_dbtypeNames[n].dataType == typ)
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
    /// <returns>The closest-match .NET type</returns>
    internal static Type DbTypeToType(DbType typ)
    {
      return _dbtypeToType[(int)typ];
    }

    private static Type[] _dbtypeToType = {
      typeof(string),   // 0
      typeof(byte[]),   // 1
      typeof(byte),     // 2
      typeof(bool),     // 3
      typeof(decimal),  // 4
      typeof(DateTime), // 5
      typeof(DateTime), // 6
      typeof(decimal),  // 7
      typeof(double),   // 8
      typeof(Guid),     // 9
      typeof(Int16),
      typeof(Int32),
      typeof(Int64),
      typeof(object),
      typeof(sbyte),
      typeof(float),
      typeof(string),
      typeof(DateTime),
      typeof(UInt16),
      typeof(UInt32),
      typeof(UInt64),
      typeof(double),
      typeof(string),
      typeof(string),
      typeof(string),
      typeof(string),   // 25 (Xml)
    };

    /// <summary>
    /// For a given type, return the closest-match SQLite TypeAffinity, which only understands a very limited subset of types.
    /// </summary>
    /// <param name="typ">The type to evaluate</param>
    /// <returns>The SQLite type affinity for that type.</returns>







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
    /// <returns>The closest-match .NET type</returns>
    internal static Type DbTypeToType(DbType typ)
    {
      return _dbtypeToType[(int)typ];
    }

    private static Type[] _dbtypeToType = {
      typeof(string),   // AnsiString (0)
      typeof(byte[]),   // Binary (1)
      typeof(byte),     // Byte (2)
      typeof(bool),     // Boolean (3)
      typeof(decimal),  // Currency (4)
      typeof(DateTime), // Date (5)
      typeof(DateTime), // DateTime (6)
      typeof(decimal),  // Decimal (7)
      typeof(double),   // Double (8)
      typeof(Guid),     // Guid (9)
      typeof(Int16),    // Int16 (10)
      typeof(Int32),    // Int32 (11)
      typeof(Int64),    // Int64 (12)
      typeof(object),   // Object (13)
      typeof(sbyte),    // SByte (14)
      typeof(float),    // Single (15)
      typeof(string),   // String (16)
      typeof(DateTime), // Time (17)
      typeof(UInt16),   // UInt16 (18)
      typeof(UInt32),   // UInt32 (19)
      typeof(UInt64),   // UInt64 (20)
      typeof(double),   // VarNumeric (21)
      typeof(string),   // AnsiStringFixedLength (22)
      typeof(string),   // StringFixedLength (23)
      typeof(string),   // ?? (24)
      typeof(string),   // Xml (25)
    };

    /// <summary>
    /// For a given type, return the closest-match SQLite TypeAffinity, which only understands a very limited subset of types.
    /// </summary>
    /// <param name="typ">The type to evaluate</param>
    /// <returns>The SQLite type affinity for that type.</returns>
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
        else
          return TypeAffinity.Text;
      }
      return _typecodeAffinities[(int)tc];
    }

    private static TypeAffinity[] _typecodeAffinities = {
      TypeAffinity.Null,
      TypeAffinity.Blob,
      TypeAffinity.Null,
      TypeAffinity.Int64,
      TypeAffinity.Int64,
      TypeAffinity.Int64,
      TypeAffinity.Int64,
      TypeAffinity.Int64, // 7
      TypeAffinity.Int64,
      TypeAffinity.Int64,
      TypeAffinity.Int64,
      TypeAffinity.Int64, // 11
      TypeAffinity.Int64,
      TypeAffinity.Double,
      TypeAffinity.Double,
      TypeAffinity.Double,
      TypeAffinity.DateTime,
      TypeAffinity.Null,
      TypeAffinity.Text,
    };

    /// <summary>
    /// Builds and returns an array containing the database column types
    /// recognized by this provider.
    /// </summary>
    /// <returns>







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
        else
          return TypeAffinity.Text;
      }
      return _typecodeAffinities[(int)tc];
    }

    private static TypeAffinity[] _typecodeAffinities = {
      TypeAffinity.Null,     // Empty (0)
      TypeAffinity.Blob,     // Object (1)
      TypeAffinity.Null,     // DBNull (2)
      TypeAffinity.Int64,    // Boolean (3)
      TypeAffinity.Int64,    // Char (4)
      TypeAffinity.Int64,    // SByte (5)
      TypeAffinity.Int64,    // Byte (6)
      TypeAffinity.Int64,    // Int16 (7)
      TypeAffinity.Int64,    // UInt16 (8)
      TypeAffinity.Int64,    // Int32 (9)
      TypeAffinity.Int64,    // UInt32 (10)
      TypeAffinity.Int64,    // Int64 (11)
      TypeAffinity.Int64,    // UInt64 (12)
      TypeAffinity.Double,   // Single (13)
      TypeAffinity.Double,   // Double (14)
      TypeAffinity.Double,   // Decimal (15)
      TypeAffinity.DateTime, // DateTime (16)
      TypeAffinity.Null,     // ?? (17)
      TypeAffinity.Text      // String (18)
    };

    /// <summary>
    /// Builds and returns an array containing the database column types
    /// recognized by this provider.
    /// </summary>
    /// <returns>
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
  /// and JulianDay.
  /// </summary>
  /// <remarks>
  /// ISO8601 is more compatible, readable, fully-processable, but less accurate as it doesn't provide time down to fractions of a second.
  /// JulianDay is the numeric format the SQLite uses internally and is arguably the most compatible with 3rd party tools.  It is
  /// not readable as text without post-processing.
  /// Ticks less compatible with 3rd party tools that query the database, and renders the DateTime field unreadable as text without post-processing.
  /// 
  /// The preferred order of choosing a datetime format is JulianDay, ISO8601, and then Ticks.  Ticks is mainly present for legacy 
  /// code support.
  /// </remarks>
  public enum SQLiteDateFormats
  {
    /// <summary>
    /// Use the value of DateTime.Ticks.  This value is not recommended and is not well supported with LINQ.
    /// </summary>







|
|







1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
  /// and JulianDay.
  /// </summary>
  /// <remarks>
  /// ISO8601 is more compatible, readable, fully-processable, but less accurate as it doesn't provide time down to fractions of a second.
  /// JulianDay is the numeric format the SQLite uses internally and is arguably the most compatible with 3rd party tools.  It is
  /// not readable as text without post-processing.
  /// Ticks less compatible with 3rd party tools that query the database, and renders the DateTime field unreadable as text without post-processing.
  ///
  /// The preferred order of choosing a datetime format is JulianDay, ISO8601, and then Ticks.  Ticks is mainly present for legacy
  /// code support.
  /// </remarks>
  public enum SQLiteDateFormats
  {
    /// <summary>
    /// Use the value of DateTime.Ticks.  This value is not recommended and is not well supported with LINQ.
    /// </summary>
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
  /// <summary>
  /// This enum determines how SQLite treats its journal file.
  /// </summary>
  /// <remarks>
  /// By default SQLite will create and delete the journal file when needed during a transaction.
  /// However, for some computers running certain filesystem monitoring tools, the rapid
  /// creation and deletion of the journal file can cause those programs to fail, or to interfere with SQLite.
  /// 
  /// If a program or virus scanner is interfering with SQLite's journal file, you may receive errors like "unable to open database file"
  /// when starting a transaction.  If this is happening, you may want to change the default journal mode to Persist.
  /// </remarks>
  public enum SQLiteJournalModeEnum
  {
    /// <summary>
    /// The default mode, this causes SQLite to use the existing journaling mode for the database.







|







1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
  /// <summary>
  /// This enum determines how SQLite treats its journal file.
  /// </summary>
  /// <remarks>
  /// By default SQLite will create and delete the journal file when needed during a transaction.
  /// However, for some computers running certain filesystem monitoring tools, the rapid
  /// creation and deletion of the journal file can cause those programs to fail, or to interfere with SQLite.
  ///
  /// If a program or virus scanner is interfering with SQLite's journal file, you may receive errors like "unable to open database file"
  /// when starting a transaction.  If this is happening, you may want to change the default journal mode to Persist.
  /// </remarks>
  public enum SQLiteJournalModeEnum
  {
    /// <summary>
    /// The default mode, this causes SQLite to use the existing journaling mode for the database.
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297

    public int GetHashCode(
      string value
      )
    {
      //
      // NOTE: The only thing that we must guarantee here, according
      //       to the MSDN documentation for IEqualityComparer, is 
      //       that for two given strings, if Equals return true then 
      //       the two strings must hash to the same value.
      //
      if (value != null)
#if !PLATFORM_COMPACTFRAMEWORK
        return value.ToLowerInvariant().GetHashCode();
#else
        return value.ToLower().GetHashCode();







|
|







1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299

    public int GetHashCode(
      string value
      )
    {
      //
      // NOTE: The only thing that we must guarantee here, according
      //       to the MSDN documentation for IEqualityComparer, is
      //       that for two given strings, if Equals return true then
      //       the two strings must hash to the same value.
      //
      if (value != null)
#if !PLATFORM_COMPACTFRAMEWORK
        return value.ToLowerInvariant().GetHashCode();
#else
        return value.ToLower().GetHashCode();