System.Data.SQLite

Check-in [320066944e]
Login

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

Overview
Comment:Add the 'PreLoadSQLite_BreakIntoDebugger' configuration setting to improve debugging support. Also, add some logging to the SQLiteProviderFactory class, pursuant to [d6e1fdba1e].
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 320066944e139af62e45d67e3c84608947652dbc
User & Date: mistachkin 2017-11-01 00:58:45.754
Context
2017-11-01
01:00
Adjust comment wording. check-in: b7307ff8d3 user: mistachkin tags: trunk
00:58
Add the 'PreLoadSQLite_BreakIntoDebugger' configuration setting to improve debugging support. Also, add some logging to the SQLiteProviderFactory class, pursuant to [d6e1fdba1e]. check-in: 320066944e user: mistachkin tags: trunk
2017-10-31
22:21
Improvements to the doc comments for the BackupDatabase method. check-in: e4df0a7df0 user: mistachkin tags: trunk
Changes
Side-by-Side Diff Ignore Whitespace Patch
Changes to Doc/Extra/Provider/environment.html.
192
193
194
195
196
197
198






199
200
201
202
203
204
205
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211







+
+
+
+
+
+







          <td>If this environment variable is set [to anything], it will be
          used instead of the application base directory by the native
          library pre-loader.  This environment variable can be especially
          useful in ASP.NET and other hosted environments where direct control
          of the location of the managed assemblies is not under the control
          of the application.</td>
        </tr>
        <tr valign="top">
          <td>PreLoadSQLite_BreakIntoDebugger</td>
          <td>If this configuration variable is set [to anything], the native
          library pre-loader subsystem will attempt to give the interactive
          user an opportunity to attach a debugger to the current process.</td>
        </tr>
        <tr valign="top">
          <td>PreLoadSQLite_LibraryFileNameOnly</td>
          <td>If this environment variable is set [to anything], it will be
          used as the base file name (without directory information) for the
          native SQLite library to be pre-loaded (e.g. "sqlite3.dll" or
          "libsqlite3.so.0").</td>
        </tr>
Changes to System.Data.SQLite.Linq/SQLiteProviderFactory.cs.
9
10
11
12
13
14
15

16
17
18
19
20
21
22
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23







+







namespace System.Data.SQLite.EF6
#else
namespace System.Data.SQLite.Linq
#endif
{
    using System;
    using System.Data.Common;
    using System.Globalization;

#if USE_ENTITY_FRAMEWORK_6
    using System.Data.Entity.Core.Common;
#endif

    /// <summary>
    /// SQLite implementation of <see cref="DbProviderFactory" />.
136
137
138
139
140
141
142





143
144





145
146
147
148
149
150
151
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







+
+
+
+
+


+
+
+
+
+







        public object GetService(
            Type serviceType
            )
        {
            if ((serviceType == typeof(ISQLiteSchemaExtensions)) ||
                (serviceType == typeof(DbProviderServices)))
            {
                SQLiteLog.LogMessage(HelperMethods.StringFormat(
                    CultureInfo.CurrentCulture,
                    "IServiceProvider.GetService for type \"{0}\" (success).",
                    serviceType));

                return SQLiteProviderServices.Instance;
            }

            SQLiteLog.LogMessage(HelperMethods.StringFormat(
                CultureInfo.CurrentCulture,
                "IServiceProvider.GetService for type \"{0}\" (failure).",
                serviceType));

            return null;
        }
        #endregion

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

Changes to System.Data.SQLite/Configurations/System.Data.SQLite.dll.config.
152
153
154
155
156
157
158









159
160
161
162
163
164
165
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174







+
+
+
+
+
+
+
+
+







              useful in ASP.NET and other hosted environments where direct
              control of the location of the managed assemblies is not under
              the control of the application.
    -->
    <!--
    <add key="PreLoadSQLite_BaseDirectory" value="" />
    -->

    <!--
        NOTE: If this configuration variable is set [to anything], the native
              library pre-loader subsystem will attempt to give the interactive
              user an opportunity to attach a debugger to the current process.
    -->
    <!--
    <add key="PreLoadSQLite_BreakIntoDebugger" value="1" />
    -->

    <!--
        NOTE: If this configuration variable is set [to anything], it will be
              used as the base file name (without directory information) for
              the native SQLite library to be pre-loaded (e.g. "sqlite3.dll"
              or "libsqlite3.so.0").
    -->
Changes to System.Data.SQLite/UnsafeNativeMethods.cs.
1
2
3
4
5
6
7
8
9
10
11
12
13

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

13
14
15
16
17
18
19
20












-
+







/********************************************************
 * ADO.NET 2.0 Data Provider for SQLite Version 3.X
 * Written by Robert Simpson (robert@blackcastlesoft.com)
 *
 * Released to the public domain, use at your own risk!
 ********************************************************/

namespace System.Data.SQLite
{
  using System;
  using System.Globalization;

#if !NET_COMPACT_20 && (TRACE_DETECTION || TRACE_SHARED || TRACE_PRELOAD || TRACE_HANDLE)
#if TRACE_DETECTION || TRACE_SHARED || TRACE_PRELOAD || TRACE_HANDLE
  using System.Diagnostics;
#endif

  using System.Collections.Generic;
  using System.IO;
  using System.Reflection;

268
269
270
271
272
273
274








275
276
277
278
279


















280
281
282
283
284
285
286
268
269
270
271
272
273
274
275
276
277
278
279
280
281
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







+
+
+
+
+
+
+
+





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







      /////////////////////////////////////////////////////////////////////////
      /// <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 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;
      #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.
      /// </returns>
      private static int GetProcessId()
      {
          Process process = Process.GetCurrentProcess();

          if (process == null)
              return 0;

          return process.Id;
      }

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

      /// <summary>
      /// Determines whether or not this assembly is running on Mono.
      /// </summary>
      /// <returns>
      /// Non-zero if this assembly is running on Mono.
      /// </returns>
      private static bool IsMono()
303
304
305
306
307
308
309



















































































310
311
312
313
314
315
316
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
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
424
425







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







          return false;
      }
      #endregion

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

      #region Internal Methods
      /// <summary>
      /// If the "PreLoadSQLite_BreakIntoDebugger" configuration setting is
      /// present (e.g. via the environment), give the interactive user the
      /// opportunity to attach a debugger to the current process; otherwise,
      /// do nothing.
      /// </summary>
      private static void MaybeBreakIntoDebugger()
      {
          lock (staticSyncRoot)
          {
              if (debuggerBreak != null)
                  return;
          }

          if (UnsafeNativeMethods.GetSettingValue(
                "PreLoadSQLite_BreakIntoDebugger", null) != null)
          {
              //
              // NOTE: Attempt to use the Console in order to prompt the
              //       interactive user (if any).  This may fail for any
              //       number of reasons.  Even in those cases, we still
              //       want to issue the actual request to break into the
              //       debugger.
              //
              try
              {
                  Console.WriteLine(StringFormat(
                      CultureInfo.CurrentCulture,
                      "Attach a debugger to process {0} " +
                      "and press any key to continue.",
                      GetProcessId()));

#if PLATFORM_COMPACTFRAMEWORK
                  Console.ReadLine();
#else
                  Console.ReadKey();
#endif
              }
#if !NET_COMPACT_20 && TRACE_SHARED
              catch (Exception e)
#else
              catch (Exception)
#endif
              {
#if !NET_COMPACT_20 && TRACE_SHARED
                  try
                  {
                      Trace.WriteLine(HelperMethods.StringFormat(
                          CultureInfo.CurrentCulture,
                          "Failed to issue debugger prompt, " +
                          "{0} may be unusable: {1}",
                          typeof(Console), e)); /* throw */
                  }
                  catch
                  {
                      // do nothing.
                  }
#endif
              }

              try
              {
                  Debugger.Break();

                  lock (staticSyncRoot)
                  {
                      debuggerBreak = true;
                  }
              }
              catch
              {
                  lock (staticSyncRoot)
                  {
                      debuggerBreak = false;
                  }

                  throw;
              }
          }
      }

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

      /// <summary>
      /// Determines if preparing a query should be logged.
      /// </summary>
      /// <param name="flags">
      /// The flags associated with the parent connection object.
      /// </param>
      /// <returns>
985
986
987
988
989
990
991






992
993
994
995
996
997
998
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113







+
+
+
+
+
+







          //       anything), skip all our special code and simply return.
          //
          if (GetSettingValue("No_PreLoadSQLite", null) != null)
              return;
#endif
#endif

          //
          // NOTE: Check if a debugger needs to be attached before
          //       doing any real work.
          //
          HelperMethods.MaybeBreakIntoDebugger();

          #region Debug Build Only
#if DEBUG
          //
          // NOTE: Create the lists of statistics that will contain
          //       various counts used in debugging, including the
          //       number of times each setting value has been read.
          //