System.Data.SQLite
Check-in [1fc7a1a94c]
Not logged in

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

Overview
Comment:Experimental changes for better DateTime handling in the LINQ assembly (incomplete, do not use yet).
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | LinqDateTime
Files: files | file ages | folders
SHA1: 1fc7a1a94c531d38a21b6e869f806daea4096dd4
User & Date: mistachkin 2011-09-23 07:20:48
Context
2011-09-23
07:20
Experimental changes for better DateTime handling in the LINQ assembly (incomplete, do not use yet). Closed-Leaf check-in: 1fc7a1a94c user: mistachkin tags: LinqDateTime
2011-09-22
05:39
The NuGet package should support both the .NET Framework 2.0 and 4.0. check-in: a9a0ee70ff user: mistachkin tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to System.Data.SQLite.Linq/Resources/SQLiteProviderServices.ProviderManifest.xml.

686
687
688
689
690
691
692


































693
694
695
696
697
698
699
      <ReturnType Type="Int32" />
      <Parameter Name="date" Type="DateTimeOffset" Mode="In" />
    </Function>
    <Function Name="DAY" BuiltIn="true">
      <ReturnType Type="Int32" />
      <Parameter Name="date" Type="String" Mode="In" />
    </Function>



































    <!-- GETDATE()
            returns: datetime   
        -->
    <Function Name="GETDATE" BuiltIn="true">
      <ReturnType Type="DateTime"/>
    </Function>







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
      <ReturnType Type="Int32" />
      <Parameter Name="date" Type="DateTimeOffset" Mode="In" />
    </Function>
    <Function Name="DAY" BuiltIn="true">
      <ReturnType Type="Int32" />
      <Parameter Name="date" Type="String" Mode="In" />
    </Function>

    <!-- TOLOCALTIME( date )
            date: smalldatetime, datetime
            returns: datetime
        -->
    <Function Name="TOLOCALTIME" BuiltIn="true">
      <ReturnType Type="DateTime" />
      <Parameter Name="date" Type="DateTime" Mode="In" />
    </Function>
    <Function Name="TOLOCALTIME" BuiltIn="true">
      <ReturnType Type="DateTime" />
      <Parameter Name="date" Type="DateTimeOffset" Mode="In" />
    </Function>
    <Function Name="TOLOCALTIME" BuiltIn="true">
      <ReturnType Type="DateTime" />
      <Parameter Name="date" Type="String" Mode="In" />
    </Function>

    <!-- TOUNIVERSALTIME( date )
            date: smalldatetime, datetime
            returns: datetime
        -->
    <Function Name="TOUNIVERSALTIME" BuiltIn="true">
      <ReturnType Type="DateTime" />
      <Parameter Name="date" Type="DateTime" Mode="In" />
    </Function>
    <Function Name="TOUNIVERSALTIME" BuiltIn="true">
      <ReturnType Type="DateTime" />
      <Parameter Name="date" Type="DateTimeOffset" Mode="In" />
    </Function>
    <Function Name="TOUNIVERSALTIME" BuiltIn="true">
      <ReturnType Type="DateTime" />
      <Parameter Name="date" Type="String" Mode="In" />
    </Function>

    <!-- GETDATE()
            returns: datetime   
        -->
    <Function Name="GETDATE" BuiltIn="true">
      <ReturnType Type="DateTime"/>
    </Function>

Changes to System.Data.SQLite.Linq/SQL Generation/SqlGenerator.cs.

314
315
316
317
318
319
320


321
322
323
324
325
326
327
....
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669







2670
2671
2672
2673
2674
2675
2676
2677
2678
....
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690







2691
2692
2693
2694
2695
2696
2697
























































2698
2699
2700
2701
2702
2703
2704
....
2740
2741
2742
2743
2744
2745
2746



2747
2748
2749
2750
2751
2752
2753
....
2756
2757
2758
2759
2760
2761
2762



2763
2764
2765
2766
2767
2768
2769
....
2786
2787
2788
2789
2790
2791
2792



2793
2794
2795
2796
2797
2798
2799
....
2810
2811
2812
2813
2814
2815
2816



2817
2818
2819
2820
2821
2822
2823
....
2846
2847
2848
2849
2850
2851
2852



2853
2854
2855
2856
2857
2858
2859
    {
      Dictionary<string, FunctionHandler> functionHandlers = new Dictionary<string, FunctionHandler>(7, StringComparer.Ordinal);
      functionHandlers.Add("CONCAT", HandleConcatFunction);
      functionHandlers.Add("DATEPART", HandleDatepartDateFunction);
      functionHandlers.Add("DatePart", HandleDatepartDateFunction);
      functionHandlers.Add("GETDATE", HandleGetDateFunction);
      functionHandlers.Add("GETUTCDATE", HandleGetUtcDateFunction);


      return functionHandlers;
    }

    /// <summary>
    /// All special non-aggregate canonical functions and their handlers
    /// </summary>
    /// <returns></returns>
................................................................................
    {
      SqlBuilder result = new SqlBuilder();
      Debug.Assert(e.Arguments.Count == 0, "Canonical getdate function should have no arguments");

      switch (sqlgen._manifest._dateFormat)
      {
        case SQLiteDateFormats.Ticks:
          result.Append("(STRFTIME('%s', 'now') * 10000000 + 621355968000000000)");
          break;
        case SQLiteDateFormats.JulianDay:
          result.Append("CAST(STRFTIME('%J', 'now') AS double)");
          break;







        default:
          result.Append("STRFTIME('%Y-%m-%d %H:%M:%S', 'now')");
          break;
      }

      return result;
    }

    private static ISqlFragment HandleGetUtcDateFunction(SqlGenerator sqlgen, DbFunctionExpression e)
................................................................................
    {
      SqlBuilder result = new SqlBuilder();
      Debug.Assert(e.Arguments.Count == 0, "Canonical getutcdate function should have no arguments");

      switch (sqlgen._manifest._dateFormat)
      {
        case SQLiteDateFormats.Ticks:
          result.Append("(STRFTIME('%s', 'now', 'utc') * 10000000 + 621355968000000000)");
          break;
        case SQLiteDateFormats.JulianDay:
          result.Append("CAST(STRFTIME('%J', 'now', 'utc') AS double)");
          break;







        default:
          result.Append("STRFTIME('%Y-%m-%d %H:%M:%S', 'now', 'utc')");
          break;
      }

      return result;
    }

























































    /// <summary>
    /// Handles special case in which datepart 'type' parameter is present. all the functions
    /// handles here have *only* the 1st parameter as datepart. datepart value is passed along
    /// the QP as string and has to be expanded as TSQL keyword.
    /// </summary>
    /// <param name="sqlgen"></param>
................................................................................
        result.Append("', ");

        switch (sqlgen._manifest._dateFormat)
        {
          case SQLiteDateFormats.Ticks:
            result.Append(String.Format("(({0} - 621355968000000000) / 10000000.0)", e.Arguments[1].Accept(sqlgen)));
            break;



          default:
            result.Append(e.Arguments[1].Accept(sqlgen));
            break;
        }

        result.Append(") AS integer)");
      }
................................................................................
        result.Append("CAST(SUBSTR(STRFTIME('%f', ");

        switch (sqlgen._manifest._dateFormat)
        {
          case SQLiteDateFormats.Ticks:
            result.Append(String.Format("(({0} - 621355968000000000) / 10000000.0)", e.Arguments[1].Accept(sqlgen)));
            break;



          default:
            result.Append(e.Arguments[1].Accept(sqlgen));
            break;
        }

        result.Append("), 4) AS integer)");
      }
................................................................................
      {
        case SQLiteDateFormats.Ticks:
          result.Append(String.Format("(STRFTIME('%s', JULIANDAY({1}) + ({0} / 86400.0)) * 10000000 + 621355968000000000)", e.Arguments[0].Accept(sqlgen), e.Arguments[1].Accept(sqlgen)));
          break;
        case SQLiteDateFormats.JulianDay:
          result.Append(String.Format("CAST(STRFTIME('%J', JULIANDAY({1}) + ({0} / 86400.0)) AS double)", e.Arguments[0].Accept(sqlgen), e.Arguments[1].Accept(sqlgen)));
          break;



        default:
          result.Append(String.Format("STRFTIME('%Y-%m-%d %H:%M:%S', JULIANDAY({1}) + ({0} / 86400.0))", e.Arguments[0].Accept(sqlgen), e.Arguments[1].Accept(sqlgen)));
          break;
      }

      return result;
    }
................................................................................
      Debug.Assert(e.Arguments.Count == 2, "Canonical datepart functions should have exactly two arguments");

      switch (sqlgen._manifest._dateFormat)
      {
        case SQLiteDateFormats.Ticks:
          result.Append(String.Format("CAST((({0} - 621355968000000000) / 10000000.0)  - (({1} - 621355968000000000) / 10000000.0) * 86400.0 AS integer)", e.Arguments[0].Accept(sqlgen), e.Arguments[1].Accept(sqlgen)));
          break;



        default:
          result.Append(String.Format("CAST((JULIANDAY({1}) - JULIANDAY({0})) * 86400.0 AS integer)", e.Arguments[0].Accept(sqlgen), e.Arguments[1].Accept(sqlgen)));
          break;
      }

      return result;
    }
................................................................................
      Debug.Assert(e.Arguments.Count == 1, "Canonical datepart functions should have exactly one argument");

      switch (sqlgen._manifest._dateFormat)
      {
        case SQLiteDateFormats.Ticks:
          result.Append(String.Format("(({0} - 621355968000000000) / 10000000.0)", e.Arguments[0].Accept(sqlgen)));
          break;



        default:
          result.Append(e.Arguments[0].Accept(sqlgen));
          break;
      }

      result.Append(") AS integer)");








>
>







 







|


|

>
>
>
>
>
>
>

|







 







|


|

>
>
>
>
>
>
>

|





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>







 







>
>
>







 







>
>
>







 







>
>
>







 







>
>
>







314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
....
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
....
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
....
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
....
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
....
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
....
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
....
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
    {
      Dictionary<string, FunctionHandler> functionHandlers = new Dictionary<string, FunctionHandler>(7, StringComparer.Ordinal);
      functionHandlers.Add("CONCAT", HandleConcatFunction);
      functionHandlers.Add("DATEPART", HandleDatepartDateFunction);
      functionHandlers.Add("DatePart", HandleDatepartDateFunction);
      functionHandlers.Add("GETDATE", HandleGetDateFunction);
      functionHandlers.Add("GETUTCDATE", HandleGetUtcDateFunction);
      functionHandlers.Add("TOLOCALTIME", HandleToLocalTimeFunction);
      functionHandlers.Add("TOUNIVERSALTIME", HandleToUniversalTimeFunction);
      return functionHandlers;
    }

    /// <summary>
    /// All special non-aggregate canonical functions and their handlers
    /// </summary>
    /// <returns></returns>
................................................................................
    {
      SqlBuilder result = new SqlBuilder();
      Debug.Assert(e.Arguments.Count == 0, "Canonical getdate function should have no arguments");

      switch (sqlgen._manifest._dateFormat)
      {
        case SQLiteDateFormats.Ticks:
          result.Append("(STRFTIME('%s', 'now', 'localtime') * 10000000 + 621355968000000000)");
          break;
        case SQLiteDateFormats.JulianDay:
          result.Append("CAST(STRFTIME('%J', 'now', 'localtime') AS double)");
          break;
        case SQLiteDateFormats.UnixEpoch:
          result.Append("STRFTIME('%s', 'now', 'localtime')");
          break;
        case SQLiteDateFormats.InvariantCulture:
        case SQLiteDateFormats.CurrentCulture:
          result.Append("STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'now', 'localtime')");
          break;
        default:
          result.Append("STRFTIME('%Y-%m-%d %H:%M:%S', 'now', 'localtime')");
          break;
      }

      return result;
    }

    private static ISqlFragment HandleGetUtcDateFunction(SqlGenerator sqlgen, DbFunctionExpression e)
................................................................................
    {
      SqlBuilder result = new SqlBuilder();
      Debug.Assert(e.Arguments.Count == 0, "Canonical getutcdate function should have no arguments");

      switch (sqlgen._manifest._dateFormat)
      {
        case SQLiteDateFormats.Ticks:
          result.Append("(STRFTIME('%s', 'now') * 10000000 + 621355968000000000)");
          break;
        case SQLiteDateFormats.JulianDay:
          result.Append("CAST(STRFTIME('%J', 'now') AS double)");
          break;
        case SQLiteDateFormats.UnixEpoch:
          result.Append("STRFTIME('%s', 'now')");
          break;
        case SQLiteDateFormats.InvariantCulture:
        case SQLiteDateFormats.CurrentCulture:
          result.Append("STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'now')");
          break;
        default:
          result.Append("STRFTIME('%Y-%m-%d %H:%M:%S', 'now')");
          break;
      }

      return result;
    }

    private static ISqlFragment HandleToUniversalTimeFunction(SqlGenerator sqlgen, DbFunctionExpression e)
    {
        SqlBuilder result = new SqlBuilder();
        Debug.Assert(e.Arguments.Count == 1, "Canonical touniversaltime function should have exactly one argument");

        switch (sqlgen._manifest._dateFormat)
        {
            case SQLiteDateFormats.Ticks:
                result.Append(String.Format("(STRFTIME('%s', {0}, 'utc') * 10000000 + 621355968000000000)", e.Arguments[0].Accept(sqlgen)));
                break;
            case SQLiteDateFormats.JulianDay:
                result.Append(String.Format("CAST(STRFTIME('%J', {0}, 'utc') AS double)", e.Arguments[0].Accept(sqlgen)));
                break;
            case SQLiteDateFormats.UnixEpoch:
                result.Append(String.Format("STRFTIME('%s', {0}, 'utc')", e.Arguments[0].Accept(sqlgen)));
                break;
            case SQLiteDateFormats.InvariantCulture:
            case SQLiteDateFormats.CurrentCulture:
                result.Append(String.Format("STRFTIME('%Y-%m-%dT%H:%M:%fZ', {0}, 'utc')", e.Arguments[0].Accept(sqlgen)));
                break;
            default:
                result.Append(String.Format("STRFTIME('%Y-%m-%d %H:%M:%S', {0}, 'utc')", e.Arguments[0].Accept(sqlgen)));
                break;
        }

        return result;
    }

    private static ISqlFragment HandleToLocalTimeFunction(SqlGenerator sqlgen, DbFunctionExpression e)
    {
        SqlBuilder result = new SqlBuilder();
        Debug.Assert(e.Arguments.Count == 1, "Canonical tolocaltime function should have exactly one argument");

        switch (sqlgen._manifest._dateFormat)
        {
            case SQLiteDateFormats.Ticks:
                result.Append(String.Format("(STRFTIME('%s', {0}, 'localtime') * 10000000 + 621355968000000000)", e.Arguments[0].Accept(sqlgen)));
                break;
            case SQLiteDateFormats.JulianDay:
                result.Append(String.Format("CAST(STRFTIME('%J', {0}, 'localtime') AS double)", e.Arguments[0].Accept(sqlgen)));
                break;
            case SQLiteDateFormats.UnixEpoch:
                result.Append(String.Format("STRFTIME('%s', {0}, 'localtime')", e.Arguments[0].Accept(sqlgen)));
                break;
            case SQLiteDateFormats.InvariantCulture:
            case SQLiteDateFormats.CurrentCulture:
                result.Append(String.Format("STRFTIME('%Y-%m-%dT%H:%M:%fZ', {0}, 'localtime')", e.Arguments[0].Accept(sqlgen)));
                break;
            default:
                result.Append(String.Format("STRFTIME('%Y-%m-%d %H:%M:%S', {0}, 'localtime')", e.Arguments[0].Accept(sqlgen)));
                break;
        }

        return result;
    }

    /// <summary>
    /// Handles special case in which datepart 'type' parameter is present. all the functions
    /// handles here have *only* the 1st parameter as datepart. datepart value is passed along
    /// the QP as string and has to be expanded as TSQL keyword.
    /// </summary>
    /// <param name="sqlgen"></param>
................................................................................
        result.Append("', ");

        switch (sqlgen._manifest._dateFormat)
        {
          case SQLiteDateFormats.Ticks:
            result.Append(String.Format("(({0} - 621355968000000000) / 10000000.0)", e.Arguments[1].Accept(sqlgen)));
            break;
          case SQLiteDateFormats.UnixEpoch:
            result.Append(String.Format("{0}, 'unixepoch'", e.Arguments[1].Accept(sqlgen)));
            break;
          default:
            result.Append(e.Arguments[1].Accept(sqlgen));
            break;
        }

        result.Append(") AS integer)");
      }
................................................................................
        result.Append("CAST(SUBSTR(STRFTIME('%f', ");

        switch (sqlgen._manifest._dateFormat)
        {
          case SQLiteDateFormats.Ticks:
            result.Append(String.Format("(({0} - 621355968000000000) / 10000000.0)", e.Arguments[1].Accept(sqlgen)));
            break;
          case SQLiteDateFormats.UnixEpoch:
            result.Append(String.Format("{0}, 'unixepoch'", e.Arguments[1].Accept(sqlgen)));
            break;
          default:
            result.Append(e.Arguments[1].Accept(sqlgen));
            break;
        }

        result.Append("), 4) AS integer)");
      }
................................................................................
      {
        case SQLiteDateFormats.Ticks:
          result.Append(String.Format("(STRFTIME('%s', JULIANDAY({1}) + ({0} / 86400.0)) * 10000000 + 621355968000000000)", e.Arguments[0].Accept(sqlgen), e.Arguments[1].Accept(sqlgen)));
          break;
        case SQLiteDateFormats.JulianDay:
          result.Append(String.Format("CAST(STRFTIME('%J', JULIANDAY({1}) + ({0} / 86400.0)) AS double)", e.Arguments[0].Accept(sqlgen), e.Arguments[1].Accept(sqlgen)));
          break;
        case SQLiteDateFormats.UnixEpoch:
          result.Append(String.Format("(STRFTIME('%s', JULIANDAY({1}) + ({0} / 86400.0)))", e.Arguments[0].Accept(sqlgen), e.Arguments[1].Accept(sqlgen)));
          break;
        default:
          result.Append(String.Format("STRFTIME('%Y-%m-%d %H:%M:%S', JULIANDAY({1}) + ({0} / 86400.0))", e.Arguments[0].Accept(sqlgen), e.Arguments[1].Accept(sqlgen)));
          break;
      }

      return result;
    }
................................................................................
      Debug.Assert(e.Arguments.Count == 2, "Canonical datepart functions should have exactly two arguments");

      switch (sqlgen._manifest._dateFormat)
      {
        case SQLiteDateFormats.Ticks:
          result.Append(String.Format("CAST((({0} - 621355968000000000) / 10000000.0)  - (({1} - 621355968000000000) / 10000000.0) * 86400.0 AS integer)", e.Arguments[0].Accept(sqlgen), e.Arguments[1].Accept(sqlgen)));
          break;
        case SQLiteDateFormats.UnixEpoch:
          result.Append(String.Format("CAST(({0} - {1}) * 86400.0 AS integer)", e.Arguments[0].Accept(sqlgen), e.Arguments[1].Accept(sqlgen)));
          break;
        default:
          result.Append(String.Format("CAST((JULIANDAY({1}) - JULIANDAY({0})) * 86400.0 AS integer)", e.Arguments[0].Accept(sqlgen), e.Arguments[1].Accept(sqlgen)));
          break;
      }

      return result;
    }
................................................................................
      Debug.Assert(e.Arguments.Count == 1, "Canonical datepart functions should have exactly one argument");

      switch (sqlgen._manifest._dateFormat)
      {
        case SQLiteDateFormats.Ticks:
          result.Append(String.Format("(({0} - 621355968000000000) / 10000000.0)", e.Arguments[0].Accept(sqlgen)));
          break;
        case SQLiteDateFormats.UnixEpoch:
          result.Append(String.Format("{0}, 'unixepoch'", e.Arguments[0].Accept(sqlgen)));
          break;
        default:
          result.Append(e.Arguments[0].Accept(sqlgen));
          break;
      }

      result.Append(") AS integer)");

Changes to System.Data.SQLite.Linq/SQLiteProviderManifest.cs.

36
37
38
39
40
41
42









43
44
45
46
47
48
49
      _dateFormat = (SQLiteDateFormats)Enum.Parse(typeof(SQLiteDateFormats), manifestToken, true);
    }

    internal static XmlReader GetProviderManifest()
    {
      return GetXmlResource("System.Data.SQLite.Linq.Resources.SQLiteProviderServices.ProviderManifest.xml");
    }










    /// <summary>
    /// Returns manifest information for the provider
    /// </summary>
    /// <param name="informationType">The name of the information to be retrieved.</param>
    /// <returns>An XmlReader at the begining of the information requested.</returns>
    protected override XmlReader GetDbInformation(string informationType)







>
>
>
>
>
>
>
>
>







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
      _dateFormat = (SQLiteDateFormats)Enum.Parse(typeof(SQLiteDateFormats), manifestToken, true);
    }

    internal static XmlReader GetProviderManifest()
    {
      return GetXmlResource("System.Data.SQLite.Linq.Resources.SQLiteProviderServices.ProviderManifest.xml");
    }

    /// <summary>
    /// Returns or sets the date/time format in use for this instance.
    /// </summary>
    internal SQLiteDateFormats DateTimeFormat
    {
        get { return _dateFormat; }
        set { _dateFormat = value; }
    }

    /// <summary>
    /// Returns manifest information for the provider
    /// </summary>
    /// <param name="informationType">The name of the information to be retrieved.</param>
    /// <returns>An XmlReader at the begining of the information requested.</returns>
    protected override XmlReader GetDbInformation(string informationType)

Changes to System.Data.SQLite/SQLite3.cs.

404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
      byte[] b = ToUTF8(value);
      int n = UnsafeNativeMethods.sqlite3_bind_text(stmt._sqlite_stmt, index, b, b.Length - 1, (IntPtr)(-1));
      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
    }

    internal override void Bind_DateTime(SQLiteStatement stmt, int index, DateTime dt)
    {
      byte[] b = ToUTF8(dt);
      int n = UnsafeNativeMethods.sqlite3_bind_text(stmt._sqlite_stmt, index, b, b.Length - 1, (IntPtr)(-1));
      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
    }

    internal override void Bind_Blob(SQLiteStatement stmt, int index, byte[] blobData)
    {
      int n = UnsafeNativeMethods.sqlite3_bind_blob(stmt._sqlite_stmt, index, blobData, blobData.Length, (IntPtr)(-1));







|







404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
      byte[] b = ToUTF8(value);
      int n = UnsafeNativeMethods.sqlite3_bind_text(stmt._sqlite_stmt, index, b, b.Length - 1, (IntPtr)(-1));
      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
    }

    internal override void Bind_DateTime(SQLiteStatement stmt, int index, DateTime dt)
    {
      byte[] b = ToBindUTF8(dt);
      int n = UnsafeNativeMethods.sqlite3_bind_text(stmt._sqlite_stmt, index, b, b.Length - 1, (IntPtr)(-1));
      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
    }

    internal override void Bind_Blob(SQLiteStatement stmt, int index, byte[] blobData)
    {
      int n = UnsafeNativeMethods.sqlite3_bind_blob(stmt._sqlite_stmt, index, blobData, blobData.Length, (IntPtr)(-1));

Changes to System.Data.SQLite/SQLiteConnection.cs.

998
999
1000
1001
1002
1003
1004























1005
1006
1007
1008
1009
1010
1011
      {
        if (_sql == null)
          throw new InvalidOperationException("Database connection not valid for getting number of changes.");

        return _sql.Changes;
      }
    }
























    /// <summary>
    /// Returns the version of the underlying SQLite database engine
    /// </summary>
    public static string SQLiteVersion
    {
      get { return SQLite3.SQLiteVersion; }







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
      {
        if (_sql == null)
          throw new InvalidOperationException("Database connection not valid for getting number of changes.");

        return _sql.Changes;
      }
    }

    /// <summary>
    /// Returns or sets the date/time format currently in use for this connection.
    /// </summary>
#if !PLATFORM_COMPACTFRAMEWORK
    [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
#endif
    public SQLiteDateFormats DateTimeFormat
    {
        get {
            if (_sql == null)
                throw new InvalidOperationException("Database connection not valid for getting date/time format.");

            return _sql.DateTimeFormat;
        }
        set
        {
            if (_sql == null)
                throw new InvalidOperationException("Database connection not valid for setting date/time format.");

            _sql.DateTimeFormat = value;
        }
    }

    /// <summary>
    /// Returns the version of the underlying SQLite database engine
    /// </summary>
    public static string SQLiteVersion
    {
      get { return SQLite3.SQLiteVersion; }

Changes to System.Data.SQLite/SQLiteConvert.cs.

20
21
22
23
24
25
26





27
28
29
30
31
32
33
..
64
65
66
67
68
69
70











71
72
73
74
75
76
77
..
96
97
98
99
100
101
102














103
104
105
106
107
108
109
...
157
158
159
160
161
162
163










164
165
166
167
168
169
170
...
193
194
195
196
197
198
199










200
201
202
203
204
205
206
  {
    /// <summary>
    /// The value for the Unix epoch (e.g. January 1, 1970 at midnight, in UTC).
    /// </summary>
    private static readonly DateTime UnixEpoch =
        new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);






    /// <summary>
    /// The format string for DateTime values when using the InvariantCulture or CurrentCulture formats.
    /// </summary>
    private const string FullFormat = "yyyy-MM-ddTHH:mm:ss.fffffffK";

    /// <summary>
    /// An array of ISO8601 datetime formats we support conversion from
................................................................................
    /// Initializes the conversion class
    /// </summary>
    /// <param name="fmt">The default date/time format to use for this instance</param>
    internal SQLiteConvert(SQLiteDateFormats fmt)
    {
      _datetimeFormat = fmt;
    }












    #region UTF-8 Conversion Functions
    /// <summary>
    /// Converts a string to a UTF-8 encoded byte array sized to include a null-terminating character.
    /// </summary>
    /// <param name="sourceText">The string to convert to UTF-8</param>
    /// <returns>A byte array containing the converted string plus an extra 0 terminating byte at the end of the array.</returns>
................................................................................
    /// </remarks>
    /// <param name="dateTimeValue">The DateTime to convert.</param>
    /// <returns>The UTF-8 encoded string, including a 0 terminating byte at the end of the array.</returns>
    public byte[] ToUTF8(DateTime dateTimeValue)
    {
      return ToUTF8(ToString(dateTimeValue));
    }















    /// <summary>
    /// Converts a UTF-8 encoded IntPtr of the specified length into a .NET string
    /// </summary>
    /// <param name="nativestring">The pointer to the memory where the UTF-8 string is encoded</param>
    /// <param name="nativestringlen">The number of bytes to decode</param>
    /// <returns>A string containing the translated character(s)</returns>
................................................................................
    /// <param name="dateText">The string containing either a long integer number of 100-nanosecond units since
    /// System.DateTime.MinValue, a Julian day double, an integer number of seconds since the Unix epoch, a
    /// culture-independent formatted date and time string, a formatted date and time string in the current
    /// culture, or an ISO8601-format string.</param>
    /// <returns>A DateTime value</returns>
    public DateTime ToDateTime(string dateText)
    {










      switch (_datetimeFormat)
      {
        case SQLiteDateFormats.Ticks:
          return new DateTime(Convert.ToInt64(dateText, CultureInfo.InvariantCulture));
        case SQLiteDateFormats.JulianDay:
          return ToDateTime(Convert.ToDouble(dateText, CultureInfo.InvariantCulture));
        case SQLiteDateFormats.UnixEpoch:
................................................................................
    /// </summary>
    /// <param name="value">The DateTime to convert</param>
    /// <returns>The JulianDay value the Datetime represents</returns>
    public double ToJulianDay(DateTime value)
    {
      return value.ToOADate() + 2415018.5;
    }











    /// <summary>
    /// Converts a DateTime to a string value, using the current DateTimeFormat specified for the connection when it was opened.
    /// </summary>
    /// <param name="dateValue">The DateTime value to convert</param>
    /// <returns>Either a string containing the long integer number of 100-nanosecond units since System.DateTime.MinValue, a
    /// Julian day double, an integer number of seconds since the Unix epoch, a culture-independent formatted date and time







>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
..
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
...
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
...
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
...
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
  {
    /// <summary>
    /// The value for the Unix epoch (e.g. January 1, 1970 at midnight, in UTC).
    /// </summary>
    private static readonly DateTime UnixEpoch =
        new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

    /// <summary>
    /// The most complete human-readable time string format natively understood by SQLite.
    /// </summary>
    private const string BindFormat = "yyyy-MM-ddTHH:mm:ss.fff";

    /// <summary>
    /// The format string for DateTime values when using the InvariantCulture or CurrentCulture formats.
    /// </summary>
    private const string FullFormat = "yyyy-MM-ddTHH:mm:ss.fffffffK";

    /// <summary>
    /// An array of ISO8601 datetime formats we support conversion from
................................................................................
    /// Initializes the conversion class
    /// </summary>
    /// <param name="fmt">The default date/time format to use for this instance</param>
    internal SQLiteConvert(SQLiteDateFormats fmt)
    {
      _datetimeFormat = fmt;
    }

    #region Public Properties
    /// <summary>
    /// Returns or sets the date/time format currently in use for this instance.
    /// </summary>
    public SQLiteDateFormats DateTimeFormat
    {
        get { return _datetimeFormat; }
        set { _datetimeFormat = value; }
    }
    #endregion

    #region UTF-8 Conversion Functions
    /// <summary>
    /// Converts a string to a UTF-8 encoded byte array sized to include a null-terminating character.
    /// </summary>
    /// <param name="sourceText">The string to convert to UTF-8</param>
    /// <returns>A byte array containing the converted string plus an extra 0 terminating byte at the end of the array.</returns>
................................................................................
    /// </remarks>
    /// <param name="dateTimeValue">The DateTime to convert.</param>
    /// <returns>The UTF-8 encoded string, including a 0 terminating byte at the end of the array.</returns>
    public byte[] ToUTF8(DateTime dateTimeValue)
    {
      return ToUTF8(ToString(dateTimeValue));
    }

    /// <summary>
    /// Convert a DateTime to a UTF-8 encoded, zero-terminated byte array.
    /// </summary>
    /// <remarks>
    /// This function is a convenience function, which first calls ToBindString() on the DateTime, and then calls ToUTF8() with
    /// the string result.
    /// </remarks>
    /// <param name="dateTimeValue">The DateTime to convert.</param>
    /// <returns>The UTF-8 encoded string, including a 0 terminating byte at the end of the array.</returns>
    public byte[] ToBindUTF8(DateTime dateTimeValue)
    {
      return ToUTF8(ToBindString(dateTimeValue));
    }

    /// <summary>
    /// Converts a UTF-8 encoded IntPtr of the specified length into a .NET string
    /// </summary>
    /// <param name="nativestring">The pointer to the memory where the UTF-8 string is encoded</param>
    /// <param name="nativestringlen">The number of bytes to decode</param>
    /// <returns>A string containing the translated character(s)</returns>
................................................................................
    /// <param name="dateText">The string containing either a long integer number of 100-nanosecond units since
    /// System.DateTime.MinValue, a Julian day double, an integer number of seconds since the Unix epoch, a
    /// culture-independent formatted date and time string, a formatted date and time string in the current
    /// culture, or an ISO8601-format string.</param>
    /// <returns>A DateTime value</returns>
    public DateTime ToDateTime(string dateText)
    {
      //
      // NOTE: First, try to interpret the string as a correctly formatted date.
      //
      DateTime result;

      if (DateTime.TryParseExact(dateText, _datetimeFormats, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None, out result))
      {
        return result;
      }

      switch (_datetimeFormat)
      {
        case SQLiteDateFormats.Ticks:
          return new DateTime(Convert.ToInt64(dateText, CultureInfo.InvariantCulture));
        case SQLiteDateFormats.JulianDay:
          return ToDateTime(Convert.ToDouble(dateText, CultureInfo.InvariantCulture));
        case SQLiteDateFormats.UnixEpoch:
................................................................................
    /// </summary>
    /// <param name="value">The DateTime to convert</param>
    /// <returns>The JulianDay value the Datetime represents</returns>
    public double ToJulianDay(DateTime value)
    {
      return value.ToOADate() + 2415018.5;
    }

    /// <summary>
    /// Converts a DateTime to a string value suitable for binding to a query parameter.
    /// </summary>
    /// <param name="dateValue">The DateTime value to convert</param>
    /// <returns>An ISO8601 formatted date/time string in the invariant culture.</returns>
    public string ToBindString(DateTime dateValue)
    {
      return dateValue.ToString(BindFormat, CultureInfo.InvariantCulture);
    }

    /// <summary>
    /// Converts a DateTime to a string value, using the current DateTimeFormat specified for the connection when it was opened.
    /// </summary>
    /// <param name="dateValue">The DateTime value to convert</param>
    /// <returns>Either a string containing the long integer number of 100-nanosecond units since System.DateTime.MinValue, a
    /// Julian day double, an integer number of seconds since the Unix epoch, a culture-independent formatted date and time

Changes to Tests/basic.eagle.

738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
...
799
800
801
802
803
804
805
806
807
808
809
























































810
811
812
813
814
815
816
817
818
819
820
821
822
  cleanupDb $fileName

  unset -nocomplain name rows result db fileName
} -constraints {eagle monoBug28 command.sql compile.DATA System.Data.SQLite} \
-result [subst {{1 {{x 1} {y2 {Wednesday, 16 December 2009}}}} {2 {{x 2} {y2\
12:00:00}}} {3 {{x 3} {y2 {Wednesday, 16 December 2009 12:00:00}}}} {4 {{x 4}\
{y2 12/16/2009}}} {5 {{x 5} {y2 12:00}}} {6 {{x 6} {y2 {12/16/2009 12:00}}}} {7\
{{x 7} {y2 2009-12-16T00:00:00.0000000Z}}} {8 {{x 8} {y2\
${date}T12:00:00.0000000Z}}} {9 {{x 9} {y2 2009-12-16T12:00:00.0000000Z}}}\
{10 {{x 10} {y2 2009-12-16T00:00:00.0000000Z}}} {11 {{x 11} {y2\
${date}T12:00:00.0000000Z}}} {12 {{x 12} {y2 2009-12-16T12:00:00.0000000Z}}}}]}

###############################################################################

runTest {test basic-1.14 {DateTime using current culture} -setup {
  setupDb [set fileName basic-1.14.db] "" "" "DateTimeFormat=CurrentCulture;"
} -body {
  set result [list]
................................................................................

  unset -nocomplain db fileName
} -constraints \
{eagle culture.en_US monoBug28 command.sql compile.DATA System.Data.SQLite} \
-result [subst {{1 {{x 1} {y2 {Wednesday, 16 December 2009}}}} {2 {{x 2} {y2\
12:00:00}}} {3 {{x 3} {y2 {Wednesday, 16 December 2009 12:00:00}}}} {4 {{x 4}\
{y2 12/16/2009}}} {5 {{x 5} {y2 12:00}}} {6 {{x 6} {y2 {12/16/2009 12:00}}}} {7\
{{x 7} {y2 2009-12-16T00:00:00.0000000Z}}} {8 {{x 8} {y2\
${date}T12:00:00.0000000Z}}} {9 {{x 9} {y2 2009-12-16T12:00:00.0000000Z}}}\
{10 {{x 10} {y2 2009-12-16T00:00:00.0000000Z}}} {11 {{x 11} {y2\
${date}T12:00:00.0000000Z}}} {12 {{x 12} {y2 2009-12-16T12:00:00.0000000Z}}}}]}

























































###############################################################################

unset -nocomplain date

###############################################################################

unset -nocomplain testExeFile testLinqExeFile northwindEfDbFile testLinqOutFile

###############################################################################

runSQLiteTestEpilogue
runTestEpilogue







|
|
|
|







 







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













738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
...
799
800
801
802
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
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
  cleanupDb $fileName

  unset -nocomplain name rows result db fileName
} -constraints {eagle monoBug28 command.sql compile.DATA System.Data.SQLite} \
-result [subst {{1 {{x 1} {y2 {Wednesday, 16 December 2009}}}} {2 {{x 2} {y2\
12:00:00}}} {3 {{x 3} {y2 {Wednesday, 16 December 2009 12:00:00}}}} {4 {{x 4}\
{y2 12/16/2009}}} {5 {{x 5} {y2 12:00}}} {6 {{x 6} {y2 {12/16/2009 12:00}}}} {7\
{{x 7} {y2 2009-12-16T00:00:00.000}}} {8 {{x 8} {y2\
${date}T12:00:00.000}}} {9 {{x 9} {y2 2009-12-16T12:00:00.000}}} {10 {{x 10}\
{y2 2009-12-16T00:00:00.000}}} {11 {{x 11} {y2 ${date}T12:00:00.000}}} {12 {{x\
12} {y2 2009-12-16T12:00:00.000}}}}]}

###############################################################################

runTest {test basic-1.14 {DateTime using current culture} -setup {
  setupDb [set fileName basic-1.14.db] "" "" "DateTimeFormat=CurrentCulture;"
} -body {
  set result [list]
................................................................................

  unset -nocomplain db fileName
} -constraints \
{eagle culture.en_US monoBug28 command.sql compile.DATA System.Data.SQLite} \
-result [subst {{1 {{x 1} {y2 {Wednesday, 16 December 2009}}}} {2 {{x 2} {y2\
12:00:00}}} {3 {{x 3} {y2 {Wednesday, 16 December 2009 12:00:00}}}} {4 {{x 4}\
{y2 12/16/2009}}} {5 {{x 5} {y2 12:00}}} {6 {{x 6} {y2 {12/16/2009 12:00}}}} {7\
{{x 7} {y2 2009-12-16T00:00:00.000}}} {8 {{x 8} {y2\
${date}T12:00:00.000}}} {9 {{x 9} {y2 2009-12-16T12:00:00.000}}} {10 {{x 10}\
{y2 2009-12-16T00:00:00.000}}} {11 {{x 11} {y2 ${date}T12:00:00.000}}} {12 {{x\
12} {y2 2009-12-16T12:00:00.000}}}}]}

###############################################################################

runTest {test basic-1.15 {other date/time functions for LINQ} -setup {
  set formats [list Ticks ISO8601 JulianDay UnixEpoch \
                    InvariantCulture CurrentCulture]

  # 1996-07-04 00:00:00|1996-08-01 00:00:00
  # 1998-05-06 00:00:00|1998-06-03 00:00:00
  # 11078|ALFKI|1|2003-01-02 04:05:06.789|
  # 2009-08-07 06:05:04.321|1999-12-25 23:59:42.654|0||||||

  set prefix "SELECT VALUE o FROM Orders AS o WHERE"

  set queries [list \
      "SQLite.GetDate() >= SQLite.ToLocalTime(@dt) AND o.OrderID = 11078;" \
      "SQLite.GetUtcDate() >= @dt AND o.OrderID = 11078;" \
      "Year(SQLite.GetDate()) == Year(@dt) AND o.OrderID = 11078;" \
      "Month(SQLite.GetDate()) == Month(@dt) AND o.OrderID = 11078;" \
      "Day(SQLite.GetDate()) == Day(@dt) AND o.OrderID = 11078;" \
      "Hour(o.OrderDate) == 4 AND o.OrderID = 11078;" \
      "Minute(o.OrderDate) == 5 AND o.OrderID = 11078;" \
      "Second(o.OrderDate) == 6 AND o.OrderID = 11078;"]
} -body {
  set result [list]

  foreach format $formats {
    foreach query $queries {
      set code [catch {
        testExec $testLinqExeFile [list -eventflags Wait -directory \
        [file dirname $testLinqExeFile] -nocarriagereturns -stdout output \
        -success 0] -dateTime [appendArgs \" $format \"] [appendArgs \" \
        $prefix " " $query \"] [appendArgs \" \
        [expr {[string first @dt $query] != -1 ? $date : ""}] \"]
      } error]

      tlog "---- BEGIN STDOUT OUTPUT\n"
      tlog $output
      tlog "\n---- END STDOUT OUTPUT\n"

      lappend result $code

      if {$code == 0} then {
        lappend result [string trim $output]
      } else {
        lappend result [string trim $error]
      }
    }
  }

  set result
} -cleanup {
  unset -nocomplain prefix format formats query queries
  unset -nocomplain code output error result
} -constraints {eagle file_testlinq.exe file_northwindEF.db} \
-result {}}

###############################################################################

unset -nocomplain date

###############################################################################

unset -nocomplain testExeFile testLinqExeFile northwindEfDbFile testLinqOutFile

###############################################################################

runSQLiteTestEpilogue
runTestEpilogue

Changes to Tests/testlinq.out.

1858
1859
1860
1861
1862
1863
1864

1865
1866
1867
1868
1869
1870
1871
3508
8010
05033
1734
1204
13008
87110

Chai
Chang
Chef Anton's Cajun Seasoning
Chef Anton's Gumbo Mix
Uncle Bob's Organic Dried Pears
Guaraná Fantástica
Gumbär Gummibärchen







>







1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
3508
8010
05033
1734
1204
13008
87110

Chai
Chang
Chef Anton's Cajun Seasoning
Chef Anton's Gumbo Mix
Uncle Bob's Organic Dried Pears
Guaraná Fantástica
Gumbär Gummibärchen

Changes to testlinq/Program.cs.

1
2
3

4

5
6
7
8
9
10
11
..
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
..
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108




















































109
110
111
112
113
114
115
...
283
284
285
286
287
288
289





















































290
291
292
293
294
295
296
using System;
using System.Diagnostics;
using System.Linq;

using System.Data.Objects;

using System.Text;
using System.Transactions;

namespace testlinq
{
  class Program
  {
................................................................................
                  {
                      return OldTests();
                  }
              case "skip":
                  {
                      int pageSize = 0;

                      if (args.Length > 1)
                      {
                          arg = args[1];

                          if (arg != null)
                              pageSize = int.Parse(arg.Trim());
                      }

................................................................................

                      return StartsWithTest(value);
                  }
              case "eftransaction":
                  {
                      bool value = false;

                      if (args.Length > 1)
                      {
                          if (!bool.TryParse(args[1], out value))
                          {
                              Console.WriteLine(
                                  "cannot parse \"{0}\" as boolean",
                                  args[1]);

                              return 1;
                          }
                      }

                      return EFTransactionTest(value);
                  }




















































              default:
                  {
                      Console.WriteLine("unknown test \"{0}\"", arg);
                      return 1;
                  }
          }
      }
................................................................................

                      Console.Write(territories.TerritoryID);

                      once = true;
                  }
              }
          }






















































          return 0;
      }

    private static int OldTests()
    {
      using (northwindEFEntities db = new northwindEFEntities())



>

>







 







|







 







|













>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
..
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
..
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
...
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
using System;
using System.Diagnostics;
using System.Linq;
using System.Data.EntityClient;
using System.Data.Objects;
using System.Data.SQLite;
using System.Text;
using System.Transactions;

namespace testlinq
{
  class Program
  {
................................................................................
                  {
                      return OldTests();
                  }
              case "skip":
                  {
                      int pageSize = 0;

                      if ((args.Length > 1) && !String.IsNullOrEmpty(args[1]))
                      {
                          arg = args[1];

                          if (arg != null)
                              pageSize = int.Parse(arg.Trim());
                      }

................................................................................

                      return StartsWithTest(value);
                  }
              case "eftransaction":
                  {
                      bool value = false;

                      if ((args.Length > 1) && !String.IsNullOrEmpty(args[1]))
                      {
                          if (!bool.TryParse(args[1], out value))
                          {
                              Console.WriteLine(
                                  "cannot parse \"{0}\" as boolean",
                                  args[1]);

                              return 1;
                          }
                      }

                      return EFTransactionTest(value);
                  }
              case "datetime":
                  {
                      SQLiteDateFormats dateTimeFormat = SQLiteDateFormats.Default;
                      string queryString = null;
                      DateTime? dateTime = null;

                      if ((args.Length > 1) && !String.IsNullOrEmpty(args[1]))
                      {
                          try
                          {
                              dateTimeFormat = (SQLiteDateFormats)Enum.Parse(
                                  typeof(SQLiteDateFormats), args[1], true);
                          }
                          catch
                          {
                              Console.WriteLine(
                                  "cannot parse \"{0}\" as a date/time format",
                                  args[1]);

                              return 1;
                          }
                      }

                      if (args.Length > 2)
                      {
                          queryString = args[2];

                          if (queryString != null)
                              queryString = queryString.Trim();
                      }

                      if ((args.Length > 3) && !String.IsNullOrEmpty(args[3]))
                      {
                          DateTime dateTimeValue;

                          if (DateTime.TryParse(args[3], out dateTimeValue))
                          {
                              dateTime = DateTime.SpecifyKind(
                                  dateTimeValue, DateTimeKind.Utc);
                          }
                          else
                          {
                              Console.WriteLine(
                                  "cannot parse \"{0}\" as a date/time",
                                  args[3]);

                              return 1;
                          }
                      }

                      return DateTimeTest(dateTimeFormat, queryString, dateTime);
                  }
              default:
                  {
                      Console.WriteLine("unknown test \"{0}\"", arg);
                      return 1;
                  }
          }
      }
................................................................................

                      Console.Write(territories.TerritoryID);

                      once = true;
                  }
              }
          }

          return 0;
      }

      //
      // NOTE: Used to test the various DateTime methods.
      //
      private static int DateTimeTest(
          SQLiteDateFormats dateTimeFormat,
          string queryString,
          DateTime? dateTime
          )
      {
          using (northwindEFEntities db = new northwindEFEntities())
          {
              EntityConnection connection = db.Connection as EntityConnection;

              if (connection == null)
              {
                  Console.WriteLine("not an entity connection");
                  return 1;
              }

              SQLiteConnection storeConnection =
                  connection.StoreConnection as SQLiteConnection;

              if (storeConnection == null)
              {
                  Console.WriteLine("not a SQLite store connection");
                  return 1;
              }

              connection.Open(); /* NOTE: Force open now. */
              storeConnection.DateTimeFormat = dateTimeFormat;

              bool once = false;

              ObjectParameter[] parameters = (dateTime != null) ?
                  new ObjectParameter[] { new ObjectParameter("dt", dateTime) } :
                  new ObjectParameter[] { };

              var query = db.CreateQuery<Orders>(queryString, parameters);

              foreach (Orders orders in query)
              {
                  if (once)
                      Console.Write(' ');

                  Console.Write(orders.OrderID);

                  once = true;
              }
          }

          return 0;
      }

    private static int OldTests()
    {
      using (northwindEFEntities db = new northwindEFEntities())

Changes to testlinq/northwindEF.db.

cannot compute difference between binary files

Changes to testlinq/testlinq.2008.csproj.

46
47
48
49
50
51
52






53
54
55
56
57
58
59
    <Reference Include="System.Core" />
    <Reference Include="System.Data.Entity" />
    <Reference Include="System.Runtime.Serialization" />
    <Reference Include="System.Transactions" />
    <Reference Include="System.Xml" />
    <Reference Include="System.Data" />
  </ItemGroup>






  <ItemGroup>
    <Compile Include="NorthwindModel2008.Designer.cs">
      <AutoGen>True</AutoGen>
      <DesignTime>True</DesignTime>
      <DependentUpon>NorthwindModel2008.edmx</DependentUpon>
    </Compile>
    <Compile Include="Program.cs" />







>
>
>
>
>
>







46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
    <Reference Include="System.Core" />
    <Reference Include="System.Data.Entity" />
    <Reference Include="System.Runtime.Serialization" />
    <Reference Include="System.Transactions" />
    <Reference Include="System.Xml" />
    <Reference Include="System.Data" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\System.Data.SQLite\System.Data.SQLite.2008.csproj">
      <Project>{AC139952-261A-4463-B6FA-AEBC25283A66}</Project>
      <Name>System.Data.SQLite.2008</Name>
    </ProjectReference>
  </ItemGroup>
  <ItemGroup>
    <Compile Include="NorthwindModel2008.Designer.cs">
      <AutoGen>True</AutoGen>
      <DesignTime>True</DesignTime>
      <DependentUpon>NorthwindModel2008.edmx</DependentUpon>
    </Compile>
    <Compile Include="Program.cs" />

Changes to testlinq/testlinq.2010.csproj.

43
44
45
46
47
48
49






50
51
52
53
54
55
56
    <Reference Include="System" />
    <Reference Include="System.Data.Entity" />
    <Reference Include="System.Runtime.Serialization" />
    <Reference Include="System.Transactions" />
    <Reference Include="System.Xml" />
    <Reference Include="System.Data" />
  </ItemGroup>






  <ItemGroup>
    <Compile Condition="'$(TargetFrameworkVersion)' == 'v3.5'"
             Include="NorthwindModel2008.Designer.cs">
      <AutoGen>True</AutoGen>
      <DesignTime>True</DesignTime>
      <DependentUpon>NorthwindModel2008.edmx</DependentUpon>
    </Compile>







>
>
>
>
>
>







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
    <Reference Include="System" />
    <Reference Include="System.Data.Entity" />
    <Reference Include="System.Runtime.Serialization" />
    <Reference Include="System.Transactions" />
    <Reference Include="System.Xml" />
    <Reference Include="System.Data" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\System.Data.SQLite\System.Data.SQLite.2010.csproj">
      <Project>{AC139952-261A-4463-B6FA-AEBC25283A66}</Project>
      <Name>System.Data.SQLite.2010</Name>
    </ProjectReference>
  </ItemGroup>
  <ItemGroup>
    <Compile Condition="'$(TargetFrameworkVersion)' == 'v3.5'"
             Include="NorthwindModel2008.Designer.cs">
      <AutoGen>True</AutoGen>
      <DesignTime>True</DesignTime>
      <DependentUpon>NorthwindModel2008.edmx</DependentUpon>
    </Compile>