System.Data.SQLite

Check-in [60011bd9e5]
Login

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

Overview
Comment:More work-in-progress on refactoring the native library pre-loader.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | refactorNativeLibraryPreLoader
Files: files | file ages | folders
SHA1: 60011bd9e570ec686395539388bf158850720e4a
User & Date: mistachkin 2013-12-26 23:48:18.169
Context
2013-12-27
04:03
Merge testing changes. Rename the XML configuration file to 'System.Data.SQLite.dll.config'. Break out shared native library pre-loading code to fix compilation issues. check-in: c43afb58ea user: mistachkin tags: refactorNativeLibraryPreLoader
2013-12-26
23:48
More work-in-progress on refactoring the native library pre-loader. check-in: 60011bd9e5 user: mistachkin tags: refactorNativeLibraryPreLoader
04:01
Refactor native library pre-loading code to be more flexible. check-in: 77a0e66f10 user: mistachkin tags: refactorNativeLibraryPreLoader
Changes
Unified Diff Ignore Whitespace Patch
Changes to System.Data.SQLite/SQLiteConnection.cs.
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
      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 (UnsafeNativeMethods.GetVariableValue("No_SQLiteConnectionNewParser") != null)
          arParts = SQLiteConvert.Split(s, ';');
      else
          arParts = SQLiteConvert.NewSplit(s, ';', true, ref error);

      if (arParts == null)
      {
          throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,







|







1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
      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 (UnsafeNativeMethods.GetSettingValue("No_SQLiteConnectionNewParser") != null)
          arParts = SQLiteConvert.Split(s, ';');
      else
          arParts = SQLiteConvert.NewSplit(s, ';', true, ref error);

      if (arParts == null)
      {
          throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
Changes to System.Data.SQLite/SQLiteFunction.cs.
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
      try
      {
#if !PLATFORM_COMPACTFRAMEWORK
        //
        // NOTE: If the "No_SQLiteFunctions" environment variable is set,
        //       skip all our special code and simply return.
        //
        if (UnsafeNativeMethods.GetVariableValue("No_SQLiteFunctions") != null)
          return;

        SQLiteFunctionAttribute at;
        System.Reflection.Assembly[] arAssemblies = System.AppDomain.CurrentDomain.GetAssemblies();
        int w = arAssemblies.Length;
        System.Reflection.AssemblyName sqlite = System.Reflection.Assembly.GetExecutingAssembly().GetName();








|







653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
      try
      {
#if !PLATFORM_COMPACTFRAMEWORK
        //
        // NOTE: If the "No_SQLiteFunctions" environment variable is set,
        //       skip all our special code and simply return.
        //
        if (UnsafeNativeMethods.GetSettingValue("No_SQLiteFunctions") != null)
          return;

        SQLiteFunctionAttribute at;
        System.Reflection.Assembly[] arAssemblies = System.AppDomain.CurrentDomain.GetAssemblies();
        int w = arAssemblies.Length;
        System.Reflection.AssemblyName sqlite = System.Reflection.Assembly.GetExecutingAssembly().GetName();

Changes to System.Data.SQLite/SQLiteLog.cs.
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
            //         is loaded per-process and has only one logging callback,
            //         not one per-AppDomain, which it knows nothing about),
            //         prevent all non-default AppDomains from registering a
            //         log handler unless the "Force_SQLiteLog" environment
            //         variable is used to manually override this safety check.
            //
            if (!AppDomain.CurrentDomain.IsDefaultAppDomain() &&
                UnsafeNativeMethods.GetVariableValue("Force_SQLiteLog") == null)
            {
                return;
            }
#endif

            lock (syncRoot)
            {







|







148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
            //         is loaded per-process and has only one logging callback,
            //         not one per-AppDomain, which it knows nothing about),
            //         prevent all non-default AppDomains from registering a
            //         log handler unless the "Force_SQLiteLog" environment
            //         variable is used to manually override this safety check.
            //
            if (!AppDomain.CurrentDomain.IsDefaultAppDomain() &&
                UnsafeNativeMethods.GetSettingValue("Force_SQLiteLog") == null)
            {
                return;
            }
#endif

            lock (syncRoot)
            {
Changes to System.Data.SQLite/System.Data.SQLite.Files.targets.
10
11
12
13
14
15
16



17
18
19
20
21
22
23
  <!--
  ******************************************************************************
  **                            Core Files (Common)                           **
  ******************************************************************************
  -->

  <ItemGroup>



    <Compile Include="AssemblyInfo.cs" />
    <Compile Include="AssemblySourceIdAttribute.cs" />
    <Compile Include="AssemblySourceTimeStampAttribute.cs" />
    <Compile Include="SQLite3.cs" />
    <Compile Include="SQLite3_UTF16.cs" />
    <Compile Include="SQLiteBackup.cs" />
    <Compile Include="SQLiteBase.cs" />







>
>
>







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  <!--
  ******************************************************************************
  **                            Core Files (Common)                           **
  ******************************************************************************
  -->

  <ItemGroup>
    <None Include="System.Data.SQLite.config">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>
    <Compile Include="AssemblyInfo.cs" />
    <Compile Include="AssemblySourceIdAttribute.cs" />
    <Compile Include="AssemblySourceTimeStampAttribute.cs" />
    <Compile Include="SQLite3.cs" />
    <Compile Include="SQLite3_UTF16.cs" />
    <Compile Include="SQLiteBackup.cs" />
    <Compile Include="SQLiteBase.cs" />
Added System.Data.SQLite/System.Data.SQLite.config.






































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
70
71
72
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
<?xml version="1.0"?>
<!--
 *
 * System.Data.SQLite.config -
 *
 * Written by Joe Mistachkin.
 * Released to the public domain, use at your own risk!
 *
-->
<configuration>
  <appSettings>
    <!--
        NOTE: If this configuration variable is set [to anything], the SQLite
              logging subsystem may be initialized in a non-default application
              domain.  By default, this is not allowed due to the potential
              for application domain unloading issues.
    -->
    <!--
    <add key="Force_SQLiteLog" value="1" />
    -->

    <!--
        NOTE: If this configuration 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.
    -->
    <!--
    <add key="No_PreLoadSQLite" value="1" />
    -->

    <!--
        NOTE: If this configuration 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.
    -->
    <!--
    <add key="No_SQLiteConnectionNewParser" value="1" />
    -->

    <!--
        NOTE: If this configuration 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 are subject to change.
    -->
    <!--
    <add key="No_SQLiteFunctions" value="1" />
    -->

    <!--
        NOTE: If this configuration 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.
    -->
    <!--
    <add key="PreLoadSQLite_BaseDirectory" value="" />
    -->

    <!--
        NOTE: If this configuration variable is set [to anything], it will be
              used instead of the processor architecture value contained in the
              PROCESSOR_ARCHITECTURE environment variable to help build the
              path of the native library to pre-load.
    -->
    <!--
    <add key="PreLoadSQLite_ProcessorArchitecture" value="x86" />
    -->

    <!--
        NOTE: If this configuration variable is set [to anything], the location
              of the currently executing assembly (i.e. the one containing all
              the managed components for System.Data.SQLite) will be used as
              the basis for locating the the native library to pre-load (i.e.
              instead of using the application domain base directory).
    -->
    <!--
    <add key="PreLoadSQLite_UseAssemblyDirectory" value="1" />
    -->

    <!--
        NOTE: This configuration variable is normally set by the operating
              system itself and should reflect the native processor
              architecture of the current process (e.g. a 32-bit x86
              application running on a 64-bit x64 operating system should have
              the value "x86").
    -->
    <!--
    <add key="PROCESSOR_ARCHITECTURE" value="%PROCESSOR_ARCHITECTURE%" />
    -->
  </appSettings>
</configuration>
Changes to System.Data.SQLite/UnsafeNativeMethods.cs.
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95

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

      private static readonly string DllFileExtension = ".dll";

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

      private static readonly string XmlConfigurationFileName =
          typeof(UnsafeNativeMethods).Namespace + ".config";

      /////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// This is the P/Invoke method that wraps the native Win32 LoadLibrary
      /// function.  See the MSDN documentation for full details on what it
      /// does.







|







81
82
83
84
85
86
87
88
89
90
91
92
93
94
95

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

      private static readonly string DllFileExtension = ".dll";

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

      private static readonly string XmlConfigFileName =
          typeof(UnsafeNativeMethods).Namespace + ".config";

      /////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// This is the P/Invoke method that wraps the native Win32 LoadLibrary
      /// function.  See the MSDN documentation for full details on what it
      /// does.
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
      /// </summary>
      internal static void Initialize()
      {
          //
          // NOTE: If the "No_PreLoadSQLite" environment variable is set (to
          //       anything), skip all our special code and simply return.
          //
          if (GetVariableValue("No_PreLoadSQLite") != null)
              return;

          lock (staticSyncRoot)
          {
              //
              // TODO: Make sure this list is updated if the supported
              //       processor architecture names and/or platform names







|







206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
      /// </summary>
      internal static void Initialize()
      {
          //
          // NOTE: If the "No_PreLoadSQLite" environment variable is set (to
          //       anything), skip all our special code and simply return.
          //
          if (GetSettingValue("No_PreLoadSQLite") != null)
              return;

          lock (staticSyncRoot)
          {
              //
              // TODO: Make sure this list is updated if the supported
              //       processor architecture names and/or platform names
247
248
249
250
251
252
253

254
255
256

257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
              if (_SQLiteModule == IntPtr.Zero)
                  _SQLiteModule = PreLoadSQLiteDll(null, null);
          }
      }

      /////////////////////////////////////////////////////////////////////////
      /// <summary>

      /// 
      /// </summary>
      /// <returns>

      /// 
      /// </returns>
      private static string GetXmlConfigurationFileName()
      {
          string directory;
          string fileName;

#if !PLATFORM_COMPACTFRAMEWORK
          directory = AppDomain.CurrentDomain.BaseDirectory;
          fileName = Path.Combine(directory, XmlConfigurationFileName);

          if (File.Exists(fileName))
              return fileName;
#endif

          directory = GetAssemblyDirectory();
          fileName = Path.Combine(directory, XmlConfigurationFileName);

          if (File.Exists(fileName))
              return fileName;

          return null;
      }








>
|


>
|

|






|






|







247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
              if (_SQLiteModule == IntPtr.Zero)
                  _SQLiteModule = PreLoadSQLiteDll(null, null);
          }
      }

      /////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// Queries and returns the XML configuration file name for the assembly
      /// containing the managed System.Data.SQLite components.
      /// </summary>
      /// <returns>
      /// The XML configuration file name -OR- null if it cannot be determined
      /// or does not exist.
      /// </returns>
      private static string GetXmlConfigFileName()
      {
          string directory;
          string fileName;

#if !PLATFORM_COMPACTFRAMEWORK
          directory = AppDomain.CurrentDomain.BaseDirectory;
          fileName = Path.Combine(directory, XmlConfigFileName);

          if (File.Exists(fileName))
              return fileName;
#endif

          directory = GetAssemblyDirectory();
          fileName = Path.Combine(directory, XmlConfigFileName);

          if (File.Exists(fileName))
              return fileName;

          return null;
      }

291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
      /// <returns>
      /// The value of the configuration variable -OR- null if it cannot be
      /// determined.  By default, references to existing environment will
      /// be expanded within the returned value unless either the "No_Expand"
      /// or "No_Expand_<paramref name="name" />" environment variables are
      /// set.
      /// </returns>
      internal static string GetVariableValue(
          string name
          )
      {
          string value = null;

          if (name == null)
              return value;







|







293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
      /// <returns>
      /// The value of the configuration variable -OR- null if it cannot be
      /// determined.  By default, references to existing environment will
      /// be expanded within the returned value unless either the "No_Expand"
      /// or "No_Expand_<paramref name="name" />" environment variables are
      /// set.
      /// </returns>
      internal static string GetSettingValue(
          string name
          )
      {
          string value = null;

          if (name == null)
              return value;
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

          if (value != null)
              return value;
#endif

          try
          {
              string fileName = GetXmlConfigurationFileName();

              if (fileName == null)
                  return value;

              XmlDocument document = new XmlDocument();

              document.Load(fileName);

              XmlElement element = document.SelectSingleNode(String.Format(
                  "/configuration/appSettings/add[@key='{0}']")) as XmlElement;

              if (element != null)
              {

                  value = element.GetAttribute("value");

                  if (String.IsNullOrEmpty(value))
                      value = null;
#if !PLATFORM_COMPACTFRAMEWORK
                  else if (expand)
                      value = Environment.ExpandEnvironmentVariables(value);
#endif
              }
          }
#if !NET_COMPACT_20 && TRACE_PRELOAD
          catch (Exception e)
#else







|













>
|

<
<

|







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

          if (value != null)
              return value;
#endif

          try
          {
              string fileName = GetXmlConfigFileName();

              if (fileName == null)
                  return value;

              XmlDocument document = new XmlDocument();

              document.Load(fileName);

              XmlElement element = document.SelectSingleNode(String.Format(
                  "/configuration/appSettings/add[@key='{0}']")) as XmlElement;

              if (element != null)
              {
                  if (element.HasAttribute("value"))
                      value = element.GetAttribute("value");



#if !PLATFORM_COMPACTFRAMEWORK
                  if (expand && !String.IsNullOrEmpty(value))
                      value = Environment.ExpandEnvironmentVariables(value);
#endif
              }
          }
#if !NET_COMPACT_20 && TRACE_PRELOAD
          catch (Exception e)
#else
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
      /// </returns>
      private static string GetBaseDirectory()
      {
          //
          // NOTE: If the "PreLoadSQLite_BaseDirectory" environment variable
          //       is set, use it verbatim for the base directory.
          //
          string directory = GetVariableValue("PreLoadSQLite_BaseDirectory");

          if (directory != null)
              return directory;

#if !PLATFORM_COMPACTFRAMEWORK
          //
          // NOTE: If the "PreLoadSQLite_UseAssemblyDirectory" environment
          //       variable is set (to anything), attempt to use the directory
          //       containing the currently executing assembly (i.e.
          //       System.Data.SQLite) intsead of the application domain base
          //       directory.
          //
          if (GetVariableValue("PreLoadSQLite_UseAssemblyDirectory") != null)
          {
              directory = GetAssemblyDirectory();

              if (directory != null)
                  return directory;
          }








|












|







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
      /// </returns>
      private static string GetBaseDirectory()
      {
          //
          // NOTE: If the "PreLoadSQLite_BaseDirectory" environment variable
          //       is set, use it verbatim for the base directory.
          //
          string directory = GetSettingValue("PreLoadSQLite_BaseDirectory");

          if (directory != null)
              return directory;

#if !PLATFORM_COMPACTFRAMEWORK
          //
          // NOTE: If the "PreLoadSQLite_UseAssemblyDirectory" environment
          //       variable is set (to anything), attempt to use the directory
          //       containing the currently executing assembly (i.e.
          //       System.Data.SQLite) intsead of the application domain base
          //       directory.
          //
          if (GetSettingValue("PreLoadSQLite_UseAssemblyDirectory") != null)
          {
              directory = GetAssemblyDirectory();

              if (directory != null)
                  return directory;
          }

539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
      private static string GetProcessorArchitecture()
      {
          //
          // NOTE: If the "PreLoadSQLite_ProcessorArchitecture" environment
          //       variable is set, use it verbatim for the current processor
          //       architecture.
          //
          string processorArchitecture = GetVariableValue(
              "PreLoadSQLite_ProcessorArchitecture");

          if (processorArchitecture != null)
              return processorArchitecture;

          //
          // BUGBUG: Will this always be reliable?
          //
          processorArchitecture = GetVariableValue(PROCESSOR_ARCHITECTURE);

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

#if !PLATFORM_COMPACTFRAMEWORK
          //
          // HACK: Check for an "impossible" situation.  If the pointer size
          //       is 32-bits, the processor architecture cannot be "AMD64".







|








|







540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
      private static string GetProcessorArchitecture()
      {
          //
          // NOTE: If the "PreLoadSQLite_ProcessorArchitecture" environment
          //       variable is set, use it verbatim for the current processor
          //       architecture.
          //
          string processorArchitecture = GetSettingValue(
              "PreLoadSQLite_ProcessorArchitecture");

          if (processorArchitecture != null)
              return processorArchitecture;

          //
          // BUGBUG: Will this always be reliable?
          //
          processorArchitecture = GetSettingValue(PROCESSOR_ARCHITECTURE);

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

#if !PLATFORM_COMPACTFRAMEWORK
          //
          // HACK: Check for an "impossible" situation.  If the pointer size
          //       is 32-bits, the processor architecture cannot be "AMD64".