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.

Changes In Branch legacyClose Excluding Merge-Ins

This is equivalent to a diff from dabfe38a9e to a75bb0a659

2013-02-15
21:43
Merge support for the INTEROP_LEGACY_CLOSE compile-time option to trunk. check-in: ec6819f0bf user: mistachkin tags: trunk
08:36
Add initial draft of the custom connection pool feature. check-in: 44b92245a6 user: mistachkin tags: customPool
04:36
Fix compilation and test issues with the INTEROP_LEGACY_CLOSE compile-time option. Closed-Leaf check-in: a75bb0a659 user: mistachkin tags: legacyClose
01:14
Add the ability to select the legacy connection closing algorithm at compile-time. check-in: 2f90848c8e user: mistachkin tags: legacyClose
2013-02-13
21:59
Add doc wording to clarify that the connection pool will not work properly in WPF applications. Pursuant to [393d954be0]. check-in: dabfe38a9e user: mistachkin tags: trunk
03:06
Revise docs on how to obtain the source code. check-in: c13ff09745 user: mistachkin tags: trunk

Changes to SQLite.Interop/src/win/interop.c.

73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
SQLITE_PRIVATE int logConfigured = 0;

SQLITE_PRIVATE void sqlite3InteropLogCallback(void *pArg, int iCode, const char *zMsg){
  sqlite3InteropDebug("INTEROP_LOG (%d) %s\n", iCode, zMsg);
}
#endif

#if SQLITE_VERSION_NUMBER < 3007014
SQLITE_PRIVATE void * sqlite3DbMallocZero_interop(sqlite3 *db, int n)
{
  void *p;
  if (db) {
    sqlite3_mutex_enter(db->mutex);
  }
  p = sqlite3DbMallocZero(db,n);







|







73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
SQLITE_PRIVATE int logConfigured = 0;

SQLITE_PRIVATE void sqlite3InteropLogCallback(void *pArg, int iCode, const char *zMsg){
  sqlite3InteropDebug("INTEROP_LOG (%d) %s\n", iCode, zMsg);
}
#endif

#if defined(INTEROP_LEGACY_CLOSE) || SQLITE_VERSION_NUMBER < 3007014
SQLITE_PRIVATE void * sqlite3DbMallocZero_interop(sqlite3 *db, int n)
{
  void *p;
  if (db) {
    sqlite3_mutex_enter(db->mutex);
  }
  p = sqlite3DbMallocZero(db,n);
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
    that memory was deallocated.  BAD.  So, what we need to do is make a copy of each statement, and call finalize() on the copy -- so that the original
    statement's memory is preserved, and marked as BAD, but we can still manage to finalize everything and forcibly close the database.  Later when the 
    GC gets around to calling finalize_interop() on the "bad" statement, we detect that and finish deallocating the pointer.
*/
SQLITE_API int WINAPI sqlite3_close_interop(sqlite3 *db)
{
  int ret;
#if SQLITE_VERSION_NUMBER >= 3007014

#if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_CLOSE)
  sqlite3InteropDebug("sqlite3_close_interop(): calling sqlite3_close_v2(%p)...\n", db);
#endif

  ret = sqlite3_close_v2(db);








|







118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
    that memory was deallocated.  BAD.  So, what we need to do is make a copy of each statement, and call finalize() on the copy -- so that the original
    statement's memory is preserved, and marked as BAD, but we can still manage to finalize everything and forcibly close the database.  Later when the 
    GC gets around to calling finalize_interop() on the "bad" statement, we detect that and finish deallocating the pointer.
*/
SQLITE_API int WINAPI sqlite3_close_interop(sqlite3 *db)
{
  int ret;
#if !defined(INTEROP_LEGACY_CLOSE) && SQLITE_VERSION_NUMBER >= 3007014

#if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_CLOSE)
  sqlite3InteropDebug("sqlite3_close_interop(): calling sqlite3_close_v2(%p)...\n", db);
#endif

  ret = sqlite3_close_v2(db);

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
426
427
428
429
430
431
432
  *plen = (pval != 0) ? wcslen((wchar_t *)pval) * sizeof(wchar_t): 0;
  return pval;
}

SQLITE_API int WINAPI sqlite3_finalize_interop(sqlite3_stmt *stmt)
{
  int ret;
#if SQLITE_VERSION_NUMBER >= 3007014

#if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_FINALIZE)
  Vdbe *p = (Vdbe *)stmt;
  sqlite3 *db = p->db;
  sqlite3InteropDebug("sqlite3_finalize_interop(): calling sqlite3_finalize(%p, %p)...\n", db, stmt);
#endif

  ret = sqlite3_finalize(stmt);

#if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_FINALIZE)
  sqlite3InteropDebug("sqlite3_finalize_interop(): sqlite3_finalize(%p, %p) returned %d.\n", db, stmt, ret);
#endif

  return ret;
#else
  Vdbe *p;
  int ret = SQLITE_OK;

  p = (Vdbe *)stmt;
  if (p)
  {
    sqlite3 *db = p->db;

    if (db != NULL)







|
















|







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
426
427
428
429
430
431
432
  *plen = (pval != 0) ? wcslen((wchar_t *)pval) * sizeof(wchar_t): 0;
  return pval;
}

SQLITE_API int WINAPI sqlite3_finalize_interop(sqlite3_stmt *stmt)
{
  int ret;
#if !defined(INTEROP_LEGACY_CLOSE) && SQLITE_VERSION_NUMBER >= 3007014

#if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_FINALIZE)
  Vdbe *p = (Vdbe *)stmt;
  sqlite3 *db = p->db;
  sqlite3InteropDebug("sqlite3_finalize_interop(): calling sqlite3_finalize(%p, %p)...\n", db, stmt);
#endif

  ret = sqlite3_finalize(stmt);

#if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_FINALIZE)
  sqlite3InteropDebug("sqlite3_finalize_interop(): sqlite3_finalize(%p, %p) returned %d.\n", db, stmt, ret);
#endif

  return ret;
#else
  Vdbe *p;
  ret = SQLITE_OK;

  p = (Vdbe *)stmt;
  if (p)
  {
    sqlite3 *db = p->db;

    if (db != NULL)
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481

  return ret;
}

SQLITE_API int WINAPI sqlite3_reset_interop(sqlite3_stmt *stmt)
{
  int ret;
#if SQLITE_VERSION_NUMBER >= 3007014

#if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_RESET)
  sqlite3InteropDebug("sqlite3_reset_interop(): calling sqlite3_reset(%p)...\n", stmt);
#endif

  ret = sqlite3_reset(stmt);








|







467
468
469
470
471
472
473
474
475
476
477
478
479
480
481

  return ret;
}

SQLITE_API int WINAPI sqlite3_reset_interop(sqlite3_stmt *stmt)
{
  int ret;
#if !defined(INTEROP_LEGACY_CLOSE) && SQLITE_VERSION_NUMBER >= 3007014

#if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_RESET)
  sqlite3InteropDebug("sqlite3_reset_interop(): calling sqlite3_reset(%p)...\n", stmt);
#endif

  ret = sqlite3_reset(stmt);

Changes to SQLite.NET.Settings.targets.

276
277
278
279
280
281
282














283
284
285
286
287
288
289
                  INTEROP_DEBUG_RESET          (0x0080)
                  INTEROP_DEBUG_CHANGES        (0x0100)
                  INTEROP_DEBUG_BREAK          (0x0200)
    -->
    <InteropDebug Condition="'$(InteropDebug)' == '' And '$(Configuration)' == 'Debug'">true</InteropDebug>
    <InteropDebug Condition="'$(InteropDebug)' == '' And '$(Configuration)' != 'Debug'">false</InteropDebug>















    <!--
        NOTE: Enable the logging callback in the custom built interop DLL (i.e.
              "SQLite.Interop.dll")?  By default, this is enabled in the Debug
              build configuration.  If this is disabled, the logging callback
              will be unavailable and diagnostic messages may not be seen if
              another native logging callback is not configured.  If this is
              enabled, it must also be enabled via the "INTEROP_LOG=1"







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







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
                  INTEROP_DEBUG_RESET          (0x0080)
                  INTEROP_DEBUG_CHANGES        (0x0100)
                  INTEROP_DEBUG_BREAK          (0x0200)
    -->
    <InteropDebug Condition="'$(InteropDebug)' == '' And '$(Configuration)' == 'Debug'">true</InteropDebug>
    <InteropDebug Condition="'$(InteropDebug)' == '' And '$(Configuration)' != 'Debug'">false</InteropDebug>

    <!--
        NOTE: Disable all use of the sqlite3_close_v2() native API and use the
              legacy System.Data.SQLite connection closing algorithm instead.
              By default, this is disabled.  If this is enabled, it must also
              be enabled via the "INTEROP_LEGACY_CLOSE=1" preprocessor define
              being present in the "INTEROP_EXTRA_DEFINES" macro in the build
              properties file:

                  "SQLite.Interop\props\SQLite.Interop.20YY.[vs]props"

              for the corresponding version(s) of Visual Studio.
    -->
    <InteropLegacyClose Condition="'$(InteropLegacyClose)' == ''">false</InteropLegacyClose>

    <!--
        NOTE: Enable the logging callback in the custom built interop DLL (i.e.
              "SQLite.Interop.dll")?  By default, this is enabled in the Debug
              build configuration.  If this is disabled, the logging callback
              will be unavailable and diagnostic messages may not be seen if
              another native logging callback is not configured.  If this is
              enabled, it must also be enabled via the "INTEROP_LOG=1"

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

592
593
594
595
596
597
598

599
600
601
602
603
604
605
                SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_close(db);
#endif
                if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError(hdl, db));
            }
        }
    }


    internal static void CloseConnectionV2(SQLiteConnectionHandle hdl, IntPtr db)
    {
        if ((hdl == null) || (db == IntPtr.Zero)) return;

        try
        {
            // do nothing.







>







592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
                SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_close(db);
#endif
                if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError(hdl, db));
            }
        }
    }

#if !INTEROP_LEGACY_CLOSE
    internal static void CloseConnectionV2(SQLiteConnectionHandle hdl, IntPtr db)
    {
        if ((hdl == null) || (db == IntPtr.Zero)) return;

        try
        {
            // do nothing.
619
620
621
622
623
624
625

626
627
628
629
630
631
632

                SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_close_v2(db);
#endif
                if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError(hdl, db));
            }
        }
    }


    internal static bool ResetConnection(SQLiteConnectionHandle hdl, IntPtr db, bool canThrow)
    {
        if ((hdl == null) || (db == IntPtr.Zero)) return false;

        bool result = false;








>







620
621
622
623
624
625
626
627
628
629
630
631
632
633
634

                SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_close_v2(db);
#endif
                if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError(hdl, db));
            }
        }
    }
#endif

    internal static bool ResetConnection(SQLiteConnectionHandle hdl, IntPtr db, bool canThrow)
    {
        if ((hdl == null) || (db == IntPtr.Zero)) return false;

        bool result = false;

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

491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
      UnsafeNativeMethods.Initialize();
#endif

#if !INTEROP_LOG
      SQLiteLog.Initialize();
#endif

#if !PLATFORM_COMPACTFRAMEWORK && SQLITE_STANDARD
      //
      // NOTE: Check if the sqlite3_close_v2() native API should be available
      //       to use.  This must be done dynamically because the delegate set
      //       here is used by the SQLiteConnectionHandle class, which is a
      //       CriticalHandle derived class (i.e. protected by a constrained
      //       execution region).  Therefore, if the underlying native entry
      //       point is unavailable, an exception will be raised even if it is







|







491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
      UnsafeNativeMethods.Initialize();
#endif

#if !INTEROP_LOG
      SQLiteLog.Initialize();
#endif

#if !PLATFORM_COMPACTFRAMEWORK && !INTEROP_LEGACY_CLOSE && SQLITE_STANDARD
      //
      // NOTE: Check if the sqlite3_close_v2() native API should be available
      //       to use.  This must be done dynamically because the delegate set
      //       here is used by the SQLiteConnectionHandle class, which is a
      //       CriticalHandle derived class (i.e. protected by a constrained
      //       execution region).  Therefore, if the underlying native entry
      //       point is unavailable, an exception will be raised even if it is

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

31
32
33
34
35
36
37




38
39
40
41
42
43
44
#if INTEROP_DEBUG
            "INTEROP_DEBUG",
#endif

#if INTEROP_EXTENSION_FUNCTIONS
            "INTEROP_EXTENSION_FUNCTIONS",
#endif





#if INTEROP_LOG
            "INTEROP_LOG",
#endif

#if INTEROP_TEST_EXTENSION
            "INTEROP_TEST_EXTENSION",







>
>
>
>







31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#if INTEROP_DEBUG
            "INTEROP_DEBUG",
#endif

#if INTEROP_EXTENSION_FUNCTIONS
            "INTEROP_EXTENSION_FUNCTIONS",
#endif

#if INTEROP_LEGACY_CLOSE
            "INTEROP_LEGACY_CLOSE",
#endif

#if INTEROP_LOG
            "INTEROP_LOG",
#endif

#if INTEROP_TEST_EXTENSION
            "INTEROP_TEST_EXTENSION",

Changes to System.Data.SQLite/System.Data.SQLite.Properties.targets.

149
150
151
152
153
154
155








156
157
158
159
160
161
162
      NOTE: Enable extra diagnostics from the custom built interop DLL (see the
            "SQLite.NET.Settings.targets" file for more information)?
  -->
  <PropertyGroup Condition="'$(InteropDebug)' != 'false'">
    <DefineConstants>$(DefineConstants);INTEROP_DEBUG</DefineConstants>
  </PropertyGroup>









  <!--
      NOTE: Enable the logging callback in the custom built interop DLL (see
            the "SQLite.NET.Settings.targets" file for more information)?
  -->
  <PropertyGroup Condition="'$(InteropLog)' != 'false'">
    <DefineConstants>$(DefineConstants);INTEROP_LOG</DefineConstants>
  </PropertyGroup>







>
>
>
>
>
>
>
>







149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
      NOTE: Enable extra diagnostics from the custom built interop DLL (see the
            "SQLite.NET.Settings.targets" file for more information)?
  -->
  <PropertyGroup Condition="'$(InteropDebug)' != 'false'">
    <DefineConstants>$(DefineConstants);INTEROP_DEBUG</DefineConstants>
  </PropertyGroup>

  <!--
      NOTE: Disable all use of the sqlite3_close_v2() native API and use the
            legacy System.Data.SQLite connection closing algorithm instead.
  -->
  <PropertyGroup Condition="'$(InteropLegacyClose)' != 'false'">
    <DefineConstants>$(DefineConstants);INTEROP_LEGACY_CLOSE</DefineConstants>
  </PropertyGroup>

  <!--
      NOTE: Enable the logging callback in the custom built interop DLL (see
            the "SQLite.NET.Settings.targets" file for more information)?
  -->
  <PropertyGroup Condition="'$(InteropLog)' != 'false'">
    <DefineConstants>$(DefineConstants);INTEROP_LOG</DefineConstants>
  </PropertyGroup>

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

639
640
641
642
643
644
645

646
647
648
649
650
651

652
653
654
655
656
657
658
#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern SQLiteErrorCode sqlite3_close(IntPtr db);


#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern SQLiteErrorCode sqlite3_close_v2(IntPtr db); /* 3.7.14+ */


#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern SQLiteErrorCode sqlite3_create_function(IntPtr db, byte[] strName, int nArgs, int nType, IntPtr pvUser, SQLiteCallback func, SQLiteCallback fstep, SQLiteFinalCallback ffinal);







>






>







639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern SQLiteErrorCode sqlite3_close(IntPtr db);

#if !INTEROP_LEGACY_CLOSE
#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern SQLiteErrorCode sqlite3_close_v2(IntPtr db); /* 3.7.14+ */
#endif

#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern SQLiteErrorCode sqlite3_create_function(IntPtr db, byte[] strName, int nArgs, int nType, IntPtr pvUser, SQLiteCallback func, SQLiteCallback fstep, SQLiteFinalCallback ffinal);

Changes to Tests/common.eagle.

1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
        #       test constraints were enabled for the managed assembly.  There
        #       are some compile-time options that must also have been enabled
        #       for the interop assembly in order to be effective.  For those
        #       options, it will be assumed that it was enabled for the interop
        #       assembly if it was enabled for the managed assembly.
        #
        foreach defineConstant [list CHECK_STATE COUNT_HANDLE INTEROP_CODEC \
                                     INTEROP_DEBUG INTEROP_LOG \
                                     INTEROP_EXTENSION_FUNCTIONS \
                                     INTEROP_TEST_EXTENSION SQLITE_STANDARD \
                                     USE_INTEROP_DLL] {
          #
          # NOTE: Check if the compile-time option is listed in the list of
          #       "define constants" kept track of by the managed assembly.
          #
          checkForSQLiteDefineConstant $::test_channel $defineConstant







|
|







1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
        #       test constraints were enabled for the managed assembly.  There
        #       are some compile-time options that must also have been enabled
        #       for the interop assembly in order to be effective.  For those
        #       options, it will be assumed that it was enabled for the interop
        #       assembly if it was enabled for the managed assembly.
        #
        foreach defineConstant [list CHECK_STATE COUNT_HANDLE INTEROP_CODEC \
                                     INTEROP_DEBUG INTEROP_LEGACY_CLOSE \
                                     INTEROP_LOG INTEROP_EXTENSION_FUNCTIONS \
                                     INTEROP_TEST_EXTENSION SQLITE_STANDARD \
                                     USE_INTEROP_DLL] {
          #
          # NOTE: Check if the compile-time option is listed in the list of
          #       "define constants" kept track of by the managed assembly.
          #
          checkForSQLiteDefineConstant $::test_channel $defineConstant

Changes to Tests/tkt-ae5267b863.eagle.

143
144
145
146
147
148
149
150

151
152
153
154
155
156
        object invoke _Dynamic${id}.Test${id} Main
      } result] : [set result ""]}] $result
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain result code results errors sql dataSource id db fileName
} -constraints [fixConstraints {eagle monoBug28 command.sql compile.DATA\
SQLite System.Data.SQLite !mda}] -match regexp -result {^Ok\

System#CodeDom#Compiler#CompilerResults#\d+ \{\} 0 \{\}$}}

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

runSQLiteTestEpilogue
runTestEpilogue







|
>
|





143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
        object invoke _Dynamic${id}.Test${id} Main
      } result] : [set result ""]}] $result
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain result code results errors sql dataSource id db fileName
} -constraints [fixConstraints {eagle monoBug28 command.sql compile.DATA\
SQLite System.Data.SQLite !mda\
!defineConstant.System.Data.SQLite.INTEROP_LEGACY_CLOSE}] -match regexp \
-result {^Ok System#CodeDom#Compiler#CompilerResults#\d+ \{\} 0 \{\}$}}

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

runSQLiteTestEpilogue
runTestEpilogue