Index: System.Data.SQLite/SQLite3.cs ================================================================== --- System.Data.SQLite/SQLite3.cs +++ System.Data.SQLite/SQLite3.cs @@ -38,12 +38,12 @@ /// /// The user-defined functions registered on this connection /// protected SQLiteFunction[] _functionsArray; - internal SQLite3(SQLiteDateFormats fmt) - : base(fmt) + internal SQLite3(SQLiteDateFormats fmt, DateTimeKind kind) + : base(fmt, kind) { } protected override void Dispose(bool bDisposing) { @@ -262,10 +262,30 @@ return SQLiteBase.SQLiteLastError(_sql); } internal override SQLiteStatement Prepare(SQLiteConnection cnn, string strSql, SQLiteStatement previous, uint timeoutMS, out string strRemain) { + if (!String.IsNullOrEmpty(strSql)) + { + // + // NOTE: SQLite does not support the concept of separate schemas + // in one database; therefore, remove the base schema name + // used to smooth integration with the base .NET Framework + // data classes. + // + string baseSchemaName = (cnn != null) ? cnn._baseSchemaName : null; + + if (!String.IsNullOrEmpty(baseSchemaName)) + { + strSql = strSql.Replace( + String.Format("[{0}].", baseSchemaName), String.Empty); + + strSql = strSql.Replace( + String.Format("{0}.", baseSchemaName), String.Empty); + } + } + IntPtr stmt = IntPtr.Zero; IntPtr ptr = IntPtr.Zero; int len = 0; int n = 17; int retries = 0; @@ -406,13 +426,38 @@ 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()); + switch (_datetimeFormat) + { + case SQLiteDateFormats.Ticks: + { + int n = UnsafeNativeMethods.sqlite3_bind_int64(stmt._sqlite_stmt, index, dt.Ticks); + if (n > 0) throw new SQLiteException(n, SQLiteLastError()); + break; + } + case SQLiteDateFormats.JulianDay: + { + int n = UnsafeNativeMethods.sqlite3_bind_double(stmt._sqlite_stmt, index, ToJulianDay(dt)); + if (n > 0) throw new SQLiteException(n, SQLiteLastError()); + break; + } + case SQLiteDateFormats.UnixEpoch: + { + int n = UnsafeNativeMethods.sqlite3_bind_int64(stmt._sqlite_stmt, index, Convert.ToInt64(dt.Subtract(UnixEpoch).TotalSeconds)); + if (n > 0) throw new SQLiteException(n, SQLiteLastError()); + break; + } + default: + { + 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()); + break; + } + } } 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)); Index: System.Data.SQLite/SQLite3_UTF16.cs ================================================================== --- System.Data.SQLite/SQLite3_UTF16.cs +++ System.Data.SQLite/SQLite3_UTF16.cs @@ -13,12 +13,12 @@ /// /// Alternate SQLite3 object, overriding many text behaviors to support UTF-16 (Unicode) /// internal class SQLite3_UTF16 : SQLite3 { - internal SQLite3_UTF16(SQLiteDateFormats fmt) - : base(fmt) + internal SQLite3_UTF16(SQLiteDateFormats fmt, DateTimeKind kind) + : base(fmt, kind) { } /// /// Overrides SQLiteConvert.ToString() to marshal UTF-16 strings instead of UTF-8 @@ -70,12 +70,37 @@ } _functionsArray = SQLiteFunction.BindFunctions(this); } internal override void Bind_DateTime(SQLiteStatement stmt, int index, DateTime dt) - { - Bind_Text(stmt, index, ToString(dt)); + { + switch (_datetimeFormat) + { + case SQLiteDateFormats.Ticks: + { + int n = UnsafeNativeMethods.sqlite3_bind_int64(stmt._sqlite_stmt, index, dt.Ticks); + if (n > 0) throw new SQLiteException(n, SQLiteLastError()); + break; + } + case SQLiteDateFormats.JulianDay: + { + int n = UnsafeNativeMethods.sqlite3_bind_double(stmt._sqlite_stmt, index, ToJulianDay(dt)); + if (n > 0) throw new SQLiteException(n, SQLiteLastError()); + break; + } + case SQLiteDateFormats.UnixEpoch: + { + int n = UnsafeNativeMethods.sqlite3_bind_int64(stmt._sqlite_stmt, index, Convert.ToInt64(dt.Subtract(UnixEpoch).TotalSeconds)); + if (n > 0) throw new SQLiteException(n, SQLiteLastError()); + break; + } + default: + { + Bind_Text(stmt, index, ToString(dt)); + break; + } + } } internal override void Bind_Text(SQLiteStatement stmt, int index, string value) { int n = UnsafeNativeMethods.sqlite3_bind_text16(stmt._sqlite_stmt, index, value, value.Length * 2, (IntPtr)(-1)); Index: System.Data.SQLite/SQLiteBase.cs ================================================================== --- System.Data.SQLite/SQLiteBase.cs +++ System.Data.SQLite/SQLiteBase.cs @@ -13,12 +13,12 @@ /// This internal class provides the foundation of SQLite support. It defines all the abstract members needed to implement /// a SQLite data provider, and inherits from SQLiteConvert which allows for simple translations of string to and from SQLite. /// internal abstract class SQLiteBase : SQLiteConvert, IDisposable { - internal SQLiteBase(SQLiteDateFormats fmt) - : base(fmt) { } + internal SQLiteBase(SQLiteDateFormats fmt, DateTimeKind kind) + : base(fmt, kind) { } static internal object _lock = new object(); /// /// Returns a string representing the active version of SQLite Index: System.Data.SQLite/SQLiteConnection.cs ================================================================== --- System.Data.SQLite/SQLiteConnection.cs +++ System.Data.SQLite/SQLiteConnection.cs @@ -50,10 +50,25 @@ /// DateTimeFormat /// Ticks - Use DateTime.Ticks
ISO8601 - Use ISO8601 DateTime format
/// N /// ISO8601 /// + /// + /// DateTimeKind + /// Unspecified - Not specified as either UTC or local time.
Utc - The time represented is UTC.
Local - The time represented is local time.
+ /// N + /// Unspecified + ///
+ /// + /// BaseSchemaName + /// Some base data classes in the framework (e.g. those that build SQL queries dynamically) + /// assume that an ADO.NET provider cannot support an alternate catalog (i.e. database) without supporting + /// alternate schemas as well; however, SQLite does not fit into this model. Therefore, this value is used + /// as a placeholder and removed prior to preparing any SQL statements that may contain it. + /// N + /// sqlite_default_schema + /// /// /// BinaryGUID /// True - Store GUID columns in binary form
False - Store GUID columns as text
/// N /// True @@ -150,10 +165,19 @@ ///
/// /// public sealed partial class SQLiteConnection : DbConnection, ICloneable { + /// + /// The default "stub" (i.e. placeholder) base schema name to use when + /// returning column schema information. Used as the initial value of + /// the BaseSchemaName property. This should start with "sqlite_*" + /// because those names are reserved for use by SQLite (i.e. they cannot + /// be confused with the names of user objects). + /// + private const string DefaultBaseSchemaName = "sqlite_default_schema"; + private const int SQLITE_FCNTL_WIN32_AV_RETRY = 9; private const string _dataDirectory = "|DataDirectory|"; private const string _masterdb = "sqlite_master"; private const string _tempmasterdb = "sqlite_temp_master"; @@ -193,10 +217,16 @@ /// /// Temporary password storage, emptied after the database has been opened /// private byte[] _password; + /// + /// The "stub" (i.e. placeholder) base schema name to use when returning + /// column schema information. + /// + internal string _baseSchemaName; + /// /// Default command timeout /// private int _defaultTimeout = 30; @@ -803,10 +833,12 @@ _defaultIsolation = (IsolationLevel)Enum.Parse(typeof(IsolationLevel), FindKey(opts, "Default IsolationLevel", "Serializable"), true); if (_defaultIsolation != IsolationLevel.Serializable && _defaultIsolation != IsolationLevel.ReadCommitted) throw new NotSupportedException("Invalid Default IsolationLevel specified"); + _baseSchemaName = FindKey(opts, "BaseSchemaName", DefaultBaseSchemaName); + //string temp = FindKey(opts, "DateTimeFormat", "ISO8601"); //if (String.Compare(temp, "ticks", StringComparison.OrdinalIgnoreCase) == 0) dateFormat = SQLiteDateFormats.Ticks; //else if (String.Compare(temp, "julianday", StringComparison.OrdinalIgnoreCase) == 0) dateFormat = SQLiteDateFormats.JulianDay; if (_sql == null) @@ -813,15 +845,18 @@ { bool bUTF16 = (SQLiteConvert.ToBoolean(FindKey(opts, "UseUTF16Encoding", Boolean.FalseString)) == true); SQLiteDateFormats dateFormat = (SQLiteDateFormats)Enum.Parse(typeof(SQLiteDateFormats), FindKey(opts, "DateTimeFormat", "ISO8601"), true); + + DateTimeKind kind = (DateTimeKind)Enum.Parse(typeof(DateTimeKind), + FindKey(opts, "DateTimeKind", "Unspecified"), true); if (bUTF16) // SQLite automatically sets the encoding of the database to UTF16 if called from sqlite3_open16() - _sql = new SQLite3_UTF16(dateFormat); + _sql = new SQLite3_UTF16(dateFormat, kind); else - _sql = new SQLite3(dateFormat); + _sql = new SQLite3(dateFormat, kind); } SQLiteOpenFlagsEnum flags = SQLiteOpenFlagsEnum.None; if (SQLiteConvert.ToBoolean(FindKey(opts, "FailIfMissing", Boolean.FalseString)) == false) @@ -1035,15 +1070,18 @@ bool bUTF16 = (SQLiteConvert.ToBoolean(FindKey(opts, "UseUTF16Encoding", Boolean.FalseString)) == true); SQLiteDateFormats dateFormat = (SQLiteDateFormats)Enum.Parse(typeof(SQLiteDateFormats), FindKey(opts, "DateTimeFormat", "ISO8601"), true); + + DateTimeKind kind = (DateTimeKind)Enum.Parse(typeof(DateTimeKind), + FindKey(opts, "DateTimeKind", "Unspecified"), true); if (bUTF16) // SQLite automatically sets the encoding of the database to UTF16 if called from sqlite3_open16() - _sql = new SQLite3_UTF16(dateFormat); + _sql = new SQLite3_UTF16(dateFormat, kind); else - _sql = new SQLite3(dateFormat); + _sql = new SQLite3(dateFormat, kind); } if (_sql != null) return _sql.Shutdown(); throw new InvalidOperationException("Database connection not active."); } Index: System.Data.SQLite/SQLiteConvert.cs ================================================================== --- System.Data.SQLite/SQLiteConvert.cs +++ System.Data.SQLite/SQLiteConvert.cs @@ -19,39 +19,58 @@ public abstract class SQLiteConvert { /// /// The value for the Unix epoch (e.g. January 1, 1970 at midnight, in UTC). /// - private static readonly DateTime UnixEpoch = + protected static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + /// + /// The value of the OLE Automation epoch represented as a Julian day. + /// + private static readonly double OleAutomationEpochAsJulianDay = 2415018.5; + /// /// The format string for DateTime values when using the InvariantCulture or CurrentCulture formats. /// private const string FullFormat = "yyyy-MM-ddTHH:mm:ss.fffffffK"; /// /// An array of ISO8601 datetime formats we support conversion from /// private static string[] _datetimeFormats = new string[] { + "THHmmssK", + "THHmmK", + "HH:mm:ss.FFFFFFFK", + "HH:mm:ssK", + "HH:mmK", + "yyyy-MM-dd HH:mm:ss.FFFFFFFK", /* NOTE: UTC default (5). */ + "yyyy-MM-dd HH:mm:ssK", + "yyyy-MM-dd HH:mmK", + "yyyy-MM-ddTHH:mm:ss.FFFFFFFK", + "yyyy-MM-ddTHH:mmK", + "yyyy-MM-ddTHH:mm:ssK", + "yyyyMMddHHmmssK", + "yyyyMMddHHmmK", + "yyyyMMddTHHmmssFFFFFFFK", "THHmmss", "THHmm", + "HH:mm:ss.FFFFFFF", "HH:mm:ss", "HH:mm", - "HH:mm:ss.FFFFFFF", - "yy-MM-dd", - "yyyy-MM-dd", - "yyyy-MM-dd HH:mm:ss.FFFFFFF", + "yyyy-MM-dd HH:mm:ss.FFFFFFF", /* NOTE: Non-UTC default (19). */ "yyyy-MM-dd HH:mm:ss", - "yyyy-MM-dd HH:mm", + "yyyy-MM-dd HH:mm", "yyyy-MM-ddTHH:mm:ss.FFFFFFF", "yyyy-MM-ddTHH:mm", "yyyy-MM-ddTHH:mm:ss", "yyyyMMddHHmmss", "yyyyMMddHHmm", "yyyyMMddTHHmmssFFFFFFF", - "yyyyMMdd" + "yyyy-MM-dd", + "yyyyMMdd", + "yy-MM-dd" }; /// /// An UTF-8 Encoding instance, so we can convert strings to and from UTF-8 /// @@ -59,16 +78,22 @@ /// /// The default DateTime format for this instance /// internal SQLiteDateFormats _datetimeFormat; /// + /// The default DateTimeKind for this instance. + /// + internal DateTimeKind _datetimeKind; + /// /// Initializes the conversion class /// /// The default date/time format to use for this instance - internal SQLiteConvert(SQLiteDateFormats fmt) + /// The DateTimeKind to use. + internal SQLiteConvert(SQLiteDateFormats fmt, DateTimeKind kind) { _datetimeFormat = fmt; + _datetimeKind = kind; } #region UTF-8 Conversion Functions /// /// Converts a string to a UTF-8 encoded byte array sized to include a null-terminating character. @@ -143,61 +168,177 @@ /// /// Converts a string into a DateTime, using the current DateTimeFormat specified for the connection when it was opened. /// /// /// Acceptable ISO8601 DateTime formats are: - /// yyyy-MM-dd HH:mm:ss - /// yyyyMMddHHmmss - /// yyyyMMddTHHmmssfffffff - /// yyyy-MM-dd - /// yy-MM-dd - /// yyyyMMdd - /// HH:mm:ss + /// THHmmssK + /// THHmmK + /// HH:mm:ss.FFFFFFFK + /// HH:mm:ssK + /// HH:mmK + /// yyyy-MM-dd HH:mm:ss.FFFFFFFK + /// yyyy-MM-dd HH:mm:ssK + /// yyyy-MM-dd HH:mmK + /// yyyy-MM-ddTHH:mm:ss.FFFFFFFK + /// yyyy-MM-ddTHH:mmK + /// yyyy-MM-ddTHH:mm:ssK + /// yyyyMMddHHmmssK + /// yyyyMMddHHmmK + /// yyyyMMddTHHmmssFFFFFFFK /// THHmmss + /// THHmm + /// HH:mm:ss.FFFFFFF + /// HH:mm:ss + /// HH:mm + /// yyyy-MM-dd HH:mm:ss.FFFFFFF + /// yyyy-MM-dd HH:mm:ss + /// yyyy-MM-dd HH:mm + /// yyyy-MM-ddTHH:mm:ss.FFFFFFF + /// yyyy-MM-ddTHH:mm + /// yyyy-MM-ddTHH:mm:ss + /// yyyyMMddHHmmss + /// yyyyMMddHHmm + /// yyyyMMddTHHmmssFFFFFFF + /// yyyy-MM-dd + /// yyyyMMdd + /// yy-MM-dd /// /// 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. /// A DateTime value 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: - return UnixEpoch.AddSeconds(Convert.ToInt32(dateText, CultureInfo.InvariantCulture)); - case SQLiteDateFormats.InvariantCulture: - return DateTime.Parse(dateText, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None); - case SQLiteDateFormats.CurrentCulture: - return DateTime.Parse(dateText, DateTimeFormatInfo.CurrentInfo, DateTimeStyles.None); - default: - return DateTime.ParseExact(dateText, _datetimeFormats, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None); - } + return ToDateTime(dateText, _datetimeFormat, _datetimeKind); + } + + /// + /// Converts a string into a DateTime, using the specified DateTimeFormat and DateTimeKind. + /// + /// + /// Acceptable ISO8601 DateTime formats are: + /// THHmmssK + /// THHmmK + /// HH:mm:ss.FFFFFFFK + /// HH:mm:ssK + /// HH:mmK + /// yyyy-MM-dd HH:mm:ss.FFFFFFFK + /// yyyy-MM-dd HH:mm:ssK + /// yyyy-MM-dd HH:mmK + /// yyyy-MM-ddTHH:mm:ss.FFFFFFFK + /// yyyy-MM-ddTHH:mmK + /// yyyy-MM-ddTHH:mm:ssK + /// yyyyMMddHHmmssK + /// yyyyMMddHHmmK + /// yyyyMMddTHHmmssFFFFFFFK + /// THHmmss + /// THHmm + /// HH:mm:ss.FFFFFFF + /// HH:mm:ss + /// HH:mm + /// yyyy-MM-dd HH:mm:ss.FFFFFFF + /// yyyy-MM-dd HH:mm:ss + /// yyyy-MM-dd HH:mm + /// yyyy-MM-ddTHH:mm:ss.FFFFFFF + /// yyyy-MM-ddTHH:mm + /// yyyy-MM-ddTHH:mm:ss + /// yyyyMMddHHmmss + /// yyyyMMddHHmm + /// yyyyMMddTHHmmssFFFFFFF + /// yyyy-MM-dd + /// yyyyMMdd + /// yy-MM-dd + /// + /// 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. + /// The SQLiteDateFormats to use. + /// The DateTimeKind to use. + /// A DateTime value + public DateTime ToDateTime(string dateText, SQLiteDateFormats format, DateTimeKind kind) + { + switch (format) + { + case SQLiteDateFormats.Ticks: + { + return new DateTime(Convert.ToInt64( + dateText, CultureInfo.InvariantCulture), kind); + } + case SQLiteDateFormats.JulianDay: + { + return ToDateTime(Convert.ToDouble( + dateText, CultureInfo.InvariantCulture), kind); + } + case SQLiteDateFormats.UnixEpoch: + { + return DateTime.SpecifyKind( + UnixEpoch.AddSeconds(Convert.ToInt32( + dateText, CultureInfo.InvariantCulture)), kind); + } + case SQLiteDateFormats.InvariantCulture: + { + return DateTime.SpecifyKind(DateTime.Parse( + dateText, DateTimeFormatInfo.InvariantInfo, + kind == DateTimeKind.Utc ? + DateTimeStyles.AdjustToUniversal : + DateTimeStyles.None), + kind); + } + case SQLiteDateFormats.CurrentCulture: + { + return DateTime.SpecifyKind(DateTime.Parse( + dateText, DateTimeFormatInfo.CurrentInfo, + kind == DateTimeKind.Utc ? + DateTimeStyles.AdjustToUniversal : + DateTimeStyles.None), + kind); + } + default: + { + return DateTime.SpecifyKind(DateTime.ParseExact( + dateText, _datetimeFormats, + DateTimeFormatInfo.InvariantInfo, + kind == DateTimeKind.Utc ? + DateTimeStyles.AdjustToUniversal : + DateTimeStyles.None), + kind); + } + } } /// /// Converts a julianday value into a DateTime /// /// The value to convert /// A .NET DateTime public DateTime ToDateTime(double julianDay) { - return DateTime.FromOADate(julianDay - 2415018.5); + return ToDateTime(julianDay, _datetimeKind); + } + + /// + /// Converts a julianday value into a DateTime + /// + /// The value to convert + /// The DateTimeKind to use. + /// A .NET DateTime + public DateTime ToDateTime(double julianDay, DateTimeKind kind) + { + return DateTime.SpecifyKind( + DateTime.FromOADate(julianDay - OleAutomationEpochAsJulianDay), kind); } /// /// Converts a DateTime struct to a JulianDay double /// /// The DateTime to convert /// The JulianDay value the Datetime represents public double ToJulianDay(DateTime value) { - return value.ToOADate() + 2415018.5; + return value.ToOADate() + OleAutomationEpochAsJulianDay; } /// /// Converts a DateTime to a string value, using the current DateTimeFormat specified for the connection when it was opened. /// @@ -218,11 +359,13 @@ case SQLiteDateFormats.InvariantCulture: return dateValue.ToString(FullFormat, CultureInfo.InvariantCulture); case SQLiteDateFormats.CurrentCulture: return dateValue.ToString(FullFormat, CultureInfo.CurrentCulture); default: - return dateValue.ToString(_datetimeFormats[7], CultureInfo.InvariantCulture); + return (dateValue.Kind == DateTimeKind.Utc) ? + dateValue.ToString(_datetimeFormats[5], CultureInfo.InvariantCulture) : // include "Z" + dateValue.ToString(_datetimeFormats[19], CultureInfo.InvariantCulture); } } /// /// Internal function to convert a UTF-8 encoded IntPtr of the specified length to a DateTime. Index: System.Data.SQLite/SQLiteDataReader.cs ================================================================== --- System.Data.SQLite/SQLiteDataReader.cs +++ System.Data.SQLite/SQLiteDataReader.cs @@ -14,11 +14,11 @@ /// /// SQLite implementation of DbDataReader. /// public sealed class SQLiteDataReader : DbDataReader - { + { /// /// Underlying command this reader is attached to /// private SQLiteCommand _command; /// @@ -73,11 +73,21 @@ /// /// An array of rowid's for the active statement if CommandBehavior.KeyInfo is specified /// private SQLiteKeyReader _keyInfo; - internal long _version; // Matches the version of the connection + /// + /// Matches the version of the connection. + /// + internal long _version; + + /// + /// The "stub" (i.e. placeholder) base schema name to use when returning + /// column schema information. Matches the base schema name used by the + /// associated connection. + /// + private string _baseSchemaName; /// /// Internal constructor, initializes the datareader and sets up to begin executing statements /// /// The SQLiteCommand this data reader is for @@ -84,11 +94,12 @@ /// The expected behavior of the data reader internal SQLiteDataReader(SQLiteCommand cmd, CommandBehavior behave) { _throwOnDisposed = true; _command = cmd; - _version = _command.Connection._version; + _version = _command.Connection._version; + _baseSchemaName = _command.Connection._baseSchemaName; _commandBehavior = behave; _activeStatementIndex = -1; _rowsAffected = -1; @@ -637,11 +648,12 @@ row[SchemaTableOptionalColumn.IsRowVersion] = false; row[SchemaTableColumn.IsUnique] = false; row[SchemaTableColumn.IsKey] = false; row[SchemaTableOptionalColumn.IsAutoIncrement] = false; row[SchemaTableColumn.DataType] = GetFieldType(n); - row[SchemaTableOptionalColumn.IsHidden] = false; + row[SchemaTableOptionalColumn.IsHidden] = false; + row[SchemaTableColumn.BaseSchemaName] = _baseSchemaName; strColumn = _command.Connection._sql.ColumnOriginalName(_activeStatement, n); if (String.IsNullOrEmpty(strColumn) == false) row[SchemaTableColumn.BaseColumnName] = strColumn; row[SchemaTableColumn.IsExpression] = String.IsNullOrEmpty(strColumn); Index: System.Data.SQLite/SQLiteLog.cs ================================================================== --- System.Data.SQLite/SQLiteLog.cs +++ System.Data.SQLite/SQLiteLog.cs @@ -146,11 +146,12 @@ // // NOTE: Create an instance of the SQLite wrapper class. // if (_sql == null) - _sql = new SQLite3(SQLiteDateFormats.Default); + _sql = new SQLite3(SQLiteDateFormats.Default, + DateTimeKind.Unspecified); // // NOTE: Create a single "global" (i.e. per-process) callback // to register with SQLite. This callback will pass the // event on to any registered handler. We only want to Index: Tests/basic.eagle ================================================================== --- Tests/basic.eagle +++ Tests/basic.eagle @@ -649,11 +649,11 @@ {z 5678}}} 2 {1 {{x 1} {y foobar} {z 1234}}} {2 {{x 2} {y foobar} {z 5678}}}}} ############################################################################### runTest {test basic-1.12 {DateTime using Unix epoch} -setup { - setupDb [set fileName basic-1.12.db] "" "" "DateTimeFormat=UnixEpoch;" + setupDb [set fileName basic-1.12.db] "" UnixEpoch Utc } -body { set result [list] sql execute $db "CREATE TABLE t1(x INTEGER PRIMARY KEY ASC, y DATETIME);" sql execute $db "INSERT INTO t1 (x, y) VALUES(1, 1302825600);" @@ -676,11 +676,11 @@ [list param1 DateTime 1334448000] sql execute -verbatim $db "INSERT INTO t1 (x, y) VALUES(9, ?);" \ [list param1 DateTime 1365984000] - sql execute -execute reader -datetimeformat "MM/dd/yyyy HH:mm:ss" $db \ + sql execute -execute reader -datetimeformat [getDateTimeFormat] $db \ "SELECT x, y FROM t1 ORDER BY x;" foreach name [lsort -integer [array names rows -regexp {^\d+$}]] { lappend result [list $name $rows($name)] } @@ -690,24 +690,24 @@ cleanupDb $fileName unset -nocomplain name rows result db fileName } -constraints \ {eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} \ --result {{1 {{x 1} {y {04/15/2011 00:00:00}}}} {2 {{x 2} {y {04/15/2012\ -00:00:00}}}} {3 {{x 3} {y {04/15/2013 00:00:00}}}} {4 {{x 4} {y {04/15/2011\ -00:00:00}}}} {5 {{x 5} {y {04/15/2012 00:00:00}}}} {6 {{x 6} {y {04/15/2013\ -00:00:00}}}} {7 {{x 7} {y {04/15/2011 00:00:00}}}} {8 {{x 8} {y {04/15/2012\ -00:00:00}}}} {9 {{x 9} {y {04/15/2013 00:00:00}}}}}} +-result {{1 {{x 1} {y {2011-04-15 00:00:00Z}}}} {2 {{x 2} {y {2012-04-15\ +00:00:00Z}}}} {3 {{x 3} {y {2013-04-15 00:00:00Z}}}} {4 {{x 4} {y {2011-04-15\ +00:00:00Z}}}} {5 {{x 5} {y {2012-04-15 00:00:00Z}}}} {6 {{x 6} {y {2013-04-15\ +00:00:00Z}}}} {7 {{x 7} {y {2011-04-15 00:00:00Z}}}} {8 {{x 8} {y {2012-04-15\ +00:00:00Z}}}} {9 {{x 9} {y {2013-04-15 00:00:00Z}}}}}} ############################################################################### set date [clock format [clock seconds] -format yyyy-MM-dd] ############################################################################### runTest {test basic-1.13 {DateTime using invariant culture} -setup { - setupDb [set fileName basic-1.13.db] "" "" "DateTimeFormat=InvariantCulture;" + setupDb [set fileName basic-1.13.db] "" InvariantCulture Utc } -body { set result [list] sql execute $db "CREATE TABLE t1(x INTEGER PRIMARY KEY ASC, y DATETIME);" @@ -739,11 +739,11 @@ [list param1 DateTime 12:00] sql execute $db "INSERT INTO t1 (x, y) VALUES(12, ?);" \ [list param1 DateTime "12/16/2009 12:00"] - sql execute -execute reader -datetimeformat "MM/dd/yyyy HH:mm:ss" $db \ + sql execute -execute reader -datetimeformat [getDateTimeFormat] $db \ "SELECT x, CAST(y AS TEXT) AS y2 FROM t1 ORDER BY x;" foreach name [lsort -integer [array names rows -regexp {^\d+$}]] { lappend result [list $name $rows($name)] } @@ -764,11 +764,11 @@ ${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;" + setupDb [set fileName basic-1.14.db] "" CurrentCulture Utc } -body { set result [list] sql execute $db "CREATE TABLE t1(x INTEGER PRIMARY KEY ASC, y DATETIME);" @@ -800,11 +800,11 @@ [list param1 DateTime 12:00] sql execute $db "INSERT INTO t1 (x, y) VALUES(12, ?);" \ [list param1 DateTime "12/16/2009 12:00"] - sql execute -execute reader -datetimeformat "MM/dd/yyyy HH:mm:ss" $db \ + sql execute -execute reader -datetimeformat [getDateTimeFormat] $db \ "SELECT x, CAST(y AS TEXT) AS y2 FROM t1 ORDER BY x;" foreach name [lsort -integer [array names rows -regexp {^\d+$}]] { lappend result [list $name $rows($name)] } Index: Tests/common.eagle ================================================================== --- Tests/common.eagle +++ Tests/common.eagle @@ -106,17 +106,25 @@ # # EagleShell.exe -initialize -postInitialize # "object invoke Interpreter.GetActive AddRuntimeOption native" # -file .\path\to\all.eagle # - if {[hasRuntimeOption native]} then { - return [file join [file dirname $::path] bin [getBuildYear] \ - [machineToPlatform $::tcl_platform(machine)] \ - [getBuildConfiguration]] + if {[info exists ::build_directory] && \ + [string length $::build_directory] > 0} then { + # + # NOTE: The location of the build directory has been overridden. + # + return $::build_directory } else { - return [file join [file dirname $::path] bin [getBuildYear] \ - [getBuildConfiguration] bin] + if {[hasRuntimeOption native]} then { + return [file join [file dirname $::path] bin [getBuildYear] \ + [machineToPlatform $::tcl_platform(machine)] \ + [getBuildConfiguration]] + } else { + return [file join [file dirname $::path] bin [getBuildYear] \ + [getBuildConfiguration] bin] + } } } proc getBuildFileName { fileName } { return [file nativename \ @@ -129,11 +137,19 @@ # itself (i.e. the Eagle shell) is located. This will be used as # the destination for the copied System.Data.SQLite native and # managed assemblies (i.e. because this is one of the few places # where the CLR will actually find and load them properly). # - return [info binary] + if {[info exists ::binary_directory] && \ + [string length $::binary_directory] > 0} then { + # + # NOTE: The location of the binary directory has been overridden. + # + return $::binary_directory + } else { + return [info binary] + } } proc getBinaryFileName { fileName } { return [file nativename \ [file join [getBinaryDirectory] [file tail $fileName]]] @@ -247,10 +263,32 @@ tputs $channel [appendArgs "yes (" $version ")\n"] } else { tputs $channel no\n } } + + proc getDateTimeFormat {} { + # + # NOTE: This procedure simply returns the "default" DateTime format used + # by the test suite. + # + if {[info exists ::datetime_format] && \ + [string length $::datetime_format] > 0} then { + # + # NOTE: Return the manually overridden value for the DateTime format. + # + return $::datetime_format + } else { + # + # NOTE: Return an ISO8601 DateTime format compatible with SQLite, + # System.Data.SQLite, and suitable for round-tripping with the + # DateTime class of the framework. If this value is changed, + # various tests may fail. + # + return "yyyy-MM-dd HH:mm:ss.FFFFFFFK" + } + } proc enumerableToList { enumerable } { set result [list] if {[string length $enumerable] == 0 || $enumerable eq "null"} then { @@ -301,11 +339,13 @@ # result. # eval $command } - proc setupDb {fileName {mode ""} {delete ""} {extra ""} {varName db}} { + proc setupDb { + fileName {mode ""} {dateTimeFormat ""} {dateTimeKind ""} {extra ""} + {delete true} {varName db}} { # # NOTE: For now, all test databases used by the test suite are placed into # the temporary directory. Each database used by a test should be # cleaned up by that test using the "cleanupDb" procedure, below. # @@ -313,11 +353,11 @@ # # NOTE: By default, delete any pre-existing database with the same file # name. # - if {[string length $delete] == 0 || $delete} then { + if {$delete} then { catch {file delete $fileName} } # # NOTE: Refer to the specified variable (e.g. "db") in the context of the @@ -336,10 +376,26 @@ # of the connection string now. # if {[string length $mode] > 0} then { append connection {;Journal Mode=${mode}} } + + # + # NOTE: If the caller specified a DateTime format, add the necessary + # portion of the connection string now. + # + if {[string length $dateTimeFormat] > 0} then { + append connection {;DateTimeFormat=${dateTimeFormat}} + } + + # + # NOTE: If the caller specified a DateTimeKind, add the necessary portion + # of the connection string now. + # + if {[string length $dateTimeKind] > 0} then { + append connection {;DateTimeKind=${dateTimeKind}} + } # # NOTE: If the caller specified an extra payload to the connection string, # append it now. # ADDED Tests/tkt-343d392b51.eagle Index: Tests/tkt-343d392b51.eagle ================================================================== --- /dev/null +++ Tests/tkt-343d392b51.eagle @@ -0,0 +1,439 @@ +############################################################################### +# +# tkt-343d392b51.eagle -- +# +# Written by Joe Mistachkin. +# Released to the public domain, use at your own risk! +# +############################################################################### + +package require Eagle +package require EagleLibrary +package require EagleTest + +runTestPrologue + +############################################################################### + +package require System.Data.SQLite.Test +runSQLiteTestPrologue + +############################################################################### + +set dateTimeFormats [list "" Ticks ISO8601 JulianDay UnixEpoch] + +for {set i 1} {$i < 5} {incr i} { + set dateTimeFormat [lindex $dateTimeFormats $i] + + runTest {test [appendArgs tkt-343d392b51-1. $i] [subst {DateTime\ + binding $dateTimeFormat format}] -setup { + setupDb [set fileName [appendArgs tkt-343d392b51-1. $i .db]] "" \ + $dateTimeFormat Utc + + set dateTime "4 October, 2011 3:27:50 PM GMT" + } -body { + sql execute $db "CREATE TABLE t1(x DATETIME);" + + set paramDateTime1 [clock format [clock scan $dateTime] -format \ + [getDateTimeFormat] -gmt true] + + switch -exact -- $dateTimeFormat { + Ticks { + set paramDateTime1 [object invoke -alias DateTime Parse $paramDateTime1] + set paramDateTime1 [$paramDateTime1 ToUniversalTime.Ticks] + set paramDateTime2 $paramDateTime1 + } + ISO8601 { + set paramDateTime2 [appendArgs ' $paramDateTime1 '] + } + JulianDay { + set paramDateTime1 [object invoke -alias DateTime Parse $paramDateTime1] + set paramDateTime1 [$paramDateTime1 -alias ToUniversalTime] + + set paramDateTime1 [expr {[$paramDateTime1 ToOADate] + \ + [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ + OleAutomationEpochAsJulianDay]}] + + set paramDateTime2 $paramDateTime1 + } + UnixEpoch { + set paramDateTime1 [clock scan $dateTime] + set paramDateTime2 $paramDateTime1 + } + } + + sql execute $db [appendArgs "INSERT INTO t1 (x) VALUES(" $paramDateTime2 \ + ");"] + + list [sql execute -verbatim -execute reader -format list -datetimeformat \ + [getDateTimeFormat] $db "SELECT x FROM t1 WHERE x = ?;" \ + [list param1 String $paramDateTime1]] \ + [sql execute -verbatim -execute reader -format list -datetimeformat \ + [getDateTimeFormat] $db "SELECT x FROM t1 WHERE x = ?;" \ + [list param1 DateTime $paramDateTime1]] + } -cleanup { + cleanupDb $fileName + + unset -nocomplain paramDateTime2 paramDateTime1 dateTime db fileName + } -constraints {eagle culture.en_US monoBug28 command.sql compile.DATA SQLite\ +System.Data.SQLite} -result {{{2011-10-04 15:27:50Z}} {{2011-10-04 15:27:50Z}}}} +} + +############################################################################### + +unset -nocomplain dateTimeFormat i dateTimeFormats + +############################################################################### + +runTest {test tkt-343d392b51-2.1 {SQLiteDataAdapter update fail} -setup { + setupDb [set fileName tkt-343d392b51-2.1.db] + set otherFileName tkt-343d392b51-2.1-otherDb.db +} -body { + set id [object invoke Interpreter.GetActive NextId] + set dataSource [file join [getTemporaryPath] $fileName] + set otherDataSource [file join [getTemporaryPath] $otherFileName] + set otherDbName otherDb + set otherTable [appendArgs $otherDbName .t1] + + set sql(inserts) "" + set sql(1) [subst { \ + ATTACH DATABASE '${otherDataSource}' AS ${otherDbName}; \ + CREATE TABLE ${otherTable}(x INTEGER PRIMARY KEY, y DATETIME); \ + [for {set i 1} {$i < 3} {incr i} { + append sql(inserts) [appendArgs \ + "INSERT INTO " ${otherTable} " (x, y) VALUES(" $i ", '" \ + [clock format $i -format [getDateTimeFormat]] "'); "] + }; return [expr {[info exists sql(inserts)] ? $sql(inserts) : ""}]] \ + }] + + set sql(2) [subst { \ + SELECT x, y FROM ${otherTable} ORDER BY x; \ + }] + + unset -nocomplain results errors + + set code [compileCSharpWith [subst { + using System; + using System.Data; + using System.Data.SQLite; + + namespace _Dynamic${id} + { + public class Test${id} + { + public static void Main() + { + using (SQLiteConnection connection = new SQLiteConnection( + "Data Source=${dataSource};")) + { + connection.Open(); + + using (SQLiteCommand command = connection.CreateCommand()) + { + command.CommandText = "${sql(1)}"; + command.ExecuteNonQuery(); + } + + using (SQLiteDataAdapter dataAdapter = new SQLiteDataAdapter( + "${sql(2)}", connection)) + { + using (DataSet dataSet = new DataSet()) + { + dataAdapter.Fill(dataSet, "${otherTable}"); + + DataTable dataTable = dataSet.Tables\["${otherTable}"\]; + + dataTable.Columns\["x"\].Unique = true; + dataTable.PrimaryKey = new DataColumn\[\] { + dataTable.Columns\["x"\] + }; + + [expr {[isMono] ? "#pragma warning disable 219" : ""}] + SQLiteCommandBuilder commandBuilder = + new SQLiteCommandBuilder(dataAdapter); + [expr {[isMono] ? "#pragma warning restore 219" : ""}] + + foreach (DataRow dataRow in dataTable.Rows) + { + // + // NOTE: Update even rows and delete odd rows. + // + if ((long)dataRow\["x"\] % 2 == 0) + dataRow\["y"\] = + DateTime.UtcNow.ToString("[getDateTimeFormat]"); + else + dataRow.Delete(); + } + + dataAdapter.Update(dataTable); // DBConcurrencyException (?) + } + } + } + } + } + } + }] results errors System.Data.SQLite.dll] + + list $code $results \ + [expr {[info exists errors] ? $errors : ""}] \ + [expr {$code eq "Ok" ? [catch { + object invoke _Dynamic${id}.Test${id} Main + } result] : [set result ""]}] $result +} -cleanup { + cleanupDb $otherFileName + cleanupDb $fileName + + unset -nocomplain result code results errors i sql otherTable otherDbName \ + otherDataSource dataSource id db otherFileName fileName +} -constraints \ +{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -match \ +glob -result {* System.Data.DBConcurrencyException: *}} + +############################################################################### + +runTest {test tkt-343d392b51-2.2 {SQLiteDataAdapter update success} -setup { + setupDb [set fileName tkt-343d392b51-2.2.db] "" JulianDay + set otherFileName tkt-343d392b51-2.2-otherDb.db +} -body { + set id [object invoke Interpreter.GetActive NextId] + set dataSource [file join [getTemporaryPath] $fileName] + set otherDataSource [file join [getTemporaryPath] $otherFileName] + set otherDbName otherDb + set otherTable [appendArgs $otherDbName .t1] + + set sql(inserts) "" + set sql(1) [subst { \ + ATTACH DATABASE '${otherDataSource}' AS ${otherDbName}; \ + CREATE TABLE ${otherTable}(x INTEGER PRIMARY KEY, y DATETIME); \ + [for {set i 1} {$i < 3} {incr i} { + append sql(inserts) [appendArgs \ + "INSERT INTO " ${otherTable} " (x, y) VALUES(" $i ", JULIANDAY('" \ + [clock format $i -format [getDateTimeFormat]] "')); "] + }; return [expr {[info exists sql(inserts)] ? $sql(inserts) : ""}]] \ + }] + + set sql(2) [subst { \ + SELECT x, y FROM ${otherTable} ORDER BY x; \ + }] + + unset -nocomplain results errors + + set code [compileCSharpWith [subst { + using System; + using System.Data; + using System.Data.SQLite; + + namespace _Dynamic${id} + { + public class Test${id} + { + public static void Main() + { + using (SQLiteConnection connection = new SQLiteConnection( + "Data Source=${dataSource};DateTimeFormat=JulianDay;")) + { + connection.Open(); + + using (SQLiteCommand command = connection.CreateCommand()) + { + command.CommandText = "${sql(1)}"; + command.ExecuteNonQuery(); + } + + using (SQLiteDataAdapter dataAdapter = new SQLiteDataAdapter( + "${sql(2)}", connection)) + { + using (DataSet dataSet = new DataSet()) + { + dataAdapter.Fill(dataSet, "${otherTable}"); + + DataTable dataTable = dataSet.Tables\["${otherTable}"\]; + + dataTable.Columns\["x"\].Unique = true; + dataTable.PrimaryKey = new DataColumn\[\] { + dataTable.Columns\["x"\] + }; + + [expr {[isMono] ? "#pragma warning disable 219" : ""}] + SQLiteCommandBuilder commandBuilder = + new SQLiteCommandBuilder(dataAdapter); + [expr {[isMono] ? "#pragma warning restore 219" : ""}] + + foreach (DataRow dataRow in dataTable.Rows) + { + // + // NOTE: Update even rows and delete odd rows. + // + if ((long)dataRow\["x"\] % 2 == 0) + dataRow\["y"\] = + DateTime.UtcNow.ToString("[getDateTimeFormat]"); + else + dataRow.Delete(); + } + + dataAdapter.Update(dataTable); // DBConcurrencyException (?) + } + } + } + } + } + } + }] results errors System.Data.SQLite.dll] + + list $code $results \ + [expr {[info exists errors] ? $errors : ""}] \ + [expr {$code eq "Ok" ? [catch { + object invoke _Dynamic${id}.Test${id} Main + } result] : [set result ""]}] $result +} -cleanup { + cleanupDb $otherFileName + cleanupDb $fileName + + unset -nocomplain result code results errors i sql otherTable otherDbName \ + otherDataSource dataSource id db otherFileName fileName +} -constraints \ +{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -match \ +regexp -result {^Ok System#CodeDom#Compiler#CompilerResults#\d+ \{\} 0 \{\}$}} + +############################################################################### + +runTest {test tkt-343d392b51-3.1 {attached database, same table name} -setup { + setupDb [set fileName tkt-343d392b51-3.1.db] + set otherFileName tkt-343d392b51-3.1-otherDb.db +} -body { + set otherDataSource [file join [getTemporaryPath] $otherFileName] + set otherDbName otherDb + set otherTable [appendArgs $otherDbName .t1] + + set sql(inserts) "" + set sql(1) [subst { \ + CREATE TABLE t1(x INTEGER PRIMARY KEY); \ + ATTACH DATABASE '${otherDataSource}' AS ${otherDbName}; \ + CREATE TABLE ${otherTable}(x INTEGER PRIMARY KEY); \ + [for {set i 1} {$i < 3} {incr i} { + append sql(inserts) [appendArgs \ + "INSERT INTO t1 (x) VALUES(" $i "); "] + + append sql(inserts) [appendArgs \ + "INSERT INTO " ${otherTable} " (x) VALUES(" [expr {$i * 2}] "); "] + }; return [expr {[info exists sql(inserts)] ? $sql(inserts) : ""}]] \ + }] + + sql execute $db $sql(1) + + list [sql execute -execute reader -format list $db "SELECT x FROM t1;"] \ + [sql execute -execute reader -format list $db [appendArgs \ + "SELECT x FROM " ${otherTable} ";"]] +} -cleanup { + cleanupDb $otherFileName + cleanupDb $fileName + + unset -nocomplain i sql otherTable otherDbName otherDataSource db \ + otherFileName fileName +} -constraints \ +{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \ +{{1 2} {2 4}}} + +############################################################################### + +runTest {test tkt-343d392b51-3.2 {adapter, attached db, table names} -setup { + setupDb [set fileName tkt-343d392b51-3.2.db] + set otherFileName tkt-343d392b51-3.2-otherDb.db +} -body { + set id [object invoke Interpreter.GetActive NextId] + set dataSource [file join [getTemporaryPath] $fileName] + set otherDataSource [file join [getTemporaryPath] $otherFileName] + set otherDbName otherDb + set otherTable [appendArgs $otherDbName .t1] + + set sql(inserts) "" + set sql(1) [subst { \ + CREATE TABLE t1(x INTEGER PRIMARY KEY); \ + ATTACH DATABASE '${otherDataSource}' AS ${otherDbName}; \ + CREATE TABLE ${otherTable}(x INTEGER PRIMARY KEY); \ + [for {set i 1} {$i < 3} {incr i} { + append sql(inserts) [appendArgs \ + "INSERT INTO t1 (x) VALUES(" $i ");"] + append sql(inserts) [appendArgs \ + "INSERT INTO " ${otherTable} " (x) VALUES(" [expr {$i * 2}] "); "] + }; return [expr {[info exists sql(inserts)] ? $sql(inserts) : ""}]] \ + }] + + set sql(2) [subst { \ + SELECT x FROM ${otherTable} ORDER BY x; \ + }] + + unset -nocomplain results errors + + set code [compileCSharpWith [subst { + using System; + using System.Data; + using System.Data.SQLite; + + namespace _Dynamic${id} + { + public class Test${id} + { + public static void Main() + { + using (SQLiteConnection connection = new SQLiteConnection( + "Data Source=${dataSource};")) + { + connection.Open(); + + using (SQLiteCommand command = connection.CreateCommand()) + { + command.CommandText = "${sql(1)}"; + command.ExecuteNonQuery(); + } + + using (SQLiteDataAdapter dataAdapter = new SQLiteDataAdapter( + "${sql(2)}", connection)) + { + using (DataSet dataSet = new DataSet()) + { + dataAdapter.Fill(dataSet, "${otherTable}"); + + DataTable dataTable = dataSet.Tables\["${otherTable}"\]; + + dataTable.Columns\["x"\].Unique = true; + dataTable.PrimaryKey = new DataColumn\[\] { + dataTable.Columns\["x"\] + }; + + [expr {[isMono] ? "#pragma warning disable 219" : ""}] + SQLiteCommandBuilder commandBuilder = + new SQLiteCommandBuilder(dataAdapter); + [expr {[isMono] ? "#pragma warning restore 219" : ""}] + + foreach (DataRow dataRow in dataTable.Rows) + dataRow.Delete(); + + dataAdapter.Update(dataTable); // DBConcurrencyException (?) + } + } + } + } + } + } + }] results errors System.Data.SQLite.dll] + + list $code $results \ + [expr {[info exists errors] ? $errors : ""}] \ + [expr {$code eq "Ok" ? [catch { + object invoke _Dynamic${id}.Test${id} Main + } result] : [set result ""]}] $result +} -cleanup { + cleanupDb $otherFileName + cleanupDb $fileName + + unset -nocomplain result code results errors i sql otherTable otherDbName \ + otherDataSource dataSource id db otherFileName fileName +} -constraints \ +{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -match \ +regexp -result {^Ok System#CodeDom#Compiler#CompilerResults#\d+ \{\} 0 \{\}$}} + +############################################################################### + +runSQLiteTestEpilogue +runTestEpilogue Index: Tests/tkt-448d663d11.eagle ================================================================== --- Tests/tkt-448d663d11.eagle +++ Tests/tkt-448d663d11.eagle @@ -34,11 +34,11 @@ runTest {test tkt-448d663d11-1.2 {missing journal mode, WAL db} -body { set fileName tkt-448d663d11-1.2.db file copy -force [file join $path wal.db] \ [file join [getTemporaryPath] $fileName] - setupDb $fileName "" false + setupDb $fileName "" "" "" "" false sql execute -execute scalar $db "PRAGMA journal_mode;" } -cleanup { cleanupDb $fileName unset -nocomplain db fileName } -constraints \ @@ -49,11 +49,11 @@ runTest {test tkt-448d663d11-1.3 {missing journal mode, non-WAL db} -body { set fileName tkt-448d663d11-1.3.db file copy -force [file join $path nonWal.db] \ [file join [getTemporaryPath] $fileName] - setupDb $fileName "" false + setupDb $fileName "" "" "" "" false sql execute -execute scalar $db "PRAGMA journal_mode;" } -cleanup { cleanupDb $fileName unset -nocomplain db fileName } -constraints \ @@ -76,11 +76,11 @@ runTest {test tkt-448d663d11-1.5 {'Default' journal mode, WAL db} -body { set fileName tkt-448d663d11-1.5.db file copy -force [file join $path wal.db] \ [file join [getTemporaryPath] $fileName] - setupDb $fileName Default false + setupDb $fileName Default "" "" "" false sql execute -execute scalar $db "PRAGMA journal_mode;" } -cleanup { cleanupDb $fileName unset -nocomplain db fileName } -constraints \ @@ -91,11 +91,11 @@ runTest {test tkt-448d663d11-1.6 {'Default' journal mode, non-WAL db} -body { set fileName tkt-448d663d11-1.6.db file copy -force [file join $path nonWal.db] \ [file join [getTemporaryPath] $fileName] - setupDb $fileName Default false + setupDb $fileName Default "" "" "" false sql execute -execute scalar $db "PRAGMA journal_mode;" } -cleanup { cleanupDb $fileName unset -nocomplain db fileName } -constraints \ @@ -118,11 +118,11 @@ runTest {test tkt-448d663d11-1.8 {'Delete' journal mode, WAL db} -body { set fileName tkt-448d663d11-1.8.db file copy -force [file join $path wal.db] \ [file join [getTemporaryPath] $fileName] - setupDb $fileName Delete false + setupDb $fileName Delete "" "" "" false sql execute -execute scalar $db "PRAGMA journal_mode;" } -cleanup { cleanupDb $fileName unset -nocomplain db fileName } -constraints \ @@ -133,11 +133,11 @@ runTest {test tkt-448d663d11-1.9 {'Delete' journal mode, non-WAL db} -body { set fileName tkt-448d663d11-1.9.db file copy -force [file join $path nonWal.db] \ [file join [getTemporaryPath] $fileName] - setupDb $fileName Delete false + setupDb $fileName Delete "" "" "" false sql execute -execute scalar $db "PRAGMA journal_mode;" } -cleanup { cleanupDb $fileName unset -nocomplain db fileName } -constraints \ @@ -208,11 +208,11 @@ runTest {test tkt-448d663d11-1.15 {'Wal' journal mode, non-WAL db} -body { set fileName tkt-448d663d11-1.15.db file copy -force [file join $path nonWal.db] \ [file join [getTemporaryPath] $fileName] - setupDb $fileName Wal false + setupDb $fileName Wal "" "" "" false sql execute -execute scalar $db "PRAGMA journal_mode;" } -cleanup { cleanupDb $fileName unset -nocomplain db fileName } -constraints \ @@ -223,11 +223,11 @@ runTest {test tkt-448d663d11-1.16 {'Wal' journal mode, WAL db} -body { set fileName tkt-448d663d11-1.16.db file copy -force [file join $path wal.db] \ [file join [getTemporaryPath] $fileName] - setupDb $fileName Wal false + setupDb $fileName Wal "" "" "" false sql execute -execute scalar $db "PRAGMA journal_mode;" } -cleanup { cleanupDb $fileName unset -nocomplain db fileName } -constraints \ @@ -250,11 +250,11 @@ runTest {test tkt-448d663d11-1.18 {'Bad' journal mode, non-WAL db} -body { set fileName tkt-448d663d11-1.18.db file copy -force [file join $path nonWal.db] \ [file join [getTemporaryPath] $fileName] - setupDb $fileName Bad false + setupDb $fileName Bad "" "" "" false sql execute -execute scalar $db "PRAGMA journal_mode;" } -cleanup { cleanupDb $fileName unset -nocomplain db fileName } -constraints \ @@ -265,11 +265,11 @@ runTest {test tkt-448d663d11-1.19 {'Bad' journal mode, WAL db} -body { set fileName tkt-448d663d11-1.19.db file copy -force [file join $path wal.db] \ [file join [getTemporaryPath] $fileName] - setupDb $fileName Bad false + setupDb $fileName Bad "" "" "" false sql execute -execute scalar $db "PRAGMA journal_mode;" } -cleanup { cleanupDb $fileName unset -nocomplain db fileName } -constraints \ Index: Tests/tkt-b4a7ddc83f.eagle ================================================================== --- Tests/tkt-b4a7ddc83f.eagle +++ Tests/tkt-b4a7ddc83f.eagle @@ -30,14 +30,14 @@ } ############################################################################### for {set i 1} {$i < 3} {incr i} { - runTest {test tkt-b4a7ddc83f-1.$i {logging shutdown} -setup \ + runTest {test [appendArgs tkt-b4a7ddc83f-1. $i] {logging shutdown} -setup \ [getAppDomainPreamble { set appDomainId(1) {[object invoke AppDomain.CurrentDomain Id]} - set fileName {tkt-b4a7ddc83f-1.$i.db} + set fileName {[appendArgs tkt-b4a7ddc83f-1. $i .db]} }] -body { set appDomainId(2) [object invoke AppDomain.CurrentDomain Id] package require EagleLibrary package require EagleTest