System.Data.SQLite

Login
This project makes use of Eagle, provided by Mistachkin Systems.
Eagle: Secure Software Automation

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

Overview
Comment:Add the GetPasswordCallback property to the SQLiteConnection class.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 5351cdbe2c220cb3153bcbe425760688578e5cc1
User & Date: mistachkin 2024-06-28 01:59:18
Context
2024-06-28
13:20
Simplify changes in the previous check-in. check-in: 5034d6b8f2 user: mistachkin tags: trunk
01:59
Add the GetPasswordCallback property to the SQLiteConnection class. check-in: 5351cdbe2c user: mistachkin tags: trunk
2024-06-26
21:15
More minor refactoring. check-in: 2c9119f941 user: mistachkin tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to Doc/Extra/Provider/version.html.

48
49
50
51
52
53
54

55
56
57
58
59
60
61
      <li>Updated to <a href="https://www.sqlite.org/releaselog/3_46_0.html">SQLite 3.46.0</a>.</li>
      <li>Update internal resource list of reserved SQL words.</li>
      <li>Add experimental support for using NuGet runtime identifiers to help locate the interop assembly. Pursuant to forum post <a href="https://www.sqlite.org/forum/forumpost/3757f4365b">[3757f4365b]</a>.</li>
      <li>Avoid NullReferenceException from Path.Combine method when the PublishSingleFile property is enabled for a project. Pursuant to forum post <a href="https://www.sqlite.org/forum/forumpost/66a0d2716a">[66a0d2716a]</a>.</li>
      <li>Avoid setting up for the Changed event when it will not be fired. Pursuant to forum post <a href="https://www.sqlite.org/forum/forumpost/25cafb35e5">[25cafb35e5]</a>.</li>
      <li>Add the VfsName connection string property.</li>
      <li>Add the &quot;compress&quot; and &quot;zipfile&quot; extensions to the interop assembly.</li>

      <li>Add the NoCase property to the SQLiteParameterCollection class.</li>
      <li>Fix rarely seen NullReferenceException in the StaticWeakConnectionPool.Add method.</li>
      <li>Revise the calculation used to bind DateTime values. Fix for <a href="https://system.data.sqlite.org/index.html/info/bbddfeb773">[bbddfeb773]</a>.</li>
      <li>Fix support for unnamed parameters using the ?NNN syntax. Pursuant to forum post <a href="https://www.sqlite.org/forum/forumpost/76cb35b58d">[76cb35b58d]</a>.</li>
    </ul>
    <p><b>1.0.118.0 - June 10, 2023</b></p>
    <ul>







>







48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
      <li>Updated to <a href="https://www.sqlite.org/releaselog/3_46_0.html">SQLite 3.46.0</a>.</li>
      <li>Update internal resource list of reserved SQL words.</li>
      <li>Add experimental support for using NuGet runtime identifiers to help locate the interop assembly. Pursuant to forum post <a href="https://www.sqlite.org/forum/forumpost/3757f4365b">[3757f4365b]</a>.</li>
      <li>Avoid NullReferenceException from Path.Combine method when the PublishSingleFile property is enabled for a project. Pursuant to forum post <a href="https://www.sqlite.org/forum/forumpost/66a0d2716a">[66a0d2716a]</a>.</li>
      <li>Avoid setting up for the Changed event when it will not be fired. Pursuant to forum post <a href="https://www.sqlite.org/forum/forumpost/25cafb35e5">[25cafb35e5]</a>.</li>
      <li>Add the VfsName connection string property.</li>
      <li>Add the &quot;compress&quot; and &quot;zipfile&quot; extensions to the interop assembly.</li>
      <li>Add the GetPasswordCallback property to the SQLiteConnection class for use with <a href="https://www.sqlite.org/see">SEE</a>.</li>
      <li>Add the NoCase property to the SQLiteParameterCollection class.</li>
      <li>Fix rarely seen NullReferenceException in the StaticWeakConnectionPool.Add method.</li>
      <li>Revise the calculation used to bind DateTime values. Fix for <a href="https://system.data.sqlite.org/index.html/info/bbddfeb773">[bbddfeb773]</a>.</li>
      <li>Fix support for unnamed parameters using the ?NNN syntax. Pursuant to forum post <a href="https://www.sqlite.org/forum/forumpost/76cb35b58d">[76cb35b58d]</a>.</li>
    </ul>
    <p><b>1.0.118.0 - June 10, 2023</b></p>
    <ul>

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

73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
    internal static partial class HelperMethods
    {
        #region Private Constants
        private const string DisplayNullObject = "<nullObject>";
        private const string DisplayEmptyString = "<emptyString>";
        private const string DisplayStringFormat = "\"{0}\"";

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

        private const string DisplayNullArray = "<nullArray>";
        private const string DisplayEmptyArray = "<emptyArray>";

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

        private const string TraceDateTimeFormat = "yyyy-MM-dd HH:mm:ss.fffffff";

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

        private const char ArrayOpen = '[';
        private const string ElementSeparator = ", ";
        private const char ArrayClose = ']';

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

        private static readonly char[] SpaceChars = {
            '\t', '\n', '\r', '\v', '\f', ' '
        };

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

        private static readonly char[] SeparatorChars = {
            '\t', '\n', ' ', ','
        };
        #endregion

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

        #region Private Data
        /// <summary>
        /// This lock is used to protect the static <see cref="isMono" /> and
        /// <see cref="isDotNetCore" /> fields.
        /// </summary>
        private static readonly object staticSyncRoot = new object();

        /////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// This type is only present when running on Mono.
        /// </summary>
        private static readonly string MonoRuntimeType = "Mono.Runtime";

        /////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// This type is only present when running on .NET Core.
        /// </summary>
        private static readonly string DotNetCoreLibType = "System.CoreLib";

        /////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Keeps track of whether we are running on Mono.  Initially null, it is
        /// set by the <see cref="IsMono" /> method on its first call.  Later, it
        /// is returned verbatim by the <see cref="IsMono" /> method.
        /// </summary>
        private static bool? isMono = null;

        /////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Keeps track of whether we are running on .NET Core.  Initially null,
        /// it is set by the <see cref="IsDotNetCore" /> method on its first
        /// call.  Later, it is returned verbatim by the
        /// <see cref="IsDotNetCore" /> method.
        /// </summary>
        private static bool? isDotNetCore = null;

        /////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Keeps track of whether we successfully invoked the
        /// <see cref="Debugger.Break" /> method.  Initially null, it is set by
        /// the <see cref="MaybeBreakIntoDebugger" /> method on its first call.
        /// </summary>
        private static bool? debuggerBreak = null;

        /////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// These are the currently enabled categories of trace messages.  If a
        /// trace message belongs to one of these categories, it will be emitted;
        /// otherwise, it will be silently dropped.
        /// </summary>
        private static TraceCategory traceCategories = TraceCategory.Default;

        /////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// This boolean flag will be non-zero when the enabled trace categories
        /// have been setup.
        /// </summary>
        private static bool traceCategoriesSet = false;
        #endregion

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

        #region Private Methods
        /// <summary>
        /// Determines the ID of the current process.  Only used for debugging.
        /// </summary>
        /// <returns>
        /// The ID of the current process -OR- zero if it cannot be determined.







|




|



|





|





|






|








|





|





|

|
|
|



|








|







|







|







|







73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
    internal static partial class HelperMethods
    {
        #region Private Constants
        private const string DisplayNullObject = "<nullObject>";
        private const string DisplayEmptyString = "<emptyString>";
        private const string DisplayStringFormat = "\"{0}\"";

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

        private const string DisplayNullArray = "<nullArray>";
        private const string DisplayEmptyArray = "<emptyArray>";

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

        private const string TraceDateTimeFormat = "yyyy-MM-dd HH:mm:ss.fffffff";

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

        private const char ArrayOpen = '[';
        private const string ElementSeparator = ", ";
        private const char ArrayClose = ']';

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

        private static readonly char[] SpaceChars = {
            '\t', '\n', '\r', '\v', '\f', ' '
        };

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

        private static readonly char[] SeparatorChars = {
            '\t', '\n', ' ', ','
        };
        #endregion

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

        #region Private Data
        /// <summary>
        /// This lock is used to protect the static <see cref="isMono" /> and
        /// <see cref="isDotNetCore" /> fields.
        /// </summary>
        private static readonly object staticSyncRoot = new object();

        ///////////////////////////////////////////////////////////////////////
        /// <summary>
        /// This type is only present when running on Mono.
        /// </summary>
        private static readonly string MonoRuntimeType = "Mono.Runtime";

        ///////////////////////////////////////////////////////////////////////
        /// <summary>
        /// This type is only present when running on .NET Core.
        /// </summary>
        private static readonly string DotNetCoreLibType = "System.CoreLib";

        ///////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Keeps track of whether we are running on Mono.  Initially null, it
        /// is set by the <see cref="IsMono" /> method on its first call.
        /// Later, it is returned verbatim by the <see cref="IsMono" /> method.
        /// </summary>
        private static bool? isMono = null;

        ///////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Keeps track of whether we are running on .NET Core.  Initially null,
        /// it is set by the <see cref="IsDotNetCore" /> method on its first
        /// call.  Later, it is returned verbatim by the
        /// <see cref="IsDotNetCore" /> method.
        /// </summary>
        private static bool? isDotNetCore = null;

        ///////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Keeps track of whether we successfully invoked the
        /// <see cref="Debugger.Break" /> method.  Initially null, it is set by
        /// the <see cref="MaybeBreakIntoDebugger" /> method on its first call.
        /// </summary>
        private static bool? debuggerBreak = null;

        ///////////////////////////////////////////////////////////////////////
        /// <summary>
        /// These are the currently enabled categories of trace messages.  If a
        /// trace message belongs to one of these categories, it will be emitted;
        /// otherwise, it will be silently dropped.
        /// </summary>
        private static TraceCategory traceCategories = TraceCategory.Default;

        ///////////////////////////////////////////////////////////////////////
        /// <summary>
        /// This boolean flag will be non-zero when the enabled trace categories
        /// have been setup.
        /// </summary>
        private static bool traceCategoriesSet = false;
        #endregion

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

        #region Private Methods
        /// <summary>
        /// Determines the ID of the current process.  Only used for debugging.
        /// </summary>
        /// <returns>
        /// The ID of the current process -OR- zero if it cannot be determined.
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
            {
                // do nothing.
            }

            return false;
        }

        /////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Determines if the specified trace category is enabled.  Disabled
        /// trace categories will not have any associated messages emitted.
        /// </summary>
        /// <param name="category">
        /// The trace category to check.
        /// </param>







|







210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
            {
                // do nothing.
            }

            return false;
        }

        ///////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Determines if the specified trace category is enabled.  Disabled
        /// trace categories will not have any associated messages emitted.
        /// </summary>
        /// <param name="category">
        /// The trace category to check.
        /// </param>
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
260
261
            TraceCategory category
            )
        {
            return (traceCategories & category) == category; /* NO-LOCK */
        }
        #endregion

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

        #region Internal Methods
        /// <summary>
        /// Resets the cached value for the "PreLoadSQLite_BreakIntoDebugger"
        /// configuration setting.
        /// </summary>
        internal static void ResetBreakIntoDebugger()
        {
            lock (staticSyncRoot)
            {
                debuggerBreak = null;
            }
        }

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

        /// <summary>
        /// If the "PreLoadSQLite_BreakIntoDebugger" configuration setting is
        /// present (e.g. via the environment), give the interactive user an
        /// opportunity to attach a debugger to the current process; otherwise,
        /// do nothing.
        /// </summary>







|














|







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
260
261
            TraceCategory category
            )
        {
            return (traceCategories & category) == category; /* NO-LOCK */
        }
        #endregion

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

        #region Internal Methods
        /// <summary>
        /// Resets the cached value for the "PreLoadSQLite_BreakIntoDebugger"
        /// configuration setting.
        /// </summary>
        internal static void ResetBreakIntoDebugger()
        {
            lock (staticSyncRoot)
            {
                debuggerBreak = null;
            }
        }

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

        /// <summary>
        /// If the "PreLoadSQLite_BreakIntoDebugger" configuration setting is
        /// present (e.g. via the environment), give the interactive user an
        /// opportunity to attach a debugger to the current process; otherwise,
        /// do nothing.
        /// </summary>
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
                lock (staticSyncRoot)
                {
                    debuggerBreak = false;
                }
            }
        }

        /////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Determines the ID of the current thread.  Only used for debugging.
        /// </summary>
        /// <returns>
        /// The ID of the current thread -OR- zero if it cannot be determined.
        /// </returns>
        internal static int GetThreadId()
        {
#if !PLATFORM_COMPACTFRAMEWORK
            return AppDomain.GetCurrentThreadId();
#else
            return 0;
#endif
        }

        /////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Determines if the current process is running on one of the Windows
        /// [sub-]platforms.
        /// </summary>
        /// <returns>
        /// Non-zero when running on Windows; otherwise, zero.
        /// </returns>







|















|







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
                lock (staticSyncRoot)
                {
                    debuggerBreak = false;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Determines the ID of the current thread.  Only used for debugging.
        /// </summary>
        /// <returns>
        /// The ID of the current thread -OR- zero if it cannot be determined.
        /// </returns>
        internal static int GetThreadId()
        {
#if !PLATFORM_COMPACTFRAMEWORK
            return AppDomain.GetCurrentThreadId();
#else
            return 0;
#endif
        }

        ///////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Determines if the current process is running on one of the Windows
        /// [sub-]platforms.
        /// </summary>
        /// <returns>
        /// Non-zero when running on Windows; otherwise, zero.
        /// </returns>
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
            {
                return true;
            }

            return false;
        }

        /////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// This is a wrapper around the
        /// <see cref="String.Format(IFormatProvider,String,Object[])" /> method.
        /// On Mono, it has to call the method overload without the
        /// <see cref="IFormatProvider" /> parameter, due to a bug in Mono.
        /// </summary>
        /// <param name="provider">
        /// This is used for culture-specific formatting.
        /// </param>
        /// <param name="format">
        /// The format string.







|


|
|







390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
            {
                return true;
            }

            return false;
        }

        ///////////////////////////////////////////////////////////////////////
        /// <summary>
        /// This is a wrapper around the
        /// <see cref="String.Format(IFormatProvider,String,Object[])" />
        /// method.  On Mono, it has to call the method overload without the
        /// <see cref="IFormatProvider" /> parameter, due to a bug in Mono.
        /// </summary>
        /// <param name="provider">
        /// This is used for culture-specific formatting.
        /// </param>
        /// <param name="format">
        /// The format string.
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
            {
                // do nothing.
            }

            return false;
        }

        /////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Attempts to determine which trace categories should be enabled based
        /// on the specified string value, which must be in the following general
        /// format:
        ///
        ///     [prefix1][name1][separator1] ... [prefixN][nameN][separatorN]
        ///







|







451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
            {
                // do nothing.
            }

            return false;
        }

        ///////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Attempts to determine which trace categories should be enabled based
        /// on the specified string value, which must be in the following general
        /// format:
        ///
        ///     [prefix1][name1][separator1] ... [prefixN][nameN][separatorN]
        ///
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
                    }
                }
            }

            return categories;
        }

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

        /// <summary>
        /// Determines if the enabled trace categories have already been set.
        /// </summary>
        /// <returns>
        /// Non-zero if the enabled trace categories have already been set;
        /// otherwise, zero.
        /// </returns>
        internal static bool AreTraceCategoriesSet()
        {
            return traceCategoriesSet;
        }

        /////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Changes the set of trace categories that are enabled.  Disabled
        /// trace categories will not have any associated messages emitted.
        /// </summary>
        /// <param name="categories">
        /// The trace categories to enable.  Any trace categories not present
        /// in this mask will be disabled.
        /// </param>
        internal static void SetTraceCategories(
            TraceCategory categories
            )
        {
            traceCategories = categories; /* NO-LOCK */
            traceCategoriesSet = true; /* NO-LOCK */

            Trace(String.Format(
                "Trace categories overridden to: {0}", categories),
                TraceCategory.Self);
        }

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

        /// <summary>
        /// Attempts to emit a message to the tracing subsystem via the
        /// <see cref="System.Diagnostics.Trace.WriteLine(String)" /> method.
        /// </summary>
        /// <param name="message">
        /// The message to emit.







|













|




















|







581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
                    }
                }
            }

            return categories;
        }

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

        /// <summary>
        /// Determines if the enabled trace categories have already been set.
        /// </summary>
        /// <returns>
        /// Non-zero if the enabled trace categories have already been set;
        /// otherwise, zero.
        /// </returns>
        internal static bool AreTraceCategoriesSet()
        {
            return traceCategoriesSet;
        }

        ///////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Changes the set of trace categories that are enabled.  Disabled
        /// trace categories will not have any associated messages emitted.
        /// </summary>
        /// <param name="categories">
        /// The trace categories to enable.  Any trace categories not present
        /// in this mask will be disabled.
        /// </param>
        internal static void SetTraceCategories(
            TraceCategory categories
            )
        {
            traceCategories = categories; /* NO-LOCK */
            traceCategoriesSet = true; /* NO-LOCK */

            Trace(String.Format(
                "Trace categories overridden to: {0}", categories),
                TraceCategory.Self);
        }

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

        /// <summary>
        /// Attempts to emit a message to the tracing subsystem via the
        /// <see cref="System.Diagnostics.Trace.WriteLine(String)" /> method.
        /// </summary>
        /// <param name="message">
        /// The message to emit.
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
                System.Diagnostics.Trace.WriteLine(
                    String.Format("[{0}] System.Data.SQLite ({1}): {2}",
                    DateTime.Now.ToString(TraceDateTimeFormat), category,
                    message));
            }
        }

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

        /// <summary>
        /// Attempts to convert an object value to a string suitable for display
        /// to humans.
        /// </summary>
        /// <param name="value">
        /// The object value to create a string representation of.







|







643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
                System.Diagnostics.Trace.WriteLine(
                    String.Format("[{0}] System.Data.SQLite ({1}): {2}",
                    DateTime.Now.ToString(TraceDateTimeFormat), category,
                    message));
            }
        }

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

        /// <summary>
        /// Attempts to convert an object value to a string suitable for display
        /// to humans.
        /// </summary>
        /// <param name="value">
        /// The object value to create a string representation of.
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
                return stringValue;

            return StringFormat(
                CultureInfo.InvariantCulture, DisplayStringFormat,
                stringValue);
        }

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

        /// <summary>
        /// Attempts to convert an array value to a string suitable for display
        /// to humans.
        /// </summary>
        /// <param name="array">
        /// The array value to create a string representation of.







|







676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
                return stringValue;

            return StringFormat(
                CultureInfo.InvariantCulture, DisplayStringFormat,
                stringValue);
        }

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

        /// <summary>
        /// Attempts to convert an array value to a string suitable for display
        /// to humans.
        /// </summary>
        /// <param name="array">
        /// The array value to create a string representation of.

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

18
19
20
21
22
23
24






































25
26
27
28
29
30
31
  using System.Runtime.InteropServices;
  using System.IO;
  using System.Text;
  using System.Threading;

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







































  /// <summary>
  /// This class represents a single value to be returned
  /// from the <see cref="SQLiteDataReader" /> class via
  /// its <see cref="SQLiteDataReader.GetBlob" />,
  /// <see cref="SQLiteDataReader.GetBoolean" />,
  /// <see cref="SQLiteDataReader.GetByte" />,
  /// <see cref="SQLiteDataReader.GetBytes" />,







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







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
  using System.Runtime.InteropServices;
  using System.IO;
  using System.Text;
  using System.Threading;

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

#if INTEROP_CODEC || INTEROP_INCLUDE_SEE
  /// <summary>
  /// This enumeration is used with the
  /// <see cref="SQLiteGetPasswordCallback" /> callback in order
  /// to determine which of the connection string properties is
  /// to be set with its returned string value.
  /// </summary>
  public enum PasswordMode
  {
    /// <summary>
    /// No password mode, skip setting the password.
    /// </summary>
    None = 0x0,

    /// <summary>
    /// Use the "Password" connection string property.
    /// </summary>
    Password = 0x1000,

    /// <summary>
    /// Use the "HexPassword" connection string property.
    /// </summary>
    HexPassword = 0x2000,

    /// <summary>
    /// Use the "TextPassword" connection string property.
    /// </summary>
    TextPassword = 0x4000,

    /// <summary>
    /// Use the "TextHexPassword" connection string property.
    /// </summary>
    TextHexPassword = 0x8000
  }
#endif

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

  /// <summary>
  /// This class represents a single value to be returned
  /// from the <see cref="SQLiteDataReader" /> class via
  /// its <see cref="SQLiteDataReader.GetBlob" />,
  /// <see cref="SQLiteDataReader.GetBoolean" />,
  /// <see cref="SQLiteDataReader.GetByte" />,
  /// <see cref="SQLiteDataReader.GetBytes" />,
620
621
622
623
624
625
626
























627
628
629
630
631
632
633
      SQLiteConnectionFlags flags,
      SQLiteReadEventArgs eventArgs,
      string typeName,
      int index,
      object userData,
      out bool complete
  );

























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

  /// <summary>
  /// This class represents the custom data type handling callbacks
  /// for a single type name.
  /// </summary>







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







658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
      SQLiteConnectionFlags flags,
      SQLiteReadEventArgs eventArgs,
      string typeName,
      int index,
      object userData,
      out bool complete
  );

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

#if INTEROP_CODEC || INTEROP_INCLUDE_SEE
  /// <summary>
  /// This represents a method to be called to obtain the encryption
  /// password for the associated connection, which is passed in the
  /// <paramref name="connection" /> parameter.
  /// </summary>
  /// <param name="connection">
  /// The connection being opened.
  /// </param>
  /// <param name="passwordMode">
  /// The called method may modify this parameter in order to change
  /// which connection string property is used to setup the password.
  /// </param>
  /// <returns>
  /// The password string to use when opening the connection.
  /// </returns>
  public delegate string SQLiteGetPasswordCallback(
      SQLiteConnection connection,  /* in */
      ref PasswordMode passwordMode /* in, out */
  );
#endif

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

  /// <summary>
  /// This class represents the custom data type handling callbacks
  /// for a single type name.
  /// </summary>
4748
4749
4750
4751
4752
4753
4754














4755
4756
4757
4758
4759
4760
4761
            case IsolationLevel.Serializable:
            case IsolationLevel.Snapshot:
                return ImmediateIsolationLevel;
            default:
                return GetFallbackDefaultIsolationLevel();
        }
    }















    /// <summary>
    /// Opens the connection using the parameters found in the <see cref="ConnectionString" />.
    /// </summary>
    public override void Open()
    {
      CheckDisposed();







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







4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
            case IsolationLevel.Serializable:
            case IsolationLevel.Snapshot:
                return ImmediateIsolationLevel;
            default:
                return GetFallbackDefaultIsolationLevel();
        }
    }

#if INTEROP_CODEC || INTEROP_INCLUDE_SEE
    /// <summary>
    /// Gets or sets the callback method that can be used to provide a
    /// connection string password when one is NOT already specified in
    /// the connection string itself.
    /// </summary>
    private SQLiteGetPasswordCallback _getPasswordCallback;
    public SQLiteGetPasswordCallback GetPasswordCallback
    {
        get { CheckDisposed(); return _getPasswordCallback; }
        set { CheckDisposed(); _getPasswordCallback = value; }
    }
#endif

    /// <summary>
    /// Opens the connection using the parameters found in the <see cref="ConnectionString" />.
    /// </summary>
    public override void Open()
    {
      CheckDisposed();
5094
5095
5096
5097
5098
5099
5100

5101
5102
5103
5104
5105
5106
5107
        string textHexPassword = FindKey(opts, "TextHexPassword", DefaultTextHexPassword);

        if (textHexPassword != null)
        {
            byte[] textHexPasswordBytes;

            error = null;

            textHexPasswordBytes = FromHexString(textHexPassword, false, ref error);

            if (textHexPasswordBytes == null)
            {
                throw new FormatException(HelperMethods.StringFormat(
                    CultureInfo.CurrentCulture,
                    "Cannot parse 'TextHexPassword' property value into byte values: {0}",







>







5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
        string textHexPassword = FindKey(opts, "TextHexPassword", DefaultTextHexPassword);

        if (textHexPassword != null)
        {
            byte[] textHexPasswordBytes;

            error = null;

            textHexPasswordBytes = FromHexString(textHexPassword, false, ref error);

            if (textHexPasswordBytes == null)
            {
                throw new FormatException(HelperMethods.StringFormat(
                    CultureInfo.CurrentCulture,
                    "Cannot parse 'TextHexPassword' property value into byte values: {0}",
5134
5135
5136
5137
5138
5139
5140

5141
5142
5143
5144
5145
5146
5147
                string hexPassword = FindKey(opts, "HexPassword", DefaultHexPassword);

                if (hexPassword != null)
                {
                    byte[] hexPasswordBytes;

                    error = null;

                    hexPasswordBytes = FromHexString(hexPassword, true, ref error);

                    if (hexPasswordBytes == null)
                    {
                        throw new FormatException(HelperMethods.StringFormat(
                            CultureInfo.CurrentCulture,
                            "Cannot parse 'HexPassword' property value into byte values: {0}",







>







5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
                string hexPassword = FindKey(opts, "HexPassword", DefaultHexPassword);

                if (hexPassword != null)
                {
                    byte[] hexPasswordBytes;

                    error = null;

                    hexPasswordBytes = FromHexString(hexPassword, true, ref error);

                    if (hexPasswordBytes == null)
                    {
                        throw new FormatException(HelperMethods.StringFormat(
                            CultureInfo.CurrentCulture,
                            "Cannot parse 'HexPassword' property value into byte values: {0}",
5164
5165
5166
5167
5168
5169
5170
















































































5171
5172
5173
5174
5175
5176
5177
                        _sql.SetPassword(passwordBytes, false);
                        _passwordWasText = false;
                        _passwordWasHex = false;
                    }
                    else if (_password != null)
                    {
                        _sql.SetPassword(_password, _passwordWasText);
















































































                    }

                    password = null; /* IMMUTABLE */
                }

                hexPassword = null; /* IMMUTABLE */
            }







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







5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
                        _sql.SetPassword(passwordBytes, false);
                        _passwordWasText = false;
                        _passwordWasHex = false;
                    }
                    else if (_password != null)
                    {
                        _sql.SetPassword(_password, _passwordWasText);
                    }
                    else if (_getPasswordCallback != null)
                    {
                        byte[] passwordBytes;
                        PasswordMode passwordMode = PasswordMode.Password;

                        password = _getPasswordCallback(this, ref passwordMode);

                        switch (passwordMode)
                        {
                            case PasswordMode.None:
                                {
                                    //
                                    // NOTE: Do nothing, ignore password.
                                    //
                                    break;
                                }
                            case PasswordMode.Password:
                                {
                                    passwordBytes = UTF8Encoding.UTF8.GetBytes(password);

                                    _sql.SetPassword(passwordBytes, false);
                                    _passwordWasText = false;
                                    _passwordWasHex = false;
                                    break;
                                }
                            case PasswordMode.HexPassword:
                                {
                                    error = null;

                                    passwordBytes = FromHexString(password, true, ref error);

                                    if (passwordBytes == null)
                                    {
                                        throw new FormatException(
                                            HelperMethods.StringFormat(CultureInfo.CurrentCulture,
                                            "Cannot parse 'HexPassword' property value into byte values: {0}",
                                            error));
                                    }

                                    _sql.SetPassword(passwordBytes, false);
                                    _passwordWasText = false;
                                    _passwordWasHex = true;
                                    break;
                                }
                            case PasswordMode.TextPassword:
                                {
                                    passwordBytes = UTF8Encoding.UTF8.GetBytes(password);

                                    Array.Resize(
                                        ref passwordBytes, passwordBytes.Length + 1);

                                    _sql.SetPassword(passwordBytes, true);
                                    _passwordWasText = true;
                                    _passwordWasHex = false;
                                    break;
                                }
                            case PasswordMode.TextHexPassword:
                                {
                                    error = null;

                                    passwordBytes = FromHexString(password, false, ref error);

                                    if (passwordBytes == null)
                                    {
                                        throw new FormatException(
                                            HelperMethods.StringFormat(CultureInfo.CurrentCulture,
                                            "Cannot parse 'TextHexPassword' property value into byte values: {0}",
                                            error));
                                    }

                                    Array.Resize(
                                        ref passwordBytes, passwordBytes.Length + 1);

                                    _sql.SetPassword(passwordBytes, true);
                                    _passwordWasText = true;
                                    _passwordWasHex = true;
                                    break;
                                }
                        }
                    }

                    password = null; /* IMMUTABLE */
                }

                hexPassword = null; /* IMMUTABLE */
            }

Changes to readme.htm.

214
215
216
217
218
219
220

221
222
223
224
225
226
227
    <li>Updated to <a href="https://www.sqlite.org/releaselog/3_46_0.html">SQLite 3.46.0</a>.</li>
    <li>Update internal resource list of reserved SQL words.</li>
    <li>Add experimental support for using NuGet runtime identifiers to help locate the interop assembly. Pursuant to forum post [3757f4365b].</li>
    <li>Avoid NullReferenceException from Path.Combine method when the PublishSingleFile property is enabled for a project. Pursuant to forum post [66a0d2716a].</li>
    <li>Avoid setting up for the Changed event when it will not be fired. Pursuant to forum post [25cafb35e5].</li>
    <li>Add the VfsName connection string property.</li>
    <li>Add the &quot;compress&quot; and &quot;zipfile&quot; extensions to the interop assembly.</li>

    <li>Add the NoCase property to the SQLiteParameterCollection class.</li>
    <li>Fix rarely seen NullReferenceException in the StaticWeakConnectionPool.Add method.</li>
    <li>Revise the calculation used to bind DateTime values. Fix for [bbddfeb773].</li>
    <li>Fix support for unnamed parameters using the ?NNN syntax. Pursuant to forum post [76cb35b58d].</li>
</ul>
<p>
    <b>1.0.118.0 - June 10, 2023</b>







>







214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
    <li>Updated to <a href="https://www.sqlite.org/releaselog/3_46_0.html">SQLite 3.46.0</a>.</li>
    <li>Update internal resource list of reserved SQL words.</li>
    <li>Add experimental support for using NuGet runtime identifiers to help locate the interop assembly. Pursuant to forum post [3757f4365b].</li>
    <li>Avoid NullReferenceException from Path.Combine method when the PublishSingleFile property is enabled for a project. Pursuant to forum post [66a0d2716a].</li>
    <li>Avoid setting up for the Changed event when it will not be fired. Pursuant to forum post [25cafb35e5].</li>
    <li>Add the VfsName connection string property.</li>
    <li>Add the &quot;compress&quot; and &quot;zipfile&quot; extensions to the interop assembly.</li>
    <li>Add the GetPasswordCallback property to the SQLiteConnection class for use with <a href="https://www.sqlite.org/see">SEE</a>.</li>
    <li>Add the NoCase property to the SQLiteParameterCollection class.</li>
    <li>Fix rarely seen NullReferenceException in the StaticWeakConnectionPool.Add method.</li>
    <li>Revise the calculation used to bind DateTime values. Fix for [bbddfeb773].</li>
    <li>Fix support for unnamed parameters using the ?NNN syntax. Pursuant to forum post [76cb35b58d].</li>
</ul>
<p>
    <b>1.0.118.0 - June 10, 2023</b>

Changes to www/news.wiki.

61
62
63
64
65
66
67

68
69
70
71
72
73
74
    <li>Updated to [https://www.sqlite.org/releaselog/3_46_0.html|SQLite 3.46.0].</li>
    <li>Update internal resource list of reserved SQL words.</li>
    <li>Add experimental support for using NuGet runtime identifiers to help locate the interop assembly. Pursuant to forum post [https://www.sqlite.org/forum/forumpost/3757f4365b|3757f4365b].</li>
    <li>Avoid NullReferenceException from Path.Combine method when the PublishSingleFile property is enabled for a project. Pursuant to forum post [https://www.sqlite.org/forum/forumpost/66a0d2716a|66a0d2716a].</li>
    <li>Avoid setting up for the Changed event when it will not be fired. Pursuant to forum post [https://www.sqlite.org/forum/forumpost/25cafb35e5|25cafb35e5]</a>.</li>
    <li>Add the VfsName connection string property.</li>
    <li>Add the &quot;compress&quot; and &quot;zipfile&quot; extensions to the interop assembly.</li>

    <li>Add the NoCase property to the SQLiteParameterCollection class.</li>
    <li>Fix rarely seen NullReferenceException in the StaticWeakConnectionPool.Add method.</li>
    <li>Revise the calculation used to bind DateTime values. Fix for [bbddfeb773].</li>
    <li>Fix support for unnamed parameters using the ?NNN syntax. Pursuant to forum post [https://www.sqlite.org/forum/forumpost/76cb35b58d|76cb35b58d].</li>
</ul>
<p>
    <b>1.0.118.0 - June 10, 2023</b>







>







61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
    <li>Updated to [https://www.sqlite.org/releaselog/3_46_0.html|SQLite 3.46.0].</li>
    <li>Update internal resource list of reserved SQL words.</li>
    <li>Add experimental support for using NuGet runtime identifiers to help locate the interop assembly. Pursuant to forum post [https://www.sqlite.org/forum/forumpost/3757f4365b|3757f4365b].</li>
    <li>Avoid NullReferenceException from Path.Combine method when the PublishSingleFile property is enabled for a project. Pursuant to forum post [https://www.sqlite.org/forum/forumpost/66a0d2716a|66a0d2716a].</li>
    <li>Avoid setting up for the Changed event when it will not be fired. Pursuant to forum post [https://www.sqlite.org/forum/forumpost/25cafb35e5|25cafb35e5]</a>.</li>
    <li>Add the VfsName connection string property.</li>
    <li>Add the &quot;compress&quot; and &quot;zipfile&quot; extensions to the interop assembly.</li>
    <li>Add the GetPasswordCallback property to the SQLiteConnection class for use with [https://www.sqlite.org/see|SEE].</li>
    <li>Add the NoCase property to the SQLiteParameterCollection class.</li>
    <li>Fix rarely seen NullReferenceException in the StaticWeakConnectionPool.Add method.</li>
    <li>Revise the calculation used to bind DateTime values. Fix for [bbddfeb773].</li>
    <li>Fix support for unnamed parameters using the ?NNN syntax. Pursuant to forum post [https://www.sqlite.org/forum/forumpost/76cb35b58d|76cb35b58d].</li>
</ul>
<p>
    <b>1.0.118.0 - June 10, 2023</b>