Index: System.Data.SQLite.Linq/Resources/SQLiteProviderServices.ProviderManifest.xml
==================================================================
--- System.Data.SQLite.Linq/Resources/SQLiteProviderServices.ProviderManifest.xml
+++ System.Data.SQLite.Linq/Resources/SQLiteProviderServices.ProviderManifest.xml
@@ -688,10 +688,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: System.Data.SQLite.Linq/SQL Generation/SqlGenerator.cs
==================================================================
--- System.Data.SQLite.Linq/SQL Generation/SqlGenerator.cs
+++ System.Data.SQLite.Linq/SQL Generation/SqlGenerator.cs
@@ -316,10 +316,12 @@
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;
}
///
/// All special non-aggregate canonical functions and their handlers
@@ -2660,17 +2662,24 @@
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)");
+ result.Append("(STRFTIME('%s', 'now', 'localtime') * 10000000 + 621355968000000000)");
break;
case SQLiteDateFormats.JulianDay:
- result.Append("CAST(STRFTIME('%J', 'now') AS double)");
+ 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')");
+ result.Append("STRFTIME('%Y-%m-%d %H:%M:%S', 'now', 'localtime')");
break;
}
return result;
}
@@ -2681,22 +2690,85 @@
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)");
+ result.Append("(STRFTIME('%s', 'now') * 10000000 + 621355968000000000)");
break;
case SQLiteDateFormats.JulianDay:
- result.Append("CAST(STRFTIME('%J', 'now', 'utc') AS double)");
+ 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', 'utc')");
+ 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;
+ }
///
/// 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.
@@ -2742,10 +2814,13 @@
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;
}
@@ -2758,10 +2833,13 @@
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;
}
@@ -2788,10 +2866,13 @@
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;
}
@@ -2812,10 +2893,13 @@
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;
}
@@ -2848,10 +2932,13 @@
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;
}
Index: System.Data.SQLite.Linq/SQLiteProviderManifest.cs
==================================================================
--- System.Data.SQLite.Linq/SQLiteProviderManifest.cs
+++ System.Data.SQLite.Linq/SQLiteProviderManifest.cs
@@ -37,10 +37,19 @@
}
internal static XmlReader GetProviderManifest()
{
return GetXmlResource("System.Data.SQLite.Linq.Resources.SQLiteProviderServices.ProviderManifest.xml");
+ }
+
+ ///
+ /// Returns or sets the date/time format in use for this instance.
+ ///
+ internal SQLiteDateFormats DateTimeFormat
+ {
+ get { return _dateFormat; }
+ set { _dateFormat = value; }
}
///
/// Returns manifest information for the provider
///
Index: System.Data.SQLite/SQLite3.cs
==================================================================
--- System.Data.SQLite/SQLite3.cs
+++ System.Data.SQLite/SQLite3.cs
@@ -406,11 +406,11 @@
if (n > 0) throw new SQLiteException(n, SQLiteLastError());
}
internal override void Bind_DateTime(SQLiteStatement stmt, int index, DateTime dt)
{
- byte[] b = ToUTF8(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)
Index: System.Data.SQLite/SQLiteConnection.cs
==================================================================
--- System.Data.SQLite/SQLiteConnection.cs
+++ System.Data.SQLite/SQLiteConnection.cs
@@ -1000,10 +1000,33 @@
throw new InvalidOperationException("Database connection not valid for getting number of changes.");
return _sql.Changes;
}
}
+
+ ///
+ /// Returns or sets the date/time format currently in use for this connection.
+ ///
+#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;
+ }
+ }
///
/// Returns the version of the underlying SQLite database engine
///
public static string SQLiteVersion
Index: System.Data.SQLite/SQLiteConvert.cs
==================================================================
--- System.Data.SQLite/SQLiteConvert.cs
+++ System.Data.SQLite/SQLiteConvert.cs
@@ -22,10 +22,15 @@
/// The value for the Unix epoch (e.g. January 1, 1970 at midnight, in UTC).
///
private static readonly DateTime UnixEpoch =
new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+ ///
+ /// The most complete human-readable time string format natively understood by SQLite.
+ ///
+ private const string BindFormat = "yyyy-MM-ddTHH:mm:ss.fff";
+
///
/// The format string for DateTime values when using the InvariantCulture or CurrentCulture formats.
///
private const string FullFormat = "yyyy-MM-ddTHH:mm:ss.fffffffK";
@@ -66,10 +71,21 @@
/// The default date/time format to use for this instance
internal SQLiteConvert(SQLiteDateFormats fmt)
{
_datetimeFormat = fmt;
}
+
+ #region Public Properties
+ ///
+ /// Returns or sets the date/time format currently in use for this instance.
+ ///
+ public SQLiteDateFormats DateTimeFormat
+ {
+ get { return _datetimeFormat; }
+ set { _datetimeFormat = value; }
+ }
+ #endregion
#region UTF-8 Conversion Functions
///
/// Converts a string to a UTF-8 encoded byte array sized to include a null-terminating character.
///
@@ -98,10 +114,24 @@
/// The UTF-8 encoded string, including a 0 terminating byte at the end of the array.
public byte[] ToUTF8(DateTime dateTimeValue)
{
return ToUTF8(ToString(dateTimeValue));
}
+
+ ///
+ /// Convert a DateTime to a UTF-8 encoded, zero-terminated byte array.
+ ///
+ ///
+ /// This function is a convenience function, which first calls ToBindString() on the DateTime, and then calls ToUTF8() with
+ /// the string result.
+ ///
+ /// The DateTime to convert.
+ /// The UTF-8 encoded string, including a 0 terminating byte at the end of the array.
+ public byte[] ToBindUTF8(DateTime dateTimeValue)
+ {
+ return ToUTF8(ToBindString(dateTimeValue));
+ }
///
/// Converts a UTF-8 encoded IntPtr of the specified length into a .NET string
///
/// The pointer to the memory where the UTF-8 string is encoded
@@ -159,10 +189,20 @@
/// culture-independent formatted date and time string, a formatted date and time string in the current
/// culture, or an ISO8601-format string.
/// A DateTime value
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:
@@ -195,10 +235,20 @@
/// The JulianDay value the Datetime represents
public double ToJulianDay(DateTime value)
{
return value.ToOADate() + 2415018.5;
}
+
+ ///
+ /// Converts a DateTime to a string value suitable for binding to a query parameter.
+ ///
+ /// The DateTime value to convert
+ /// An ISO8601 formatted date/time string in the invariant culture.
+ public string ToBindString(DateTime dateValue)
+ {
+ return dateValue.ToString(BindFormat, CultureInfo.InvariantCulture);
+ }
///
/// Converts a DateTime to a string value, using the current DateTimeFormat specified for the connection when it was opened.
///
/// The DateTime value to convert
Index: Tests/basic.eagle
==================================================================
--- Tests/basic.eagle
+++ Tests/basic.eagle
@@ -740,14 +740,14 @@
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}}}}]}
+{{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;"
@@ -801,14 +801,70 @@
} -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}}}}]}
+{{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
Index: Tests/testlinq.out
==================================================================
--- Tests/testlinq.out
+++ Tests/testlinq.out
@@ -1860,10 +1860,11 @@
05033
1734
1204
13008
87110
+
Chai
Chang
Chef Anton's Cajun Seasoning
Chef Anton's Gumbo Mix
Uncle Bob's Organic Dried Pears
Index: testlinq/Program.cs
==================================================================
--- testlinq/Program.cs
+++ testlinq/Program.cs
@@ -1,9 +1,11 @@
using System;
using System.Diagnostics;
-using System.Linq;
+using System.Linq;
+using System.Data.EntityClient;
using System.Data.Objects;
+using System.Data.SQLite;
using System.Text;
using System.Transactions;
namespace testlinq
{
@@ -48,11 +50,11 @@
}
case "skip":
{
int pageSize = 0;
- if (args.Length > 1)
+ if ((args.Length > 1) && !String.IsNullOrEmpty(args[1]))
{
arg = args[1];
if (arg != null)
pageSize = int.Parse(arg.Trim());
@@ -90,11 +92,11 @@
}
case "eftransaction":
{
bool value = false;
- if (args.Length > 1)
+ if ((args.Length > 1) && !String.IsNullOrEmpty(args[1]))
{
if (!bool.TryParse(args[1], out value))
{
Console.WriteLine(
"cannot parse \"{0}\" as boolean",
@@ -104,10 +106,62 @@
}
}
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;
}
@@ -285,10 +339,63 @@
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(queryString, parameters);
+
+ foreach (Orders orders in query)
+ {
+ if (once)
+ Console.Write(' ');
+
+ Console.Write(orders.OrderID);
+
+ once = true;
+ }
+ }
return 0;
}
private static int OldTests()
Index: testlinq/northwindEF.db
==================================================================
--- testlinq/northwindEF.db
+++ testlinq/northwindEF.db
cannot compute difference between binary files
Index: testlinq/testlinq.2008.csproj
==================================================================
--- testlinq/testlinq.2008.csproj
+++ testlinq/testlinq.2008.csproj
@@ -48,10 +48,16 @@
+
+
+ {AC139952-261A-4463-B6FA-AEBC25283A66}
+ System.Data.SQLite.2008
+
+
True
True
NorthwindModel2008.edmx
Index: testlinq/testlinq.2010.csproj
==================================================================
--- testlinq/testlinq.2010.csproj
+++ testlinq/testlinq.2010.csproj
@@ -45,10 +45,16 @@
+
+
+ {AC139952-261A-4463-B6FA-AEBC25283A66}
+ System.Data.SQLite.2010
+
+
True
True