System.Data.SQLite
Check-in [54f887ca5c]
Not logged in

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

Overview
Comment:Add connection flags NoConnectionPool and UseConnectionPool. Several enhancements to the stress test.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 54f887ca5c895fef4720cd31608b9005597084d3
User & Date: mistachkin 2014-01-17 00:10:10
Context
2014-01-17
00:56
Improvements to download page. check-in: b6ec17e14b user: mistachkin tags: trunk
00:10
Add connection flags NoConnectionPool and UseConnectionPool. Several enhancements to the stress test. check-in: 54f887ca5c user: mistachkin tags: trunk
2014-01-15
22:37
Refactor and enhance all NuGet packages, adding configuration transform support and registration of the EF6 provider, where applicable. check-in: b4ff09e435 user: mistachkin tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to Doc/Extra/version.html.

45
46
47
48
49
50
51

52
53
54
55
56
57
58
    <h1 class="heading">Version History</h1>
    <p><b>1.0.91.0 - February XX, 2014 <font color="red">(release scheduled)</font></b></p>
    <ul>
      <li>Add support for <a href="http://entityframework.codeplex.com/">Entity Framework 6</a>.</li>
      <li>Modify the namespace used for all internal classes in the System.Data.SQLite.Linq assembly.&nbsp;<b>** Potentially Incompatible Change **</b></li>
      <li>Add SQLiteCompileOptions and InteropCompileOptions properties to the SQLiteConnection class to return the compile-time options for the SQLite core library and interop assembly, respectively.</li>
      <li>Add BindInvariantText and ConvertInvariantText connection flags to force the invariant culture to be used when converting parameter values to/from strings.</li>

      <li>Modify handling of the design-time components installer to run Visual Studio <b>devenv.exe /setup</b> after installing the package. This appears to be necessary in some circumstances for Visual Studio 2013. Pursuant to <a href="http://system.data.sqlite.org/index.html/info/a47eff2c71">[a47eff2c71]</a>.</li>
      <li>Modify the native library pre-loader to support reading settings from an XML configuration file and to be capable of checking more than one directory. Persuant to <a href="http://system.data.sqlite.org/index.html/info/f0246d1817">[f0246d1817]</a>.</li>
      <li>Change the default behavior for the native library pre-loader so it first searches the executing (i.e. System.Data.SQLite) assembly directory and then the application domain directory. Pursuant to <a href="http://system.data.sqlite.org/index.html/info/f0246d1817">[f0246d1817]</a>.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    </ul>
    <p><b>1.0.90.0 - December 23, 2013</b></p>
    <ul>
      <li>Updated to <a href="http://www.sqlite.org/releaselog/3_8_2.html">SQLite 3.8.2</a>.</li>







>







45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
    <h1 class="heading">Version History</h1>
    <p><b>1.0.91.0 - February XX, 2014 <font color="red">(release scheduled)</font></b></p>
    <ul>
      <li>Add support for <a href="http://entityframework.codeplex.com/">Entity Framework 6</a>.</li>
      <li>Modify the namespace used for all internal classes in the System.Data.SQLite.Linq assembly.&nbsp;<b>** Potentially Incompatible Change **</b></li>
      <li>Add SQLiteCompileOptions and InteropCompileOptions properties to the SQLiteConnection class to return the compile-time options for the SQLite core library and interop assembly, respectively.</li>
      <li>Add BindInvariantText and ConvertInvariantText connection flags to force the invariant culture to be used when converting parameter values to/from strings.</li>
      <li>Add NoConnectionPool and UseConnectionPool connection flags to disable or enable connection pooling by default.</li>
      <li>Modify handling of the design-time components installer to run Visual Studio <b>devenv.exe /setup</b> after installing the package. This appears to be necessary in some circumstances for Visual Studio 2013. Pursuant to <a href="http://system.data.sqlite.org/index.html/info/a47eff2c71">[a47eff2c71]</a>.</li>
      <li>Modify the native library pre-loader to support reading settings from an XML configuration file and to be capable of checking more than one directory. Persuant to <a href="http://system.data.sqlite.org/index.html/info/f0246d1817">[f0246d1817]</a>.</li>
      <li>Change the default behavior for the native library pre-loader so it first searches the executing (i.e. System.Data.SQLite) assembly directory and then the application domain directory. Pursuant to <a href="http://system.data.sqlite.org/index.html/info/f0246d1817">[f0246d1817]</a>.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    </ul>
    <p><b>1.0.90.0 - December 23, 2013</b></p>
    <ul>
      <li>Updated to <a href="http://www.sqlite.org/releaselog/3_8_2.html">SQLite 3.8.2</a>.</li>

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

991
992
993
994
995
996
997


















998
999
1000
1001
1002
1003
1004

      /// <summary>
      /// When binding parameter values, always use the invariant culture when
      /// converting their values to strings.
      /// </summary>
      BindInvariantText = 0x20000,



















      /// <summary>
      /// When binding parameter values or returning column values, always
      /// treat them as though they were plain text (i.e. no numeric,
      /// date/time, or other conversions should be attempted).
      /// </summary>
      BindAndGetAllAsText = BindAllAsText | GetAllAsText,








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







991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022

      /// <summary>
      /// When binding parameter values, always use the invariant culture when
      /// converting their values to strings.
      /// </summary>
      BindInvariantText = 0x20000,

      /// <summary>
      /// Disable using the connection pool by default.  If the "Pooling"
      /// connection string property is specified, its value will override
      /// this flag.  The precise outcome of combining this flag with the
      /// <see cref="UseConnectionPool" /> flag is unspecified; however,
      /// one of the flags will be in effect.
      /// </summary>
      NoConnectionPool = 0x40000,

      /// <summary>
      /// Enable using the connection pool by default.  If the "Pooling"
      /// connection string property is specified, its value will override
      /// this flag.  The precise outcome of combining this flag with the
      /// <see cref="NoConnectionPool" /> flag is unspecified; however,
      /// one of the flags will be in effect.
      /// </summary>
      UseConnectionPool = 0x80000,

      /// <summary>
      /// When binding parameter values or returning column values, always
      /// treat them as though they were plain text (i.e. no numeric,
      /// date/time, or other conversions should be attempted).
      /// </summary>
      BindAndGetAllAsText = BindAllAsText | GetAllAsText,

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

357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
....
2020
2021
2022
2023
2024
2025
2026

































2027
2028
2029
2030
2031
2032
2033
....
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
    private const int DefaultMaxPoolSize = 100;
    private const int DefaultConnectionTimeout = 30;
    private const bool DefaultFailIfMissing = false;
    private const bool DefaultReadOnly = false;
    private const bool DefaultBinaryGUID = true;
    private const bool DefaultUseUTF16Encoding = false;
    private const bool DefaultToFullPath = true;
    private const bool DefaultPooling = false;
    private const bool DefaultLegacyFormat = false;
    private const bool DefaultForeignKeys = false;
    private const bool DefaultEnlist = true;
    private const bool DefaultSetDefaults = true;

    private const int SQLITE_FCNTL_WIN32_AV_RETRY = 9;

................................................................................

                return null;
            }
        }

        return result;
    }


































    /// <summary>
    /// Opens the connection using the parameters found in the <see cref="ConnectionString" />.
    /// </summary>
    public override void Open()
    {
      CheckDisposed();
................................................................................
          bool toFullPath = SQLiteConvert.ToBoolean(FindKey(opts, "ToFullPath", DefaultToFullPath.ToString()));
          fileName = ExpandFileName(fileName, toFullPath);
        }
      }

      try
      {
        bool usePooling = SQLiteConvert.ToBoolean(FindKey(opts, "Pooling", DefaultPooling.ToString()));
        int maxPoolSize = Convert.ToInt32(FindKey(opts, "Max Pool Size", DefaultMaxPoolSize.ToString()), CultureInfo.InvariantCulture);

        _defaultTimeout = Convert.ToInt32(FindKey(opts, "Default Timeout", DefaultConnectionTimeout.ToString()), CultureInfo.InvariantCulture);

        enumValue = TryParseEnum(typeof(IsolationLevel), FindKey(opts, "Default IsolationLevel", DefaultIsolationLevel.ToString()), true);
        _defaultIsolation = (enumValue is IsolationLevel) ? (IsolationLevel)enumValue : DefaultIsolationLevel;








|







 







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







 







|







357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
....
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
....
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
    private const int DefaultMaxPoolSize = 100;
    private const int DefaultConnectionTimeout = 30;
    private const bool DefaultFailIfMissing = false;
    private const bool DefaultReadOnly = false;
    private const bool DefaultBinaryGUID = true;
    private const bool DefaultUseUTF16Encoding = false;
    private const bool DefaultToFullPath = true;
    private const bool DefaultPooling = false; // TODO: Maybe promote this to static property?
    private const bool DefaultLegacyFormat = false;
    private const bool DefaultForeignKeys = false;
    private const bool DefaultEnlist = true;
    private const bool DefaultSetDefaults = true;

    private const int SQLITE_FCNTL_WIN32_AV_RETRY = 9;

................................................................................

                return null;
            }
        }

        return result;
    }

    /// <summary>
    /// This method figures out what the default connection pool setting should
    /// be based on the connection flags.  When present, the "Pooling" connection
    /// string property value always overrides the value returned by this method.
    /// </summary>
    /// <returns>
    /// Non-zero if the connection pool should be enabled by default; otherwise,
    /// zero.
    /// </returns>
    private bool GetDefaultPooling()
    {
        bool result = DefaultPooling;

        if (result) /* NOTE: True branch not reached in the default build. */
        {
            if ((_flags & SQLiteConnectionFlags.NoConnectionPool) == SQLiteConnectionFlags.NoConnectionPool)
                result = false;

            if ((_flags & SQLiteConnectionFlags.UseConnectionPool) == SQLiteConnectionFlags.UseConnectionPool)
                result = true;
        }
        else
        {
            if ((_flags & SQLiteConnectionFlags.UseConnectionPool) == SQLiteConnectionFlags.UseConnectionPool)
                result = true;

            if ((_flags & SQLiteConnectionFlags.NoConnectionPool) == SQLiteConnectionFlags.NoConnectionPool)
                result = false;
        }

        return result;
    }

    /// <summary>
    /// Opens the connection using the parameters found in the <see cref="ConnectionString" />.
    /// </summary>
    public override void Open()
    {
      CheckDisposed();
................................................................................
          bool toFullPath = SQLiteConvert.ToBoolean(FindKey(opts, "ToFullPath", DefaultToFullPath.ToString()));
          fileName = ExpandFileName(fileName, toFullPath);
        }
      }

      try
      {
        bool usePooling = SQLiteConvert.ToBoolean(FindKey(opts, "Pooling", GetDefaultPooling().ToString()));
        int maxPoolSize = Convert.ToInt32(FindKey(opts, "Max Pool Size", DefaultMaxPoolSize.ToString()), CultureInfo.InvariantCulture);

        _defaultTimeout = Convert.ToInt32(FindKey(opts, "Default Timeout", DefaultConnectionTimeout.ToString()), CultureInfo.InvariantCulture);

        enumValue = TryParseEnum(typeof(IsolationLevel), FindKey(opts, "Default IsolationLevel", DefaultIsolationLevel.ToString()), true);
        _defaultIsolation = (enumValue is IsolationLevel) ? (IsolationLevel)enumValue : DefaultIsolationLevel;

Changes to Tests/settings.stress.mistachkin.eagle.

9
10
11
12
13
14
15


# set count(1) 10;        # Workload iteration count (i.e. within a run).
# set count(2) 200;       # Workload iteration delay, in milliseconds.
# set count(3) 10000;     # Workload "small" data chunk size, in bytes.
# set count(5) 209715200; # Maximum heap memory to exclude at one time.
# set exitOnFail true;    # Halt testing and exit process on test failure?
# set noTrace true;       # Disable SQLite trace logging to a file?








>
9
10
11
12
13
14
15
16

# set count(1) 10;        # Workload iteration count (i.e. within a run).
# set count(2) 200;       # Workload iteration delay, in milliseconds.
# set count(3) 10000;     # Workload "small" data chunk size, in bytes.
# set count(5) 209715200; # Maximum heap memory to exclude at one time.
# set exitOnFail true;    # Halt testing and exit process on test failure?
# set noTrace true;       # Disable SQLite trace logging to a file?
# set noWorkload [list];  # Workloads to be omitted from the run, by index.

Changes to Tests/stress.eagle.

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
...
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
...
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
...
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
...
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
...
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
...
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
...
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
...
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
...
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
...
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
...
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
...
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
....
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
....
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
....
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
....
1252
1253
1254
1255
1256
1257
1258


























































1259


















1260
1261
1262
1263
1264
1265
1266
....
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285



1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
....
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
....
1407
1408
1409
1410
1411
1412
1413








1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
....
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444

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

runTest {test stress-1.1 {multithreaded stress testing} -setup {
  unset -nocomplain result thread index workload priority noWorkload \
      priorities srcDb db fileName compiled options count times logFileName \
      logListener event timeout connection indicators iterations exitOnFail \
      coTaskMem noTrace failures status

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

  proc setupWorkloadMemDb { fileName {varName db} } {
    #
    # NOTE: This should be an in-memory database; therefore, skip attempting
    #       to delete the underlying database file as that would not make any
    #       sense.  Also, disable use of "PRAGMA temp_store_directory" when
    #       setting up the new connection because it is not thread-safe.
    #
    uplevel 1 [list setupDb $fileName "" "" "" "" "" false false true false \
        $varName true]
  }

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

  proc setupWorkloadFileDb { fileName {varName db} } {
    #
    # NOTE: Skip attempting to delete the underlying database file.  Also,
    #       disable use of "PRAGMA temp_store_directory" when setting up
    #       the new connection because it is not thread-safe.
    #
    uplevel 1 [list setupDb $fileName "" "" "" "" "" true false false false \
        $varName true]
................................................................................
  #
  set fileName(2) [file join [getDatabaseDirectory] [appendArgs \
      stress- [pid] - [string trim [clock seconds] -] .db]]

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

  setupWorkloadMemDb $fileName(1) srcDb
  setupWorkloadFileDb $fileName(2)

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

  #
  # NOTE: This serves two purposes.  First, it allows us to verify the trace
  #       logging subsystem is working properly.  Second, it places the file
  #       name for the associated database file into the trace log file.
................................................................................
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #1, CREATE TABLE statements.
    #
    waitTest A
    lappend ::times(1) [lindex [time {
      initTest A
      setupWorkloadFileDb $dstFileName
      for {set index 2} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db [appendArgs \
              "CREATE TABLE IF NOT EXISTS t" \
              $index "(x PRIMARY KEY, y, z);"]
          showTest A
        } error]} then {
................................................................................
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #2, DROP TABLE statements.
    #
    waitTest B
    lappend ::times(2) [lindex [time {
      initTest B
      setupWorkloadFileDb $dstFileName
      for {set index 2} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db [appendArgs \
              "DROP TABLE IF EXISTS t" $index \;]
          showTest B
        } error]} then {
          if {[isExpectedError $error]} then {
................................................................................
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #3, "small" SELECT statements.
    #
    waitTest C
    lappend ::times(3) [lindex [time {
      initTest C
      setupWorkloadFileDb $dstFileName
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          set reader [sql execute -execute reader \
              -format dataReader -alias $db [appendArgs \
              "SELECT x, y FROM " $table " WHERE z = 'small';"]]
          while {[$reader Read]} {
            #
................................................................................
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #4, "big" SELECT statements.
    #
    waitTest D
    lappend ::times(4) [lindex [time {
      initTest D
      setupWorkloadFileDb $dstFileName
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          set reader [sql execute -execute reader \
              -format dataReader -alias $db [appendArgs \
              "SELECT x, y FROM " $table " WHERE z = 'big';"]]
          while {[$reader Read]} {
            #
................................................................................
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #5, "small" INSERT statements.
    #
    waitTest E
    lappend ::times(5) [lindex [time {
      initTest E
      setupWorkloadFileDb $dstFileName
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db [appendArgs "INSERT INTO " $table \
              "(x, y, z) VALUES('" [format %lX [expr {random()}]] \
              "', '" [base64 encode -- [expr {randstr($count2)}]] \
              "', 'small');"]
          showTest E
................................................................................
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #6, "big" INSERT statements.
    #
    waitTest F
    lappend ::times(6) [lindex [time {
      initTest F
      setupWorkloadFileDb $dstFileName
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db [appendArgs "INSERT INTO " $table \
              "(x, y, z) VALUES('" [format %lX [expr {random()}]] \
              "', RANDOMBLOB(" $count3 "), 'big');"]
          showTest F
        } error]} then {
................................................................................
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #7, "small" UPDATE statements.
    #
    waitTest G
    lappend ::times(7) [lindex [time {
      initTest G
      setupWorkloadFileDb $dstFileName
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db [appendArgs "UPDATE " $table \
              " SET y = '" [base64 encode -- [expr {randstr($count2)}]] \
              "' WHERE x LIKE '" [format %X $index] "%' AND z = 'small';"]
          showTest G
        } error]} then {
................................................................................
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #8, "big" UPDATE statements.
    #
    waitTest H
    lappend ::times(8) [lindex [time {
      initTest H
      setupWorkloadFileDb $dstFileName
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db [appendArgs "UPDATE " $table \
              " SET y = RANDOMBLOB(" $count3 ") WHERE x LIKE '" \
              [format %X $index] "%' AND z = 'big';"]
          showTest H
        } error]} then {
................................................................................
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #9, "small" DELETE statements.
    #
    waitTest I
    lappend ::times(9) [lindex [time {
      initTest I
      setupWorkloadFileDb $dstFileName
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db [appendArgs "DELETE FROM " $table \
              " WHERE x LIKE '" [format %X $index] "%' AND z = 'small';"]
          showTest I
        } error]} then {
          if {[isExpectedError $error]} then {
................................................................................
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #10, "big" DELETE statements.
    #
    waitTest J
    lappend ::times(10) [lindex [time {
      initTest J
      setupWorkloadFileDb $dstFileName
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db [appendArgs "DELETE FROM " $table \
              " WHERE x LIKE '" [format %X $index] "%' AND z = 'big';"]
          showTest J
        } error]} then {
          if {[isExpectedError $error]} then {
................................................................................
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #11, VACUUM statement.
    #
    waitTest K
    lappend ::times(11) [lindex [time {
      initTest K
      setupWorkloadFileDb $dstFileName
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db "VACUUM;"
          showTest K
        } error]} then {
          if {[isExpectedError $error]} then {
            showTest k
................................................................................
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #14, PRAGMA integrity check statement.
    #
    waitTest N
    lappend ::times(14) [lindex [time {
      initTest N
      setupWorkloadFileDb $dstFileName
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          set result [sql execute -execute scalar $db \
              "PRAGMA integrity_check;"]
          if {$result ne "ok"} then {
            error [appendArgs "integrity check failed: " $result]
          }
................................................................................
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #17, change the database journal mode
    #
    waitTest Q
    lappend ::times(17) [lindex [time {
      initTest Q
      setupWorkloadFileDb $dstFileName
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db [appendArgs "PRAGMA journal_mode = \"" \
              [expr {$index % 2 == 0 ? "delete" : "wal"}] \"\;]
          showTest Q
        } error]} then {
          if {[isExpectedError $error]} then {
................................................................................
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #18, execute queries against the in-memory database
    #
    waitTest R
    lappend ::times(18) [lindex [time {
      initTest R
      setupWorkloadMemDb $srcFileName
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          #
          # NOTE: Workload #18.3, "small" SELECT statements.
          #
          set reader [sql execute -execute reader \
              -format dataReader -alias $db [appendArgs \
................................................................................
          }
        }
      }
      cleanupDb $srcFileName db false true false
      doneTest R
    }] 0]
  }]


























































} -body {


















  tputs $test_channel [appendArgs \
      "==== WARNING: this stress test may take several minutes...\n"]

  for {set index(0) 1} {$index(0) <= $count(0)} {incr index(0)} {
    if {$index(0) > 1} then {
      #
      # NOTE: Advance output to the next line due to the workload
................................................................................
        "---- starting workload run #" $index(0) ...\n]

    unset -nocomplain thread status; doneTest

    sql execute $srcDb "CREATE TABLE IF NOT EXISTS t1(x PRIMARY KEY, y, z);"
    sql execute $db "CREATE TABLE IF NOT EXISTS t1(x PRIMARY KEY, y, z);"

    foreach index(1) [lsort -integer [array names workload]] {
      if {[lsearch -exact $noWorkload $index(1)] == -1} then {
        set thread($index(1)) [object create -alias System.Threading.Thread \
            [list apply $workload($index(1)) $fileName(1) $fileName(2) t1 \
            $count(1) $count(3) $count(4)] 1048576]




        $thread($index(1)) Name [appendArgs \
            [file rootname [file tail $fileName(2)]] " #" $index(1)]

        if {[info exists priority($index(1))]} then {
          $thread($index(1)) Priority $priority($index(1))
        }
      }
    }

    foreach index(1) [array names thread] {
      $thread($index(1)) Start
    }

................................................................................
  # NOTE: Advance output to the next line due to the workload
  #       iteration progress indicators from the final run.
  #
  tputs $test_channel \n

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

  foreach index(0) [lsort -integer [array names workload]] {
    if {[lsearch -exact $noWorkload $index(0)] == -1} then {
      tputs $test_channel [formatWorkloadResult $index(0)]
    }
  }

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

  foreach index(0) [lsort -integer [array names times]] {
    tputs $test_channel [formatWorkloadTime $index(0)]
  }
................................................................................
  rename delayTest ""
  rename initTest ""
  rename isExpectedError ""
  rename formatWorkloadTime ""
  rename formatWorkloadResult ""
  rename setupWorkloadFileDb ""
  rename setupWorkloadMemDb ""









  cleanupDb $fileName(2)
  cleanupDb $fileName(1) srcDb

  foreach index(0) [array names workload] {
    catch {
      object removecallback [list apply $workload($index(0)) $fileName(1) \
          $fileName(2) t1 $count(1) $count(3) $count(4)]
    }
  }

  freeDbConnection

  if {!$noTrace} then {
    cleanupLogging $logFileName
................................................................................

  rename cleanupLogging ""
  rename setupLogging ""

  unset -nocomplain result thread index workload priority noWorkload \
      priorities srcDb db fileName compiled options count times logFileName \
      logListener event timeout connection indicators iterations exitOnFail \
      coTaskMem noTrace failures status
} -time true -constraints {eagle monoBug28 command.sql compile.DATA SQLite\
System.Data.SQLite compileCSharp} -result {0}}

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

#
# NOTE: Report after test.







|



|












|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







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

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







 







|
|
<
|
|

>
>
>
|
|

|
|
<







 







|
<
|
<







 







>
>
>
>
>
>
>
>




|

|
<







 







|







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
...
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
...
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
...
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
...
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
...
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
...
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
...
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
...
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
...
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
...
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
...
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
...
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
....
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
....
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
....
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
....
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
....
1349
1350
1351
1352
1353
1354
1355
1356
1357

1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368

1369
1370
1371
1372
1373
1374
1375
....
1422
1423
1424
1425
1426
1427
1428
1429

1430

1431
1432
1433
1434
1435
1436
1437
....
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503

1504
1505
1506
1507
1508
1509
1510
....
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526

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

runTest {test stress-1.1 {multithreaded stress testing} -setup {
  unset -nocomplain result thread index workload priority noWorkload \
      priorities srcDb db fileName compiled options count times logFileName \
      logListener event timeout connection indicators iterations exitOnFail \
      coTaskMem noTrace failures status workloadNames workloadCallbacks

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

  proc setupWorkloadMemDb { fileName varName } {
    #
    # NOTE: This should be an in-memory database; therefore, skip attempting
    #       to delete the underlying database file as that would not make any
    #       sense.  Also, disable use of "PRAGMA temp_store_directory" when
    #       setting up the new connection because it is not thread-safe.
    #
    uplevel 1 [list setupDb $fileName "" "" "" "" "" false false true false \
        $varName true]
  }

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

  proc setupWorkloadFileDb { fileName varName } {
    #
    # NOTE: Skip attempting to delete the underlying database file.  Also,
    #       disable use of "PRAGMA temp_store_directory" when setting up
    #       the new connection because it is not thread-safe.
    #
    uplevel 1 [list setupDb $fileName "" "" "" "" "" true false false false \
        $varName true]
................................................................................
  #
  set fileName(2) [file join [getDatabaseDirectory] [appendArgs \
      stress- [pid] - [string trim [clock seconds] -] .db]]

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

  setupWorkloadMemDb $fileName(1) srcDb
  setupWorkloadFileDb $fileName(2) db

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

  #
  # NOTE: This serves two purposes.  First, it allows us to verify the trace
  #       logging subsystem is working properly.  Second, it places the file
  #       name for the associated database file into the trace log file.
................................................................................
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #1, CREATE TABLE statements.
    #
    waitTest A
    lappend ::times(1) [lindex [time {
      initTest A
      setupWorkloadFileDb $dstFileName db
      for {set index 2} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db [appendArgs \
              "CREATE TABLE IF NOT EXISTS t" \
              $index "(x PRIMARY KEY, y, z);"]
          showTest A
        } error]} then {
................................................................................
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #2, DROP TABLE statements.
    #
    waitTest B
    lappend ::times(2) [lindex [time {
      initTest B
      setupWorkloadFileDb $dstFileName db
      for {set index 2} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db [appendArgs \
              "DROP TABLE IF EXISTS t" $index \;]
          showTest B
        } error]} then {
          if {[isExpectedError $error]} then {
................................................................................
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #3, "small" SELECT statements.
    #
    waitTest C
    lappend ::times(3) [lindex [time {
      initTest C
      setupWorkloadFileDb $dstFileName db
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          set reader [sql execute -execute reader \
              -format dataReader -alias $db [appendArgs \
              "SELECT x, y FROM " $table " WHERE z = 'small';"]]
          while {[$reader Read]} {
            #
................................................................................
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #4, "big" SELECT statements.
    #
    waitTest D
    lappend ::times(4) [lindex [time {
      initTest D
      setupWorkloadFileDb $dstFileName db
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          set reader [sql execute -execute reader \
              -format dataReader -alias $db [appendArgs \
              "SELECT x, y FROM " $table " WHERE z = 'big';"]]
          while {[$reader Read]} {
            #
................................................................................
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #5, "small" INSERT statements.
    #
    waitTest E
    lappend ::times(5) [lindex [time {
      initTest E
      setupWorkloadFileDb $dstFileName db
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db [appendArgs "INSERT INTO " $table \
              "(x, y, z) VALUES('" [format %lX [expr {random()}]] \
              "', '" [base64 encode -- [expr {randstr($count2)}]] \
              "', 'small');"]
          showTest E
................................................................................
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #6, "big" INSERT statements.
    #
    waitTest F
    lappend ::times(6) [lindex [time {
      initTest F
      setupWorkloadFileDb $dstFileName db
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db [appendArgs "INSERT INTO " $table \
              "(x, y, z) VALUES('" [format %lX [expr {random()}]] \
              "', RANDOMBLOB(" $count3 "), 'big');"]
          showTest F
        } error]} then {
................................................................................
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #7, "small" UPDATE statements.
    #
    waitTest G
    lappend ::times(7) [lindex [time {
      initTest G
      setupWorkloadFileDb $dstFileName db
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db [appendArgs "UPDATE " $table \
              " SET y = '" [base64 encode -- [expr {randstr($count2)}]] \
              "' WHERE x LIKE '" [format %X $index] "%' AND z = 'small';"]
          showTest G
        } error]} then {
................................................................................
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #8, "big" UPDATE statements.
    #
    waitTest H
    lappend ::times(8) [lindex [time {
      initTest H
      setupWorkloadFileDb $dstFileName db
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db [appendArgs "UPDATE " $table \
              " SET y = RANDOMBLOB(" $count3 ") WHERE x LIKE '" \
              [format %X $index] "%' AND z = 'big';"]
          showTest H
        } error]} then {
................................................................................
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #9, "small" DELETE statements.
    #
    waitTest I
    lappend ::times(9) [lindex [time {
      initTest I
      setupWorkloadFileDb $dstFileName db
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db [appendArgs "DELETE FROM " $table \
              " WHERE x LIKE '" [format %X $index] "%' AND z = 'small';"]
          showTest I
        } error]} then {
          if {[isExpectedError $error]} then {
................................................................................
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #10, "big" DELETE statements.
    #
    waitTest J
    lappend ::times(10) [lindex [time {
      initTest J
      setupWorkloadFileDb $dstFileName db
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db [appendArgs "DELETE FROM " $table \
              " WHERE x LIKE '" [format %X $index] "%' AND z = 'big';"]
          showTest J
        } error]} then {
          if {[isExpectedError $error]} then {
................................................................................
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #11, VACUUM statement.
    #
    waitTest K
    lappend ::times(11) [lindex [time {
      initTest K
      setupWorkloadFileDb $dstFileName db
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db "VACUUM;"
          showTest K
        } error]} then {
          if {[isExpectedError $error]} then {
            showTest k
................................................................................
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #14, PRAGMA integrity check statement.
    #
    waitTest N
    lappend ::times(14) [lindex [time {
      initTest N
      setupWorkloadFileDb $dstFileName db
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          set result [sql execute -execute scalar $db \
              "PRAGMA integrity_check;"]
          if {$result ne "ok"} then {
            error [appendArgs "integrity check failed: " $result]
          }
................................................................................
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #17, change the database journal mode
    #
    waitTest Q
    lappend ::times(17) [lindex [time {
      initTest Q
      setupWorkloadFileDb $dstFileName db
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db [appendArgs "PRAGMA journal_mode = \"" \
              [expr {$index % 2 == 0 ? "delete" : "wal"}] \"\;]
          showTest Q
        } error]} then {
          if {[isExpectedError $error]} then {
................................................................................
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #18, execute queries against the in-memory database
    #
    waitTest R
    lappend ::times(18) [lindex [time {
      initTest R
      setupWorkloadMemDb $srcFileName db
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          #
          # NOTE: Workload #18.3, "small" SELECT statements.
          #
          set reader [sql execute -execute reader \
              -format dataReader -alias $db [appendArgs \
................................................................................
          }
        }
      }
      cleanupDb $srcFileName db false true false
      doneTest R
    }] 0]
  }]

  #############################################################################
  #                              WORKLOAD #19 (S)                             #
  #############################################################################

  set workload(19) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #19, rapidly open/close connections, thread #1.
    #
    waitTest S
    lappend ::times(19) [lindex [time {
      initTest S
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          setupWorkloadFileDb $dstFileName db
          cleanupDb $dstFileName db false true false
          showTest S
        } error]} then {
          if {[isExpectedError $error]} then {
            showTest s
          } else {
            failTest s $error
          }
        }
      }
      doneTest S
    }] 0]
  }]

  #############################################################################
  #                              WORKLOAD #20 (T)                             #
  #############################################################################

  set workload(20) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #20, rapidly open/close connections, thread #2.
    #
    waitTest T
    lappend ::times(20) [lindex [time {
      initTest T
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          setupWorkloadFileDb $dstFileName db
          cleanupDb $dstFileName db false true false
          showTest T
        } error]} then {
          if {[isExpectedError $error]} then {
            showTest t
          } else {
            failTest t $error
          }
        }
      }
      doneTest T
    }] 0]
  }]
} -body {
  set workloadNames(all) [array names workload]

  tputs $test_channel [appendArgs \
      "---- there are " [llength $workloadNames(all)] \
      " total workloads, their names are: " $workloadNames(all) \n]

  set workloadNames(enabled) [list]

  foreach index(0) [lsort -integer $workloadNames(all)] {
    if {[lsearch -exact $noWorkload $index(0)] == -1} then {
      lappend workloadNames(enabled) $index(0)
    }
  }

  tputs $test_channel [appendArgs \
      "---- there are " [llength $workloadNames(enabled)] \
      " enabled workloads, their names are: " $workloadNames(enabled) \n]

  tputs $test_channel [appendArgs \
      "==== WARNING: this stress test may take several minutes...\n"]

  for {set index(0) 1} {$index(0) <= $count(0)} {incr index(0)} {
    if {$index(0) > 1} then {
      #
      # NOTE: Advance output to the next line due to the workload
................................................................................
        "---- starting workload run #" $index(0) ...\n]

    unset -nocomplain thread status; doneTest

    sql execute $srcDb "CREATE TABLE IF NOT EXISTS t1(x PRIMARY KEY, y, z);"
    sql execute $db "CREATE TABLE IF NOT EXISTS t1(x PRIMARY KEY, y, z);"

    foreach index(1) [lsort -integer $workloadNames(enabled)] {
      set workloadCallbacks($index(1)) [list \

          apply $workload($index(1)) $fileName(1) $fileName(2) t1 $count(1) \
          $count(3) $count(4)]

      set thread($index(1)) [object create -alias System.Threading.Thread \
          $workloadCallbacks($index(1)) 1048576]

      $thread($index(1)) Name [appendArgs \
          [file rootname [file tail $fileName(2)]] " #" $index(1)]

      if {[info exists priority($index(1))]} then {
        $thread($index(1)) Priority $priority($index(1))

      }
    }

    foreach index(1) [array names thread] {
      $thread($index(1)) Start
    }

................................................................................
  # NOTE: Advance output to the next line due to the workload
  #       iteration progress indicators from the final run.
  #
  tputs $test_channel \n

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

  foreach index(0) [lsort -integer $workloadNames(enabled)] {

    tputs $test_channel [formatWorkloadResult $index(0)]

  }

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

  foreach index(0) [lsort -integer [array names times]] {
    tputs $test_channel [formatWorkloadTime $index(0)]
  }
................................................................................
  rename delayTest ""
  rename initTest ""
  rename isExpectedError ""
  rename formatWorkloadTime ""
  rename formatWorkloadResult ""
  rename setupWorkloadFileDb ""
  rename setupWorkloadMemDb ""

  catch {
    #
    # NOTE: We must clear the connection pool now because we intend
    #       to delete the databases for this test.
    #
    object invoke System.Data.SQLite.SQLiteConnection ClearAllPools
  }

  cleanupDb $fileName(2)
  cleanupDb $fileName(1) srcDb

  foreach index(0) [array names workloadCallbacks] {
    catch {
      object removecallback $workloadCallbacks($index(0))

    }
  }

  freeDbConnection

  if {!$noTrace} then {
    cleanupLogging $logFileName
................................................................................

  rename cleanupLogging ""
  rename setupLogging ""

  unset -nocomplain result thread index workload priority noWorkload \
      priorities srcDb db fileName compiled options count times logFileName \
      logListener event timeout connection indicators iterations exitOnFail \
      coTaskMem noTrace failures status workloadNames workloadCallbacks
} -time true -constraints {eagle monoBug28 command.sql compile.DATA SQLite\
System.Data.SQLite compileCSharp} -result {0}}

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

#
# NOTE: Report after test.

Changes to readme.htm.

212
213
214
215
216
217
218

219
220
221
222
223
224
225
    <b>1.0.91.0 - February XX, 2014 <font color="red">(release scheduled)</font></b>
</p>
<ul>
    <li>Add support for <a href="http://entityframework.codeplex.com/">Entity Framework 6</a>.</li>
    <li>Modify the namespace used for all internal classes in the System.Data.SQLite.Linq assembly.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>Add SQLiteCompileOptions and InteropCompileOptions properties to the SQLiteConnection class to return the compile-time options for the SQLite core library and interop assembly, respectively.</li>
    <li>Add BindInvariantText and ConvertInvariantText connection flags to force the invariant culture to be used when converting parameter values to/from strings.</li>

    <li>Modify handling of the design-time components installer to run Visual Studio <b>devenv.exe /setup</b> after installing the package. This appears to be necessary in some circumstances for Visual Studio 2013. Pursuant to [a47eff2c71].</li>
    <li>Modify the native library pre-loader to support reading settings from an XML configuration file and to be capable of checking more than one directory. Persuant to [f0246d1817].</li>
    <li>Change the default behavior for the native library pre-loader so it first searches the executing (i.e. System.Data.SQLite) assembly directory and then the application domain directory. Pursuant to [f0246d1817].&nbsp;<b>** Potentially Incompatible Change **</b></li>
</ul>
<p>
    <b>1.0.90.0 - December 23, 2013</b>
</p>







>







212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
    <b>1.0.91.0 - February XX, 2014 <font color="red">(release scheduled)</font></b>
</p>
<ul>
    <li>Add support for <a href="http://entityframework.codeplex.com/">Entity Framework 6</a>.</li>
    <li>Modify the namespace used for all internal classes in the System.Data.SQLite.Linq assembly.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>Add SQLiteCompileOptions and InteropCompileOptions properties to the SQLiteConnection class to return the compile-time options for the SQLite core library and interop assembly, respectively.</li>
    <li>Add BindInvariantText and ConvertInvariantText connection flags to force the invariant culture to be used when converting parameter values to/from strings.</li>
    <li>Add NoConnectionPool and UseConnectionPool connection flags to disable or enable connection pooling by default.</li>
    <li>Modify handling of the design-time components installer to run Visual Studio <b>devenv.exe /setup</b> after installing the package. This appears to be necessary in some circumstances for Visual Studio 2013. Pursuant to [a47eff2c71].</li>
    <li>Modify the native library pre-loader to support reading settings from an XML configuration file and to be capable of checking more than one directory. Persuant to [f0246d1817].</li>
    <li>Change the default behavior for the native library pre-loader so it first searches the executing (i.e. System.Data.SQLite) assembly directory and then the application domain directory. Pursuant to [f0246d1817].&nbsp;<b>** Potentially Incompatible Change **</b></li>
</ul>
<p>
    <b>1.0.90.0 - December 23, 2013</b>
</p>

Changes to www/news.wiki.

6
7
8
9
10
11
12

13
14
15
16
17
18
19
    <b>1.0.91.0 - February XX, 2014 <font color="red">(release scheduled)</font></b>
</p>
<ul>
    <li>Add support for [http://entityframework.codeplex.com/|Entity Framework 6].</li>
    <li>Modify the namespace used for all internal classes in the System.Data.SQLite.Linq assembly.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>Add SQLiteCompileOptions and InteropCompileOptions properties to the SQLiteConnection class to return the compile-time options for the SQLite core library and interop assembly, respectively.</li>
    <li>Add BindInvariantText and ConvertInvariantText connection flags to force the invariant culture to be used when converting parameter values to/from strings.</li>

    <li>Modify handling of the design-time components installer to run Visual Studio <b>devenv.exe /setup</b> after installing the package. This appears to be necessary in some circumstances for Visual Studio 2013. Pursuant to [a47eff2c71].</li>
    <li>Modify the native library pre-loader to support reading settings from an XML configuration file and to be capable of checking more than one directory. Persuant to [f0246d1817].</li>
    <li>Change the default behavior for the native library pre-loader so it first searches the executing (i.e. System.Data.SQLite) assembly directory and then the application domain directory. Pursuant to [f0246d1817].&nbsp;<b>** Potentially Incompatible Change **</b></li>
</ul>
<p>
    <b>1.0.90.0 - December 23, 2013</b>
</p>







>







6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    <b>1.0.91.0 - February XX, 2014 <font color="red">(release scheduled)</font></b>
</p>
<ul>
    <li>Add support for [http://entityframework.codeplex.com/|Entity Framework 6].</li>
    <li>Modify the namespace used for all internal classes in the System.Data.SQLite.Linq assembly.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>Add SQLiteCompileOptions and InteropCompileOptions properties to the SQLiteConnection class to return the compile-time options for the SQLite core library and interop assembly, respectively.</li>
    <li>Add BindInvariantText and ConvertInvariantText connection flags to force the invariant culture to be used when converting parameter values to/from strings.</li>
    <li>Add NoConnectionPool and UseConnectionPool connection flags to disable or enable connection pooling by default.</li>
    <li>Modify handling of the design-time components installer to run Visual Studio <b>devenv.exe /setup</b> after installing the package. This appears to be necessary in some circumstances for Visual Studio 2013. Pursuant to [a47eff2c71].</li>
    <li>Modify the native library pre-loader to support reading settings from an XML configuration file and to be capable of checking more than one directory. Persuant to [f0246d1817].</li>
    <li>Change the default behavior for the native library pre-loader so it first searches the executing (i.e. System.Data.SQLite) assembly directory and then the application domain directory. Pursuant to [f0246d1817].&nbsp;<b>** Potentially Incompatible Change **</b></li>
</ul>
<p>
    <b>1.0.90.0 - December 23, 2013</b>
</p>