System.Data.SQLite

Check-in [4f933521a1]
Login

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

Overview
Comment:Add DateTimeFormatString connection string property to allow the DateTime format string used for all parsing and formatting to be overridden. Disable use of the new connection string parsing algorithm when the No_SQLiteConnectionNewParser environment variable is set. Pursuant to [bbdda6eae2].
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 4f933521a13694bc2a9cc7fb0053020f7ea75fa2
User & Date: mistachkin 2013-05-30 00:44:55.904
Context
2013-06-22
03:36
Update several wiki pages. check-in: ef62d192d4 user: mistachkin tags: trunk
2013-06-03
01:57
Initial phase of experimental support for implementing virtual tables in managed code. No docs, no tests, does not work yet, and may not even compile. check-in: 273b0c601f user: mistachkin tags: virtualTables
2013-05-30
00:44
Add DateTimeFormatString connection string property to allow the DateTime format string used for all parsing and formatting to be overridden. Disable use of the new connection string parsing algorithm when the No_SQLiteConnectionNewParser environment variable is set. Pursuant to [bbdda6eae2]. check-in: 4f933521a1 user: mistachkin tags: trunk
2013-05-29
23:04
Honor the DateTimeFormat and DateTimeKind connection string properties even when the BindAllAsText connection flag is in use. check-in: d81d546e99 user: mistachkin tags: trunk
Changes
Side-by-Side Diff Ignore Whitespace Patch
Changes to Doc/Extra/environment.html.
70
71
72
73
74
75
76






77
78
79
80
81
82
83
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89







+
+
+
+
+
+







          <td>If this environment variable is set [to anything], the native
          library pre-loading functionality will be disabled.  By default,
          the native library pre-loading will attempt to load the native
          SQLite library from architecture-specific (e.g. "x86", "amd64",
          "x64") or platform-specific (e.g. "Win32") directories that reside
          underneath the application base directory.</td>
        </tr>
        <tr valign="top">
          <td>No_SQLiteConnectionNewParser</td>
          <td>If this environment variable is set [to anything], the new
          connection string parsing algorithm will not be used.  This
          environment variable is intended for use with legacy code only.</td>
        </tr>
        <tr valign="top">
          <td>No_SQLiteFunctions</td>
          <td>If this environment variable is set [to anything], the initial
          search for types in all loaded assemblies that are tagged with the
          SQLiteFunction attribute will be skipped.  Normally, this search is
          conducted only once per application domain by the static constructor
          of the SQLiteFunction class; however, these implementation details
Changes to Doc/Extra/version.html.
42
43
44
45
46
47
48


49
50
51
52
53
54
55
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57







+
+







    </div>
    <div id="mainSection">
    <div id="mainBody">
    <h1 class="heading">Version History</h1>
    <p><b>1.0.87.0 - June XX, 2013 <font color="red">(release scheduled)</font></b></p>
    <ul>
      <li>The DbType to type name translation needs to prioritize the Entity Framework type names. Fix for <a href="http://system.data.sqlite.org/index.html/info/47f4bac575">[47f4bac575]</a>.</li>
      <li>Add DateTimeFormatString connection string property to allow the DateTime format string used for all parsing and formatting to be overridden.</li>
      <li>Disable use of the new connection string parsing algorithm when the No_SQLiteConnectionNewParser environment variable is set. Pursuant to <a href="http://system.data.sqlite.org/index.html/info/bbdda6eae2">[bbdda6eae2]</a>.</li>
    </ul>
    <p><b>1.0.86.0 - May 23, 2013</b></p>
    <ul>
      <li>Updated to <a href="http://www.sqlite.org/releaselog/3_7_17.html">SQLite 3.7.17</a>.</li>
      <li>Disable use of the AllowPartiallyTrustedCallers attribute when compiled for the .NET Framework 4.0/4.5.&nbsp;<b>** Potentially Incompatible Change **</b></li>
      <li>Allow semi-colons in the data source file name. Fix for <a href="http://system.data.sqlite.org/index.html/info/48a6b8e4ca">[e47b3d8346]</a>.&nbsp;<b>** Potentially Incompatible Change **</b></li>
      <li>NULL values should be reported as type &quot;object&quot;, not &quot;DBNull&quot;. Fix for <a href="http://system.data.sqlite.org/index.html/info/48a6b8e4ca">[48a6b8e4ca]</a>.</li>
Changes to System.Data.SQLite/SQLite3.cs.
73
74
75
76
77
78
79
80
81


82
83
84
85
86
87
88
73
74
75
76
77
78
79


80
81
82
83
84
85
86
87
88







-
-
+
+







#endif

    /// <summary>
    /// The user-defined functions registered on this connection
    /// </summary>
    protected SQLiteFunction[] _functionsArray;

    internal SQLite3(SQLiteDateFormats fmt, DateTimeKind kind)
      : base(fmt, kind)
    internal SQLite3(SQLiteDateFormats fmt, DateTimeKind kind, string fmtString)
      : base(fmt, kind, fmtString)
    {
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////

    #region IDisposable "Pattern" Members
    private bool disposed;
Changes to System.Data.SQLite/SQLite3_UTF16.cs.
17
18
19
20
21
22
23
24
25


26
27
28
29
30
31
32
17
18
19
20
21
22
23


24
25
26
27
28
29
30
31
32







-
-
+
+







  using System.Runtime.InteropServices;

  /// <summary>
  /// Alternate SQLite3 object, overriding many text behaviors to support UTF-16 (Unicode)
  /// </summary>
  internal sealed class SQLite3_UTF16 : SQLite3
  {
    internal SQLite3_UTF16(SQLiteDateFormats fmt, DateTimeKind kind)
      : base(fmt, kind)
    internal SQLite3_UTF16(SQLiteDateFormats fmt, DateTimeKind kind, string fmtString)
      : base(fmt, kind, fmtString)
    {
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////

    #region IDisposable "Pattern" Members
    private bool disposed;
Changes to System.Data.SQLite/SQLiteBase.cs.
15
16
17
18
19
20
21
22
23


24
25
26
27
28
29
30
15
16
17
18
19
20
21


22
23
24
25
26
27
28
29
30







-
-
+
+








  /// <summary>
  /// 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.
  /// </summary>
  internal abstract class SQLiteBase : SQLiteConvert, IDisposable
  {
    internal SQLiteBase(SQLiteDateFormats fmt, DateTimeKind kind)
      : base(fmt, kind) { }
    internal SQLiteBase(SQLiteDateFormats fmt, DateTimeKind kind, string fmtString)
      : base(fmt, kind, fmtString) { }

    /// <summary>
    /// Returns a string representing the active version of SQLite
    /// </summary>
    internal abstract string Version { get; }
    /// <summary>
    /// Returns an integer representing the active version of SQLite
Changes to System.Data.SQLite/SQLiteConnection.cs.
144
145
146
147
148
149
150







151
152
153
154
155
156
157
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164







+
+
+
+
+
+
+







  /// </item>
  /// <item>
  /// <description>DateTimeKind</description>
  /// <description><b>Unspecified</b> - Not specified as either UTC or local time.<br/><b>Utc</b> - The time represented is UTC.<br/><b>Local</b> - The time represented is local time.</description>
  /// <description>N</description>
  /// <description>Unspecified</description>
  /// </item>
  /// <item>
  /// <description>DateTimeFormatString</description>
  /// <description>The exact DateTime format string to use for all formatting and parsing of all DateTime
  /// values for this connection.</description>
  /// <description>N</description>
  /// <description>null</description>
  /// </item>
  /// <item>
  /// <description>BaseSchemaName</description>
  /// <description>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.</description>
  /// <description>N</description>
308
309
310
311
312
313
314

315
316
317
318
319
320
321
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329







+








    private const SQLiteConnectionFlags DefaultFlags = SQLiteConnectionFlags.Default;
    private const SQLiteSynchronousEnum DefaultSynchronous = SQLiteSynchronousEnum.Default;
    private const SQLiteJournalModeEnum DefaultJournalMode = SQLiteJournalModeEnum.Default;
    private const IsolationLevel DefaultIsolationLevel = IsolationLevel.Serializable;
    private const SQLiteDateFormats DefaultDateTimeFormat = SQLiteDateFormats.ISO8601;
    private const DateTimeKind DefaultDateTimeKind = DateTimeKind.Unspecified;
    private const string DefaultDateTimeFormatString = null;
    private const string DefaultDataSource = null;
    private const string DefaultUri = null;
    private const string DefaultFullUri = null;
    private const string DefaultHexPassword = null;
    private const string DefaultPassword = null;
    private const int DefaultVersion = 3;
    private const int DefaultPageSize = 1024;
1165
1166
1167
1168
1169
1170
1171







1172
1173
1174
1175
1176
1177
1178
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193







+
+
+
+
+
+
+







    /// </item>
    /// <item>
    /// <description>DateTimeKind</description>
    /// <description><b>Unspecified</b> - Not specified as either UTC or local time.<br/><b>Utc</b> - The time represented is UTC.<br/><b>Local</b> - The time represented is local time.</description>
    /// <description>N</description>
    /// <description>Unspecified</description>
    /// </item>
    /// <item>
    /// <description>DateTimeFormatString</description>
    /// <description>The exact DateTime format string to use for all formatting and parsing of all DateTime
    /// values for this connection.</description>
    /// <description>N</description>
    /// <description>null</description>
    /// </item>
    /// <item>
    /// <description>BaseSchemaName</description>
    /// <description>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.</description>
    /// <description>N</description>
1409
1410
1411
1412
1413
1414
1415







1416

1417
1418

1419




1420
1421
1422
1423
1424
1425
1426
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437

1438
1439
1440
1441

1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452







+
+
+
+
+
+
+
-
+


+
-
+
+
+
+







    {
      string s = connectionString;
      int n;
      SortedList<string, string> ls = new SortedList<string, string>(StringComparer.OrdinalIgnoreCase);

      // First split into semi-colon delimited values.
      string error = null;
      string[] arParts;

#if !PLATFORM_COMPACTFRAMEWORK
      if (Environment.GetEnvironmentVariable("No_SQLiteConnectionNewParser") != null)
          arParts = SQLiteConvert.Split(s, ';');
      else
#endif
      string[] arParts = SQLiteConvert.NewSplit(s, ';', true, ref error);
          arParts = SQLiteConvert.NewSplit(s, ';', true, ref error);

      if (arParts == null)
      {
          throw new ArgumentException(String.Format("Invalid ConnectionString format, cannot parse: {0}", error));
          throw new ArgumentException(String.Format(
              "Invalid ConnectionString format, cannot parse: {0}", (error != null) ?
              error : "could not split connection string into properties"));
      }

      int x = (arParts != null) ? arParts.Length : 0;
      // For each semi-colon piece, split into key and value pairs by the presence of the = sign
      for (n = 0; n < x; n++)
      {
        if (arParts[n] == null)
          continue;
1866
1867
1868
1869
1870
1871
1872



1873
1874
1875
1876
1877
1878
1879
1880

1881
1882
1883
1884

1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908

1909
1910
1911
1912

1913
1914
1915
1916
1917
1918
1919
1920







+
+
+







-
+



-
+








            enumValue = TryParseEnum(typeof(DateTimeKind), FindKey(opts,
                "DateTimeKind", DefaultDateTimeKind.ToString()), true);

            DateTimeKind kind = (enumValue is DateTimeKind) ?
                (DateTimeKind)enumValue : DefaultDateTimeKind;

            string dateTimeFormat = FindKey(opts, "DateTimeFormatString",
                DefaultDateTimeFormatString);

            //
            // NOTE: SQLite automatically sets the encoding of the database to
            //       UTF16 if called from sqlite3_open16().
            //
            if (SQLiteConvert.ToBoolean(FindKey(opts, "UseUTF16Encoding",
                      DefaultUseUTF16Encoding.ToString())))
            {
                _sql = new SQLite3_UTF16(dateFormat, kind);
                _sql = new SQLite3_UTF16(dateFormat, kind, dateTimeFormat);
            }
            else
            {
                _sql = new SQLite3(dateFormat, kind);
                _sql = new SQLite3(dateFormat, kind, dateTimeFormat);
            }
        }

        SQLiteOpenFlagsEnum flags = SQLiteOpenFlagsEnum.None;

        if (!SQLiteConvert.ToBoolean(FindKey(opts, "FailIfMissing", DefaultFailIfMissing.ToString())))
          flags |= SQLiteOpenFlagsEnum.Create;
2295
2296
2297
2298
2299
2300
2301



2302
2303
2304
2305
2306
2307
2308
2309

2310
2311
2312
2313

2314
2315
2316
2317
2318
2319
2320
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340

2341
2342
2343
2344

2345
2346
2347
2348
2349
2350
2351
2352







+
+
+







-
+



-
+








            enumValue = TryParseEnum(typeof(DateTimeKind), FindKey(opts,
                "DateTimeKind", DefaultDateTimeKind.ToString()), true);

            DateTimeKind kind = (enumValue is DateTimeKind) ?
                (DateTimeKind)enumValue : DefaultDateTimeKind;

            string dateTimeFormat = FindKey(opts, "DateTimeFormatString",
                DefaultDateTimeFormatString);

            //
            // NOTE: SQLite automatically sets the encoding of the database to
            //       UTF16 if called from sqlite3_open16().
            //
            if (SQLiteConvert.ToBoolean(FindKey(opts,
                    "UseUTF16Encoding", DefaultUseUTF16Encoding.ToString())))
            {
                _sql = new SQLite3_UTF16(dateFormat, kind);
                _sql = new SQLite3_UTF16(dateFormat, kind, dateTimeFormat);
            }
            else
            {
                _sql = new SQLite3(dateFormat, kind);
                _sql = new SQLite3(dateFormat, kind, dateTimeFormat);
            }
        }
        if (_sql != null) return _sql.Shutdown();
        throw new InvalidOperationException("Database connection not active.");
    }

    /// Enables or disabled extended result codes returned by SQLite
Changes to System.Data.SQLite/SQLiteConnectionStringBuilder.cs.
486
487
488
489
490
491
492




























493
494
495
496
497
498
499
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







            return DateTimeKind.Unspecified;
        }
        set
        {
            this["datetimekind"] = value;
        }
    }

    /// <summary>
    /// Gets/sets the DateTime format string used for formatting
    /// and parsing purposes.
    /// </summary>
    [Browsable(true)]
    [DefaultValue(null)]
    public string DateTimeFormatString
    {
        get
        {
            object value;

            if (TryGetValue("datetimeformatstring", out value))
            {
                if (value is string)
                    return (string)value;
                else if (value != null)
                    return value.ToString();
            }

            return null;
        }
        set
        {
            this["datetimeformatstring"] = value;
        }
    }

    /// <summary>
    /// Gets/Sets the placeholder base schema name used for
    /// .NET Framework compatibility purposes.
    /// </summary>
    [Browsable(true)]
    [DefaultValue(SQLiteConnection.DefaultBaseSchemaName)]
Changes to System.Data.SQLite/SQLiteConvert.cs.
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
116
117
118
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
116
117
118
119
120
121
122
123
124
125
126
127
128







-
+







+
+
+
+




+
-
+
+
+
+
+



+







    private static readonly string _datetimeFormatLocal = _datetimeFormats[19];

    /// <summary>
    /// An UTF-8 Encoding instance, so we can convert strings to and from UTF-8
    /// </summary>
    private static Encoding _utf8 = new UTF8Encoding();
    /// <summary>
    /// The default DateTime format for this instance
    /// The default DateTime format for this instance.
    /// </summary>
    internal SQLiteDateFormats _datetimeFormat;
    /// <summary>
    /// The default DateTimeKind for this instance.
    /// </summary>
    internal DateTimeKind _datetimeKind;
    /// <summary>
    /// The default DateTime format string for this instance.
    /// </summary>
    internal string _datetimeFormatString = null;
    /// <summary>
    /// Initializes the conversion class
    /// </summary>
    /// <param name="fmt">The default date/time format to use for this instance</param>
    /// <param name="kind">The DateTimeKind to use.</param>
    /// <param name="fmtString">The DateTime format string to use.</param>
    internal SQLiteConvert(SQLiteDateFormats fmt, DateTimeKind kind)
    internal SQLiteConvert(
        SQLiteDateFormats fmt,
        DateTimeKind kind,
        string fmtString
        )
    {
      _datetimeFormat = fmt;
      _datetimeKind = kind;
      _datetimeFormatString = fmtString;
    }

    #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>
181
182
183
184
185
186
187
188


189
190
191
192
193
194
195
191
192
193
194
195
196
197

198
199
200
201
202
203
204
205
206







-
+
+







    }


    #endregion

    #region DateTime Conversion Functions
    /// <summary>
    /// Converts a string into a DateTime, using the current DateTimeFormat specified for the connection when it was opened.
    /// Converts a string into a DateTime, using the DateTimeFormat, DateTimeKind,
    /// and DateTimeFormatString specified for the connection when it was opened.
    /// </summary>
    /// <remarks>
    /// Acceptable ISO8601 DateTime formats are:
    /// <list type="bullet">
    /// <item><description>THHmmssK</description></item>
    /// <item><description>THHmmK</description></item>
    /// <item><description>HH:mm:ss.FFFFFFFK</description></item>
218
219
220
221
222
223
224
225



226
227
228
229
230
231
232
233
234

235
236
237
238


239
240
241
242
243
244
245
229
230
231
232
233
234
235

236
237
238
239
240
241
242
243
244
245
246

247
248
249
250

251
252
253
254
255
256
257
258
259







-
+
+
+








-
+



-
+
+







    /// <item><description>yyyyMMddHHmmss</description></item>
    /// <item><description>yyyyMMddHHmm</description></item>
    /// <item><description>yyyyMMddTHHmmssFFFFFFF</description></item>
    /// <item><description>yyyy-MM-dd</description></item>
    /// <item><description>yyyyMMdd</description></item>
    /// <item><description>yy-MM-dd</description></item>
    /// </list>
    /// If the string cannot be matched to one of the above formats, an exception will be thrown.
    /// If the string cannot be matched to one of the above formats -OR-
    /// the DateTimeFormatString if one was provided, an exception will
    /// be thrown.
    /// </remarks>
    /// <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)
    {
      return ToDateTime(dateText, _datetimeFormat, _datetimeKind);
      return ToDateTime(dateText, _datetimeFormat, _datetimeKind, _datetimeFormatString);
    }

    /// <summary>
    /// Converts a string into a DateTime, using the specified DateTimeFormat and DateTimeKind.
    /// Converts a string into a DateTime, using the specified DateTimeFormat,
    /// DateTimeKind and DateTimeFormatString.
    /// </summary>
    /// <remarks>
    /// Acceptable ISO8601 DateTime formats are:
    /// <list type="bullet">
    /// <item><description>THHmmssK</description></item>
    /// <item><description>THHmmK</description></item>
    /// <item><description>HH:mm:ss.FFFFFFFK</description></item>
268
269
270
271
272
273
274
275



276
277
278
279
280
281
282

283
284






285
286
287
288
289
290
291
282
283
284
285
286
287
288

289
290
291
292
293
294
295
296
297
298
299
300

301
302
303
304
305
306
307
308
309
310
311
312
313







-
+
+
+







+

-
+
+
+
+
+
+







    /// <item><description>yyyyMMddHHmmss</description></item>
    /// <item><description>yyyyMMddHHmm</description></item>
    /// <item><description>yyyyMMddTHHmmssFFFFFFF</description></item>
    /// <item><description>yyyy-MM-dd</description></item>
    /// <item><description>yyyyMMdd</description></item>
    /// <item><description>yy-MM-dd</description></item>
    /// </list>
    /// If the string cannot be matched to one of the above formats, an exception will be thrown.
    /// If the string cannot be matched to one of the above formats -OR-
    /// the DateTimeFormatString if one was provided, an exception will
    /// be thrown.
    /// </remarks>
    /// <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>
    /// <param name="format">The SQLiteDateFormats to use.</param>
    /// <param name="kind">The DateTimeKind to use.</param>
    /// <param name="formatString">The DateTime format string to use.</param>
    /// <returns>A DateTime value</returns>
    public static DateTime ToDateTime(string dateText, SQLiteDateFormats format, DateTimeKind kind)
    public static DateTime ToDateTime(
        string dateText,
        SQLiteDateFormats format,
        DateTimeKind kind,
        string formatString
        )
    {
        switch (format)
        {
            case SQLiteDateFormats.Ticks:
                {
                    return new DateTime(Convert.ToInt64(
                        dateText, CultureInfo.InvariantCulture), kind);
299
300
301
302
303
304
305









306
307
308
309
310
311






312
313
314









315
316
317
318
319
320






321
322
323

324
325
326
327
328
329
330















331
332
333
334
335
336
337
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336






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







+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+



+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+



+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







                {
                    return DateTime.SpecifyKind(
                        UnixEpoch.AddSeconds(Convert.ToInt32(
                        dateText, CultureInfo.InvariantCulture)), kind);
                }
            case SQLiteDateFormats.InvariantCulture:
                {
                    if (formatString != null)
                        return DateTime.SpecifyKind(DateTime.ParseExact(
                            dateText, formatString,
                            DateTimeFormatInfo.InvariantInfo,
                            kind == DateTimeKind.Utc ?
                                DateTimeStyles.AdjustToUniversal :
                                DateTimeStyles.None),
                            kind);
                    else
                    return DateTime.SpecifyKind(DateTime.Parse(
                        dateText, DateTimeFormatInfo.InvariantInfo,
                        kind == DateTimeKind.Utc ?
                            DateTimeStyles.AdjustToUniversal :
                            DateTimeStyles.None),
                        kind);
                        return DateTime.SpecifyKind(DateTime.Parse(
                            dateText, DateTimeFormatInfo.InvariantInfo,
                            kind == DateTimeKind.Utc ?
                                DateTimeStyles.AdjustToUniversal :
                                DateTimeStyles.None),
                            kind);
                }
            case SQLiteDateFormats.CurrentCulture:
                {
                    if (formatString != null)
                        return DateTime.SpecifyKind(DateTime.ParseExact(
                            dateText, formatString,
                            DateTimeFormatInfo.CurrentInfo,
                            kind == DateTimeKind.Utc ?
                                DateTimeStyles.AdjustToUniversal :
                                DateTimeStyles.None),
                            kind);
                    else
                    return DateTime.SpecifyKind(DateTime.Parse(
                        dateText, DateTimeFormatInfo.CurrentInfo,
                        kind == DateTimeKind.Utc ?
                            DateTimeStyles.AdjustToUniversal :
                            DateTimeStyles.None),
                        kind);
                        return DateTime.SpecifyKind(DateTime.Parse(
                            dateText, DateTimeFormatInfo.CurrentInfo,
                            kind == DateTimeKind.Utc ?
                                DateTimeStyles.AdjustToUniversal :
                                DateTimeStyles.None),
                            kind);
                }
            default: /* ISO-8601 */
                {
                    if (formatString != null)
                    return DateTime.SpecifyKind(DateTime.ParseExact(
                        dateText, _datetimeFormats,
                        DateTimeFormatInfo.InvariantInfo,
                        kind == DateTimeKind.Utc ?
                            DateTimeStyles.AdjustToUniversal :
                            DateTimeStyles.None),
                        kind);
                        return DateTime.SpecifyKind(DateTime.ParseExact(
                            dateText, formatString,
                            DateTimeFormatInfo.InvariantInfo,
                            kind == DateTimeKind.Utc ?
                                DateTimeStyles.AdjustToUniversal :
                                DateTimeStyles.None),
                            kind);
                    else
                        return DateTime.SpecifyKind(DateTime.ParseExact(
                            dateText, _datetimeFormats,
                            DateTimeFormatInfo.InvariantInfo,
                            kind == DateTimeKind.Utc ?
                                DateTimeStyles.AdjustToUniversal :
                                DateTimeStyles.None),
                            kind);
                }
        }
    }

    /// <summary>
    /// Converts a julianday value into a DateTime
    /// </summary>
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
404
405
406
407
408

409

410

411

412
413
414
415
416




417
418
419
420
421
422
423
421
422
423
424
425
426
427


428
429
430
431
432
433

434
435

436
437
438
439
440
441
442
443
444
445
446

447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464

465
466
467

468
469
470
471


472
473
474
475
476
477
478
479
480
481
482







-
-
+
+


+

-
+

-
+
+
+
+

+




+
-
+
















+
-
+

+
-
+



-
-
+
+
+
+







    /// <returns>The whole number of seconds since the Unix epoch</returns>
    public static long ToUnixEpoch(DateTime value)
    {
        return (value.Subtract(UnixEpoch).Ticks / TimeSpan.TicksPerSecond);
    }

    /// <summary>
    /// Returns the default DateTime format string to use for the specified
    /// DateTimeKind.
    /// Returns the DateTime format string to use for the specified DateTimeKind.
    /// If <paramref name="formatString"/> is not null, it will be returned verbatim.
    /// </summary>
    /// <param name="kind">The DateTimeKind to use.</param>
    /// <param name="formatString">The DateTime format string to use.</param>
    /// <returns>
    /// The default DateTime format string to use for the specified DateTimeKind.
    /// The DateTime format string to use for the specified DateTimeKind.
    /// </returns>
    private static string GetDateTimeKindFormat(DateTimeKind kind)
    private static string GetDateTimeKindFormat(
        DateTimeKind kind,
        string formatString
        )
    {
        if (formatString != null) return formatString;
        return (kind == DateTimeKind.Utc) ? _datetimeFormatUtc : _datetimeFormatLocal;
    }

    /// <summary>
    /// Converts a string into a DateTime, using the DateTimeFormat, DateTimeKind,
    /// Converts a DateTime to a string value, using the current DateTimeFormat specified for the connection when it was opened.
    /// and DateTimeFormatString 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
    /// string, a formatted date and time string in the current culture, or an ISO8601-format date/time string.</returns>
    public string ToString(DateTime dateValue)
    {
        switch (_datetimeFormat)
        {
            case SQLiteDateFormats.Ticks:
                return dateValue.Ticks.ToString(CultureInfo.InvariantCulture);
            case SQLiteDateFormats.JulianDay:
                return ToJulianDay(dateValue).ToString(CultureInfo.InvariantCulture);
            case SQLiteDateFormats.UnixEpoch:
                return ((long)(dateValue.Subtract(UnixEpoch).Ticks / TimeSpan.TicksPerSecond)).ToString();
            case SQLiteDateFormats.InvariantCulture:
                return dateValue.ToString((_datetimeFormatString != null) ?
                return dateValue.ToString(FullFormat, CultureInfo.InvariantCulture);
                    _datetimeFormatString : FullFormat, CultureInfo.InvariantCulture);
            case SQLiteDateFormats.CurrentCulture:
                return dateValue.ToString((_datetimeFormatString != null) ?
                return dateValue.ToString(FullFormat, CultureInfo.CurrentCulture);
                    _datetimeFormatString : FullFormat, CultureInfo.CurrentCulture);
            default:
                return (dateValue.Kind == DateTimeKind.Unspecified) ?
                    DateTime.SpecifyKind(dateValue, _datetimeKind).ToString(
                        GetDateTimeKindFormat(_datetimeKind), CultureInfo.InvariantCulture) :
                    dateValue.ToString(GetDateTimeKindFormat(dateValue.Kind), CultureInfo.InvariantCulture);
                        GetDateTimeKindFormat(_datetimeKind, _datetimeFormatString),
                            CultureInfo.InvariantCulture) : dateValue.ToString(
                        GetDateTimeKindFormat(dateValue.Kind, _datetimeFormatString),
                            CultureInfo.InvariantCulture);
        }
    }

    /// <summary>
    /// Internal function to convert a UTF-8 encoded IntPtr of the specified length to a DateTime.
    /// </summary>
    /// <remarks>
863
864
865
866
867
868
869





870
871
872
873
874
875
876
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940







+
+
+
+
+







      0,            // VarNumeric (21)
      DBNull.Value, // AnsiStringFixedLength (22)
      DBNull.Value, // StringFixedLength (23)
      DBNull.Value, // ?? (24)
      DBNull.Value  // Xml (25)
    };

    /// <summary>
    /// Determines the type name for the given database value type.
    /// </summary>
    /// <param name="typ">The database value type.</param>
    /// <returns>The type name or an empty string if it cannot be determined.</returns>
    internal static string DbTypeToTypeName(DbType typ)
    {
        lock (_syncRoot)
        {
            if (_typeNames == null)
                _typeNames = GetSQLiteDbTypeMap();

967
968
969
970
971
972
973
974

975
976
977
978

979
980
981
982
983
984
985
1031
1032
1033
1034
1035
1036
1037

1038
1039
1040
1041

1042
1043
1044
1045
1046
1047
1048
1049







-
+



-
+







      TypeAffinity.Double,   // Decimal (15)
      TypeAffinity.DateTime, // DateTime (16)
      TypeAffinity.Null,     // ?? (17)
      TypeAffinity.Text      // String (18)
    };

    /// <summary>
    /// Builds and returns an array containing the database column types
    /// Builds and returns a map containing the database column types
    /// recognized by this provider.
    /// </summary>
    /// <returns>
    /// An array containing the database column types recognized by this
    /// A map containing the database column types recognized by this
    /// provider.
    /// </returns>
    private static SQLiteDbTypeMap GetSQLiteDbTypeMap()
    {
        return new SQLiteDbTypeMap(new SQLiteDbTypeMapping[] {
            new SQLiteDbTypeMapping("BIGINT", DbType.Int64, false),
            new SQLiteDbTypeMapping("BIGUINT", DbType.UInt64, false),
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1490
1491
1492
1493
1494
1495
1496










1497
1498
1499
1500
1501
1502
1503







-
-
-
-
-
-
-
-
-
-







          if (collection == null)
              throw new ArgumentNullException("collection");

          foreach (SQLiteDbTypeMapping item in collection)
              Add(item);
      }

      /////////////////////////////////////////////////////////////////////////

      public new void Add(
          string key, /* IGNORED */
          SQLiteDbTypeMapping value
          )
      {
          Add(value);
      }

      /////////////////////////////////////////////////////////////////////////

      public void Add(SQLiteDbTypeMapping item)
      {
          if (item == null)
              throw new ArgumentNullException("item");

Changes to System.Data.SQLite/SQLiteLog.cs.
177
178
179
180
181
182
183
184

185
186
187
188
189
190
191
177
178
179
180
181
182
183

184
185
186
187
188
189
190
191







-
+







#endif

                //
                // NOTE: Create an instance of the SQLite wrapper class.
                //
                if (_sql == null)
                    _sql = new SQLite3(SQLiteDateFormats.Default,
                        DateTimeKind.Unspecified);
                        DateTimeKind.Unspecified, null);

                //
                // 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
                //       do this once.
                //
Changes to Tests/basic.eagle.
869
870
871
872
873
874
875
876


877
878
879
880
881
882
883
884

885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903









904
905
906
907

908
909
910
911

912
913
914
915
916
917
918
919
920
921
922
923
924


925
926
927
928
929
930
931
869
870
871
872
873
874
875

876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904

905
906
907
908
909
910
911
912
913
914
915
916

917
918
919
920

921




922
923
924
925
926
927
928
929

930
931
932
933
934
935
936
937
938







-
+
+








+


















-
+
+
+
+
+
+
+
+
+



-
+



-
+
-
-
-
-








-
+
+








    namespace _Dynamic${id}
    {
      public static class Test${id}
      {
        public static string GetConnectionString(
          string format,
          string kind
          string kind,
          string formatString
          )
        {
          SQLiteConnectionStringBuilder builder =
              new SQLiteConnectionStringBuilder();

          builder.Add("Date Source", "test.db");
          builder.Add("DateTimeFormat", format);
          builder.Add("DateTimeKind", kind);
          builder.Add("DateTimeFormatString", formatString);

          return builder.ToString();
        }

        ///////////////////////////////////////////////////////////////////////

        public static void Main()
        {
          // do nothing.
        }
      }
    }
  }] true true true 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} GetConnectionString \
            null null
            null null null
      } result] : [set result ""]}] $result \
      [expr {$code eq "Ok" ? [catch {
        object invoke _Dynamic${id}.Test${id} GetConnectionString \
            Default null null
      } result] : [set result ""]}] $result \
      [expr {$code eq "Ok" ? [catch {
        object invoke _Dynamic${id}.Test${id} GetConnectionString \
            null Unspecified null
      } result] : [set result ""]}] $result \
      [expr {$code eq "Ok" ? [catch {
        object invoke _Dynamic${id}.Test${id} GetConnectionString \
            Default null
            ISO8601 Utc null
      } result] : [set result ""]}] $result \
      [expr {$code eq "Ok" ? [catch {
        object invoke _Dynamic${id}.Test${id} GetConnectionString \
            null Unspecified
            Ticks Local yyyy-MM-dd
      } result] : [set result ""]}] $result \
      [expr {$code eq "Ok" ? [catch {
        object invoke _Dynamic${id}.Test${id} GetConnectionString \
            ISO8601 Utc
      } result] : [set result ""]}] $result
} -cleanup {
  unset -nocomplain result results errors code id
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -match \
regexp -result {^Ok System#CodeDom#Compiler#CompilerResults#\d+ \{\} 0 \{Date\
Source=test\.db\} 0 \{Date Source=test\.db;DateTimeFormat=(?:Default|ISO8601)\}\
0 \{Date Source=test\.db;DateTimeKind=Unspecified\} 0 \{Date\
Source=test\.db;DateTimeFormat=(?:Default|ISO8601);DateTimeKind=Utc\}$}}
Source=test\.db;DateTimeFormat=(?:Default|ISO8601);DateTimeKind=Utc\} 0 \{Date\
Source=test\.db;DateTimeFormat=Ticks;DateTimeKind=Local;DateTimeFormatString=yyyy-MM-dd\}$}}

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

runTest {test data-1.16 {SQLiteConnectionStringBuilder properties} -body {
  set id [object invoke Interpreter.GetActive NextId]

  unset -nocomplain results errors
997
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
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
1035
1036
1037







-
-
-
+
+
+





-
+







-
-
-
+
+
+
+







  lappend results $code [expr {[info exists errors] ? $errors : ""}]

  if {$code eq "Ok"} then {
    set keys [list null Version Synchronous UseUTF16Encoding Pooling \
                   BinaryGUID "Data Source" Uri FullUri "Default Timeout" \
                   Enlist FailIfMissing "Legacy Format" "Read Only" \
                   Password "Page Size" "Max Page Count" "Cache Size" \
                   DateTimeFormat DateTimeKind BaseSchemaName \
                   "Journal Mode" "Default IsolationLevel" "Foreign Keys" \
                   Flags SetDefaults ToFullPath HexPassword]
                   DateTimeFormat DateTimeKind DateTimeFormatString \
                   BaseSchemaName "Journal Mode" "Default IsolationLevel" \
                   "Foreign Keys" Flags SetDefaults ToFullPath HexPassword]

    set values [list null 3 Normal True False \
                     True test.db test.db file:test.db 60 \
                     False True False True \
                     secret 4096 1024 8192 \
                     UnixEpoch Utc sqlite_schema \
                     UnixEpoch Utc yyyy-MM-dd sqlite_schema \
                     Memory Serializable False \
                     Default False False 736563726574]

    set propertyNames [list null Version SyncMode UseUTF16Encoding Pooling \
                            BinaryGUID DataSource Uri FullUri DefaultTimeout \
                            Enlist FailIfMissing LegacyFormat ReadOnly \
                            Password PageSize MaxPageCount CacheSize \
                            DateTimeFormat DateTimeKind BaseSchemaName \
                            JournalMode DefaultIsolationLevel ForeignKeys \
                            Flags SetDefaults ToFullPath HexPassword]
                            DateTimeFormat DateTimeKind DateTimeFormatString \
                            BaseSchemaName JournalMode DefaultIsolationLevel \
                            ForeignKeys Flags SetDefaults ToFullPath \
                            HexPassword]

    foreach key $keys value $values propertyName $propertyNames {
      set code [catch {
        object invoke _Dynamic${id}.Test${id} GetConnectionString \
            $key $value $propertyName
      } result]

1042
1043
1044
1045
1046
1047
1048

1049
1050
1051



1052
1053
1054
1055
1056
1057
1058
1050
1051
1052
1053
1054
1055
1056
1057



1058
1059
1060
1061
1062
1063
1064
1065
1066
1067







+
-
-
-
+
+
+







UseUTF16Encoding=True\} 0 \{False, Pooling=False\} 0 \{True, BinaryGUID=True\}\
0 \{test\.db, Data Source=test\.db\} 0 \{test\.db, Uri=test\.db\} 0\
\{file:test.db, FullUri=file:test\.db\} 0 \{60, Default Timeout=60\} 0 \{False,\
Enlist=False\} 0 \{True, FailIfMissing=True\} 0 \{False, Legacy Format=False\}\
0 \{True, Read Only=True\} 0 \{secret, Password=secret\} 0 \{4096, Page\
Size=4096\} 0 \{1024, Max Page Count=1024\} 0 \{8192, Cache Size=8192\} 0\
\{UnixEpoch, DateTimeFormat=UnixEpoch\} 0 \{Utc, DateTimeKind=Utc\} 0\
\{yyyy-MM-dd, DateTimeFormatString=yyyy-MM-dd\} 0 \{sqlite_schema,\
\{sqlite_schema, BaseSchemaName=sqlite_schema\} 0 \{Memory, Journal\
Mode=Memory\} 0 \{Serializable, Default IsolationLevel=Serializable\} 0\
\{False, Foreign Keys=False\} 0 \{(?:Default|LogCallbackException),\
BaseSchemaName=sqlite_schema\} 0 \{Memory, Journal Mode=Memory\} 0\
\{Serializable, Default IsolationLevel=Serializable\} 0 \{False, Foreign\
Keys=False\} 0 \{(?:Default|LogCallbackException),\
Flags=(?:Default|LogCallbackException)\} 0 \{False, SetDefaults=False\} 0\
\{False, ToFullPath=False\} 0 {736563726574, HexPassword=736563726574}$}}

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

runTest {test data-1.17 {SQLiteConvert ToDateTime (Julian Day)} -body {
  set dateTime [object invoke -create System.Data.SQLite.SQLiteConvert \
1465
1466
1467
1468
1469
1470
1471
1472

1473
1474
1475
1476
1477
1478
1479
1474
1475
1476
1477
1478
1479
1480

1481
1482
1483
1484
1485
1486
1487
1488







-
+







  #
  shutdownSQLite $test_channel

  #
  # NOTE: Create an instance of the core SQLite library interop wrapper class.
  #
  set sqlite3 [object create -flags +NonPublic System.Data.SQLite.SQLite3 \
      Default Unspecified]
      Default Unspecified null]
} -body {
  set result(rc1) [object invoke -flags +NonPublic $sqlite3 SetMemoryStatus \
      false]

  set result(before) [object invoke -flags +NonPublic $sqlite3 MemoryUsed]

  set result(ptr1) [object invoke -create -flags +NonPublic \
Changes to readme.htm.
187
188
189
190
191
192
193


194
195
196
197
198
199
200
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202







+
+







<h2><b>Version History</b></h2>

<p>
    <b>1.0.87.0 - June XX, 2013 <font color="red">(release scheduled)</font></b>
</p>
<ul>
    <li>The DbType to type name translation needs to prioritize the Entity Framework type names. Fix for [47f4bac575].</li>
    <li>Add DateTimeFormatString connection string property to allow the DateTime format string used for all parsing and formatting to be overridden.</li>
    <li>Disable use of the new connection string parsing algorithm when the No_SQLiteConnectionNewParser environment variable is set. Pursuant to [bbdda6eae2].</li>
</ul>
<p>
    <b>1.0.86.0 - May 23, 2013</b>
</p>
<ul>
    <li>Updated to <a href="http://www.sqlite.org/releaselog/3_7_17.html">SQLite 3.7.17</a>.</li>
    <li>Disable use of the AllowPartiallyTrustedCallers attribute when compiled for the .NET Framework 4.0/4.5.&nbsp;<b>** Potentially Incompatible Change **</b></li>
Changes to www/news.wiki.
1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18









+
+







<title>News</title>

<b>Version History</b>

<p>
    <b>1.0.87.0 - June XX, 2013 <font color="red">(release scheduled)</font></b>
</p>
<ul>
    <li>The DbType to type name translation needs to prioritize the Entity Framework type names. Fix for [47f4bac575].</li>
    <li>Add DateTimeFormatString connection string property to allow the DateTime format string used for all parsing and formatting to be overridden.</li>
    <li>Disable use of the new connection string parsing algorithm when the No_SQLiteConnectionNewParser environment variable is set. Pursuant to [bbdda6eae2].</li>
</ul>
<p>
    <b>1.0.86.0 - May 23, 2013</b>
</p>
<ul>
    <li>Updated to [http://www.sqlite.org/releaselog/3_7_17.html|SQLite 3.7.17].</li>
    <li>Disable use of the AllowPartiallyTrustedCallers attribute when compiled for the .NET Framework 4.0/4.5.&nbsp;<b>** Potentially Incompatible Change **</b></li>