System.Data.SQLite

Check-in Differences
Login

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

Difference From d145c7f8900fd4b7 To a81eb9b135e0fd97

2013-01-17
04:59
Update SQLite core library to include the RTree error message changes. Closed-Leaf check-in: d145c7f890 user: mistachkin tags: tkt-d1fb769a8e
01:47
Add initial draft of test for ticket [d1fb769a8e]. check-in: 4e9be1fcdb user: mistachkin tags: tkt-d1fb769a8e
2012-10-14
01:07
Add workload to the stress test that allocates (large amounts of) native heap memory. check-in: 977ba2a5fb user: mistachkin tags: trunk
2012-10-13
22:38
Revise handling of errors in the stress test. check-in: a81eb9b135 user: mistachkin tags: trunk
20:28
Make the stress test failure handling more flexible, add more comments, and improve readability. check-in: 742684b09c user: mistachkin tags: trunk

Deleted .fossil-settings/crnl-glob.
1

-
*
Deleted .fossil-settings/ignore-glob.
1
2


-
-
*.mistachkin.eagle
Externals/Eagle/bin/Eagle*.pdb
Changes to Doc/Extra/dbfactorysupport.html.
81
82
83
84
85
86
87
88

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

88
89
90
91
92
93
94
95







-
+







<configuration>
  <system.data>
    <DbProviderFactories>
      <remove invariant="System.Data.SQLite"/>
      <add name="SQLite Data Provider" invariant="System.Data.SQLite" 
           description=".Net Framework Data Provider for SQLite"
           type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite,
                 Version=1.0.84.0, Culture=neutral,
                 Version=1.0.83.0, Culture=neutral,
                 PublicKeyToken=db937bc2d44ff139"/>
    </DbProviderFactories>
  </system.data>
</configuration>
</pre>
      </div>
      <p>
Changes to Doc/Extra/environment.html.
74
75
76
77
78
79
80
81

82
83
84
85
86
87
88
89
90
91
74
75
76
77
78
79
80

81



82
83
84
85
86
87
88







-
+
-
-
-







          "x64") or platform-specific (e.g. "Win32") directories that reside
          underneath the application base directory.</td>
        </tr>
        <tr valign="top">
          <td>PreLoadSQLite_BaseDirectory</td>
          <td>If this environment variable is set [to anything], it will be
          used instead of the application base directory by the native
          library pre-loader.  This environment variable can be especially
          library pre-loader.</td>
          useful in ASP.NET and other hosted environments where direct control
          of the location of the managed assemblies is not under the control
          of the application.</td>
        </tr>
        <tr valign="top">
          <td>PreLoadSQLite_ProcessorArchitecture</td>
          <td>If this environment 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.</td>
Changes to Doc/Extra/version.html.
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
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







-
-
-
-
-
-
-
-
+

-
+




-
-
-













-
+



-

-
-
-







          </td>
        </tr>
      </table>
    </div>
    <div id="mainSection">
    <div id="mainBody">
    <h1 class="heading">Version History</h1>
    <p><b>1.0.84.0 - January 9, 2013</p>
    <ul>
      <li>Updated to <a href="http://www.sqlite.org/releaselog/3_7_15_2.html">SQLite 3.7.15.2</a>.</li>
      <li>Explicitly dispose of all SQLiteCommand objects managed by the DbDataAdapter class. Fix for <a href="http://system.data.sqlite.org/index.html/info/6434e23a0f">[6434e23a0f]</a>.</li>
      <li>Add Cancel method to the SQLiteConnection class to interrupt a long running query.</li>
      <li>Improve thread safety of the SQLiteLog.LogMessage method.</li>
    </ul>
    <p><b>1.0.83.0 - December 29, 2012</p>
    <p><b>1.0.83.0 - December XX, 2012 <font color="red">(release scheduled)</font></b></p>
    <ul>
      <li>Updated to <a href="http://www.sqlite.org/releaselog/3_7_15_1.html">SQLite 3.7.15.1</a>.</li>
      <li>Updated to <a href="http://www.sqlite.org/src/info/trunk">SQLite 3.7.15</a>.</li>
      <li>Add Visual Studio 2012 support to all the applicable solution/project files, their associated supporting files, and the test suite.</li>
      <li>Add Visual Studio 2012 support to the redesigned designer support installer.</li>
      <li>Allow opened connections to skip adding the extension functions included in the interop assembly via the new NoExtensionFunctions connection flag.</li>
      <li>Support loading of SQLite extensions via the new EnableExtensions and LoadExtension methods of the SQLiteConnection class. Pursuant to <a href="http://system.data.sqlite.org/index.html/info/17045010df">[17045010df]</a>.</li>
      <li>Remove one set of surrounding single or double quotes from property names and values parsed from the connection string. Fix for <a href="http://system.data.sqlite.org/index.html/info/b4cc611998">[b4cc611998]</a>.</li>
      <li>Modify parsing of connection strings to allow property names and values to be quoted.&nbsp;<b>** Potentially Incompatible Change **</b></li>
      <li>Add ParseViaFramework property to the SQLiteConnection class to allow the built-in (i.e. framework provided) connection string parser to be used when opening a connection. Pursuant to <a href="http://system.data.sqlite.org/index.html/info/b4cc611998">[b4cc611998]</a>.</li>
      <li>Add notifications before and after any connection is opened and closed, as well as other related notifications, via the new static Changed event.</li>
      <li>Add an overload of the SQLiteLog.LogMessage method that takes a single string parameter.</li>
      <li>Add an overload of the SQLiteConnection.LogMessage method that takes a SQLiteErrorCode parameter.</li>
      <li>All applicable calls into the SQLite core library now return a SQLiteErrorCode instead of an integer error code.</li>
      <li>Make sure the error code of the SQLiteException class gets serialized.</li>
      <li>Make the test project for the .NET Compact Framework more flexible.</li>
      <li>When available, the new sqlite3_errstr function from the core library is used to get the error message for a specific return code.</li>
      <li>The SetMemoryStatus, Shutdown, ResultCode, ExtendedResultCode, and SetAvRetry methods of the SQLiteConnection class now return a SQLiteErrorCode instead of an integer error code.&nbsp;<b>** Potentially Incompatible Change **</b></li>
      <li>The public constructor for the SQLiteException now takes a SQLiteErrorCode instead of an integer error code.&nbsp;<b>** Potentially Incompatible Change **</b></li>
      <li>The ErrorCode property of the SQLiteException is now an Int32, to allow the property inherited from the base class to be properly overridden.&nbsp;<b>** Potentially Incompatible Change **</b></li>
      <li>The ErrorCode field of the LogEventArgs is now an object instead of an integer.&nbsp;<b>** Potentially Incompatible Change **</b></li>
      <li>The names and messages associated with the SQLiteErrorCode enumeration values have been normalized to match those in the SQLite core library.&nbsp;<b>** Potentially Incompatible Change **</b></li>
      <li>Implement more robust locking semantics for the CriticalHandle derived classes when compiled for the .NET Compact Framework.</li>
      <li>Cache column indexes as they are looked up when using the SQLiteDataReader to improve performance.</li>
      <li>Cache column indexes are they are looked up when using the SQLiteDataReader to improve performance.</li>
      <li>Prevent the SQLiteConnection.Close method from throwing non-fatal exceptions during its disposal.</li>
      <li>Rename the interop assembly functions sqlite3_cursor_rowid, sqlite3_context_collcompare, sqlite3_context_collseq, sqlite3_cursor_rowid, and sqlite3_table_cursor to include an &quot;_interop&quot; suffix.&nbsp;<b>** Potentially Incompatible Change **</b></li>
      <li>Prevent the LastInsertRowId, MemoryUsed, and MemoryHighwater connection properties from throwing NotSupportedException when running on the .NET Compact Framework. Fix for <a href="http://system.data.sqlite.org/index.html/info/dd45aba387">[dd45aba387]</a>.</li>
      <li>Improve automatic detection of the sqlite3_close_v2 function when compiled to use the standard SQLite library.</li>
      <li>Add protection against ThreadAbortException asynchronously interrupting native resource initialization and finalization.</li>
      <li>Add native logging callback for use with the sqlite3_log function to the interop assembly, enabled via the INTEROP_LOG preprocessor definition.</li>
      <li>Add various diagnostic messages to the interop assembly, enabled via flags in the INTEROP_DEBUG preprocessor definition.</li>
      <li>Further enhancements to the build and test automation.</li>
      <li>Add test automation for the Windows CE binaries.</li>
    </ul>
    <p><b>1.0.82.0 - September 3, 2012</b></p>
    <ul>
      <li>Updated to <a href="http://www.sqlite.org/releaselog/3_7_14.html">SQLite 3.7.14</a>.</li>
      <li>Properly handle quoted data source values in the connection string. Fix for <a href="http://system.data.sqlite.org/index.html/info/8c3bee31c8">[8c3bee31c8]</a>.</li>
      <li>The <a href="http://nuget.org/packages/System.Data.SQLite">primary NuGet package</a> now supports x86 / x64 and the .NET Framework 2.0 / 4.0 (i.e. in a single package).</li>
Changes to Doc/Extra/welcome.html.
156
157
158
159
160
161
162
163

164
165
166
167
168
169
170
156
157
158
159
160
161
162

163
164
165
166
167
168
169
170







-
+







        <font color="red">
          Itanium processor support not currently included.
        </font>
      </p>
      <h1 class="heading">Distributing the Binaries (Compact Framework)</h1>
      <p>Both the <b>System.Data.SQLite.DLL </b>and <b>SQLite.Interop.XXX.DLL</b> files
        must be deployed on the Compact Framework.&nbsp; The XXX is the build number of
        the System.Data.SQLite library (e.g. &quot;084&quot;).&nbsp; The
        the System.Data.SQLite library (e.g. &quot;083&quot;).&nbsp; The
        <b>SQLite.Interop.XXX.DLL</b> file is a fully native assembly compiled for
        the ARM processor, and System.Data.SQLite is the fully-managed Compact
        Framework assembly.</p>
      <hr />
      <div id="footer">
        <p>
          <a href="mailto:sqlite-users@sqlite.org?subject=SQLite.NET%20Class%20Library%20Documentation%20Feedback:%20Welcome">
Changes to Doc/SQLite.NET.chm.

cannot compute difference between binary files

Changes to Externals/Eagle/bin/Eagle.dll.

cannot compute difference between binary files

Changes to Externals/Eagle/bin/EagleShell.exe.

cannot compute difference between binary files

Changes to Externals/Eagle/bin/EagleShell.exe.mda.config.
9
10
11
12
13
14
15
16

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

16

17
18
19
20
21
22
23







-
+
-







 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: $
 *
-->
<mdaConfig xmlns="http://schemas.microsoft.com/CLR/2004/10/mda">
  <assistants>
    <!--++
    <!--
    <asynchronousThreadAbort />
    <bindingFailure />
    <callbackOnCollectedDelegate listSize="50" />
    <contextSwitchDeadlock enable="true" />
    <dangerousThreadingAPI />
    <dateTimeInvalidLocalFormat />
    <dirtyCastAndCallOnInterface />
    <disconnectedContext enable="true" />
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82

83
84
60
61
62
63
64
65
66

67
68
69
70
71
72
73
74
75
76
77
78
79

80
81
82







-













-
+


    <overlappedFreeError />
    <pInvokeLog>
      <filter>
        <match dllName="advapi32.dll" />
        <match dllName="advpack.dll" />
        <match dllName="kernel32.dll" />
        <match dllName="mscoree.dll" />
        <match dllName="msvcrt.dll" />
        <match dllName="ntdll.dll" />
        <match dllName="shell32.dll" />
        <match dllName="user32.dll" />
        <match dllName="wintrust.dll" />
      </filter>
    </pInvokeLog>
    <pInvokeStackImbalance />
    <raceOnRCWCleanup />
    <reentrancy />
    <releaseHandleFailed />
    <reportAvOnComRelease allowAv="true" />
    <streamWriterBufferedDataLost />
    <virtualCERCall />
    ++-->
    -->
  </assistants>
</mdaConfig>
Changes to Externals/Eagle/lib/Eagle1.0/init.eagle.
139
140
141
142
143
144
145
146

147
148
149
150
151
152
153
139
140
141
142
143
144
145

146
147
148
149
150
151
152
153







-
+







    set result ""; eval append result $args
  }

  proc lappendArgs { args } {
    #
    # NOTE: This should work properly in both Tcl and Eagle.
    #
    set result [list]; eval lappend result $args
    eval lappend result $args
  }

  proc getDictionaryValue { dictionary name {default ""} {wrap ""} } {
    #
    # NOTE: Locate the named value we are interested in.  The dictionary must
    #       be a list with an even number of elements in the following format:
    #
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
976
977
978
979
980
981
982





983
984
985
986
987
988
989







-
-
-
-
-







      #       therefore, dispose it now.
      #
      unset errors; # dispose

      return $code
    }

    proc matchEnginePublicKeyToken { publicKeyToken } {
      return [expr {[string length $publicKeyToken] == 0 || \
          $publicKeyToken eq [info engine PublicKeyToken]}]
    }

    proc matchEngineName { name } {
      return [expr {[string length $name] == 0 || \
          $name eq [info engine Name]}]
    }

    proc matchEngineCulture { culture } {
      return [expr {[string length $culture] == 0 || \
1043
1044
1045
1046
1047
1048
1049
1050
1051













1052
1053
1054
1055
1056
1057





1058
1059
1060



1061
1062
1063










1064
1065
1066
1067


1068
1069
1070
1071
1072
1073
1074
1038
1039
1040
1041
1042
1043
1044


1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057

1058




1059
1060
1061
1062
1063
1064


1065
1066
1067



1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079


1080
1081
1082
1083
1084
1085
1086
1087
1088







-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-

-
-
-
-
+
+
+
+
+

-
-
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+


-
-
+
+







              set components [list $baseUri releases $patchLevel]

              #
              # NOTE: Next, figure out what type of download is being
              #       requested.
              #
              switch -exact -nocase -- $type {
                source -
                setup -
                source {
                  #
                  # NOTE: Source code download.  This may be a RAR or an EXE
                  #       file.  Append the appropriate file name and then
                  #       join all the URI components to form the final URI.
                  #
                  set fileName [appendArgs EagleSource $patchLevel $extension]
                  lappend components $fileName

                  set result [list [eval uri join $components] \
                      [file join $directory $fileName]]
                }
                setup {
                binary {
                  #
                  # NOTE: Source code, setup, or binary download.  This may be
                  #       a RAR or an EXE file.  Append the appropriate file
                  #       name and then join all the URI components to form the
                  #       final URI.
                  # NOTE: Windows setup download.  Always append an ".exe"
                  #       extension because we never distribute the setup as
                  #       a RAR file.  Append the appropriate file name and
                  #       then join all the URI components to form the final
                  #       URI.
                  #
                  set fileName [appendArgs \
                      [info engine] [string totitle $type] $patchLevel \
                  set fileName [appendArgs EagleSetup $patchLevel .exe]
                  lappend components $fileName

                      [expr {[string tolower $type] eq "setup" ? ".exe" : \
                      $extension}]]

                  set result [list [eval uri join $components] \
                      [file join $directory $fileName]]
                }
                binary {
                  #
                  # NOTE: Binary file download.  This may be a RAR or an EXE
                  #       file.  Append the appropriate file name and then
                  #       join all the URI components to form the final URI.
                  #
                  set fileName [appendArgs EagleBinary $patchLevel $extension]
                  lappend components $fileName

                  set result [list [eval uri join $components] [file join \
                      $directory $fileName]]
                  set result [list [eval uri join $components] \
                      [file join $directory $fileName]]
                }
              }
            }
          }
        }
      }

1234
1235
1236
1237
1238
1239
1240
1241

1242
1243
1244
1245
1246
1247
1248
1248
1249
1250
1251
1252
1253
1254

1255
1256
1257
1258
1259
1260
1261
1262







-
+







            #       make sure we get the same "flavor" of the engine.
            #       The lines are organized so that the "latest stable
            #       version" is on the first line (for a given public key
            #       token), followed by development builds, experimental
            #       builds, etc.
            #
            if {$protocolId eq "1" && \
                [matchEnginePublicKeyToken $publicKeyToken] && \
                $publicKeyToken eq [info engine PublicKeyToken] && \
                [matchEngineName $name] && \
                [matchEngineCulture $culture]} then {
              #
              # NOTE: Grab the patch level field.
              #
              set patchLevel [lindex $fields 4]

1423
1424
1425
1426
1427
1428
1429
1430
1431


1432
1433
1434


1435
1436
1437
1438
1439
1440
1441
1437
1438
1439
1440
1441
1442
1443


1444
1445
1446


1447
1448
1449
1450
1451
1452
1453
1454
1455







-
-
+
+

-
-
+
+








        #
        # HACK: Mono does not currently support calling the String.Format
        #       overload that takes a variable number of arguments via
        #       reflection (Mono bug #636939).
        #
        if {![isMono]} then {
          set line [string format -verbatim -- [appendArgs "\{0,-" \
              $maxLength "\} = {1}"] $nameString $valueString]
          set line [string format -verbatim -- "{0,-$maxLength} = {1}" \
              $nameString $valueString]
        } else {
          set line [object invoke String Format [appendArgs "\{0,-" \
              $maxLength "\} = {1}"] $nameString $valueString]
          set line [object invoke String Format "{0,-$maxLength} = {1}" \
              $nameString $valueString]
        }

        puts stdout $line
      }
    }

    proc pdict { d } {
1534
1535
1536
1537
1538
1539
1540
1541

1542
1543
1544
1545
1546

1547
1548
1549
1550
1551
1552








1553
1554
1555

1556
1557
1558



1559
1560
1561
1562
1563
1564


1565
1566
1567
1568
1569
1570
1571


1572
1573
1574
1575
1576
1577

1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610

1611
1612
1613
1614
1615
1616
1617
1618
1619


1620
1621
1622
1623
1624
1625

1626
1627
1628
1629
1630
1631
1632


1633
1634
1635
1636
1637
1638

1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658

1659
1660
1661
1662
1663
1664
1665
1666
1667


1668
1669
1670
1671
1672
1673

1674
1675
1676
1677
1678
1679
1680


1681
1682
1683
1684
1685
1686

1687
1688
1689
1690
1691
1692
1693
1548
1549
1550
1551
1552
1553
1554

1555
1556
1557
1558


1559






1560
1561
1562
1563
1564
1565
1566
1567



1568



1569
1570
1571






1572
1573







1574
1575
1576
1577
1578
1579
1580

1581













1582
1583
1584
1585
1586
1587
1588
1589
1590
1591







1592
1593

1594
1595








1596
1597
1598
1599
1600
1601
1602

1603
1604
1605
1606
1607
1608


1609
1610
1611
1612
1613
1614
1615

1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626







1627
1628

1629
1630








1631
1632
1633
1634
1635
1636
1637

1638
1639
1640
1641
1642
1643


1644
1645
1646
1647
1648
1649
1650

1651
1652
1653
1654
1655
1656
1657
1658







-
+



-
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
+
-
-
-
+
+
+
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
+
+





-
+
-
-
-
-
-
-
-
-
-
-
-
-
-










-
-
-
-
-
-
-


-
+

-
-
-
-
-
-
-
-
+
+





-
+





-
-
+
+





-
+










-
-
-
-
-
-
-


-
+

-
-
-
-
-
-
-
-
+
+





-
+





-
-
+
+





-
+







    proc tclLog { string } {
      #
      # NOTE: This should work properly in both Tcl and Eagle.
      #
      catch {puts stderr $string}
    }

    proc makeVariableFast { name fast } {
    proc findDirectories { pattern } {
      #
      # NOTE: This should work properly in Eagle only.
      #
      catch {
        uplevel 1 [list object invoke -flags +NonPublic \
      set result [list]
            Interpreter.GetActive MakeVariableFast $name $fast]
      }
    }

    proc findDirectories { pattern } {
      #

      foreach dir [split [exec $::env(ComSpec) /c dir /ad /b \
          [appendArgs \" [file nativename $pattern] \"]] \n] {
        set dir [string trim $dir]

        if {[string length $dir] > 0} then {
          set dir [getDirResultPath $pattern $dir]

      # NOTE: Block non-Windows platforms since this is Windows specific.
      #
      if {$::tcl_platform(platform) ne "windows"} then {
          if {[lsearch -exact -nocase $result $dir] == -1} then {
        error "not supported on this operating system"
      }

            lappend result $dir
          }
        }
      #
      # NOTE: This should work properly in Eagle only.
      #
      set dir ""; set result [list]

      #
      }

      # HACK: Optimize the variable access in this procedure to be
      #       as fast as possible.
      #
      makeVariableFast dir true; makeVariableFast result true

      foreach dir [split [exec -unicode $::env(ComSpec) /u /c dir \
          /ad /b [appendArgs \" [file nativename $pattern] \"]] \n] {
      foreach dir [split [exec $::env(ComSpec) /c dir /ahd /b \
          [appendArgs \" [file nativename $pattern] \"]] \n] {
        set dir [string trim $dir]

        if {[string length $dir] > 0} then {
          set dir [getDirResultPath $pattern $dir]

          if {[lsearch -variable -exact -nocase result $dir] == -1} then {
          if {[lsearch -exact -nocase $result $dir] == -1} then {
            lappend result $dir
          }
        }
      }

      foreach dir [split [exec -unicode $::env(ComSpec) /u /c dir \
          /ahd /b [appendArgs \" [file nativename $pattern] \"]] \n] {
        set dir [string trim $dir]

        if {[string length $dir] > 0} then {
          set dir [getDirResultPath $pattern $dir]

          if {[lsearch -variable -exact -nocase result $dir] == -1} then {
            lappend result $dir
          }
        }
      }

      return $result
    }

    proc findFiles { pattern } {
      #
      # NOTE: Block non-Windows platforms since this is Windows specific.
      #
      if {$::tcl_platform(platform) ne "windows"} then {
        error "not supported on this operating system"
      }

      #
      # NOTE: This should work properly in Eagle only.
      #
      set fileName ""; set result [list]
      set result [list]

      #
      # HACK: Optimize the variable access in this procedure to be
      #       as fast as possible.
      #
      makeVariableFast fileName true; makeVariableFast result true

      foreach fileName [split [exec -unicode $::env(ComSpec) /u /c dir \
          /a-d /b [appendArgs \" [file nativename $pattern] \"]] \n] {
      foreach fileName [split [exec $::env(ComSpec) /c dir /a-d /b \
          [appendArgs \" [file nativename $pattern] \"]] \n] {
        set fileName [string trim $fileName]

        if {[string length $fileName] > 0} then {
          set fileName [getDirResultPath $pattern $fileName]

          if {[lsearch -variable -exact -nocase result $fileName] == -1} then {
          if {[lsearch -exact -nocase $result $fileName] == -1} then {
            lappend result $fileName
          }
        }
      }

      foreach fileName [split [exec -unicode $::env(ComSpec) /u /c dir \
          /ah-d /b [appendArgs \" [file nativename $pattern] \"]] \n] {
      foreach fileName [split [exec $::env(ComSpec) /c dir /ah-d /b \
          [appendArgs \" [file nativename $pattern] \"]] \n] {
        set fileName [string trim $fileName]

        if {[string length $fileName] > 0} then {
          set fileName [getDirResultPath $pattern $fileName]

          if {[lsearch -variable -exact -nocase result $fileName] == -1} then {
          if {[lsearch -exact -nocase $result $fileName] == -1} then {
            lappend result $fileName
          }
        }
      }

      return $result
    }

    proc findFilesRecursive { pattern } {
      #
      # NOTE: Block non-Windows platforms since this is Windows specific.
      #
      if {$::tcl_platform(platform) ne "windows"} then {
        error "not supported on this operating system"
      }

      #
      # NOTE: This should work properly in Eagle only.
      #
      set fileName ""; set result [list]
      set result [list]

      #
      # HACK: Optimize the variable access in this procedure to be
      #       as fast as possible.
      #
      makeVariableFast fileName true; makeVariableFast result true

      foreach fileName [split [exec -unicode $::env(ComSpec) /u /c dir \
          /a-d /s /b [appendArgs \" [file nativename $pattern] \"]] \n] {
      foreach fileName [split [exec $::env(ComSpec) /c dir /a-d /s /b \
          [appendArgs \" [file nativename $pattern] \"]] \n] {
        set fileName [string trim $fileName]

        if {[string length $fileName] > 0} then {
          set fileName [getDirResultPath $pattern $fileName]

          if {[lsearch -variable -exact -nocase result $fileName] == -1} then {
          if {[lsearch -exact -nocase $result $fileName] == -1} then {
            lappend result $fileName
          }
        }
      }

      foreach fileName [split [exec -unicode $::env(ComSpec) /u /c dir \
          /ah-d /s /b [appendArgs \" [file nativename $pattern] \"]] \n] {
      foreach fileName [split [exec $::env(ComSpec) /c dir /ah-d /s /b \
          [appendArgs \" [file nativename $pattern] \"]] \n] {
        set fileName [string trim $fileName]

        if {[string length $fileName] > 0} then {
          set fileName [getDirResultPath $pattern $fileName]

          if {[lsearch -variable -exact -nocase result $fileName] == -1} then {
          if {[lsearch -exact -nocase $result $fileName] == -1} then {
            lappend result $fileName
          }
        }
      }

      return $result
    }
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1702
1703
1704
1705
1706
1707
1708







1709
1710
1711
1712
1713
1714
1715







-
-
-
-
-
-
-







      eval lappend result [glob -nocomplain -types {f hidden} \
          [file normalize $pattern]]

      return $result
    }

    proc findFilesRecursive { pattern } {
      #
      # NOTE: Block non-Windows platforms since this is Windows specific.
      #
      if {$::tcl_platform(platform) ne "windows"} then {
        error "not supported on this operating system"
      }

      #
      # NOTE: This should work properly in Tcl only.
      #
      set result [list]

      catch {
        foreach fileName [split [exec $::env(ComSpec) /c dir /a-d /s /b \
1831
1832
1833
1834
1835
1836
1837
1838

1839
1840

1841
1842
1843
1844

1845
1846

1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1789
1790
1791
1792
1793
1794
1795

1796


1797




1798


1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812







-
+
-
-
+
-
-
-
-
+
-
-
+













    }

    #
    # NOTE: Exports the necessary commands from this package and import them
    #       into the global namespace.
    #
    exportAndImportPackageCommands [namespace current] [list \
        isEagle haveGaruda isMono getEnvironmentVariable combineFlags \
        exportAndImportPackageCommands isEagle isMono getEnvironmentVariable \
        getCompileInfo getPlatformInfo getPluginPath appendArgs lappendArgs \
        getDictionaryValue getColumnValue getRowColumnValue tqputs tqlog \
        getPluginPath getDictionaryValue getColumnValue getRowColumnValue \
        readFile readSharedFile writeFile appendFile appendLogFile \
        appendSharedFile appendSharedLogFile readAsciiFile writeAsciiFile \
        readUnicodeFile writeUnicodeFile getDirResultPath addToPath \
        removeFromPath execShell ldifference filter map reduce \
        appendArgs haveGaruda lappendArgs readFile filter map reduce \
        getLengthModifier debug findDirectories findFiles findFilesRecursive \
        exportAndImportPackageCommands] false false
        getPlatformInfo execShell combineFlags tqputs tqlog] false false

    ###########################################################################
    ############################## END Tcl ONLY ###############################
    ###########################################################################
  }

  #
  # NOTE: Provide the Eagle library package to the interpreter.
  #
  package provide Eagle.Library \
    [expr {[isEagle] ? [info engine PatchLevel] : "1.0"}]
}

Changes to Externals/Eagle/lib/Eagle1.0/test.eagle.
295
296
297
298
299
300
301
302

303
304

305
306
307
308
309

310
311
312
313
314
315
316
295
296
297
298
299
300
301

302
303

304
305
306
307
308

309
310
311
312
313
314
315
316







-
+

-
+




-
+








      #
      # NOTE: Calculate how many whole seconds we need to spin for.
      #
      set seconds [expr {$milliseconds / 1000}]

      #
      # NOTE: Calculate the starting and ending values of [clock seconds].
      # NOTE: Calculate the value of [clock seconds] now and at the stop time.
      #
      set now [clock seconds]; set start $now; set stop [expr {$now + $seconds}]
      set start [clock seconds]; set stop [expr {$start + $seconds}]

      #
      # NOTE: Do nothing for X seconds (i.e. except call [clock seconds]).
      #
      while {$start <= $now && $now < $stop} {set now [clock seconds]}
      while {$start <= [clock seconds] && [clock seconds] < $stop} {}

      #
      # NOTE: Record the final Tcl command count.
      #
      set after [info cmdcount]

      #
385
386
387
388
389
390
391
392

393
394
395
396
397
398
399
385
386
387
388
389
390
391

392
393
394
395
396
397
398
399







-
+







    upvar 1 $varName array

    #
    # TODO: Add more support for standard tcltest options here.
    #
    set options [list -configuration -constraints -exitOnComplete -file \
        -logFile -match -no -notFile -postTest -preTest -skip -stopOnFailure \
        -suffix -tclsh -threshold]
        -suffix -threshold]

    foreach {name value} $args {
      #
      # NOTE: Use the [tqputs] command here just in case the test log file
      #       has not been setup yet (i.e. by default, this procedure is
      #       almost always called by the test prologue file prior to the
      #       test log file having been setup and we do not want to just
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
414
415
416
417
418
419
420



























421
422
423
424
425
426
427







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








    #
    # NOTE: Now, attempt to flush the test log queue, if available.
    #
    tlog ""
  }

  proc getTclShellFileName {} {
    #
    # NOTE: Check the environment variables we know about that
    #       may contain the path where the Tcl shell is located.
    #
    foreach name [list Eagle_Tcl_Shell Tcl_Shell] {
      set value [getEnvironmentVariable $name]

      #
      # TODO: Possibly add a check if the file actually exists
      #       here.
      #
      if {[string length $value] > 0} then {
        #
        # NOTE: *EXTERNAL* Return verbatim, no normalization.
        #
        return $value
      }
    }

    #
    # NOTE: None of the environment variables returned anything
    #       valid, return the fallback default.
    #
    return tclsh
  }

  proc getTemporaryPath {} {
    #
    # NOTE: Build the list of "temporary directory" override
    #       environment variables to check.
    #
    set names [list]

702
703
704
705
706
707
708
709

710
711
712
713
714
715
716
675
676
677
678
679
680
681

682
683
684
685
686
687
688
689







-
+







    #
    proc [namespace current]::testPuts { args } {
      switch [llength $args] {
        1 {
          #
          # NOTE: Only the string to be printed is specified (stdout).
          #
          return [tputs $::test_channel [appendArgs [lindex $args 0] \n]]
          return [tputs $::test_channel [lindex $args 0]]
        }
        2 {
          #
          # NOTE: Either -nonewline or channelId has been specified.
          #
          if {[lindex $args 0] eq "-nonewline"} then {
            return [tputs $::test_channel [lindex $args end]]
947
948
949
950
951
952
953
954

955
956
957
958
959

960
961
962
963
964
965
966
920
921
922
923
924
925
926

927
928
929
930
931

932
933
934
935
936
937
938
939







-
+




-
+







        incr count

        tputs $channel [appendArgs "==== \"" $fileName "\" LEAKED " \
            $statistic \n]

        if {[info exists array($statistic,before,list)]} then {
          tputs $channel [appendArgs "---- " $statistic " BEFORE: " \
              [formatList $array($statistic,before,list)] \n]
              $array($statistic,before,list) \n]
        }

        if {[info exists array($statistic,after,list)]} then {
          tputs $channel [appendArgs "---- " $statistic " AFTER: " \
              [formatList $array($statistic,after,list)] \n]
              $array($statistic,after,list) \n]
        }
      }
    }

    #
    # NOTE: Make sure this file name is recorded in the list of file names with
    #       leaking tests.
1114
1115
1116
1117
1118
1119
1120
1121

1122
1123
1124

1125
1126
1127
1128
1129
1130
1131
1087
1088
1089
1090
1091
1092
1093

1094
1095
1096

1097
1098
1099
1100
1101
1102
1103
1104







-
+


-
+







    #
    # NOTE: Show the exact arguments we received since they may not
    #       have been displayed by the caller (or anybody else).
    #
    tputs $channel [appendArgs "---- test run path: \"" $path \"\n]

    tputs $channel [appendArgs "---- test run file names: " \
        [formatList [removePathFromFileNames $path $fileNames]] \n]
        [list [removePathFromFileNames $path $fileNames]] \n]

    tputs $channel [appendArgs "---- test run skip file names: " \
        [formatList $skipFileNames] \n]
        [list $skipFileNames] \n]

    #
    # NOTE: Keep going unless this becomes true (i.e. if one of the
    #       test files signals us to stop).
    #
    set stop false

1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1289
1290
1291
1292
1293
1294
1295






1296
1297
1298
1299
1300
1301
1302







-
-
-
-
-
-







            #
            # NOTE: Determine if any resource leaks have occurred and
            #       output diagnostics as necessary if they have.
            #
            reportTestStatistics $channel $fileName leaks leaked
          }
        } else {
          #
          # NOTE: This entire file has been skipped.  Record that fact in the
          #       test suite log file.
          #
          tputs $channel [appendArgs "==== \"" $fileName "\" NON_TEST_FILE\n"]

          #
          # NOTE: This file does not actually count towards the total (i.e.
          #       it contains no actual tests).
          #
          incr total -1
        }

1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1318
1319
1320
1321
1322
1323
1324






1325
1326
1327
1328
1329
1330
1331







-
-
-
-
-
-







        #       test failure with the stop-on-failure flag enabled),
        #       break out of the test loop now.
        #
        if {$stop} then {
          break
        }
      } else {
        #
        # NOTE: This entire file has been skipped.  Record that fact in the
        #       test suite log file.
        #
        tputs $channel [appendArgs "==== \"" $fileName "\" SKIPPED\n"]

        #
        # NOTE: This file does not actually count towards the total (i.e.
        #       it is part of the test suite infrastructure).
        #
        incr total -1
      }

1391
1392
1393
1394
1395
1396
1397
1398

1399
1400
1401
1402
1403

1404
1405
1406
1407
1408
1409
1410
1411
1352
1353
1354
1355
1356
1357
1358

1359

1360
1361
1362

1363

1364
1365
1366
1367
1368
1369
1370







-
+
-



-
+
-







    tputs $channel [appendArgs "---- sourced " $count " test " \
        [expr {$count > 1 ? "files" : "file"}] \n]

    #
    # NOTE: Show the files that had failing and/or leaking tests.
    #
    if {[llength $failed] > 0} then {
      tputs $channel [appendArgs "---- files with failing tests: " \
      tputs $channel [appendArgs "---- files with failing tests: " $failed \n]
          [formatList $failed] \n]
    }

    if {[llength $leaked] > 0} then {
      tputs $channel [appendArgs "---- files with leaking tests: " \
      tputs $channel [appendArgs "---- files with leaking tests: " $leaked \n]
          [formatList $leaked] \n]
    }
  }

  proc configureTcltest { constraints imports force } {
    if {[isEagle]} then {
      #
      # HACK: Flag the "test" and "runTest" script library procedures so
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853


1854
1855
1856
1857
1858
1859
1860
1861

















1862
1863
1864
1865
1866
1867
1868
1713
1714
1715
1716
1717
1718
1719






1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731



































































1732
1733
1734
1735
1736
1737
1738

1739
1740
1741







1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765







-
-
-
-
-
-












-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







-
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







          #       type for the native Tcl shell.
          #
          catch {file delete $fileName}
        }
      }
    }

    proc getCommandsForTclShell {} {
      return [testExecTclScript {
        puts -nonewline stdout [info commands]
      }]
    }

    proc getMachineForTclShell {} {
      return [testExecTclScript {
        puts -nonewline stdout $tcl_platform(machine)
      }]
    }

    proc getTkVersion {} {
      return [testExecTclScript {
        puts -nonewline stdout [package require Tk]; exit
      }]
    }

    proc getTestConfiguration {} {
      #
      # NOTE: Determine the effective test configuration and return it.  If
      #       the test configuration cannot be determined, return an empty
      #       string.
      #
      if {[info exists ::test_flags(-configuration)] && \
          [string length $::test_flags(-configuration)] > 0} then {
        #
        # NOTE: The test configuration has been manually overridden via the
        #       test flags; therefore, use it.
        #
        return $::test_flags(-configuration)
      } elseif {[info exists ::test_configuration]} then {
        #
        # NOTE: Use the test configuration.  The default value is "Release",
        #       as set by the test suite prologue; however, this may have
        #       been overridden.
        #
        return $::test_configuration
      } elseif {[info exists ::eagle_platform(configuration)]} then {
        #
        # NOTE: Use the build configuration of Eagle itself.  This value will
        #       always be "Debug" or "Release".
        #
        return $::eagle_platform(configuration)
      } else {
        #
        # NOTE: We are missing the configuration, return nothing.
        #
        return ""
      }
    }

    proc getTestSuffix {} {
      #
      # NOTE: Determine the effective test suffix and return it.  If
      #       the test suffix cannot be determined, return an empty
      #       string.
      #
      if {[info exists ::test_flags(-suffix)] && \
          [string length $::test_flags(-suffix)] > 0} then {
        #
        # NOTE: The test suffix has been manually overridden via the
        #       test flags; therefore, use it.
        #
        return $::test_flags(-suffix)
      } elseif {[info exists ::test_suffix]} then {
        #
        # NOTE: Use the test suffix.  There is no default value for
        #       this variable (i.e. by default, it does not exist).
        #
        return $::test_suffix
      } elseif {[info exists ::eagle_platform(text)]} then {
        #
        # NOTE: Use the build text of Eagle itself.  This value will
        #       typically be "NetFx20" or "NetFx40".
        #
        return $::eagle_platform(text)
      } else {
        #
        # NOTE: We are missing the suffix, return nothing.
        #
        return ""
      }
    }

    proc getGarudaDll {} {
      #
      # NOTE: Get the Garuda DLL of the same platform (i.e. machine type)
      #       as the native Tcl shell.
      #
      if {[info exists ::base_path]} then {
        #
        # NOTE: Get the effective test configuration.
        # NOTE: If the test configuration is available, use it.  Failing that,
        #       use the build configuration of Eagle itself.
        #
        set configuration [getTestConfiguration]

        #
        # NOTE: If there is no effective test configuration available, we
        #       cannot continue.
        #
        if {[string length $configuration] == 0} then {
        if {[info exists ::test_configuration]} then {
          #
          # NOTE: Use the test configuration.  The default value is "Release",
          #       as set by the test suite prologue; however, this may have
          #       been overridden.
          #
          set configuration $::test_configuration
        } elseif {[info exists ::eagle_platform(configuration)]} then {
          #
          # NOTE: Use the build configuration of Eagle itself.  This value will
          #       always be "Debug" or "Release".
          #
          set configuration $::eagle_platform(configuration)
        } else {
          #
          # NOTE: We are missing the configuration, return nothing.
          #
          return ""
        }

        #
        # NOTE: Build the full path and file name of the Garuda DLL, using
        #       the Eagle base path.  Currently, this will only work
        #       correctly if the test suite is being run from inside the
2070
2071
2072
2073
2074
2075
2076
2077
2078


2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
1967
1968
1969
1970
1971
1972
1973


1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988







-
-
+
+













    exportAndImportPackageCommands [namespace current] [list addConstraint \
        calculateRelativePerformance haveConstraint haveOrAddConstraint \
        processTestArguments getTemporaryPath getTestLog getTestLogId getFiles \
        getConstraints getTestFiles getTestRunId execTestShell runTestPrologue \
        runTestEpilogue runTest runAllTests fixConstraints sourceIfValid \
        isExitOnComplete getPassPercentage getSkipPercentage testExec tlog \
        returnInfoScript tputs formatDecimal formatList configureTcltest \
        calculateBogoCops removeConstraint machineToPlatform tsource testShim \
        getTestConfiguration getTestSuffix getTclShellFileName] false false
        calculateBogoCops removeConstraint machineToPlatform tsource testShim] \
        false false

    ###########################################################################
    ############################## END Tcl ONLY ###############################
    ###########################################################################
  }

  #
  # NOTE: Provide the Eagle test package to the interpreter.
  #
  package provide Eagle.Test \
    [expr {[isEagle] ? [info engine PatchLevel] : "1.0"}]
}

Changes to Externals/Eagle/lib/Eagle1.0/vendor.eagle.
40
41
42
43
44
45
46
47
48
49


50
51
52
53
54
55
56
57
58
40
41
42
43
44
45
46



47
48


49
50
51
52
53
54
55







-
-
-
+
+
-
-







        if {![uplevel 1 [list info exists $varName]]} then {
          continue
        }

        incr result

        if {!$quiet} then {
          catch {
            tqputs $channel [appendArgs \
                "---- found vendor-specific test override \"" $varName \
          tqputs $channel [appendArgs \
              "---- found vendor-specific test override \"" $varName "\".\n"]
                "\" with value \"" [uplevel 1 [list set $varName]] \"\n]
          }
        }
      }

      #
      # NOTE: Keep track of the list of test override variables, for later
      #       use by the test suite.  This needs to be done after the loop
      #       above because the variable used to keep track is listed with
108
109
110
111
112
113
114
115
116
117
118



119
120
121
122
123
124
125
126
105
106
107
108
109
110
111




112
113
114

115
116
117
118
119
120
121







-
-
-
-
+
+
+
-







          #
          if {![info exists ::env(EAGLELIBPATH)] || \
              [lsearch -exact $::env(EAGLELIBPATH) $dir2] == -1} then {
            #
            # NOTE: If we have NOT been instructed to be quiet, report now.
            #
            if {!$quiet} then {
              catch {
                tqputs $channel [appendArgs \
                    "---- found vendor-specific test package directory \"" \
                    $dir2 "\", adding...\n"]
              tqputs $channel [appendArgs \
                  "---- found vendor-specific test package directory \"" \
                  $dir2 "\", adding...\n"]
              }
            }

            #
            # NOTE: Append the directory to the necessary environment variable
            #       so that it will get picked up when Eagle actually rebuilds
            #       the auto-path list (below).
            #
145
146
147
148
149
150
151
152
153
154


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


175
176
177
178
179
180
181
182
183
184
185
186
187
188
189


190
191
192
193
194
195
196
140
141
142
143
144
145
146



147
148

149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164



165
166

167
168
169
170
171
172
173
174
175
176
177
178


179
180
181
182
183
184
185
186
187







-
-
-
+
+
-
















-
-
-
+
+
-












-
-
+
+







        set dir [file dirname $dir]
      }

      #
      # NOTE: If we have NOT been instructed to be quiet, report now.
      #
      if {!$quiet} then {
        catch {
          tqputs $channel \
              "---- could not find vendor-specific test package directory\n"
        tqputs $channel \
            "---- could not find vendor-specific test package directory.\n"
        }
      }

      #
      # NOTE: Directory not found, return failure.
      #
      return false
    }

    proc setupInterpreterTestPath { channel dir quiet } {
      set testPath [object invoke -flags +NonPublic Interpreter.GetActive \
          TestPath]

      if {$dir ne $testPath} then {
        object invoke -flags +NonPublic Interpreter.GetActive TestPath $dir

        if {!$quiet} then {
          catch {
            tqputs $channel [appendArgs \
                "---- set interpreter test path to \"" $dir \"\n]
          tqputs $channel [appendArgs \
              "---- set interpreter test path to \"" $dir \".\n]
          }
        }
      }
    }

    #
    # NOTE: Check for any overridden settings that may have been specified via
    #       the command line, etc.
    #
    checkForTestOverrides stdout [expr {[info exists test_overrides] ? \
        $test_overrides : [list binary_directory build_base_directory \
        build_directory common_directory connection_flags database_directory \
        datetime_format scratch_directory temporary_directory \
        test_configuration test_constraints test_overrides test_year \
        test_year_clr_v2 test_year_clr_v4 vendor_directory]}] false
        test_configuration test_overrides test_year test_year_clr_v2 \
        test_year_clr_v4 vendor_directory]}] false

    #
    # NOTE: This variable will contain the name of the directory containing the
    #       vendor-specific testing infrastructure.  If the variable does not
    #       already exist, create it; otherwise, it has been overridden and the
    #       existing value should be left intact.
    #
Changes to Externals/Eagle/lib/Test1.0/constraints.eagle.
24
25
26
27
28
29
30
31

32
33
34
35
36
37
38
24
25
26
27
28
29
30

31
32
33
34
35
36
37
38







-
+







    tputs $channel "---- checking for platform... "

    if {[info exists ::tcl_platform(platform)]} then {
      addConstraint $::tcl_platform(platform)

      tputs $channel [appendArgs $::tcl_platform(platform) \n]
    } else {
      tputs $channel unknown\n
      tputs $channel [appendArgs unknown \n]
    }

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

    if {![isEagle]} then {
      #
      # BUGFIX: We do not normally want to skip any Mono bugs in native Tcl.
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
57
58
59
60
61
62
63














































64
65
66
67
68
69
70







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







        foreach constraint $constraints {
          addConstraint $constraint
        }
      }
    }
  }

  proc checkForScriptLibrary { channel } {
    tputs $channel "---- checking for script library... "

    #
    # NOTE: See if the variable containing the script library location
    #       exists.
    #
    if {[info exists ::tcl_library] && \
        [string length $::tcl_library] > 0} then {
      #
      # NOTE: Now see if the script library is external or embedded.
      #
      if {[file isdirectory $::tcl_library]} then {
        #
        # NOTE: Yes, it appears to be a directory name, which should
        #       mean that the necessary files are physically contained
        #       within it.
        #
        addConstraint tcl_library_external

        tputs $channel "yes (external)\n"

        #
        # NOTE: We are done here, return now.
        #
        return
      } elseif {[file isfile $::tcl_library]} then {
        #
        # NOTE: Yes, it appears to be a file name, which should mean
        #       that the necessary files are physically embedded within
        #       it.
        #
        addConstraint tcl_library_embedded

        tputs $channel "yes (embedded)\n"

        #
        # NOTE: We are done here, return now.
        #
        return
      }
    }

    tputs $channel no\n
  }

  proc checkForVariable { channel name {notEmpty true} {constraint ""} } {
    tputs $channel [appendArgs "---- checking for variable \"" $name \
        "\"... "]

    #
    # NOTE: First, normalize the variable name to be in the global scope.
    #
594
595
596
597
598
599
600
601

602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620

621
622
623
624
625
626
627
628
629
548
549
550
551
552
553
554

555
556
557
558
559
560
561
562












563


564
565
566
567
568
569
570







-
+







-
-
-
-
-
-
-
-
-
-
-
-
+
-
-







      tputs $channel yes\n
    } else {
      tputs $channel no\n
    }
  }

  proc checkForTestConfiguration { channel } {
    tputs $channel "---- checking for test configuration... "
    tputs $channel [appendArgs "---- checking for test configuration... "]

    if {[info exists ::test_configuration] && \
        [string length $::test_configuration] > 0} then {
      addConstraint [appendArgs configuration. $::test_configuration]

      tputs $channel [appendArgs $::test_configuration \n]
    } else {
      tputs $channel unknown\n
    }
  }

  proc checkForTestSuffix { channel } {
    tputs $channel "---- checking for test suffix... "

    if {[info exists ::test_suffix] && \
        [string length $::test_suffix] > 0} then {
      addConstraint [appendArgs suffix. $::test_suffix]

      tputs $channel [appendArgs $::test_suffix \n]
      tputs $channel [appendArgs unknown \n]
    } else {
      tputs $channel unknown\n
    }
  }

  proc checkForFile { channel name {constraint ""} } {
    tputs $channel [appendArgs "---- checking for file \"" $name \
        "\"... "]

831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
772
773
774
775
776
777
778

















779
780
781
782
783
784
785







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








      tputs $channel yes\n
    } else {
      tputs $channel no\n
    }
  }

  proc checkForTip405 { channel } {
    tputs $channel "---- checking for TIP #405... "

    #
    # NOTE: Does the interpreter have TIP #405 (i.e. [lmap])?
    #
    catch {lmap} error

    if {$error ne "invalid command name \"lmap\""} then {
      addConstraint tip405

      tputs $channel yes\n
    } else {
      tputs $channel no\n
    }
  }

  proc checkForTiming {
          channel threshold {constraint ""} {tries 1} {delay 1000}
          {asynchronous false} } {
    tputs $channel [appendArgs \
        "---- checking for precision timing (threshold of " $threshold \
        " milliseconds, delay of " $delay " milliseconds)... "]

940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
864
865
866
867
868
869
870















871
872
873
874
875
876
877
878
879
880
881
882
883
884
885































886
887
888
889
890
891
892







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








      tputs $channel yes\n
    } else {
      tputs $channel no\n
    }
  }

  proc checkForStackIntensive { channel } {
    tputs $channel "---- checking for stack intensive testing... "

    #
    # NOTE: Are we allowed to do stack intensive testing?
    #
    if {![info exists ::no(stackIntensive)]} then {
      addConstraint stackIntensive

      tputs $channel yes\n
    } else {
      tputs $channel no\n
    }
  }

  proc checkForInteractive { channel } {
    tputs $channel "---- checking for interactive user... "

    #
    # NOTE: Is there an interactive user?
    #
    if {[info exists ::tcl_interactive] && $::tcl_interactive} then {
      addConstraint interactive

      tputs $channel yes\n
    } else {
      tputs $channel no\n
    }
  }

  proc checkForInteractiveCommand { channel name } {
    tputs $channel [appendArgs "---- checking for interactive command \"" \
        $name "\"... "]

    #
    # NOTE: Currently, only Eagle has "interactive commands".
    #
    if {[isEagle]} then {
      #
      # NOTE: Attempt to query the interactive command names from Eagle.
      #
      if {[catch {object invoke Utility GetInteractiveCommandNames $name \
              false} names] == 0 && \
          [llength $names] > 0} then {
        #
        # NOTE: Yes, it appears that it is available.
        #
        addConstraint [appendArgs interactiveCommand. $name]

        tputs $channel yes\n

        #
        # NOTE: We are done here, return now.
        #
        return
      }
    }

    tputs $channel no\n
  }

  proc checkForUserInteraction { channel } {
    tputs $channel "---- checking for user interaction... "

    #
    # HACK: For now, do the exact same check as checkForInteractive; however,
    #       this is still useful as a separate constraint because it can be
    #       individually disabled in "prologue.eagle".
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1008
1009
1010
1011
1012
1013
1014
























































































1015
1016
1017
1018
1019
1020
1021







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








        tputs $channel trusted\n
      } else {
        tputs $channel untrusted\n
      }
    }

    proc checkForManagedDebuggingAssistants { channel } {
      set fileName [file normalize [appendArgs [info nameofexecutable] \
          .mda.config]]

      tputs $channel [appendArgs \
          "---- checking for managed debugging assistants enabled via \"" \
          $fileName "\"... "]

      if {[file exists $fileName]} then {
        #
        # NOTE: Since the System.Xml assembly may not be loaded, wrap the
        #       detection in a [catch] block.
        #
        if {[catch {
          #
          # NOTE: Create and load an XML document based on the data from the
          #       MDA configuration file associated with the executable that
          #       started this process.
          #
          set document [object create -alias System.Xml.XmlDocument]
          $document LoadXml [readFile $fileName]

          #
          # NOTE: Setup the XML namespace manager for use when using XPath
          #       to query the XML document.
          #
          set nameTable [$document NameTable]

          set namespaceManager [object create \
              -alias System.Xml.XmlNamespaceManager $nameTable]

          $namespaceManager AddNamespace mda \
              http://schemas.microsoft.com/CLR/2004/10/mda

          #
          # NOTE: Select all nodes underneath the location where they should
          #       reside in the MDA configuration XML document.
          #
          set nodes [$document SelectNodes \
              /mda:mdaConfig/mda:assistants/* $namespaceManager]

          #
          # NOTE: Populate the local result variable with the names of
          #       all the XML nodes found.
          #
          set names [object lmap -alias node $nodes {
            $node Name
          }]
        }] == 0} then {
          #
          # NOTE: Ok, the XML configuration file was loaded and parsed
          #       correctly, see if any managed debugging assistants were
          #       found enabled within it.
          #
          if {[info exists names] && [llength $names] > 0} then {
            #
            # NOTE: Add a test constraint for each managed debugging
            #       assistant that appears to be enabled.
            #
            addConstraint mda

            foreach name $names {
              addConstraint [appendArgs mda. $name]
            }

            #
            # NOTE: Save the list of managed debugging assistants for
            #       later use by the test suite.
            #
            set ::test_mdas $names

            #
            # NOTE: Yes, it appears that at least one managed debugging
            #       assistant is enabled.
            #
            tputs $channel [appendArgs "yes (" $names ")\n"]

            #
            # NOTE: We are done here, return now.
            #
            return
          }
        }
      }

      tputs $channel no\n
    }

    proc checkForStrongName { channel } {
      tputs $channel "---- checking for strong name... "

      if {[catch {object invoke Interpreter.GetActive GetStrongName} \
              strongName] == 0 && \
          [string length $strongName] > 0} then {
        #
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384




2385
2386

2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2164
2165
2166
2167
2168
2169
2170




2171
2172
2173
2174


2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188







-
-
-
-
+
+
+
+
-
-
+













    # NOTE: We need several of our test constraint related commands in the
    #       global namespace.
    #
    exportAndImportPackageCommands [namespace current] [list checkForPlatform \
        checkForEagle checkForGaruda checkForShell checkForDebug checkForTk \
        checkForVersion checkForCommand checkForFile checkForNativeCode \
        checkForTip127 checkForTip194 checkForTip241 checkForTip285 \
        checkForTip405 checkForPerformance checkForTiming checkForInteractive \
        checkForSymbols checkForLogFile checkForNetwork checkForCompileOption \
        checkForInteractiveCommand checkForWindowsCommandProcessor \
        checkForUserInteraction checkForTclOptions checkForTestConfiguration \
        checkForPerformance checkForTiming checkForInteractive checkForSymbols \
        checkForLogFile checkForNetwork checkForCompileOption \
        checkForWindowsCommandProcessor checkForUserInteraction \
        checkForTclOptions checkForTestConfiguration checkForVariable \
        checkForTestSuffix checkForVariable checkForScriptLibrary \
        checkForStackIntensive checkForFossil] false false
        checkForFossil] false false

    ###########################################################################
    ############################## END Tcl ONLY ###############################
    ###########################################################################
  }

  #
  # NOTE: Provide the Eagle test constraints package to the interpreter.
  #
  package provide Eagle.Test.Constraints \
    [expr {[isEagle] ? [info engine PatchLevel] : "1.0"}]
}

Changes to Externals/Eagle/lib/Test1.0/prologue.eagle.
18
19
20
21
22
23
24
25
26
27



28
29
30
31
32
33
34
18
19
20
21
22
23
24



25
26
27
28
29
30
31
32
33
34







-
-
-
+
+
+







  if {[info level] > 0} then {
    error "cannot run, current level is not global"
  }

  #
  # NOTE: Make sure all the variables used by this prologue are unset.
  #
  unset -nocomplain pkg_dir pattern exec dummy directory name value expr \
      publicKeyToken encoding memory stack drive server database timeout \
      user password percent checkout timeStamp
  unset -nocomplain pkg_dir pattern exec dummy directory name value \
      expr publicKeyToken encoding memory stack drive server database \
      timeout user password percent checkout timeStamp

  #
  # NOTE: Set the location of the test suite, if necessary.
  #
  if {![info exists test_path]} then {
    set test_path [file normalize [file dirname [info script]]]
  }
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
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







-


















-
+







  set test_flags(-constraints) [list]; # default to no manual constraints.
  set test_flags(-logFile) ""; # default to using standard log file naming.
  set test_flags(-threshold) ""; # default to requiring all tests to pass.
  set test_flags(-stopOnFailure) ""; # default to continue on failure.
  set test_flags(-exitOnComplete) ""; # default to not exit after complete.
  set test_flags(-preTest) ""; # default to not evaluating anything.
  set test_flags(-postTest) ""; # default to not evaluating anything.
  set test_flags(-tclsh) ""; # Tcl shell, default to empty.

  #
  # NOTE: Check for and process any command line arguments.
  #
  if {[info exists argv]} then {
    eval processTestArguments test_flags $argv

    if {[info exists test_flags(-no)] && \
        [string length $test_flags(-no)] > 0} then {
      #
      # NOTE: Set the test run restrictions based on the provided command line
      #       argument value (which is assumed to be a "dictionary-style" list
      #       containing name/value pairs to add to the global "no" array).
      #
      foreach {name value} $test_flags(-no) {
        set no($name) $value
      }

      unset -nocomplain name value
      unset name value
    }

    if {[info exists test_flags(-logFile)] && \
        [string length $test_flags(-logFile)] > 0} then {
      #
      # NOTE: Set the log file name to the one provided by the command line.
      #
332
333
334
335
336
337
338
339
340


341
342
343
344
345
346
347
348
349
350
351
352
353
354
355

356
357
358
359
360
361
362
363
364
365
366
367
368
331
332
333
334
335
336
337


338
339
340
341






342






343






344
345
346
347
348
349
350







-
-
+
+


-
-
-
-
-
-

-
-
-
-
-
-
+
-
-
-
-
-
-







  #       necessary.
  #
  if {![info exists test_configuration]} then {
    set test_configuration [getPlatformInfo configuration Release]
  }

  #
  # NOTE: Set the Tcl shell executable to use for those specialized tests that
  #       may require it, if necessary.
  # NOTE: Set the Tcl shell executable to use for those specialized
  #       tests that may require it, if necessary.
  #
  if {![info exists test_tclsh]} then {
    #
    # NOTE: When running in Eagle, more complex logic is required to determine
    #       the Tcl shell to use for the various tests that require it.  Also,
    #       this same logic is used with Tcl when it is not running from an
    #       instance of the Tcl shell executable.
    #
    if {[isEagle] || ![string match tclsh* $bin_file]} then {
      if {[info exists test_flags(-tclsh)] && \
          [string length $test_flags(-tclsh)] > 0} then {
        #
        # NOTE: Use the Tcl shell specified via the command line.
        #
        set test_tclsh $test_flags(-tclsh)
      set test_tclsh tclsh
      } else {
        #
        # NOTE: Check for a Tcl shell specified via the environment.
        #
        set test_tclsh [getTclShellFileName]
      }
    } else {
      set test_tclsh $bin_file
    }
  }

  #
  # NOTE: Has automatic log file naming been disabled?
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
427
428
429
430
431
432
433




434
435
436
437
438
439
440







-
-
-
-







  tputs $test_channel [appendArgs "---- test channel: " \
      $test_channel \n]

  tputs $test_channel [appendArgs "---- test configuration: " \
      [expr {[info exists test_configuration] ? \
          $test_configuration : "<none>"}] \n]

  tputs $test_channel [appendArgs "---- test suffix: " \
      [expr {[info exists test_suffix] ? \
          $test_suffix : "<none>"}] \n]

  if {[isEagle]} then {
    catch {info engine PublicKeyToken} publicKeyToken

    if {[string length $publicKeyToken] == 0} then {
      #
      # NOTE: The Eagle core library is not strong name signed.  This is not an
      #       error, per se; however, it may cause some tests to fail and it
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
855
856
857
858
859
860
861











862
863
864
865
866
867
868







-
-
-
-
-
-
-
-
-
-
-







        #
        # NOTE: For tests "debug-1.1", "debug-2.1", "debug-3.1" and
        #       "debug-4.1".
        #
        checkForCompileOption $test_channel DEBUGGER
      }

      #
      # NOTE: Has application domain management support been enabled (at
      #       compile-time)?
      #
      if {![info exists no(compileAppDomains)]} then {
        #
        # NOTE: For test "interp-1.27".
        #
        checkForCompileOption $test_channel APPDOMAINS
      }

      #
      # NOTE: Has isolated interpreter support been enabled (at compile-time)?
      #
      if {![info exists no(compileIsolatedInterpreters)]} then {
        #
        # NOTE: For test "xaml-1.2".
        #
1182
1183
1184
1185
1186
1187
1188
1189

1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1149
1150
1151
1152
1153
1154
1155

1156
1157
1158
1159






1160
1161
1162
1163
1164
1165
1166







-
+



-
-
-
-
-
-







        checkForObjectMember $test_channel Eagle._Tests.Default \
            *TestAddNamedFunction*

        checkForObjectMember $test_channel Eagle._Tests.Default \
            *TestRemoveNamedFunction*

        #
        # NOTE: For test "interp-1.19".
        # NOTE: For test "interp-1.18".
        #
        checkForObjectMember $test_channel Eagle._Tests.Default \
            *TestAddNamedFunction2*

        #
        # NOTE: For tests "function-5.*".
        #
        checkForObjectMember $test_channel Eagle._Tests.Default \
            *TestAddNamedFunction3*
      }

      #
      # NOTE: Has write-box testing support been disabled?
      #
      if {![info exists no(testWriteBox)]} then {
        #
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1506
1507
1508
1509
1510
1511
1512








1513
1514
1515
1516
1517
1518
1519







-
-
-
-
-
-
-
-







    #
    # NOTE: Has managed debugger testing support been disabled?
    #
    if {![info exists no(managedDebugger)]} then {
      checkForManagedDebugger $test_channel
    }

    #
    # NOTE: Has managed debugging assistants testing support been
    #       disabled?
    #
    if {![info exists no(managedDebuggingAssistants)]} then {
      checkForManagedDebuggingAssistants $test_channel
    }

    #
    # NOTE: Has script debugger testing support been disabled?
    #
    if {![info exists no(scriptDebugger)]} then {
      #
      # NOTE: For tests "debug-1.1", "debug-2.1", "debug-3.1", and
      #       "debug-4.1".
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1622
1623
1624
1625
1626
1627
1628







1629
1630
1631
1632
1633
1634
1635







-
-
-
-
-
-
-







  #
  # NOTE: Has checking for the test configuration been disabled?
  #
  if {![info exists no(testConfiguration)]} then {
    checkForTestConfiguration $test_channel
  }

  #
  # NOTE: Has checking for the test suffix been disabled?
  #
  if {![info exists no(testSuffix)]} then {
    checkForTestSuffix $test_channel
  }

  #
  # NOTE: Has checking for the extra files needed by various tests been
  #       disabled?
  #
  if {![info exists no(checkForFile)]} then {
    #
    # NOTE: For test "package-1.0".
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1740
1741
1742
1743
1744
1745
1746







1747
1748
1749
1750
1751
1752
1753







-
-
-
-
-
-
-







    #
    # NOTE: For tests "excel-2.*".
    #
    if {![info exists no(test.xls)]} then {
      checkForFile $test_channel [file join $test_path test.xls]
    }

    #
    # NOTE: For test "proc-1.9".
    #
    if {![info exists no(testProcs.tcl)]} then {
      checkForFile $test_channel [file join $test_path testProcs.tcl]
    }

    #
    # NOTE: For test "interp-1.10".
    #
    if {![info exists no(settings.xml)]} then {
      checkForFile $test_channel [file join $test_path settings.xml]
    }

1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1833
1834
1835
1836
1837
1838
1839




1840
1841
1842
1843




1844
1845
1846
1847
1848
1849
1850







-
-
-
-




-
-
-
-







  # NOTE: Check the core test constraints unless they have been
  #       explicitly disabled.
  #
  if {![info exists no(platform)]} then {
    checkForPlatform $test_channel
  }

  if {![info exists no(scriptLibrary)]} then {
    checkForScriptLibrary $test_channel
  }

  if {![info exists no(tclOptions)]} then {
    checkForTclOptions $test_channel
  }

  if {![info exists no(stackIntensive)]} then {
    checkForStackIntensive $test_channel
  }

  if {![info exists no(windowsCommandProcessor)]} then {
    checkForWindowsCommandProcessor $test_channel cmd.exe
  }

  if {![info exists no(fossil)]} then {
    checkForFossil $test_channel
  }
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
1938
1939
1940
1941
1942
1943
1944




1945
1946
1947
1948
1949
1950
1951







-
-
-
-







    checkForTip241 $test_channel
  }

  if {![info exists no(tip285)]} then {
    checkForTip285 $test_channel
  }

  if {![info exists no(tip405)]} then {
    checkForTip405 $test_channel
  }

  #
  # NOTE: Has performance testing been disabled?
  #
  if {![info exists no(performance)]} then {
    checkForPerformance $test_channel
  }

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
2067
1966
1967
1968
1969
1970
1971
1972















1973
1974
1975
1976
1977
1978
1979







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







  #
  # NOTE: Has interactive testing been disabled?
  #
  if {![info exists no(interactive)]} then {
    checkForInteractive $test_channel
  }

  #
  # NOTE: Has interactive command testing been disabled?
  #
  if {![info exists no(interactiveCommand)]} then {
    #
    # NOTE: For test "debug-1.8".
    #
    checkForInteractiveCommand $test_channel go

    #
    # NOTE: For test "debug-1.9".
    #
    checkForInteractiveCommand $test_channel done
  }

  if {![info exists no(userInteraction)]} then {
    checkForUserInteraction $test_channel
  }

  #
  # NOTE: Check for network connectivity to our test host (i.e.
  #       the Eagle distribution site).
Changes to Membership/Properties/AssemblyInfo.cs.
29
30
31
32
33
34
35
36
37


29
30
31
32
33
34
35


36
37







-
-
+
+
//      Major Version
//      Minor Version 
//      Build Number
//      Revision
//
// You can specify all the values or you can default the Revision and Build Numbers 
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.84.0")]
[assembly: AssemblyFileVersion("1.0.84.0")]
[assembly: AssemblyVersion("1.0.83.0")]
[assembly: AssemblyFileVersion("1.0.83.0")]
Deleted SQLite.Beta.nuspec.
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







































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
<?xml version="1.0" encoding="utf-8"?>
<!--
 *
 * SQLite.Beta.nuspec -
 *
 * Written by Joe Mistachkin.
 * Released to the public domain, use at your own risk!
 *
-->
<package>
  <metadata>
    <id>System.Data.SQLite.Beta</id>
    <title>System.Data.SQLite (x86/x64) Beta</title>
    <version>1.0.84.0</version>
    <authors>SQLite Development Team</authors>
    <description>The official SQLite database engine for both x86 and x64 along with the ADO.NET provider.</description>
    <language>en-US</language>
    <projectUrl>http://system.data.sqlite.org/</projectUrl>
    <iconUrl>http://system.data.sqlite.org/images/sqlite32.png</iconUrl>
    <licenseUrl>http://www.sqlite.org/copyright.html</licenseUrl>
    <tags>sqlite database ado.net provider interop</tags>
    <copyright>Public Domain</copyright>
  </metadata>
  <files>
    <file src="bin\2008\Release\bin\System.Data.SQLite.dll" target="lib\net20" />
    <file src="bin\2010\Release\bin\System.Data.SQLite.dll" target="lib\net40" />
    <file src="bin\2012\Release\bin\System.Data.SQLite.dll" target="lib\net45" />
    <file src="bin\2008\Release\bin\System.Data.SQLite.Linq.dll" target="lib\net20" />
    <file src="bin\2010\Release\bin\System.Data.SQLite.Linq.dll" target="lib\net40" />
    <file src="bin\2012\Release\bin\System.Data.SQLite.Linq.dll" target="lib\net45" />
    <file src="bin\2008\Win32\ReleaseNativeOnlyStatic\SQLite.Interop.dll" target="content\net20\x86" />
    <file src="bin\2008\x64\ReleaseNativeOnlyStatic\SQLite.Interop.dll" target="content\net20\x64" />
    <file src="bin\2010\Win32\ReleaseNativeOnlyStatic\SQLite.Interop.dll" target="content\net40\x86" />
    <file src="bin\2010\x64\ReleaseNativeOnlyStatic\SQLite.Interop.dll" target="content\net40\x64" />
    <file src="bin\2012\Win32\ReleaseNativeOnlyStatic\SQLite.Interop.dll" target="content\net45\x86" />
    <file src="bin\2012\x64\ReleaseNativeOnlyStatic\SQLite.Interop.dll" target="content\net45\x64" />
    <file src="install.ps1" target="tools\install.ps1" />
  </files>
</package>
Changes to SQLite.Designer/AssemblyInfo.cs.
39
40
41
42
43
44
45
46
47


39
40
41
42
43
44
45


46
47







-
-
+
+
//      Major Version
//      Minor Version 
//      Build Number
//      Revision
//
// You can specify all the values or you can default the Revision and Build Numbers 
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.84.0")]
[assembly: AssemblyFileVersion("1.0.84.0")]
[assembly: AssemblyVersion("1.0.83.0")]
[assembly: AssemblyFileVersion("1.0.83.0")]
Changes to SQLite.Designer/source.extension.vsixmanifest.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







<?xml version="1.0" encoding="utf-8"?>
<Vsix Version="1.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2010">
  <Identifier Id="67b5f3a9-cde1-430f-a12b-af95bb064851">
    <Name>System.Data.SQLite Designer</Name>
    <Author>http://system.data.sqlite.org/</Author>
    <Version>1.0.84.0</Version>
    <Version>1.0.83.0</Version>
    <Description>ADO.NET Data Designer for SQLite</Description>
    <Locale>1033</Locale>
    <InstalledByMsi>false</InstalledByMsi>
    <SupportedProducts>
      <VisualStudio Version="10.0">
        <Edition>Pro</Edition>
      </VisualStudio>
Changes to SQLite.Interop/SQLite.Interop.2010.vcxproj.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10




11
12
13
14
15
16
17










-
-
-
-







<?xml version="1.0" encoding="utf-8"?>
<!--
 *
 * SQLite.Interop.2010.vcxproj -
 *
 * Written by Joe Mistachkin.
 * Released to the public domain, use at your own risk!
 *
-->
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
  <PropertyGroup>
    <SQLiteNetDir>$(MSBuildProjectDirectory)\..</SQLiteNetDir>
  </PropertyGroup>
  <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets" />
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="DebugNativeOnly|x64">
      <Configuration>DebugNativeOnly</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|Win32">
      <Configuration>Debug</Configuration>
Changes to SQLite.Interop/SQLite.Interop.2012.vcxproj.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10




11
12
13
14
15
16
17










-
-
-
-







<?xml version="1.0" encoding="utf-8"?>
<!--
 *
 * SQLite.Interop.2012.vcxproj -
 *
 * Written by Joe Mistachkin.
 * Released to the public domain, use at your own risk!
 *
-->
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
  <PropertyGroup>
    <SQLiteNetDir>$(MSBuildProjectDirectory)\..</SQLiteNetDir>
  </PropertyGroup>
  <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets" />
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="DebugNativeOnly|x64">
      <Configuration>DebugNativeOnly</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|Win32">
      <Configuration>Debug</Configuration>
Changes to SQLite.Interop/SQLite.Interop.Static.2010.vcxproj.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10




11
12
13
14
15
16
17










-
-
-
-







<?xml version="1.0" encoding="utf-8"?>
<!--
 *
 * SQLite.Interop.Static.2010.vcxproj -
 *
 * Written by Joe Mistachkin.
 * Released to the public domain, use at your own risk!
 *
-->
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
  <PropertyGroup>
    <SQLiteNetDir>$(MSBuildProjectDirectory)\..</SQLiteNetDir>
  </PropertyGroup>
  <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets" />
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="DebugNativeOnly|x64">
      <Configuration>DebugNativeOnly</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|Win32">
      <Configuration>Debug</Configuration>
Changes to SQLite.Interop/SQLite.Interop.Static.2012.vcxproj.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10




11
12
13
14
15
16
17










-
-
-
-







<?xml version="1.0" encoding="utf-8"?>
<!--
 *
 * SQLite.Interop.Static.2012.vcxproj -
 *
 * Written by Joe Mistachkin.
 * Released to the public domain, use at your own risk!
 *
-->
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
  <PropertyGroup>
    <SQLiteNetDir>$(MSBuildProjectDirectory)\..</SQLiteNetDir>
  </PropertyGroup>
  <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets" />
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="DebugNativeOnly|x64">
      <Configuration>DebugNativeOnly</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|Win32">
      <Configuration>Debug</Configuration>
Changes to SQLite.Interop/props/SQLite.Interop.2005.vsprops.
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
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







-
+









-
+




-
+




-
+







	<UserMacro
		Name="ConfigurationYear"
		Value="2005"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_BUILD_NUMBER"
		Value="084"
		Value="083"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_LINKER_VERSION"
		Value="1.0"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_MANIFEST_VERSION"
		Value="1.0.84.0"
		Value="1.0.83.0"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_RC_VERSION"
		Value="1,0,84,0"
		Value="1,0,83,0"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_DEBUG_DEFINES"
		Value="INTEROP_DEBUG=0x31F;INTEROP_LOG=1;INTEROP_TEST_EXTENSION=1"
		Value="INTEROP_DEBUG=0x307;INTEROP_TEST_EXTENSION=1"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_EXTRA_DEFINES"
		Value="INTEROP_EXTENSION_FUNCTIONS=1;INTEROP_CODEC=1"
		PerformEnvironmentSet="true"
	/>
Changes to SQLite.Interop/props/SQLite.Interop.2008.vsprops.
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
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







-
+









-
+




-
+




-
+







	<UserMacro
		Name="ConfigurationYear"
		Value="2008"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_BUILD_NUMBER"
		Value="084"
		Value="083"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_LINKER_VERSION"
		Value="1.0"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_MANIFEST_VERSION"
		Value="1.0.84.0"
		Value="1.0.83.0"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_RC_VERSION"
		Value="1,0,84,0"
		Value="1,0,83,0"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_DEBUG_DEFINES"
		Value="INTEROP_DEBUG=0x31F;INTEROP_LOG=1;INTEROP_TEST_EXTENSION=1"
		Value="INTEROP_DEBUG=0x307;INTEROP_TEST_EXTENSION=1"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_EXTRA_DEFINES"
		Value="INTEROP_EXTENSION_FUNCTIONS=1;INTEROP_CODEC=1"
		PerformEnvironmentSet="true"
	/>
Changes to SQLite.Interop/props/SQLite.Interop.2010.props.
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17



18
19
20
21
22
23
24
1
2
3
4
5
6
7
8
9
10
11
12

13
14



15
16
17
18
19
20
21
22
23
24












-
+

-
-
-
+
+
+







<?xml version="1.0" encoding="utf-8"?>
<!--
 *
 * SQLite.Interop.2010.props -
 *
 * Written by Joe Mistachkin.
 * Released to the public domain, use at your own risk!
 *
-->
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
  <PropertyGroup Label="UserMacros">
    <ConfigurationYear>2010</ConfigurationYear>
    <INTEROP_BUILD_NUMBER>084</INTEROP_BUILD_NUMBER>
    <INTEROP_BUILD_NUMBER>083</INTEROP_BUILD_NUMBER>
    <INTEROP_LINKER_VERSION>1.0</INTEROP_LINKER_VERSION>
    <INTEROP_MANIFEST_VERSION>1.0.84.0</INTEROP_MANIFEST_VERSION>
    <INTEROP_RC_VERSION>1,0,84,0</INTEROP_RC_VERSION>
    <INTEROP_DEBUG_DEFINES>INTEROP_DEBUG=0x31F;INTEROP_LOG=1;INTEROP_TEST_EXTENSION=1</INTEROP_DEBUG_DEFINES>
    <INTEROP_MANIFEST_VERSION>1.0.83.0</INTEROP_MANIFEST_VERSION>
    <INTEROP_RC_VERSION>1,0,83,0</INTEROP_RC_VERSION>
    <INTEROP_DEBUG_DEFINES>INTEROP_DEBUG=0x307;INTEROP_TEST_EXTENSION=1</INTEROP_DEBUG_DEFINES>
    <INTEROP_EXTRA_DEFINES>INTEROP_EXTENSION_FUNCTIONS=1;INTEROP_CODEC=1</INTEROP_EXTRA_DEFINES>
    <INTEROP_ASSEMBLY_RESOURCES>/ASSEMBLYRESOURCE:..\System.Data.SQLite\SQLiteCommand.bmp,System.Data.SQLite.SQLiteCommand.bmp /ASSEMBLYRESOURCE:..\System.Data.SQLite\SQLiteConnection.bmp,System.Data.SQLite.SQLiteConnection.bmp /ASSEMBLYRESOURCE:..\System.Data.SQLite\SQLiteDataAdapter.bmp,System.Data.SQLite.SQLiteDataAdapter.bmp</INTEROP_ASSEMBLY_RESOURCES>
    <INTEROP_KEY_FILE>$(ProjectDir)..\System.Data.SQLite\System.Data.SQLite.snk</INTEROP_KEY_FILE>
    <INTEROP_NATIVE_NAME>SQLite.Interop</INTEROP_NATIVE_NAME>
    <INTEROP_MIXED_NAME>System.Data.SQLite</INTEROP_MIXED_NAME>
  </PropertyGroup>
  <ItemGroup>
Changes to SQLite.Interop/props/SQLite.Interop.2012.props.
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17



18
19
20
21
22
23
24
1
2
3
4
5
6
7
8
9
10
11
12

13
14



15
16
17
18
19
20
21
22
23
24












-
+

-
-
-
+
+
+







<?xml version="1.0" encoding="utf-8"?>
<!--
 *
 * SQLite.Interop.2012.props -
 *
 * Written by Joe Mistachkin.
 * Released to the public domain, use at your own risk!
 *
-->
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
  <PropertyGroup Label="UserMacros">
    <ConfigurationYear>2012</ConfigurationYear>
    <INTEROP_BUILD_NUMBER>084</INTEROP_BUILD_NUMBER>
    <INTEROP_BUILD_NUMBER>083</INTEROP_BUILD_NUMBER>
    <INTEROP_LINKER_VERSION>1.0</INTEROP_LINKER_VERSION>
    <INTEROP_MANIFEST_VERSION>1.0.84.0</INTEROP_MANIFEST_VERSION>
    <INTEROP_RC_VERSION>1,0,84,0</INTEROP_RC_VERSION>
    <INTEROP_DEBUG_DEFINES>INTEROP_DEBUG=0x31F;INTEROP_LOG=1;INTEROP_TEST_EXTENSION=1</INTEROP_DEBUG_DEFINES>
    <INTEROP_MANIFEST_VERSION>1.0.83.0</INTEROP_MANIFEST_VERSION>
    <INTEROP_RC_VERSION>1,0,83,0</INTEROP_RC_VERSION>
    <INTEROP_DEBUG_DEFINES>INTEROP_DEBUG=0x307;INTEROP_TEST_EXTENSION=1</INTEROP_DEBUG_DEFINES>
    <INTEROP_EXTRA_DEFINES>INTEROP_EXTENSION_FUNCTIONS=1;INTEROP_CODEC=1</INTEROP_EXTRA_DEFINES>
    <INTEROP_ASSEMBLY_RESOURCES>/ASSEMBLYRESOURCE:..\System.Data.SQLite\SQLiteCommand.bmp,System.Data.SQLite.SQLiteCommand.bmp /ASSEMBLYRESOURCE:..\System.Data.SQLite\SQLiteConnection.bmp,System.Data.SQLite.SQLiteConnection.bmp /ASSEMBLYRESOURCE:..\System.Data.SQLite\SQLiteDataAdapter.bmp,System.Data.SQLite.SQLiteDataAdapter.bmp</INTEROP_ASSEMBLY_RESOURCES>
    <INTEROP_KEY_FILE>$(ProjectDir)..\System.Data.SQLite\System.Data.SQLite.snk</INTEROP_KEY_FILE>
    <INTEROP_NATIVE_NAME>SQLite.Interop</INTEROP_NATIVE_NAME>
    <INTEROP_MIXED_NAME>System.Data.SQLite</INTEROP_MIXED_NAME>
  </PropertyGroup>
  <ItemGroup>
Changes to SQLite.Interop/props/sqlite3.props.
1
2
3
4
5
6
7
8
9
10
11
12
13


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


12
13
14
15
16
17
18
19
20











-
-
+
+







<?xml version="1.0" encoding="utf-8"?>
<!--
 *
 * sqlite3.props -
 *
 * Written by Joe Mistachkin.
 * Released to the public domain, use at your own risk!
 *
-->
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
  <PropertyGroup Label="UserMacros">
    <SQLITE_MANIFEST_VERSION>3.7.16</SQLITE_MANIFEST_VERSION>
    <SQLITE_RC_VERSION>3,7,16</SQLITE_RC_VERSION>
    <SQLITE_MANIFEST_VERSION>3.7.15</SQLITE_MANIFEST_VERSION>
    <SQLITE_RC_VERSION>3,7,15</SQLITE_RC_VERSION>
    <SQLITE_COMMON_DEFINES>_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;SQLITE_THREADSAFE=1;SQLITE_USE_URI=1;SQLITE_ENABLE_COLUMN_METADATA=1;SQLITE_ENABLE_STAT3=1;SQLITE_ENABLE_FTS3=1;SQLITE_ENABLE_LOAD_EXTENSION=1;SQLITE_ENABLE_RTREE=1;SQLITE_SOUNDEX=1</SQLITE_COMMON_DEFINES>
    <SQLITE_EXTRA_DEFINES>SQLITE_HAS_CODEC=1</SQLITE_EXTRA_DEFINES>
    <SQLITE_WINCE_DEFINES>SQLITE_OMIT_WAL=1</SQLITE_WINCE_DEFINES>
    <SQLITE_DEBUG_DEFINES>SQLITE_DEBUG=1;SQLITE_MEMDEBUG=1;SQLITE_ENABLE_EXPENSIVE_ASSERT=1</SQLITE_DEBUG_DEFINES>
    <SQLITE_RELEASE_DEFINES>SQLITE_WIN32_MALLOC=1</SQLITE_RELEASE_DEFINES>
    <SQLITE_DISABLE_WARNINGS>4055;4100;4127;4146;4210;4232;4244;4245;4267;4306;4389;4701;4703;4706</SQLITE_DISABLE_WARNINGS>
    <SQLITE_DISABLE_X64_WARNINGS></SQLITE_DISABLE_X64_WARNINGS>
Changes to SQLite.Interop/props/sqlite3.vsprops.
10
11
12
13
14
15
16
17

18
19
20
21
22

23
24
25
26
27
28
29
10
11
12
13
14
15
16

17
18
19
20
21

22
23
24
25
26
27
28
29







-
+




-
+







<VisualStudioPropertySheet
	ProjectType="Visual C++"
	Version="8.00"
	Name="sqlite3"
	>
	<UserMacro
		Name="SQLITE_MANIFEST_VERSION"
		Value="3.7.16"
		Value="3.7.15"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="SQLITE_RC_VERSION"
		Value="3,7,16"
		Value="3,7,15"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="SQLITE_COMMON_DEFINES"
		Value="_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;SQLITE_THREADSAFE=1;SQLITE_USE_URI=1;SQLITE_ENABLE_COLUMN_METADATA=1;SQLITE_ENABLE_STAT3=1;SQLITE_ENABLE_FTS3=1;SQLITE_ENABLE_LOAD_EXTENSION=1;SQLITE_ENABLE_RTREE=1;SQLITE_SOUNDEX=1"
		PerformEnvironmentSet="true"
	/>
Changes to SQLite.Interop/src/core/sqlite3.c.
1
2
3

4
5
6
7
8
9
10
1
2

3
4
5
6
7
8
9
10


-
+







/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
** version 3.7.16.  By combining all the individual C code files into this 
** version 3.7.15.  By combining all the individual C code files into this 
** single large file, the entire code can be compiled as a single translation
** unit.  This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately.  Performance improvements
** of 5% or more are commonly seen when SQLite is compiled as a single
** translation unit.
**
** This file is all you need to compile SQLite.  To use SQLite in other
669
670
671
672
673
674
675
676
677
678



679
680
681
682
683
684
685
669
670
671
672
673
674
675



676
677
678
679
680
681
682
683
684
685







-
-
-
+
+
+







** string contains the date and time of the check-in (UTC) and an SHA1
** hash of the entire source tree.
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.7.16"
#define SQLITE_VERSION_NUMBER 3007016
#define SQLITE_SOURCE_ID      "2013-01-17 03:18:38 652233d646236d3fbca629813b20d075f00f3ed6"
#define SQLITE_VERSION        "3.7.15"
#define SQLITE_VERSION_NUMBER 3007015
#define SQLITE_SOURCE_ID      "2012-10-12 18:06:07 de784399ed1f0e27fc875e32719643d19819c8fb"

/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version, sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1036
1037
1038
1039
1040
1041
1042

1043
1044
1045
1046
1047
1048
1049







-







#define SQLITE_IOERR_CLOSE             (SQLITE_IOERR | (16<<8))
#define SQLITE_IOERR_DIR_CLOSE         (SQLITE_IOERR | (17<<8))
#define SQLITE_IOERR_SHMOPEN           (SQLITE_IOERR | (18<<8))
#define SQLITE_IOERR_SHMSIZE           (SQLITE_IOERR | (19<<8))
#define SQLITE_IOERR_SHMLOCK           (SQLITE_IOERR | (20<<8))
#define SQLITE_IOERR_SHMMAP            (SQLITE_IOERR | (21<<8))
#define SQLITE_IOERR_SEEK              (SQLITE_IOERR | (22<<8))
#define SQLITE_IOERR_DELETE_NOENT      (SQLITE_IOERR | (23<<8))
#define SQLITE_LOCKED_SHAREDCACHE      (SQLITE_LOCKED |  (1<<8))
#define SQLITE_BUSY_RECOVERY           (SQLITE_BUSY   |  (1<<8))
#define SQLITE_CANTOPEN_NOTEMPDIR      (SQLITE_CANTOPEN | (1<<8))
#define SQLITE_CANTOPEN_ISDIR          (SQLITE_CANTOPEN | (2<<8))
#define SQLITE_CANTOPEN_FULLPATH       (SQLITE_CANTOPEN | (3<<8))
#define SQLITE_CORRUPT_VTAB            (SQLITE_CORRUPT | (1<<8))
#define SQLITE_READONLY_RECOVERY       (SQLITE_READONLY | (1<<8))
1419
1420
1421
1422
1423
1424
1425

1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436










1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452

1453
1454
1455
1456
1457
1458
1459







+











-
-
-
-
-
-
-
-
-
-
















-







** VFS has handled the PRAGMA itself and the parser generates a no-op
** prepared statement.  ^If the [SQLITE_FCNTL_PRAGMA] file control returns
** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means
** that the VFS encountered an error while handling the [PRAGMA] and the
** compilation of the PRAGMA fails with an error.  ^The [SQLITE_FCNTL_PRAGMA]
** file control occurs at the beginning of pragma statement analysis and so
** it is able to override built-in [PRAGMA] statements.
** </ul>
**
** <li>[[SQLITE_FCNTL_BUSYHANDLER]]
** ^This file-control may be invoked by SQLite on the database file handle
** shortly after it is opened in order to provide a custom VFS with access
** to the connections busy-handler callback. The argument is of type (void **)
** - an array of two (void *) values. The first (void *) actually points
** to a function of type (int (*)(void *)). In order to invoke the connections
** busy-handler, this function should be invoked with the second (void *) in
** the array as the only argument. If it returns non-zero, then the operation
** should be retried. If it returns zero, the custom VFS should abandon the
** current operation.
**
** <li>[[SQLITE_FCNTL_TEMPFILENAME]]
** ^Application can invoke this file-control to have SQLite generate a
** temporary filename using the same algorithm that is followed to generate
** temporary filenames for TEMP tables and other internal uses.  The
** argument should be a char** which will be filled with the filename
** written into memory obtained from [sqlite3_malloc()].  The caller should
** invoke [sqlite3_free()] on the result to avoid a memory leak.
**
** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE               1
#define SQLITE_GET_LOCKPROXYFILE             2
#define SQLITE_SET_LOCKPROXYFILE             3
#define SQLITE_LAST_ERRNO                    4
#define SQLITE_FCNTL_SIZE_HINT               5
#define SQLITE_FCNTL_CHUNK_SIZE              6
#define SQLITE_FCNTL_FILE_POINTER            7
#define SQLITE_FCNTL_SYNC_OMITTED            8
#define SQLITE_FCNTL_WIN32_AV_RETRY          9
#define SQLITE_FCNTL_PERSIST_WAL            10
#define SQLITE_FCNTL_OVERWRITE              11
#define SQLITE_FCNTL_VFSNAME                12
#define SQLITE_FCNTL_POWERSAFE_OVERWRITE    13
#define SQLITE_FCNTL_PRAGMA                 14
#define SQLITE_FCNTL_BUSYHANDLER            15
#define SQLITE_FCNTL_TEMPFILENAME           16

/*
** CAPI3REF: Mutex Handle
**
** The mutex module within SQLite defines [sqlite3_mutex] to be an
** abstract type for a mutex object.  The SQLite core never looks
** at the internal representation of an [sqlite3_mutex].  It only
2154
2155
2156
2157
2158
2159
2160
2161

2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2143
2144
2145
2146
2147
2148
2149

2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
















2166
2167
2168
2169
2170
2171
2172







-
+















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







** connection is opened. If it is globally disabled, filenames are
** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the
** database connection is opened. By default, URI handling is globally
** disabled. The default value may be changed by compiling with the
** [SQLITE_USE_URI] symbol defined.
**
** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN
** <dd> This option takes a single integer argument which is interpreted as
** <dd> This option taks a single integer argument which is interpreted as
** a boolean in order to enable or disable the use of covering indices for
** full table scans in the query optimizer.  The default setting is determined
** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"
** if that compile-time option is omitted.
** The ability to disable the use of covering indices for full table scans
** is because some incorrectly coded legacy applications might malfunction
** malfunction when the optimization is enabled.  Providing the ability to
** disable the optimization allows the older, buggy application code to work
** without change even with newer versions of SQLite.
**
** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]]
** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE
** <dd> These options are obsolete and should not be used by new code.
** They are retained for backwards compatibility but are now no-ops.
** </dl>
**
** [[SQLITE_CONFIG_SQLLOG]]
** <dt>SQLITE_CONFIG_SQLLOG
** <dd>This option is only available if sqlite is compiled with the
** SQLITE_ENABLE_SQLLOG pre-processor macro defined. The first argument should
** be a pointer to a function of type void(*)(void*,sqlite3*,const char*, int).
** The second should be of type (void*). The callback is invoked by the library
** in three separate circumstances, identified by the value passed as the
** fourth parameter. If the fourth parameter is 0, then the database connection
** passed as the second argument has just been opened. The third argument
** points to a buffer containing the name of the main database file. If the
** fourth parameter is 1, then the SQL statement that the third parameter
** points to has just been executed. Or, if the fourth parameter is 2, then
** the connection being passed as the second parameter is being closed. The
** third parameter is passed NULL In this case.
** </dl>
*/
#define SQLITE_CONFIG_SINGLETHREAD  1  /* nil */
#define SQLITE_CONFIG_MULTITHREAD   2  /* nil */
#define SQLITE_CONFIG_SERIALIZED    3  /* nil */
#define SQLITE_CONFIG_MALLOC        4  /* sqlite3_mem_methods* */
#define SQLITE_CONFIG_GETMALLOC     5  /* sqlite3_mem_methods* */
#define SQLITE_CONFIG_SCRATCH       6  /* void*, int sz, int N */
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2180
2181
2182
2183
2184
2185
2186

2187
2188
2189
2190
2191
2192
2193







-







#define SQLITE_CONFIG_PCACHE       14  /* no-op */
#define SQLITE_CONFIG_GETPCACHE    15  /* no-op */
#define SQLITE_CONFIG_LOG          16  /* xFunc, void* */
#define SQLITE_CONFIG_URI          17  /* int */
#define SQLITE_CONFIG_PCACHE2      18  /* sqlite3_pcache_methods2* */
#define SQLITE_CONFIG_GETPCACHE2   19  /* sqlite3_pcache_methods2* */
#define SQLITE_CONFIG_COVERING_INDEX_SCAN 20  /* int */
#define SQLITE_CONFIG_SQLLOG       21  /* xSqllog, void* */

/*
** CAPI3REF: Database Connection Configuration Options
**
** These constants are the available integer configuration options that
** can be passed as the second argument to the [sqlite3_db_config()] interface.
**
8465
8466
8467
8468
8469
8470
8471
8472
8473
8474
8475
8476
8477
8478
8479
8480
8437
8438
8439
8440
8441
8442
8443


8444
8445
8446
8447
8448
8449
8450







-
-







SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree*, int, int*);
SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, int*);
SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree*, int);

SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue);
SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);

SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p);

/*
** The second parameter to sqlite3BtreeGetMeta or sqlite3BtreeUpdateMeta
** should be one of the following values. The integer values are assigned 
** to constants so that the offset of the corresponding field in an
** SQLite database header may be found using the following formula:
**
**   offset = 36 + (idx * 4)
8981
8982
8983
8984
8985
8986
8987
8988

8989
8990
8991
8992
8993
8994
8995
8951
8952
8953
8954
8955
8956
8957

8958
8959
8960
8961
8962
8963
8964
8965







-
+







SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe*, int addr);
SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int);
SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3*,Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeDeleteObject(sqlite3*,Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeMakeReady(Vdbe*,Parse*);
SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe*, int);
SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe*);
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE   int sqlite3VdbeAssertMayAbort(Vdbe *, int);
SQLITE_PRIVATE   void sqlite3VdbeTrace(Vdbe*,FILE*);
9894
9895
9896
9897
9898
9899
9900
9901

9902
9903
9904
9905
9906
9907
9908
9864
9865
9866
9867
9868
9869
9870

9871
9872
9873
9874
9875
9876
9877
9878







-
+







  Db *aDb;                      /* All backends */
  int nDb;                      /* Number of backends currently in use */
  int flags;                    /* Miscellaneous flags. See below */
  i64 lastRowid;                /* ROWID of most recent insert (see above) */
  unsigned int openFlags;       /* Flags passed to sqlite3_vfs.xOpen() */
  int errCode;                  /* Most recent error code (SQLITE_*) */
  int errMask;                  /* & result codes with this before returning */
  u16 dbOptFlags;               /* Flags to enable/disable optimizations */
  u8 dbOptFlags;                /* Flags to enable/disable optimizations */
  u8 autoCommit;                /* The auto-commit flag. */
  u8 temp_store;                /* 1: file 2: memory 0: default */
  u8 mallocFailed;              /* True if we have seen a malloc failure */
  u8 dfltLockMode;              /* Default locking-mode for attached dbs */
  signed char nextAutovac;      /* Autovac setting after VACUUM if >=0 */
  u8 suppressErr;               /* Do not issue error messages if true */
  u8 vtabOnConflict;            /* Value to return for s3_vtab_on_conflict() */
10039
10040
10041
10042
10043
10044
10045
10046
10047

10048
10049
10050
10051
10052
10053
10054
10009
10010
10011
10012
10013
10014
10015


10016
10017
10018
10019
10020
10021
10022
10023







-
-
+







#define SQLITE_ColumnCache    0x0002   /* Column cache */
#define SQLITE_GroupByOrder   0x0004   /* GROUPBY cover of ORDERBY */
#define SQLITE_FactorOutConst 0x0008   /* Constant factoring */
#define SQLITE_IdxRealAsInt   0x0010   /* Store REAL as INT in indices */
#define SQLITE_DistinctOpt    0x0020   /* DISTINCT using indexes */
#define SQLITE_CoverIdxScan   0x0040   /* Covering index scans */
#define SQLITE_OrderByIdxJoin 0x0080   /* ORDER BY of joins via index */
#define SQLITE_SubqCoroutine  0x0100   /* Evaluate subqueries as coroutines */
#define SQLITE_AllOpts        0xffff   /* All optimizations */
#define SQLITE_AllOpts        0x00ff   /* All optimizations */

/*
** Macros for testing whether or not optimizations are enabled or disabled.
*/
#ifndef SQLITE_OMIT_BUILTIN_TEST
#define OptimizationDisabled(db, mask)  (((db)->dbOptFlags&(mask))!=0)
#define OptimizationEnabled(db, mask)   (((db)->dbOptFlags&(mask))==0)
10217
10218
10219
10220
10221
10222
10223












10224

10225
10226
10227
10228
10229
10230
10231
10186
10187
10188
10189
10190
10191
10192
10193
10194
10195
10196
10197
10198
10199
10200
10201
10202
10203
10204

10205
10206
10207
10208
10209
10210
10211
10212







+
+
+
+
+
+
+
+
+
+
+
+
-
+







#define COLFLAG_HIDDEN   0x0002    /* A hidden column in a virtual table */

/*
** A "Collating Sequence" is defined by an instance of the following
** structure. Conceptually, a collating sequence consists of a name and
** a comparison routine that defines the order of that sequence.
**
** There may two separate implementations of the collation function, one
** that processes text in UTF-8 encoding (CollSeq.xCmp) and another that
** processes text encoded in UTF-16 (CollSeq.xCmp16), using the machine
** native byte order. When a collation sequence is invoked, SQLite selects
** the version that will require the least expensive encoding
** translations, if any.
**
** The CollSeq.pUser member variable is an extra parameter that passed in
** as the first argument to the UTF-8 comparison function, xCmp.
** CollSeq.pUser16 is the equivalent for the UTF-16 comparison function,
** xCmp16.
**
** If CollSeq.xCmp is NULL, it means that the
** If both CollSeq.xCmp and CollSeq.xCmp16 are NULL, it means that the
** collating sequence is undefined.  Indices built on an undefined
** collating sequence may not be read or written.
*/
struct CollSeq {
  char *zName;          /* Name of the collating sequence, UTF-8 encoded */
  u8 enc;               /* Text encoding handled by xCmp() */
  void *pUser;          /* First argument to xCmp() */
10551
10552
10553
10554
10555
10556
10557
10558
10559
10560
10561
10562
10563
10564
10565
10566
10567











10568
10569
10570
10571



10572
10573
10574
10575
10576
10577
10578
10532
10533
10534
10535
10536
10537
10538










10539
10540
10541
10542
10543
10544
10545
10546
10547
10548
10549




10550
10551
10552
10553
10554
10555
10556
10557
10558
10559







-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+







** must be unique and what to do if they are not.  When Index.onError=OE_None,
** it means this is not a unique index.  Otherwise it is a unique index
** and the value of Index.onError indicate the which conflict resolution 
** algorithm to employ whenever an attempt is made to insert a non-unique
** element.
*/
struct Index {
  char *zName;             /* Name of this index */
  int *aiColumn;           /* Which columns are used by this index.  1st is 0 */
  tRowcnt *aiRowEst;       /* From ANALYZE: Est. rows selected by each column */
  Table *pTable;           /* The SQL table being indexed */
  char *zColAff;           /* String defining the affinity of each column */
  Index *pNext;            /* The next index associated with the same table */
  Schema *pSchema;         /* Schema containing this index */
  u8 *aSortOrder;          /* for each column: True==DESC, False==ASC */
  char **azColl;           /* Array of collation sequence names for index */
  int tnum;                /* DB Page containing root of this index */
  char *zName;     /* Name of this index */
  int *aiColumn;   /* Which columns are used by this index.  1st is 0 */
  tRowcnt *aiRowEst; /* Result of ANALYZE: Est. rows selected by each column */
  Table *pTable;   /* The SQL table being indexed */
  char *zColAff;   /* String defining the affinity of each column */
  Index *pNext;    /* The next index associated with the same table */
  Schema *pSchema; /* Schema containing this index */
  u8 *aSortOrder;  /* Array of size Index.nColumn. True==DESC, False==ASC */
  char **azColl;   /* Array of collation sequence names for index */
  int nColumn;     /* Number of columns in the table used by this index */
  int tnum;        /* Page containing root of this index in database file */
  u16 nColumn;             /* Number of columns in table used by this index */
  u8 onError;              /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
  unsigned autoIndex:2;    /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
  unsigned bUnordered:1;   /* Use this index for == or IN queries only */
  u8 onError;      /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
  u8 autoIndex;    /* True if is automatically created (ex: by UNIQUE) */
  u8 bUnordered;   /* Use this index for == or IN queries only */
#ifdef SQLITE_ENABLE_STAT3
  int nSample;             /* Number of elements in aSample[] */
  tRowcnt avgEq;           /* Average nEq value for key values not in aSample */
  IndexSample *aSample;    /* Samples of the left-most key */
#endif
};

10745
10746
10747
10748
10749
10750
10751

10752
10753
10754
10755
10756
10757
10758
10726
10727
10728
10729
10730
10731
10732
10733
10734
10735
10736
10737
10738
10739
10740







+








  Expr *pLeft;           /* Left subnode */
  Expr *pRight;          /* Right subnode */
  union {
    ExprList *pList;     /* Function arguments or in "<expr> IN (<expr-list)" */
    Select *pSelect;     /* Used for sub-selects and "<expr> IN (<select>)" */
  } x;
  CollSeq *pColl;        /* The collation type of the column or 0 */

  /* If the EP_Reduced flag is set in the Expr.flags mask, then no
  ** space is allocated for the fields below this point. An attempt to
  ** access them will result in a segfault or malfunction.
  *********************************************************************/

#if SQLITE_MAX_EXPR_DEPTH>0
10780
10781
10782
10783
10784
10785
10786
10787

10788
10789
10790
10791
10792
10793
10794
10762
10763
10764
10765
10766
10767
10768

10769
10770
10771
10772
10773
10774
10775
10776







-
+







#define EP_Agg        0x0002  /* Contains one or more aggregate functions */
#define EP_Resolved   0x0004  /* IDs have been resolved to COLUMNs */
#define EP_Error      0x0008  /* Expression contains one or more errors */
#define EP_Distinct   0x0010  /* Aggregate function with DISTINCT keyword */
#define EP_VarSelect  0x0020  /* pSelect is correlated, not constant */
#define EP_DblQuoted  0x0040  /* token.z was originally in "..." */
#define EP_InfixFunc  0x0080  /* True for an infix function: LIKE, GLOB, etc */
#define EP_Collate    0x0100  /* Tree contains a TK_COLLATE opeartor */
#define EP_ExpCollate 0x0100  /* Collating sequence specified explicitly */
#define EP_FixedDest  0x0200  /* Result needed in a specific register */
#define EP_IntValue   0x0400  /* Integer value contained in u.iValue */
#define EP_xIsSelect  0x0800  /* x.pSelect is valid (otherwise x.pList is) */
#define EP_Hint       0x1000  /* Not used */
#define EP_Reduced    0x2000  /* Expr struct is EXPR_REDUCEDSIZE bytes only */
#define EP_TokenOnly  0x4000  /* Expr struct is EXPR_TOKENONLYSIZE bytes only */
#define EP_Static     0x8000  /* Held in memory not obtained from malloc() */
10838
10839
10840
10841
10842
10843
10844
10845
10846
10847
10848
10849
10850
10851
10852
10853
10854
10855
10856
10857
10858
10859
10860
10861
10862





10863
10864
10865


10866
10867
10868
10869
10870
10871
10872
10820
10821
10822
10823
10824
10825
10826








10827
10828
10829
10830
10831





10832
10833
10834
10835
10836



10837
10838
10839
10840
10841
10842
10843
10844
10845







-
-
-
-
-
-
-
-





-
-
-
-
-
+
+
+
+
+
-
-
-
+
+







/*
** A list of expressions.  Each expression may optionally have a
** name.  An expr/name combination can be used in several ways, such
** as the list of "expr AS ID" fields following a "SELECT" or in the
** list of "ID = expr" items in an UPDATE.  A list of expressions can
** also be used as the argument to a function, in which case the a.zName
** field is not used.
**
** By default the Expr.zSpan field holds a human-readable description of
** the expression that is used in the generation of error messages and
** column labels.  In this case, Expr.zSpan is typically the text of a
** column expression as it exists in a SELECT statement.  However, if
** the bSpanIsTab flag is set, then zSpan is overloaded to mean the name
** of the result column in the form: DATABASE.TABLE.COLUMN.  This later
** form is used for name resolution with nested FROM clauses.
*/
struct ExprList {
  int nExpr;             /* Number of expressions on the list */
  int iECursor;          /* VDBE Cursor associated with this ExprList */
  struct ExprList_item { /* For each expression in the list */
    Expr *pExpr;            /* The list of expressions */
    char *zName;            /* Token associated with this expression */
    char *zSpan;            /* Original text of the expression */
    u8 sortOrder;           /* 1 for DESC or 0 for ASC */
    unsigned done :1;       /* A flag to indicate when processing is finished */
    Expr *pExpr;           /* The list of expressions */
    char *zName;           /* Token associated with this expression */
    char *zSpan;           /* Original text of the expression */
    u8 sortOrder;          /* 1 for DESC or 0 for ASC */
    u8 done;               /* A flag to indicate when processing is finished */
    unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */
    u16 iOrderByCol;        /* For ORDER BY, column number in result set */
    u16 iAlias;             /* Index into Parse.aAlias[] for zName */
    u16 iOrderByCol;       /* For ORDER BY, column number in result set */
    u16 iAlias;            /* Index into Parse.aAlias[] for zName */
  } *a;                  /* Alloc a power of two greater or equal to nExpr */
};

/*
** An instance of this structure is used by the parser to record both
** the parse tree for an expression and the span of input text for an
** expression.
10942
10943
10944
10945
10946
10947
10948
10949
10950


10951
10952
10953
10954
10955
10956
10957
10958
10915
10916
10917
10918
10919
10920
10921


10922
10923

10924
10925
10926
10927
10928
10929
10930







-
-
+
+
-







    char *zName;      /* Name of the table */
    char *zAlias;     /* The "B" part of a "A AS B" phrase.  zName is the "A" */
    Table *pTab;      /* An SQL table corresponding to zName */
    Select *pSelect;  /* A SELECT statement used in place of a table name */
    int addrFillSub;  /* Address of subroutine to manifest a subquery */
    int regReturn;    /* Register holding return address of addrFillSub */
    u8 jointype;      /* Type of join between this able and the previous */
    unsigned notIndexed :1;    /* True if there is a NOT INDEXED clause */
    unsigned isCorrelated :1;  /* True if sub-query is correlated */
    u8 notIndexed;    /* True if there is a NOT INDEXED clause */
    u8 isCorrelated;  /* True if sub-query is correlated */
    unsigned viaCoroutine :1;  /* Implemented as a co-routine */
#ifndef SQLITE_OMIT_EXPLAIN
    u8 iSelectId;     /* If pSelect!=0, the id of the sub-select in EQP */
#endif
    int iCursor;      /* The VDBE cursor number used to access this table */
    Expr *pOn;        /* The ON clause of a join */
    IdList *pUsing;   /* The USING clause of a join */
    Bitmask colUsed;  /* Bit N (1<<N) set if column N of pTab is used */
11030
11031
11032
11033
11034
11035
11036
11037
11038
11039
11040
11041
11042
11043
11044
11002
11003
11004
11005
11006
11007
11008

11009
11010
11011
11012
11013
11014
11015







-







      struct InLoop {
        int iCur;              /* The VDBE cursor used by this IN operator */
        int addrInTop;         /* Top of the IN loop */
      } *aInLoop;           /* Information about each nested IN operator */
    } in;                 /* Used when plan.wsFlags&WHERE_IN_ABLE */
    Index *pCovidx;       /* Possible covering index for WHERE_MULTI_OR */
  } u;
  double rOptCost;      /* "Optimal" cost for this level */

  /* The following field is really not part of the current level.  But
  ** we need a place to cache virtual table index information for each
  ** virtual table in the FROM clause and the WhereLevel structure is
  ** a convenient place since there is one WhereLevel for each FROM clause
  ** element.
  */
11169
11170
11171
11172
11173
11174
11175
11176
11177
11178
11179
11180
11181
11182
11183








11184
11185
11186
11187
11188
11189
11190
11191
11192
11140
11141
11142
11143
11144
11145
11146








11147
11148
11149
11150
11151
11152
11153
11154


11155
11156
11157
11158
11159
11160
11161







-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-







  Expr *pOffset;         /* OFFSET expression. NULL means not used. */
};

/*
** Allowed values for Select.selFlags.  The "SF" prefix stands for
** "Select Flag".
*/
#define SF_Distinct        0x0001  /* Output should be DISTINCT */
#define SF_Resolved        0x0002  /* Identifiers have been resolved */
#define SF_Aggregate       0x0004  /* Contains aggregate functions */
#define SF_UsesEphemeral   0x0008  /* Uses the OpenEphemeral opcode */
#define SF_Expanded        0x0010  /* sqlite3SelectExpand() called on this */
#define SF_HasTypeInfo     0x0020  /* FROM subqueries have Table metadata */
#define SF_UseSorter       0x0040  /* Sort using a sorter */
#define SF_Values          0x0080  /* Synthesized from VALUES clause */
#define SF_Distinct        0x01  /* Output should be DISTINCT */
#define SF_Resolved        0x02  /* Identifiers have been resolved */
#define SF_Aggregate       0x04  /* Contains aggregate functions */
#define SF_UsesEphemeral   0x08  /* Uses the OpenEphemeral opcode */
#define SF_Expanded        0x10  /* sqlite3SelectExpand() called on this */
#define SF_HasTypeInfo     0x20  /* FROM subqueries have Table metadata */
#define SF_UseSorter       0x40  /* Sort using a sorter */
#define SF_Values          0x80  /* Synthesized from VALUES clause */
#define SF_Materialize     0x0100  /* Force materialization of views */
#define SF_NestedFrom      0x0200  /* Part of a parenthesized FROM clause */


/*
** The results of a select can be distributed in several ways.  The
** "SRT" prefix means "SELECT Result Type".
*/
#define SRT_Union        1  /* Store result as keys in an index */
11407
11408
11409
11410
11411
11412
11413
11414
11415
11416
11417
11418
11419
11420
11421
11376
11377
11378
11379
11380
11381
11382

11383
11384
11385
11386
11387
11388
11389







-







#define OPFLAG_APPEND        0x08    /* This is likely to be an append */
#define OPFLAG_USESEEKRESULT 0x10    /* Try to avoid a seek in BtreeInsert() */
#define OPFLAG_CLEARCACHE    0x20    /* Clear pseudo-table cache in OP_Column */
#define OPFLAG_LENGTHARG     0x40    /* OP_Column only used for length() */
#define OPFLAG_TYPEOFARG     0x80    /* OP_Column only used for typeof() */
#define OPFLAG_BULKCSR       0x01    /* OP_Open** used to open bulk cursor */
#define OPFLAG_P2ISREG       0x02    /* P2 to OP_Open** is a register number */
#define OPFLAG_PERMUTE       0x01    /* OP_Compare: use the permutation */

/*
 * Each trigger present in the database schema is stored as an instance of
 * struct Trigger. 
 *
 * Pointers to instances of struct Trigger are stored in two ways.
 * 1. In the "trigHash" hash table (part of the sqlite3* that represents the 
11580
11581
11582
11583
11584
11585
11586
11587
11588
11589
11590
11591
11592
11593
11594
11595
11596
11597
11548
11549
11550
11551
11552
11553
11554




11555
11556
11557
11558
11559
11560
11561







-
-
-
-







  int isMallocInit;                 /* True after malloc is initialized */
  int isPCacheInit;                 /* True after malloc is initialized */
  sqlite3_mutex *pInitMutex;        /* Mutex used by sqlite3_initialize() */
  int nRefInitMutex;                /* Number of users of pInitMutex */
  void (*xLog)(void*,int,const char*); /* Function for logging */
  void *pLogArg;                       /* First argument to xLog() */
  int bLocaltimeFault;              /* True to fail localtime() calls */
#ifdef SQLITE_ENABLE_SQLLOG
  void(*xSqllog)(void*,sqlite3*,const char*, int);
  void *pSqllogArg;
#endif
};

/*
** Context pointer passed down through the tree-walk.
*/
struct Walker {
  int (*xExprCallback)(Walker*, Expr*);     /* Callback for expressions */
11891
11892
11893
11894
11895
11896
11897
11898

11899
11900
11901
11902
11903
11904
11905
11855
11856
11857
11858
11859
11860
11861

11862
11863
11864
11865
11866
11867
11868
11869







-
+







SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3*, IdList*);
SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3*, SrcList*);
SQLITE_PRIVATE Index *sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
                        Token*, int, int);
SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int);
SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*);
SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
                         Expr*,ExprList*,u16,Expr*,Expr*);
                         Expr*,ExprList*,int,Expr*,Expr*);
SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*);
SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*);
SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, int);
SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse *, SrcList *, Expr *, ExprList *, Expr *, Expr *, char *);
#endif
12099
12100
12101
12102
12103
12104
12105
12106
12107
12108


12109
12110
12111
12112
12113
12114
12115
12063
12064
12065
12066
12067
12068
12069



12070
12071
12072
12073
12074
12075
12076
12077
12078







-
-
-
+
+







SQLITE_PRIVATE u8 sqlite3HexToInt(int h);
SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
SQLITE_PRIVATE const char *sqlite3ErrStr(int);
SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse);
SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, Token*);
SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*);
SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Expr*, CollSeq*);
SQLITE_PRIVATE Expr *sqlite3ExprSetCollByToken(Parse *pParse, Expr*, Token*);
SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *);
SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *, const char *);
SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int);
SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64);
SQLITE_PRIVATE int sqlite3SubInt64(i64*,i64);
SQLITE_PRIVATE int sqlite3MulInt64(i64*,i64);
SQLITE_PRIVATE int sqlite3AbsInt32(int);
12148
12149
12150
12151
12152
12153
12154
12155
12156
12157
12158
12159
12160
12161
12162
12111
12112
12113
12114
12115
12116
12117

12118
12119
12120
12121
12122
12123
12124







-







SQLITE_PRIVATE void sqlite3AlterFunctions(void);
SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *);
SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...);
SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*);
SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *, Expr *, int, int);
SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*);
SQLITE_PRIVATE int sqlite3MatchSpanName(const char*, const char*, const char*, const char*);
SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*);
SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *);
SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
12287
12288
12289
12290
12291
12292
12293
12294
12295
12296
12297
12298
12299
12300
12301
12302
12303
12304
12249
12250
12251
12252
12253
12254
12255

12256
12257

12258
12259
12260
12261
12262
12263
12264







-


-







  #define sqlite3FkCheck(a,b,c,d)
  #define sqlite3FkDropTable(a,b,c)
  #define sqlite3FkOldmask(a,b)      0
  #define sqlite3FkRequired(a,b,c,d) 0
#endif
#ifndef SQLITE_OMIT_FOREIGN_KEY
SQLITE_PRIVATE   void sqlite3FkDelete(sqlite3 *, Table*);
SQLITE_PRIVATE   int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**);
#else
  #define sqlite3FkDelete(a,b)
  #define sqlite3FkLocateIndex(a,b,c,d,e)
#endif


/*
** Available fault injectors.  Should be numbered beginning with 0.
*/
#define SQLITE_FAULTINJECTOR_MALLOC     0
12322
12323
12324
12325
12326
12327
12328
12329
12330
12331
12332
12333
12334
12335
12336
12337
12338
12339
12282
12283
12284
12285
12286
12287
12288

12289
12290

12291
12292
12293
12294
12295
12296
12297







-


-







#define IN_INDEX_INDEX           3
SQLITE_PRIVATE int sqlite3FindInIndex(Parse *, Expr *, int*);

#ifdef SQLITE_ENABLE_ATOMIC_WRITE
SQLITE_PRIVATE   int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int);
SQLITE_PRIVATE   int sqlite3JournalSize(sqlite3_vfs *);
SQLITE_PRIVATE   int sqlite3JournalCreate(sqlite3_file *);
SQLITE_PRIVATE   int sqlite3JournalExists(sqlite3_file *p);
#else
  #define sqlite3JournalSize(pVfs) ((pVfs)->szOsFile)
  #define sqlite3JournalExists(p) 1
#endif

SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *);
SQLITE_PRIVATE int sqlite3MemJournalSize(void);
SQLITE_PRIVATE int sqlite3IsMemJournal(sqlite3_file *);

#if SQLITE_MAX_EXPR_DEPTH>0
12596
12597
12598
12599
12600
12601
12602
12603
12604
12605
12606
12607
12608
12609
12610
12611
12612
12613
12554
12555
12556
12557
12558
12559
12560




12561
12562
12563
12564
12565
12566
12567







-
-
-
-







   0,                         /* isMallocInit */
   0,                         /* isPCacheInit */
   0,                         /* pInitMutex */
   0,                         /* nRefInitMutex */
   0,                         /* xLog */
   0,                         /* pLogArg */
   0,                         /* bLocaltimeFault */
#ifdef SQLITE_ENABLE_SQLLOG
   0,                         /* xSqllog */
   0                          /* pSqllogArg */
#endif
};


/*
** Hash table for global functions - functions common to all
** database connections.  After initialization, this table is
** read-only.
13140
13141
13142
13143
13144
13145
13146
13147
13148
13149
13150
13151
13152
13153
13154
13094
13095
13096
13097
13098
13099
13100

13101
13102
13103
13104
13105
13106
13107







-







  Bool useRandomRowid;  /* Generate new record numbers semi-randomly */
  Bool nullRow;         /* True if pointing to a row with no data */
  Bool deferredMoveto;  /* A call to sqlite3BtreeMoveto() is needed */
  Bool isTable;         /* True if a table requiring integer keys */
  Bool isIndex;         /* True if an index containing keys only - no data */
  Bool isOrdered;       /* True if the underlying table is BTREE_UNORDERED */
  Bool isSorter;        /* True if a new-style sorter */
  Bool multiPseudo;     /* Multi-register pseudo-cursor */
  sqlite3_vtab_cursor *pVtabCursor;  /* The cursor for a virtual table */
  const sqlite3_module *pModule;     /* Module for cursor pVtabCursor */
  i64 seqCount;         /* Sequence counter */
  i64 movetoTarget;     /* Argument to the deferred sqlite3BtreeMoveto() */
  i64 lastRowid;        /* Last rowid from a Next or NextIdx operation */
  VdbeSorter *pSorter;  /* Sorter object for OP_SorterOpen cursors */

13754
13755
13756
13757
13758
13759
13760
13761

13762
13763
13764
13765
13766
13767
13768
13769
13707
13708
13709
13710
13711
13712
13713

13714

13715
13716
13717
13718
13719
13720
13721







-
+
-







    */
    case SQLITE_DBSTATUS_STMT_USED: {
      struct Vdbe *pVdbe;         /* Used to iterate through VMs */
      int nByte = 0;              /* Used to accumulate return value */

      db->pnBytesFreed = &nByte;
      for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){
        sqlite3VdbeClearObject(db, pVdbe);
        sqlite3VdbeDeleteObject(db, pVdbe);
        sqlite3DbFree(db, pVdbe);
      }
      db->pnBytesFreed = 0;

      *pHighwater = 0;
      *pCurrent = nByte;

      break;
22425
22426
22427
22428
22429
22430
22431
22432

22433
22434
22435
22436
22437
22438
22439
22377
22378
22379
22380
22381
22382
22383

22384
22385
22386
22387
22388
22389
22390
22391







-
+







      pEntry->chain = elem->next;
    }
    pEntry->count--;
    assert( pEntry->count>=0 );
  }
  sqlite3_free( elem );
  pH->count--;
  if( pH->count==0 ){
  if( pH->count<=0 ){
    assert( pH->first==0 );
    assert( pH->count==0 );
    sqlite3HashClear(pH);
  }
}

/* Attempt to locate an element of the hash table pH with a key
22723
22724
22725
22726
22727
22728
22729
22730
22731
22732
22733
22734
22735
22736
22737
22738
22739
22740
22741
22742
22743
22675
22676
22677
22678
22679
22680
22681







22682
22683
22684
22685
22686
22687
22688







-
-
-
-
-
-
-







**   *  sqlite3_vfs method implementations.
**   *  Locking primitives for the proxy uber-locking-method. (MacOSX only)
**   *  Definitions of sqlite3_vfs objects for all locking methods
**      plus implementations of sqlite3_os_init() and sqlite3_os_end().
*/
#if SQLITE_OS_UNIX              /* This file is used on unix only */

/* Use posix_fallocate() if it is available
*/
#if !defined(HAVE_POSIX_FALLOCATE) \
      && (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L)
# define HAVE_POSIX_FALLOCATE 1
#endif

/*
** There are various methods for file locking used for concurrency
** control:
**
**   1. POSIX locking (the default),
**   2. No locking,
**   3. Dot-file locking,
22902
22903
22904
22905
22906
22907
22908
22909
22910
22911
22912
22913
22914
22915
22916
22917
22918
22919
22847
22848
22849
22850
22851
22852
22853




22854
22855
22856
22857
22858
22859
22860







-
-
-
-







  unsigned short int ctrlFlags;       /* Behavioral bits.  UNIXFILE_* flags */
  int lastErrno;                      /* The unix errno from last I/O error */
  void *lockingContext;               /* Locking style specific state */
  UnixUnusedFd *pUnused;              /* Pre-allocated UnixUnusedFd */
  const char *zPath;                  /* Name of the file */
  unixShm *pShm;                      /* Shared memory segment information */
  int szChunk;                        /* Configured by FCNTL_CHUNK_SIZE */
#ifdef __QNXNTO__
  int sectorSize;                     /* Device sector size */
  int deviceCharacteristics;          /* Precomputed device characteristics */
#endif
#if SQLITE_ENABLE_LOCKING_STYLE
  int openFlags;                      /* The flags specified at open() */
#endif
#if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__)
  unsigned fsFlags;                   /* cached details from statfs() */
#endif
#if OS_VXWORKS
23297
23298
23299
23300
23301
23302
23303

23304



23305
23306
23307
23308
23309
23310
23311
23238
23239
23240
23241
23242
23243
23244
23245
23246
23247
23248
23249
23250
23251
23252
23253
23254
23255
23256







+

+
+
+







  { "pwrite64",     (sqlite3_syscall_ptr)pwrite64,   0  },
#else
  { "pwrite64",     (sqlite3_syscall_ptr)0,          0  },
#endif
#define osPwrite64  ((ssize_t(*)(int,const void*,size_t,off_t))\
                    aSyscall[13].pCurrent)

#if SQLITE_ENABLE_LOCKING_STYLE
  { "fchmod",       (sqlite3_syscall_ptr)fchmod,     0  },
#else
  { "fchmod",       (sqlite3_syscall_ptr)0,          0  },
#endif
#define osFchmod    ((int(*)(int,mode_t))aSyscall[14].pCurrent)

#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
  { "fallocate",    (sqlite3_syscall_ptr)posix_fallocate,  0 },
#else
  { "fallocate",    (sqlite3_syscall_ptr)0,                0 },
#endif
23321
23322
23323
23324
23325
23326
23327



23328
23329
23330
23331
23332
23333
23334
23266
23267
23268
23269
23270
23271
23272
23273
23274
23275
23276
23277
23278
23279
23280
23281
23282







+
+
+







#define osMkdir     ((int(*)(const char*,mode_t))aSyscall[18].pCurrent)

  { "rmdir",        (sqlite3_syscall_ptr)rmdir,           0 },
#define osRmdir     ((int(*)(const char*))aSyscall[19].pCurrent)

  { "fchown",       (sqlite3_syscall_ptr)posixFchown,     0 },
#define osFchown    ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)

  { "umask",        (sqlite3_syscall_ptr)umask,           0 },
#define osUmask     ((mode_t(*)(mode_t))aSyscall[21].pCurrent)

}; /* End of the overrideable system calls */

/*
** This is the xSetSystemCall() method of sqlite3_vfs for all of the
** "unix" VFSes.  Return SQLITE_OK opon successfully updating the
** system call pointer, or SQLITE_NOTFOUND if there is no configurable
23426
23427
23428
23429
23430
23431
23432



23433





23434
23435
23436
23437
23438
23439
23440
23441
23442

23443
23444
23445
23446


23447
23448
23449

23450
23451
23452
23453
23454
23455
23456
23457
23458
23374
23375
23376
23377
23378
23379
23380
23381
23382
23383

23384
23385
23386
23387
23388
23389
23390
23391
23392
23393
23394
23395


23396




23397
23398

23399

23400
23401

23402
23403
23404
23405
23406
23407
23408







+
+
+
-
+
+
+
+
+







-
-
+
-
-
-
-
+
+
-

-
+

-







** In that way, if a database file is -rw-rw-rw or -rw-rw-r-, and a
** transaction crashes and leaves behind hot journals, then any
** process that is able to write to the database will also be able to
** recover the hot journals.
*/
static int robust_open(const char *z, int f, mode_t m){
  int fd;
  mode_t m2;
  mode_t origM = 0;
  if( m==0 ){
  mode_t m2 = m ? m : SQLITE_DEFAULT_FILE_PERMISSIONS;
    m2 = SQLITE_DEFAULT_FILE_PERMISSIONS;
  }else{
    m2 = m;
    origM = osUmask(0);
  }
  do{
#if defined(O_CLOEXEC)
    fd = osOpen(z,f|O_CLOEXEC,m2);
#else
    fd = osOpen(z,f,m2);
#endif
  }while( fd<0 && errno==EINTR );
  if( fd>=0 ){
    if( m!=0 ){
  if( m ){
      struct stat statbuf;
      if( osFstat(fd, &statbuf)==0 && (statbuf.st_mode&0777)!=m ){
        osFchmod(fd, m);
      }
    osUmask(origM);
  }
    }
#if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0)
    osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
  if( fd>=0 ) osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
#endif
  }
  return fd;
}

/*
** Helper functions to obtain and relinquish the global mutex. The
** global mutex is used to protect the unixInodeInfo and
** vxworksFileId objects used by this file, all of which may be 
26457
26458
26459
26460
26461
26462
26463
26464
26465
26466
26467
26468
26469
26470
26471
26472
26473
26407
26408
26409
26410
26411
26412
26413



26414
26415
26416
26417
26418
26419
26420







-
-
-







  }else if( (*pArg)==0 ){
    pFile->ctrlFlags &= ~mask;
  }else{
    pFile->ctrlFlags |= mask;
  }
}

/* Forward declaration */
static int unixGetTempname(int nBuf, char *zBuf);

/*
** Information and control of an open file handle.
*/
static int unixFileControl(sqlite3_file *id, int op, void *pArg){
  unixFile *pFile = (unixFile*)id;
  switch( op ){
    case SQLITE_FCNTL_LOCKSTATE: {
26497
26498
26499
26500
26501
26502
26503
26504
26505
26506
26507
26508
26509
26510
26511
26512
26513
26514
26515
26516
26517
26518
26444
26445
26446
26447
26448
26449
26450








26451
26452
26453
26454
26455
26456
26457







-
-
-
-
-
-
-
-







      unixModeBit(pFile, UNIXFILE_PSOW, (int*)pArg);
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_VFSNAME: {
      *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName);
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_TEMPFILENAME: {
      char *zTFile = sqlite3_malloc( pFile->pVfs->mxPathname );
      if( zTFile ){
        unixGetTempname(pFile->pVfs->mxPathname, zTFile);
        *(char**)pArg = zTFile;
      }
      return SQLITE_OK;
    }
#ifdef SQLITE_DEBUG
    /* The pager calls this method to signal that it has done
    ** a rollback and that the database is therefore unchanged and
    ** it hence it is OK for the transaction change counter to be
    ** unchanged.
    */
    case SQLITE_FCNTL_DB_UNCHANGED: {
26536
26537
26538
26539
26540
26541
26542
26543
26544
26545


26546
26547
26548
26549
26550
26551
26552
26553
26554
26555
26556
26557
26558
26559
26560
26561
26562
26563
26564
26565
26566
26567
26568
26569
26570
26571
26572
26573
26574
26575
26576
26577
26578
26579
26580
26581
26582
26583
26584
26585
26586
26587
26588
26589
26590
26591
26592
26593
26594
26595
26596
26597
26598
26599
26600
26601
26602
26603
26604
26605
26606
26607
26608
26609
26610
26611
26612
26613
26614
26615
26616
26617
26618
26619
26620
26621
26622
26623
26624
26625
26626
26627
26628
26629
26630
26631
26632
26633
26634
26635
26636
26637
26638
26639
26640
26641
26642
26643
26644
26645
26646
26647
26648
26649
26650
26651
26652
26653




26654
26655
26656
26657
26658
26659
26660
26475
26476
26477
26478
26479
26480
26481



26482
26483
26484
26485

















































































26486
26487
26488
26489
26490
26491
26492
26493
26494
26495
26496
26497
26498
26499
26500
26501





26502



26503
26504
26505
26506
26507
26508
26509
26510
26511
26512
26513







-
-
-
+
+


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
















-
-
-
-
-

-
-
-
+
+
+
+







** larger for some devices.
**
** SQLite code assumes this function cannot fail. It also assumes that
** if two files are created in the same file-system directory (i.e.
** a database and its journal file) that the sector size will be the
** same for both.
*/
#ifndef __QNXNTO__ 
static int unixSectorSize(sqlite3_file *NotUsed){
  UNUSED_PARAMETER(NotUsed);
static int unixSectorSize(sqlite3_file *pFile){
  (void)pFile;
  return SQLITE_DEFAULT_SECTOR_SIZE;
}
#endif

/*
** The following version of unixSectorSize() is optimized for QNX.
*/
#ifdef __QNXNTO__
#include <sys/dcmd_blk.h>
#include <sys/statvfs.h>
static int unixSectorSize(sqlite3_file *id){
  unixFile *pFile = (unixFile*)id;
  if( pFile->sectorSize == 0 ){
    struct statvfs fsInfo;
       
    /* Set defaults for non-supported filesystems */
    pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
    pFile->deviceCharacteristics = 0;
    if( fstatvfs(pFile->h, &fsInfo) == -1 ) {
      return pFile->sectorSize;
    }

    if( !strcmp(fsInfo.f_basetype, "tmp") ) {
      pFile->sectorSize = fsInfo.f_bsize;
      pFile->deviceCharacteristics =
        SQLITE_IOCAP_ATOMIC4K |       /* All ram filesystem writes are atomic */
        SQLITE_IOCAP_SAFE_APPEND |    /* growing the file does not occur until
                                      ** the write succeeds */
        SQLITE_IOCAP_SEQUENTIAL |     /* The ram filesystem has no write behind
                                      ** so it is ordered */
        0;
    }else if( strstr(fsInfo.f_basetype, "etfs") ){
      pFile->sectorSize = fsInfo.f_bsize;
      pFile->deviceCharacteristics =
        /* etfs cluster size writes are atomic */
        (pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) |
        SQLITE_IOCAP_SAFE_APPEND |    /* growing the file does not occur until
                                      ** the write succeeds */
        SQLITE_IOCAP_SEQUENTIAL |     /* The ram filesystem has no write behind
                                      ** so it is ordered */
        0;
    }else if( !strcmp(fsInfo.f_basetype, "qnx6") ){
      pFile->sectorSize = fsInfo.f_bsize;
      pFile->deviceCharacteristics =
        SQLITE_IOCAP_ATOMIC |         /* All filesystem writes are atomic */
        SQLITE_IOCAP_SAFE_APPEND |    /* growing the file does not occur until
                                      ** the write succeeds */
        SQLITE_IOCAP_SEQUENTIAL |     /* The ram filesystem has no write behind
                                      ** so it is ordered */
        0;
    }else if( !strcmp(fsInfo.f_basetype, "qnx4") ){
      pFile->sectorSize = fsInfo.f_bsize;
      pFile->deviceCharacteristics =
        /* full bitset of atomics from max sector size and smaller */
        ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
        SQLITE_IOCAP_SEQUENTIAL |     /* The ram filesystem has no write behind
                                      ** so it is ordered */
        0;
    }else if( strstr(fsInfo.f_basetype, "dos") ){
      pFile->sectorSize = fsInfo.f_bsize;
      pFile->deviceCharacteristics =
        /* full bitset of atomics from max sector size and smaller */
        ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
        SQLITE_IOCAP_SEQUENTIAL |     /* The ram filesystem has no write behind
                                      ** so it is ordered */
        0;
    }else{
      pFile->deviceCharacteristics =
        SQLITE_IOCAP_ATOMIC512 |      /* blocks are atomic */
        SQLITE_IOCAP_SAFE_APPEND |    /* growing the file does not occur until
                                      ** the write succeeds */
        0;
    }
  }
  /* Last chance verification.  If the sector size isn't a multiple of 512
  ** then it isn't valid.*/
  if( pFile->sectorSize % 512 != 0 ){
    pFile->deviceCharacteristics = 0;
    pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
  }
  return pFile->sectorSize;
}
#endif /* __QNXNTO__ */

/*
** Return the device characteristics for the file.
**
** This VFS is set up to return SQLITE_IOCAP_POWERSAFE_OVERWRITE by default.
** However, that choice is contraversial since technically the underlying
** file system does not always provide powersafe overwrites.  (In other
** words, after a power-loss event, parts of the file that were never
** written might end up being altered.)  However, non-PSOW behavior is very,
** very rare.  And asserting PSOW makes a large reduction in the amount
** of required I/O for journaling, since a lot of padding is eliminated.
**  Hence, while POWERSAFE_OVERWRITE is on by default, there is a file-control
** available to turn it off and URI query parameter available to turn it off.
*/
static int unixDeviceCharacteristics(sqlite3_file *id){
  unixFile *p = (unixFile*)id;
  int rc = 0;
#ifdef __QNXNTO__
  if( p->sectorSize==0 ) unixSectorSize(id);
  rc = p->deviceCharacteristics;
#endif
  if( p->ctrlFlags & UNIXFILE_PSOW ){
    rc |= SQLITE_IOCAP_POWERSAFE_OVERWRITE;
  }
  return rc;
    return SQLITE_IOCAP_POWERSAFE_OVERWRITE;
  }else{
    return 0;
  }
}

#ifndef SQLITE_OMIT_WAL


/*
** Object used to represent an shared memory buffer.  
27062
27063
27064
27065
27066
27067
27068
27069
27070
27071
27072
27073
27074
27075
27076
27077
27078
27079
27080
27081
27082
27083
27084
27085
27086
27087
27088
26915
26916
26917
26918
26919
26920
26921







26922
26923
26924
26925
26926

26927
26928
26929
26930
26931
26932
26933







-
-
-
-
-
-
-





-







        /* The requested memory region does not exist. If bExtend is set to
        ** false, exit early. *pp will be set to NULL and SQLITE_OK returned.
        **
        ** Alternatively, if bExtend is true, use ftruncate() to allocate
        ** the requested memory region.
        */
        if( !bExtend ) goto shmpage_out;
#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
        if( osFallocate(pShmNode->h, sStat.st_size, nByte)!=0 ){
          rc = unixLogError(SQLITE_IOERR_SHMSIZE, "fallocate",
                            pShmNode->zFilename);
          goto shmpage_out;
        }
#else
        if( robust_ftruncate(pShmNode->h, nByte) ){
          rc = unixLogError(SQLITE_IOERR_SHMSIZE, "ftruncate",
                            pShmNode->zFilename);
          goto shmpage_out;
        }
#endif
      }
    }

    /* Map the requested memory region into this processes address space. */
    apNew = (char **)sqlite3_realloc(
        pShmNode->apRegion, (iRegion+1)*sizeof(char *)
    );
28276
28277
28278
28279
28280
28281
28282
28283

28284
28285
28286
28287

28288
28289
28290
28291
28292
28293
28294
28295
28296
28121
28122
28123
28124
28125
28126
28127

28128




28129


28130
28131
28132
28133
28134
28135
28136







-
+
-
-
-
-
+
-
-







  sqlite3_vfs *NotUsed,     /* VFS containing this as the xDelete method */
  const char *zPath,        /* Name of file to be deleted */
  int dirSync               /* If true, fsync() directory after deleting file */
){
  int rc = SQLITE_OK;
  UNUSED_PARAMETER(NotUsed);
  SimulateIOError(return SQLITE_IOERR_DELETE);
  if( osUnlink(zPath)==(-1) ){
  if( osUnlink(zPath)==(-1) && errno!=ENOENT ){
    if( errno==ENOENT ){
      rc = SQLITE_IOERR_DELETE_NOENT;
    }else{
      rc = unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
    return unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
    }
    return rc;
  }
#ifndef SQLITE_DISABLE_DIRSYNC
  if( (dirSync & 1)!=0 ){
    int fd;
    rc = osOpenDirectory(zPath, &fd);
    if( rc==SQLITE_OK ){
#if OS_VXWORKS
29870
29871
29872
29873
29874
29875
29876
29877

29878
29879
29880
29881
29882
29883
29884
29710
29711
29712
29713
29714
29715
29716

29717
29718
29719
29720
29721
29722
29723
29724







-
+







    UNIXVFS("unix-proxy",    proxyIoFinder ),
#endif
  };
  unsigned int i;          /* Loop counter */

  /* Double-check that the aSyscall[] array has been constructed
  ** correctly.  See ticket [bb3a86e890c8e96ab] */
  assert( ArraySize(aSyscall)==21 );
  assert( ArraySize(aSyscall)==22 );

  /* Register all VFSes defined in the aVfs[] array */
  for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
    sqlite3_vfs_register(&aVfs[i], i==0);
  }
  return SQLITE_OK; 
}
32295
32296
32297
32298
32299
32300
32301
32302
32303

32304
32305
32306
32307
32308
32309
32310
32135
32136
32137
32138
32139
32140
32141


32142
32143
32144
32145
32146
32147
32148
32149







-
-
+







      if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){
#else
      if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){
#endif
        if( retryIoerr(&nRetry, &lastErrno) ) continue;
        break;
      }
      assert( nWrite==0 || nWrite<=(DWORD)nRem );
      if( nWrite==0 || nWrite>(DWORD)nRem ){
      if( nWrite<=0 ){
        lastErrno = osGetLastError();
        break;
      }
#if !SQLITE_OS_WINCE
      offset += nWrite;
      overlapped.Offset = (LONG)(offset & 0xffffffff);
      overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
32794
32795
32796
32797
32798
32799
32800
32801
32802
32803
32804
32805
32806
32807
32808
32809
32810
32633
32634
32635
32636
32637
32638
32639



32640
32641
32642
32643
32644
32645
32646







-
-
-







  }else if( (*pArg)==0 ){
    pFile->ctrlFlags &= ~mask;
  }else{
    pFile->ctrlFlags |= mask;
  }
}

/* Forward declaration */
static int getTempname(int nBuf, char *zBuf);

/*
** Control and query of the open file handle.
*/
static int winFileControl(sqlite3_file *id, int op, void *pArg){
  winFile *pFile = (winFile*)id;
  switch( op ){
    case SQLITE_FCNTL_LOCKSTATE: {
32855
32856
32857
32858
32859
32860
32861
32862
32863
32864
32865
32866
32867
32868
32869
32870
32871
32872
32873
32874
32875
32876
32691
32692
32693
32694
32695
32696
32697








32698
32699
32700
32701
32702
32703
32704







-
-
-
-
-
-
-
-







        a[0] = win32IoerrRetry;
      }
      if( a[1]>0 ){
        win32IoerrRetryDelay = a[1];
      }else{
        a[1] = win32IoerrRetryDelay;
      }
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_TEMPFILENAME: {
      char *zTFile = sqlite3_malloc( pFile->pVfs->mxPathname );
      if( zTFile ){
        getTempname(pFile->pVfs->mxPathname, zTFile);
        *(char**)pArg = zTFile;
      }
      return SQLITE_OK;
    }
  }
  return SQLITE_NOTFOUND;
}

/*
34002
34003
34004
34005
34006
34007
34008
34009
34010
34011
34012
34013

34014
34015
34016
34017
34018
34019
34020
34021
34022
34023
34024
34025

34026
34027
34028
34029
34030
34031
34032
34033
33830
33831
33832
33833
33834
33835
33836





33837

33838
33839
33840
33841
33842
33843





33844

33845
33846
33847
33848
33849
33850
33851







-
-
-
-
-
+
-






-
-
-
-
-
+
-







#if SQLITE_OS_WINRT
      WIN32_FILE_ATTRIBUTE_DATA sAttrData;
      memset(&sAttrData, 0, sizeof(sAttrData));
      if ( osGetFileAttributesExW(zConverted, GetFileExInfoStandard,
                                  &sAttrData) ){
        attr = sAttrData.dwFileAttributes;
      }else{
        lastErrno = osGetLastError();
        if( lastErrno==ERROR_FILE_NOT_FOUND || lastErrno==ERROR_PATH_NOT_FOUND ){
          rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
        }else{
          rc = SQLITE_ERROR;
        rc = SQLITE_OK; /* Already gone? */
        }
        break;
      }
#else
      attr = osGetFileAttributesW(zConverted);
#endif
      if ( attr==INVALID_FILE_ATTRIBUTES ){
        lastErrno = osGetLastError();
        if( lastErrno==ERROR_FILE_NOT_FOUND || lastErrno==ERROR_PATH_NOT_FOUND ){
          rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
        }else{
          rc = SQLITE_ERROR;
        rc = SQLITE_OK; /* Already gone? */
        }
        break;
      }
      if ( attr&FILE_ATTRIBUTE_DIRECTORY ){
        rc = SQLITE_ERROR; /* Files only. */
        break;
      }
      if ( osDeleteFileW(zConverted) ){
34041
34042
34043
34044
34045
34046
34047
34048
34049
34050
34051
34052

34053
34054
34055
34056
34057
34058
34059
34060
34061
34062
34063
34064
34065
34066
34067
34068
34069
34070
34071

34072
34073
34074
34075
34076
34077
34078
33859
33860
33861
33862
33863
33864
33865





33866

33867
33868
33869
33870
33871
33872
33873
33874
33875
33876
33877
33878
33879
33880
33881
33882
33883

33884
33885
33886
33887
33888
33889
33890
33891







-
-
-
-
-
+
-

















-
+







    } while(1);
  }
#ifdef SQLITE_WIN32_HAS_ANSI
  else{
    do {
      attr = osGetFileAttributesA(zConverted);
      if ( attr==INVALID_FILE_ATTRIBUTES ){
        lastErrno = osGetLastError();
        if( lastErrno==ERROR_FILE_NOT_FOUND || lastErrno==ERROR_PATH_NOT_FOUND ){
          rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
        }else{
          rc = SQLITE_ERROR;
        rc = SQLITE_OK; /* Already gone? */
        }
        break;
      }
      if ( attr&FILE_ATTRIBUTE_DIRECTORY ){
        rc = SQLITE_ERROR; /* Files only. */
        break;
      }
      if ( osDeleteFileA(zConverted) ){
        rc = SQLITE_OK; /* Deleted OK. */
        break;
      }
      if ( !retryIoerr(&cnt, &lastErrno) ){
        rc = SQLITE_ERROR; /* No more retries. */
        break;
      }
    } while(1);
  }
#endif
  if( rc && rc!=SQLITE_IOERR_DELETE_NOENT ){
  if( rc ){
    rc = winLogError(SQLITE_IOERR_DELETE, lastErrno,
             "winDelete", zFilename);
  }else{
    logIoerr(cnt);
  }
  sqlite3_free(zConverted);
  OSTRACE(("DELETE \"%s\" %s\n", zFilename, (rc ? "failed" : "ok" )));
39258
39259
39260
39261
39262
39263
39264
39265
39266
39267
39268
39269
39270
39271

39272
39273
39274
39275
39276
39277
39278
39071
39072
39073
39074
39075
39076
39077

39078
39079
39080
39081
39082

39083
39084
39085
39086
39087
39088
39089
39090







-





-
+







      pPager->journalOff = 0;
    }else{
      /* This branch may be executed with Pager.journalMode==MEMORY if
      ** a hot-journal was just rolled back. In this case the journal
      ** file should be closed and deleted. If this connection writes to
      ** the database file, it will do so using an in-memory journal. 
      */
      int bDelete = (!pPager->tempFile && sqlite3JournalExists(pPager->jfd));
      assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE 
           || pPager->journalMode==PAGER_JOURNALMODE_MEMORY 
           || pPager->journalMode==PAGER_JOURNALMODE_WAL 
      );
      sqlite3OsClose(pPager->jfd);
      if( bDelete ){
      if( !pPager->tempFile ){
        rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
      }
    }
  }

#ifdef SQLITE_CHECK_PAGES
  sqlite3PcacheIterateDirty(pPager->pPCache, pager_set_pagehash);
40477
40478
40479
40480
40481
40482
40483
40484
40485
40486
40487
40488
40489
40490
40491
40289
40290
40291
40292
40293
40294
40295

40296
40297
40298
40299
40300
40301
40302







-







    int isWal;                    /* True if WAL file exists */
    Pgno nPage;                   /* Size of the database file */

    rc = pagerPagecount(pPager, &nPage);
    if( rc ) return rc;
    if( nPage==0 ){
      rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0);
      if( rc==SQLITE_IOERR_DELETE_NOENT ) rc = SQLITE_OK;
      isWal = 0;
    }else{
      rc = sqlite3OsAccess(
          pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal
      );
    }
    if( rc==SQLITE_OK ){
40803
40804
40805
40806
40807
40808
40809
40810

40811
40812
40813
40814
40815
40816
40817
40614
40615
40616
40617
40618
40619
40620

40621
40622
40623
40624
40625
40626
40627
40628







-
+







  pPager->xBusyHandler = xBusyHandler;
  pPager->pBusyHandlerArg = pBusyHandlerArg;

  if( isOpen(pPager->fd) ){
    void **ap = (void **)&pPager->xBusyHandler;
    assert( ((int(*)(void *))(ap[0]))==xBusyHandler );
    assert( ap[1]==pBusyHandlerArg );
    sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_BUSYHANDLER, (void *)ap);
    sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_BUSYHANDLER, (void *)ap);
  }
}

/*
** Change the page size used by the Pager object. The new page size 
** is passed in *pPageSize.
**
42984
42985
42986
42987
42988
42989
42990
42991

42992
42993
42994
42995
42996
42997
42998
42795
42796
42797
42798
42799
42800
42801

42802
42803
42804
42805
42806
42807
42808
42809







-
+







# define DIRECT_MODE 0
  assert( isDirectMode==0 );
  UNUSED_PARAMETER(isDirectMode);
#else
# define DIRECT_MODE isDirectMode
#endif

  if( !pPager->changeCountDone && ALWAYS(pPager->dbSize>0) ){
  if( !pPager->changeCountDone && pPager->dbSize>0 ){
    PgHdr *pPgHdr;                /* Reference to page 1 */

    assert( !pPager->tempFile && isOpen(pPager->fd) );

    /* Open page 1 of the file for writing. */
    rc = sqlite3PagerGet(pPager, 1, &pPgHdr);
    assert( pPgHdr==0 || rc==SQLITE_OK );
43204
43205
43206
43207
43208
43209
43210
43211

43212
43213
43214
43215
43216
43217
43218

43219
43220
43221
43222
43223
43224
43225
43226
43227
43228
43229
43230
43231
43232
43233
43234
43235
43236
43237

43238
43239
43240
43241
43242
43243
43244
43015
43016
43017
43018
43019
43020
43021

43022
43023
43024
43025
43026
43027
43028
43029
43030
43031
43032
43033
43034
43035
43036
43037
43038
43039
43040
43041
43042
43043
43044
43045
43046
43047
43048
43049
43050
43051
43052
43053
43054
43055
43056
43057







-
+







+



















+







  #else
      rc = pager_incr_changecounter(pPager, 0);
  #endif
      if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
  
      /* If this transaction has made the database smaller, then all pages
      ** being discarded by the truncation must be written to the journal
      ** file.
      ** file. This can only happen in auto-vacuum mode.
      **
      ** Before reading the pages with page numbers larger than the 
      ** current value of Pager.dbSize, set dbSize back to the value
      ** that it took at the start of the transaction. Otherwise, the
      ** calls to sqlite3PagerGet() return zeroed pages instead of 
      ** reading data from the database file.
      */
  #ifndef SQLITE_OMIT_AUTOVACUUM
      if( pPager->dbSize<pPager->dbOrigSize 
       && pPager->journalMode!=PAGER_JOURNALMODE_OFF
      ){
        Pgno i;                                   /* Iterator variable */
        const Pgno iSkip = PAGER_MJ_PGNO(pPager); /* Pending lock page */
        const Pgno dbSize = pPager->dbSize;       /* Database image size */ 
        pPager->dbSize = pPager->dbOrigSize;
        for( i=dbSize+1; i<=pPager->dbOrigSize; i++ ){
          if( !sqlite3BitvecTest(pPager->pInJournal, i) && i!=iSkip ){
            PgHdr *pPage;             /* Page to journal */
            rc = sqlite3PagerGet(pPager, i, &pPage);
            if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
            rc = sqlite3PagerWrite(pPage);
            sqlite3PagerUnref(pPage);
            if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
          }
        }
        pPager->dbSize = dbSize;
      } 
  #endif
  
      /* Write the master journal name into the journal file. If a master 
      ** journal file name has already been written to the journal file, 
      ** or if zMaster is NULL (no master journal), then this call is a no-op.
      */
      rc = writeMasterJournal(pPager, zMaster);
      if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
46787
46788
46789
46790
46791
46792
46793
46794

46795
46796
46797
46798
46799
46800
46801
46600
46601
46602
46603
46604
46605
46606

46607
46608
46609
46610
46611
46612
46613
46614







-
+







      ** are no outstanding references to any page other than page 1. And
      ** page 1 is never written to the log until the transaction is
      ** committed. As a result, the call to xUndo may not fail.
      */
      assert( walFramePgno(pWal, iFrame)!=1 );
      rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame));
    }
    if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal);
    walCleanupHash(pWal);
  }
  assert( rc==SQLITE_OK );
  return rc;
}

/* 
** Argument aWalData must point to an array of WAL_SAVEPOINT_NDATA u32 
50841
50842
50843
50844
50845
50846
50847
50848
50849
50850
50851
50852
50853
50854
50855
50856
50857
50858
50859
50860
50861
50862
50863
50864
50865
50866
50867
50868
50654
50655
50656
50657
50658
50659
50660














50661
50662
50663
50664
50665
50666
50667







-
-
-
-
-
-
-
-
-
-
-
-
-
-







  put4byte(&data[36 + 7*4], pBt->incrVacuum);
#endif
  pBt->nPage = 1;
  data[31] = 1;
  return SQLITE_OK;
}

/*
** Initialize the first page of the database file (creating a database
** consisting of a single page and no schema objects). Return SQLITE_OK
** if successful, or an SQLite error code otherwise.
*/
SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p){
  int rc;
  sqlite3BtreeEnter(p);
  p->pBt->nPage = 0;
  rc = newDatabase(p->pBt);
  sqlite3BtreeLeave(p);
  return rc;
}

/*
** Attempt to start a new transaction. A write-transaction
** is started if the second argument is nonzero, otherwise a read-
** transaction.  If the second argument is 2 or more and exclusive
** transaction is started, meaning that no other process is allowed
** to access the database.  A preexisting transaction may not be
** upgraded to exclusive by calling this routine a second time - the
54054
54055
54056
54057
54058
54059
54060
54061

54062
54063
54064
54065
54066
54067
54068
53853
53854
53855
53856
53857
53858
53859

53860
53861
53862
53863
53864
53865
53866
53867







-
+







  Pgno pgnoNew;                        /* Page number of pNew */

  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  assert( sqlite3PagerIswriteable(pParent->pDbPage) );
  assert( pPage->nOverflow==1 );

  /* This error condition is now caught prior to reaching this function */
  if( pPage->nCell==0 ) return SQLITE_CORRUPT_BKPT;
  if( pPage->nCell<=0 ) return SQLITE_CORRUPT_BKPT;

  /* Allocate a new page. This page will become the right-sibling of 
  ** pPage. Make the parent page writable, so that the new divider cell
  ** may be inserted. If both these operations are successful, proceed.
  */
  rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0);

56336
56337
56338
56339
56340
56341
56342
56343

56344
56345
56346
56347
56348
56349
56350
56135
56136
56137
56138
56139
56140
56141

56142
56143
56144
56145
56146
56147
56148
56149







-
+







  if( !sCheck.aPgRef ){
    *pnErr = 1;
    sqlite3BtreeLeave(p);
    return 0;
  }
  i = PENDING_BYTE_PAGE(pBt);
  if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i);
  sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), SQLITE_MAX_LENGTH);
  sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), 20000);
  sCheck.errMsg.useMalloc = 2;

  /* Check the integrity of the freelist
  */
  checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]),
            get4byte(&pBt->pPage1->aData[36]), "Main freelist: ");

56871
56872
56873
56874
56875
56876
56877
56878

56879
56880
56881
56882
56883
56884
56885
56886
56887
56888
56889
56890
56670
56671
56672
56673
56674
56675
56676

56677





56678
56679
56680
56681
56682
56683
56684







-
+
-
-
-
-
-







}

/*
** Parameter zSrcData points to a buffer containing the data for 
** page iSrcPg from the source database. Copy this data into the 
** destination database.
*/
static int backupOnePage(
static int backupOnePage(sqlite3_backup *p, Pgno iSrcPg, const u8 *zSrcData){
  sqlite3_backup *p,              /* Backup handle */
  Pgno iSrcPg,                    /* Source database page to backup */
  const u8 *zSrcData,             /* Source database page data */
  int bUpdate                     /* True for an update, false otherwise */
){
  Pager * const pDestPager = sqlite3BtreePager(p->pDest);
  const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc);
  int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest);
  const int nCopy = MIN(nSrcPgsz, nDestPgsz);
  const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz;
#ifdef SQLITE_HAS_CODEC
  /* Use BtreeGetReserveNoMutex() for the source b-tree, as although it is
56949
56950
56951
56952
56953
56954
56955
56956
56957
56958
56959
56960
56961
56962
56963
56964
56965
56743
56744
56745
56746
56747
56748
56749



56750
56751
56752
56753
56754
56755
56756







-
-
-







      ** and the pager code use this trick (clearing the first byte
      ** of the page 'extra' space to invalidate the Btree layers
      ** cached parse of the page). MemPage.isInit is marked 
      ** "MUST BE FIRST" for this purpose.
      */
      memcpy(zOut, zIn, nCopy);
      ((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0;
      if( iOff==0 && bUpdate==0 ){
        sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(p->pSrc));
      }
    }
    sqlite3PagerUnref(pDestPg);
  }

  return rc;
}

57058
57059
57060
57061
57062
57063
57064
57065

57066
57067
57068
57069
57070
57071
57072
56849
56850
56851
56852
56853
56854
56855

56856
56857
56858
56859
56860
56861
56862
56863







-
+







    assert( nSrcPage>=0 );
    for(ii=0; (nPage<0 || ii<nPage) && p->iNext<=(Pgno)nSrcPage && !rc; ii++){
      const Pgno iSrcPg = p->iNext;                 /* Source page number */
      if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){
        DbPage *pSrcPg;                             /* Source page object */
        rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg);
        if( rc==SQLITE_OK ){
          rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0);
          rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg));
          sqlite3PagerUnref(pSrcPg);
        }
      }
      p->iNext++;
    }
    if( rc==SQLITE_OK ){
      p->nPagecount = nSrcPage;
57080
57081
57082
57083
57084
57085
57086
57087
57088
57089
57090
57091
57092

57093
57094
57095
57096
57097
57098
57099
57100
56871
56872
56873
56874
56875
56876
56877






56878

56879
56880
56881
56882
56883
56884
56885







-
-
-
-
-
-
+
-







  
    /* Update the schema version field in the destination database. This
    ** is to make sure that the schema-version really does change in
    ** the case where the source and destination databases have the
    ** same schema version.
    */
    if( rc==SQLITE_DONE ){
      if( nSrcPage==0 ){
        rc = sqlite3BtreeNewDb(p->pDest);
        nSrcPage = 1;
      }
      if( rc==SQLITE_OK || rc==SQLITE_DONE ){
        rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1);
      rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1);
      }
      if( rc==SQLITE_OK ){
        if( p->pDestDb ){
          sqlite3ResetAllSchemasOfConnection(p->pDestDb);
        }
        if( destMode==PAGER_JOURNALMODE_WAL ){
          rc = sqlite3BtreeSetVersion(p->pDest, 2);
        }
57120
57121
57122
57123
57124
57125
57126
57127
57128
57129
57130
57131
57132
57133
57134
57135
57136
57137
57138
57139
57140
57141
57142
57143
57144
57145
57146
57147

57148
57149
57150
57151
57152
57153
57154
56905
56906
56907
56908
56909
56910
56911

56912
56913
56914
56915
56916
56917
56918
56919
56920
56921
56922
56923
56924
56925
56926
56927
56928
56929


56930
56931
56932
56933
56934
56935
56936
56937







-


















-
-
+







          nDestTruncate = (nSrcPage+ratio-1)/ratio;
          if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){
            nDestTruncate--;
          }
        }else{
          nDestTruncate = nSrcPage * (pgszSrc/pgszDest);
        }
        assert( nDestTruncate>0 );
        sqlite3PagerTruncateImage(pDestPager, nDestTruncate);

        if( pgszSrc<pgszDest ){
          /* If the source page-size is smaller than the destination page-size,
          ** two extra things may need to happen:
          **
          **   * The destination may need to be truncated, and
          **
          **   * Data stored on the pages immediately following the 
          **     pending-byte page in the source database may need to be
          **     copied into the destination database.
          */
          const i64 iSize = (i64)pgszSrc * (i64)nSrcPage;
          sqlite3_file * const pFile = sqlite3PagerFile(pDestPager);
          i64 iOff;
          i64 iEnd;

          assert( pFile );
          assert( nDestTruncate==0 
              || (i64)nDestTruncate*(i64)pgszDest >= iSize || (
          assert( (i64)nDestTruncate*(i64)pgszDest >= iSize || (
                nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1)
             && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest
          ));

          /* This call ensures that all data required to recreate the original
          ** database has been stored in the journal for pDestPager and the
          ** journal synced to disk. So at this point we may safely modify
57306
57307
57308
57309
57310
57311
57312
57313

57314
57315
57316
57317
57318
57319
57320
57089
57090
57091
57092
57093
57094
57095

57096
57097
57098
57099
57100
57101
57102
57103







-
+







      /* The backup process p has already copied page iPage. But now it
      ** has been modified by a transaction on the source pager. Copy
      ** the new data into the backup.
      */
      int rc;
      assert( p->pDestDb );
      sqlite3_mutex_enter(p->pDestDb->mutex);
      rc = backupOnePage(p, iPage, aData, 1);
      rc = backupOnePage(p, iPage, aData);
      sqlite3_mutex_leave(p->pDestDb->mutex);
      assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED );
      if( rc!=SQLITE_OK ){
        p->rc = rc;
      }
    }
  }
58610
58611
58612
58613
58614
58615
58616
58617

58618
58619
58620
58621
58622
58623
58624
58393
58394
58395
58396
58397
58398
58399

58400
58401
58402
58403
58404
58405
58406
58407







-
+








/*
** Remember the SQL string for a prepared statement.
*/
SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepareV2){
  assert( isPrepareV2==1 || isPrepareV2==0 );
  if( p==0 ) return;
#if defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_ENABLE_SQLLOG)
#ifdef SQLITE_OMIT_TRACE
  if( !isPrepareV2 ) return;
#endif
  assert( p->zSql==0 );
  p->zSql = sqlite3DbStrNDup(p->db, z, n);
  p->isPrepareV2 = (u8)isPrepareV2;
}

59280
59281
59282
59283
59284
59285
59286
59287
59288
59289
59290
59291
59292
59293
59294
59063
59064
59065
59066
59067
59068
59069

59070
59071
59072
59073
59074
59075
59076







-







  }
  assert( p->nOp>0 );
  assert( addr<p->nOp );
  if( addr<0 ){
    addr = p->nOp - 1;
  }
  pOp = &p->aOp[addr];
  assert( pOp->p4type==P4_NOTUSED || pOp->p4type==P4_INT32 );
  freeP4(db, pOp->p4type, pOp->p4.p);
  pOp->p4.p = 0;
  if( n==P4_INT32 ){
    /* Note: this cast is safe, because the origin data point was an int
    ** that was cast to a (const char *). */
    pOp->p4.i = SQLITE_PTR_TO_INT(zP4);
    pOp->p4type = P4_INT32;
59423
59424
59425
59426
59427
59428
59429
59430
59431
59432
59433
59434
59435
59436
59437
59438
59439
59440
59441
















59442
59443
59444
59445
59446
59447
59448
59205
59206
59207
59208
59209
59210
59211












59212
59213
59214
59215
59216
59217
59218
59219
59220
59221
59222
59223
59224
59225
59226
59227
59228
59229
59230
59231
59232
59233
59234







-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







      int i, j;
      KeyInfo *pKeyInfo = pOp->p4.pKeyInfo;
      assert( pKeyInfo->aSortOrder!=0 );
      sqlite3_snprintf(nTemp, zTemp, "keyinfo(%d", pKeyInfo->nField);
      i = sqlite3Strlen30(zTemp);
      for(j=0; j<pKeyInfo->nField; j++){
        CollSeq *pColl = pKeyInfo->aColl[j];
        const char *zColl = pColl ? pColl->zName : "nil";
        int n = sqlite3Strlen30(zColl);
        if( i+n>nTemp-6 ){
          memcpy(&zTemp[i],",...",4);
          break;
        }
        zTemp[i++] = ',';
        if( pKeyInfo->aSortOrder[j] ){
          zTemp[i++] = '-';
        }
        memcpy(&zTemp[i], zColl, n+1);
        i += n;
        if( pColl ){
          int n = sqlite3Strlen30(pColl->zName);
          if( i+n>nTemp-6 ){
            memcpy(&zTemp[i],",...",4);
            break;
          }
          zTemp[i++] = ',';
          if( pKeyInfo->aSortOrder[j] ){
            zTemp[i++] = '-';
          }
          memcpy(&zTemp[i], pColl->zName,n+1);
          i += n;
        }else if( i+4<nTemp-6 ){
          memcpy(&zTemp[i],",nil",4);
          i += 4;
        }
      }
      zTemp[i++] = ')';
      zTemp[i] = 0;
      assert( i<nTemp );
      break;
    }
    case P4_COLLSEQ: {
60880
60881
60882
60883
60884
60885
60886
60887
60888
60889
60890
60891
60892
60893
60894
60895
60896
60897
60898
60899
60900
60901
60902
60903
60904
60905
60906
60907
60908
60909
60910
60911
60912
60913
60914
60666
60667
60668
60669
60670
60671
60672





















60673
60674
60675
60676
60677
60678
60679







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







    db->errCode = rc;
  }else{
    sqlite3Error(db, rc, 0);
  }
  return rc;
}

#ifdef SQLITE_ENABLE_SQLLOG
/*
** If an SQLITE_CONFIG_SQLLOG hook is registered and the VM has been run, 
** invoke it.
*/
static void vdbeInvokeSqllog(Vdbe *v){
  if( sqlite3GlobalConfig.xSqllog && v->rc==SQLITE_OK && v->zSql && v->pc>=0 ){
    char *zExpanded = sqlite3VdbeExpandSql(v, v->zSql);
    assert( v->db->init.busy==0 );
    if( zExpanded ){
      sqlite3GlobalConfig.xSqllog(
          sqlite3GlobalConfig.pSqllogArg, v->db, zExpanded, 1
      );
      sqlite3DbFree(v->db, zExpanded);
    }
  }
}
#else
# define vdbeInvokeSqllog(x)
#endif

/*
** Clean up a VDBE after execution but do not delete the VDBE just yet.
** Write any error messages into *pzErrMsg.  Return the result code.
**
** After this routine is run, the VDBE should be ready to be executed
** again.
**
60928
60929
60930
60931
60932
60933
60934
60935
60936
60937
60938
60939
60940
60941
60942
60693
60694
60695
60696
60697
60698
60699

60700
60701
60702
60703
60704
60705
60706







-








  /* If the VDBE has be run even partially, then transfer the error code
  ** and error message from the VDBE into the main database structure.  But
  ** if the VDBE has just been set to run but has not actually executed any
  ** instructions yet, leave the main database error information unchanged.
  */
  if( p->pc>=0 ){
    vdbeInvokeSqllog(p);
    sqlite3VdbeTransferError(p);
    sqlite3DbFree(db, p->zErrMsg);
    p->zErrMsg = 0;
    if( p->runOnlyOnce ) p->expired = 1;
  }else if( p->rc && p->expired ){
    /* The expired flag was set on the VDBE before the first call
    ** to sqlite3_step(). For consistency (since sqlite3_step() was
61010
61011
61012
61013
61014
61015
61016
61017

61018
61019
61020
61021
61022

61023
61024

61025
61026
61027
61028
61029
61030
61031
61032
61033
61034
61035
61036
61037
61038
61039
61040
61041
61042

61043
61044

61045
61046
61047
61048
61049
61050
61051
61052
61053
61054
61055
61056
61057
61058
61059
61060
61061
61062
61063
61064
61065
61066
61067
61068

61069
61070
61071
61072
61073
61074
61075
60774
60775
60776
60777
60778
60779
60780

60781


60782
60783

60784
60785

60786
60787
60788
60789
60790
60791
60792
60793
60794
60795
60796
60797
60798
60799
60800
60801
60802
60803

60804
60805
60806
60807
60808
60809
60810
60811
60812
60813
60814
60815
60816
60817
60818

60819
60820
60821
60822
60823
60824
60825
60826
60827
60828
60829

60830
60831
60832
60833
60834
60835
60836
60837







-
+
-
-


-
+

-
+

















-
+


+











-











-
+







      }
      pAux->pAux = 0;
    }
  }
}

/*
** Free all memory associated with the Vdbe passed as the second argument,
** Free all memory associated with the Vdbe passed as the second argument.
** except for object itself, which is preserved.
**
** The difference between this function and sqlite3VdbeDelete() is that
** VdbeDelete() also unlinks the Vdbe from the list of VMs associated with
** the database connection and frees the object itself.
** the database connection.
*/
SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
SQLITE_PRIVATE void sqlite3VdbeDeleteObject(sqlite3 *db, Vdbe *p){
  SubProgram *pSub, *pNext;
  int i;
  assert( p->db==0 || p->db==db );
  releaseMemArray(p->aVar, p->nVar);
  releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
  for(pSub=p->pProgram; pSub; pSub=pNext){
    pNext = pSub->pNext;
    vdbeFreeOpArray(db, pSub->aOp, pSub->nOp);
    sqlite3DbFree(db, pSub);
  }
  for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]);
  vdbeFreeOpArray(db, p->aOp, p->nOp);
  sqlite3DbFree(db, p->aLabel);
  sqlite3DbFree(db, p->aColName);
  sqlite3DbFree(db, p->zSql);
  sqlite3DbFree(db, p->pFree);
#if defined(SQLITE_ENABLE_TREE_EXPLAIN)
  sqlite3_free(p->zExplain);
  sqlite3DbFree(db, p->zExplain);
  sqlite3DbFree(db, p->pExplain);
#endif
  sqlite3DbFree(db, p);
}

/*
** Delete an entire VDBE.
*/
SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){
  sqlite3 *db;

  if( NEVER(p==0) ) return;
  db = p->db;
  assert( sqlite3_mutex_held(db->mutex) );
  sqlite3VdbeClearObject(db, p);
  if( p->pPrev ){
    p->pPrev->pNext = p->pNext;
  }else{
    assert( db->pVdbe==p );
    db->pVdbe = p->pNext;
  }
  if( p->pNext ){
    p->pNext->pPrev = p->pPrev;
  }
  p->magic = VDBE_MAGIC_DEAD;
  p->db = 0;
  sqlite3DbFree(db, p);
  sqlite3VdbeDeleteObject(db, p);
}

/*
** Make sure the cursor p is ready to read or write the row to which it
** was last positioned.  Return an error code if an OOM fault or I/O error
** prevents us from positioning the cursor to its correct position.
**
63824
63825
63826
63827
63828
63829
63830
63831

63832
63833
63834
63835
63836
63837
63838
63839
63840
63586
63587
63588
63589
63590
63591
63592

63593


63594
63595
63596
63597
63598
63599
63600







-
+
-
-







#endif

#ifdef SQLITE_DEBUG
/*
** Print the value of a register for tracing purposes:
*/
static void memTracePrint(FILE *out, Mem *p){
  if( p->flags & MEM_Invalid ){
  if( p->flags & MEM_Null ){
    fprintf(out, " undefined");
  }else if( p->flags & MEM_Null ){
    fprintf(out, " NULL");
  }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){
    fprintf(out, " si:%lld", p->u.i);
  }else if( p->flags & MEM_Int ){
    fprintf(out, " i:%lld", p->u.i);
#ifndef SQLITE_OMIT_FLOATING_POINT
  }else if( p->flags & MEM_Real ){
64099
64100
64101
64102
64103
64104
64105
64106
64107
64108
64109
64110
64111
64112
64113
63859
63860
63861
63862
63863
63864
63865

63866
63867
63868
63869
63870
63871
63872







-







      Mem *pMem;
      int i;
    } af;
    struct OP_Concat_stack_vars {
      i64 nByte;
    } ag;
    struct OP_Remainder_stack_vars {
      char bIntint;   /* Started out as two integer operands */
      int flags;      /* Combined MEM_* flags from both inputs */
      i64 iA;         /* Integer value of left operand */
      i64 iB;         /* Integer value of right operand */
      double rA;      /* Real value of left operand */
      double rB;      /* Real value of right operand */
    } ah;
    struct OP_Function_stack_vars {
65009
65010
65011
65012
65013
65014
65015
65016
65017
65018
65019
65020
65021
65022
65023
65024
65025
64768
64769
64770
64771
64772
64773
64774



64775
64776
64777
64778
64779
64780
64781







-
-
-







  u.ae.n = pOp->p3;
  pIn1 = &aMem[pOp->p1];
  pOut = &aMem[pOp->p2];
  assert( pOut!=pIn1 );
  while( 1 ){
    sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
    Deephemeralize(pOut);
#ifdef SQLITE_DEBUG
    pOut->pScopyFrom = 0;
#endif
    REGISTER_TRACE(pOp->p2+pOp->p3-u.ae.n, pOut);
    if( (u.ae.n--)==0 ) break;
    pOut++;
    pIn1++;
  }
  break;
}
65205
65206
65207
65208
65209
65210
65211
65212
65213
65214
65215
65216
65217
65218
65219
65220
65221
65222
65223
65224
65225
65226
65227
65228
65229
65230
65231
65232
65233
65234
65235
65236
65237
65238
65239
65240
65241
65242
65243
65244
65245
65246
65247
65248
65249
65250
65251
65252
65253
65254
65255
65256
65257
65258
64961
64962
64963
64964
64965
64966
64967

64968
64969
64970
64971
64972
64973
64974
64975
64976
64977
64978
64979
64980
64981
64982
64983
64984

64985
64986
64987
64988
64989
64990
64991
64992
64993
64994
64995
64996
64997
64998
64999
65000
65001
65002
65003
65004

65005
65006
65007
65008
65009
65010
65011







-

















-




















-







*/
case OP_Add:                   /* same as TK_PLUS, in1, in2, out3 */
case OP_Subtract:              /* same as TK_MINUS, in1, in2, out3 */
case OP_Multiply:              /* same as TK_STAR, in1, in2, out3 */
case OP_Divide:                /* same as TK_SLASH, in1, in2, out3 */
case OP_Remainder: {           /* same as TK_REM, in1, in2, out3 */
#if 0  /* local variables moved into u.ah */
  char bIntint;   /* Started out as two integer operands */
  int flags;      /* Combined MEM_* flags from both inputs */
  i64 iA;         /* Integer value of left operand */
  i64 iB;         /* Integer value of right operand */
  double rA;      /* Real value of left operand */
  double rB;      /* Real value of right operand */
#endif /* local variables moved into u.ah */

  pIn1 = &aMem[pOp->p1];
  applyNumericAffinity(pIn1);
  pIn2 = &aMem[pOp->p2];
  applyNumericAffinity(pIn2);
  pOut = &aMem[pOp->p3];
  u.ah.flags = pIn1->flags | pIn2->flags;
  if( (u.ah.flags & MEM_Null)!=0 ) goto arithmetic_result_is_null;
  if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){
    u.ah.iA = pIn1->u.i;
    u.ah.iB = pIn2->u.i;
    u.ah.bIntint = 1;
    switch( pOp->opcode ){
      case OP_Add:       if( sqlite3AddInt64(&u.ah.iB,u.ah.iA) ) goto fp_math;  break;
      case OP_Subtract:  if( sqlite3SubInt64(&u.ah.iB,u.ah.iA) ) goto fp_math;  break;
      case OP_Multiply:  if( sqlite3MulInt64(&u.ah.iB,u.ah.iA) ) goto fp_math;  break;
      case OP_Divide: {
        if( u.ah.iA==0 ) goto arithmetic_result_is_null;
        if( u.ah.iA==-1 && u.ah.iB==SMALLEST_INT64 ) goto fp_math;
        u.ah.iB /= u.ah.iA;
        break;
      }
      default: {
        if( u.ah.iA==0 ) goto arithmetic_result_is_null;
        if( u.ah.iA==-1 ) u.ah.iA = 1;
        u.ah.iB %= u.ah.iA;
        break;
      }
    }
    pOut->u.i = u.ah.iB;
    MemSetTypeFlag(pOut, MEM_Int);
  }else{
    u.ah.bIntint = 0;
fp_math:
    u.ah.rA = sqlite3VdbeRealValue(pIn1);
    u.ah.rB = sqlite3VdbeRealValue(pIn2);
    switch( pOp->opcode ){
      case OP_Add:         u.ah.rB += u.ah.rA;       break;
      case OP_Subtract:    u.ah.rB -= u.ah.rA;       break;
      case OP_Multiply:    u.ah.rB *= u.ah.rA;       break;
65276
65277
65278
65279
65280
65281
65282
65283

65284
65285
65286
65287
65288
65289
65290
65029
65030
65031
65032
65033
65034
65035

65036
65037
65038
65039
65040
65041
65042
65043







-
+







    MemSetTypeFlag(pOut, MEM_Int);
#else
    if( sqlite3IsNaN(u.ah.rB) ){
      goto arithmetic_result_is_null;
    }
    pOut->r = u.ah.rB;
    MemSetTypeFlag(pOut, MEM_Real);
    if( (u.ah.flags & MEM_Real)==0 && !u.ah.bIntint ){
    if( (u.ah.flags & MEM_Real)==0 ){
      sqlite3VdbeIntegerAffinity(pOut);
    }
#endif
  }
  break;

arithmetic_result_is_null:
65837
65838
65839
65840
65841
65842
65843
65844
65845
65846



65847
65848
65849
65850
65851
65852
65853
65854
65855

65856
65857
65858
65859
65860
65861
65862
65863
65864
65865
65866
65867
65868
65869
65870
65871
65872
65873
65874
65875
65876
65877
65878
65879
65880
65881
65882
65883
65884
65885
65886
65887
65888
65889
65890
65891
65892
65893
65590
65591
65592
65593
65594
65595
65596



65597
65598
65599
65600
65601
65602
65603
65604
65605
65606
65607

65608
65609
65610
65611
65612
65613





65614
65615
65616
65617
65618
65619
65620
65621
65622
65623
65624
65625
65626
65627
65628
65629
65630
65631
65632
65633

65634
65635
65636
65637
65638
65639
65640







-
-
-
+
+
+








-
+





-
-
-
-
-




















-







}

/* Opcode: Permutation * * * P4 *
**
** Set the permutation used by the OP_Compare operator to be the array
** of integers in P4.
**
** The permutation is only valid until the next OP_Compare that has
** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should 
** occur immediately prior to the OP_Compare.
** The permutation is only valid until the next OP_Permutation, OP_Compare,
** OP_Halt, or OP_ResultRow.  Typically the OP_Permutation should occur
** immediately prior to the OP_Compare.
*/
case OP_Permutation: {
  assert( pOp->p4type==P4_INTARRAY );
  assert( pOp->p4.ai );
  aPermute = pOp->p4.ai;
  break;
}

/* Opcode: Compare P1 P2 P3 P4 P5
/* Opcode: Compare P1 P2 P3 P4 *
**
** Compare two vectors of registers in reg(P1)..reg(P1+P3-1) (call this
** vector "A") and in reg(P2)..reg(P2+P3-1) ("B").  Save the result of
** the comparison for use by the next OP_Jump instruct.
**
** If P5 has the OPFLAG_PERMUTE bit set, then the order of comparison is
** determined by the most recent OP_Permutation operator.  If the
** OPFLAG_PERMUTE bit is clear, then register are compared in sequential
** order.
**
** P4 is a KeyInfo structure that defines collating sequences and sort
** orders for the comparison.  The permutation applies to registers
** only.  The KeyInfo elements are used sequentially.
**
** The comparison is a sort comparison, so NULLs compare equal,
** NULLs are less than numbers, numbers are less than strings,
** and strings are less than blobs.
*/
case OP_Compare: {
#if 0  /* local variables moved into u.al */
  int n;
  int i;
  int p1;
  int p2;
  const KeyInfo *pKeyInfo;
  int idx;
  CollSeq *pColl;    /* Collating sequence to use on this term */
  int bRev;          /* True for DESCENDING sort order */
#endif /* local variables moved into u.al */

  if( (pOp->p5 & OPFLAG_PERMUTE)==0 ) aPermute = 0;
  u.al.n = pOp->p3;
  u.al.pKeyInfo = pOp->p4.pKeyInfo;
  assert( u.al.n>0 );
  assert( u.al.pKeyInfo!=0 );
  u.al.p1 = pOp->p1;
  u.al.p2 = pOp->p2;
#if SQLITE_DEBUG
66025
66026
66027
66028
66029
66030
66031


66032
66033
66034
66035
66036
66037
66038
65772
65773
65774
65775
65776
65777
65778
65779
65780
65781
65782
65783
65784
65785
65786
65787







+
+







  break;
}

/* Opcode: Once P1 P2 * * *
**
** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise,
** set the flag and fall through to the next instruction.
**
** See also: JumpOnce
*/
case OP_Once: {             /* jump */
  assert( pOp->p1<p->nOnceFlag );
  if( p->aOnceFlag[pOp->p1] ){
    pc = pOp->p2-1;
  }else{
    p->aOnceFlag[pOp->p1] = 1;
66199
66200
66201
66202
66203
66204
66205
66206
66207
66208
66209
66210
66211
66212
66213
66214
66215
66216
66217
65948
65949
65950
65951
65952
65953
65954





65955
65956
65957
65958
65959
65960
65961







-
-
-
-
-







    }else{
      assert( sqlite3BtreeCursorIsValid(u.ao.pCrsr) );
      VVA_ONLY(rc =) sqlite3BtreeDataSize(u.ao.pCrsr, &u.ao.payloadSize);
      assert( rc==SQLITE_OK );   /* DataSize() cannot fail */
    }
  }else if( ALWAYS(u.ao.pC->pseudoTableReg>0) ){
    u.ao.pReg = &aMem[u.ao.pC->pseudoTableReg];
    if( u.ao.pC->multiPseudo ){
      sqlite3VdbeMemShallowCopy(u.ao.pDest, u.ao.pReg+u.ao.p2, MEM_Ephem);
      Deephemeralize(u.ao.pDest);
      goto op_column_out;
    }
    assert( u.ao.pReg->flags & MEM_Blob );
    assert( memIsValid(u.ao.pReg) );
    u.ao.payloadSize = u.ao.pReg->n;
    u.ao.zRec = u.ao.pReg->z;
    u.ao.pC->cacheStatus = (pOp->p5&OPFLAG_CLEARCACHE) ? CACHE_STALE : p->cacheCtr;
    assert( u.ao.payloadSize==0 || u.ao.zRec!=0 );
  }else{
67284
67285
67286
67287
67288
67289
67290
67291

67292
67293
67294
67295
67296
67297
67298
67028
67029
67030
67031
67032
67033
67034

67035
67036
67037
67038
67039
67040
67041
67042







-
+







    }
  }
  u.az.pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
  u.az.pCx->isIndex = !u.az.pCx->isTable;
  break;
}

/* Opcode: SorterOpen P1 P2 * P4 *
/* Opcode: OpenSorter P1 P2 * P4 *
**
** This opcode works like OP_OpenEphemeral except that it opens
** a transient index that is specifically designed to sort large
** tables using an external merge-sort algorithm.
*/
case OP_SorterOpen: {
#if 0  /* local variables moved into u.ba */
67309
67310
67311
67312
67313
67314
67315
67316

67317
67318
67319
67320
67321


67322
67323
67324
67325
67326
67327
67328
67329
67053
67054
67055
67056
67057
67058
67059

67060
67061
67062
67063


67064
67065

67066
67067
67068
67069
67070
67071
67072







-
+



-
-
+
+
-







#else
  pOp->opcode = OP_OpenEphemeral;
  pc--;
#endif
  break;
}

/* Opcode: OpenPseudo P1 P2 P3 * P5
/* Opcode: OpenPseudo P1 P2 P3 * *
**
** Open a new cursor that points to a fake table that contains a single
** row of data.  The content of that one row in the content of memory
** register P2 when P5==0.  In other words, cursor P1 becomes an alias for the 
** MEM_Blob content contained in register P2.  When P5==1, then the
** register P2.  In other words, cursor P1 becomes an alias for the 
** MEM_Blob content contained in register P2.
** row is represented by P3 consecutive registers beginning with P2.
**
** A pseudo-table created by this opcode is used to hold a single
** row output from the sorter so that the row can be decomposed into
** individual columns using the OP_Column opcode.  The OP_Column opcode
** is the only cursor opcode that works with a pseudo-table.
**
** P3 is the number of fields in the records that will be stored by
67337
67338
67339
67340
67341
67342
67343
67344
67345
67346
67347
67348
67349
67350
67351
67080
67081
67082
67083
67084
67085
67086

67087
67088
67089
67090
67091
67092
67093







-







  assert( pOp->p1>=0 );
  u.bb.pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0);
  if( u.bb.pCx==0 ) goto no_mem;
  u.bb.pCx->nullRow = 1;
  u.bb.pCx->pseudoTableReg = pOp->p2;
  u.bb.pCx->isTable = 1;
  u.bb.pCx->isIndex = 0;
  u.bb.pCx->multiPseudo = pOp->p5;
  break;
}

/* Opcode: Close P1 * * * *
**
** Close a cursor previously opened as P1.  If P1 is not
** currently open, this instruction is a no-op.
68326
68327
68328
68329
68330
68331
68332
68333

68334
68335
68336
68337
68338
68339
68340
68068
68069
68070
68071
68072
68073
68074

68075
68076
68077
68078
68079
68080
68081
68082







-
+







  sqlite3_vtab *pVtab;
  const sqlite3_module *pModule;
#endif /* local variables moved into u.bn */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bn.pC = p->apCsr[pOp->p1];
  assert( u.bn.pC!=0 );
  assert( u.bn.pC->pseudoTableReg==0 || u.bn.pC->nullRow );
  assert( u.bn.pC->pseudoTableReg==0 );
  if( u.bn.pC->nullRow ){
    pOut->flags = MEM_Null;
    break;
  }else if( u.bn.pC->deferredMoveto ){
    u.bn.v = u.bn.pC->movetoTarget;
#ifndef SQLITE_OMIT_VIRTUALTABLE
  }else if( u.bn.pC->pVtabCursor ){
70993
70994
70995
70996
70997
70998
70999
71000
71001
71002
71003

71004

71005
71006
71007
71008
71009
71010
71011
70735
70736
70737
70738
70739
70740
70741




70742

70743
70744
70745
70746
70747
70748
70749
70750







-
-
-
-
+
-
+







  ** than p->nBuffer bytes remaining in the PMA, read all remaining data.  */
  iBuf = p->iReadOff % p->nBuffer;
  if( iBuf==0 ){
    int nRead;                    /* Bytes to read from disk */
    int rc;                       /* sqlite3OsRead() return code */

    /* Determine how many bytes of data to read. */
    if( (p->iEof - p->iReadOff) > (i64)p->nBuffer ){
      nRead = p->nBuffer;
    }else{
      nRead = (int)(p->iEof - p->iReadOff);
    nRead = (int)(p->iEof - p->iReadOff);
    }
    if( nRead>p->nBuffer ) nRead = p->nBuffer;
    assert( nRead>0 );

    /* Read data from the file. Return early if an error occurs. */
    rc = sqlite3OsRead(p->pFile, p->aBuffer, nRead, p->iReadOff);
    assert( rc!=SQLITE_IOERR_SHORT_READ );
    if( rc!=SQLITE_OK ) return rc;
  }
71900
71901
71902
71903
71904
71905
71906
71907
71908
71909
71910
71911
71912
71913
71914
71915
71916
71917
71918
71919
71920
71921
71639
71640
71641
71642
71643
71644
71645








71646
71647
71648
71649
71650
71651
71652







-
-
-
-
-
-
-
-







    rc = sqlite3OsOpen(p->pVfs, p->zJournal, pReal, p->flags, 0);
    if( rc==SQLITE_OK ){
      p->pReal = pReal;
      if( p->iSize>0 ){
        assert(p->iSize<=p->nBuf);
        rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0);
      }
      if( rc!=SQLITE_OK ){
        /* If an error occurred while writing to the file, close it before
        ** returning. This way, SQLite uses the in-memory journal data to 
        ** roll back changes made to the internal page-cache before this
        ** function was called.  */
        sqlite3OsClose(pReal);
        p->pReal = 0;
      }
    }
  }
  return rc;
}

/*
** Close the file.
72077
72078
72079
72080
72081
72082
72083
72084
72085
72086
72087
72088
72089
72090
72091
72092
72093
72094
72095
72096
72097
72098
72099
72100
71808
71809
71810
71811
71812
71813
71814










71815
71816
71817
71818
71819
71820
71821







-
-
-
-
-
-
-
-
-
-







SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *p){
  if( p->pMethods!=&JournalFileMethods ){
    return SQLITE_OK;
  }
  return createFile((JournalFile *)p);
}

/*
** The file-handle passed as the only argument is guaranteed to be an open
** file. It may or may not be of class JournalFile. If the file is a
** JournalFile, and the underlying file on disk has not yet been opened,
** return 0. Otherwise, return 1.
*/
SQLITE_PRIVATE int sqlite3JournalExists(sqlite3_file *p){
  return (p->pMethods!=&JournalFileMethods || ((JournalFile *)p)->pReal!=0);
}

/* 
** Return the number of bytes required to store a JournalFile that uses vfs
** pVfs to create the underlying on-disk files.
*/
SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *pVfs){
  return (pVfs->szOsFile+sizeof(JournalFile));
}
72572
72573
72574
72575
72576
72577
72578
72579
72580
72581
72582
72583
72584
72585
72586
72587
72588
72589
72590
72591
72592
72593
72594
72293
72294
72295
72296
72297
72298
72299









72300
72301
72302
72303
72304
72305
72306







-
-
-
-
-
-
-
-
-







**
**     SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5
**
** The result of random()%5 in the GROUP BY clause is probably different
** from the result in the result-set.  We might fix this someday.  Or
** then again, we might not...
**
** If the reference is followed by a COLLATE operator, then make sure
** the COLLATE operator is preserved.  For example:
**
**     SELECT a+b, c+d FROM t1 ORDER BY 1 COLLATE nocase;
**
** Should be transformed into:
**
**     SELECT a+b, c+d FROM t1 ORDER BY (a+b) COLLATE nocase;
**
** The nSubquery parameter specifies how many levels of subquery the
** alias is removed from the original expression.  The usually value is
** zero but it might be more if the alias is contained within a subquery
** of the original expression.  The Expr.op2 field of TK_AGG_FUNCTION
** structures must be increased by the nSubquery amount.
*/
static void resolveAlias(
72604
72605
72606
72607
72608
72609
72610
72611
72612
72613

72614
72615
72616
72617
72618
72619
72620













72621
72622
72623



72624
72625
72626
72627
72628
72629
72630
72631
72632
72633
72634
72635
72636
72637
72638
72639
72640
72641
72642
72643
72644
72645
72646
72647
72648
72649
72650
72651
72652
72653
72654
72655
72656
72657
72658
72659
72660
72661
72662
72663
72664
72665
72666
72667
72668
72669
72670
72671
72672
72673
72674
72675
72676
72677
72678
72679
72680
72681
72682
72683
72684
72685
72686
72687
72688
72689
72690
72691
72692
72693
72694
72695
72696
72316
72317
72318
72319
72320
72321
72322


72323
72324
72325
72326
72327
72328
72329
72330
72331
72332
72333
72334
72335
72336
72337
72338
72339
72340
72341
72342
72343
72344
72345


72346
72347
72348
72349
72350
72351
72352
72353



72354
72355
72356
72357





72358
72359
72360
72361
72362
72363
72364
72365
72366
72367
72368
72369
72370
72371
72372
72373
72374
72375
72376
72377





























72378
72379
72380
72381
72382
72383
72384







-
-

+







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

-
-
+
+
+





-
-
-




-
-
-
-
-




















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







  sqlite3 *db;           /* The database connection */

  assert( iCol>=0 && iCol<pEList->nExpr );
  pOrig = pEList->a[iCol].pExpr;
  assert( pOrig!=0 );
  assert( pOrig->flags & EP_Resolved );
  db = pParse->db;
  pDup = sqlite3ExprDup(db, pOrig, 0);
  if( pDup==0 ) return;
  if( pOrig->op!=TK_COLUMN && zType[0]!='G' ){
    pDup = sqlite3ExprDup(db, pOrig, 0);
    incrAggFunctionDepth(pDup, nSubquery);
    pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0);
    if( pDup==0 ) return;
    if( pEList->a[iCol].iAlias==0 ){
      pEList->a[iCol].iAlias = (u16)(++pParse->nAlias);
    }
    pDup->iTable = pEList->a[iCol].iAlias;
  }else if( ExprHasProperty(pOrig, EP_IntValue) || pOrig->u.zToken==0 ){
    pDup = sqlite3ExprDup(db, pOrig, 0);
    if( pDup==0 ) return;
  }else{
    char *zToken = pOrig->u.zToken;
    assert( zToken!=0 );
    pOrig->u.zToken = 0;
    pDup = sqlite3ExprDup(db, pOrig, 0);
    pOrig->u.zToken = zToken;
    if( pDup==0 ) return;
    assert( (pDup->flags & (EP_Reduced|EP_TokenOnly))==0 );
    pDup->flags2 |= EP2_MallocedToken;
    pDup->u.zToken = sqlite3DbStrDup(db, zToken);
  }
  if( pExpr->op==TK_COLLATE ){
    pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
  if( pExpr->flags & EP_ExpCollate ){
    pDup->pColl = pExpr->pColl;
    pDup->flags |= EP_ExpCollate;
  }

  /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This 
  ** prevents ExprDelete() from deleting the Expr structure itself,
  ** allowing it to be repopulated by the memcpy() on the following line.
  ** The pExpr->u.zToken might point into memory that will be freed by the
  ** sqlite3DbFree(db, pDup) on the last line of this block, so be sure to
  ** make a copy of the token before doing the sqlite3DbFree().
  */
  ExprSetProperty(pExpr, EP_Static);
  sqlite3ExprDelete(db, pExpr);
  memcpy(pExpr, pDup, sizeof(*pExpr));
  if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){
    assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 );
    pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken);
    pExpr->flags2 |= EP2_MallocedToken;
  }
  sqlite3DbFree(db, pDup);
}


/*
** Return TRUE if the name zCol occurs anywhere in the USING clause.
**
** Return FALSE if the USING clause is NULL or if it does not contain
** zCol.
*/
static int nameInUsingClause(IdList *pUsing, const char *zCol){
  if( pUsing ){
    int k;
    for(k=0; k<pUsing->nId; k++){
      if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ) return 1;
    }
  }
  return 0;
}

/*
** Subqueries stores the original database, table and column names for their
** result sets in ExprList.a[].zSpan, in the form "DATABASE.TABLE.COLUMN".
** Check to see if the zSpan given to this routine matches the zDb, zTab,
** and zCol.  If any of zDb, zTab, and zCol are NULL then those fields will
** match anything.
*/
SQLITE_PRIVATE int sqlite3MatchSpanName(
  const char *zSpan,
  const char *zCol,
  const char *zTab,
  const char *zDb
){
  int n;
  for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
  if( zDb && sqlite3StrNICmp(zSpan, zDb, n)!=0 ){
    return 0;
  }
  zSpan += n+1;
  for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
  if( zTab && sqlite3StrNICmp(zSpan, zTab, n)!=0 ){
    return 0;
  }
  zSpan += n+1;
  if( zCol && sqlite3StrICmp(zSpan, zCol)!=0 ){
    return 0;
  }
  return 1;
}

/*
** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
** that name in the set of source tables in pSrcList and make the pExpr 
** expression node refer back to that source column.  The following changes
** are made to pExpr:
**
72739
72740
72741
72742
72743
72744
72745
72746
72747
72748
72749
72750
72751
72752
72753
72754
72755
72756
72757
72758
72759
72760
72761
72762
72763
72764
72765
72766
72767

72768
72769
72770
72771

72772
72773
72774
72775
72776
72777
72778
72779
72780


72781
72782

72783
72784
72785
72786
72787
72788
72789






72790
72791
72792
72793
72794



72795
72796
72797



72798
72799
72800
72801
72802
72803
72804
72805
72806
72807
72808
72809
72810


72811

72812
72813
72814
72815
72816
72817
72818
72819
72820
72821
72822

72823
72824
72825
72826
72827
72828
72829
72830
72427
72428
72429
72430
72431
72432
72433














72434
72435
72436
72437
72438
72439
72440
72441
72442
72443
72444
72445
72446
72447
72448








72449
72450


72451







72452
72453
72454
72455
72456
72457





72458
72459
72460
72461
72462
72463
72464
72465
72466
72467
72468
72469
72470
72471
72472
72473
72474
72475
72476
72477
72478
72479
72480
72481
72482
72483
72484
72485
72486
72487
72488
72489





72490

72491
72492
72493
72494
72495
72496
72497







-
-
-
-
-
-
-
-
-
-
-
-
-
-








+




+

-
-
-
-
-
-
-
-
+
+
-
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
+
+
+



+
+
+













+
+

+






-
-
-
-
-
+
-







  assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );

  /* Initialize the node to no-match */
  pExpr->iTable = -1;
  pExpr->pTab = 0;
  ExprSetIrreducible(pExpr);

  /* Translate the schema name in zDb into a pointer to the corresponding
  ** schema.  If not found, pSchema will remain NULL and nothing will match
  ** resulting in an appropriate error message toward the end of this routine
  */
  if( zDb ){
    for(i=0; i<db->nDb; i++){
      assert( db->aDb[i].zName );
      if( sqlite3StrICmp(db->aDb[i].zName,zDb)==0 ){
        pSchema = db->aDb[i].pSchema;
        break;
      }
    }
  }

  /* Start at the inner-most context and move outward until a match is found */
  while( pNC && cnt==0 ){
    ExprList *pEList;
    SrcList *pSrcList = pNC->pSrcList;

    if( pSrcList ){
      for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
        Table *pTab;
        int iDb;
        Column *pCol;
  
        pTab = pItem->pTab;
        assert( pTab!=0 && pTab->zName!=0 );
        iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
        assert( pTab->nCol>0 );
        if( pItem->pSelect && (pItem->pSelect->selFlags & SF_NestedFrom)!=0 ){
          ExprList *pEList = pItem->pSelect->pEList;
          int hit = 0;
          for(j=0; j<pEList->nExpr; j++){
            if( sqlite3MatchSpanName(pEList->a[j].zSpan, zCol, zTab, zDb) ){
              cnt++;
              cntTab = 2;
              pMatch = pItem;
        if( zTab ){
          if( pItem->zAlias ){
              pExpr->iColumn = j;
              hit = 1;
            char *zTabName = pItem->zAlias;
            }
          }
          if( hit || zTab==0 ) continue;
        }
        if( zDb && pTab->pSchema!=pSchema ){
          continue;
        }
            if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
          }else{
            char *zTabName = pTab->zName;
            if( NEVER(zTabName==0) || sqlite3StrICmp(zTabName, zTab)!=0 ){
              continue;
            }
        if( zTab ){
          const char *zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName;
          assert( zTabName!=0 );
          if( sqlite3StrICmp(zTabName, zTab)!=0 ){
            continue;
            if( zDb!=0 && sqlite3StrICmp(db->aDb[iDb].zName, zDb)!=0 ){
              continue;
            }
          }
        }
        if( 0==(cntTab++) ){
          pExpr->iTable = pItem->iCursor;
          pExpr->pTab = pTab;
          pSchema = pTab->pSchema;
          pMatch = pItem;
        }
        for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
          if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
            /* If there has been exactly one prior match and this match
            ** is for the right-hand table of a NATURAL JOIN or is in a 
            ** USING clause, then skip this match.
            */
            if( cnt==1 ){
              if( pItem->jointype & JT_NATURAL ) continue;
              if( nameInUsingClause(pItem->pUsing, zCol) ) continue;
            }
            cnt++;
            pExpr->iTable = pItem->iCursor;
            pExpr->pTab = pTab;
            pMatch = pItem;
            pSchema = pTab->pSchema;
            /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
            pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j;
            break;
          }
        }
      }
      if( pMatch ){
        pExpr->iTable = pMatch->iCursor;
        pExpr->pTab = pMatch->pTab;
        pSchema = pExpr->pTab->pSchema;
      }
    }
    } /* if( pSrcList ) */

#ifndef SQLITE_OMIT_TRIGGER
    /* If we have not already resolved the name, then maybe 
    ** it is a new.* or old.* trigger argument reference
    */
    if( zDb==0 && zTab!=0 && cnt==0 && pParse->pTriggerTab!=0 ){
      int op = pParse->eTriggerOp;
73151
73152
73153
73154
73155
73156
73157
73158

73159
73160
73161
73162
73163
73164
73165
72818
72819
72820
72821
72822
72823
72824

72825
72826
72827
72828
72829
72830
72831
72832







-
+







        }
      }
#endif
      if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){
        sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
        pNC->nErr++;
        is_agg = 0;
      }else if( no_such_func && pParse->db->init.busy==0 ){
      }else if( no_such_func ){
        sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
        pNC->nErr++;
      }else if( wrong_num_args ){
        sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
             nId, zId);
        pNC->nErr++;
      }
73370
73371
73372
73373
73374
73375
73376
73377

73378
73379
73380
73381
73382
73383
73384
73385
73386
73387
73388
73389
73390
73391
73392
73393
73394
73395
73396
73397
73398
73399
73400








73401
73402
73403
73404
73405
73406
73407
73408
73409
73410
73411
73412
73413
73414
73415
73037
73038
73039
73040
73041
73042
73043

73044
73045
73046
73047
73048
73049
73050
73051
73052
73053
73054
73055
73056
73057
73058
73059
73060
73061






73062
73063
73064
73065
73066
73067
73068
73069








73070
73071
73072
73073
73074
73075
73076







-
+

















-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-







    moreToDo = 0;
    pEList = pSelect->pEList;
    assert( pEList!=0 );
    for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
      int iCol = -1;
      Expr *pE, *pDup;
      if( pItem->done ) continue;
      pE = sqlite3ExprSkipCollate(pItem->pExpr);
      pE = pItem->pExpr;
      if( sqlite3ExprIsInteger(pE, &iCol) ){
        if( iCol<=0 || iCol>pEList->nExpr ){
          resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr);
          return 1;
        }
      }else{
        iCol = resolveAsName(pParse, pEList, pE);
        if( iCol==0 ){
          pDup = sqlite3ExprDup(db, pE, 0);
          if( !db->mallocFailed ){
            assert(pDup);
            iCol = resolveOrderByTermToExprList(pParse, pSelect, pDup);
          }
          sqlite3ExprDelete(db, pDup);
        }
      }
      if( iCol>0 ){
        /* Convert the ORDER BY term into an integer column number iCol,
        ** taking care to preserve the COLLATE clause if it exists */
        Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
        if( pNew==0 ) return 1;
        pNew->flags |= EP_IntValue;
        pNew->u.iValue = iCol;
        CollSeq *pColl = pE->pColl;
        int flags = pE->flags & EP_ExpCollate;
        sqlite3ExprDelete(db, pE);
        pItem->pExpr = pE = sqlite3Expr(db, TK_INTEGER, 0);
        if( pE==0 ) return 1;
        pE->pColl = pColl;
        pE->flags |= EP_IntValue | flags;
        pE->u.iValue = iCol;
        if( pItem->pExpr==pE ){
          pItem->pExpr = pNew;
        }else{
          assert( pItem->pExpr->op==TK_COLLATE );
          assert( pItem->pExpr->pLeft==pE );
          pItem->pExpr->pLeft = pNew;
        }
        sqlite3ExprDelete(db, pE);
        pItem->iOrderByCol = (u16)iCol;
        pItem->done = 1;
      }else{
        moreToDo = 1;
      }
    }
    pSelect = pSelect->pNext;
73506
73507
73508
73509
73510
73511
73512
73513

73514
73515
73516
73517

73518
73519
73520
73521
73522
73523
73524
73167
73168
73169
73170
73171
73172
73173

73174
73175
73176
73177

73178
73179
73180
73181
73182
73183
73184
73185







-
+



-
+







      /* If an AS-name match is found, mark this ORDER BY column as being
      ** a copy of the iCol-th result-set column.  The subsequent call to
      ** sqlite3ResolveOrderGroupBy() will convert the expression to a
      ** copy of the iCol-th result-set expression. */
      pItem->iOrderByCol = (u16)iCol;
      continue;
    }
    if( sqlite3ExprIsInteger(sqlite3ExprSkipCollate(pE), &iCol) ){
    if( sqlite3ExprIsInteger(pE, &iCol) ){
      /* The ORDER BY term is an integer constant.  Again, set the column
      ** number so that sqlite3ResolveOrderGroupBy() will convert the
      ** order-by term to a copy of the result-set expression */
      if( iCol<1 || iCol>0xffff ){
      if( iCol<1 ){
        resolveOutOfRangeError(pParse, zType, i+1, nResult);
        return 1;
      }
      pItem->iOrderByCol = (u16)iCol;
      continue;
    }

73586
73587
73588
73589
73590
73591
73592

















73593
73594
73595
73596
73597
73598
73599
73247
73248
73249
73250
73251
73252
73253
73254
73255
73256
73257
73258
73259
73260
73261
73262
73263
73264
73265
73266
73267
73268
73269
73270
73271
73272
73273
73274
73275
73276
73277







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







    */
    memset(&sNC, 0, sizeof(sNC));
    sNC.pParse = pParse;
    if( sqlite3ResolveExprNames(&sNC, p->pLimit) ||
        sqlite3ResolveExprNames(&sNC, p->pOffset) ){
      return WRC_Abort;
    }
  
    /* Set up the local name-context to pass to sqlite3ResolveExprNames() to
    ** resolve the result-set expression list.
    */
    sNC.ncFlags = NC_AllowAgg;
    sNC.pSrcList = p->pSrc;
    sNC.pNext = pOuterNC;
  
    /* Resolve names in the result set. */
    pEList = p->pEList;
    assert( pEList!=0 );
    for(i=0; i<pEList->nExpr; i++){
      Expr *pX = pEList->a[i].pExpr;
      if( sqlite3ResolveExprNames(&sNC, pX) ){
        return WRC_Abort;
      }
    }
  
    /* Recursively resolve names in all subqueries
    */
    for(i=0; i<p->pSrc->nSrc; i++){
      struct SrcList_item *pItem = &p->pSrc->a[i];
      if( pItem->pSelect ){
        NameContext *pNC;         /* Used to iterate name contexts */
73614
73615
73616
73617
73618
73619
73620
73621
73622
73623
73624
73625
73626
73627
73628
73629
73630
73631
73632
73633
73634
73635
73636
73637
73638
73639
73640
73641
73642
73643
73644
73292
73293
73294
73295
73296
73297
73298

















73299
73300
73301
73302
73303
73304
73305







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








        for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef;
        assert( pItem->isCorrelated==0 && nRef<=0 );
        pItem->isCorrelated = (nRef!=0);
      }
    }
  
    /* Set up the local name-context to pass to sqlite3ResolveExprNames() to
    ** resolve the result-set expression list.
    */
    sNC.ncFlags = NC_AllowAgg;
    sNC.pSrcList = p->pSrc;
    sNC.pNext = pOuterNC;
  
    /* Resolve names in the result set. */
    pEList = p->pEList;
    assert( pEList!=0 );
    for(i=0; i<pEList->nExpr; i++){
      Expr *pX = pEList->a[i].pExpr;
      if( sqlite3ResolveExprNames(&sNC, pX) ){
        return WRC_Abort;
      }
    }
  
    /* If there are no aggregate functions in the result-set, and no GROUP BY 
    ** expression, do not allow aggregates in any of the other expressions.
    */
    assert( (p->selFlags & SF_Aggregate)==0 );
    pGroupBy = p->pGroupBy;
    if( pGroupBy || (sNC.ncFlags & NC_HasAgg)!=0 ){
      p->selFlags |= SF_Aggregate;
73864
73865
73866
73867
73868
73869
73870
73871
73872
73873

73874
73875
73876
73877
73878
73879
73880
73525
73526
73527
73528
73529
73530
73531



73532
73533
73534
73535
73536
73537
73538
73539







-
-
-
+







**
** CREATE TABLE t1(a);
** SELECT * FROM t1 WHERE a;
** SELECT a AS b FROM t1 WHERE b;
** SELECT * FROM t1 WHERE (select a from t1);
*/
SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){
  int op;
  pExpr = sqlite3ExprSkipCollate(pExpr);
  op = pExpr->op;
  int op = pExpr->op;
  if( op==TK_SELECT ){
    assert( pExpr->flags&EP_xIsSelect );
    return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
  }
#ifndef SQLITE_OMIT_CAST
  if( op==TK_CAST ){
    assert( !ExprHasProperty(pExpr, EP_IntValue) );
73891
73892
73893
73894
73895
73896
73897
73898

73899
73900
73901
73902
73903
73904
73905
73906
73907
73908
73909
73910
73911
73912
73913
73914
73915
73916
73917
73918
73919
73920
73921
73922
73923

73924
73925
73926
73927
73928
73929
73930




73931
73932
73933
73934
73935
73936
73937
73938
73939








73940
73941
73942












73943
73944
73945
73946
73947
73948
73949

73950
73951

73952
73953
73954
73955
73956
73957
73958
73959
73960
73961
73962

73963
73964
73965



73966
73967

73968
73969

73970
73971

73972

73973

73974
73975
73976
73977

73978
73979
73980
73981
73982
73983
73984
73985

73986
73987
73988
73989
73990
73991
73992
73550
73551
73552
73553
73554
73555
73556

73557

























73558



73559



73560
73561
73562
73563
73564
73565
73566
73567
73568




73569
73570
73571
73572
73573
73574
73575
73576



73577
73578
73579
73580
73581
73582
73583
73584
73585
73586
73587
73588
73589
73590

73591
73592
73593

73594


73595











73596



73597
73598
73599


73600
73601
73602
73603
73604
73605
73606

73607
73608
73609
73610
73611
73612

73613






73614
73615
73616
73617
73618
73619
73620
73621
73622
73623







-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-

-
-
-
+
+
+
+





-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+


-



-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
+
+
-
-
+


+


+
-
+

+



-
+
-
-
-
-
-
-


+







    assert( pExpr->pTab && j<pExpr->pTab->nCol );
    return pExpr->pTab->aCol[j].affinity;
  }
  return pExpr->affinity;
}

/*
** Set the collating sequence for expression pExpr to be the collating
** Set the explicit collating sequence for an expression to the
** sequence named by pToken.   Return a pointer to a new Expr node that
** implements the COLLATE operator.
**
** If a memory allocation error occurs, that fact is recorded in pParse->db
** and the pExpr parameter is returned unchanged.
*/
SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr *pExpr, Token *pCollName){
  if( pCollName->n>0 ){
    Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, 1);
    if( pNew ){
      pNew->pLeft = pExpr;
      pNew->flags |= EP_Collate;
      pExpr = pNew;
    }
  }
  return pExpr;
}
SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){
  Token s;
  assert( zC!=0 );
  s.z = zC;
  s.n = sqlite3Strlen30(s.z);
  return sqlite3ExprAddCollateToken(pParse, pExpr, &s);
}

** collating sequence supplied in the second argument.
/*
** Skip over any TK_COLLATE and/or TK_AS operators at the root of
** an expression.
*/
SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr *pExpr){
  while( pExpr && (pExpr->op==TK_COLLATE || pExpr->op==TK_AS) ){
    pExpr = pExpr->pLeft;
SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Expr *pExpr, CollSeq *pColl){
  if( pExpr && pColl ){
    pExpr->pColl = pColl;
    pExpr->flags |= EP_ExpCollate;
  }
  return pExpr;
}

/*
** Return the collation sequence for the expression pExpr. If
** there is no defined collating sequence, return NULL.
**
** The collating sequence might be determined by a COLLATE operator
** Set the collating sequence for expression pExpr to be the collating
** sequence named by pToken.   Return a pointer to the revised expression.
** The collating sequence is marked as "explicit" using the EP_ExpCollate
** flag.  An explicit collating sequence will override implicit
** collating sequences.
*/
SQLITE_PRIVATE Expr *sqlite3ExprSetCollByToken(Parse *pParse, Expr *pExpr, Token *pCollName){
  char *zColl = 0;            /* Dequoted name of collation sequence */
** or by the presence of a column with a defined collating sequence.
** COLLATE operators take first precedence.  Left operands take
** precedence over right operands.
  CollSeq *pColl;
  sqlite3 *db = pParse->db;
  zColl = sqlite3NameFromToken(db, pCollName);
  pColl = sqlite3LocateCollSeq(pParse, zColl);
  sqlite3ExprSetColl(pExpr, pColl);
  sqlite3DbFree(db, zColl);
  return pExpr;
}

/*
** Return the default collation sequence for the expression pExpr. If
** there is no default collation type, return 0.
*/
SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
  sqlite3 *db = pParse->db;
  CollSeq *pColl = 0;
  Expr *p = pExpr;
  while( p ){
    int op = p->op;
    int op;
    if( op==TK_CAST || op==TK_UPLUS ){
      p = p->pLeft;
    pColl = p->pColl;
      continue;
    }
    assert( op!=TK_REGISTER || p->op2!=TK_COLLATE );
    if( op==TK_COLLATE ){
      if( db->init.busy ){
        /* Do not report errors when parsing while the schema */
        pColl = sqlite3FindCollSeq(db, ENC(db), p->u.zToken, 0);
      }else{
        pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
      }
      break;
    if( pColl ) break;
    }
    if( p->pTab!=0
     && (op==TK_AGG_COLUMN || op==TK_COLUMN
    op = p->op;
    if( p->pTab!=0 && (
        op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER || op==TK_TRIGGER
          || op==TK_REGISTER || op==TK_TRIGGER)
    ){
    )){
      /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally
      ** a TK_COLUMN but was previously evaluated and cached in a register */
      const char *zColl;
      int j = p->iColumn;
      if( j>=0 ){
        sqlite3 *db = pParse->db;
        const char *zColl = p->pTab->aCol[j].zColl;
        zColl = p->pTab->aCol[j].zColl;
        pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
        pExpr->pColl = pColl;
      }
      break;
    }
    if( p->flags & EP_Collate ){
    if( op!=TK_CAST && op!=TK_UPLUS ){
      if( ALWAYS(p->pLeft) && (p->pLeft->flags & EP_Collate)!=0 ){
        p = p->pLeft;
      }else{
        p = p->pRight;
      }
    }else{
      break;
    }
    p = p->pLeft;
  }
  if( sqlite3CheckCollSeq(pParse, pColl) ){ 
    pColl = 0;
  }
  return pColl;
}

74082
74083
74084
74085
74086
74087
74088
74089
74090
74091
74092






74093
74094
74095
74096
74097
74098
74099
73713
73714
73715
73716
73717
73718
73719




73720
73721
73722
73723
73724
73725
73726
73727
73728
73729
73730
73731
73732







-
-
-
-
+
+
+
+
+
+







SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(
  Parse *pParse, 
  Expr *pLeft, 
  Expr *pRight
){
  CollSeq *pColl;
  assert( pLeft );
  if( pLeft->flags & EP_Collate ){
    pColl = sqlite3ExprCollSeq(pParse, pLeft);
  }else if( pRight && (pRight->flags & EP_Collate)!=0 ){
    pColl = sqlite3ExprCollSeq(pParse, pRight);
  if( pLeft->flags & EP_ExpCollate ){
    assert( pLeft->pColl );
    pColl = pLeft->pColl;
  }else if( pRight && pRight->flags & EP_ExpCollate ){
    assert( pRight->pColl );
    pColl = pRight->pColl;
  }else{
    pColl = sqlite3ExprCollSeq(pParse, pLeft);
    if( !pColl ){
      pColl = sqlite3ExprCollSeq(pParse, pRight);
    }
  }
  return pColl;
74315
74316
74317
74318
74319
74320
74321

74322



74323
74324
74325

74326



74327
74328
74329
74330
74331
74332
74333
73948
73949
73950
73951
73952
73953
73954
73955

73956
73957
73958
73959
73960
73961
73962

73963
73964
73965
73966
73967
73968
73969
73970
73971
73972







+
-
+
+
+



+
-
+
+
+







  if( pRoot==0 ){
    assert( db->mallocFailed );
    sqlite3ExprDelete(db, pLeft);
    sqlite3ExprDelete(db, pRight);
  }else{
    if( pRight ){
      pRoot->pRight = pRight;
      if( pRight->flags & EP_ExpCollate ){
      pRoot->flags |= EP_Collate & pRight->flags;
        pRoot->flags |= EP_ExpCollate;
        pRoot->pColl = pRight->pColl;
      }
    }
    if( pLeft ){
      pRoot->pLeft = pLeft;
      if( pLeft->flags & EP_ExpCollate ){
      pRoot->flags |= EP_Collate & pLeft->flags;
        pRoot->flags |= EP_ExpCollate;
        pRoot->pColl = pLeft->pColl;
      }
    }
    exprSetHeight(pRoot);
  }
}

/*
** Allocate a Expr node which joins as many as two subtrees.
74577
74578
74579
74580
74581
74582
74583
74584

74585
74586
74587
74588
74589
74590
74591
74216
74217
74218
74219
74220
74221
74222

74223
74224
74225
74226
74227
74228
74229
74230







-
+







  if( 0==(flags&EXPRDUP_REDUCE) ){
    nSize = EXPR_FULLSIZE;
  }else{
    assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) );
    assert( !ExprHasProperty(p, EP_FromJoin) ); 
    assert( (p->flags2 & EP2_MallocedToken)==0 );
    assert( (p->flags2 & EP2_Irreducible)==0 );
    if( p->pLeft || p->pRight || p->x.pList ){
    if( p->pLeft || p->pRight || p->pColl || p->x.pList ){
      nSize = EXPR_REDUCEDSIZE | EP_Reduced;
    }else{
      nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly;
    }
  }
  return nSize;
}
74794
74795
74796
74797
74798
74799
74800
74801
74802
74803
74804
74805
74806
74807
74808
74433
74434
74435
74436
74437
74438
74439

74440
74441
74442
74443
74444
74445
74446







-







    pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
    pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
    pNewItem->jointype = pOldItem->jointype;
    pNewItem->iCursor = pOldItem->iCursor;
    pNewItem->addrFillSub = pOldItem->addrFillSub;
    pNewItem->regReturn = pOldItem->regReturn;
    pNewItem->isCorrelated = pOldItem->isCorrelated;
    pNewItem->viaCoroutine = pOldItem->viaCoroutine;
    pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex);
    pNewItem->notIndexed = pOldItem->notIndexed;
    pNewItem->pIndex = pOldItem->pIndex;
    pTab = pNewItem->pTab = pOldItem->pTab;
    if( pTab ){
      pTab->nRef++;
    }
76601
76602
76603
76604
76605
76606
76607
76608
76609
76610
76611
76612
76613
76614
76615
76239
76240
76241
76242
76243
76244
76245

76246
76247
76248
76249
76250
76251
76252







-







      testcase( regFree2==0 );
      codeCompare(pParse, pLeft, pRight, OP_Le, r1, r2, r4, SQLITE_STOREP2);
      sqlite3VdbeAddOp3(v, OP_And, r3, r4, target);
      sqlite3ReleaseTempReg(pParse, r3);
      sqlite3ReleaseTempReg(pParse, r4);
      break;
    }
    case TK_COLLATE: 
    case TK_UPLUS: {
      inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
      break;
    }

    case TK_TRIGGER: {
      /* If the opcode is TK_TRIGGER, then the expression is a reference
76971
76972
76973
76974
76975
76976
76977
76978
76979
76980
76981
76982
76983
76984
76985
76986
76987
76988
76989
76990
76608
76609
76610
76611
76612
76613
76614






76615
76616
76617
76618
76619
76620
76621







-
-
-
-
-
-







    case TK_UMINUS:  zUniOp = "UMINUS"; break;
    case TK_UPLUS:   zUniOp = "UPLUS";  break;
    case TK_BITNOT:  zUniOp = "BITNOT"; break;
    case TK_NOT:     zUniOp = "NOT";    break;
    case TK_ISNULL:  zUniOp = "ISNULL"; break;
    case TK_NOTNULL: zUniOp = "NOTNULL"; break;

    case TK_COLLATE: {
      sqlite3ExplainExpr(pOut, pExpr->pLeft);
      sqlite3ExplainPrintf(pOut,".COLLATE(%s)",pExpr->u.zToken);
      break;
    }

    case TK_AGG_FUNCTION:
    case TK_CONST_FUNC:
    case TK_FUNCTION: {
      ExprList *pFarg;       /* List of function arguments */
      if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ){
        pFarg = 0;
      }else{
77114
77115
77116
77117
77118
77119
77120
77121
77122
77123
77124
77125
77126
77127
77128
77129
77130
77131
77132
77133
76745
76746
76747
76748
76749
76750
76751






76752
76753
76754
76755
76756
76757
76758







-
-
-
-
-
-







  }else{
    sqlite3ExplainPush(pOut);
    for(i=0; i<pList->nExpr; i++){
      sqlite3ExplainPrintf(pOut, "item[%d] = ", i);
      sqlite3ExplainPush(pOut);
      sqlite3ExplainExpr(pOut, pList->a[i].pExpr);
      sqlite3ExplainPop(pOut);
      if( pList->a[i].zName ){
        sqlite3ExplainPrintf(pOut, " AS %s", pList->a[i].zName);
      }
      if( pList->a[i].bSpanIsTab ){
        sqlite3ExplainPrintf(pOut, " (%s)", pList->a[i].zSpan);
      }
      if( i<pList->nExpr-1 ){
        sqlite3ExplainNL(pOut);
      }
    }
    sqlite3ExplainPop(pOut);
  }
}
77201
77202
77203
77204
77205
77206
77207
77208
77209
77210
77211
77212
77213
77214
77215
77216
77217
76826
76827
76828
76829
76830
76831
76832



76833
76834
76835
76836
76837
76838
76839







-
-
-







static int evalConstExpr(Walker *pWalker, Expr *pExpr){
  Parse *pParse = pWalker->pParse;
  switch( pExpr->op ){
    case TK_IN:
    case TK_REGISTER: {
      return WRC_Prune;
    }
    case TK_COLLATE: {
      return WRC_Continue;
    }
    case TK_FUNCTION:
    case TK_AGG_FUNCTION:
    case TK_CONST_FUNC: {
      /* The arguments to a function have a fixed destination.
      ** Mark them this way to avoid generated unneeded OP_SCopy
      ** instructions. 
      */
77225
77226
77227
77228
77229
77230
77231

77232

77233
77234

77235
77236
77237
77238
77239
77240
77241
77242
77243
76847
76848
76849
76850
76851
76852
76853
76854

76855


76856


76857
76858
76859
76860
76861
76862
76863







+
-
+
-
-
+
-
-







        }
      }
      break;
    }
  }
  if( isAppropriateForFactoring(pExpr) ){
    int r1 = ++pParse->nMem;
    int r2;
    int r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
    r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
    /* If r2!=r1, it means that register r1 is never used.  That is harmless
    ** but suboptimal, so we want to know about the situation to fix it.
    if( NEVER(r1!=r2) ) sqlite3ReleaseTempReg(pParse, r1);
    ** Hence the following assert: */
    assert( r2==r1 );
    pExpr->op2 = pExpr->op;
    pExpr->op = TK_REGISTER;
    pExpr->iTable = r2;
    return WRC_Prune;
  }
  return WRC_Continue;
}
77646
77647
77648
77649
77650
77651
77652
77653

77654
77655
77656
77657
77658
77659
77660
77661
77662
77663
77664
77665
77666
77667
77668
77669
77670
77671
77672
77673

77674
77675


77676
77677
77678
77679
77680
77681
77682
77266
77267
77268
77269
77270
77271
77272

77273








77274
77275
77276
77277
77278
77279
77280
77281
77282
77283
77284

77285
77286
77287
77288
77289
77290
77291
77292
77293
77294
77295
77296







-
+
-
-
-
-
-
-
-
-











-
+


+
+







  }
  assert( !ExprHasAnyProperty(pA, EP_TokenOnly|EP_Reduced) );
  assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) );
  if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){
    return 2;
  }
  if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
  if( pA->op!=pB->op ){
  if( pA->op!=pB->op ) return 2;
    if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB)<2 ){
      return 1;
    }
    if( pB->op==TK_COLLATE && sqlite3ExprCompare(pA, pB->pLeft)<2 ){
      return 1;
    }
    return 2;
  }
  if( sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 2;
  if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2;
  if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList) ) return 2;
  if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 2;
  if( ExprHasProperty(pA, EP_IntValue) ){
    if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){
      return 2;
    }
  }else if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken){
    if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2;
    if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){
      return pA->op==TK_COLLATE ? 1 : 2;
      return 2;
    }
  }
  if( (pA->flags & EP_ExpCollate)!=(pB->flags & EP_ExpCollate) ) return 1;
  if( (pA->flags & EP_ExpCollate)!=0 && pA->pColl!=pB->pColl ) return 2;
  return 0;
}

/*
** Compare two ExprList objects.  Return 0 if they are identical and 
** non-zero if they differ in any way.
**
77909
77910
77911
77912
77913
77914
77915
77916
77917
77918
77919

77920
77921
77922
77923
77924
77925
77926
77927
77928
77929
77930
77931
77932
77933



77934
77935
77936
77937
77938
77939
77940
77941
77523
77524
77525
77526
77527
77528
77529



77530
77531
77532
77533
77534
77535
77536
77537
77538
77539
77540
77541
77542



77543
77544
77545

77546
77547
77548
77549
77550
77551
77552







-
-
-

+











-
-
-
+
+
+
-







        }
        /* Make pExpr point to the appropriate pAggInfo->aFunc[] entry
        */
        assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
        ExprSetIrreducible(pExpr);
        pExpr->iAgg = (i16)i;
        pExpr->pAggInfo = pAggInfo;
        return WRC_Prune;
      }else{
        return WRC_Continue;
      }
      return WRC_Prune;
    }
  }
  return WRC_Continue;
}
static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){
  UNUSED_PARAMETER(pWalker);
  UNUSED_PARAMETER(pSelect);
  return WRC_Continue;
}

/*
** Analyze the pExpr expression looking for aggregate functions and
** for variables that need to be added to AggInfo object that pNC->pAggInfo
** points to.  Additional entries are made on the AggInfo object as
** Analyze the given expression looking for aggregate functions and
** for variables that need to be added to the pParse->aAgg[] array.
** Make additional entries to the pParse->aAgg[] array as necessary.
** necessary.
**
** This routine should only be called after the expression has been
** analyzed by sqlite3ResolveExprNames().
*/
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
  Walker w;
  memset(&w, 0, sizeof(w));
80451
80452
80453
80454
80455
80456
80457
80458

80459
80460
80461
80462
80463
80464
80465
80062
80063
80064
80065
80066
80067
80068

80069
80070
80071
80072
80073
80074
80075
80076







-
+







  for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
    if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){
      sqlite3ErrorMsg(pFix->pParse,
         "%s %T cannot reference objects in database %s",
         pFix->zType, pFix->pName, pItem->zDatabase);
      return 1;
    }
    sqlite3DbFree(pFix->pParse->db, pItem->zDatabase);
    sqlite3_free(pItem->zDatabase);
    pItem->zDatabase = 0;
    pItem->pSchema = pFix->pSchema;
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
    if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
    if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1;
#endif
  }
80919
80920
80921
80922
80923
80924
80925
80926
80927
80928
80929
80930
80931
80932
80933
80530
80531
80532
80533
80534
80535
80536

80537
80538
80539
80540
80541
80542
80543







-







** Note that if an error occurred, it might be the case that
** no VDBE code was generated.
*/
SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
  sqlite3 *db;
  Vdbe *v;

  assert( pParse->pToplevel==0 );
  db = pParse->db;
  if( db->mallocFailed ) return;
  if( pParse->nested ) return;
  if( pParse->nErr ) return;

  /* Begin by generating some termination code at the end of the
  ** vdbe program
83483
83484
83485
83486
83487
83488
83489
83490
83491




83492
83493
83494
83495
83496
83497
83498
83093
83094
83095
83096
83097
83098
83099


83100
83101
83102
83103
83104
83105
83106
83107
83108
83109
83110







-
-
+
+
+
+








  /* Figure out how many bytes of space are required to store explicitly
  ** specified collation sequence names.
  */
  for(i=0; i<pList->nExpr; i++){
    Expr *pExpr = pList->a[i].pExpr;
    if( pExpr ){
      CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr);
      if( pColl ){
      CollSeq *pColl = pExpr->pColl;
      /* Either pColl!=0 or there was an OOM failure.  But if an OOM
      ** failure we have quit before reaching this point. */
      if( ALWAYS(pColl) ){
        nExtra += (1 + sqlite3Strlen30(pColl->zName));
      }
    }
  }

  /* 
  ** Allocate the index structure. 
83547
83548
83549
83550
83551
83552
83553
83554
83555
83556
83557
83558
83559
83560
83561
83562
83563
83564
83565
83566





83567

83568
83569
83570
83571

83572
83573
83574
83575
83576
83577
83578
83159
83160
83161
83162
83163
83164
83165

83166
83167
83168
83169
83170
83171
83172
83173
83174
83175
83176
83177
83178
83179
83180
83181
83182

83183


83184

83185
83186
83187
83188
83189
83190
83191
83192







-












+
+
+
+
+
-
+
-
-

-
+







  ** same column more than once cannot be an error because that would 
  ** break backwards compatibility - it needs to be a warning.
  */
  for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){
    const char *zColName = pListItem->zName;
    Column *pTabCol;
    int requestedSortOrder;
    CollSeq *pColl;                /* Collating sequence */
    char *zColl;                   /* Collation sequence name */

    for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){
      if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break;
    }
    if( j>=pTab->nCol ){
      sqlite3ErrorMsg(pParse, "table %s has no column named %s",
        pTab->zName, zColName);
      pParse->checkSchema = 1;
      goto exit_create_index;
    }
    pIndex->aiColumn[i] = j;
    /* Justification of the ALWAYS(pListItem->pExpr->pColl):  Because of
    ** the way the "idxlist" non-terminal is constructed by the parser,
    ** if pListItem->pExpr is not null then either pListItem->pExpr->pColl
    ** must exist or else there must have been an OOM error.  But if there
    ** was an OOM error, we would never reach this point. */
    if( pListItem->pExpr
    if( pListItem->pExpr && ALWAYS(pListItem->pExpr->pColl) ){
     && (pColl = sqlite3ExprCollSeq(pParse, pListItem->pExpr))!=0
    ){
      int nColl;
      zColl = pColl->zName;
      zColl = pListItem->pExpr->pColl->zName;
      nColl = sqlite3Strlen30(zColl) + 1;
      assert( nExtra>=nColl );
      memcpy(zExtra, zColl, nColl);
      zColl = zExtra;
      zExtra += nColl;
      nExtra -= nColl;
    }else{
84378
84379
84380
84381
84382
84383
84384
84385
84386
84387
84388
84389
84390
84391
84392
84393
84394
84395
84396
84397
84398
84399
84400
83992
83993
83994
83995
83996
83997
83998









83999
84000
84001
84002
84003
84004
84005







-
-
-
-
-
-
-
-
-







** If iDb<0 then code the OP_Goto only - don't set flag to verify the
** schema on any databases.  This can be used to position the OP_Goto
** early in the code, before we know if any database tables will be used.
*/
SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
  Parse *pToplevel = sqlite3ParseToplevel(pParse);

#ifndef SQLITE_OMIT_TRIGGER
  if( pToplevel!=pParse ){
    /* This branch is taken if a trigger is currently being coded. In this
    ** case, set cookieGoto to a non-zero value to show that this function
    ** has been called. This is used by the sqlite3ExprCodeConstants()
    ** function. */
    pParse->cookieGoto = -1;
  }
#endif
  if( pToplevel->cookieGoto==0 ){
    Vdbe *v = sqlite3GetVdbe(pToplevel);
    if( v==0 ) return;  /* This only happens if there was a prior error */
    pToplevel->cookieGoto = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0)+1;
  }
  if( iDb>=0 ){
    sqlite3 *db = pToplevel->db;
85253
85254
85255
85256
85257
85258
85259
85260
85261
85262
85263
85264
85265
85266
85267
84858
84859
84860
84861
84862
84863
84864

84865
84866
84867
84868
84869
84870
84871







-







      pFrom->a[0].pSelect = pDup;
      assert( pFrom->a[0].pOn==0 );
      assert( pFrom->a[0].pUsing==0 );
    }else{
      sqlite3SelectDelete(db, pDup);
    }
    pDup = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0);
    if( pDup ) pDup->selFlags |= SF_Materialize;
  }
  sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
  sqlite3Select(pParse, pDup, &dest);
  sqlite3SelectDelete(db, pDup);
}
#endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */

85964
85965
85966
85967
85968
85969
85970
85971
85972
85973
85974
85975
85976
85977
85978
85979
85980
85981
85982
85983
85984
85985
85986
85987
85988
85989
85990
85991
85992
85993
85994
85995
85996
85997
85998
85999
86000
86001
86002
86003
86004
86005
86006
86007
86008
86009
86010
86011
86012
86013
86014
86015
86016
86017
86018
86019
86020
86021
86022
86023
86024
86025
86026
86027
85568
85569
85570
85571
85572
85573
85574


















































85575
85576
85577
85578
85579
85580
85581







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







      if( rVal<0 ) rVal = -rVal;
      sqlite3_result_double(context, rVal);
      break;
    }
  }
}

/*
** Implementation of the instr() function.
**
** instr(haystack,needle) finds the first occurrence of needle
** in haystack and returns the number of previous characters plus 1,
** or 0 if needle does not occur within haystack.
**
** If both haystack and needle are BLOBs, then the result is one more than
** the number of bytes in haystack prior to the first occurrence of needle,
** or 0 if needle never occurs in haystack.
*/
static void instrFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const unsigned char *zHaystack;
  const unsigned char *zNeedle;
  int nHaystack;
  int nNeedle;
  int typeHaystack, typeNeedle;
  int N = 1;
  int isText;

  UNUSED_PARAMETER(argc);
  typeHaystack = sqlite3_value_type(argv[0]);
  typeNeedle = sqlite3_value_type(argv[1]);
  if( typeHaystack==SQLITE_NULL || typeNeedle==SQLITE_NULL ) return;
  nHaystack = sqlite3_value_bytes(argv[0]);
  nNeedle = sqlite3_value_bytes(argv[1]);
  if( typeHaystack==SQLITE_BLOB && typeNeedle==SQLITE_BLOB ){
    zHaystack = sqlite3_value_blob(argv[0]);
    zNeedle = sqlite3_value_blob(argv[1]);
    isText = 0;
  }else{
    zHaystack = sqlite3_value_text(argv[0]);
    zNeedle = sqlite3_value_text(argv[1]);
    isText = 1;
  }
  while( nNeedle<=nHaystack && memcmp(zHaystack, zNeedle, nNeedle)!=0 ){
    N++;
    do{
      nHaystack--;
      zHaystack++;
    }while( isText && (zHaystack[0]&0xc0)==0x80 );
  }
  if( nNeedle>nHaystack ) N = 0;
  sqlite3_result_int(context, N);
}

/*
** Implementation of the substr() function.
**
** substr(x,p1,p2)  returns p2 characters of x[] beginning with p1.
** p1 is 1-indexed.  So substr(x,1,1) returns the first character
** of x.  If x is text, then we actually count UTF-8 characters.
** If x is a blob, then we count bytes.
87382
87383
87384
87385
87386
87387
87388
87389
87390
87391
87392
87393
87394
87395
87396
86936
86937
86938
86939
86940
86941
86942

86943
86944
86945
86946
86947
86948
86949







-







    FUNCTION(min,                0, 0, 1, 0                ),
    AGGREGATE(min,               1, 0, 1, minmaxStep,      minMaxFinalize ),
    FUNCTION(max,               -1, 1, 1, minmaxFunc       ),
    FUNCTION(max,                0, 1, 1, 0                ),
    AGGREGATE(max,               1, 1, 1, minmaxStep,      minMaxFinalize ),
    FUNCTION2(typeof,            1, 0, 0, typeofFunc,  SQLITE_FUNC_TYPEOF),
    FUNCTION2(length,            1, 0, 0, lengthFunc,  SQLITE_FUNC_LENGTH),
    FUNCTION(instr,              2, 0, 0, instrFunc        ),
    FUNCTION(substr,             2, 0, 0, substrFunc       ),
    FUNCTION(substr,             3, 0, 0, substrFunc       ),
    FUNCTION(abs,                1, 0, 0, absFunc          ),
#ifndef SQLITE_OMIT_FLOATING_POINT
    FUNCTION(round,              1, 0, 0, roundFunc        ),
    FUNCTION(round,              2, 0, 0, roundFunc        ),
#endif
87597
87598
87599
87600
87601
87602
87603
87604

87605
87606
87607
87608
87609
87610
87611
87150
87151
87152
87153
87154
87155
87156

87157
87158
87159
87160
87161
87162
87163
87164







-
+







**   Register (x+3):      3.1  (type real)
*/

/*
** A foreign key constraint requires that the key columns in the parent
** table are collectively subject to a UNIQUE or PRIMARY KEY constraint.
** Given that pParent is the parent table for foreign key constraint pFKey, 
** search the schema for a unique index on the parent key columns. 
** search the schema a unique index on the parent key columns. 
**
** If successful, zero is returned. If the parent key is an INTEGER PRIMARY 
** KEY column, then output variable *ppIdx is set to NULL. Otherwise, *ppIdx 
** is set to point to the unique index. 
** 
** If the parent key consists of a single column (the foreign key constraint
** is not a composite foreign key), output variable *paiCol is set to NULL.
87633
87634
87635
87636
87637
87638
87639
87640

87641
87642
87643
87644
87645
87646
87647
87186
87187
87188
87189
87190
87191
87192

87193
87194
87195
87196
87197
87198
87199
87200







-
+







**      consists of a a different number of columns to the child key in 
**      the child table.
**
** then non-zero is returned, and a "foreign key mismatch" error loaded
** into pParse. If an OOM error occurs, non-zero is returned and the
** pParse->db->mallocFailed flag is set.
*/
SQLITE_PRIVATE int sqlite3FkLocateIndex(
static int locateFkeyIndex(
  Parse *pParse,                  /* Parse context to store any error in */
  Table *pParent,                 /* Parent table of FK constraint pFKey */
  FKey *pFKey,                    /* Foreign key to find index for */
  Index **ppIdx,                  /* OUT: Unique index on parent table */
  int **paiCol                    /* OUT: Map of index columns in pFKey */
){
  Index *pIdx = 0;                    /* Value to return via *ppIdx */
87730
87731
87732
87733
87734
87735
87736
87737

87738
87739
87740
87741
87742
87743
87744
87745
87746
87283
87284
87285
87286
87287
87288
87289

87290


87291
87292
87293
87294
87295
87296
87297







-
+
-
-







        if( i==nCol ) break;      /* pIdx is usable */
      }
    }
  }

  if( !pIdx ){
    if( !pParse->disableTriggers ){
      sqlite3ErrorMsg(pParse,
      sqlite3ErrorMsg(pParse, "foreign key mismatch");
           "foreign key mismatch - \"%w\" referencing \"%w\"",
           pFKey->pFrom->zName, pFKey->zTo);
    }
    sqlite3DbFree(pParse->db, aiCol);
    return 1;
  }

  *ppIdx = pIdx;
  return 0;
87968
87969
87970
87971
87972
87973
87974
87975
87976
87977
87978
87979
87980
87981

87982
87983
87984
87985
87986
87987
87988
87989
87990
87519
87520
87521
87522
87523
87524
87525

87526
87527
87528
87529
87530

87531


87532
87533
87534
87535
87536
87537
87538







-





-
+
-
-








    pLeft = sqlite3Expr(db, TK_REGISTER, 0);
    if( pLeft ){
      /* Set the collation sequence and affinity of the LHS of each TK_EQ
      ** expression to the parent key column defaults.  */
      if( pIdx ){
        Column *pCol;
        const char *zColl;
        iCol = pIdx->aiColumn[i];
        pCol = &pTab->aCol[iCol];
        if( pTab->iPKey==iCol ) iCol = -1;
        pLeft->iTable = regData+iCol+1;
        pLeft->affinity = pCol->affinity;
        zColl = pCol->zColl;
        pLeft->pColl = sqlite3LocateCollSeq(pParse, pCol->zColl);
        if( zColl==0 ) zColl = db->pDfltColl->zName;
        pLeft = sqlite3ExprAddCollateString(pParse, pLeft, zColl);
      }else{
        pLeft->iTable = regData;
        pLeft->affinity = SQLITE_AFF_INTEGER;
      }
    }
    iCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom;
    assert( iCol>=0 );
88193
88194
88195
88196
88197
88198
88199
88200

88201
88202
88203
88204
88205
88206
88207
87741
87742
87743
87744
87745
87746
87747

87748
87749
87750
87751
87752
87753
87754
87755







-
+







    ** schema items cannot be located, set an error in pParse and return 
    ** early.  */
    if( pParse->disableTriggers ){
      pTo = sqlite3FindTable(db, pFKey->zTo, zDb);
    }else{
      pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb);
    }
    if( !pTo || sqlite3FkLocateIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){
    if( !pTo || locateFkeyIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){
      assert( isIgnoreErrors==0 || (regOld!=0 && regNew==0) );
      if( !isIgnoreErrors || db->mallocFailed ) return;
      if( pTo==0 ){
        /* If isIgnoreErrors is true, then a table is being dropped. In this
        ** case SQLite runs a "DELETE FROM xxx" on the table being dropped
        ** before actually dropping it in order to check FK constraints.
        ** If the parent table of an FK constraint on the current table is
88273
88274
88275
88276
88277
88278
88279
88280

88281
88282
88283
88284
88285
88286
88287
87821
87822
87823
87824
87825
87826
87827

87828
87829
87830
87831
87832
87833
87834
87835







-
+







    if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){
      assert( regOld==0 && regNew!=0 );
      /* Inserting a single row into a parent table cannot cause an immediate
      ** foreign key violation. So do nothing in this case.  */
      continue;
    }

    if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){
    if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){
      if( !isIgnoreErrors || db->mallocFailed ) return;
      continue;
    }
    assert( aiCol || pFKey->nCol==1 );

    /* Create a SrcList structure containing a single table (the table 
    ** the foreign key that refers to this table is attached to). This
88328
88329
88330
88331
88332
88333
88334
88335

88336
88337
88338
88339
88340
88341
88342
87876
87877
87878
87879
87880
87881
87882

87883
87884
87885
87886
87887
87888
87889
87890







-
+







    FKey *p;
    int i;
    for(p=pTab->pFKey; p; p=p->pNextFrom){
      for(i=0; i<p->nCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom);
    }
    for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
      Index *pIdx = 0;
      sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0);
      locateFkeyIndex(pParse, pTab, p, &pIdx, 0);
      if( pIdx ){
        for(i=0; i<pIdx->nColumn; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]);
      }
    }
  }
  return mask;
}
88454
88455
88456
88457
88458
88459
88460
88461

88462
88463
88464
88465
88466
88467
88468
88002
88003
88004
88005
88006
88007
88008

88009
88010
88011
88012
88013
88014
88015
88016







-
+







    TriggerStep *pStep = 0;        /* First (only) step of trigger program */
    Expr *pWhere = 0;             /* WHERE clause of trigger step */
    ExprList *pList = 0;          /* Changes list if ON UPDATE CASCADE */
    Select *pSelect = 0;          /* If RESTRICT, "SELECT RAISE(...)" */
    int i;                        /* Iterator variable */
    Expr *pWhen = 0;              /* WHEN clause for the trigger */

    if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0;
    if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0;
    assert( aiCol || pFKey->nCol==1 );

    for(i=0; i<pFKey->nCol; i++){
      Token tOld = { "old", 3 };  /* Literal "old" token */
      Token tNew = { "new", 3 };  /* Literal "new" token */
      Token tFromCol;             /* Name of column in child table */
      Token tToCol;               /* Name of column in parent table */
88707
88708
88709
88710
88711
88712
88713
88714

88715
88716
88717
88718
88719
88720
88721
88255
88256
88257
88258
88259
88260
88261

88262
88263
88264
88265
88266
88267
88268
88269







-
+







  Parse *p,       /* Generate code into this VDBE */
  int iCur,       /* The cursor number of the table */
  int iDb,        /* The database index in sqlite3.aDb[] */
  Table *pTab,    /* The table to be opened */
  int opcode      /* OP_OpenRead or OP_OpenWrite */
){
  Vdbe *v;
  assert( !IsVirtual(pTab) );
  if( IsVirtual(pTab) ) return;
  v = sqlite3GetVdbe(p);
  assert( opcode==OP_OpenWrite || opcode==OP_OpenRead );
  sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite)?1:0, pTab->zName);
  sqlite3VdbeAddOp3(v, opcode, iCur, pTab->tnum, iDb);
  sqlite3VdbeChangeP4(v, -1, SQLITE_INT_TO_PTR(pTab->nCol), P4_INT32);
  VdbeComment((v, "%s", pTab->zName));
}
89956
89957
89958
89959
89960
89961
89962



89963
89964
89965
89966
89967
89968
89969
89970
89971
89972
89973
89974
89975
89976
















89977
89978
89979
89980
89981
89982
89983
89504
89505
89506
89507
89508
89509
89510
89511
89512
89513














89514
89515
89516
89517
89518
89519
89520
89521
89522
89523
89524
89525
89526
89527
89528
89529
89530
89531
89532
89533
89534
89535
89536







+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







#ifndef SQLITE_OMIT_CHECK
  if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
    ExprList *pCheck = pTab->pCheck;
    pParse->ckBase = regData;
    onError = overrideError!=OE_Default ? overrideError : OE_Abort;
    for(i=0; i<pCheck->nExpr; i++){
      int allOk = sqlite3VdbeMakeLabel(v);
      Expr *pDup = sqlite3ExprDup(db, pCheck->a[i].pExpr, 0);
      if( !db->mallocFailed ){
        assert( pDup!=0 );
      sqlite3ExprIfTrue(pParse, pCheck->a[i].pExpr, allOk, SQLITE_JUMPIFNULL);
      if( onError==OE_Ignore ){
        sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
      }else{
        char *zConsName = pCheck->a[i].zName;
        if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */
        if( zConsName ){
          zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName);
        }else{
          zConsName = 0;
        }
        sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC);
      }
      sqlite3VdbeResolveLabel(v, allOk);
        sqlite3ExprIfTrue(pParse, pDup, allOk, SQLITE_JUMPIFNULL);
        if( onError==OE_Ignore ){
          sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
        }else{
          char *zConsName = pCheck->a[i].zName;
          if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */
          if( zConsName ){
            zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName);
          }else{
            zConsName = 0;
          }
          sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC);
        }
        sqlite3VdbeResolveLabel(v, allOk);
      }
      sqlite3ExprDelete(db, pDup);
    }
  }
#endif /* !defined(SQLITE_OMIT_CHECK) */

  /* If we have an INTEGER PRIMARY KEY, make sure the primary key
  ** of the new record does not previously exist.  Except, if this
  ** is an UPDATE and the primary key is not changing, that is OK.
92794
92795
92796
92797
92798
92799
92800
92801

92802
92803
92804
92805
92806
92807
92808
92809
92810
92811
92812
92347
92348
92349
92350
92351
92352
92353

92354
92355
92356


92357
92358
92359
92360
92361
92362
92363







-
+


-
-







  ** dflt_value: The default value for the column, if any.
  */
  if( sqlite3StrICmp(zLeft, "table_info")==0 && zRight ){
    Table *pTab;
    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
    pTab = sqlite3FindTable(db, zRight, zDb);
    if( pTab ){
      int i, k;
      int i;
      int nHidden = 0;
      Column *pCol;
      Index *pPk;
      for(pPk=pTab->pIndex; pPk && pPk->autoIndex!=2; pPk=pPk->pNext){}
      sqlite3VdbeSetNumCols(v, 6);
      pParse->nMem = 6;
      sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", SQLITE_STATIC);
      sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
      sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "type", SQLITE_STATIC);
      sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "notnull", SQLITE_STATIC);
      sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "dflt_value", SQLITE_STATIC);
92823
92824
92825
92826
92827
92828
92829
92830
92831
92832
92833
92834
92835
92836
92837


92838
92839
92840
92841
92842
92843
92844
92374
92375
92376
92377
92378
92379
92380








92381
92382
92383
92384
92385
92386
92387
92388
92389







-
-
-
-
-
-
-
-
+
+







           pCol->zType ? pCol->zType : "", 0);
        sqlite3VdbeAddOp2(v, OP_Integer, (pCol->notNull ? 1 : 0), 4);
        if( pCol->zDflt ){
          sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)pCol->zDflt, 0);
        }else{
          sqlite3VdbeAddOp2(v, OP_Null, 0, 5);
        }
        if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){
          k = 0;
        }else if( pPk==0 ){
          k = 1;
        }else{
          for(k=1; ALWAYS(k<=pTab->nCol) && pPk->aiColumn[k-1]!=i; k++){}
        }
        sqlite3VdbeAddOp2(v, OP_Integer, k, 6);
        sqlite3VdbeAddOp2(v, OP_Integer,
                            (pCol->colFlags&COLFLAG_PRIMKEY)!=0, 6);
        sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6);
      }
    }
  }else

  if( sqlite3StrICmp(zLeft, "index_info")==0 && zRight ){
    Index *pIdx;
92965
92966
92967
92968
92969
92970
92971
92972
92973
92974
92975
92976
92977
92978
92979
92980
92981
92982
92983
92984
92985
92986
92987
92988
92989
92990
92991
92992
92993
92994
92995
92996
92997
92998
92999
93000
93001
93002
93003
93004
93005
93006
93007
93008
93009
93010
93011
93012
93013
93014
93015
93016
93017
93018
93019
93020
93021
93022
93023
93024
93025
93026
93027
93028
93029
93030
93031
93032
93033
93034
93035
93036
93037
93038
93039
93040
93041
93042
93043
93044
93045
93046
93047
93048
93049
93050
93051
93052
93053
93054
93055
93056
93057
93058
93059
93060
93061
93062
93063
93064
93065
93066
93067
93068
93069
93070
93071
93072
93073
93074
93075
93076
93077
93078
93079
93080
93081
93082
93083
93084
93085
93086
93087
93088
93089
93090
93091
93092
92510
92511
92512
92513
92514
92515
92516


















































































































92517
92518
92519
92520
92521
92522
92523







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







            sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 8);
          }
          ++i;
          pFK = pFK->pNextFrom;
        }
      }
    }
  }else
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */

#ifndef SQLITE_OMIT_FOREIGN_KEY
  if( sqlite3StrICmp(zLeft, "foreign_key_check")==0 ){
    FKey *pFK;             /* A foreign key constraint */
    Table *pTab;           /* Child table contain "REFERENCES" keyword */
    Table *pParent;        /* Parent table that child points to */
    Index *pIdx;           /* Index in the parent table */
    int i;                 /* Loop counter:  Foreign key number for pTab */
    int j;                 /* Loop counter:  Field of the foreign key */
    HashElem *k;           /* Loop counter:  Next table in schema */
    int x;                 /* result variable */
    int regResult;         /* 3 registers to hold a result row */
    int regKey;            /* Register to hold key for checking the FK */
    int regRow;            /* Registers to hold a row from pTab */
    int addrTop;           /* Top of a loop checking foreign keys */
    int addrOk;            /* Jump here if the key is OK */
    int *aiCols;           /* child to parent column mapping */

    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
    regResult = pParse->nMem+1;
    pParse->nMem += 4;
    regKey = ++pParse->nMem;
    regRow = ++pParse->nMem;
    v = sqlite3GetVdbe(pParse);
    sqlite3VdbeSetNumCols(v, 4);
    sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "table", SQLITE_STATIC);
    sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "rowid", SQLITE_STATIC);
    sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "parent", SQLITE_STATIC);
    sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "fkid", SQLITE_STATIC);
    sqlite3CodeVerifySchema(pParse, iDb);
    k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash);
    while( k ){
      if( zRight ){
        pTab = sqlite3LocateTable(pParse, 0, zRight, zDb);
        k = 0;
      }else{
        pTab = (Table*)sqliteHashData(k);
        k = sqliteHashNext(k);
      }
      if( pTab==0 || pTab->pFKey==0 ) continue;
      sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
      if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow;
      sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead);
      sqlite3VdbeAddOp4(v, OP_String8, 0, regResult, 0, pTab->zName,
                        P4_TRANSIENT);
      for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
        pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb);
        if( pParent==0 ) break;
        pIdx = 0;
        sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName);
        x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0);
        if( x==0 ){
          if( pIdx==0 ){
            sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead);
          }else{
            KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
            sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb);
            sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF);
          }
        }else{
          k = 0;
          break;
        }
      }
      if( pFK ) break;
      if( pParse->nTab<i ) pParse->nTab = i;
      addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0);
      for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
        pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb);
        assert( pParent!=0 );
        pIdx = 0;
        aiCols = 0;
        x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
        assert( x==0 );
        addrOk = sqlite3VdbeMakeLabel(v);
        if( pIdx==0 ){
          int iKey = pFK->aCol[0].iFrom;
          assert( iKey>=0 && iKey<pTab->nCol );
          if( iKey!=pTab->iPKey ){
            sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow);
            sqlite3ColumnDefault(v, pTab, iKey, regRow);
            sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk);
            sqlite3VdbeAddOp2(v, OP_MustBeInt, regRow,
               sqlite3VdbeCurrentAddr(v)+3);
          }else{
            sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow);
          }
          sqlite3VdbeAddOp3(v, OP_NotExists, i, 0, regRow);
          sqlite3VdbeAddOp2(v, OP_Goto, 0, addrOk);
          sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
        }else{
          for(j=0; j<pFK->nCol; j++){
            sqlite3ExprCodeGetColumnOfTable(v, pTab, 0,
                            aiCols ? aiCols[j] : pFK->aCol[0].iFrom, regRow+j);
            sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk);
          }
          sqlite3VdbeAddOp3(v, OP_MakeRecord, regRow, pFK->nCol, regKey);
          sqlite3VdbeChangeP4(v, -1,
                   sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT);
          sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
        }
        sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1);
        sqlite3VdbeAddOp4(v, OP_String8, 0, regResult+2, 0, 
                          pFK->zTo, P4_TRANSIENT);
        sqlite3VdbeAddOp2(v, OP_Integer, i-1, regResult+3);
        sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 4);
        sqlite3VdbeResolveLabel(v, addrOk);
        sqlite3DbFree(db, aiCols);
      }
      sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop+1);
      sqlite3VdbeJumpHere(v, addrTop);
    }
  }else
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */

#ifndef NDEBUG
  if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){
    if( zRight ){
      if( sqlite3GetBoolean(zRight, 0) ){
93579
93580
93581
93582
93583
93584
93585
93586

93587
93588
93589
93590
93591
93592
93593
93010
93011
93012
93013
93014
93015
93016

93017
93018
93019
93020
93021
93022
93023
93024







-
+







      sqlite3_key(db, zKey, i/2);
    }else{
      sqlite3_rekey(db, zKey, i/2);
    }
  }else
#endif
#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
  if( sqlite3StrICmp(zLeft, "activate_extensions")==0 && zRight ){
  if( sqlite3StrICmp(zLeft, "activate_extensions")==0 ){
#ifdef SQLITE_HAS_CODEC
    if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){
      sqlite3_activate_see(&zRight[4]);
    }
#endif
#ifdef SQLITE_ENABLE_CEROD
    if( sqlite3StrNICmp(zRight, "cerod-", 6)==0 ){
94538
94539
94540
94541
94542
94543
94544
94545

94546
94547
94548
94549
94550
94551
94552
93969
93970
93971
93972
93973
93974
93975

93976
93977
93978
93979
93980
93981
93982
93983







-
+







  Parse *pParse,        /* Parsing context */
  ExprList *pEList,     /* which columns to include in the result */
  SrcList *pSrc,        /* the FROM clause -- which tables to scan */
  Expr *pWhere,         /* the WHERE clause */
  ExprList *pGroupBy,   /* the GROUP BY clause */
  Expr *pHaving,        /* the HAVING clause */
  ExprList *pOrderBy,   /* the ORDER BY clause */
  u16 selFlags,         /* Flag parameters, such as SF_Distinct */
  int isDistinct,       /* true if the DISTINCT keyword is present */
  Expr *pLimit,         /* LIMIT value.  NULL means not used */
  Expr *pOffset         /* OFFSET value.  NULL means no offset */
){
  Select *pNew;
  Select standin;
  sqlite3 *db = pParse->db;
  pNew = sqlite3DbMallocZero(db, sizeof(*pNew) );
94562
94563
94564
94565
94566
94567
94568
94569

94570
94571
94572
94573
94574
94575
94576
93993
93994
93995
93996
93997
93998
93999

94000
94001
94002
94003
94004
94005
94006
94007







-
+







  pNew->pEList = pEList;
  if( pSrc==0 ) pSrc = sqlite3DbMallocZero(db, sizeof(*pSrc));
  pNew->pSrc = pSrc;
  pNew->pWhere = pWhere;
  pNew->pGroupBy = pGroupBy;
  pNew->pHaving = pHaving;
  pNew->pOrderBy = pOrderBy;
  pNew->selFlags = selFlags;
  pNew->selFlags = isDistinct ? SF_Distinct : 0;
  pNew->op = TK_SELECT;
  pNew->pLimit = pLimit;
  pNew->pOffset = pOffset;
  assert( pOffset==0 || pLimit!=0 );
  pNew->addrOpenEphm[0] = -1;
  pNew->addrOpenEphm[1] = -1;
  pNew->addrOpenEphm[2] = -1;
95818
95819
95820
95821
95822
95823
95824
95825



95826
95827
95828
95829
95830
95831
95832
95249
95250
95251
95252
95253
95254
95255

95256
95257
95258
95259
95260
95261
95262
95263
95264
95265







-
+
+
+







  }
  *pnCol = nCol;
  *paCol = aCol;

  for(i=0, pCol=aCol; i<nCol; i++, pCol++){
    /* Get an appropriate name for the column
    */
    p = sqlite3ExprSkipCollate(pEList->a[i].pExpr);
    p = pEList->a[i].pExpr;
    assert( p->pRight==0 || ExprHasProperty(p->pRight, EP_IntValue)
               || p->pRight->u.zToken==0 || p->pRight->u.zToken[0]!=0 );
    if( (zName = pEList->a[i].zName)!=0 ){
      /* If the column contains an "AS <name>" phrase, use <name> as the name */
      zName = sqlite3DbStrDup(db, zName);
    }else{
      Expr *pColExpr = p;  /* The expression that is the result column name */
      Table *pTab;         /* Table associated with this expression */
      while( pColExpr->op==TK_DOT ){
95856
95857
95858
95859
95860
95861
95862
95863
95864
95865
95866
95867
95868
95869
95870
95871
95872
95289
95290
95291
95292
95293
95294
95295



95296
95297
95298
95299
95300
95301
95302







-
-
-







    /* Make sure the column name is unique.  If the name is not unique,
    ** append a integer to the name so that it becomes unique.
    */
    nName = sqlite3Strlen30(zName);
    for(j=cnt=0; j<i; j++){
      if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){
        char *zNewName;
        int k;
        for(k=nName-1; k>1 && sqlite3Isdigit(zName[k]); k--){}
        if( zName[k]==':' ) nName = k;
        zName[nName] = 0;
        zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt);
        sqlite3DbFree(db, zName);
        zName = zNewName;
        j = -1;
        if( zName==0 ) break;
      }
96817
96818
96819
96820
96821
96822
96823
96824
96825


96826
96827
96828

96829
96830

96831
96832
96833
96834
96835
96836
96837
96247
96248
96249
96250
96251
96252
96253


96254
96255
96256
96257

96258


96259
96260
96261
96262
96263
96264
96265
96266







-
-
+
+


-
+
-
-
+







    if( pKeyMerge ){
      pKeyMerge->aSortOrder = (u8*)&pKeyMerge->aColl[nOrderBy];
      pKeyMerge->nField = (u16)nOrderBy;
      pKeyMerge->enc = ENC(db);
      for(i=0; i<nOrderBy; i++){
        CollSeq *pColl;
        Expr *pTerm = pOrderBy->a[i].pExpr;
        if( pTerm->flags & EP_Collate ){
          pColl = sqlite3ExprCollSeq(pParse, pTerm);
        if( pTerm->flags & EP_ExpCollate ){
          pColl = pTerm->pColl;
        }else{
          pColl = multiSelectCollSeq(pParse, p, aPermute[i]);
          if( pColl==0 ) pColl = db->pDfltColl;
          pTerm->flags |= EP_ExpCollate;
          pOrderBy->a[i].pExpr =
             sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName);
          pTerm->pColl = pColl;
        }
        pKeyMerge->aColl[i] = pColl;
        pKeyMerge->aSortOrder[i] = pOrderBy->a[i].sortOrder;
      }
    }
  }else{
    pKeyMerge = 0;
97026
97027
97028
97029
97030
97031
97032
97033
97034
97035
97036
97037
97038
97039
97040
96455
96456
96457
96458
96459
96460
96461

96462
96463
96464
96465
96466
96467
96468







-








  /* Implement the main merge loop
  */
  sqlite3VdbeResolveLabel(v, labelCmpr);
  sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY);
  sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy,
                         (char*)pKeyMerge, P4_KEYINFO_HANDOFF);
  sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE);
  sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB);

  /* Release temporary registers
  */
  if( regPrev ){
    sqlite3ReleaseTempRange(pParse, regPrev, nOrderBy+1);
  }
97094
97095
97096
97097
97098
97099
97100



97101
97102
97103
97104
97105
97106
97107
96522
96523
96524
96525
96526
96527
96528
96529
96530
96531
96532
96533
96534
96535
96536
96537
96538







+
+
+







    if( pExpr->iColumn<0 ){
      pExpr->op = TK_NULL;
    }else{
      Expr *pNew;
      assert( pEList!=0 && pExpr->iColumn<pEList->nExpr );
      assert( pExpr->pLeft==0 && pExpr->pRight==0 );
      pNew = sqlite3ExprDup(db, pEList->a[pExpr->iColumn].pExpr, 0);
      if( pNew && pExpr->pColl ){
        pNew->pColl = pExpr->pColl;
      }
      sqlite3ExprDelete(db, pExpr);
      pExpr = pNew;
    }
  }else{
    pExpr->pLeft = substExpr(db, pExpr->pLeft, iTable, pEList);
    pExpr->pRight = substExpr(db, pExpr->pRight, iTable, pEList);
    if( ExprHasProperty(pExpr, EP_xIsSelect) ){
97581
97582
97583
97584
97585
97586
97587
97588
97589
97590




97591
97592
97593
97594
97595
97596
97597
97012
97013
97014
97015
97016
97017
97018



97019
97020
97021
97022
97023
97024
97025
97026
97027
97028
97029







-
-
-
+
+
+
+







    **
    ** We look at every expression in the outer query and every place we see
    ** "a" we substitute "x*3" and every place we see "b" we substitute "y+10".
    */
    pList = pParent->pEList;
    for(i=0; i<pList->nExpr; i++){
      if( pList->a[i].zName==0 ){
        char *zName = sqlite3DbStrDup(db, pList->a[i].zSpan);
        sqlite3Dequote(zName);
        pList->a[i].zName = zName;
        const char *zSpan = pList->a[i].zSpan;
        if( ALWAYS(zSpan) ){
          pList->a[i].zName = sqlite3DbStrDup(db, zSpan);
        }
      }
    }
    substExprList(db, pParent->pEList, iParent, pSub->pEList);
    if( isAgg ){
      substExprList(db, pParent->pGroupBy, iParent, pSub->pEList);
      pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList);
    }
97644
97645
97646
97647
97648
97649
97650
97651
97652




97653
97654

97655
97656
97657
97658
97659


97660
97661
97662
97663
97664
97665

97666
97667
97668
97669
97670
97671


97672


97673
97674
97675
97676
97677








97678
97679
97680


97681
97682

97683
97684
97685
97686
97687

97688
97689
97690
97691
97692
97693
97694
97076
97077
97078
97079
97080
97081
97082


97083
97084
97085
97086
97087

97088


97089


97090
97091




97092

97093






97094
97095
97096
97097
97098





97099
97100
97101
97102
97103
97104
97105
97106



97107
97108


97109





97110
97111
97112
97113
97114
97115
97116
97117







-
-
+
+
+
+

-
+
-
-

-
-
+
+
-
-
-
-

-
+
-
-
-
-
-
-
+
+

+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
+
+
-
-
+
-
-
-
-
-
+







  sqlite3SelectDelete(db, pSub1);

  return 1;
}
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */

/*
** Based on the contents of the AggInfo structure indicated by the first
** argument, this function checks if the following are true:
** Analyze the SELECT statement passed as an argument to see if it
** is a min() or max() query. Return WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX if 
** it is, or 0 otherwise. At present, a query is considered to be
** a min()/max() query if:
**
**    * the query contains just a single aggregate function,
**   1. There is a single object in the FROM clause.
**    * the aggregate function is either min() or max(), and
**    * the argument to the aggregate function is a column value.
**
** If all of the above are true, then WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX
** is returned as appropriate. Also, *ppMinMax is set to point to the 
**   2. There is a single expression in the result set, and it is
**      either min(x) or max(x), where x is a column reference.
** list of arguments passed to the aggregate before returning.
**
** Or, if the conditions above are not met, *ppMinMax is set to 0 and
** WHERE_ORDERBY_NORMAL is returned.
*/
static u8 minMaxQuery(AggInfo *pAggInfo, ExprList **ppMinMax){
static u8 minMaxQuery(Select *p){
  int eRet = WHERE_ORDERBY_NORMAL;          /* Return value */

  *ppMinMax = 0;
  if( pAggInfo->nFunc==1 ){
    Expr *pExpr = pAggInfo->aFunc[0].pExpr; /* Aggregate function */
    ExprList *pEList = pExpr->x.pList;      /* Arguments to agg function */
  Expr *pExpr;
  ExprList *pEList = p->pEList;

  if( pEList->nExpr!=1 ) return WHERE_ORDERBY_NORMAL;
  pExpr = pEList->a[0].pExpr;
    assert( pExpr->op==TK_AGG_FUNCTION );
    if( pEList && pEList->nExpr==1 && pEList->a[0].pExpr->op==TK_AGG_COLUMN ){
      const char *zFunc = pExpr->u.zToken;
      if( sqlite3StrICmp(zFunc, "min")==0 ){
        eRet = WHERE_ORDERBY_MIN;
  if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
  if( NEVER(ExprHasProperty(pExpr, EP_xIsSelect)) ) return 0;
  pEList = pExpr->x.pList;
  if( pEList==0 || pEList->nExpr!=1 ) return 0;
  if( pEList->a[0].pExpr->op!=TK_AGG_COLUMN ) return WHERE_ORDERBY_NORMAL;
  assert( !ExprHasProperty(pExpr, EP_IntValue) );
  if( sqlite3StrICmp(pExpr->u.zToken,"min")==0 ){
    return WHERE_ORDERBY_MIN;
        *ppMinMax = pEList;
      }else if( sqlite3StrICmp(zFunc, "max")==0 ){
        eRet = WHERE_ORDERBY_MAX;
  }else if( sqlite3StrICmp(pExpr->u.zToken,"max")==0 ){
    return WHERE_ORDERBY_MAX;
        *ppMinMax = pEList;
      }
  }
    }
  }

  assert( *ppMinMax==0 || (*ppMinMax)->nExpr==1 );
  return eRet;
  return WHERE_ORDERBY_NORMAL;
}

/*
** The select statement passed as the first argument is an aggregate query.
** The second argment is the associated aggregate-info object. This 
** function tests if the SELECT is of the form:
**
97775
97776
97777
97778
97779
97780
97781
97782
97783
97784
97785
97786
97787
97788
97789
97198
97199
97200
97201
97202
97203
97204

97205
97206
97207
97208
97209
97210
97211







-







static int selectExpander(Walker *pWalker, Select *p){
  Parse *pParse = pWalker->pParse;
  int i, j, k;
  SrcList *pTabList;
  ExprList *pEList;
  struct SrcList_item *pFrom;
  sqlite3 *db = pParse->db;
  Expr *pE, *pRight, *pExpr;

  if( db->mallocFailed  ){
    return WRC_Abort;
  }
  if( NEVER(p->pSrc==0) || (p->selFlags & SF_Expanded)!=0 ){
    return WRC_Prune;
  }
97861
97862
97863
97864
97865
97866
97867
97868

97869
97870
97871
97872
97873
97874
97875
97876
97877
97878
97879
97880
97881
97882
97883
97884
97885
97886
97887
97888
97889
97890
97891
97892
97893
97894

97895
97896
97897


97898
97899
97900
97901
97902
97903
97904
97905
97906
97907
97908
97909
97910
97911
97912

97913
97914
97915
97916


97917
97918
97919
97920
97921
97922
97923
97924
97925
97926
97927
97928
97929
97930
97931
97932
97933




97934
97935
97936

97937
97938
97939
97940
97941
97942
97943
97944
97945
97946
97947
97948
97949
97950
97951
97952
97953
97954
97955
97956
97957
97958
97959
97960
97961
97962
97963
97964
97283
97284
97285
97286
97287
97288
97289

97290
97291
97292
97293
97294
97295
97296
97297
97298
97299
97300
97301
97302
97303
97304
97305
97306
97307







97308

97309



97310
97311
97312
97313
97314
97315
97316
97317
97318
97319
97320
97321
97322
97323
97324
97325

97326
97327
97328
97329
97330
97331
97332
97333
97334
97335

97336


97337
97338
97339
97340






97341
97342
97343
97344


97345
97346
97347
97348
97349
97350
97351







97352
97353
97354
97355
97356
97357
97358
97359

97360
97361
97362
97363
97364
97365
97366







-
+

















-
-
-
-
-
-
-

-
+
-
-
-
+
+














-
+




+
+



-

-
-




-
-
-
-
-
-
+
+
+
+
-
-

+





-
-
-
-
-
-
-








-







  ** The following code just has to locate the TK_ALL expressions and expand
  ** each one to the list of all columns in all tables.
  **
  ** The first loop just checks to see if there are any "*" operators
  ** that need expanding.
  */
  for(k=0; k<pEList->nExpr; k++){
    pE = pEList->a[k].pExpr;
    Expr *pE = pEList->a[k].pExpr;
    if( pE->op==TK_ALL ) break;
    assert( pE->op!=TK_DOT || pE->pRight!=0 );
    assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) );
    if( pE->op==TK_DOT && pE->pRight->op==TK_ALL ) break;
  }
  if( k<pEList->nExpr ){
    /*
    ** If we get here it means the result set contains one or more "*"
    ** operators that need to be expanded.  Loop through each expression
    ** in the result set and expand them one by one.
    */
    struct ExprList_item *a = pEList->a;
    ExprList *pNew = 0;
    int flags = pParse->db->flags;
    int longNames = (flags & SQLITE_FullColNames)!=0
                      && (flags & SQLITE_ShortColNames)==0;

    /* When processing FROM-clause subqueries, it is always the case
    ** that full_column_names=OFF and short_column_names=ON.  The
    ** sqlite3ResultSetOfSelect() routine makes it so. */
    assert( (p->selFlags & SF_NestedFrom)==0
          || ((flags & SQLITE_FullColNames)==0 &&
              (flags & SQLITE_ShortColNames)!=0) );

    for(k=0; k<pEList->nExpr; k++){
      pE = a[k].pExpr;
      Expr *pE = a[k].pExpr;
      pRight = pE->pRight;
      assert( pE->op!=TK_DOT || pRight!=0 );
      if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pRight->op!=TK_ALL) ){
      assert( pE->op!=TK_DOT || pE->pRight!=0 );
      if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pE->pRight->op!=TK_ALL) ){
        /* This particular expression does not need to be expanded.
        */
        pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr);
        if( pNew ){
          pNew->a[pNew->nExpr-1].zName = a[k].zName;
          pNew->a[pNew->nExpr-1].zSpan = a[k].zSpan;
          a[k].zName = 0;
          a[k].zSpan = 0;
        }
        a[k].pExpr = 0;
      }else{
        /* This expression is a "*" or a "TABLE.*" and needs to be
        ** expanded. */
        int tableSeen = 0;      /* Set to 1 when TABLE matches */
        char *zTName = 0;       /* text of name of TABLE */
        char *zTName;            /* text of name of TABLE */
        if( pE->op==TK_DOT ){
          assert( pE->pLeft!=0 );
          assert( !ExprHasProperty(pE->pLeft, EP_IntValue) );
          zTName = pE->pLeft->u.zToken;
        }else{
          zTName = 0;
        }
        for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
          Table *pTab = pFrom->pTab;
          Select *pSub = pFrom->pSelect;
          char *zTabName = pFrom->zAlias;
          const char *zSchemaName = 0;
          int iDb;
          if( zTabName==0 ){
            zTabName = pTab->zName;
          }
          if( db->mallocFailed ) break;
          if( pSub==0 || (pSub->selFlags & SF_NestedFrom)==0 ){
            pSub = 0;
            if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
              continue;
            }
            iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
          if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
            continue;
          }
          tableSeen = 1;
            zSchemaName = iDb>=0 ? db->aDb[iDb].zName : "*";
          }
          for(j=0; j<pTab->nCol; j++){
            Expr *pExpr, *pRight;
            char *zName = pTab->aCol[j].zName;
            char *zColname;  /* The computed column name */
            char *zToFree;   /* Malloced string that needs to be freed */
            Token sColname;  /* Computed column name as a token */

            assert( zName );
            if( zTName && pSub
             && sqlite3MatchSpanName(pSub->pEList->a[j].zSpan, 0, zTName, 0)==0
            ){
              continue;
            }

            /* If a column is marked as 'hidden' (currently only possible
            ** for virtual tables), do not include it in the expanded
            ** result-set list.
            */
            if( IsHiddenColumn(&pTab->aCol[j]) ){
              assert(IsVirtual(pTab));
              continue;
            }
            tableSeen = 1;

            if( i>0 && zTName==0 ){
              if( (pFrom->jointype & JT_NATURAL)!=0
                && tableAndColumnIndex(pTabList, i, zName, 0, 0)
              ){
                /* In a NATURAL join, omit the join columns from the 
                ** table to the right of the join */
97973
97974
97975
97976
97977
97978
97979
97980
97981
97982
97983
97984
97985
97986
97987
97988
97989
97990
97991
97992
97993
97994
97995
97996
97997
97998
97999
98000
98001
98002
98003
98004
98005
98006
98007
98008
98009
98010
98011
98012
98013
97375
97376
97377
97378
97379
97380
97381




97382
97383
97384
97385
97386
97387
97388
97389
97390
97391
97392












97393
97394
97395
97396
97397
97398
97399







-
-
-
-











-
-
-
-
-
-
-
-
-
-
-
-







            pRight = sqlite3Expr(db, TK_ID, zName);
            zColname = zName;
            zToFree = 0;
            if( longNames || pTabList->nSrc>1 ){
              Expr *pLeft;
              pLeft = sqlite3Expr(db, TK_ID, zTabName);
              pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
              if( zSchemaName ){
                pLeft = sqlite3Expr(db, TK_ID, zSchemaName);
                pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pExpr, 0);
              }
              if( longNames ){
                zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName);
                zToFree = zColname;
              }
            }else{
              pExpr = pRight;
            }
            pNew = sqlite3ExprListAppend(pParse, pNew, pExpr);
            sColname.z = zColname;
            sColname.n = sqlite3Strlen30(zColname);
            sqlite3ExprListSetName(pParse, pNew, &sColname, 0);
            if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){
              struct ExprList_item *pX = &pNew->a[pNew->nExpr-1];
              if( pSub ){
                pX->zSpan = sqlite3DbStrDup(db, pSub->pEList->a[j].zSpan);
                testcase( pX->zSpan==0 );
              }else{
                pX->zSpan = sqlite3MPrintf(db, "%s.%s.%s",
                                           zSchemaName, zTabName, zColname);
                testcase( pX->zSpan==0 );
              }
              pX->bSpanIsTab = 1;
            }
            sqlite3DbFree(db, zToFree);
          }
        }
        if( !tableSeen ){
          if( zTName ){
            sqlite3ErrorMsg(pParse, "no such table: %s", zTName);
          }else{
98438
98439
98440
98441
98442
98443
98444
98445
98446
98447
98448
98449
98450
98451
98452
98453
98454

98455
98456
98457
98458
98459
98460
98461
98462
98463
98464
98465
98466
98467
98468
98469
98470
98471
98472
98473
98474
98475
98476
98477
98478
98479
98480
98481
98482
98483
98484
98485
98486
98487
98488
98489
98490
98491
98492
98493
98494
98495
98496
98497
98498
98499
98500
98501
98502
98503
98504
98505
98506
98507
98508
98509
98510
98511
98512
98513
98514
98515
98516
98517
98518
98519
98520
97824
97825
97826
97827
97828
97829
97830







97831


97832

97833
97834
97835
97836
97837
97838
97839
97840
97841
97842
97843
97844
97845
97846
97847
97848
97849
97850
97851
97852






































97853
97854
97855
97856
97857
97858
97859







-
-
-
-
-
-
-

-
-
+
-




















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







  for(i=0; !p->pPrior && i<pTabList->nSrc; i++){
    struct SrcList_item *pItem = &pTabList->a[i];
    SelectDest dest;
    Select *pSub = pItem->pSelect;
    int isAggSub;

    if( pSub==0 ) continue;

    /* Sometimes the code for a subquery will be generated more than
    ** once, if the subquery is part of the WHERE clause in a LEFT JOIN,
    ** for example.  In that case, do not regenerate the code to manifest
    ** a view or the co-routine to implement a view.  The first instance
    ** is sufficient, though the subroutine to manifest the view does need
    ** to be invoked again. */
    if( pItem->addrFillSub ){
      if( pItem->viaCoroutine==0 ){
        sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub);
      sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub);
      }
      continue;
    }

    /* Increment Parse.nHeight by the height of the largest expression
    ** tree refered to by this, the parent select. The child select
    ** may contain expression trees of at most
    ** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit
    ** more conservative than necessary, but much easier than enforcing
    ** an exact limit.
    */
    pParse->nHeight += sqlite3SelectExprHeight(p);

    isAggSub = (pSub->selFlags & SF_Aggregate)!=0;
    if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){
      /* This subquery can be absorbed into its parent. */
      if( isAggSub ){
        isAgg = 1;
        p->selFlags |= SF_Aggregate;
      }
      i = -1;
    }else if( pTabList->nSrc==1 && (p->selFlags & SF_Materialize)==0
      && OptimizationEnabled(db, SQLITE_SubqCoroutine)
    ){
      /* Implement a co-routine that will return a single row of the result
      ** set on each invocation.
      */
      int addrTop;
      int addrEof;
      pItem->regReturn = ++pParse->nMem;
      addrEof = ++pParse->nMem;
      /* Before coding the OP_Goto to jump to the start of the main routine,
      ** ensure that the jump to the verify-schema routine has already
      ** been coded. Otherwise, the verify-schema would likely be coded as 
      ** part of the co-routine. If the main routine then accessed the 
      ** database before invoking the co-routine for the first time (for 
      ** example to initialize a LIMIT register from a sub-select), it would 
      ** be doing so without having verified the schema version and obtained 
      ** the required db locks. See ticket d6b36be38.  */
      sqlite3CodeVerifySchema(pParse, -1);
      sqlite3VdbeAddOp0(v, OP_Goto);
      addrTop = sqlite3VdbeAddOp1(v, OP_OpenPseudo, pItem->iCursor);
      sqlite3VdbeChangeP5(v, 1);
      VdbeComment((v, "coroutine for %s", pItem->pTab->zName));
      pItem->addrFillSub = addrTop;
      sqlite3VdbeAddOp2(v, OP_Integer, 0, addrEof);
      sqlite3VdbeChangeP5(v, 1);
      sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
      explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
      sqlite3Select(pParse, pSub, &dest);
      pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;
      pItem->viaCoroutine = 1;
      sqlite3VdbeChangeP2(v, addrTop, dest.iSdst);
      sqlite3VdbeChangeP3(v, addrTop, dest.nSdst);
      sqlite3VdbeAddOp2(v, OP_Integer, 1, addrEof);
      sqlite3VdbeAddOp1(v, OP_Yield, pItem->regReturn);
      VdbeComment((v, "end %s", pItem->pTab->zName));
      sqlite3VdbeJumpHere(v, addrTop-1);
      sqlite3ClearTempRegCache(pParse);
    }else{
      /* Generate a subroutine that will fill an ephemeral table with
      ** the content of this subquery.  pItem->addrFillSub will point
      ** to the address of the generated subroutine.  pItem->regReturn
      ** is a register allocated to hold the subroutine return address
      */
      int topAddr;
99057
99058
99059
99060
99061
99062
99063
99064
99065
99066
99067
99068
99069

99070
99071
99072
99073


99074

99075
99076
99077
99078
99079
99080
99081
98396
98397
98398
98399
98400
98401
98402






98403



98404
98405
98406

98407
98408
98409
98410
98411
98412
98413
98414







-
-
-
-
-
-
+
-
-
-

+
+
-
+







        **
        **   + The optimizer code in where.c (the thing that decides which
        **     index or indices to use) should place a different priority on 
        **     satisfying the 'ORDER BY' clause than it does in other cases.
        **     Refer to code and comments in where.c for details.
        */
        ExprList *pMinMax = 0;
        u8 flag = WHERE_ORDERBY_NORMAL;
        
        assert( p->pGroupBy==0 );
        assert( flag==0 );
        if( p->pHaving==0 ){
          flag = minMaxQuery(&sAggInfo, &pMinMax);
        u8 flag = minMaxQuery(p);
        }
        assert( flag==0 || (pMinMax!=0 && pMinMax->nExpr==1) );

        if( flag ){
          assert( !ExprHasProperty(p->pEList->a[0].pExpr, EP_xIsSelect) );
          assert( p->pEList->a[0].pExpr->x.pList->nExpr==1 );
          pMinMax = sqlite3ExprListDup(db, pMinMax, 0);
          pMinMax = sqlite3ExprListDup(db, p->pEList->a[0].pExpr->x.pList,0);
          pDel = pMinMax;
          if( pMinMax && !db->mallocFailed ){
            pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0;
            pMinMax->a[0].pExpr->op = TK_COLUMN;
          }
        }
  
100171
100172
100173
100174
100175
100176
100177
100178
100179
100180
100181
100182
100183
100184
100185
100186
100187
100188
100189
100190
100191
100192
100193
99504
99505
99506
99507
99508
99509
99510









99511
99512
99513
99514
99515
99516
99517







-
-
-
-
-
-
-
-
-







    **   END;
    **
    **   INSERT INTO t1 ... ;            -- insert into t2 uses REPLACE policy
    **   INSERT OR IGNORE INTO t1 ... ;  -- insert into t2 uses IGNORE policy
    */
    pParse->eOrconf = (orconf==OE_Default)?pStep->orconf:(u8)orconf;

    /* Clear the cookieGoto flag. When coding triggers, the cookieGoto 
    ** variable is used as a flag to indicate to sqlite3ExprCodeConstants()
    ** that it is not safe to refactor constants (this happens after the
    ** start of the first loop in the SQL statement is coded - at that 
    ** point code may be conditionally executed, so it is no longer safe to 
    ** initialize constant register values).  */
    assert( pParse->cookieGoto==0 || pParse->cookieGoto==-1 );
    pParse->cookieGoto = 0;

    switch( pStep->op ){
      case TK_UPDATE: {
        sqlite3Update(pParse, 
          targetSrcList(pParse, pStep),
          sqlite3ExprListDup(db, pStep->pExprList, 0), 
          sqlite3ExprDup(db, pStep->pWhere, 0), 
          pParse->eOrconf
101336
101337
101338
101339
101340
101341
101342
101343
101344
101345
101346
101347
101348
101349
101350
100660
100661
100662
100663
100664
100665
100666

100667
100668
100669
100670
100671
100672
100673







-







** with 2.0.0, SQLite no longer uses GDBM so this command has
** become a no-op.
*/
SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse){
  Vdbe *v = sqlite3GetVdbe(pParse);
  if( v ){
    sqlite3VdbeAddOp2(v, OP_Vacuum, 0, 0);
    sqlite3VdbeUsesBtree(v, 0);
  }
  return;
}

/*
** This routine implements the OP_Vacuum opcode of the VDBE.
*/
102096
102097
102098
102099
102100
102101
102102

102103
102104
102105
102106
102107
102108
102109
102110
102111
102112
102113
102114
102115

102116
102117
102118
102119
102120
102121
102122
101419
101420
101421
101422
101423
101424
101425
101426
101427
101428
101429
101430
101431
101432
101433
101434
101435
101436
101437
101438
101439
101440
101441
101442
101443
101444
101445
101446
101447







+













+







  if( !pVTable ){
    sqlite3DbFree(db, zModuleName);
    return SQLITE_NOMEM;
  }
  pVTable->db = db;
  pVTable->pMod = pMod;

  assert( pTab->azModuleArg[1]==0 );
  iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
  pTab->azModuleArg[1] = db->aDb[iDb].zName;

  /* Invoke the virtual table constructor */
  assert( &db->pVtabCtx );
  assert( xConstruct );
  sCtx.pTab = pTab;
  sCtx.pVTable = pVTable;
  pPriorCtx = db->pVtabCtx;
  db->pVtabCtx = &sCtx;
  rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr);
  db->pVtabCtx = pPriorCtx;
  if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
  pTab->azModuleArg[1] = 0;

  if( SQLITE_OK!=rc ){
    if( zErr==0 ){
      *pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName);
    }else {
      *pzErr = sqlite3MPrintf(db, "%s", zErr);
      sqlite3_free(zErr);
102955
102956
102957
102958
102959
102960
102961
102962

102963
102964
102965
102966
102967
102968
102969
102280
102281
102282
102283
102284
102285
102286

102287
102288
102289
102290
102291
102292
102293
102294







-
+







#define WHERE_ROWID_RANGE  0x00002000  /* rowid<EXPR and/or rowid>EXPR */
#define WHERE_COLUMN_EQ    0x00010000  /* x=EXPR or x IN (...) or x IS NULL */
#define WHERE_COLUMN_RANGE 0x00020000  /* x<EXPR and/or x>EXPR */
#define WHERE_COLUMN_IN    0x00040000  /* x IN (...) */
#define WHERE_COLUMN_NULL  0x00080000  /* x IS NULL */
#define WHERE_INDEXED      0x000f0000  /* Anything that uses an index */
#define WHERE_NOT_FULLSCAN 0x100f3000  /* Does not do a full table scan */
#define WHERE_IN_ABLE      0x080f1000  /* Able to support an IN operator */
#define WHERE_IN_ABLE      0x000f1000  /* Able to support an IN operator */
#define WHERE_TOP_LIMIT    0x00100000  /* x<EXPR or x<=EXPR constraint */
#define WHERE_BTM_LIMIT    0x00200000  /* x>EXPR or x>=EXPR constraint */
#define WHERE_BOTH_LIMIT   0x00300000  /* Both x>EXPR and x<EXPR */
#define WHERE_IDX_ONLY     0x00400000  /* Use index only - omit table */
#define WHERE_ORDERED      0x00800000  /* Output will appear in correct order */
#define WHERE_REVERSE      0x01000000  /* Scan in reverse order */
#define WHERE_UNIQUE       0x02000000  /* Selects no more than one row */
103105
103106
103107
103108
103109
103110
103111
103112

103113
103114
103115
103116
103117
103118
103119
102430
102431
102432
102433
102434
102435
102436

102437
102438
102439
102440
102441
102442
102443
102444







-
+







    memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm);
    if( pOld!=pWC->aStatic ){
      sqlite3DbFree(db, pOld);
    }
    pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
  }
  pTerm = &pWC->a[idx = pWC->nTerm++];
  pTerm->pExpr = sqlite3ExprSkipCollate(p);
  pTerm->pExpr = p;
  pTerm->wtFlags = wtFlags;
  pTerm->pWC = pWC;
  pTerm->iParent = -1;
  return idx;
}

/*
103265
103266
103267
103268
103269
103270
103271
103272
103273

103274
103275
103276

103277
103278

103279
103280
103281
103282
103283


103284
103285
103286
103287
103288
103289
103290
103291


103292
103293


103294
103295

103296
103297
103298
103299
103300
103301
103302
103303
103304
102590
102591
102592
102593
102594
102595
102596


102597
102598
102599

102600
102601

102602
102603
102604
102605


102606
102607
102608







102609
102610


102611
102612


102613


102614
102615
102616
102617
102618
102619
102620







-
-
+


-
+

-
+



-
-
+
+

-
-
-
-
-
-
-
+
+
-
-
+
+
-
-
+
-
-







*/
#define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;}

/*
** Commute a comparison operator.  Expressions of the form "X op Y"
** are converted into "Y op X".
**
** If left/right precendence rules come into play when determining the
** collating
** If a collation sequence is associated with either the left or right
** side of the comparison, it remains associated with the same side after
** the commutation. So "Y collate NOCASE op X" becomes 
** "X op Y". This is because any collation sequence on
** "X collate NOCASE op Y". This is because any collation sequence on
** the left hand side of a comparison overrides any collation sequence 
** attached to the right. For the same reason the EP_Collate flag
** attached to the right. For the same reason the EP_ExpCollate flag
** is not commuted.
*/
static void exprCommute(Parse *pParse, Expr *pExpr){
  u16 expRight = (pExpr->pRight->flags & EP_Collate);
  u16 expLeft = (pExpr->pLeft->flags & EP_Collate);
  u16 expRight = (pExpr->pRight->flags & EP_ExpCollate);
  u16 expLeft = (pExpr->pLeft->flags & EP_ExpCollate);
  assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN );
  if( expRight==expLeft ){
    /* Either X and Y both have COLLATE operator or neither do */
    if( expRight ){
      /* Both X and Y have COLLATE operators.  Make sure X is always
      ** used by clearing the EP_Collate flag from Y. */
      pExpr->pRight->flags &= ~EP_Collate;
    }else if( sqlite3ExprCollSeq(pParse, pExpr->pLeft)!=0 ){
  pExpr->pRight->pColl = sqlite3ExprCollSeq(pParse, pExpr->pRight);
  pExpr->pLeft->pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
      /* Neither X nor Y have COLLATE operators, but X has a non-default
      ** collating sequence.  So add the EP_Collate marker on X to cause
  SWAP(CollSeq*,pExpr->pRight->pColl,pExpr->pLeft->pColl);
  pExpr->pRight->flags = (pExpr->pRight->flags & ~EP_ExpCollate) | expLeft;
      ** it to be searched first. */
      pExpr->pLeft->flags |= EP_Collate;
  pExpr->pLeft->flags = (pExpr->pLeft->flags & ~EP_ExpCollate) | expRight;
    }
  }
  SWAP(Expr*,pExpr->pRight,pExpr->pLeft);
  if( pExpr->op>=TK_GT ){
    assert( TK_LT==TK_GT+2 );
    assert( TK_GE==TK_LE+2 );
    assert( TK_GT>TK_EQ );
    assert( TK_GT<TK_LE );
    assert( pExpr->op>=TK_GT && pExpr->op<=TK_GE );
103367
103368
103369
103370
103371
103372
103373
103374

103375
103376
103377
103378
103379

103380
103381
103382
103383
103384
103385
103386
102683
102684
102685
102686
102687
102688
102689

102690
102691
102692
102693
102694

102695
102696
102697
102698
102699
102700
102701
102702







-
+




-
+







  
          /* Figure out the collation sequence required from an index for
          ** it to be useful for optimising expression pX. Store this
          ** value in variable pColl.
          */
          assert(pX->pLeft);
          pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
          if( pColl==0 ) pColl = pParse->db->pDfltColl;
          assert(pColl || pParse->nErr);
  
          for(j=0; pIdx->aiColumn[j]!=iColumn; j++){
            if( NEVER(j>=pIdx->nColumn) ) return 0;
          }
          if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue;
          if( pColl && sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue;
        }
        return pTerm;
      }
    }
  }
  return 0;
}
103891
103892
103893
103894
103895
103896
103897
103898
103899
103900
103901
103902
103903
103904
103905
103207
103208
103209
103210
103211
103212
103213

103214
103215
103216
103217
103218
103219
103220







-








  if( db->mallocFailed ){
    return;
  }
  pTerm = &pWC->a[idxTerm];
  pMaskSet = pWC->pMaskSet;
  pExpr = pTerm->pExpr;
  assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE );
  prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft);
  op = pExpr->op;
  if( op==TK_IN ){
    assert( pExpr->pRight==0 );
    if( ExprHasProperty(pExpr, EP_xIsSelect) ){
      pTerm->prereqRight = exprSelectTableUsage(pMaskSet, pExpr->x.pSelect);
    }else{
103918
103919
103920
103921
103922
103923
103924
103925
103926


103927
103928
103929
103930
103931
103932
103933
103233
103234
103235
103236
103237
103238
103239


103240
103241
103242
103243
103244
103245
103246
103247
103248







-
-
+
+







                       ** on left table of a LEFT JOIN.  Ticket #3015 */
  }
  pTerm->prereqAll = prereqAll;
  pTerm->leftCursor = -1;
  pTerm->iParent = -1;
  pTerm->eOperator = 0;
  if( allowedOp(op) && (pTerm->prereqRight & prereqLeft)==0 ){
    Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft);
    Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight);
    Expr *pLeft = pExpr->pLeft;
    Expr *pRight = pExpr->pRight;
    if( pLeft->op==TK_COLUMN ){
      pTerm->leftCursor = pLeft->iTable;
      pTerm->u.leftColumn = pLeft->iColumn;
      pTerm->eOperator = operatorMask(op);
    }
    if( pRight && pRight->op==TK_COLUMN ){
      WhereTerm *pNew;
103947
103948
103949
103950
103951
103952
103953
103954

103955
103956
103957
103958
103959
103960
103961
103262
103263
103264
103265
103266
103267
103268

103269
103270
103271
103272
103273
103274
103275
103276







-
+







        pTerm->nChild = 1;
        pTerm->wtFlags |= TERM_COPIED;
      }else{
        pDup = pExpr;
        pNew = pTerm;
      }
      exprCommute(pParse, pDup);
      pLeft = sqlite3ExprSkipCollate(pDup->pLeft);
      pLeft = pDup->pLeft;
      pNew->leftCursor = pLeft->iTable;
      pNew->u.leftColumn = pLeft->iColumn;
      testcase( (prereqLeft | extraRight) != prereqLeft );
      pNew->prereqRight = prereqLeft | extraRight;
      pNew->prereqAll = prereqAll;
      pNew->eOperator = operatorMask(pDup->op);
    }
104026
104027
104028
104029
104030
104031
104032
104033

104034
104035
104036
104037
104038
104039
104040
103341
103342
103343
103344
103345
103346
103347

103348
103349
103350
103351
103352
103353
103354
103355







-
+







  ){
    Expr *pLeft;       /* LHS of LIKE/GLOB operator */
    Expr *pStr2;       /* Copy of pStr1 - RHS of LIKE/GLOB operator */
    Expr *pNewExpr1;
    Expr *pNewExpr2;
    int idxNew1;
    int idxNew2;
    Token sCollSeqName;  /* Name of collating sequence */
    CollSeq *pColl;    /* Collating sequence to use */

    pLeft = pExpr->x.pList->a[1].pExpr;
    pStr2 = sqlite3ExprDup(db, pStr1, 0);
    if( !db->mallocFailed ){
      u8 c, *pC;       /* Last character before the first wildcard */
      pC = (u8*)&pStr2->u.zToken[sqlite3Strlen30(pStr2->u.zToken)-1];
      c = *pC;
104048
104049
104050
104051
104052
104053
104054
104055

104056
104057
104058
104059
104060


104061
104062
104063
104064
104065
104066
104067


104068
104069
104070
104071
104072
104073
104074
103363
103364
103365
103366
103367
103368
103369

103370


103371


103372
103373
103374
103375
103376

103377


103378
103379
103380
103381
103382
103383
103384
103385
103386







-
+
-
-

-
-
+
+



-

-
-
+
+







        if( c=='A'-1 ) isComplete = 0;   /* EV: R-64339-08207 */


        c = sqlite3UpperToLower[c];
      }
      *pC = c + 1;
    }
    sCollSeqName.z = noCase ? "NOCASE" : "BINARY";
    pColl = sqlite3FindCollSeq(db, SQLITE_UTF8, noCase ? "NOCASE" : "BINARY",0);
    sCollSeqName.n = 6;
    pNewExpr1 = sqlite3ExprDup(db, pLeft, 0);
    pNewExpr1 = sqlite3PExpr(pParse, TK_GE, 
           sqlite3ExprAddCollateToken(pParse,pNewExpr1,&sCollSeqName),
           pStr1, 0);
                     sqlite3ExprSetColl(sqlite3ExprDup(db,pLeft,0), pColl),
                     pStr1, 0);
    idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
    testcase( idxNew1==0 );
    exprAnalyze(pSrc, pWC, idxNew1);
    pNewExpr2 = sqlite3ExprDup(db, pLeft, 0);
    pNewExpr2 = sqlite3PExpr(pParse, TK_LT,
           sqlite3ExprAddCollateToken(pParse,pNewExpr2,&sCollSeqName),
           pStr2, 0);
                     sqlite3ExprSetColl(sqlite3ExprDup(db,pLeft,0), pColl),
                     pStr2, 0);
    idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC);
    testcase( idxNew2==0 );
    exprAnalyze(pSrc, pWC, idxNew2);
    pTerm = &pWC->a[idxTerm];
    if( isComplete ){
      pWC->a[idxNew1].iParent = idxTerm;
      pWC->a[idxNew2].iParent = idxTerm;
104178
104179
104180
104181
104182
104183
104184
104185

104186
104187
104188
104189
104190

104191
104192
104193
104194
104195
104196
104197
103490
103491
103492
103493
103494
103495
103496

103497
103498
103499
103500
103501

103502
103503
103504
103505
103506
103507
103508
103509







-
+




-
+







  Index *pIdx,                    /* Index to match column of */
  int iCol                        /* Column of index to match */
){
  int i;
  const char *zColl = pIdx->azColl[iCol];

  for(i=0; i<pList->nExpr; i++){
    Expr *p = sqlite3ExprSkipCollate(pList->a[i].pExpr);
    Expr *p = pList->a[i].pExpr;
    if( p->op==TK_COLUMN
     && p->iColumn==pIdx->aiColumn[iCol]
     && p->iTable==iBase
    ){
      CollSeq *pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr);
      CollSeq *pColl = sqlite3ExprCollSeq(pParse, p);
      if( ALWAYS(pColl) && 0==sqlite3StrICmp(pColl->zName, zColl) ){
        return i;
      }
    }
  }

  return -1;
104230
104231
104232
104233
104234
104235
104236
104237

104238
104239
104240
104241
104242
104243
104244
103542
103543
103544
103545
103546
103547
103548

103549
103550
103551
103552
103553
103554
103555
103556







-
+







  ** can be ignored. If it does not, and the column does not belong to the
  ** same table as index pIdx, return early. Finally, if there is no
  ** matching "col=X" expression and the column is on the same table as pIdx,
  ** set the corresponding bit in variable mask.
  */
  for(i=0; i<pDistinct->nExpr; i++){
    WhereTerm *pTerm;
    Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr);
    Expr *p = pDistinct->a[i].pExpr;
    if( p->op!=TK_COLUMN ) return 0;
    pTerm = findTerm(pWC, p->iTable, p->iColumn, ~(Bitmask)0, WO_EQ, 0);
    if( pTerm ){
      Expr *pX = pTerm->pExpr;
      CollSeq *p1 = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
      CollSeq *p2 = sqlite3ExprCollSeq(pParse, p);
      if( p1==p2 ) continue;
104282
104283
104284
104285
104286
104287
104288
104289

104290
104291
104292
104293
104294
104295
104296
103594
103595
103596
103597
103598
103599
103600

103601
103602
103603
103604
103605
103606
103607
103608







-
+







  pTab = pTabList->a[0].pTab;

  /* If any of the expressions is an IPK column on table iBase, then return 
  ** true. Note: The (p->iTable==iBase) part of this test may be false if the
  ** current SELECT is a correlated sub-query.
  */
  for(i=0; i<pDistinct->nExpr; i++){
    Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr);
    Expr *p = pDistinct->a[i].pExpr;
    if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1;
  }

  /* Loop through all indices on the table, checking each to see if it makes
  ** the DISTINCT qualifier redundant. It does so if:
  **
  **   1. The index is itself UNIQUE, and
104530
104531
104532
104533
104534
104535
104536
104537

104538
104539
104540
104541
104542
104543
104544
104545
104546
104547
104548
104549
104550
104551
104552
104553
103842
103843
103844
103845
103846
103847
103848

103849


103850
103851
103852




103853
103854
103855
103856
103857
103858
103859







-
+
-
-



-
-
-
-







    /* There is no point in building an automatic index for a single scan */
    return;
  }
  if( (pParse->db->flags & SQLITE_AutoIndex)==0 ){
    /* Automatic indices are disabled at run-time */
    return;
  }
  if( (p->cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0
  if( (p->cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0 ){
   && (p->cost.plan.wsFlags & WHERE_COVER_SCAN)==0
  ){
    /* We already have some kind of index in use for this query. */
    return;
  }
  if( pSrc->viaCoroutine ){
    /* Cannot index a co-routine */
    return;
  }
  if( pSrc->notIndexed ){
    /* The NOT INDEXED clause appears in the SQL. */
    return;
  }
  if( pSrc->isCorrelated ){
    /* The source is a correlated sub-query. No point in indexing it. */
    return;
104759
104760
104761
104762
104763
104764
104765
104766

104767
104768
104769
104770
104771
104772
104773
104065
104066
104067
104068
104069
104070
104071

104072
104073
104074
104075
104076
104077
104078
104079







-
+







  /* Count the number of possible WHERE clause constraints referring
  ** to this virtual table */
  for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
    if( pTerm->leftCursor != pSrc->iCursor ) continue;
    assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
    testcase( pTerm->eOperator==WO_IN );
    testcase( pTerm->eOperator==WO_ISNULL );
    if( pTerm->eOperator & (WO_ISNULL) ) continue;
    if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
    if( pTerm->wtFlags & TERM_VNULL ) continue;
    nTerm++;
  }

  /* If the ORDER BY clause contains only columns in the current 
  ** virtual table then allocate space for the aOrderBy part of
  ** the sqlite3_index_info structure.
104807
104808
104809
104810
104811
104812
104813
104814
104815
104816
104817
104818
104819

104820
104821
104822
104823
104824
104825

104826
104827
104828
104829
104830
104831
104832
104833
104834
104835

104836
104837
104838
104839
104840
104841
104842
104113
104114
104115
104116
104117
104118
104119

104120
104121
104122
104123

104124
104125
104126
104127



104128
104129
104130
104131
104132
104133
104134
104135
104136
104137

104138
104139
104140
104141
104142
104143
104144
104145







-




-
+



-
-
-
+









-
+







  *(int*)&pIdxInfo->nOrderBy = nOrderBy;
  *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint = pIdxCons;
  *(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy;
  *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage =
                                                                   pUsage;

  for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
    u8 op;
    if( pTerm->leftCursor != pSrc->iCursor ) continue;
    assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
    testcase( pTerm->eOperator==WO_IN );
    testcase( pTerm->eOperator==WO_ISNULL );
    if( pTerm->eOperator & (WO_ISNULL) ) continue;
    if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
    if( pTerm->wtFlags & TERM_VNULL ) continue;
    pIdxCons[j].iColumn = pTerm->u.leftColumn;
    pIdxCons[j].iTermOffset = i;
    op = (u8)pTerm->eOperator;
    if( op==WO_IN ) op = WO_EQ;
    pIdxCons[j].op = op;
    pIdxCons[j].op = (u8)pTerm->eOperator;
    /* The direct assignment in the previous line is possible only because
    ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical.  The
    ** following asserts verify this fact. */
    assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ );
    assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT );
    assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE );
    assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
    assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
    assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH );
    assert( pTerm->eOperator & (WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) );
    assert( pTerm->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) );
    j++;
  }
  for(i=0; i<nOrderBy; i++){
    Expr *pExpr = pOrderBy->a[i].pExpr;
    pIdxOrderBy[i].iColumn = pExpr->iColumn;
    pIdxOrderBy[i].desc = pOrderBy->a[i].sortOrder;
  }
104914
104915
104916
104917
104918
104919
104920
104921
104922
104923
104924
104925
104926
104927
104928
104217
104218
104219
104220
104221
104222
104223

104224
104225
104226
104227
104228
104229
104230







-







  Table *pTab = pSrc->pTab;
  sqlite3_index_info *pIdxInfo;
  struct sqlite3_index_constraint *pIdxCons;
  struct sqlite3_index_constraint_usage *pUsage;
  WhereTerm *pTerm;
  int i, j;
  int nOrderBy;
  int bAllowIN;                   /* Allow IN optimizations */
  double rCost;

  /* Make sure wsFlags is initialized to some sane value. Otherwise, if the 
  ** malloc in allocateIndexInfo() fails and this function returns leaving
  ** wsFlags in an uninitialized state, the caller may behave unpredictably.
  */
  memset(&p->cost, 0, sizeof(p->cost));
104949
104950
104951
104952
104953
104954
104955
104956
104957
104958
104959
104960
104961
104962
104963
104964
104965
104966
104967
104968
104969
104970
104971
104972
104973
104974
104975
104976
104977
104978
104979
104980
104981
104982
104983
104984
104985
104986
104987
104988
104989
104990
104991

























104992
104993
104994
104995

104996
104997
104998
104999
105000
105001
105002
105003
105004
105005
105006
105007
105008
105009
105010
105011
105012
105013
105014
105015
105016
105017
105018
105019
105020
105021























105022
105023
105024

105025
105026
105027
105028
105029
105030
105031
105032
105033



105034
105035
105036
105037
105038
105039
105040
105041
105042
105043
104251
104252
104253
104254
104255
104256
104257




































104258
104259
104260
104261
104262
104263
104264
104265
104266
104267
104268
104269
104270
104271
104272
104273
104274
104275
104276
104277
104278
104279
104280
104281
104282




104283


























104284
104285
104286
104287
104288
104289
104290
104291
104292
104293
104294
104295
104296
104297
104298
104299
104300
104301
104302
104303
104304
104305
104306



104307









104308
104309
104310



104311
104312
104313
104314
104315
104316
104317







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-







  /* The module name must be defined. Also, by this point there must
  ** be a pointer to an sqlite3_vtab structure. Otherwise
  ** sqlite3ViewGetColumnNames() would have picked up the error. 
  */
  assert( pTab->azModuleArg && pTab->azModuleArg[0] );
  assert( sqlite3GetVTable(pParse->db, pTab) );

  /* Try once or twice.  On the first attempt, allow IN optimizations.
  ** If an IN optimization is accepted by the virtual table xBestIndex
  ** method, but the  pInfo->aConstrainUsage.omit flag is not set, then
  ** the query will not work because it might allow duplicate rows in
  ** output.  In that case, run the xBestIndex method a second time
  ** without the IN constraints.  Usually this loop only runs once.
  ** The loop will exit using a "break" statement.
  */
  for(bAllowIN=1; 1; bAllowIN--){
    assert( bAllowIN==0 || bAllowIN==1 );

    /* Set the aConstraint[].usable fields and initialize all 
    ** output variables to zero.
    **
    ** aConstraint[].usable is true for constraints where the right-hand
    ** side contains only references to tables to the left of the current
    ** table.  In other words, if the constraint is of the form:
    **
    **           column = expr
    **
    ** and we are evaluating a join, then the constraint on column is 
    ** only valid if all tables referenced in expr occur to the left
    ** of the table containing column.
    **
    ** The aConstraints[] array contains entries for all constraints
    ** on the current table.  That way we only have to compute it once
    ** even though we might try to pick the best index multiple times.
    ** For each attempt at picking an index, the order of tables in the
    ** join might be different so we have to recompute the usable flag
    ** each time.
    */
    pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
    pUsage = pIdxInfo->aConstraintUsage;
    for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
      j = pIdxCons->iTermOffset;
      pTerm = &pWC->a[j];
  /* Set the aConstraint[].usable fields and initialize all 
  ** output variables to zero.
  **
  ** aConstraint[].usable is true for constraints where the right-hand
  ** side contains only references to tables to the left of the current
  ** table.  In other words, if the constraint is of the form:
  **
  **           column = expr
  **
  ** and we are evaluating a join, then the constraint on column is 
  ** only valid if all tables referenced in expr occur to the left
  ** of the table containing column.
  **
  ** The aConstraints[] array contains entries for all constraints
  ** on the current table.  That way we only have to compute it once
  ** even though we might try to pick the best index multiple times.
  ** For each attempt at picking an index, the order of tables in the
  ** join might be different so we have to recompute the usable flag
  ** each time.
  */
  pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
  pUsage = pIdxInfo->aConstraintUsage;
  for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
    j = pIdxCons->iTermOffset;
    pTerm = &pWC->a[j];
      if( (pTerm->prereqRight&p->notReady)==0
       && (bAllowIN || pTerm->eOperator!=WO_IN)
      ){
        pIdxCons->usable = 1;
    pIdxCons->usable = (pTerm->prereqRight&p->notReady) ? 0 : 1;
      }else{
        pIdxCons->usable = 0;
      }
    }
    memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint);
    if( pIdxInfo->needToFreeIdxStr ){
      sqlite3_free(pIdxInfo->idxStr);
    }
    pIdxInfo->idxStr = 0;
    pIdxInfo->idxNum = 0;
    pIdxInfo->needToFreeIdxStr = 0;
    pIdxInfo->orderByConsumed = 0;
    /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */
    pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2);
    nOrderBy = pIdxInfo->nOrderBy;
    if( !p->pOrderBy ){
      pIdxInfo->nOrderBy = 0;
    }
  
    if( vtabBestIndex(pParse, pTab, pIdxInfo) ){
      return;
    }
  
    pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
    for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
      if( pUsage[i].argvIndex>0 ){
  }
  memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint);
  if( pIdxInfo->needToFreeIdxStr ){
    sqlite3_free(pIdxInfo->idxStr);
  }
  pIdxInfo->idxStr = 0;
  pIdxInfo->idxNum = 0;
  pIdxInfo->needToFreeIdxStr = 0;
  pIdxInfo->orderByConsumed = 0;
  /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */
  pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2);
  nOrderBy = pIdxInfo->nOrderBy;
  if( !p->pOrderBy ){
    pIdxInfo->nOrderBy = 0;
  }

  if( vtabBestIndex(pParse, pTab, pIdxInfo) ){
    return;
  }

  pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
  for(i=0; i<pIdxInfo->nConstraint; i++){
    if( pUsage[i].argvIndex>0 ){
        j = pIdxCons->iTermOffset;
        pTerm = &pWC->a[j];
        p->cost.used |= pTerm->prereqRight;
      p->cost.used |= pWC->a[pIdxCons[i].iTermOffset].prereqRight;
        if( pTerm->eOperator==WO_IN && pUsage[i].omit==0 ){
          /* Do not attempt to use an IN constraint if the virtual table
          ** says that the equivalent EQ constraint cannot be safely omitted.
          ** If we do attempt to use such a constraint, some rows might be
          ** repeated in the output. */
          break;
        }
      }
    }
    }
  }

    if( i>=pIdxInfo->nConstraint ) break;
  }
  
  /* If there is an ORDER BY clause, and the selected virtual table index
  ** does not satisfy it, increase the cost of the scan accordingly. This
  ** matches the processing for non-virtual tables in bestBtreeIndex().
  */
  rCost = pIdxInfo->estimatedCost;
  if( p->pOrderBy && pIdxInfo->orderByConsumed==0 ){
    rCost += estLog(rCost)*rCost;
105600
105601
105602
105603
105604
105605
105606
105607

105608
105609
105610
105611
105612
105613
105614
104874
104875
104876
104877
104878
104879
104880

104881
104882
104883
104884
104885
104886
104887
104888







-
+







    int isMatch;            /* ORDER BY term matches the index term */
    const char *zColl;      /* Name of collating sequence for i-th index term */
    WhereTerm *pConstraint; /* A constraint in the WHERE clause */

    /* If the next term of the ORDER BY clause refers to anything other than
    ** a column in the "base" table, then this index will not be of any
    ** further use in handling the ORDER BY. */
    pOBExpr = sqlite3ExprSkipCollate(pOBItem->pExpr);
    pOBExpr = pOBItem->pExpr;
    if( pOBExpr->op!=TK_COLUMN || pOBExpr->iTable!=base ){
      break;
    }

    /* Find column number and collating sequence for the next entry
    ** in the index */
    if( pIdx->zName && i<pIdx->nColumn ){
105626
105627
105628
105629
105630
105631
105632
105633

105634
105635
105636
105637
105638
105639
105640
104900
104901
104902
104903
104904
104905
104906

104907
104908
104909
104910
104911
104912
104913
104914







-
+







    }

    /* Check to see if the column number and collating sequence of the
    ** index match the column number and collating sequence of the ORDER BY
    ** clause entry.  Set isMatch to 1 if they both match. */
    if( pOBExpr->iColumn==iColumn ){
      if( zColl ){
        pColl = sqlite3ExprCollSeq(pParse, pOBItem->pExpr);
        pColl = sqlite3ExprCollSeq(pParse, pOBExpr);
        if( !pColl ) pColl = db->pDfltColl;
        isMatch = sqlite3StrICmp(pColl->zName, zColl)==0;
      }else{
        isMatch = 1;
      }
    }else{
      isMatch = 0;
105749
105750
105751
105752
105753
105754
105755
105756

105757
105758
105759
105760
105761
105762
105763
105764
105765
105766
105767
105768
105769
105770
105771
105772
105773
105774
105775
105776
105777
105778
105779
105780
105781
105782
105783
105784
105785
105023
105024
105025
105026
105027
105028
105029

105030
105031
105032
105033
105034
105035
105036
105037
105038
105039
105040
105041
105042
105043
105044
105045
105046
105047





105048
105049
105050
105051
105052
105053
105054







-
+

















-
-
-
-
-







**
** If there was an INDEXED BY clause (pSrc->pIndex) attached to the table in
** the SQL statement, then this function only considers plans using the 
** named index. If no such plan is found, then the returned cost is
** SQLITE_BIG_DBL. If a plan is found that uses the named index, 
** then the cost is calculated in the usual way.
**
** If a NOT INDEXED clause was attached to the table 
** If a NOT INDEXED clause (pSrc->notIndexed!=0) was attached to the table 
** in the SELECT statement, then no indexes are considered. However, the 
** selected plan may still take advantage of the built-in rowid primary key
** index.
*/
static void bestBtreeIndex(WhereBestIdx *p){
  Parse *pParse = p->pParse;  /* The parsing context */
  WhereClause *pWC = p->pWC;  /* The WHERE clause */
  struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */
  int iCur = pSrc->iCursor;   /* The cursor of the table to be accessed */
  Index *pProbe;              /* An index we are evaluating */
  Index *pIdx;                /* Copy of pProbe, or zero for IPK index */
  int eqTermMask;             /* Current mask of valid equality operators */
  int idxEqTermMask;          /* Index mask of valid equality operators */
  Index sPk;                  /* A fake index object for the primary key */
  tRowcnt aiRowEstPk[2];      /* The aiRowEst[] value for the sPk index */
  int aiColumnPk = -1;        /* The aColumn[] value for the sPk index */
  int wsFlagMask;             /* Allowed flags in p->cost.plan.wsFlag */
  int nPriorSat;              /* ORDER BY terms satisfied by outer loops */
  int nOrderBy;               /* Number of ORDER BY terms */
  char bSortInit;             /* Initializer for bSort in inner loop */
  char bDistInit;             /* Initializer for bDist in inner loop */


  /* Initialize the cost to a worst-case value */
  memset(&p->cost, 0, sizeof(p->cost));
  p->cost.rCost = SQLITE_BIG_DBL;

  /* If the pSrc table is the right table of a LEFT JOIN then we may not
  ** use an index to satisfy IS NULL constraints on that table.  This is
105821
105822
105823
105824
105825
105826
105827
105828
105829
105830
105831
105832
105833
105834
105835
105836
105837
105838
105839
105840
105841
105842
105843
105844
105845
105090
105091
105092
105093
105094
105095
105096











105097
105098
105099
105100
105101
105102
105103







-
-
-
-
-
-
-
-
-
-
-







    wsFlagMask = ~(
        WHERE_COLUMN_IN|WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_RANGE
    );
    eqTermMask = WO_EQ|WO_IN;
    pIdx = 0;
  }

  nOrderBy = p->pOrderBy ? p->pOrderBy->nExpr : 0;
  if( p->i ){
    nPriorSat = p->aLevel[p->i-1].plan.nOBSat;
    bSortInit = nPriorSat<nOrderBy;
    bDistInit = 0;
  }else{
    nPriorSat = 0;
    bSortInit = nOrderBy>0;
    bDistInit = p->pDistinct!=0;
  }

  /* Loop over all indices looking for the best one to use
  */
  for(; pProbe; pIdx=pProbe=pProbe->pNext){
    const tRowcnt * const aiRowEst = pProbe->aiRowEst;
    WhereCost pc;               /* Cost of using pProbe */
    double log10N = (double)1;  /* base-10 logarithm of nRow (inexact) */

105909
105910
105911
105912
105913
105914
105915
105916
105917
105918





105919
105920
105921
105922
105923
105924
105925
105926
105927
105928






105929




105930
105931
105932
105933
105934
105935
105936
105167
105168
105169
105170
105171
105172
105173



105174
105175
105176
105177
105178
105179
105180
105181
105182
105183
105184
105185
105186
105187
105188
105189
105190
105191
105192
105193
105194

105195
105196
105197
105198
105199
105200
105201
105202
105203
105204
105205







-
-
-
+
+
+
+
+










+
+
+
+
+
+
-
+
+
+
+







    **             SELECT a, b    FROM tbl WHERE a = 1;
    **             SELECT a, b, c FROM tbl WHERE a = 1;
    */
    int bInEst = 0;               /* True if "x IN (SELECT...)" seen */
    int nInMul = 1;               /* Number of distinct equalities to lookup */
    double rangeDiv = (double)1;  /* Estimated reduction in search space */
    int nBound = 0;               /* Number of range constraints seen */
    char bSort = bSortInit;       /* True if external sort required */
    char bDist = bDistInit;       /* True if index cannot help with DISTINCT */
    char bLookup = 0;             /* True if not a covering index */
    int bSort;                    /* True if external sort required */
    int bDist;                    /* True if index cannot help with DISTINCT */
    int bLookup = 0;              /* True if not a covering index */
    int nPriorSat;                /* ORDER BY terms satisfied by outer loops */
    int nOrderBy;                 /* Number of ORDER BY terms */
    WhereTerm *pTerm;             /* A single term of the WHERE clause */
#ifdef SQLITE_ENABLE_STAT3
    WhereTerm *pFirstTerm = 0;    /* First term matching the index */
#endif

    WHERETRACE((
      "   %s(%s):\n",
      pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk")
    ));
    memset(&pc, 0, sizeof(pc));
    nOrderBy = p->pOrderBy ? p->pOrderBy->nExpr : 0;
    if( p->i ){
      nPriorSat = pc.plan.nOBSat = p->aLevel[p->i-1].plan.nOBSat;
      bSort = nPriorSat<nOrderBy;
      bDist = 0;
    }else{
    pc.plan.nOBSat = nPriorSat;
      nPriorSat = pc.plan.nOBSat = 0;
      bSort = nOrderBy>0;
      bDist = p->pDistinct!=0;
    }

    /* Determine the values of pc.plan.nEq and nInMul */
    for(pc.plan.nEq=0; pc.plan.nEq<pProbe->nColumn; pc.plan.nEq++){
      int j = pProbe->aiColumn[pc.plan.nEq];
      pTerm = findTerm(pWC, iCur, j, p->notReady, eqTermMask, pIdx);
      if( pTerm==0 ) break;
      pc.plan.wsFlags |= (WHERE_COLUMN_EQ|WHERE_ROWID_EQ);
106004
106005
106006
106007
106008
106009
106010
106011

106012
106013
106014
106015
106016
106017
106018
105273
105274
105275
105276
105277
105278
105279

105280
105281
105282
105283
105284
105285
105286
105287







-
+







    ** variable.  */
    if( bSort && (pSrc->jointype & JT_LEFT)==0 ){
      int bRev = 2;
      WHERETRACE(("      --> before isSortingIndex: nPriorSat=%d\n",nPriorSat));
      pc.plan.nOBSat = isSortingIndex(p, pProbe, iCur, &bRev);
      WHERETRACE(("      --> after  isSortingIndex: bRev=%d nOBSat=%d\n",
                  bRev, pc.plan.nOBSat));
      if( nPriorSat<pc.plan.nOBSat || (pc.plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
      if( nPriorSat<pc.plan.nOBSat || (pc.plan.wsFlags & WHERE_UNIQUE)!=0 ){
        pc.plan.wsFlags |= WHERE_ORDERED;
      }
      if( nOrderBy==pc.plan.nOBSat ){
        bSort = 0;
        pc.plan.wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE;
      }
      if( bRev & 1 ) pc.plan.wsFlags |= WHERE_REVERSE;
106271
106272
106273
106274
106275
106276
106277
106278
106279


106280
106281
106282
106283
106284
106285
106286
106287
105540
105541
105542
105543
105544
105545
105546


105547
105548

105549
105550
105551
105552
105553
105554
105555







-
-
+
+
-







  assert( p->pOrderBy || (p->cost.plan.wsFlags&WHERE_ORDERED)==0 );
  assert( p->cost.plan.u.pIdx==0 || (p->cost.plan.wsFlags&WHERE_ROWID_EQ)==0 );
  assert( pSrc->pIndex==0 
       || p->cost.plan.u.pIdx==0 
       || p->cost.plan.u.pIdx==pSrc->pIndex 
  );

  WHERETRACE(("   best index is %s cost=%.1f\n",
         p->cost.plan.u.pIdx ? p->cost.plan.u.pIdx->zName : "ipk",
  WHERETRACE(("   best index is: %s\n",
         p->cost.plan.u.pIdx ? p->cost.plan.u.pIdx->zName : "ipk"));
         p->cost.rCost));
  
  bestOrClauseIndex(p);
  bestAutomaticIndex(p);
  p->cost.plan.wsFlags |= eqTermMask;
}

/*
106783
106784
106785
106786
106787
106788
106789
106790
106791
106792
106793
106794
106795
106796
106797
106798
106799
106800
106801
106802
106803
106804
106805
106806
106807
106808
106809
106810
106811
106812
106813
106814
106815
106816
106817
106818
106819
106820

106821
106822
106823
106824
106825
106826

106827
106828
106829
106830
106831
106832
106833
106834
106835

106836
106837
106838
106839
106840
106841
106842
106051
106052
106053
106054
106055
106056
106057










106058
106059
106060
106061
106062
106063

106064
106065
106066
106067
106068
106069
106070
106071
106072

106073
106074
106075

106076






106077

106078
106079
106080
106081
106082
106083
106084

106085
106086
106087
106088
106089
106090
106091
106092







-
-
-
-
-
-
-
-
-
-






-









-



-
+
-
-
-
-
-
-
+
-







-
+







  */
  if( pLevel->iFrom>0 && (pTabItem[0].jointype & JT_LEFT)!=0 ){
    pLevel->iLeftJoin = ++pParse->nMem;
    sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin);
    VdbeComment((v, "init LEFT JOIN no-match flag"));
  }

  /* Special case of a FROM clause subquery implemented as a co-routine */
  if( pTabItem->viaCoroutine ){
    int regYield = pTabItem->regReturn;
    sqlite3VdbeAddOp2(v, OP_Integer, pTabItem->addrFillSub-1, regYield);
    pLevel->p2 =  sqlite3VdbeAddOp1(v, OP_Yield, regYield);
    VdbeComment((v, "next row of co-routine %s", pTabItem->pTab->zName));
    sqlite3VdbeAddOp2(v, OP_If, regYield+1, addrBrk);
    pLevel->op = OP_Goto;
  }else

#ifndef SQLITE_OMIT_VIRTUALTABLE
  if(  (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){
    /* Case 0:  The table is a virtual-table.  Use the VFilter and VNext
    **          to access the data.
    */
    int iReg;   /* P3 Value for OP_VFilter */
    int addrNotFound;
    sqlite3_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx;
    int nConstraint = pVtabIdx->nConstraint;
    struct sqlite3_index_constraint_usage *aUsage =
                                                pVtabIdx->aConstraintUsage;
    const struct sqlite3_index_constraint *aConstraint =
                                                pVtabIdx->aConstraint;

    sqlite3ExprCachePush(pParse);
    iReg = sqlite3GetTempRange(pParse, nConstraint+2);
    addrNotFound = pLevel->addrBrk;
    for(j=1; j<=nConstraint; j++){
      for(k=0; k<nConstraint; k++){
        if( aUsage[k].argvIndex==j ){
          WhereTerm *pTerm = &pWC->a[aConstraint[k].iTermOffset];
          int iTerm = aConstraint[k].iTermOffset;
          int iTarget = iReg+j+1;
          if( pTerm->eOperator & WO_IN ){
            codeEqualityTerm(pParse, pTerm, pLevel, iTarget);
            addrNotFound = pLevel->addrNxt;
          }else{
            sqlite3ExprCode(pParse, pTerm->pExpr->pRight, iTarget);
          sqlite3ExprCode(pParse, pWC->a[iTerm].pExpr->pRight, iReg+j+1);
          }
          break;
        }
      }
      if( k==nConstraint ) break;
    }
    sqlite3VdbeAddOp2(v, OP_Integer, pVtabIdx->idxNum, iReg);
    sqlite3VdbeAddOp2(v, OP_Integer, j-1, iReg+1);
    sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, pVtabIdx->idxStr,
    sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrBrk, iReg, pVtabIdx->idxStr,
                      pVtabIdx->needToFreeIdxStr ? P4_MPRINTF : P4_STATIC);
    pVtabIdx->needToFreeIdxStr = 0;
    for(j=0; j<nConstraint; j++){
      if( aUsage[j].omit ){
        int iTerm = aConstraint[j].iTermOffset;
        disableTerm(pLevel, &pWC->a[iTerm]);
      }
107774
107775
107776
107777
107778
107779
107780
107781
107782
107783
107784
107785
107786
107787
107788
107024
107025
107026
107027
107028
107029
107030

107031
107032
107033
107034
107035
107036
107037







-







  for(sWBI.i=iFrom=0, pLevel=pWInfo->a; sWBI.i<nTabList; sWBI.i++, pLevel++){
    WhereCost bestPlan;         /* Most efficient plan seen so far */
    Index *pIdx;                /* Index for FROM table at pTabItem */
    int j;                      /* For looping over FROM tables */
    int bestJ = -1;             /* The value of j */
    Bitmask m;                  /* Bitmask value for j or bestJ */
    int isOptimal;              /* Iterator for optimal/non-optimal search */
    int ckOptimal;              /* Do the optimal scan check */
    int nUnconstrained;         /* Number tables without INDEXED BY */
    Bitmask notIndexed;         /* Mask of tables that cannot use an index */

    memset(&bestPlan, 0, sizeof(bestPlan));
    bestPlan.rCost = SQLITE_BIG_DBL;
    WHERETRACE(("*** Begin search for loop %d ***\n", sWBI.i));

107809
107810
107811
107812
107813
107814
107815
107816
107817




107818
107819
107820
107821
107822
107823
107824
107825
107826
107827
107828
107829
107830
107831
107832

107833
107834
107835
107836
107837
107838
107839




107840
107841
107842
107843
107844
107845
107846
107847
107848
107849
107850
107851
107852
107853
107854
107855
107856
107857
107858
107859
107860
107861
107862
107863
107864
107865
107866
107867
107868
107869
107870
107871
107872
107873
107058
107059
107060
107061
107062
107063
107064


107065
107066
107067
107068
107069
107070
107071
107072
107073
107074
107075
107076
107077
107078
107079
107080
107081
107082

107083






107084
107085
107086
107087
107088
107089
107090
107091
107092
107093






















107094
107095
107096
107097
107098
107099
107100







-
-
+
+
+
+














-
+
-
-
-
-
-
-

+
+
+
+





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







    ** that do not use indices.  But this nRow reduction only happens if the
    ** table really is the innermost join.  
    **
    ** The second loop iteration is only performed if no optimal scan
    ** strategies were found by the first iteration. This second iteration
    ** is used to search for the lowest cost scan overall.
    **
    ** Without the optimal scan step (the first iteration) a suboptimal
    ** plan might be chosen for queries like this:
    ** Previous versions of SQLite performed only the second iteration -
    ** the next outermost loop was always that with the lowest overall
    ** cost. However, this meant that SQLite could select the wrong plan
    ** for scripts such as the following:
    **   
    **   CREATE TABLE t1(a, b); 
    **   CREATE TABLE t2(c, d);
    **   SELECT * FROM t2, t1 WHERE t2.rowid = t1.a;
    **
    ** The best strategy is to iterate through table t1 first. However it
    ** is not possible to determine this with a simple greedy algorithm.
    ** Since the cost of a linear scan through table t2 is the same 
    ** as the cost of a linear scan through table t1, a simple greedy 
    ** algorithm may choose to use t2 for the outer loop, which is a much
    ** costlier approach.
    */
    nUnconstrained = 0;
    notIndexed = 0;

    for(isOptimal=(iFrom<nTabList-1); isOptimal>=0 && bestJ<0; isOptimal--){
    /* The optimal scan check only occurs if there are two or more tables
    ** available to be reordered */
    if( iFrom==nTabList-1 ){
      ckOptimal = 0;  /* Common case of just one table in the FROM clause */
    }else{
      ckOptimal = -1;
      for(j=iFrom, sWBI.pSrc=&pTabList->a[j]; j<nTabList; j++, sWBI.pSrc++){
        int doNotReorder;    /* True if this table should not be reordered */
  
        doNotReorder =  (sWBI.pSrc->jointype & (JT_LEFT|JT_CROSS))!=0;
        if( j!=iFrom && doNotReorder ) break;
        m = getMask(pMaskSet, sWBI.pSrc->iCursor);
        if( (m & sWBI.notValid)==0 ){
          if( j==iFrom ) iFrom++;
          continue;
        }
        if( j>iFrom && (sWBI.pSrc->jointype & (JT_LEFT|JT_CROSS))!=0 ) break;
        if( ++ckOptimal ) break;
        if( (sWBI.pSrc->jointype & JT_LEFT)!=0 ) break;
      }
    }
    assert( ckOptimal==0 || ckOptimal==1 );

    for(isOptimal=ckOptimal; isOptimal>=0 && bestJ<0; isOptimal--){
      for(j=iFrom, sWBI.pSrc=&pTabList->a[j]; j<nTabList; j++, sWBI.pSrc++){
        if( j>iFrom && (sWBI.pSrc->jointype & (JT_LEFT|JT_CROSS))!=0 ){
          /* This break and one like it in the ckOptimal computation loop
          ** above prevent table reordering across LEFT and CROSS JOINs.
          ** The LEFT JOIN case is necessary for correctness.  The prohibition
          ** against reordering across a CROSS JOIN is an SQLite feature that
          ** allows the developer to control table reordering */
          break;
        }
        m = getMask(pMaskSet, sWBI.pSrc->iCursor);
        if( (m & sWBI.notValid)==0 ){
          assert( j>iFrom );
          continue;
        }
        sWBI.notReady = (isOptimal ? m : sWBI.notValid);
        if( sWBI.pSrc->pIndex==0 ) nUnconstrained++;
  
        WHERETRACE(("   === trying table %d (%s) with isOptimal=%d ===\n",
                    j, sWBI.pSrc->pTab->zName, isOptimal));
        assert( sWBI.pSrc->pTab );
#ifndef SQLITE_OMIT_VIRTUALTABLE
107886
107887
107888
107889
107890
107891
107892
107893
107894
107895
107896
107897
107898
107899
107900
107901
107902
107903
107904
107905
107906
107907
107908
107909
107910
107911
107912
107913
107914


107915
107916
107917
107918
107919
107920
107921
107922
107923
107924
107925
107926
107927
107928



107929
107930
107931
107932
107933
107934
107935
107936
107937
107938
107939
107940
107941

107942
107943
107944
107945
107946
107947
107948
107949
107950
107951
107952
107953
107954
107955
107956
107957
107958
107959
107960
107113
107114
107115
107116
107117
107118
107119













107120
107121
107122
107123
107124
107125
107126


107127
107128
107129
107130
107131
107132
107133
107134
107135
107136
107137
107138
107139
107140
107141
107142
107143
107144
107145
107146
107147
107148
107149
107150
107151
107152
107153
107154
107155
107156
107157

107158




107159
107160
107161
107162




107163
107164
107165
107166
107167
107168
107169







-
-
-
-
-
-
-
-
-
-
-
-
-







-
-
+
+














+
+
+












-
+
-
-
-
-




-
-
-
-







        assert( sWBI.pSrc->pIndex==0 
                  || (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0
                  || sWBI.cost.plan.u.pIdx==sWBI.pSrc->pIndex );

        if( isOptimal && (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){
          notIndexed |= m;
        }
        if( isOptimal ){
          pWInfo->a[j].rOptCost = sWBI.cost.rCost;
        }else if( ckOptimal ){
          /* If two or more tables have nearly the same outer loop cost, but
          ** very different inner loop (optimal) cost, we want to choose
          ** for the outer loop that table which benefits the least from
          ** being in the inner loop.  The following code scales the 
          ** outer loop cost estimate to accomplish that. */
          WHERETRACE(("   scaling cost from %.1f to %.1f\n",
                      sWBI.cost.rCost,
                      sWBI.cost.rCost/pWInfo->a[j].rOptCost));
          sWBI.cost.rCost /= pWInfo->a[j].rOptCost;
        }

        /* Conditions under which this table becomes the best so far:
        **
        **   (1) The table must not depend on other tables that have not
        **       yet run.  (In other words, it must not depend on tables
        **       in inner loops.)
        **
        **   (2) (This rule was removed on 2012-11-09.  The scaling of the
        **       cost using the optimal scan cost made this rule obsolete.)
        **   (2) A full-table-scan plan cannot supercede indexed plan unless
        **       the full-table-scan is an "optimal" plan as defined above.
        **
        **   (3) All tables have an INDEXED BY clause or this table lacks an
        **       INDEXED BY clause or this table uses the specific
        **       index specified by its INDEXED BY clause.  This rule ensures
        **       that a best-so-far is always selected even if an impossible
        **       combination of INDEXED BY clauses are given.  The error
        **       will be detected and relayed back to the application later.
        **       The NEVER() comes about because rule (2) above prevents
        **       An indexable full-table-scan from reaching rule (3).
        **
        **   (4) The plan cost must be lower than prior plans, where "cost"
        **       is defined by the compareCost() function above. 
        */
        if( (sWBI.cost.used&sWBI.notValid)==0                    /* (1) */
            && (bestJ<0 || (notIndexed&m)!=0                     /* (2) */
                || (bestPlan.plan.wsFlags & WHERE_NOT_FULLSCAN)==0
                || (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0)
            && (nUnconstrained==0 || sWBI.pSrc->pIndex==0        /* (3) */
                || NEVER((sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0))
            && (bestJ<0 || compareCost(&sWBI.cost, &bestPlan))   /* (4) */
        ){
          WHERETRACE(("   === table %d (%s) is best so far\n"
                      "       cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=%08x\n",
                      j, sWBI.pSrc->pTab->zName,
                      sWBI.cost.rCost, sWBI.cost.plan.nRow,
                      sWBI.cost.plan.nOBSat, sWBI.cost.plan.wsFlags));
          bestPlan = sWBI.cost;
          bestJ = j;
        }

        if( doNotReorder ) break;
        /* In a join like "w JOIN x LEFT JOIN y JOIN z"  make sure that
        ** table y (and not table z) is always the next inner loop inside
        ** of table x. */
        if( (sWBI.pSrc->jointype & JT_LEFT)!=0 ) break;
      }
    }
    assert( bestJ>=0 );
    assert( sWBI.notValid & getMask(pMaskSet, pTabList->a[bestJ].iCursor) );
    assert( bestJ==iFrom || (pTabList->a[iFrom].jointype & JT_LEFT)==0 );
    testcase( bestJ>iFrom && (pTabList->a[iFrom].jointype & JT_CROSS)!=0 );
    testcase( bestJ>iFrom && bestJ<nTabList-1
                          && (pTabList->a[bestJ+1].jointype & JT_LEFT)!=0 );
    WHERETRACE(("*** Optimizer selects table %d (%s) for loop %d with:\n"
                "    cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=0x%08x\n",
                bestJ, pTabList->a[bestJ].pTab->zName,
                pLevel-pWInfo->a, bestPlan.rCost, bestPlan.plan.nRow,
                bestPlan.plan.nOBSat, bestPlan.plan.wsFlags));
    if( (bestPlan.plan.wsFlags & WHERE_DISTINCT)!=0 ){
      assert( pWInfo->eDistinct==0 );
108049
108050
108051
108052
108053
108054
108055
108056
108057
108058
108059
108060
108061
108062
108063
108064
107258
107259
107260
107261
107262
107263
107264


107265
107266
107267
107268
107269
107270
107271







-
-







      /* Do nothing */
    }else
#ifndef SQLITE_OMIT_VIRTUALTABLE
    if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){
      const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
      int iCur = pTabItem->iCursor;
      sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, pVTab, P4_VTAB);
    }else if( IsVirtual(pTab) ){
      /* noop */
    }else
#endif
    if( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0
         && (wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 ){
      int op = pWInfo->okOnePass ? OP_OpenWrite : OP_OpenRead;
      sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op);
      testcase( pTab->nCol==BMS-1 );
108506
108507
108508
108509
108510
108511
108512
108513
108514
108515
108516
108517
108518
108519
108520
107713
107714
107715
107716
107717
107718
107719

107720
107721
107722
107723
107724
107725
107726







-







  sqlite3ParserTOKENTYPE yy0;
  struct LimitVal yy64;
  Expr* yy122;
  Select* yy159;
  IdList* yy180;
  struct {int value; int mask;} yy207;
  u8 yy258;
  u16 yy305;
  struct LikeOp yy318;
  TriggerStep* yy327;
  ExprSpan yy342;
  SrcList* yy347;
  int yy392;
  struct TrigEvent yy410;
  ExprList* yy442;
110457
110458
110459
110460
110461
110462
110463


110464
110465
110466
110467
110468
110469
110470
110471
110472

110473
110474
110475
110476
110477
110478
110479
109663
109664
109665
109666
109667
109668
109669
109670
109671
109672
109673
109674
109675
109676
109677
109678
109679
109680
109681
109682
109683
109684
109685
109686
109687
109688







+
+









+







      case 31: /* temp ::= */ yytestcase(yyruleno==31);
      case 69: /* autoinc ::= */ yytestcase(yyruleno==69);
      case 82: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==82);
      case 84: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==84);
      case 86: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==86);
      case 98: /* defer_subclause_opt ::= */ yytestcase(yyruleno==98);
      case 109: /* ifexists ::= */ yytestcase(yyruleno==109);
      case 120: /* distinct ::= ALL */ yytestcase(yyruleno==120);
      case 121: /* distinct ::= */ yytestcase(yyruleno==121);
      case 221: /* between_op ::= BETWEEN */ yytestcase(yyruleno==221);
      case 224: /* in_op ::= IN */ yytestcase(yyruleno==224);
{yygotominor.yy392 = 0;}
        break;
      case 29: /* ifnotexists ::= IF NOT EXISTS */
      case 30: /* temp ::= TEMP */ yytestcase(yyruleno==30);
      case 70: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==70);
      case 85: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==85);
      case 108: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==108);
      case 119: /* distinct ::= DISTINCT */ yytestcase(yyruleno==119);
      case 222: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==222);
      case 225: /* in_op ::= NOT IN */ yytestcase(yyruleno==225);
{yygotominor.yy392 = 1;}
        break;
      case 32: /* create_table_args ::= LP columnlist conslist_opt RP */
{
  sqlite3EndTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0);
110705
110706
110707
110708
110709
110710
110711
110712

110713
110714
110715
110716
110717
110718
110719
110720
110721
110722
110723
110724
110725
110726
110727
109914
109915
109916
109917
109918
109919
109920

109921
109922







109923
109924
109925
109926
109927
109928
109929







-
+

-
-
-
-
-
-
-







}
        break;
      case 116: /* multiselect_op ::= UNION ALL */
{yygotominor.yy392 = TK_ALL;}
        break;
      case 118: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
{
  yygotominor.yy159 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy442,yymsp[-5].minor.yy347,yymsp[-4].minor.yy122,yymsp[-3].minor.yy442,yymsp[-2].minor.yy122,yymsp[-1].minor.yy442,yymsp[-7].minor.yy305,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset);
  yygotominor.yy159 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy442,yymsp[-5].minor.yy347,yymsp[-4].minor.yy122,yymsp[-3].minor.yy442,yymsp[-2].minor.yy122,yymsp[-1].minor.yy442,yymsp[-7].minor.yy392,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset);
}
        break;
      case 119: /* distinct ::= DISTINCT */
{yygotominor.yy305 = SF_Distinct;}
        break;
      case 120: /* distinct ::= ALL */
      case 121: /* distinct ::= */ yytestcase(yyruleno==121);
{yygotominor.yy305 = 0;}
        break;
      case 122: /* sclp ::= selcollist COMMA */
      case 246: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==246);
{yygotominor.yy442 = yymsp[-1].minor.yy442;}
        break;
      case 123: /* sclp ::= */
      case 151: /* orderby_opt ::= */ yytestcase(yyruleno==151);
110783
110784
110785
110786
110787
110788
110789
110790
110791
110792
110793
110794
110795
110796
110797
110798
110799
110800
110801
110802
110803

110804
110805
110806
110807
110808
110809
110810
109985
109986
109987
109988
109989
109990
109991










109992
109993
109994

109995
109996
109997
109998
109999
110000
110001
110002







-
-
-
-
-
-
-
-
-
-



-
+







    yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy159,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
  }
        break;
      case 136: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
{
    if( yymsp[-6].minor.yy347==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy122==0 && yymsp[0].minor.yy180==0 ){
      yygotominor.yy347 = yymsp[-4].minor.yy347;
    }else if( yymsp[-4].minor.yy347->nSrc==1 ){
      yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
      if( yygotominor.yy347 ){
        struct SrcList_item *pNew = &yygotominor.yy347->a[yygotominor.yy347->nSrc-1];
        struct SrcList_item *pOld = yymsp[-4].minor.yy347->a;
        pNew->zName = pOld->zName;
        pNew->zDatabase = pOld->zDatabase;
        pOld->zName = pOld->zDatabase = 0;
      }
      sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy347);
    }else{
      Select *pSubquery;
      sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy347);
      pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,SF_NestedFrom,0,0);
      pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,0,0,0);
      yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
    }
  }
        break;
      case 137: /* dbnm ::= */
      case 146: /* indexed_opt ::= */ yytestcase(yyruleno==146);
{yygotominor.yy0.z=0; yygotominor.yy0.n=0;}
111011
111012
111013
111014
111015
111016
111017
111018

111019
111020
111021
111022
111023
111024
111025
111026
111027
111028
111029
111030
111031
111032
111033
111034
111035
111036

111037
111038
111039
111040
111041
111042
111043
110203
110204
110205
110206
110207
110208
110209

110210
110211
110212
110213
110214
110215
110216
110217
110218
110219
110220
110221
110222
110223
110224
110225
110226
110227

110228
110229
110230
110231
110232
110233
110234
110235







-
+

















-
+







  spanExpr(&yygotominor.yy342, pParse, TK_VARIABLE, &yymsp[0].minor.yy0);
  sqlite3ExprAssignVarNumber(pParse, yygotominor.yy342.pExpr);
  spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
}
        break;
      case 194: /* expr ::= expr COLLATE ids */
{
  yygotominor.yy342.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy342.pExpr, &yymsp[0].minor.yy0);
  yygotominor.yy342.pExpr = sqlite3ExprSetCollByToken(pParse, yymsp[-2].minor.yy342.pExpr, &yymsp[0].minor.yy0);
  yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart;
  yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
}
        break;
      case 195: /* expr ::= CAST LP expr AS typetoken RP */
{
  yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy342.pExpr, 0, &yymsp[-1].minor.yy0);
  spanSet(&yygotominor.yy342,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0);
}
        break;
      case 196: /* expr ::= ID LP distinct exprlist RP */
{
  if( yymsp[-1].minor.yy442 && yymsp[-1].minor.yy442->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
    sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0);
  }
  yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy442, &yymsp[-4].minor.yy0);
  spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
  if( yymsp[-2].minor.yy305 && yygotominor.yy342.pExpr ){
  if( yymsp[-2].minor.yy392 && yygotominor.yy342.pExpr ){
    yygotominor.yy342.pExpr->flags |= EP_Distinct;
  }
}
        break;
      case 197: /* expr ::= ID LP STAR RP */
{
  yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0);
111270
111271
111272
111273
111274
111275
111276

111277




111278
111279
111280
111281
111282
111283
111284
111285

111286




111287
111288
111289
111290
111291
111292
111293
110462
110463
110464
110465
110466
110467
110468
110469

110470
110471
110472
110473
110474
110475
110476
110477
110478
110479
110480
110481
110482

110483
110484
110485
110486
110487
110488
110489
110490
110491
110492
110493







+
-
+
+
+
+








+
-
+
+
+
+







{yygotominor.yy392 = OE_Abort;}
        break;
      case 244: /* uniqueflag ::= */
{yygotominor.yy392 = OE_None;}
        break;
      case 247: /* idxlist ::= idxlist COMMA nm collate sortorder */
{
  Expr *p = 0;
  Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0);
  if( yymsp[-1].minor.yy0.n>0 ){
    p = sqlite3Expr(pParse->db, TK_COLUMN, 0);
    sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0);
  }
  yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, p);
  sqlite3ExprListSetName(pParse,yygotominor.yy442,&yymsp[-2].minor.yy0,1);
  sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index");
  if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
}
        break;
      case 248: /* idxlist ::= nm collate sortorder */
{
  Expr *p = 0;
  Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0);
  if( yymsp[-1].minor.yy0.n>0 ){
    p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0);
    sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0);
  }
  yygotominor.yy442 = sqlite3ExprListAppend(pParse,0, p);
  sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1);
  sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index");
  if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
}
        break;
      case 249: /* collate ::= */
113094
113095
113096
113097
113098
113099
113100
113101
113102
113103
113104
113105
113106
113107
113108
113109
113110
113111
113112
113113
113114
112294
112295
112296
112297
112298
112299
112300







112301
112302
112303
112304
112305
112306
112307







-
-
-
-
-
-
-







  /* If SQLite is already completely initialized, then this call
  ** to sqlite3_initialize() should be a no-op.  But the initialization
  ** must be complete.  So isInit must not be set until the very end
  ** of this routine.
  */
  if( sqlite3GlobalConfig.isInit ) return SQLITE_OK;

#ifdef SQLITE_ENABLE_SQLLOG
  {
    extern void sqlite3_init_sqllog(void);
    sqlite3_init_sqllog();
  }
#endif

  /* Make sure the mutex subsystem is initialized.  If unable to 
  ** initialize the mutex subsystem, return early with the error.
  ** If the system is so sick that we are unable to allocate a mutex,
  ** there is not much SQLite is going to be able to do.
  **
  ** The mutex subsystem must take care of serializing its own
  ** initialization.
113449
113450
113451
113452
113453
113454
113455
113456
113457
113458
113459
113460
113461
113462
113463
113464
113465
113466
113467
113468
113469
113470
113471
112642
112643
112644
112645
112646
112647
112648









112649
112650
112651
112652
112653
112654
112655







-
-
-
-
-
-
-
-
-







    }

    case SQLITE_CONFIG_COVERING_INDEX_SCAN: {
      sqlite3GlobalConfig.bUseCis = va_arg(ap, int);
      break;
    }

#ifdef SQLITE_ENABLE_SQLLOG
    case SQLITE_CONFIG_SQLLOG: {
      typedef void(*SQLLOGFUNC_t)(void*, sqlite3*, const char*, int);
      sqlite3GlobalConfig.xSqllog = va_arg(ap, SQLLOGFUNC_t);
      sqlite3GlobalConfig.pSqllogArg = va_arg(ap, void *);
      break;
    }
#endif

    default: {
      rc = SQLITE_ERROR;
      break;
    }
  }
  va_end(ap);
  return rc;
113797
113798
113799
113800
113801
113802
113803
113804
113805
113806
113807
113808
113809
113810
113811
113812
113813
113814
113815
113816
113817
112981
112982
112983
112984
112985
112986
112987







112988
112989
112990
112991
112992
112993
112994







-
-
-
-
-
-
-







  if( !forceZombie && connectionIsBusy(db) ){
    sqlite3Error(db, SQLITE_BUSY, "unable to close due to unfinalized "
       "statements or unfinished backups");
    sqlite3_mutex_leave(db->mutex);
    return SQLITE_BUSY;
  }

#ifdef SQLITE_ENABLE_SQLLOG
  if( sqlite3GlobalConfig.xSqllog ){
    /* Closing the handle. Fourth parameter is passed the value 2. */
    sqlite3GlobalConfig.xSqllog(sqlite3GlobalConfig.pSqllogArg, db, 0, 2);
  }
#endif

  /* Convert the connection into a zombie and then close it.
  */
  db->magic = SQLITE_MAGIC_ZOMBIE;
  sqlite3LeaveMutexAndCloseZombie(db);
  return SQLITE_OK;
}

115436
115437
115438
115439
115440
115441
115442
115443
115444
115445
115446
115447
115448
115449
115450
115451
115452
115453
115454
115455
115456
114613
114614
114615
114616
114617
114618
114619







114620
114621
114622
114623
114624
114625
114626







-
-
-
-
-
-
-







  if( rc==SQLITE_NOMEM ){
    sqlite3_close(db);
    db = 0;
  }else if( rc!=SQLITE_OK ){
    db->magic = SQLITE_MAGIC_SICK;
  }
  *ppDb = db;
#ifdef SQLITE_ENABLE_SQLLOG
  if( sqlite3GlobalConfig.xSqllog ){
    /* Opening a db handle. Fourth parameter is passed 0. */
    void *pArg = sqlite3GlobalConfig.pSqllogArg;
    sqlite3GlobalConfig.xSqllog(pArg, db, zFilename, 0);
  }
#endif
  return sqlite3ApiExit(0, rc);
}

/*
** Open a new database handle.
*/
SQLITE_API int sqlite3_open(
116011
116012
116013
116014
116015
116016
116017
116018

116019
116020
116021
116022
116023
116024
116025
115181
115182
115183
115184
115185
115186
115187

115188
115189
115190
115191
115192
115193
115194
115195







-
+







    ** operation N should be 0.  The idea is that a test program (like the
    ** SQL Logic Test or SLT test module) can run the same SQL multiple times
    ** with various optimizations disabled to verify that the same answer
    ** is obtained in every case.
    */
    case SQLITE_TESTCTRL_OPTIMIZATIONS: {
      sqlite3 *db = va_arg(ap, sqlite3*);
      db->dbOptFlags = (u16)(va_arg(ap, int) & 0xffff);
      db->dbOptFlags = (u8)(va_arg(ap, int) & 0xff);
      break;
    }

#ifdef SQLITE_N_KEYWORD
    /* sqlite3_test_control(SQLITE_TESTCTRL_ISKEYWORD, const char *zWord)
    **
    ** If zWord is a keyword recognized by the parser, then return the
122083
122084
122085
122086
122087
122088
122089
122090
122091
122092
122093
122094
122095
122096
122097
122098
122099







122100
122101
122102
122103
122104
122105
122106
122107
122108
122109
122110
122111
122112
122113
122114
122115
122116
122117
122118
122119



















122120
122121

122122
122123
122124
122125
122126
122127
122128
122129
121253
121254
121255
121256
121257
121258
121259










121260
121261
121262
121263
121264
121265
121266
121267



















121268
121269
121270
121271
121272
121273
121274
121275
121276
121277
121278
121279
121280
121281
121282
121283
121284
121285
121286
121287

121288

121289
121290
121291
121292
121293
121294
121295







-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+
-







    char *aTmp;                   /* Temp space for PoslistNearMerge() */

    /* Allocate temporary working space. */
    for(p=pExpr; p->pLeft; p=p->pLeft){
      nTmp += p->pRight->pPhrase->doclist.nList;
    }
    nTmp += p->pPhrase->doclist.nList;
    if( nTmp==0 ){
      res = 0;
    }else{
      aTmp = sqlite3_malloc(nTmp*2);
      if( !aTmp ){
        *pRc = SQLITE_NOMEM;
        res = 0;
      }else{
        char *aPoslist = p->pPhrase->doclist.pList;
        int nToken = p->pPhrase->nToken;
    aTmp = sqlite3_malloc(nTmp*2);
    if( !aTmp ){
      *pRc = SQLITE_NOMEM;
      res = 0;
    }else{
      char *aPoslist = p->pPhrase->doclist.pList;
      int nToken = p->pPhrase->nToken;

        for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
          Fts3Phrase *pPhrase = p->pRight->pPhrase;
          int nNear = p->nNear;
          res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
        }

        aPoslist = pExpr->pRight->pPhrase->doclist.pList;
        nToken = pExpr->pRight->pPhrase->nToken;
        for(p=pExpr->pLeft; p && res; p=p->pLeft){
          int nNear;
          Fts3Phrase *pPhrase;
          assert( p->pParent && p->pParent->pLeft==p );
          nNear = p->pParent->nNear;
          pPhrase = (
              p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
              );
          res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
        }
      }
      for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
        Fts3Phrase *pPhrase = p->pRight->pPhrase;
        int nNear = p->nNear;
        res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
      }
  
      aPoslist = pExpr->pRight->pPhrase->doclist.pList;
      nToken = pExpr->pRight->pPhrase->nToken;
      for(p=pExpr->pLeft; p && res; p=p->pLeft){
        int nNear;
        Fts3Phrase *pPhrase;
        assert( p->pParent && p->pParent->pLeft==p );
        nNear = p->pParent->nNear;
        pPhrase = (
            p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
        );
        res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
      }
    }

      sqlite3_free(aTmp);
    sqlite3_free(aTmp);
    }
  }

  return res;
}

/*
** This function is a helper function for fts3EvalTestDeferredAndNear().
123353
123354
123355
123356
123357
123358
123359
123360

123361
123362
123363
123364
123365
123366
123367
122519
122520
122521
122522
122523
122524
122525

122526
122527
122528
122529
122530
122531
122532
122533







-
+







  sqlite3_tokenizer_cursor *pCursor;
  Fts3Expr *pRet = 0;
  int nConsumed = 0;

  rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, n, &pCursor);
  if( rc==SQLITE_OK ){
    const char *zToken;
    int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0;
    int nToken, iStart, iEnd, iPosition;
    int nByte;                               /* total space to allocate */

    rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
    if( rc==SQLITE_OK ){
      nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken;
      pRet = (Fts3Expr *)fts3MallocZero(nByte);
      if( !pRet ){
123468
123469
123470
123471
123472
123473
123474
123475

123476
123477
123478
123479
123480
123481
123482
122634
122635
122636
122637
122638
122639
122640

122641
122642
122643
122644
122645
122646
122647
122648







-
+







  */
  rc = sqlite3Fts3OpenTokenizer(
      pTokenizer, pParse->iLangid, zInput, nInput, &pCursor);
  if( rc==SQLITE_OK ){
    int ii;
    for(ii=0; rc==SQLITE_OK; ii++){
      const char *zByte;
      int nByte = 0, iBegin = 0, iEnd = 0, iPos = 0;
      int nByte, iBegin, iEnd, iPos;
      rc = pModule->xNext(pCursor, &zByte, &nByte, &iBegin, &iEnd, &iPos);
      if( rc==SQLITE_OK ){
        Fts3PhraseToken *pToken;

        p = fts3ReallocOrFree(p, nSpace + ii*sizeof(Fts3PhraseToken));
        if( !p ) goto no_mem;

125465
125466
125467
125468
125469
125470
125471
125472
125473
125474
125475




125476
125477
125478
125479
125480
125481
125482
124631
124632
124633
124634
124635
124636
124637




124638
124639
124640
124641
124642
124643
124644
124645
124646
124647
124648







-
-
-
-
+
+
+
+







  int nName;
  const char *zInput;
  int nInput;

  const char *azArg[64];

  const char *zToken;
  int nToken = 0;
  int iStart = 0;
  int iEnd = 0;
  int iPos = 0;
  int nToken;
  int iStart;
  int iEnd;
  int iPos;
  int i;

  Tcl_Obj *pRet;

  if( argc<2 ){
    sqlite3_result_error(context, "insufficient arguments", -1);
    return;
126715
126716
126717
126718
126719
126720
126721
126722

126723
126724
126725
126726
126727



126728
126729
126730
126731

126732
126733
126734
126735
126736
126737
126738
125881
125882
125883
125884
125885
125886
125887

125888
125889
125890



125891
125892
125893
125894
125895
125896

125897
125898
125899
125900
125901
125902
125903
125904







-
+


-
-
-
+
+
+



-
+







** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code.
*/
static int fts3PendingTermsAdd(
  Fts3Table *p,                   /* Table into which text will be inserted */
  int iLangid,                    /* Language id to use */
  const char *zText,              /* Text of document to be inserted */
  int iCol,                       /* Column into which text is being inserted */
  u32 *pnWord                     /* IN/OUT: Incr. by number tokens inserted */
  u32 *pnWord                     /* OUT: Number of tokens inserted */
){
  int rc;
  int iStart = 0;
  int iEnd = 0;
  int iPos = 0;
  int iStart;
  int iEnd;
  int iPos;
  int nWord = 0;

  char const *zToken;
  int nToken = 0;
  int nToken;

  sqlite3_tokenizer *pTokenizer = p->pTokenizer;
  sqlite3_tokenizer_module const *pModule = pTokenizer->pModule;
  sqlite3_tokenizer_cursor *pCsr;
  int (*xNext)(sqlite3_tokenizer_cursor *pCursor,
      const char**,int*,int*,int*,int*);

126779
126780
126781
126782
126783
126784
126785
126786

126787
126788
126789
126790
126791
126792
126793
125945
125946
125947
125948
125949
125950
125951

125952
125953
125954
125955
125956
125957
125958
125959







-
+







      rc = fts3PendingTermsAddOne(
          p, iCol, iPos, &pIndex->hPending, zToken, pIndex->nPrefix
      );
    }
  }

  pModule->xClose(pCsr);
  *pnWord += nWord;
  *pnWord = nWord;
  return (rc==SQLITE_DONE ? SQLITE_OK : rc);
}

/* 
** Calling this function indicates that subsequent calls to 
** fts3PendingTermsAdd() are to add term/position-list pairs for the
** contents of the document with docid iDocid.
126983
126984
126985
126986
126987
126988
126989
126990

126991
126992
126993
126994
126995
126996
126997
126998
126999
127000
127001
127002
127003
127004
127005
127006
127007
127008
127009
127010
127011
127012
127013
127014
127015
127016
127017
127018
127019
127020
127021
126149
126150
126151
126152
126153
126154
126155

126156

126157
126158
126159
126160

126161
126162
126163
126164
126165
126166
126167
126168
126169
126170
126171
126172
126173
126174
126175
126176
126177

126178
126179
126180
126181
126182
126183
126184







-
+
-




-

















-







** (an integer) of a row about to be deleted. Remove all terms from the
** full-text index.
*/
static void fts3DeleteTerms( 
  int *pRC,               /* Result code */
  Fts3Table *p,           /* The FTS table to delete from */
  sqlite3_value *pRowid,  /* The docid to be deleted */
  u32 *aSz,               /* Sizes of deleted document written here */
  u32 *aSz                /* Sizes of deleted document written here */
  int *pbFound            /* OUT: Set to true if row really does exist */
){
  int rc;
  sqlite3_stmt *pSelect;

  assert( *pbFound==0 );
  if( *pRC ) return;
  rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, &pRowid);
  if( rc==SQLITE_OK ){
    if( SQLITE_ROW==sqlite3_step(pSelect) ){
      int i;
      int iLangid = langidFromSelect(p, pSelect);
      rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pSelect, 0));
      for(i=1; rc==SQLITE_OK && i<=p->nColumn; i++){
        const char *zText = (const char *)sqlite3_column_text(pSelect, i);
        rc = fts3PendingTermsAdd(p, iLangid, zText, -1, &aSz[i-1]);
        aSz[p->nColumn] += sqlite3_column_bytes(pSelect, i);
      }
      if( rc!=SQLITE_OK ){
        sqlite3_reset(pSelect);
        *pRC = rc;
        return;
      }
      *pbFound = 1;
    }
    rc = sqlite3_reset(pSelect);
  }else{
    sqlite3_reset(pSelect);
  }
  *pRC = rc;
}
129232
129233
129234
129235
129236
129237
129238
129239

129240
129241
129242
129243
129244
129245
129246
128395
128396
128397
128398
128399
128400
128401

128402
128403
128404
128405
128406
128407
128408
128409







-
+







      }
    }

    while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
      int iCol;
      int iLangid = langidFromSelect(p, pStmt);
      rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pStmt, 0));
      memset(aSz, 0, sizeof(aSz[0]) * (p->nColumn+1));
      aSz[p->nColumn] = 0;
      for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){
        const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1);
        rc = fts3PendingTermsAdd(p, iLangid, z, iCol, &aSz[iCol]);
        aSz[p->nColumn] += sqlite3_column_bytes(pStmt, iCol+1);
      }
      if( p->bHasDocsize ){
        fts3InsertDocsize(&rc, p, aSz);
130876
130877
130878
130879
130880
130881
130882
130883
130884
130885



130886
130887
130888
130889
130890
130891
130892
130039
130040
130041
130042
130043
130044
130045



130046
130047
130048
130049
130050
130051
130052
130053
130054
130055







-
-
-
+
+
+







        const char *zText = (const char *)sqlite3_column_text(pStmt, iCol+1);
        int nText = sqlite3_column_bytes(pStmt, iCol+1);
        sqlite3_tokenizer_cursor *pT = 0;

        rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, nText, &pT);
        while( rc==SQLITE_OK ){
          char const *zToken;       /* Buffer containing token */
          int nToken = 0;           /* Number of bytes in token */
          int iDum1 = 0, iDum2 = 0; /* Dummy variables */
          int iPos = 0;             /* Position of token in zText */
          int nToken;               /* Number of bytes in token */
          int iDum1, iDum2;         /* Dummy variables */
          int iPos;                 /* Position of token in zText */

          rc = pModule->xNext(pT, &zToken, &nToken, &iDum1, &iDum2, &iPos);
          if( rc==SQLITE_OK ){
            int i;
            cksum2 = cksum2 ^ fts3ChecksumEntry(
                zToken, nToken, iLang, 0, iDocid, iCol, iPos
            );
131045
131046
131047
131048
131049
131050
131051
131052
131053
131054



131055
131056
131057
131058
131059
131060
131061
130208
130209
130210
130211
130212
130213
130214



130215
130216
130217
130218
130219
130220
130221
130222
130223
130224







-
-
-
+
+
+







    for(i=0; i<p->nColumn && rc==SQLITE_OK; i++){
      const char *zText = (const char *)sqlite3_column_text(pCsr->pStmt, i+1);
      sqlite3_tokenizer_cursor *pTC = 0;
  
      rc = sqlite3Fts3OpenTokenizer(pT, pCsr->iLangid, zText, -1, &pTC);
      while( rc==SQLITE_OK ){
        char const *zToken;       /* Buffer containing token */
        int nToken = 0;           /* Number of bytes in token */
        int iDum1 = 0, iDum2 = 0; /* Dummy variables */
        int iPos = 0;             /* Position of token in zText */
        int nToken;               /* Number of bytes in token */
        int iDum1, iDum2;         /* Dummy variables */
        int iPos;                 /* Position of token in zText */
  
        rc = pModule->xNext(pTC, &zToken, &nToken, &iDum1, &iDum2, &iPos);
        for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
          Fts3PhraseToken *pPT = pDef->pToken;
          if( (pDef->iCol>=p->nColumn || pDef->iCol==i)
           && (pPT->bFirst==0 || iPos==0)
           && (pPT->n==nToken || (pPT->isPrefix && pPT->n<nToken))
131136
131137
131138
131139
131140
131141
131142
131143

131144
131145
131146
131147
131148
131149
131150
131151
131152
131153
131154
131155
131156
131157
131158
131159









131160
131161

131162
131163
131164
131165
131166
131167









131168
131169
131170
131171
131172
131173
131174
131175
130299
130300
130301
130302
130303
130304
130305

130306
130307
130308














130309
130310
130311
130312
130313
130314
130315
130316
130317


130318






130319
130320
130321
130322
130323
130324
130325
130326
130327

130328
130329
130330
130331
130332
130333
130334







-
+


-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-







** SQLite value pRowid contains the rowid of a row that may or may not be
** present in the FTS3 table. If it is, delete it and adjust the contents
** of subsiduary data structures accordingly.
*/
static int fts3DeleteByRowid(
  Fts3Table *p, 
  sqlite3_value *pRowid, 
  int *pnChng,                    /* IN/OUT: Decrement if row is deleted */
  int *pnDoc,
  u32 *aSzDel
){
  int rc = SQLITE_OK;             /* Return code */
  int bFound = 0;                 /* True if *pRowid really is in the table */

  fts3DeleteTerms(&rc, p, pRowid, aSzDel, &bFound);
  if( bFound && rc==SQLITE_OK ){
    int isEmpty = 0;              /* Deleting *pRowid leaves the table empty */
    rc = fts3IsEmpty(p, pRowid, &isEmpty);
    if( rc==SQLITE_OK ){
      if( isEmpty ){
        /* Deleting this row means the whole table is empty. In this case
        ** delete the contents of all three tables and throw away any
        ** data in the pendingTerms hash table.  */
        rc = fts3DeleteAll(p, 1);
        *pnChng = 0;
  int isEmpty = 0;
  int rc = fts3IsEmpty(p, pRowid, &isEmpty);
  if( rc==SQLITE_OK ){
    if( isEmpty ){
      /* Deleting this row means the whole table is empty. In this case
      ** delete the contents of all three tables and throw away any
      ** data in the pendingTerms hash table.  */
      rc = fts3DeleteAll(p, 1);
      *pnDoc = *pnDoc - 1;
        memset(aSzDel, 0, sizeof(u32) * (p->nColumn+1) * 2);
      }else{
    }else{
        *pnChng = *pnChng - 1;
        if( p->zContentTbl==0 ){
          fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, &pRowid);
        }
        if( p->bHasDocsize ){
          fts3SqlExec(&rc, p, SQL_DELETE_DOCSIZE, &pRowid);
      fts3DeleteTerms(&rc, p, pRowid, aSzDel);
      if( p->zContentTbl==0 ){
        fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, &pRowid);
        if( sqlite3_changes(p->db) ) *pnDoc = *pnDoc - 1;
      }else{
        *pnDoc = *pnDoc - 1;
      }
      if( p->bHasDocsize ){
        fts3SqlExec(&rc, p, SQL_DELETE_DOCSIZE, &pRowid);
        }
      }
    }
  }

  return rc;
}

131192
131193
131194
131195
131196
131197
131198
131199

131200
131201
131202
131203
131204
131205
131206
130351
130352
130353
130354
130355
130356
130357

130358
130359
130360
130361
130362
130363
130364
130365







-
+







  sqlite3_value **apVal,          /* Array of arguments */
  sqlite_int64 *pRowid            /* OUT: The affected (or effected) rowid */
){
  Fts3Table *p = (Fts3Table *)pVtab;
  int rc = SQLITE_OK;             /* Return Code */
  int isRemove = 0;               /* True for an UPDATE or DELETE */
  u32 *aSzIns = 0;                /* Sizes of inserted documents */
  u32 *aSzDel = 0;                /* Sizes of deleted documents */
  u32 *aSzDel;                    /* Sizes of deleted documents */
  int nChng = 0;                  /* Net change in number of documents */
  int bInsertDone = 0;

  assert( p->pSegments==0 );
  assert( 
      nArg==1                     /* DELETE operations */
   || nArg==(2 + p->nColumn + 3)  /* INSERT or UPDATE operations */
131220
131221
131222
131223
131224
131225
131226
131227
131228


131229
131230
131231
131232
131233


131234
131235
131236
131237
131238
131239
131240
130379
130380
130381
130382
130383
130384
130385


130386
130387
130388
130389
130390


130391
130392
130393
130394
130395
130396
130397
130398
130399







-
-
+
+



-
-
+
+








  if( nArg>1 && sqlite3_value_int(apVal[2 + p->nColumn + 2])<0 ){
    rc = SQLITE_CONSTRAINT;
    goto update_out;
  }

  /* Allocate space to hold the change in document sizes */
  aSzDel = sqlite3_malloc( sizeof(aSzDel[0])*(p->nColumn+1)*2 );
  if( aSzDel==0 ){
  aSzIns = sqlite3_malloc( sizeof(aSzIns[0])*(p->nColumn+1)*2 );
  if( aSzIns==0 ){
    rc = SQLITE_NOMEM;
    goto update_out;
  }
  aSzIns = &aSzDel[p->nColumn+1];
  memset(aSzDel, 0, sizeof(aSzDel[0])*(p->nColumn+1)*2);
  aSzDel = &aSzIns[p->nColumn+1];
  memset(aSzIns, 0, sizeof(aSzIns[0])*(p->nColumn+1)*2);

  /* If this is an INSERT operation, or an UPDATE that modifies the rowid
  ** value, then this operation requires constraint handling.
  **
  ** If the on-conflict mode is REPLACE, this means that the existing row
  ** should be deleted from the database before inserting the new row. Or,
  ** if the on-conflict mode is other than REPLACE, then this method must
131311
131312
131313
131314
131315
131316
131317
131318

131319
131320
131321
131322
131323
131324
131325
130470
130471
130472
130473
130474
130475
130476

130477
130478
130479
130480
130481
130482
130483
130484







-
+







  }

  if( p->bFts4 ){
    fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nChng);
  }

 update_out:
  sqlite3_free(aSzDel);
  sqlite3_free(aSzIns);
  sqlite3Fts3SegmentsClose(p);
  return rc;
}

/* 
** Flush any data in the pending-terms hash table to disk. If successful,
** merge all segments in the database (including the new segment, if 
131919
131920
131921
131922
131923
131924
131925
131926

131927
131928
131929
131930
131931
131932
131933
131078
131079
131080
131081
131082
131083
131084

131085
131086
131087
131088
131089
131090
131091
131092







-
+







      ** or more tokens in zDoc/nDoc.
      */
      rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, iLangid, zDoc, nDoc, &pC);
      if( rc!=SQLITE_OK ){
        return rc;
      }
      while( rc==SQLITE_OK && iCurrent<(nSnippet+nDesired) ){
        const char *ZDUMMY; int DUMMY1 = 0, DUMMY2 = 0, DUMMY3 = 0;
        const char *ZDUMMY; int DUMMY1, DUMMY2, DUMMY3;
        rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &DUMMY2, &DUMMY3, &iCurrent);
      }
      pMod->xClose(pC);
      if( rc!=SQLITE_OK && rc!=SQLITE_DONE ){ return rc; }

      nShift = (rc==SQLITE_DONE)+iCurrent-nSnippet;
      assert( nShift<=nDesired );
131963
131964
131965
131966
131967
131968
131969


131970
131971
131972
131973
131974
131975
131976
131977
131978
131979
131980
131981
131982
131983
131984
131985
131986
131987
131988
131989
131990
131991
131992



131993
131994
131995
131996
131997
131998
131999
132000
132001
132002
132003
132004
132005
132006
132007
132008
132009
132010
132011
131122
131123
131124
131125
131126
131127
131128
131129
131130
131131
131132
131133
131134
131135
131136
131137
131138
131139
131140
131141
131142
131143
131144
131145
131146
131147
131148





131149
131150
131151
131152











131153
131154
131155
131156
131157
131158
131159







+
+


















-
-
-
-
-
+
+
+

-
-
-
-
-
-
-
-
-
-
-







  int iEnd = 0;                   /* Byte offset of end of current token */
  int isShiftDone = 0;            /* True after snippet is shifted */
  int iPos = pFragment->iPos;     /* First token of snippet */
  u64 hlmask = pFragment->hlmask; /* Highlight-mask for snippet */
  int iCol = pFragment->iCol+1;   /* Query column to extract text from */
  sqlite3_tokenizer_module *pMod; /* Tokenizer module methods object */
  sqlite3_tokenizer_cursor *pC;   /* Tokenizer cursor open on zDoc/nDoc */
  const char *ZDUMMY;             /* Dummy argument used with tokenizer */
  int DUMMY1;                     /* Dummy argument used with tokenizer */
  
  zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol);
  if( zDoc==0 ){
    if( sqlite3_column_type(pCsr->pStmt, iCol)!=SQLITE_NULL ){
      return SQLITE_NOMEM;
    }
    return SQLITE_OK;
  }
  nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol);

  /* Open a token cursor on the document. */
  pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule;
  rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, pCsr->iLangid, zDoc,nDoc,&pC);
  if( rc!=SQLITE_OK ){
    return rc;
  }

  while( rc==SQLITE_OK ){
    const char *ZDUMMY;           /* Dummy argument used with tokenizer */
    int DUMMY1 = -1;              /* Dummy argument used with tokenizer */
    int iBegin = 0;               /* Offset in zDoc of start of token */
    int iFin = 0;                 /* Offset in zDoc of end of token */
    int isHighlight = 0;          /* True for highlighted terms */
    int iBegin;                   /* Offset in zDoc of start of token */
    int iFin;                     /* Offset in zDoc of end of token */
    int isHighlight;              /* True for highlighted terms */

    /* Variable DUMMY1 is initialized to a negative value above. Elsewhere
    ** in the FTS code the variable that the third argument to xNext points to
    ** is initialized to zero before the first (*but not necessarily
    ** subsequent*) call to xNext(). This is done for a particular application
    ** that needs to know whether or not the tokenizer is being used for
    ** snippet generation or for some other purpose.
    **
    ** Extreme care is required when writing code to depend on this
    ** initialization. It is not a documented part of the tokenizer interface.
    ** If a tokenizer is used directly by any code outside of FTS, this
    ** convention might not be respected.  */
    rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &iBegin, &iFin, &iCurrent);
    if( rc!=SQLITE_OK ){
      if( rc==SQLITE_DONE ){
        /* Special case - the last token of the snippet is also the last token
        ** of the column. Append any punctuation that occurred between the end
        ** of the previous token and the end of the document to the output. 
        ** Then break out of the loop. */
132687
132688
132689
132690
132691
132692
132693


132694
132695
132696
132697
132698
132699
132700
131835
131836
131837
131838
131839
131840
131841
131842
131843
131844
131845
131846
131847
131848
131849
131850







+
+







*/
SQLITE_PRIVATE void sqlite3Fts3Offsets(
  sqlite3_context *pCtx,          /* SQLite function call context */
  Fts3Cursor *pCsr                /* Cursor object */
){
  Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
  sqlite3_tokenizer_module const *pMod = pTab->pTokenizer->pModule;
  const char *ZDUMMY;             /* Dummy argument used with xNext() */
  int NDUMMY;                     /* Dummy argument used with xNext() */
  int rc;                         /* Return Code */
  int nToken;                     /* Number of tokens in query */
  int iCol;                       /* Column currently being processed */
  StrBuffer res = {0, 0, 0};      /* Result string */
  TermOffsetCtx sCtx;             /* Context for fts3ExprTermOffsetInit() */

  if( !pCsr->pExpr ){
132719
132720
132721
132722
132723
132724
132725
132726
132727
132728
132729
132730



132731
132732
132733
132734
132735
132736
132737
131869
131870
131871
131872
131873
131874
131875





131876
131877
131878
131879
131880
131881
131882
131883
131884
131885







-
-
-
-
-
+
+
+







  sCtx.pCsr = pCsr;

  /* Loop through the table columns, appending offset information to 
  ** string-buffer res for each column.
  */
  for(iCol=0; iCol<pTab->nColumn; iCol++){
    sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor */
    const char *ZDUMMY;           /* Dummy argument used with xNext() */
    int NDUMMY = 0;               /* Dummy argument used with xNext() */
    int iStart = 0;
    int iEnd = 0;
    int iCurrent = 0;
    int iStart;
    int iEnd;
    int iCurrent;
    const char *zDoc;
    int nDoc;

    /* Initialize the contents of sCtx.aTerm[] for column iCol. There is 
    ** no way that this operation can fail, so the return code from
    ** fts3ExprIterate() can be discarded.
    */
136676
136677
136678
136679
136680
136681
136682
136683

136684
136685
136686
136687
136688
136689
136690
136691
136692
136693
136694
136695
136696
136697
136698
136699
136700
136701
136702
136703
136704
136705
136706
136707
136708
136709
136710
136711
136712
136713
136714
136715
135824
135825
135826
135827
135828
135829
135830

135831

135832
135833
135834
135835
135836
135837
135838
135839
135840
135841
135842
135843


135844
135845
135846
135847
135848
135849
135850



135851
135852
135853
135854
135855
135856
135857







-
+
-












-
-







-
-
-







** This ensures that each node is stored on a single database page. If the 
** database page-size is so large that more than RTREE_MAXCELLS entries 
** would fit in a single node, use a smaller node-size.
*/
static int getNodeSize(
  sqlite3 *db,                    /* Database handle */
  Rtree *pRtree,                  /* Rtree handle */
  int isCreate,                   /* True for xCreate, false for xConnect */
  int isCreate                    /* True for xCreate, false for xConnect */
  char **pzErr                    /* OUT: Error message, if any */
){
  int rc;
  char *zSql;
  if( isCreate ){
    int iPageSize = 0;
    zSql = sqlite3_mprintf("PRAGMA %Q.page_size", pRtree->zDb);
    rc = getIntFromStmt(db, zSql, &iPageSize);
    if( rc==SQLITE_OK ){
      pRtree->iNodeSize = iPageSize-64;
      if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)<pRtree->iNodeSize ){
        pRtree->iNodeSize = 4+pRtree->nBytesPerCell*RTREE_MAXCELLS;
      }
    }else{
      *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
    }
  }else{
    zSql = sqlite3_mprintf(
        "SELECT length(data) FROM '%q'.'%q_node' WHERE nodeno = 1",
        pRtree->zDb, pRtree->zName
    );
    rc = getIntFromStmt(db, zSql, &pRtree->iNodeSize);
    if( rc!=SQLITE_OK ){
      *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
    }
  }

  sqlite3_free(zSql);
  return rc;
}

/* 
136765
136766
136767
136768
136769
136770
136771
136772

136773
136774
136775
136776
136777
136778
136779
135907
135908
135909
135910
135911
135912
135913

135914
135915
135916
135917
135918
135919
135920
135921







-
+







  pRtree->nDim = (argc-4)/2;
  pRtree->nBytesPerCell = 8 + pRtree->nDim*4*2;
  pRtree->eCoordType = eCoordType;
  memcpy(pRtree->zDb, argv[1], nDb);
  memcpy(pRtree->zName, argv[2], nName);

  /* Figure out the node size to use. */
  rc = getNodeSize(db, pRtree, isCreate, pzErr);
  rc = getNodeSize(db, pRtree, isCreate);

  /* Create/Connect to the underlying relational database schema. If
  ** that is successful, call sqlite3_declare_vtab() to configure
  ** the r-tree table schema.
  */
  if( rc==SQLITE_OK ){
    if( (rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate)) ){
137612
137613
137614
137615
137616
137617
137618
137619

137620
137621
137622
137623
137624
137625
137626
137627

137628
137629
137630
137631
137632
137633
137634
136754
136755
136756
136757
136758
136759
136760

136761
136762
136763
136764
136765
136766
136767
136768

136769
136770
136771
136772
136773
136774
136775
136776







-
+







-
+







    zInput = "";
  }else if( nInput<0 ){
    nInput = strlen(zInput);
  }
  nChar = nInput+1;
  pCsr = (IcuCursor *)sqlite3_malloc(
      sizeof(IcuCursor) +                /* IcuCursor */
      ((nChar+3)&~3) * sizeof(UChar) +   /* IcuCursor.aChar[] */
      nChar * sizeof(UChar) +            /* IcuCursor.aChar[] */
      (nChar+1) * sizeof(int)            /* IcuCursor.aOffset[] */
  );
  if( !pCsr ){
    return SQLITE_NOMEM;
  }
  memset(pCsr, 0, sizeof(IcuCursor));
  pCsr->aChar = (UChar *)&pCsr[1];
  pCsr->aOffset = (int *)&pCsr->aChar[(nChar+3)&~3];
  pCsr->aOffset = (int *)&pCsr->aChar[nChar];

  pCsr->aOffset[iOut] = iInput;
  U8_NEXT(zInput, iInput, nInput, c); 
  while( c>0 ){
    int isError = 0;
    c = u_foldCase(c, opt);
    U16_APPEND(pCsr->aChar, iOut, nChar, c, isError);
Changes to SQLite.Interop/src/core/sqlite3.h.
103
104
105
106
107
108
109
110
111
112



113
114
115
116
117
118
119
103
104
105
106
107
108
109



110
111
112
113
114
115
116
117
118
119







-
-
-
+
+
+







** string contains the date and time of the check-in (UTC) and an SHA1
** hash of the entire source tree.
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.7.16"
#define SQLITE_VERSION_NUMBER 3007016
#define SQLITE_SOURCE_ID      "2013-01-17 03:18:38 652233d646236d3fbca629813b20d075f00f3ed6"
#define SQLITE_VERSION        "3.7.15"
#define SQLITE_VERSION_NUMBER 3007015
#define SQLITE_SOURCE_ID      "2012-10-12 18:06:07 de784399ed1f0e27fc875e32719643d19819c8fb"

/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version, sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
470
471
472
473
474
475
476

477
478
479
480
481
482
483







-







#define SQLITE_IOERR_CLOSE             (SQLITE_IOERR | (16<<8))
#define SQLITE_IOERR_DIR_CLOSE         (SQLITE_IOERR | (17<<8))
#define SQLITE_IOERR_SHMOPEN           (SQLITE_IOERR | (18<<8))
#define SQLITE_IOERR_SHMSIZE           (SQLITE_IOERR | (19<<8))
#define SQLITE_IOERR_SHMLOCK           (SQLITE_IOERR | (20<<8))
#define SQLITE_IOERR_SHMMAP            (SQLITE_IOERR | (21<<8))
#define SQLITE_IOERR_SEEK              (SQLITE_IOERR | (22<<8))
#define SQLITE_IOERR_DELETE_NOENT      (SQLITE_IOERR | (23<<8))
#define SQLITE_LOCKED_SHAREDCACHE      (SQLITE_LOCKED |  (1<<8))
#define SQLITE_BUSY_RECOVERY           (SQLITE_BUSY   |  (1<<8))
#define SQLITE_CANTOPEN_NOTEMPDIR      (SQLITE_CANTOPEN | (1<<8))
#define SQLITE_CANTOPEN_ISDIR          (SQLITE_CANTOPEN | (2<<8))
#define SQLITE_CANTOPEN_FULLPATH       (SQLITE_CANTOPEN | (3<<8))
#define SQLITE_CORRUPT_VTAB            (SQLITE_CORRUPT | (1<<8))
#define SQLITE_READONLY_RECOVERY       (SQLITE_READONLY | (1<<8))
853
854
855
856
857
858
859

860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870










871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886

887
888
889
890
891
892
893







+











-
-
-
-
-
-
-
-
-
-
















-







** VFS has handled the PRAGMA itself and the parser generates a no-op
** prepared statement.  ^If the [SQLITE_FCNTL_PRAGMA] file control returns
** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means
** that the VFS encountered an error while handling the [PRAGMA] and the
** compilation of the PRAGMA fails with an error.  ^The [SQLITE_FCNTL_PRAGMA]
** file control occurs at the beginning of pragma statement analysis and so
** it is able to override built-in [PRAGMA] statements.
** </ul>
**
** <li>[[SQLITE_FCNTL_BUSYHANDLER]]
** ^This file-control may be invoked by SQLite on the database file handle
** shortly after it is opened in order to provide a custom VFS with access
** to the connections busy-handler callback. The argument is of type (void **)
** - an array of two (void *) values. The first (void *) actually points
** to a function of type (int (*)(void *)). In order to invoke the connections
** busy-handler, this function should be invoked with the second (void *) in
** the array as the only argument. If it returns non-zero, then the operation
** should be retried. If it returns zero, the custom VFS should abandon the
** current operation.
**
** <li>[[SQLITE_FCNTL_TEMPFILENAME]]
** ^Application can invoke this file-control to have SQLite generate a
** temporary filename using the same algorithm that is followed to generate
** temporary filenames for TEMP tables and other internal uses.  The
** argument should be a char** which will be filled with the filename
** written into memory obtained from [sqlite3_malloc()].  The caller should
** invoke [sqlite3_free()] on the result to avoid a memory leak.
**
** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE               1
#define SQLITE_GET_LOCKPROXYFILE             2
#define SQLITE_SET_LOCKPROXYFILE             3
#define SQLITE_LAST_ERRNO                    4
#define SQLITE_FCNTL_SIZE_HINT               5
#define SQLITE_FCNTL_CHUNK_SIZE              6
#define SQLITE_FCNTL_FILE_POINTER            7
#define SQLITE_FCNTL_SYNC_OMITTED            8
#define SQLITE_FCNTL_WIN32_AV_RETRY          9
#define SQLITE_FCNTL_PERSIST_WAL            10
#define SQLITE_FCNTL_OVERWRITE              11
#define SQLITE_FCNTL_VFSNAME                12
#define SQLITE_FCNTL_POWERSAFE_OVERWRITE    13
#define SQLITE_FCNTL_PRAGMA                 14
#define SQLITE_FCNTL_BUSYHANDLER            15
#define SQLITE_FCNTL_TEMPFILENAME           16

/*
** CAPI3REF: Mutex Handle
**
** The mutex module within SQLite defines [sqlite3_mutex] to be an
** abstract type for a mutex object.  The SQLite core never looks
** at the internal representation of an [sqlite3_mutex].  It only
1588
1589
1590
1591
1592
1593
1594
1595

1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1577
1578
1579
1580
1581
1582
1583

1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
















1600
1601
1602
1603
1604
1605
1606







-
+















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







** connection is opened. If it is globally disabled, filenames are
** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the
** database connection is opened. By default, URI handling is globally
** disabled. The default value may be changed by compiling with the
** [SQLITE_USE_URI] symbol defined.
**
** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN
** <dd> This option takes a single integer argument which is interpreted as
** <dd> This option taks a single integer argument which is interpreted as
** a boolean in order to enable or disable the use of covering indices for
** full table scans in the query optimizer.  The default setting is determined
** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"
** if that compile-time option is omitted.
** The ability to disable the use of covering indices for full table scans
** is because some incorrectly coded legacy applications might malfunction
** malfunction when the optimization is enabled.  Providing the ability to
** disable the optimization allows the older, buggy application code to work
** without change even with newer versions of SQLite.
**
** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]]
** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE
** <dd> These options are obsolete and should not be used by new code.
** They are retained for backwards compatibility but are now no-ops.
** </dl>
**
** [[SQLITE_CONFIG_SQLLOG]]
** <dt>SQLITE_CONFIG_SQLLOG
** <dd>This option is only available if sqlite is compiled with the
** SQLITE_ENABLE_SQLLOG pre-processor macro defined. The first argument should
** be a pointer to a function of type void(*)(void*,sqlite3*,const char*, int).
** The second should be of type (void*). The callback is invoked by the library
** in three separate circumstances, identified by the value passed as the
** fourth parameter. If the fourth parameter is 0, then the database connection
** passed as the second argument has just been opened. The third argument
** points to a buffer containing the name of the main database file. If the
** fourth parameter is 1, then the SQL statement that the third parameter
** points to has just been executed. Or, if the fourth parameter is 2, then
** the connection being passed as the second parameter is being closed. The
** third parameter is passed NULL In this case.
** </dl>
*/
#define SQLITE_CONFIG_SINGLETHREAD  1  /* nil */
#define SQLITE_CONFIG_MULTITHREAD   2  /* nil */
#define SQLITE_CONFIG_SERIALIZED    3  /* nil */
#define SQLITE_CONFIG_MALLOC        4  /* sqlite3_mem_methods* */
#define SQLITE_CONFIG_GETMALLOC     5  /* sqlite3_mem_methods* */
#define SQLITE_CONFIG_SCRATCH       6  /* void*, int sz, int N */
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1614
1615
1616
1617
1618
1619
1620

1621
1622
1623
1624
1625
1626
1627







-







#define SQLITE_CONFIG_PCACHE       14  /* no-op */
#define SQLITE_CONFIG_GETPCACHE    15  /* no-op */
#define SQLITE_CONFIG_LOG          16  /* xFunc, void* */
#define SQLITE_CONFIG_URI          17  /* int */
#define SQLITE_CONFIG_PCACHE2      18  /* sqlite3_pcache_methods2* */
#define SQLITE_CONFIG_GETPCACHE2   19  /* sqlite3_pcache_methods2* */
#define SQLITE_CONFIG_COVERING_INDEX_SCAN 20  /* int */
#define SQLITE_CONFIG_SQLLOG       21  /* xSqllog, void* */

/*
** CAPI3REF: Database Connection Configuration Options
**
** These constants are the available integer configuration options that
** can be passed as the second argument to the [sqlite3_db_config()] interface.
**
Changes to SQLite.Interop/src/win/AssemblyInfo.cpp.
8
9
10
11
12
13
14
15

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

15
16
17
18
19
20
21
22







-
+







using namespace System::Reflection;
using namespace System::Resources;
using namespace System::Runtime::InteropServices;

#include "interop.h"

[assembly:AssemblyTitleAttribute("SQLite.Interop")];
[assembly:AssemblyCompanyAttribute("http://system.data.sqlite.org/")];
[assembly:AssemblyCompanyAttribute("Robert Simpson, et al.")];
[assembly:AssemblyDescriptionAttribute("System.Data.SQLite Interop Assembly")];
[assembly:AssemblyProductAttribute("System.Data.SQLite")];
[assembly:AssemblyCopyrightAttribute("Public Domain")];
[assembly:AssemblyVersionAttribute(INTEROP_VERSION)];
[assembly:AssemblyFileVersionAttribute(INTEROP_VERSION)];

#if DEBUG
Changes to SQLite.Interop/src/win/interop.c.
37
38
39
40
41
42
43
44

45
46
47
48
49
50
51
37
38
39
40
41
42
43

44
45
46
47
48
49
50
51







-
+







#else
#define sqlite3InteropBreak(a)
#endif

typedef void (*SQLITEUSERFUNC)(sqlite3_context *, int, sqlite3_value **);
typedef void (*SQLITEFUNCFINAL)(sqlite3_context *);

#if defined(INTEROP_DEBUG) || defined(INTEROP_LOG)
#if defined(INTEROP_DEBUG)
SQLITE_PRIVATE void sqlite3InteropDebug(const char *zFormat, ...){
  va_list ap;                         /* Vararg list */
  StrAccum acc;                       /* String accumulator */
  char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */
  va_start(ap, zFormat);
  sqlite3StrAccumInit(&acc, zMsg, sizeof(zMsg), 0);
  acc.useMalloc = 0;
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
63
64
65
66
67
68
69








70
71
72
73
74
75
76







-
-
-
-
-
-
-
-







      sqlite3_free(zWideMsg);
    }
  }
#else
  fprintf(stderr, "%s", sqlite3StrAccumFinish(&acc));
#endif
}
#endif

#if defined(INTEROP_LOG)
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) {
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

213
214
215
216
217
218
219
179
180
181
182
183
184
185



















186
187
188
189
190
191
192
193







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+







    sqlite3_mutex_leave(db->mutex);
    ret = sqlite3_close(db);
  }
  return ret;
#endif
}

#if defined(INTEROP_LOG)
SQLITE_API int WINAPI sqlite3_config_log_interop()
{
  int ret;
  if( !logConfigured ){
    ret = sqlite3_config(SQLITE_CONFIG_LOG, sqlite3InteropLogCallback, 0);
    if( ret==SQLITE_OK ){
      logConfigured = 1;
    }else{
      sqlite3InteropDebug("sqlite3_config_log_interop(): sqlite3_config(SQLITE_CONFIG_LOG) returned %d.\n", ret);
    }
  }else{
    ret = SQLITE_OK;
  }
  return ret;
}
#endif

SQLITE_API int WINAPI sqlite3_open_interop(const char *filename, int flags, sqlite3 **ppdb)
SQLITE_API int WINAPI sqlite3_open_interop(const char*filename, int flags, sqlite3 **ppdb)
{
  int ret;

#if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_OPEN)
  sqlite3InteropDebug("sqlite3_open_interop(): calling sqlite3_open_v2(\"%s\", %d, %p)...\n", filename, flags, ppdb);
#endif

265
266
267
268
269
270
271



272
273
274
275
276
277
278
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255







+
+
+







#if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_CHANGES)
  sqlite3InteropDebug("sqlite3_changes_interop(): calling sqlite3_changes(%p)...\n", db);
#endif

#ifndef NDEBUG
  if (!db)
      sqlite3InteropBreak("null database handle for sqlite3_changes()");

  if (!sqlite3SafetyCheckOk(db))
      sqlite3InteropBreak("bad database handle for sqlite3_changes()");
#endif

  result = sqlite3_changes(db);

#if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_CHANGES)
  sqlite3InteropDebug("sqlite3_changes_interop(): sqlite3_changes(%p) returned %d.\n", db, result);
#endif
756
757
758
759
760
761
762
763

764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811

812
813
814
815
816

817
818
819
733
734
735
736
737
738
739

740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757


















758
759
760
761
762
763
764
765
766
767

768

769
770




771


772







-
+

















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-










-

-
+

-
-
-
-
+
-
-

#include "../core/sqlite3ext.h"
SQLITE_EXTENSION_INIT1

/*
** The interopTest() SQL function returns its first argument or raises an
** error if there are not enough arguments.
*/
SQLITE_PRIVATE void interopTestFunc(
static void interopTestFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const unsigned char *z;
  if( argc!=1 ){
    sqlite3_result_error(context, "need exactly one argument", -1);
    return;
  }
  z = sqlite3_value_text(argv[0]);
  if( z ){
    sqlite3_result_text(context, (char*)z, -1, SQLITE_STATIC);
  }else{
    sqlite3_result_null(context);
  }
}

/*
** The interopSleep() SQL function waits the specified number of milliseconds
** or raises an error if there are not enough arguments.
*/
SQLITE_PRIVATE void interopSleepFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  int m;
  if( argc!=1 ){
    sqlite3_result_error(context, "need exactly one argument", -1);
    return;
  }
  m = sqlite3_value_int(argv[0]);
  sqlite3_result_int(context, SleepEx(m, TRUE));
}

/* SQLite invokes this routine once when it loads the extension.
** Create new functions, collating sequences, and virtual table
** modules here.  This is usually the only exported symbol in
** the shared library.
*/
SQLITE_API int interop_test_extension_init(
  sqlite3 *db,
  char **pzErrMsg,
  const sqlite3_api_routines *pApi
){
  int rc;
  SQLITE_EXTENSION_INIT2(pApi)
  rc = sqlite3_create_function(db, "interopTest", -1, SQLITE_ANY, 0,
  return sqlite3_create_function(db, "interopTest", -1, SQLITE_ANY, 0,
      interopTestFunc, 0, 0);
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "interopSleep", 1, SQLITE_ANY, 0,
        interopSleepFunc, 0, 0);
  }
}
  return rc;
}
#endif
Changes to SQLite.Interop/src/win/interop.h.
1
2
3
4
5
6
7
8
9

10
1
2
3
4
5
6
7
8

9
10








-
+

/*
 * interop.h -
 *
 * Written by Joe Mistachkin.
 * Released to the public domain, use at your own risk!
 */

#ifndef INTEROP_VERSION
#define INTEROP_VERSION       "1.0.84.0"
#define INTEROP_VERSION       "1.0.83.0"
#endif
Changes to SQLite.MSIL.nuspec.
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
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












-
+












-


-


<?xml version="1.0" encoding="utf-8"?>
<!--
 *
 * SQLite.MSIL.nuspec -
 *
 * Written by Joe Mistachkin.
 * Released to the public domain, use at your own risk!
 *
-->
<package>
  <metadata>
    <id>System.Data.SQLite.MSIL</id>
    <version>1.0.84.0</version>
    <version>1.0.83.0</version>
    <authors>SQLite Development Team</authors>
    <description>An ADO.NET provider for SQLite (managed-only).</description>
    <language>en-US</language>
    <projectUrl>http://system.data.sqlite.org/</projectUrl>
    <iconUrl>http://system.data.sqlite.org/images/sqlite32.png</iconUrl>
    <licenseUrl>http://www.sqlite.org/copyright.html</licenseUrl>
    <tags>sqlite database ado.net provider interop</tags>
    <copyright>Public Domain</copyright>
  </metadata>
  <files>
    <file src="bin\2008\Release\bin\System.Data.SQLite.dll" target="lib\net20" />
    <file src="bin\2010\Release\bin\System.Data.SQLite.dll" target="lib\net40" />
    <file src="bin\2012\Release\bin\System.Data.SQLite.dll" target="lib\net45" />
    <file src="bin\2008\Release\bin\System.Data.SQLite.Linq.dll" target="lib\net20" />
    <file src="bin\2010\Release\bin\System.Data.SQLite.Linq.dll" target="lib\net40" />
    <file src="bin\2012\Release\bin\System.Data.SQLite.Linq.dll" target="lib\net45" />
  </files>
</package>
Changes to SQLite.NET.Settings.targets.
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
16
17
18
19
20
21
22



























23
24
25
26
27
28
29







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







  <!--
      NOTE: If the per-user settings file exists, import it now.  The contained
            settings, if any, will override the default ones provided below.
  -->
  <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets.user"
          Condition="Exists('$(SQLiteNetDir)\SQLite.NET.Settings.targets.user')" />

  <!--
  ******************************************************************************
  **                        Load Per-Framework Settings                       **
  ******************************************************************************
  -->

  <!--
      NOTE: If the per-framework settings files exist, import them now.  The
            contained settings, if any, will override the default ones provided
            below.
  -->
  <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets.netFx20"
          Condition="'$(NetFx20)' != '' And '$(NetFx20)' != 'false' And
                     Exists('$(SQLiteNetDir)\SQLite.NET.Settings.targets.netFx20')" />

  <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets.netFx35"
          Condition="'$(NetFx35)' != '' And '$(NetFx35)' != 'false' And
                     Exists('$(SQLiteNetDir)\SQLite.NET.Settings.targets.netFx35')" />

  <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets.netFx40"
          Condition="'$(NetFx40)' != '' And '$(NetFx40)' != 'false' And
                     Exists('$(SQLiteNetDir)\SQLite.NET.Settings.targets.netFx40')" />

  <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets.netFx45"
          Condition="'$(NetFx45)' != '' And '$(NetFx45)' != 'false' And
                     Exists('$(SQLiteNetDir)\SQLite.NET.Settings.targets.netFx45')" />

  <!--
  ******************************************************************************
  **                       [Fairly] Generic Properties                        **
  ******************************************************************************
  -->

  <PropertyGroup>
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
110
111
112
113
114
115
116













117
118
119
120
121
122
123







-
-
-
-
-
-
-
-
-
-
-
-
-







    <!--
        NOTE: Enable extra internal state checking for the public members of
              several key classes that use a connection.  By default, this is
              disabled.
    -->
    <CheckState Condition="'$(CheckState)' == ''">false</CheckState>

    <!--
        NOTE: Enable counting of all object instances for the CriticalHandle
              derived classes?  By default, this is disabled.  If this is
              enabled, this library will keep count of all non-disposed object
              instances for all the CriticalHandle derived classes.  Each
              counter will be incremented when an instance of the associated
              critical handle class is constructed and decremented when the
              ReleaseHandle method is completed successfully on an instance.
              These counts are intended to be used by the test suite to detect
              possible resource leaks.
    -->
    <CountHandle Condition="'$(CountHandle)' == ''">false</CountHandle>

    <!--
        NOTE: For interaction with the native SQLite implementation, use the
              custom built interop DLL (i.e. "SQLite.Interop.dll")?  By default,
              this is enabled.  This property is mutually exclusive with the
              "UseSqliteStandard" one, below.  This should always be disabled in
              the project file that builds the NetModule target.
    -->
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
236
237
238
239
240
241
242

















243
244
245
246
247
248
249







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







                  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"
              preprocessor define being present in the "INTEROP_DEBUG_DEFINES"
              macro in the build properties file:

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

              for the corresponding version(s) of Visual Studio.
    -->
    <InteropLog Condition="'$(InteropLog)' == '' And '$(Configuration)' == 'Debug'">true</InteropLog>
    <InteropLog Condition="'$(InteropLog)' == '' And '$(Configuration)' != 'Debug'">false</InteropLog>

    <!--
        NOTE: Enable the use of native Windows APIs, when available?  By
              default, this is enabled.  If this is disabled, all features
              that require the use of native Windows APIs will be unavailable.
    -->
    <UseWindows Condition="'$(UseWindows)' == ''">true</UseWindows>
  </PropertyGroup>
Deleted SQLite.NET.Settings.targets.netFx35.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22






















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
<!--
 *
 * SQLite.NET.Settings.targets.netFx35 -
 *
 * Written by Joe Mistachkin.
 * Released to the public domain, use at your own risk!
 *
-->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup Condition="'$(ConfigurationYear)' != '' And
                            '$(ConfigurationYear)' != '2005' And
                            '$(ConfigurationYear)' != '2008'">
    <NetFx20>true</NetFx20>
    <NetFx35>true</NetFx35>
    <NetFx40>false</NetFx40>
    <NetFx45>false</NetFx45>
    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
    <TargetFrameworkProfile></TargetFrameworkProfile>
    <Prefer32Bit>false</Prefer32Bit>
    <PlatformToolset>v110</PlatformToolset>
  </PropertyGroup>
</Project>
Changes to SQLite.nuspec.
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
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













-
+












-


-




-
-



<?xml version="1.0" encoding="utf-8"?>
<!--
 *
 * SQLite.nuspec -
 *
 * Written by Joe Mistachkin.
 * Released to the public domain, use at your own risk!
 *
-->
<package>
  <metadata>
    <id>System.Data.SQLite</id>
    <title>System.Data.SQLite (x86/x64)</title>
    <version>1.0.84.0</version>
    <version>1.0.83.0</version>
    <authors>SQLite Development Team</authors>
    <description>The official SQLite database engine for both x86 and x64 along with the ADO.NET provider.</description>
    <language>en-US</language>
    <projectUrl>http://system.data.sqlite.org/</projectUrl>
    <iconUrl>http://system.data.sqlite.org/images/sqlite32.png</iconUrl>
    <licenseUrl>http://www.sqlite.org/copyright.html</licenseUrl>
    <tags>sqlite database ado.net provider interop</tags>
    <copyright>Public Domain</copyright>
  </metadata>
  <files>
    <file src="bin\2008\Release\bin\System.Data.SQLite.dll" target="lib\net20" />
    <file src="bin\2010\Release\bin\System.Data.SQLite.dll" target="lib\net40" />
    <file src="bin\2012\Release\bin\System.Data.SQLite.dll" target="lib\net45" />
    <file src="bin\2008\Release\bin\System.Data.SQLite.Linq.dll" target="lib\net20" />
    <file src="bin\2010\Release\bin\System.Data.SQLite.Linq.dll" target="lib\net40" />
    <file src="bin\2012\Release\bin\System.Data.SQLite.Linq.dll" target="lib\net45" />
    <file src="bin\2008\Win32\ReleaseNativeOnlyStatic\SQLite.Interop.dll" target="content\net20\x86" />
    <file src="bin\2008\x64\ReleaseNativeOnlyStatic\SQLite.Interop.dll" target="content\net20\x64" />
    <file src="bin\2010\Win32\ReleaseNativeOnlyStatic\SQLite.Interop.dll" target="content\net40\x86" />
    <file src="bin\2010\x64\ReleaseNativeOnlyStatic\SQLite.Interop.dll" target="content\net40\x64" />
    <file src="bin\2012\Win32\ReleaseNativeOnlyStatic\SQLite.Interop.dll" target="content\net45\x86" />
    <file src="bin\2012\x64\ReleaseNativeOnlyStatic\SQLite.Interop.dll" target="content\net45\x64" />
    <file src="install.ps1" target="tools\install.ps1" />
  </files>
</package>
Changes to SQLite.x64.nuspec.
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
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












-
+












-


-


<?xml version="1.0" encoding="utf-8"?>
<!--
 *
 * SQLite.x64.nuspec -
 *
 * Written by Joe Mistachkin.
 * Released to the public domain, use at your own risk!
 *
-->
<package>
  <metadata>
    <id>System.Data.SQLite.x64</id>
    <version>1.0.84.0</version>
    <version>1.0.83.0</version>
    <authors>SQLite Development Team</authors>
    <description>The official SQLite database engine combined with a complete ADO.NET provider all rolled into a single mixed-mode assembly for x64.</description>
    <language>en-US</language>
    <projectUrl>http://system.data.sqlite.org/</projectUrl>
    <iconUrl>http://system.data.sqlite.org/images/sqlite32.png</iconUrl>
    <licenseUrl>http://www.sqlite.org/copyright.html</licenseUrl>
    <tags>sqlite database ado.net provider interop</tags>
    <copyright>Public Domain</copyright>
  </metadata>
  <files>
    <file src="bin\2008\x64\ReleaseStatic\System.Data.SQLite.dll" target="lib\net20" />
    <file src="bin\2010\x64\ReleaseStatic\System.Data.SQLite.dll" target="lib\net40" />
    <file src="bin\2012\x64\ReleaseStatic\System.Data.SQLite.dll" target="lib\net45" />
    <file src="bin\2008\Release\bin\System.Data.SQLite.Linq.dll" target="lib\net20" />
    <file src="bin\2010\Release\bin\System.Data.SQLite.Linq.dll" target="lib\net40" />
    <file src="bin\2012\Release\bin\System.Data.SQLite.Linq.dll" target="lib\net45" />
  </files>
</package>
Changes to SQLite.x86.nuspec.
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
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












-
+












-


-


<?xml version="1.0" encoding="utf-8"?>
<!--
 *
 * SQLite.x86.nuspec -
 *
 * Written by Joe Mistachkin.
 * Released to the public domain, use at your own risk!
 *
-->
<package>
  <metadata>
    <id>System.Data.SQLite.x86</id>
    <version>1.0.84.0</version>
    <version>1.0.83.0</version>
    <authors>SQLite Development Team</authors>
    <description>The official SQLite database engine combined with a complete ADO.NET provider all rolled into a single mixed-mode assembly for x86.</description>
    <language>en-US</language>
    <projectUrl>http://system.data.sqlite.org/</projectUrl>
    <iconUrl>http://system.data.sqlite.org/images/sqlite32.png</iconUrl>
    <licenseUrl>http://www.sqlite.org/copyright.html</licenseUrl>
    <tags>sqlite database ado.net provider interop</tags>
    <copyright>Public Domain</copyright>
  </metadata>
  <files>
    <file src="bin\2008\Win32\ReleaseStatic\System.Data.SQLite.dll" target="lib\net20" />
    <file src="bin\2010\Win32\ReleaseStatic\System.Data.SQLite.dll" target="lib\net40" />
    <file src="bin\2012\Win32\ReleaseStatic\System.Data.SQLite.dll" target="lib\net45" />
    <file src="bin\2008\Release\bin\System.Data.SQLite.Linq.dll" target="lib\net20" />
    <file src="bin\2010\Release\bin\System.Data.SQLite.Linq.dll" target="lib\net40" />
    <file src="bin\2012\Release\bin\System.Data.SQLite.Linq.dll" target="lib\net45" />
  </files>
</package>
Changes to Setup/SQLite.iss.
79
80
81
82
83
84
85
86

87
88
89
90
91
92
93
79
80
81
82
83
84
85

86
87
88
89
90
91
92
93







-
+







#if Year == "2005"
Components: Application\Core\MSIL; Name: gac; Description: Install the assemblies into the global assembly cache.; Flags: unchecked; Check: CheckIsNetFx2Setup() or CheckIsNetFx4Setup()
#else
Components: Application\Core\MSIL Or Application\LINQ; Name: gac; Description: Install the assemblies into the global assembly cache.; Flags: unchecked; Check: CheckIsNetFx2Setup() or CheckIsNetFx4Setup()
#endif

#if AppProcessor == "x86"
#if Year == "2005"
#if Year == "2005" || Year == "2008"
Components: {#InstallerCondition}; Name: gac\vs2005; Description: Install the designer components for Visual Studio 2005.; Flags: unchecked; Check: CheckIsNetFx2Setup()
#endif
#if Year == "2008"
Components: {#InstallerCondition}; Name: gac\vs2008; Description: Install the designer components for Visual Studio 2008.; Flags: unchecked; Check: CheckIsNetFx2Setup()
#endif
#if Year == "2010"
Components: {#InstallerCondition}; Name: gac\vs2010; Description: Install the designer components for Visual Studio 2010.; Flags: unchecked; Check: CheckIsNetFx4Setup()
104
105
106
107
108
109
110
111

112
113
114
115
116
117
118
119
120
121
122

123
124
125
126
127
128
129

130
131
132
133
134
135
136
137
138

139
140
141
142
143
144
145
104
105
106
107
108
109
110

111
112
113
114
115
116
117
118
119
120
121

122
123
124
125
126
127
128

129
130
131
132
133
134
135
136
137

138
139
140
141
142
143
144
145







-
+










-
+






-
+








-
+








#if Year != "2005"
Components: Application\LINQ; Tasks: ngen; Filename: {code:GetNetFx2InstallRoot|Ngen.exe}; Parameters: "install ""{app}\bin\System.Data.SQLite.Linq.dll"" /nologo"; Flags: skipifdoesntexist; Check: CheckIsNetFx2Setup() and CheckForNetFx35(1)
Components: Application\LINQ; Tasks: ngen; Filename: {code:GetNetFx4InstallRoot|Ngen.exe}; Parameters: "install ""{app}\bin\System.Data.SQLite.Linq.dll"" /nologo"; Flags: skipifdoesntexist; Check: CheckIsNetFx4Setup()
#endif

#if Pos("NativeOnly", AppConfiguration) == 0 && AppProcessor == "x86"
#if Year == "2005"
#if Year == "2005" || Year == "2008"
Components: {#InstallerCondition}; Tasks: gac\vs2005; Filename: {app}\bin\Installer.exe; Parameters: "-install true -wow64 true -installFlags AllExceptGlobalAssemblyCache -tracePriority Lowest -verbose true -noCompact true -noNetFx35 true -noNetFx40 true -noNetFx45 true -noVs2008 true -noVs2010 true -noVs2012 true -whatIf false -confirm true"; Flags: skipifdoesntexist; Check: CheckIsNetFx2Setup()
#endif
#if Year == "2008"
Components: {#InstallerCondition}; Tasks: gac\vs2008; Filename: {app}\bin\Installer.exe; Parameters: "-install true -wow64 true -installFlags AllExceptGlobalAssemblyCache -tracePriority Lowest -verbose true -noCompact true -noNetFx40 true -noNetFx45 true -noVs2005 true -noVs2010 true -noVs2012 true -whatIf false -confirm true"; Flags: skipifdoesntexist; Check: CheckIsNetFx2Setup()
#endif
#if Year == "2010"
Components: {#InstallerCondition}; Tasks: gac\vs2010; Filename: {app}\bin\Installer.exe; Parameters: "-install true -wow64 true -installFlags AllExceptGlobalAssemblyCache -tracePriority Lowest -verbose true -noCompact true -noNetFx20 true -noNetFx45 true -noVs2005 true -noVs2008 true -noVs2012 true -whatIf false -confirm true"; Flags: skipifdoesntexist; Check: CheckIsNetFx4Setup()
#endif
#if Year == "2012"
Components: {#InstallerCondition}; Tasks: gac\vs2012; Filename: {app}\bin\Installer.exe; Parameters: "-install true -wow64 true -installFlags AllExceptGlobalAssemblyCache -tracePriority Lowest -verbose true -noCompact true -noNetFx20 true -noNetFx40 true -noVs2005 true -noVs2008 true -noVs2010 true -configVersion 4.0.30319 -whatIf false -confirm true"; Flags: skipifdoesntexist; Check: CheckIsNetFx4Setup()
Components: {#InstallerCondition}; Tasks: gac\vs2012; Filename: {app}\bin\Installer.exe; Parameters: "-perUser true -install true -wow64 true -installFlags AllExceptGlobalAssemblyCache -tracePriority Lowest -verbose true -noCompact true -noNetFx20 true -noNetFx40 true -noNetFx45 true -noVs2005 true -noVs2008 true -noVs2010 true -configVersion 4.0.30319 -vsVersionSuffix _Config -whatIf false -confirm true"; Flags: skipifdoesntexist; Check: CheckIsNetFx4Setup()
Components: {#InstallerCondition}; Tasks: gac\vs2012; Filename: {app}\bin\Installer.exe; Parameters: "-perUser true -install true -wow64 true -installFlags AllExceptGlobalAssemblyCache -tracePriority Lowest -verbose true -noCompact true -noNetFx20 true -noNetFx40 true -noVs2005 true -noVs2008 true -noVs2010 true -configVersion 4.0.30319 -vsVersionSuffix _Config -whatIf false -confirm true"; Flags: skipifdoesntexist; Check: CheckIsNetFx4Setup()
#endif
#endif

[UninstallRun]
#if Pos("NativeOnly", AppConfiguration) == 0 && AppProcessor == "x86"
#if Year == "2012"
Components: {#InstallerCondition}; Tasks: gac\vs2012; Filename: {app}\bin\Installer.exe; Parameters: "-perUser true -install false -wow64 true -installFlags AllExceptGlobalAssemblyCache -tracePriority Lowest -verbose true -noCompact true -noNetFx20 true -noNetFx40 true -noNetFx45 true -noVs2005 true -noVs2008 true -noVs2010 true -configVersion 4.0.30319 -vsVersionSuffix _Config -whatIf false -confirm true"; Flags: skipifdoesntexist; Check: CheckIsNetFx4Setup()
Components: {#InstallerCondition}; Tasks: gac\vs2012; Filename: {app}\bin\Installer.exe; Parameters: "-perUser true -install false -wow64 true -installFlags AllExceptGlobalAssemblyCache -tracePriority Lowest -verbose true -noCompact true -noNetFx20 true -noNetFx40 true -noVs2005 true -noVs2008 true -noVs2010 true -configVersion 4.0.30319 -vsVersionSuffix _Config -whatIf false -confirm true"; Flags: skipifdoesntexist; Check: CheckIsNetFx4Setup()
Components: {#InstallerCondition}; Tasks: gac\vs2012; Filename: {app}\bin\Installer.exe; Parameters: "-install false -wow64 true -installFlags AllExceptGlobalAssemblyCache -tracePriority Lowest -verbose true -noCompact true -noNetFx20 true -noNetFx40 true -noVs2005 true -noVs2008 true -noVs2010 true -configVersion 4.0.30319 -whatIf false -confirm true"; Flags: skipifdoesntexist; Check: CheckIsNetFx4Setup()
#endif
#if Year == "2010"
Components: {#InstallerCondition}; Tasks: gac\vs2010; Filename: {app}\bin\Installer.exe; Parameters: "-install false -wow64 true -installFlags AllExceptGlobalAssemblyCache -tracePriority Lowest -verbose true -noCompact true -noNetFx20 true -noNetFx45 true -noVs2005 true -noVs2008 true -noVs2012 true -whatIf false -confirm true"; Flags: skipifdoesntexist; Check: CheckIsNetFx4Setup()
#endif
#if Year == "2008"
Components: {#InstallerCondition}; Tasks: gac\vs2008; Filename: {app}\bin\Installer.exe; Parameters: "-install false -wow64 true -installFlags AllExceptGlobalAssemblyCache -tracePriority Lowest -verbose true -noCompact true -noNetFx40 true -noNetFx45 true -noVs2005 true -noVs2010 true -noVs2012 true -whatIf false -confirm true"; Flags: skipifdoesntexist; Check: CheckIsNetFx2Setup()
#endif
#if Year == "2005"
#if Year == "2005" || Year == "2008"
Components: {#InstallerCondition}; Tasks: gac\vs2005; Filename: {app}\bin\Installer.exe; Parameters: "-install false -wow64 true -installFlags AllExceptGlobalAssemblyCache -tracePriority Lowest -verbose true -noCompact true -noNetFx35 true -noNetFx40 true -noNetFx45 true -noVs2008 true -noVs2010 true -noVs2012 true -whatIf false -confirm true"; Flags: skipifdoesntexist; Check: CheckIsNetFx2Setup()
#endif
#endif

#if Year != "2005"
Components: Application\LINQ; Tasks: ngen; Filename: {code:GetNetFx4InstallRoot|Ngen.exe}; Parameters: "uninstall ""{app}\bin\System.Data.SQLite.Linq.dll"" /nologo"; Flags: skipifdoesntexist; Check: CheckIsNetFx4Setup()
Components: Application\LINQ; Tasks: ngen; Filename: {code:GetNetFx2InstallRoot|Ngen.exe}; Parameters: "uninstall ""{app}\bin\System.Data.SQLite.Linq.dll"" /nologo"; Flags: skipifdoesntexist; Check: CheckIsNetFx2Setup() and CheckForNetFx35(1)
Changes to Setup/build_ce.bat.
26
27
28
29
30
31
32
33

34
35
36
37
38
39
40
26
27
28
29
30
31
32

33
34
35
36
37
38
39
40







-
+







)

SET TOOLS=%~dp0
SET TOOLS=%TOOLS:~0,-1%

%_VECHO% Tools = '%TOOLS%'

SET BUILD_CONFIGURATIONS=Debug Release
SET BUILD_CONFIGURATIONS=Release
SET BASE_CONFIGURATIONSUFFIX=Compact
SET PLATFORMS="Pocket PC 2003 (ARMV4)"
SET PROCESSORS=arm
SET YEARS=2008
SET BASE_PLATFORM=PocketPC

CALL :fn_ResetErrorLevel
Changes to Setup/set_common.bat.
16
17
18
19
20
21
22
23

24
25
26
27

28
29
30
31
32
33
34
16
17
18
19
20
21
22

23
24
25
26

27
28
29
30
31
32
33
34







-
+



-
+







)

IF NOT DEFINED PUBLICKEY (
  SET PUBLICKEY=db937bc2d44ff139
)

IF NOT DEFINED BUILD_CONFIGURATIONS (
  SET BUILD_CONFIGURATIONS=Debug DebugNativeOnly Release ReleaseNativeOnly
  SET BUILD_CONFIGURATIONS=Release ReleaseNativeOnly
)

IF NOT DEFINED TEST_CONFIGURATIONS (
  SET TEST_CONFIGURATIONS=Debug Release
  SET TEST_CONFIGURATIONS=Release
)

IF NOT DEFINED BAKE_CONFIGURATIONS (
  SET BAKE_CONFIGURATIONS=Release ReleaseNativeOnly
)

IF NOT DEFINED RELEASE_CONFIGURATIONS (
Changes to Setup/set_user_mistachkin_Debug.bat.
9
10
11
12
13
14
15
16
17
18
19
9
10
11
12
13
14
15

16
17
18







-



:: Released to the public domain, use at your own risk!
::

REM
REM NOTE: Enables the extra debug code helpful in troubleshooting issues.
REM
SET MSBUILD_ARGS=/p:CheckState=true
SET MSBUILD_ARGS=%MSBUILD_ARGS% /p:CountHandle=true
SET MSBUILD_ARGS=%MSBUILD_ARGS% /p:TraceConnection=true
SET MSBUILD_ARGS=%MSBUILD_ARGS% /p:TraceHandle=true
SET MSBUILD_ARGS=%MSBUILD_ARGS% /p:TraceStatement=true
Changes to Setup/test_all.bat.
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
96
97
98
99
100
101
102






103
104
105
106
107
108
109







-
-
-
-
-
-







%__ECHO2% PUSHD "%ROOT%"

IF ERRORLEVEL 1 (
  ECHO Could not change directory to "%ROOT%".
  GOTO errors
)

REM
REM NOTE: Set an environment variable that can be used by the test suite to
REM       determine that testing is being performed in batch mode.
REM
SET TEST_ALL=1

FOR %%C IN (%TEST_CONFIGURATIONS%) DO (
  FOR %%Y IN (%YEARS%) DO (
    IF NOT DEFINED NOMANAGEDONLY (
      %__ECHO% Externals\Eagle\bin\EagleShell.exe -preInitialize "set test_year {%%Y}; set test_configuration {%%C}" -file "%TEST_FILE%"

      IF ERRORLEVEL 1 (
        ECHO Testing of "%%Y/%%C" managed-only assembly failed.
Changes to Setup/verify.lst.
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
78
79
80
81
82
83
84

85
86
87
88
89
90
91







-







  Setup/bake.bat
  Setup/bake_all.bat
  Setup/build.bat
  Setup/build_all.bat
  Setup/build_ce.bat
  Setup/CheckForNetFx.pas
  Setup/clean.bat
  Setup/deployAndTestCe.eagle
  Setup/InitializeSetup.pas
  Setup/release.bat
  Setup/release_all.bat
  Setup/release_ce.bat
  Setup/release_static.bat
  Setup/set_2005.bat
  Setup/set_2008.bat
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
126
127
128
129
130
131
132

133
134
135
136
137
138
139







-







  Setup/set_x64_2012.bat
  Setup/set_x86_2005.bat
  Setup/set_x86_2008.bat
  Setup/set_x86_2010.bat
  Setup/set_x86_2012.bat
  Setup/SQLite.iss
  Setup/test_all.bat
  Setup/test_ce.bat
  Setup/updateFileInfo.tcl
  Setup/verify.eagle
  Setup/verify.lst
  Setup/vsSp.bat
  SQLite.Designer/
  SQLite.Designer/AssemblyInfo.cs
  SQLite.Designer/ChangePasswordDialog.cs
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
233
234
235
236
237
238
239

240
241
242
243
244
245
246
247
248
249

250
251
252
253
254
255
256







-










-







  SQLite.Interop/src/core/sqlite3ext.h
  SQLite.Interop/src/win/
  SQLite.Interop/src/win/AssemblyInfo.cpp
  SQLite.Interop/src/win/crypt.c
  SQLite.Interop/src/win/interop.c
  SQLite.Interop/src/win/interop.h
  SQLite.Interop/src/win/SQLite.Interop.rc
  SQLite.Beta.nuspec
  SQLite.MSIL.nuspec
  SQLite.NET.2005.MSBuild.sln
  SQLite.NET.2005.sln
  SQLite.NET.2008.MSBuild.sln
  SQLite.NET.2008.sln
  SQLite.NET.2010.MSBuild.sln
  SQLite.NET.2010.sln
  SQLite.NET.2012.MSBuild.sln
  SQLite.NET.2012.sln
  SQLite.NET.Settings.targets
  SQLite.NET.Settings.targets.netFx35
  SQLite.NET.targets
  SQLite.nuspec
  SQLite.x64.nuspec
  SQLite.x86.nuspec
  System.Data.SQLite/
  System.Data.SQLite/AssemblyInfo.cs
  System.Data.SQLite/DataTypes.xml
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
390
391
392
393
394
395
396

397
398
399
400
401
402
403
404
405

406
407
408
409
410
411
412
413
414
415
416


417
418
419
420
421
422
423
424

425
426
427
428
429
430
431







-









-











-
-








-







  testlinq/testlinq.2010.csproj
  testlinq/testlinq.2012.csproj
  Tests/
  Tests/all.eagle
  Tests/backup.eagle
  Tests/basic.eagle
  Tests/common.eagle
  Tests/empty.eagle
  Tests/installer.eagle
  Tests/Installer_Test_Vs2005.log
  Tests/Installer_Test_Vs2008.log
  Tests/Installer_Test_Vs2010.log
  Tests/Installer_Test_Vs2012.log
  Tests/nonWal.db
  Tests/pkgIndex.eagle
  Tests/stress.eagle
  Tests/testlinq.out
  Tests/thread.eagle
  Tests/tkt-00f86f9739.eagle
  Tests/tkt-0d5b1ef362.eagle
  Tests/tkt-17045010df.eagle
  Tests/tkt-201128cc88.eagle
  Tests/tkt-2c630bffa7.eagle
  Tests/tkt-2ce0870fad.eagle
  Tests/tkt-343d392b51.eagle
  Tests/tkt-3aa50d8413.eagle
  Tests/tkt-448d663d11.eagle
  Tests/tkt-544dba0a2f.eagle
  Tests/tkt-59edc1018b.eagle
  Tests/tkt-6434e23a0f.eagle
  Tests/tkt-6c6ecccc5f.eagle
  Tests/tkt-72905c9a77.eagle
  Tests/tkt-7e3fa93744.eagle
  Tests/tkt-84718e79fa.eagle
  Tests/tkt-8554170e09.eagle
  Tests/tkt-8b7d179c3c.eagle
  Tests/tkt-8c3bee31c8.eagle
  Tests/tkt-996d13cd87.eagle
  Tests/tkt-ac47dd230a.eagle
  Tests/tkt-ae5267b863.eagle
  Tests/tkt-b4a7ddc83f.eagle
  Tests/tkt-bb4b04d457.eagle
  Tests/tkt-ccfa69fc32.eagle
  Tests/tkt-e1b2e0f769.eagle
  Tests/tkt-e30b820248.eagle
  Tests/Uninstaller_Test_Vs2005.log
  Tests/Uninstaller_Test_Vs2008.log
Changes to System.Data.SQLite.Linq/AssemblyInfo.cs.
40
41
42
43
44
45
46
47
48


40
41
42
43
44
45
46


47
48







-
-
+
+
//      Minor Version 
//      Build Number
//      Revision
//
// You can specify all the values or you can default the Build and Revision Numbers 
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.84.0")]
[assembly: AssemblyFileVersion("1.0.84.0")]
[assembly: AssemblyVersion("1.0.83.0")]
[assembly: AssemblyFileVersion("1.0.83.0")]
Changes to System.Data.SQLite.Linq/SQLiteProviderServices.cs.
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112

113
114
115
116
117
118
119
120
98
99
100
101
102
103
104








105

106
107
108
109
110
111
112







-
-
-
-
-
-
-
-
+
-







    }

    protected override string GetDbProviderManifestToken(DbConnection connection)
    {
      if (String.IsNullOrEmpty(connection.ConnectionString))
        throw new ArgumentNullException("ConnectionString");

      bool parseViaFramework = false;

      if (connection is SQLiteConnection)
          parseViaFramework = ((SQLiteConnection)connection).ParseViaFramework;

      SortedList<string, string> opts = parseViaFramework ?
          SQLiteConnection.ParseConnectionStringViaFramework(connection.ConnectionString, false) :
          SQLiteConnection.ParseConnectionString(connection.ConnectionString);
      SortedList<string, string> opts = SQLiteConnection.ParseConnectionString(connection.ConnectionString);

      return SQLiteConnection.FindKey(opts, "DateTimeFormat", "ISO8601");
    }

    protected override DbProviderManifest GetDbProviderManifest(string versionHint)
    {
      return new SQLiteProviderManifest(versionHint);
    }
Changes to System.Data.SQLite/AssemblyInfo.cs.
60
61
62
63
64
65
66
67

68
69

70
60
61
62
63
64
65
66

67
68

69
70







-
+

-
+

//      Major Version
//      Minor Version 
//      Build Number
//      Revision
//
// You can specify all the values or you can default the Revision and Build Numbers 
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.84.0")]
[assembly: AssemblyVersion("1.0.83.0")]
#if !PLATFORM_COMPACTFRAMEWORK
[assembly: AssemblyFileVersion("1.0.84.0")]
[assembly: AssemblyFileVersion("1.0.83.0")]
#endif
Changes to System.Data.SQLite/LINQ/SQLiteFactory_Linq.cs.
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
24
25
26
27
28
29
30






31
32
33
34
35
36
37







-
-
-
-
-
-







    {
#if (SQLITE_STANDARD || USE_INTEROP_DLL || PLATFORM_COMPACTFRAMEWORK) && PRELOAD_NATIVE_LIBRARY
        UnsafeNativeMethods.Initialize();
#endif

#if !PLATFORM_COMPACTFRAMEWORK
        SQLiteLog.Initialize();
#elif INTEROP_LOG
        if (UnsafeNativeMethods.sqlite3_config_log_interop() == SQLiteErrorCode.Ok)
        {
            UnsafeNativeMethods.sqlite3_log(
                SQLiteErrorCode.Ok, SQLiteConvert.ToUTF8("logging initialized."));
        }
#endif

        string version =
#if NET_40 || NET_45
            "4.0.0.0";
#else
            "3.5.0.0";
Changes to System.Data.SQLite/SQLite3.cs.
53
54
55
56
57
58
59
60

61
62
63
64
65
66
67
53
54
55
56
57
58
59

60
61
62
63
64
65
66
67







-
+







    internal const string PublicKey =
        "002400000480000094000000060200000024000052534131000400000100010005a288de5687c4e1" +
        "b621ddff5d844727418956997f475eb829429e411aff3e93f97b70de698b972640925bdd44280df0" +
        "a25a843266973704137cbb0e7441c1fe7cae4e2440ae91ab8cde3933febcb1ac48dd33b40e13c421" +
        "d8215c18a4349a436dd499e3c385cc683015f886f6c10bd90115eb2bd61b67750839e3a19941dc9c";

#if !PLATFORM_COMPACTFRAMEWORK
    internal const string DesignerVersion = "1.0.84.0";
    internal const string DesignerVersion = "1.0.83.0";
#endif

    /// <summary>
    /// The opaque pointer returned to us by the sqlite provider
    /// </summary>
    protected internal SQLiteConnectionHandle _sql;
    protected string _fileName;
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
171
172
173
174
175
176
177








178
179
180
181
182
183
184







-
-
-
-
-
-
-
-







    {
      get
      {
        return SQLite3.SQLiteVersion;
      }
    }

    internal override int VersionNumber
    {
      get
      {
        return SQLite3.SQLiteVersionNumber;
      }
    }

    internal static string DefineConstants
    {
        get
        {
            StringBuilder result = new StringBuilder();
            IList<string> list = SQLiteDefineConstants.OptionList;

212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
204
205
206
207
208
209
210








211
212
213
214
215
216
217







-
-
-
-
-
-
-
-







    {
      get
      {
        return UTF8ToString(UnsafeNativeMethods.sqlite3_libversion(), -1);
      }
    }

    internal static int SQLiteVersionNumber
    {
      get
      {
        return UnsafeNativeMethods.sqlite3_libversion_number();
      }
    }

    internal static string SQLiteSourceId
    {
      get
      {
        return UTF8ToString(UnsafeNativeMethods.sqlite3_sourceid(), -1);
      }
    }
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1787
1788
1789
1790
1791
1792
1793




1794
1795
1796
1797
1798
1799
1800







-
-
-
-







        if (handlePtr == IntPtr.Zero)
            throw new InvalidOperationException(
                "Backup object has an invalid handle pointer.");

        SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_backup_finish(handlePtr);
        handle.SetHandleAsInvalid();

#if COUNT_HANDLE
        if (n == SQLiteErrorCode.Ok) handle.WasReleasedOk();
#endif

        if ((n != SQLiteErrorCode.Ok) && (n != backup._stepResult))
            throw new SQLiteException(n, GetLastError());
    }

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

    /// <summary>
Changes to System.Data.SQLite/SQLiteBase.cs.
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
23
24
25
26
27
28
29




30
31
32
33
34
35
36







-
-
-
-







      : base(fmt, kind) { }

    /// <summary>
    /// Returns a string representing the active version of SQLite
    /// </summary>
    internal abstract string Version { get; }
    /// <summary>
    /// Returns an integer representing the active version of SQLite
    /// </summary>
    internal abstract int VersionNumber { get; }
    /// <summary>
    /// Returns the rowid of the most recent successful INSERT into the database from this connection.
    /// </summary>
    internal abstract long LastInsertRowId { get; }
    /// <summary>
    /// Returns the number of changes the last executing insert/update caused.
    /// </summary>
    internal abstract int Changes { get; }
577
578
579
580
581
582
583
584

585
586

587
588
589

590
591
592
593
594
595
596
597
598


599
600


601
602
603
604
605
606
607
608


609
610

611
612
613

614
615
616
617
618
619
620
621
573
574
575
576
577
578
579

580
581

582



583









584
585


586
587








588
589


590



591

592
593
594
595
596
597
598







-
+

-
+
-
-
-
+
-
-
-
-
-
-
-
-
-
+
+
-
-
+
+
-
-
-
-
-
-
-
-
+
+
-
-
+
-
-
-
+
-







#else
            lock (hdl)
#endif
            {
#if !SQLITE_STANDARD
                SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_close_interop(db);
#else
                ResetConnection(hdl, db, false);
                ResetConnection(hdl, db);

                SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_close(db);
                SQLiteErrorCode n;
#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
        {
                try
                {
            // do nothing.
        }
                    n = UnsafeNativeMethods.sqlite3_close_v2(db);
                }
        finally /* NOTE: Thread.Abort() protection. */
        {
#if PLATFORM_COMPACTFRAMEWORK
            lock (hdl.syncRoot)
#else
            lock (hdl)
#endif
            {
                catch (EntryPointNotFoundException)
                {
#if !SQLITE_STANDARD
                SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_close_interop(db);
                    n = UnsafeNativeMethods.sqlite3_close(db);
#else
                ResetConnection(hdl, db, false);

                }
                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)
Changes to System.Data.SQLite/SQLiteConnection.cs.
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
330
331
332
333
334
335
336







337
338
339
340
341
342
343







-
-
-
-
-
-
-







    /// </summary>
    private static object _syncRoot = new object();

    /// <summary>
    /// Static variable to store the connection event handlers to call.
    /// </summary>
    private static event SQLiteConnectionEventHandler _handlers;

#if SQLITE_STANDARD && !PLATFORM_COMPACTFRAMEWORK
    /// <summary>
    /// Used to hold the active library version number of SQLite.
    /// </summary>
    private static int _versionNumber;
#endif
    #endregion

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

    #region Private Data
    /// <summary>
    /// State of the current connection
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
398
399
400
401
402
403
404






405
406
407
408
409
410
411







-
-
-
-
-
-







    private SQLiteConnectionFlags _flags;

    /// <summary>
    /// Default command timeout
    /// </summary>
    private int _defaultTimeout = 30;

    /// <summary>
    /// Non-zero if the built-in (i.e. framework provided) connection string
    /// parser should be used when opening the connection.
    /// </summary>
    private bool _parseViaFramework;

    internal bool _binaryGuid;

    internal long _version;

    private event SQLiteUpdateEventHandler _updateHandler;
    private event SQLiteCommitHandler _commitHandler;
    private event SQLiteTraceEventHandler _traceHandler;
447
448
449
450
451
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
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507

508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528

529
530
531
532
533
534
535
434
435
436
437
438
439
440

441
442

443
444

445















446
447
448
449
450
451























452



453






454
455
456
457
458
459
460
461
462
463
464
465
466
467

468
469
470
471
472
473
474
475







-
+

-
+

-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-






-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
+
-
-
-
-
-
-














-
+







    /// </summary>
    public SQLiteConnection()
      : this("")
    {
    }

    /// <summary>
    /// Initializes the connection with the specified connection string.
    /// Initializes the connection with the specified connection string
    /// </summary>
    /// <param name="connectionString">The connection string to use.</param>
    /// <param name="connectionString">The connection string to use on the connection</param>
    public SQLiteConnection(string connectionString)
        : this(connectionString, false)
    {
        // do nothing.
    }

    /// <summary>
    /// Initializes the connection with the specified connection string.
    /// </summary>
    /// <param name="connectionString">
    /// The connection string to use on.
    /// </param>
    /// <param name="parseViaFramework">
    /// Non-zero to parse the connection string using the built-in (i.e.
    /// framework provided) parser when opening the connection.
    /// </param>
    public SQLiteConnection(string connectionString, bool parseViaFramework)
    {
#if (SQLITE_STANDARD || USE_INTEROP_DLL || PLATFORM_COMPACTFRAMEWORK) && PRELOAD_NATIVE_LIBRARY
      UnsafeNativeMethods.Initialize();
#endif

#if !PLATFORM_COMPACTFRAMEWORK
      SQLiteLog.Initialize();

#if 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
      //       never actually called (i.e. because the runtime eagerly prepares
      //       all the methods in the call graph of the constrained execution
      //       region).
      //
      lock (_syncRoot)
      {
          if (_versionNumber == 0)
          {
              _versionNumber = SQLite3.SQLiteVersionNumber;

              if (_versionNumber >= 3007014)
                  SQLiteConnectionHandle.closeConnection = SQLiteBase.CloseConnectionV2;
          }
      }
#endif
#elif INTEROP_LOG
      if (UnsafeNativeMethods.sqlite3_config_log_interop() == SQLiteErrorCode.Ok)
      {

          UnsafeNativeMethods.sqlite3_log(
              SQLiteErrorCode.Ok, SQLiteConvert.ToUTF8("logging initialized."));
      }
#endif

      _parseViaFramework = parseViaFramework;
      _flags = SQLiteConnectionFlags.Default;
      _connectionState = ConnectionState.Closed;
      _connectionString = "";
      //_commandList = new List<WeakReference>();

      if (connectionString != null)
        ConnectionString = connectionString;
    }

    /// <summary>
    /// Clones the settings and connection string from an existing connection.  If the existing connection is already open, this
    /// function will open its own connection, enumerate any attached databases of the original connection, and automatically
    /// attach to them.
    /// </summary>
    /// <param name="connection">The connection to copy the settings from.</param>
    /// <param name="connection"></param>
    public SQLiteConnection(SQLiteConnection connection)
      : this(connection.ConnectionString)
    {
      string str;

      if (connection.State == ConnectionState.Open)
      {
1320
1321
1322
1323
1324
1325
1326
1327

1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340

1341
1342
1343
1344
1345
1346
1347
1348
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
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
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







-
+
-











-
+





-
-
-
-
-
-
-
-



-
+

-
+




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







      else if (path.StartsWith ("/", StringComparison.OrdinalIgnoreCase))
            return path;
      else
            throw new InvalidOperationException ("Invalid connection string: invalid URI");
    }

    /// <summary>
    /// Parses the connection string into component parts using the custom
    /// Parses the connection string into component parts
    /// connection string parser.
    /// </summary>
    /// <param name="connectionString">The connection string to parse</param>
    /// <returns>An array of key-value pairs representing each parameter of the connection string</returns>
    internal static SortedList<string, string> ParseConnectionString(string connectionString)
    {
      string s = connectionString;
      int n;
      SortedList<string, string> ls = new SortedList<string, string>(StringComparer.OrdinalIgnoreCase);

      // First split into semi-colon delimited values.  The Split() function of SQLiteBase accounts for and properly
      // skips semi-colons in quoted strings
      string[] arParts = s.Split(';');
      string[] arParts = SQLiteConvert.Split(s, ';');

      int x = arParts.Length;
      // For each semi-colon piece, split into key and value pairs by the presence of the = sign
      for (n = 0; n < x; n++)
      {
        if (arParts[n] == null)
          continue;

        arParts[n] = arParts[n].Trim();

        if (arParts[n].Length == 0)
          continue;

        int indexOf = arParts[n].IndexOf('=');

        if (indexOf != -1)
          ls.Add(UnwrapString(arParts[n].Substring(0, indexOf).Trim()), UnwrapString(arParts[n].Substring(indexOf + 1).Trim()));
          ls.Add(arParts[n].Substring(0, indexOf), arParts[n].Substring(indexOf + 1));
        else
          throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, "Invalid ConnectionString format for part \"{0}\", no equal sign found", arParts[n]));
          throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, "Invalid ConnectionString format for part \"{0}\"", arParts[n]));
      }
      return ls;
    }

    /// <summary>
    /// Parses a connection string using the built-in (i.e. framework provided)
    /// connection string parser class and returns the key/value pairs.  An
    /// exception may be thrown if the connection string is invalid or cannot be
    /// parsed.  When compiled for the .NET Compact Framework, the custom
    /// connection string parser is always used instead because the framework
    /// provided one is unavailable there.
    /// </summary>
    /// <param name="connectionString">
    /// The connection string to parse.
    /// </param>
    /// <param name="strict">
    /// Non-zero to throw an exception if any connection string values are not of
    /// the <see cref="String" /> type.
    /// </param>
    /// <returns>The list of key/value pairs.</returns>
    internal static SortedList<string, string> ParseConnectionStringViaFramework(
        string connectionString,
        bool strict
        )
    {
#if !PLATFORM_COMPACTFRAMEWORK
        DbConnectionStringBuilder connectionStringBuilder
            = new DbConnectionStringBuilder();

        connectionStringBuilder.ConnectionString = connectionString; /* throw */

        SortedList<string, string> result =
            new SortedList<string, string>(StringComparer.OrdinalIgnoreCase);

        foreach (string keyName in connectionStringBuilder.Keys)
        {
            object value = connectionStringBuilder[keyName];
            string keyValue = null;

            if (value is string)
            {
                keyValue = (string)value;
            }
            else if (strict)
            {
                throw new ArgumentException(
                    "connection property value is not a string",
                    keyName);
            }
            else if (value != null)
            {
                keyValue = value.ToString();
            }

            result.Add(keyName, keyValue);
        }

        return result;
#else
        //
        // NOTE: On the .NET Compact Framework, always use our custom connection
        //       string parser as the built-in (i.e. framework provided) one is
        //       unavailable.
        //
        return ParseConnectionString(connectionString);
#endif
    }

#if !PLATFORM_COMPACTFRAMEWORK
    /// <summary>
    /// Manual distributed transaction enlistment support
    /// </summary>
    /// <param name="transaction">The distributed transaction to enlist in</param>
    public override void EnlistTransaction(System.Transactions.Transaction transaction)
    {
1562
1563
1564
1565
1566
1567
1568
1569

1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587

1588
1589
1590
1591
1592
1593
1594
1429
1430
1431
1432
1433
1434
1435

1436





1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457







-
+
-
-
-
-
-













+







          SQLiteConnectionEventType.Opening, null, null, null, null, null));

      if (_connectionState != ConnectionState.Closed)
        throw new InvalidOperationException();

      Close();

      SortedList<string, string> opts = _parseViaFramework ?
      SortedList<string, string> opts = ParseConnectionString(_connectionString);
          ParseConnectionStringViaFramework(_connectionString, false) :
          ParseConnectionString(_connectionString);

      OnChanged(this, new ConnectionEventArgs(
          SQLiteConnectionEventType.ConnectionString, null, null, null, _connectionString, opts));

      object enumValue;

      enumValue = TryParseEnum(typeof(SQLiteConnectionFlags), FindKey(opts, "Flags", DefaultFlags.ToString()), true);
      _flags = (enumValue is SQLiteConnectionFlags) ? (SQLiteConnectionFlags)enumValue : DefaultFlags;

      bool fullUri = false;
      string fileName;

      if (Convert.ToInt32(FindKey(opts, "Version", DefaultVersion.ToString()), CultureInfo.InvariantCulture) != DefaultVersion)
        throw new NotSupportedException(String.Format(CultureInfo.CurrentCulture, "Only SQLite Version {0} is supported at this time", DefaultVersion));

      fileName = FindKey(opts, "Data Source", DefaultDataSource);
      fileName = UnwrapFileName(fileName);

      if (String.IsNullOrEmpty(fileName))
      {
        fileName = FindKey(opts, "Uri", DefaultUri);
        if (String.IsNullOrEmpty(fileName))
        {
          fileName = FindKey(opts, "FullUri", DefaultFullUri);
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1700
1701
1702
1703
1704
1705
1706










1707
1708
1709
1710
1711
1712
1713







-
-
-
-
-
-
-
-
-
-







    /// </summary>
    public int DefaultTimeout
    {
      get { CheckDisposed(); return _defaultTimeout; }
      set { CheckDisposed(); _defaultTimeout = value; }
    }

    /// <summary>
    /// Non-zero if the built-in (i.e. framework provided) connection string
    /// parser should be used when opening the connection.
    /// </summary>
    public bool ParseViaFramework
    {
        get { CheckDisposed(); return _parseViaFramework; }
        set { CheckDisposed(); _parseViaFramework = value; }
    }

    /// <summary>
    /// Gets/sets the extra behavioral flags for this connection.  See the
    /// <see cref="SQLiteConnectionFlags" /> enumeration for a list of
    /// possible values.
    /// </summary>
    public SQLiteConnectionFlags Flags
    {
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1749
1750
1751
1752
1753
1754
1755



















1756
1757
1758
1759
1760
1761
1762







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







        if (_sql == null)
          throw new InvalidOperationException("Database connection not valid for getting last insert rowid.");

        return _sql.LastInsertRowId;
      }
    }

    /// <summary>
    /// This method causes any pending database operation to abort and return at
    /// its earliest opportunity.  This routine is typically called in response
    /// to a user action such as pressing "Cancel" or Ctrl-C where the user wants
    /// a long query operation to halt immediately.  It is safe to call this
    /// routine from any thread.  However, it is not safe to call this routine
    /// with a database connection that is closed or might close before this method
    /// returns.
    /// </summary>
    public void Cancel()
    {
        CheckDisposed();

        if (_sql == null)
            throw new InvalidOperationException("Database connection not valid for query cancellation.");

        _sql.Cancel(); /* throw */
    }

    /// <summary>
    /// Returns the number of rows changed by the last INSERT, UPDATE, or DELETE statement executed on
    /// this connection.
    /// </summary>
#if !PLATFORM_COMPACTFRAMEWORK
    [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
#endif
2036
2037
2038
2039
2040
2041
2042
2043

2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
1870
1871
1872
1873
1874
1875
1876

1877



1878
1879
1880
1881
1882
1883
1884







-
+
-
-
-







    public SQLiteErrorCode Shutdown()
    {
        CheckDisposed();

        // make sure we have an instance of the base class
        if (_sql == null)
        {
            SortedList<string, string> opts = _parseViaFramework ?
            SortedList<string, string> opts = ParseConnectionString(_connectionString);
                ParseConnectionStringViaFramework(_connectionString, false) :
                ParseConnectionString(_connectionString);

            object enumValue;

            enumValue = TryParseEnum(typeof(SQLiteDateFormats), FindKey(opts,
                "DateTimeFormat", DefaultDateTimeFormat.ToString()), true);

            SQLiteDateFormats dateFormat = (enumValue is SQLiteDateFormats) ?
                (SQLiteDateFormats)enumValue : DefaultDateTimeFormat;
2232
2233
2234
2235
2236
2237
2238
2239
2240


2241
2242

2243
2244
2245


2246
2247
2248
2249

2250
2251

2252
2253
2254
2255
2256

2257
2258
2259

2260
2261
2262


2263
2264
2265
2266
2267

2268
2269
2270
2271
2272
2273

2274
2275
2276
2277
2278
2279
2280
2063
2064
2065
2066
2067
2068
2069


2070
2071
2072

2073
2074


2075
2076




2077
2078

2079
2080
2081
2082
2083

2084
2085
2086

2087
2088


2089
2090
2091
2092
2093
2094

2095
2096
2097
2098
2099
2100

2101
2102
2103
2104
2105
2106
2107
2108







-
-
+
+

-
+

-
-
+
+
-
-
-
-
+

-
+




-
+


-
+

-
-
+
+




-
+





-
+







                Marshal.FreeHGlobal(pArg);
        }

        return rc;
    }

    /// <summary>
    /// Removes one set of surrounding single -OR- double quotes from the string
    /// value and returns the resulting string value.  If the string is null, empty,
    /// Removes one set of surrounding single -OR- double quotes from the file
    /// name and returns the resulting file name.  If the string is null, empty,
    /// or contains quotes that are not balanced, nothing is done and the original
    /// string value will be returned.
    /// string will be returned.
    /// </summary>
    /// <param name="value">The string value to process.</param>
    /// <returns>
    /// <param name="sourceFile">The database file name to process.</param>
    /// <returns>The modified database file name.</returns>
    /// The string value, modified to remove one set of surrounding single -OR-
    /// double quotes, if applicable.
    /// </returns>
    private static string UnwrapString(string value)
    private string UnwrapFileName(string sourceFile)
    {
        if (String.IsNullOrEmpty(value))
        if (String.IsNullOrEmpty(sourceFile))
        {
            //
            // NOTE: The string is null or empty, return it verbatim.
            //
            return value;
            return sourceFile;
        }

        int length = value.Length;
        int length = sourceFile.Length;

        if (((value[0] == '\'') && (value[length - 1] == '\'')) ||
            ((value[0] == '"') && (value[length - 1] == '"')))
        if (((sourceFile[0] == '\'') && (sourceFile[length - 1] == '\'')) ||
            ((sourceFile[0] == '"') && (sourceFile[length - 1] == '"')))
        {
            //
            // NOTE: Remove the first and last character.
            //
            return value.Substring(1, length - 2);
            return sourceFile.Substring(1, length - 2);
        }

        //
        // NOTE: No match, return the input string verbatim.
        //
        return value;
        return sourceFile;
    }

    /// <summary>
    /// Expand the filename of the data source, resolving the |DataDirectory|
    /// macro as appropriate.
    /// </summary>
    /// <param name="sourceFile">The database filename to expand</param>
Changes to System.Data.SQLite/SQLiteConvert.cs.
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020

1021
1022
1023
1024
1025
1026

1027
1028
1029
1030
1031

1032
1033
1034
1035
1036

1037
1038
1039
1040
1041

1042
1043
1044
1045
1046

1047
1048
1049
1050
1051

1052
1053
1054
1055
1056
1057
1058
1005
1006
1007
1008
1009
1010
1011





1012
1013
1014

1015
1016
1017
1018
1019
1020

1021
1022
1023
1024
1025

1026
1027
1028
1029
1030

1031
1032
1033
1034
1035

1036
1037
1038
1039
1040

1041
1042
1043
1044
1045

1046
1047
1048
1049
1050
1051
1052
1053







-
-
-
-
-



-
+





-
+




-
+




-
+




-
+




-
+




-
+







      Unknown = 0,

      /// <summary>
      /// The connection is being opened.
      /// </summary>
      Opening = 1,

      /// <summary>
      /// The connection string has been parsed.
      /// </summary>
      ConnectionString = 2,

      /// <summary>
      /// The connection was opened.
      /// </summary>
      Opened = 3,
      Opened = 2,

      /// <summary>
      /// The <see cref="ChangeDatabase" /> method was called on the
      /// connection.
      /// </summary>
      ChangeDatabase = 4,
      ChangeDatabase = 3,

      /// <summary>
      /// A transaction was created using the connection.
      /// </summary>
      NewTransaction = 5,
      NewTransaction = 4,

      /// <summary>
      /// The connection was enlisted into a transaction.
      /// </summary>
      EnlistTransaction = 6,
      EnlistTransaction = 5,

      /// <summary>
      /// A command was created using the connection.
      /// </summary>
      NewCommand = 7,
      NewCommand = 6,

      /// <summary>
      /// The connection is being closed.
      /// </summary>
      Closing = 8,
      Closing = 7,

      /// <summary>
      /// The connection was closed.
      /// </summary>
      Closed = 9
      Closed = 8
  }

  /// <summary>
  /// This implementation of SQLite for ADO.NET can process date/time fields in databases in only one of three formats.  Ticks, ISO8601
  /// and JulianDay.
  /// </summary>
  /// <remarks>
Changes to System.Data.SQLite/SQLiteDataAdapter.cs.
80
81
82
83
84
85
86
87

88
89
90



91
92

93
94
95
96
97
98

99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
80
81
82
83
84
85
86

87



88
89
90


91






92


















93
94
95
96
97
98
99







-
+
-
-
-
+
+
+
-
-
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








    protected override void Dispose(bool disposing)
    {
        try
        {
            if (!disposed)
            {
                if (disposing)
                //if (disposing)
                {
                    ////////////////////////////////////
                    // dispose managed resources here...
                //{
                //    ////////////////////////////////////
                //    // dispose managed resources here...
                    ////////////////////////////////////

                //    ////////////////////////////////////
                    if (SelectCommand != null)
                    {
                        SelectCommand.Dispose();
                        SelectCommand = null;
                    }

                //}
                    if (InsertCommand != null)
                    {
                        InsertCommand.Dispose();
                        InsertCommand = null;
                    }

                    if (UpdateCommand != null)
                    {
                        UpdateCommand.Dispose();
                        UpdateCommand = null;
                    }

                    if (DeleteCommand != null)
                    {
                        DeleteCommand.Dispose();
                        DeleteCommand = null;
                    }
                }

                //////////////////////////////////////
                // release unmanaged resources here...
                //////////////////////////////////////

                disposed = true;
            }
Changes to System.Data.SQLite/SQLiteDefineConstants.cs.
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
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







-
-
-
-
















-
-
-
-







    internal static class SQLiteDefineConstants
    {
        public static readonly IList<string> OptionList = new List<string>(new string[] {
#if CHECK_STATE
            "CHECK_STATE",
#endif

#if COUNT_HANDLE
            "COUNT_HANDLE",
#endif

#if DEBUG
            "DEBUG",
#endif

#if INTEROP_CODEC
            "INTEROP_CODEC",
#endif

#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",
#endif

#if NET_20
            "NET_20",
#endif
Changes to System.Data.SQLite/SQLiteException.cs.
1
2
3
4

5
6
7
8
9
10
11
1
2
3

4
5
6
7
8
9
10
11



-
+







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

namespace System.Data.SQLite
{
  using System;
  using System.Data.Common;
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
180
181
182
183
184
185
186

187



188
189
190
191
192
193
194







-

-
-
-







    private static string GetStockErrorMessage(
        SQLiteErrorCode errorCode,
        string message
        )
    {
        return String.Format("{0}{1}{2}",
            GetErrorString(errorCode),
#if !NET_COMPACT_20
            Environment.NewLine, message).Trim();
#else
            "\r\n", message).Trim();
#endif
    }
  }

  /// <summary>
  /// SQLite error codes.  Actually, this enumeration represents a return code,
  /// which may also indicate success in one of several ways (e.g. SQLITE_OK,
  /// SQLITE_ROW, and SQLITE_DONE).  Therefore, the name of this enumeration is
Changes to System.Data.SQLite/SQLiteLog.cs.
354
355
356
357
358
359
360
361
362
363
364
365

366
367
368
369
370
371
372
354
355
356
357
358
359
360





361
362
363
364
365
366
367
368







-
-
-
-
-
+







        {
            bool enabled;
            SQLiteLogEventHandler handlers;

            lock (syncRoot)
            {
                enabled = _enabled;

                if (_handlers != null)
                    handlers = _handlers.Clone() as SQLiteLogEventHandler;
                else
                    handlers = null;
                handlers = _handlers;
            }

            if (enabled && (handlers != null))
                handlers(null, new LogEventArgs(
                    IntPtr.Zero, errorCode, message, null));
        }

Changes to System.Data.SQLite/System.Data.SQLite.Properties.targets.
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
66
67
68
69
70
71
72







73
74
75
76
77
78
79







-
-
-
-
-
-
-







  <!--
      NOTE: Enable extra internal state checking?
  -->
  <PropertyGroup Condition="'$(CheckState)' != 'false'">
    <DefineConstants>$(DefineConstants);CHECK_STATE</DefineConstants>
  </PropertyGroup>

  <!--
      NOTE: Enable counting of the CriticalHandle derived object instances?
  -->
  <PropertyGroup Condition="'$(CountHandle)' != 'false'">
    <DefineConstants>$(DefineConstants);COUNT_HANDLE</DefineConstants>
  </PropertyGroup>

  <!--
      NOTE: For interaction with the native SQLite implementation, use the
            custom build interop DLL (i.e. "SQLite.Interop.DLL")?
  -->
  <PropertyGroup Condition="'$(UseInteropDll)' != 'false'">
    <DefineConstants>$(DefineConstants);USE_INTEROP_DLL</DefineConstants>
  </PropertyGroup>
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
142
143
144
145
146
147
148








149
150
151
152
153
154
155







-
-
-
-
-
-
-
-







      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>

  <!--
      NOTE: Enable various Trace.WriteLine statements included in the code,
            based on several criteria (see the "SQLite.NET.Settings.targets"
            file for more information)?
  -->
  <PropertyGroup Condition="'$(TraceConnection)' != 'false'">
    <DefineConstants>$(DefineConstants);TRACE_CONNECTION</DefineConstants>
Changes to System.Data.SQLite/UnsafeNativeMethods.cs.
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
22
23
24
25
26
27
28

29
30
31
32
33
34
35
36
37



















38
39
40
41
42
43
44







-
+








-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








#if !PLATFORM_COMPACTFRAMEWORK && !DEBUG
  using System.Security;
#endif

  using System.Runtime.InteropServices;

#if !PLATFORM_COMPACTFRAMEWORK || COUNT_HANDLE
#if !PLATFORM_COMPACTFRAMEWORK
  using System.Threading;
#endif

#if !PLATFORM_COMPACTFRAMEWORK && !DEBUG
  [SuppressUnmanagedCodeSecurity]
#endif
  internal static class UnsafeNativeMethods
  {
      #region Critical Handle Counts (Debug Build Only)
#if COUNT_HANDLE
      //
      // NOTE: These counts represent the total number of outstanding
      //       (non-disposed) CriticalHandle derived object instances
      //       created by this library and are primarily for use by
      //       the test suite.  These counts are incremented by the
      //       associated constructors and are decremented upon the
      //       successful completion of the associated ReleaseHandle
      //       methods.
      //
      internal static int connectionCount;
      internal static int statementCount;
      internal static int backupCount;
#endif
      #endregion

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

      #region Optional Native SQLite Library Pre-Loading Code
      //
      // NOTE: If we are looking for the standard SQLite DLL ("sqlite3.dll"),
      //       the interop DLL ("SQLite.Interop.dll"), or we are running on the
      //       .NET Compact Framework, we should include this code (only if the
      //       feature has actually been enabled).  This code would be totally
      //       redundant if this module has been bundled into the mixed-mode
504
505
506
507
508
509
510
511

512
513
514
515
516
517
518
485
486
487
488
489
490
491

492
493
494
495
496
497
498
499







-
+







    //
    // NOTE: On the .NET Compact Framework, the native interop assembly must
    //       be used because it provides several workarounds to .NET Compact
    //       Framework limitations important for proper operation of the core
    //       System.Data.SQLite functionality (e.g. being able to bind
    //       parameters and handle column values of types Int64 and Double).
    //
    internal const string SQLITE_DLL = "SQLite.Interop.084.dll";
    internal const string SQLITE_DLL = "SQLite.Interop.083.dll";
#elif SQLITE_STANDARD
    //
    // NOTE: Otherwise, if the standard SQLite library is enabled, use it.
    //
    private const string SQLITE_DLL = "sqlite3";
#elif USE_INTEROP_DLL
    //
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
565
566
567
568
569
570
571




572
573
574
575
576
577
578







-
-
-
-








    [DllImport(SQLITE_DLL)]
    internal static extern IntPtr sqlite3_value_text_interop(IntPtr p, out int len);

    [DllImport(SQLITE_DLL)]
    internal static extern IntPtr sqlite3_value_text16_interop(IntPtr p, out int len);

#if INTEROP_LOG
    [DllImport(SQLITE_DLL)]
    internal static extern SQLiteErrorCode sqlite3_config_log_interop();
#endif
#endif
// !SQLITE_STANDARD

    #endregion

    // These functions add existing functionality on top of SQLite and require a little effort to
    // get working when using the standard SQLite library.
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
837
838
839
840
841
842
843







844
845
846
847
848
849
850







-
-
-
-
-
-
-







#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern IntPtr sqlite3_libversion();

#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern int sqlite3_libversion_number();

#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern IntPtr sqlite3_sourceid();

1491
1492
1493
1494
1495
1496
1497
1498

1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1461
1462
1463
1464
1465
1466
1467

1468
1469










1470
1471
1472
1473
1474
1475
1476







-
+

-
-
-
-
-
-
-
-
-
-







#endif

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

    #region SQLiteConnectionHandle Class
    // Handles the unmanaged database pointer, and provides finalization
    // support for it.
    internal sealed class SQLiteConnectionHandle : CriticalHandle
    internal class SQLiteConnectionHandle : CriticalHandle
    {
#if SQLITE_STANDARD && !PLATFORM_COMPACTFRAMEWORK
        internal delegate void CloseConnectionCallback(
            SQLiteConnectionHandle hdl, IntPtr db);

        internal static CloseConnectionCallback closeConnection =
            SQLiteBase.CloseConnection;
#endif

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

#if PLATFORM_COMPACTFRAMEWORK
        internal readonly object syncRoot = new object();
#endif

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

        public static implicit operator IntPtr(SQLiteConnectionHandle db)
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1501
1502
1503
1504
1505
1506
1507




1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519

1520



1521

1522
1523
1524
1525
1526
1527
1528







-
-
-
-












-

-
-
-

-







        }

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

        private SQLiteConnectionHandle()
            : base(IntPtr.Zero)
        {
#if COUNT_HANDLE
            Interlocked.Increment(
                ref UnsafeNativeMethods.connectionCount);
#endif
        }

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

        protected override bool ReleaseHandle()
        {
            try
            {
#if !PLATFORM_COMPACTFRAMEWORK
                IntPtr localHandle = Interlocked.Exchange(
                    ref handle, IntPtr.Zero);

#if SQLITE_STANDARD
                if (localHandle != IntPtr.Zero)
                    closeConnection(this, localHandle);
#else
                if (localHandle != IntPtr.Zero)
                    SQLiteBase.CloseConnection(this, localHandle);
#endif

#if !NET_COMPACT_20 && TRACE_HANDLE
                try
                {
                    Trace.WriteLine(String.Format(
                        "CloseConnection: {0}", localHandle));
                }
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1536
1537
1538
1539
1540
1541
1542




1543
1544
1545
1546
1547
1548
1549







-
-
-
-







                    if (handle != IntPtr.Zero)
                    {
                        SQLiteBase.CloseConnection(this, handle);
                        SetHandle(IntPtr.Zero);
                    }
                }
#endif
#if COUNT_HANDLE
                Interlocked.Decrement(
                    ref UnsafeNativeMethods.connectionCount);
#endif
#if DEBUG
                return true;
#endif
            }
#if !NET_COMPACT_20 && TRACE_HANDLE
            catch (SQLiteException e)
#else
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1576
1577
1578
1579
1580
1581
1582










1583
1584
1585
1586
1587
1588
1589







-
-
-
-
-
-
-
-
-
-







#else
            return true;
#endif
        }

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

#if COUNT_HANDLE
        public int WasReleasedOk()
        {
            return Interlocked.Decrement(
                ref UnsafeNativeMethods.connectionCount);
        }
#endif

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

        public override bool IsInvalid
        {
            get
            {
#if PLATFORM_COMPACTFRAMEWORK
                lock (syncRoot)
#endif
1672
1673
1674
1675
1676
1677
1678
1679

1680
1681
1682
1683
1684
1685
1686
1609
1610
1611
1612
1613
1614
1615

1616
1617
1618
1619
1620
1621
1622
1623







-
+







    }
    #endregion

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

    #region SQLiteStatementHandle Class
    // Provides finalization support for unmanaged SQLite statements.
    internal sealed class SQLiteStatementHandle : CriticalHandle
    internal class SQLiteStatementHandle : CriticalHandle
    {
#if PLATFORM_COMPACTFRAMEWORK
        internal readonly object syncRoot = new object();
#endif

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

1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1654
1655
1656
1657
1658
1659
1660




1661
1662
1663
1664
1665
1666
1667







-
-
-
-







        }

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

        private SQLiteStatementHandle()
            : base(IntPtr.Zero)
        {
#if COUNT_HANDLE
            Interlocked.Increment(
                ref UnsafeNativeMethods.statementCount);
#endif
        }

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

        protected override bool ReleaseHandle()
        {
            try
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1689
1690
1691
1692
1693
1694
1695




1696
1697
1698
1699
1700
1701
1702







-
-
-
-







                    if (handle != IntPtr.Zero)
                    {
                        SQLiteBase.FinalizeStatement(cnn, handle);
                        SetHandle(IntPtr.Zero);
                    }
                }
#endif
#if COUNT_HANDLE
                Interlocked.Decrement(
                    ref UnsafeNativeMethods.statementCount);
#endif
#if DEBUG
                return true;
#endif
            }
#if !NET_COMPACT_20 && TRACE_HANDLE
            catch (SQLiteException e)
#else
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1729
1730
1731
1732
1733
1734
1735










1736
1737
1738
1739
1740
1741
1742







-
-
-
-
-
-
-
-
-
-







#else
            return true;
#endif
        }

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

#if COUNT_HANDLE
        public int WasReleasedOk()
        {
            return Interlocked.Decrement(
                ref UnsafeNativeMethods.statementCount);
        }
#endif

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

        public override bool IsInvalid
        {
            get
            {
#if PLATFORM_COMPACTFRAMEWORK
                lock (syncRoot)
#endif
1843
1844
1845
1846
1847
1848
1849
1850

1851
1852
1853
1854
1855
1856
1857
1762
1763
1764
1765
1766
1767
1768

1769
1770
1771
1772
1773
1774
1775
1776







-
+







    }
    #endregion

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

    #region SQLiteBackupHandle Class
    // Provides finalization support for unmanaged SQLite backup objects.
    internal sealed class SQLiteBackupHandle : CriticalHandle
    internal class SQLiteBackupHandle : CriticalHandle
    {
#if PLATFORM_COMPACTFRAMEWORK
        internal readonly object syncRoot = new object();
#endif

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

1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1807
1808
1809
1810
1811
1812
1813




1814
1815
1816
1817
1818
1819
1820







-
-
-
-







        }

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

        private SQLiteBackupHandle()
            : base(IntPtr.Zero)
        {
#if COUNT_HANDLE
            Interlocked.Increment(
                ref UnsafeNativeMethods.backupCount);
#endif
        }

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

        protected override bool ReleaseHandle()
        {
            try
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1842
1843
1844
1845
1846
1847
1848




1849
1850
1851
1852
1853
1854
1855







-
-
-
-







                    if (handle != IntPtr.Zero)
                    {
                        SQLiteBase.FinishBackup(cnn, handle);
                        SetHandle(IntPtr.Zero);
                    }
                }
#endif
#if COUNT_HANDLE
                Interlocked.Decrement(
                    ref UnsafeNativeMethods.backupCount);
#endif
#if DEBUG
                return true;
#endif
            }
#if !NET_COMPACT_20 && TRACE_HANDLE
            catch (SQLiteException e)
#else
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1880
1881
1882
1883
1884
1885
1886










1887
1888
1889
1890
1891
1892
1893







-
-
-
-
-
-
-
-
-
-







#if DEBUG
            return false;
#else
            return true;
#endif
        }

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

#if COUNT_HANDLE
        public int WasReleasedOk()
        {
            return Interlocked.Decrement(
                ref UnsafeNativeMethods.backupCount);
        }
#endif

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

        public override bool IsInvalid
        {
            get
            {
#if PLATFORM_COMPACTFRAMEWORK
Changes to Tests/all.eagle.
44
45
46
47
48
49
50
51

52
53
54
55
56
57
58
44
45
46
47
48
49
50

51
52
53
54
55
56
57
58







-
+







#
# NOTE: Run all the unit tests.
#
set test_time [time {
  runAllTests $test_channel $path \
      [getTestFiles [list $path] $test_flags(-file) $test_flags(-notFile)] \
      [list [file tail [info script]] *.tcl pkgIndex.eagle common.eagle \
      constraints.eagle empty.eagle epilogue.eagle prologue.eagle]
      constraints.eagle epilogue.eagle prologue.eagle]
}]

#
# NOTE: Run the local test epilogue, if any.
#
if {[file exists [file join $path epilogue.eagle]]} then {
  source [file join $path epilogue.eagle]
Changes to Tests/backup.eagle.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
16
17
18
19
20
21
22






23
24
25
26
27
28
29







-
-
-
-
-
-







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

package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

checkForSQLiteDirectories $test_channel
getSQLiteHandleCounts $test_channel
reportSQLiteResources $test_channel

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

set params(pages) [list -1 -1 0 0 1 1 2 2 1000 1000]

set params(callbacks) [list null "new SQLiteBackupCallback(BackupCallback)" \
                            null "new SQLiteBackupCallback(BackupCallback)" \
                            null "new SQLiteBackupCallback(BackupCallback)" \
                            null "new SQLiteBackupCallback(BackupCallback)" \
                            null "new SQLiteBackupCallback(BackupCallback)"]
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
224
225
226
227
228
229
230






231
232
233
234







-
-
-
-
-
-




[lindex $params(results) $i]]}
}

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

unset -nocomplain i params pages callback

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

checkForSQLiteDirectories $test_channel
getSQLiteHandleCounts $test_channel
reportSQLiteResources $test_channel

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

runSQLiteTestEpilogue
runTestEpilogue
Changes to Tests/basic.eagle.
1688
1689
1690
1691
1692
1693
1694
1695

1696
1697
1698
1699
1700
1701
1702
1703
1704
1705

1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718

1719
1720
1721
1722
1723
1724
1725
1726
1688
1689
1690
1691
1692
1693
1694

1695
1696
1697
1698
1699
1700
1701
1702
1703
1704

1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716


1717

1718
1719
1720
1721
1722
1723
1724







-
+









-
+











-
-
+
-








  set found(data) [expr \
      {[llength [file list $directory(data) $fileName]] == 1}]

  set t [object create -alias Thread threadStart]
  sql execute $db "BEGIN TRANSACTION;"; $t Start

  for {set i 1} {$i < 1000} {incr i} {
  for {set i 1} {$i < 100} {incr i} {
    #
    # NOTE: Execute a query that should force the creation of a temporary file
    #       for its statement journal.
    #
    sql execute $db "UPDATE t1 SET x = ?;" [list param1 String $i]

    #
    # NOTE: Give the other thread some time to notice the temporary file.
    #
    after [expr {int(rand() * 1000)}]
    after 1000

    #
    # NOTE: Stop when the other thread confirms that the temporary file was
    #       created in the correct directory.
    #
    if {[info exists found(temp)] && $found(temp)} then {
      break
    }
  }

  $t Join; sql execute $db "COMMIT TRANSACTION;"

  lappend result $found(data) [expr {[info exists found(temp)] ? \
  lappend result $found(data) $found(temp); set result
      $found(temp) : False}]; set result
} -cleanup {
  #
  # NOTE: Close the database; however, do not attempt to delete the file as
  #       it is not located in the database directory known to the cleanupDb
  #       procedure (i.e. the one returned by getDatabaseDirectory).
  #
  cleanupDb $fileName db true false false
1791
1792
1793
1794
1795
1796
1797
1798

1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833






1834
1835
1836
1837

1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869


1870
1871
1872


1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946

1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
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
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146


2147
2148
2149
2150
2151
2152
2153
1789
1790
1791
1792
1793
1794
1795

1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815



1816
1817
1818
1819
1820
1821
1822
1823





1824
1825
1826
1827
1828
1829
1830
1831
1832

1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852



1853
1854
1855
1856
1857
1858
1859
1860


1861
1862



1863
1864








































































1865

1866






























































1867














1868
1869

























































































































1870
1871
1872
1873
1874
1875
1876
1877
1878







-
+



















-
-
-








-
-
-
-
-
+
+
+
+
+
+



-
+



















-
-
-








-
-
+
+
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-
-


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+







} -constraints {eagle SQLite System.Data.SQLite} -result \
[string map [list \n \r\n] {CantOpen {unable to open database file
this is a test} CantOpen {unable to open database file
this is a test} True True}]}

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

runTest {test data-1.35 {unencrypted database, with password} -setup {
runTest {test data-1.35 {open unencrypted database, with password} -setup {
  setupDb [set fileName data-1.35.db]
} -body {
  sql execute $db "CREATE TABLE t1(x);"
  sql execute $db "INSERT INTO t1 (x) VALUES(1);"

  cleanupDb $fileName db true false false
  setupDb $fileName "" "" "" "" "Password=12345;" true false

  set result [list]

  lappend result [catch {sql execute -execute scalar $db \
      "SELECT COUNT(*) FROM t1;"} error] $error

  lappend result [catch {sql execute $db \
      "INSERT INTO t1 (x) VALUES(1);"} error] $error

  cleanupDb $fileName db true false false
  setupDb $fileName "" "" "" "" "" true false

  lappend result [catch {sql execute $db \
      "INSERT INTO t1 (x) VALUES(1);"} error] $error

  lappend result [catch {sql execute -execute scalar $db \
      "SELECT COUNT(*) FROM t1;"} error] $error

  set result
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain error result db fileName
} -constraints {eagle defineConstant.System.Data.SQLite.INTEROP_CODEC monoBug28\
command.sql compile.DATA SQLite System.Data.SQLite} -match regexp -result {^1\
\{System\.Data\.SQLite\.SQLiteException \(0x80004005\): file is encrypted or is\
not a database.*?\} 1 \{System\.Data\.SQLite\.SQLiteException \(0x80004005\):\
file is encrypted or is not a database.*?\} 0 1 0 2$}}
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} \
-match regexp -result {^1 \{System\.Data\.SQLite\.SQLiteException\
\(0x80004005\): file is encrypted or is not a database.*?\} 1\
\{System\.Data\.SQLite\.SQLiteException \(0x80004005\): file is encrypted or is\
not a database.*?\} 0 1$}}

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

runTest {test data-1.36 {encrypted database, wrong password} -setup {
runTest {test data-1.36 {open encrypted database, wrong password} -setup {
  setupDb [set fileName data-1.36.db] "" "" "" "" "Password=12345;"
} -body {
  sql execute $db "CREATE TABLE t1(x);"
  sql execute $db "INSERT INTO t1 (x) VALUES(1);"

  cleanupDb $fileName db true false false
  setupDb $fileName "" "" "" "" "Password=12346;" true false

  set result [list]

  lappend result [catch {sql execute -execute scalar $db \
      "SELECT COUNT(*) FROM t1;"} error] $error

  lappend result [catch {sql execute $db \
      "INSERT INTO t1 (x) VALUES(1);"} error] $error

  cleanupDb $fileName db true false false
  setupDb $fileName "" "" "" "" "Password=12345;" true false

  lappend result [catch {sql execute $db \
      "INSERT INTO t1 (x) VALUES(1);"} error] $error

  lappend result [catch {sql execute -execute scalar $db \
      "SELECT COUNT(*) FROM t1;"} error] $error

  set result
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain error result db fileName
} -constraints {eagle defineConstant.System.Data.SQLite.INTEROP_CODEC monoBug28\
command.sql compile.DATA SQLite System.Data.SQLite} -match regexp -result {^1\
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} \
\{System\.Data\.SQLite\.SQLiteException \(0x80004005\): file is encrypted or is\
not a database.*?\} 1 \{System\.Data\.SQLite\.SQLiteException \(0x80004005\):\
file is encrypted or is not a database.*?\} 0 1 0 2$}}
-match regexp -result {^1 \{System\.Data\.SQLite\.SQLiteException\
\(0x80004005\): file is encrypted or is not a database.*?\} 1\

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

runTest {test data-1.37 {encrypted database, password w/start-space} -setup {
  setupDb [set fileName data-1.37.db] "" "" "" "" "Password= 1234;"
} -body {
  sql execute $db "CREATE TABLE t1(x);"
  sql execute $db "INSERT INTO t1 (x) VALUES(1);"

  cleanupDb $fileName db true false false
  setupDb $fileName "" "" "" "" "Password=1234;" true false

  set result [list]

  lappend result [catch {sql execute -execute scalar $db \
      "SELECT COUNT(*) FROM t1;"} error] $error

  lappend result [catch {sql execute $db \
      "INSERT INTO t1 (x) VALUES(1);"} error] $error

  cleanupDb $fileName db true false false
  setupDb $fileName "" "" "" "" "Password= 1234;" true false

  lappend result [catch {sql execute $db \
      "INSERT INTO t1 (x) VALUES(1);"} error] $error

  lappend result [catch {sql execute -execute scalar $db \
      "SELECT COUNT(*) FROM t1;"} error] $error

  set result
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain error result db fileName
} -constraints {eagle defineConstant.System.Data.SQLite.INTEROP_CODEC monoBug28\
command.sql compile.DATA SQLite System.Data.SQLite} -result {0 1 0 1 0 1 0 3}}

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

runTest {test data-1.38 {encrypted database, w/quoted-start-space} -setup {
  setupDb [set fileName data-1.38.db] "" "" "" "" "Password=\" 1234\";"
} -body {
  sql execute $db "CREATE TABLE t1(x);"
  sql execute $db "INSERT INTO t1 (x) VALUES(1);"

  cleanupDb $fileName db true false false
  setupDb $fileName "" "" "" "" "Password=1234;" true false

  set result [list]

  lappend result [catch {sql execute -execute scalar $db \
      "SELECT COUNT(*) FROM t1;"} error] $error

  lappend result [catch {sql execute $db \
      "INSERT INTO t1 (x) VALUES(1);"} error] $error

  cleanupDb $fileName db true false false
  setupDb $fileName "" "" "" "" "Password=\" 1234\";" true false

  lappend result [catch {sql execute $db \
      "INSERT INTO t1 (x) VALUES(1);"} error] $error

  lappend result [catch {sql execute -execute scalar $db \
      "SELECT COUNT(*) FROM t1;"} error] $error

  set result
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain error result db fileName
} -constraints {eagle defineConstant.System.Data.SQLite.INTEROP_CODEC monoBug28\
command.sql compile.DATA SQLite System.Data.SQLite} -match regexp -result {^1\
\{System\.Data\.SQLite\.SQLiteException \(0x80004005\): file is encrypted or is\
not a database.*?\} 1 \{System\.Data\.SQLite\.SQLiteException \(0x80004005\):\
not a database.*?\} 0 1$}}
file is encrypted or is not a database.*?\} 0 1 0 2$}}

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

runTest {test data-1.39 {encrypted database, password w/mid-space} -setup {
  setupDb [set fileName data-1.39.db] "" "" "" "" "Password=12 45;"
} -body {
  sql execute $db "CREATE TABLE t1(x);"
  sql execute $db "INSERT INTO t1 (x) VALUES(1);"

  cleanupDb $fileName db true false false
  setupDb $fileName "" "" "" "" "Password=1245;" true false

  set result [list]

  lappend result [catch {sql execute -execute scalar $db \
      "SELECT COUNT(*) FROM t1;"} error] $error

  lappend result [catch {sql execute $db \
      "INSERT INTO t1 (x) VALUES(1);"} error] $error

  cleanupDb $fileName db true false false
  setupDb $fileName "" "" "" "" "Password=12 45;" true false

  lappend result [catch {sql execute $db \
      "INSERT INTO t1 (x) VALUES(1);"} error] $error

  lappend result [catch {sql execute -execute scalar $db \
      "SELECT COUNT(*) FROM t1;"} error] $error

  set result
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain error result db fileName
} -constraints {eagle defineConstant.System.Data.SQLite.INTEROP_CODEC monoBug28\
command.sql compile.DATA SQLite System.Data.SQLite} -match regexp -result {^1\
\{System\.Data\.SQLite\.SQLiteException \(0x80004005\): file is encrypted or is\
not a database.*?\} 1 \{System\.Data\.SQLite\.SQLiteException \(0x80004005\):\
file is encrypted or is not a database.*?\} 0 1 0 2$}}

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

runTest {test data-1.40 {encrypted database, password w/end-space} -setup {
  setupDb [set fileName data-1.40.db] "" "" "" "" "Password=1234 ;"
} -body {
  sql execute $db "CREATE TABLE t1(x);"
  sql execute $db "INSERT INTO t1 (x) VALUES(1);"

  cleanupDb $fileName db true false false
  setupDb $fileName "" "" "" "" "Password=1234;" true false

  set result [list]

  lappend result [catch {sql execute -execute scalar $db \
      "SELECT COUNT(*) FROM t1;"} error] $error

  lappend result [catch {sql execute $db \
      "INSERT INTO t1 (x) VALUES(1);"} error] $error

  cleanupDb $fileName db true false false
  setupDb $fileName "" "" "" "" "Password=1234 ;" true false

  lappend result [catch {sql execute $db \
      "INSERT INTO t1 (x) VALUES(1);"} error] $error

  lappend result [catch {sql execute -execute scalar $db \
      "SELECT COUNT(*) FROM t1;"} error] $error

  set result
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain error result db fileName
} -constraints {eagle defineConstant.System.Data.SQLite.INTEROP_CODEC monoBug28\
command.sql compile.DATA SQLite System.Data.SQLite} -result {0 1 0 1 0 1 0 3}}

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

runTest {test data-1.41 {encrypted database, w/quoted-end-space} -setup {
  setupDb [set fileName data-1.41.db] "" "" "" "" "Password=\"1234 \";"
} -body {
  sql execute $db "CREATE TABLE t1(x);"
  sql execute $db "INSERT INTO t1 (x) VALUES(1);"

  cleanupDb $fileName db true false false
  setupDb $fileName "" "" "" "" "Password=1234;" true false

  set result [list]

  lappend result [catch {sql execute -execute scalar $db \
      "SELECT COUNT(*) FROM t1;"} error] $error

  lappend result [catch {sql execute $db \
      "INSERT INTO t1 (x) VALUES(1);"} error] $error

  cleanupDb $fileName db true false false
  setupDb $fileName "" "" "" "" "Password=\"1234 \";" true false

  lappend result [catch {sql execute $db \
      "INSERT INTO t1 (x) VALUES(1);"} error] $error

  lappend result [catch {sql execute -execute scalar $db \
      "SELECT COUNT(*) FROM t1;"} error] $error

  set result
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain error result db fileName
} -constraints {eagle defineConstant.System.Data.SQLite.INTEROP_CODEC monoBug28\
command.sql compile.DATA SQLite System.Data.SQLite} -match regexp -result {^1\
\{System\.Data\.SQLite\.SQLiteException \(0x80004005\): file is encrypted or is\
not a database.*?\} 1 \{System\.Data\.SQLite\.SQLiteException \(0x80004005\):\
file is encrypted or is not a database.*?\} 0 1 0 2$}}

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

runTest {test data-1.42 {encrypted database, password via builder} -setup {
  setupDb [set fileName data-1.42.db] "" "" "" "" "Password=67 89;"
} -body {
  sql execute $db "CREATE TABLE t1(x);"
  sql execute $db "INSERT INTO t1 (x) VALUES(1);"

  cleanupDb $fileName db true false false

  set connectionStringBuilder [object create -alias \
      System.Data.SQLite.SQLiteConnectionStringBuilder]

  $connectionStringBuilder DataSource \
      [file join [getDatabaseDirectory] $fileName]

  $connectionStringBuilder Password "67 89"

  set connection [object create -alias \
      System.Data.SQLite.SQLiteConnection \
      [$connectionStringBuilder ToString] true]

  $connection Open; addDbConnection $connection

  set result [list]

  lappend result [catch {sql execute -execute scalar $db \
      "SELECT COUNT(*) FROM t1;"} error] $error

  lappend result [catch {sql execute $db \
      "INSERT INTO t1 (x) VALUES(1);"} error] $error

  cleanupDb $fileName db true false false
  setupDb $fileName "" "" "" "" "Password=\"67 89\";" true false

  lappend result [catch {sql execute $db \
      "INSERT INTO t1 (x) VALUES(1);"} error] $error

  lappend result [catch {sql execute -execute scalar $db \
      "SELECT COUNT(*) FROM t1;"} error] $error

  set result
} -cleanup {
  unset -nocomplain connection

  cleanupDb $fileName; # NOTE: After object disposal.

  unset -nocomplain connectionStringBuilder error result db fileName
} -constraints {eagle defineConstant.System.Data.SQLite.INTEROP_CODEC monoBug28\
command.sql compile.DATA SQLite System.Data.SQLite} -result {0 1 0 1 0 1 0 3}}

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

runTest {test data-1.43 {quoted connection string properties} -setup {
  unset -nocomplain result list pair strings string
} -body {
  set result [list]

  set strings [list \
      "OneTwo=ThreeFour" "\"OneTwo\"=\"ThreeFour\"" \
      "One Two=Three Four" "\"One Two\"=\"Three Four\"" \
      "OneTwo=ThreeFour;" "\"OneTwo\"=\"ThreeFour\";" \
      "One Two=Three Four;" "\"One Two\"=\"Three Four\";"]

  foreach string $strings {
    set list [object invoke -flags +NonPublic \
        System.Data.SQLite.SQLiteConnection ParseConnectionString $string]

    object foreach -alias pair $list {
      lappend result [list [$pair Key] [$pair Value]]
    }
  }

  set result
} -cleanup {
  unset -nocomplain result list pair strings string
} -constraints {eagle System.Data.SQLite} -result {{OneTwo ThreeFour} {OneTwo\
ThreeFour} {{One Two} {Three Four}} {{One Two} {Three Four}} {OneTwo ThreeFour}\
{OneTwo ThreeFour} {{One Two} {Three Four}} {{One Two} {Three Four}}}}

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

runTest {test data-1.44 {rollback to nested savepoint} -setup {
  setupDb [set fileName data-1.44.db]
runTest {test data-1.37 {rollback to nested savepoint} -setup {
  setupDb [set fileName data-1.37.db]
} -body {
  sql execute $db "BEGIN IMMEDIATE TRANSACTION;"
  sql execute $db "SAVEPOINT one;"

  sql execute $db "CREATE TABLE t1(x);"
  sql execute $db "SAVEPOINT two;"

2168
2169
2170
2171
2172
2173
2174
2175
2176


2177
2178
2179
2180
2181
2182
2183
1893
1894
1895
1896
1897
1898
1899


1900
1901
1902
1903
1904
1905
1906
1907
1908







-
-
+
+







  unset -nocomplain result db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{1 2 1}}

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

runTest {test data-1.45 {NoExtensionFunctions connection flag} -setup {
  setupDb [set fileName data-1.45.db]
runTest {test data-1.38 {NoExtensionFunctions connection flag} -setup {
  setupDb [set fileName data-1.38.db]
} -body {
  set result [list]

  lappend result [catch {sql execute -execute scalar $db \
      "SELECT replicate('1234', 2);"} output] $output

  cleanupDb $fileName
2200
2201
2202
2203
2204
2205
2206
2207
2208


2209
2210
2211
2212
2213
2214
2215
1925
1926
1927
1928
1929
1930
1931


1932
1933
1934
1935
1936
1937
1938
1939
1940







-
-
+
+







} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -match \
regexp -result {^0 12341234 1 \{System\.Data\.SQLite\.SQLiteException\
\(0x80004005\): SQL logic error or missing database.*?\} 0 1234123412341234$}}

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

runTest {test data-1.46 {column name and index lookup} -setup {
  setupDb [set fileName data-1.46.db]
runTest {test data-1.39 {column name and index lookup} -setup {
  setupDb [set fileName data-1.39.db]
} -body {
  sql execute $db {
    CREATE TABLE t1(x, y, z);
    INSERT INTO t1 (x, y, z) VALUES(1, 'foo', 1234);
  }

  set dataReader [sql execute -execute reader -format datareader \
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
1959
1960
1961
1962
1963
1964
1965










































1966
1967
1968
1969
1970
1971
1972
1973
1974







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-









  cleanupDb $fileName

  unset -nocomplain result db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{{x 0 1} {y 1 foo} {z 2 1234}}}

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

runTest {test data-1.47 {nullable value types} -setup {
  setupDb [set fileName data-1.47.db]
} -body {
  sql execute $db {
    CREATE TABLE t1(x INTEGER);
    INSERT INTO t1 (x) VALUES(NULL);
    INSERT INTO t1 (x) VALUES(1);
  }

  set dataReader [sql execute -execute reader -format datareader \
      -alias $db "SELECT x FROM t1 ORDER BY x;"]

  set result [list]

  while {[$dataReader Read]} {
    foreach {a b c d e} [list "" "" "" "" ""] break

    set x [$dataReader GetOrdinal x]

    foreach {a b c e} [list \
        [$dataReader GetName $x] [$dataReader GetValue $x] \
        [catch {$dataReader GetInt64 $x} d] [$dataReader Item x]] break

    lappend result [list $x $a $b $c $d $e]
  }

  set result
} -cleanup {
  unset -nocomplain dataReader

  cleanupDb $fileName

  unset -nocomplain e d c b a x result db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -match \
regexp -result {^\{0 x System#DBNull#\d+ 1\
\{System\.Reflection\.TargetInvocationException: Exception has been thrown by\
the target of an invocation\. ---> System\.InvalidCastException:.*\}\
System#DBNull#\d+\} \{0 x 1 0 1 1\}$}}

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

unset -nocomplain systemDataSQLiteDllFile systemDataSQLiteLinqDllFile \
    testExeFile testLinqExeFile northwindEfDbFile testLinqOutFile

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

runSQLiteTestEpilogue
runTestEpilogue
Changes to Tests/common.eagle.
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
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
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373

374
375
376
377
378
379
380

381
382
383
384
385
386
387
292
293
294
295
296
297
298





































299
300
301
302
303
304
305
306
307
308
309
310

311
312
313
314
315
316
317

318
319
320
321
322
323
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







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-












-
+






-
+

















-
+






-
+







        # NOTE: Return the native-only interop assembly file name.
        #
        return [file nativename \
            [file join [getBinaryDirectory] SQLite.Interop.dll]]
      }
    }

    proc getCommonDirectory {} {
      #
      # NOTE: This procedure returns the directory where the test scripts
      #       should be located.  By default, this just returns the Eagle
      #       binary directory.
      #
      if {[info exists ::common_directory] && \
          [string length $::common_directory] > 0} then {
        #
        # NOTE: The location of the common directory has been set;
        #       therefore, use it.
        #
        return $::common_directory
      } elseif {[info exists ::vendor_directory] && \
          [string length $::vendor_directory] > 0} then {
        #
        # NOTE: The location of the vendor directory has been set;
        #       therefore, use it.
        #
        return $::vendor_directory
      } elseif {[info exists ::tcl_library] && \
          [string length $::tcl_library] > 0 && \
          [file isdirectory $::tcl_library]} then {
        #
        # NOTE: The variable with the location of the script library is
        #       set and appears to be a real directory (i.e. not embedded
        #       within a file); therefore, use it.
        #
        return $::tcl_library
      } else {
        #
        # NOTE: Fallback to the directory containing the executable.
        #
        return [info binary]
      }
    }

    proc getDatabaseDirectory {} {
      #
      # NOTE: This procedure returns the directory where the test databases
      #       should be located.  By default, this just uses the temporary
      #       directory configured for this system.
      #
      if {[info exists ::database_directory] && \
          [string length $::database_directory] > 0} then {
        #
        # NOTE: The location of the database directory has been overridden;
        #       therefore, use it.
        #
        return $::database_directory
        return [file normalize $::database_directory]
      } elseif {[info exists ::scratch_directory] && \
          [string length $::scratch_directory] > 0} then {
        #
        # NOTE: The location of the scratch directory has been overridden;
        #       therefore, use it.
        #
        return $::scratch_directory
        return [file normalize $::scratch_directory]
      } else {
        return [getTemporaryPath]
      }
    }

    proc getTemporaryDirectory {} {
      #
      # NOTE: This procedure returns the directory where the temporary files
      #       should be located.  By default, this just uses the temporary
      #       directory configured for this system.
      #
      if {[info exists ::temporary_directory] && \
          [string length $::temporary_directory] > 0} then {
        #
        # NOTE: The location of the temporary directory has been overridden;
        #       therefore, use it.
        #
        return $::temporary_directory
        return [file normalize $::temporary_directory]
      } elseif {[info exists ::scratch_directory] && \
          [string length $::scratch_directory] > 0} then {
        #
        # NOTE: The location of the scratch directory has been overridden;
        #       therefore, use it.
        #
        return $::scratch_directory
        return [file normalize $::scratch_directory]
      } else {
        return [getTemporaryPath]
      }
    }

    proc getTestOverridesPreamble { {extraVarNames ""} } {
      set varNames [list]
468
469
470
471
472
473
474
475

476
477

478
479
480
481
482

483
484
485

486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518

519
520
521
522
523
524
525
526
431
432
433
434
435
436
437

438


439





440



441



















442
443
444
445
446
447
448
449
450
451




452

453
454
455
456
457
458
459







-
+
-
-
+
-
-
-
-
-
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-










-
-
-
-
+
-







      return [uplevel 1 [list subst [appendArgs $prefix {
        if {[hasRuntimeOption native]} then {
          object invoke Interpreter.GetActive AddRuntimeOption native
        }
      } [getTestOverridesPreamble [list path test_channel]] $suffix]]]
    }

    proc tryCopyBinaryFile { fileName {newFileName ""} } {
    proc tryCopyBuildFile { fileName } {
      set sourceFileName [getBinaryFileName $fileName]

      #
      if {![file exists $sourceFileName]} then {
        tputs $::test_channel [appendArgs \
            "---- skipped copying binary file \"" $sourceFileName \
            "\", it does not exist\n"]

      # NOTE: If we cannot copy the assembly then it is probably already loaded.
        return
      }

      #
      if {[string length $newFileName] > 0} then {
        set targetFileName [getBuildFileName $newFileName]
      } else {
        set targetFileName [getBuildFileName $fileName]
      }

      if {[catch {
              file copy -force $sourceFileName $targetFileName}] == 0} then {
        tputs $::test_channel [appendArgs \
            "---- copied binary file from \"" $sourceFileName "\" to \"" \
            $targetFileName \"\n]
      } else {
        tputs $::test_channel [appendArgs \
            "---- failed to copy binary file from \"" $sourceFileName \
            "\" to \"" $targetFileName \"\n]
      }
    }

    proc tryCopyBuildFile { fileName {newFileName ""} } {
      set sourceFileName [getBuildFileName $fileName]

      if {![file exists $sourceFileName]} then {
        tputs $::test_channel [appendArgs \
            "---- skipped copying build file \"" $sourceFileName \
            "\", it does not exist\n"]

        return
      }

      if {[string length $newFileName] > 0} then {
        set targetFileName [getBinaryFileName $newFileName]
      } else {
        set targetFileName [getBinaryFileName $fileName]
      set targetFileName [getBinaryFileName $fileName]
      }

      if {[catch {
              file copy -force $sourceFileName $targetFileName}] == 0} then {
        tputs $::test_channel [appendArgs \
            "---- copied build file from \"" $sourceFileName "\" to \"" \
            $targetFileName \"\n]
      } else {
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
479
480
481
482
483
484
485




















486
487
488
489
490
491
492







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







            "---- deleted binary file \"" $fileName \"\n]
      } else {
        tputs $::test_channel [appendArgs \
            "---- failed to delete binary file \"" $fileName \"\n]
      }
    }

    proc tryDeleteBuildFile { fileName } {
      set fileName [getBuildFileName $fileName]

      if {![file exists $fileName]} then {
        tputs $::test_channel [appendArgs \
            "---- skipped deleting build file \"" $fileName \
            "\", it does not exist\n"]

        return
      }

      if {[catch {file delete $fileName}] == 0} then {
        tputs $::test_channel [appendArgs \
            "---- deleted build file \"" $fileName \"\n]
      } else {
        tputs $::test_channel [appendArgs \
            "---- failed to delete build file \"" $fileName \"\n]
      }
    }

    proc tryCopyAssembly { fileName {pdb true} } {
      tryCopyBuildFile $fileName

      if {$pdb} then {
        tryCopyBuildFile [appendArgs [file rootname $fileName] .pdb]
      }
    }
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
521
522
523
524
525
526
527















528
529
530
531
532
533
534







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







        #
        return $fileName
      }

      return ""
    }

    proc isSQLiteReady {} {
      #
      # NOTE: This procedure must return non-zero only if the SQLite native
      #       library and the System.Data.SQLite managed assembly are loaded
      #       and ready for use by the test suite.  Currently, this procedure
      #       should be called only after the [tryLoadAssembly] procedure has
      #       been called to probe for the System.Data.SQLite managed assembly
      #       and the [checkForSQLite] procedure has been called to probe for
      #       the SQLite native library; otherwise, this procedure will simply
      #       always return zero.
      #
      return [expr {[haveConstraint System.Data.SQLite] && \
          [haveConstraint SQLite]}]
    }

    proc checkForSQLite { channel } {
      tputs $channel "---- checking for core SQLite library... "

      if {[catch {
              object invoke -flags +NonPublic System.Data.SQLite.SQLite3 \
              SQLiteVersion} version] == 0} then {
        #
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
916
917
918
919
920
921
922























923
924
925
926
927
928
929







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







        #
        tputs $::test_channel [appendArgs \
            "==== WARNING: failed to remove connection handle \"" $connection \
            "\", error: " \n\t $error \n]
      }
    }

    proc addDbConnection { connection {varName db} } {
      #
      # NOTE: Refer to the specified variable (e.g. "db") in the context of our
      #       caller.
      #
      upvar 1 $varName db

      #
      # NOTE: Create a correctly formatted name for the database connection to
      #       be added to the list managed by the Eagle interpreter.
      #
      set db [object invoke -flags +NonPublic \
          Eagle._Components.Private.FormatOps DatabaseObjectName $connection \
          SQLiteConnection [object invoke Interpreter.GetActive NextId]]

      #
      # NOTE: Add the database connection provided by our caller to the list
      #       of those known to the Eagle interpreter.
      #
      object invoke -flags +NonPublic Interpreter.GetActive.connections Add \
          $db $connection
    }

    proc cleanupDb { fileName {varName db} {collect true} {qualify true}
                     {delete true} } {
      #
      # NOTE: Attempt to force all pending "garbage" objects to be collected,
      #       including SQLite statements and backup objects; this should allow
      #       the underlying database file to be deleted.
      #
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1000
1001
1002
1003
1004
1005
1006






























































1007
1008
1009
1010
1011
1012
1013







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







        #
        set code 0
      }

      return $code
    }

    proc setupDbInterruptCallback { channel log } {
      tputs $channel "---- setting up debugger interrupt callback... "

      if {[catch {
        #
        # NOTE: Make sure the script debugger and the isolated interpreter are
        #       setup and ready for use.
        #
        debug setup true true

        #
        # NOTE: Load the necessary packages into the isolated interpreter.
        #
        debug eval {
          package require Eagle
          package require Eagle.Library
          package require Eagle.Test
        }

        #
        # NOTE: Copy the necessary variables into the isolated interpreter.
        #
        debug invoke 0 set ::test_channel $channel; # NOTE: For [tputs].
        debug invoke 0 set ::test_log $log; # NOTE: For [tlog].

        #
        # NOTE: Install the callback script to be evaluated in the isolated
        #       interpreter when this interpreter is interrupted by script
        #       cancellation, etc.
        #
        debug callback apply {{sender e} {
          #
          # NOTE: Check if this callback is one that we care about.
          #
          if {"Canceled" in [split [$e InterruptType] ", "]} then {
            #
            # NOTE: Iterate through all database connections known to the
            #       parent interpreter.
            #
            object foreach -alias pair \
                [object invoke -flags +NonPublic $e Interpreter.connections] {
              #
              # NOTE: Attempt to cancel any SQL queries in progress on this
              #       database connection.
              #
              if {[catch {$pair Value.Cancel} error] != 0} then {
                tputs $::test_channel [appendArgs \n \
                    "==== WARNING: failed to cancel query for connection \"" \
                    [$pair Key] "\", error: " \n\t $error \n]
              }
            }
          }
        }}
      } error] == 0} then {
        addConstraint interruptCallback.sqlite3

        tputs $channel yes\n
      } else {
        tputs $channel [appendArgs "no, error: " \n\t $error \n]
      }
    }

    proc cleanupFile { fileName {collect true} {force false} } {
      #
      # NOTE: Attempt to force all pending "garbage" objects to be collected,
      #       including SQLite statements and backup objects; this should allow
      #       the underlying database file to be deleted.
      #
      if {$collect} then {
1237
1238
1239
1240
1241
1242
1243
1244

1245
1246
1247
1248
1249
1250
1251
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
1343
1344
1345


1346
1347
1348
1349
1350
1351
1352
1050
1051
1052
1053
1054
1055
1056

1057












1058




















1059
1060
1061
1062
1063
1064
1065
1066















































1067
1068
1069
1070
1071
1072
1073
1074
1075


1076

1077






1078


1079
1080
1081
1082
1083
1084
1085
1086
1087







-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-









-
-

-
+
-
-
-
-
-
-

-
-
+
+







        #
        set code 0
      }

      return $code
    }

    proc collectGarbage { channel {milliseconds 1000} {quiet true} } {
    proc collectGarbage { channel } {
      if {[catch {object invoke GC GetTotalMemory false} result] == 0} then {
        if {!$quiet} then {
          tputs $channel [appendArgs \
              "---- memory in use by the CLR before collection... " \
              $result " bytes\n"]
        }
      } else {
        tputs $channel [appendArgs \
            "==== WARNING: failed to get CLR memory usage, error: " \
            \n\t $result \n]
      }

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

      #
      # NOTE: Repeatedly attempt to collect garbage until the allotted number
      #       of milliseconds has elapsed.  Always attempt to collect garbage
      #       at least once.
      #
      set start [clock seconds]
      set stop [expr {$start + ($milliseconds / 1000)}]

      do {
        #
        # NOTE: Attempt to force a full garbage collection now.  Report any
        #       error that is encountered if we fail.
        #
        if {[catch {object invoke GC GetTotalMemory true} error]} then {
          tputs $channel [appendArgs \
              "==== WARNING: failed full garbage collection, error: " \
              \n\t $error \n]
        }
      # NOTE: Attempt to force a full garbage collection now.  Report any
      #       error that is encountered if we fail.
      #
      if {[catch {object invoke GC GetTotalMemory true} error]} then {
        tputs $channel [appendArgs \
            "==== WARNING: failed full garbage collection, error: " \
            \n\t $error \n]
      }

        set now [clock seconds]
      } while {$start <= $now && $now < $stop}

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

      if {[catch {object invoke GC GetTotalMemory false} result] == 0} then {
        if {!$quiet} then {
          tputs $channel [appendArgs \
              "---- memory in use by the CLR after collection... " \
              $result " bytes\n"]
        }
      } else {
        tputs $channel [appendArgs \
            "==== WARNING: failed to get CLR memory usage, error: " \
            \n\t $result \n]
      }
    }

    proc getSQLiteHandleCounts { channel {quiet false} } {
      set result [list]

      if {[haveConstraint \
              defineConstant.System.Data.SQLite.COUNT_HANDLE]} then {
        #
        # NOTE: Add each critical handle count to the resulting list.
        #
        foreach name [list connectionCount statementCount backupCount] {
          set value [object invoke -flags +NonPublic \
              System.Data.SQLite.UnsafeNativeMethods $name]

          if {!$quiet} then {
            tputs $channel [appendArgs \
                "---- critical handle count \"" $name "\" is " $value \n]
          }

          lappend result $value
        }
      } elseif {!$quiet} then {
        #
        # NOTE: The actual handle counts are not available; therefore, just
        #       return an empty list.
        #
        tputs $channel "---- critical handle counts unavailable\n"
      }

      return $result
    }

    proc shutdownSQLite { channel {force false} {quiet false} } {
      #
      # NOTE: Make sure that SQLite core library is completely shutdown.  This
      #       is used by tests that change configuration options and/or those
      #       that need to make sure logging is initialized (i.e. just in case
      #       the SQLite core library was initialized in the process prior to
      #       the SQLiteLog class being able to setup its logging callback).
      #       Normally, this should only be performed if SQLite is loaded and
      #       ready for use by the test suite.
      #
      if {$force || [isSQLiteReady]} then {
      if {$force || [haveConstraint SQLite]} then {
        #
        # BUGFIX: Before calling the native shutdown function, make sure both
        #         of the PRAGMA related directory names are freed.
        #
        checkForSQLiteDirectories $channel true

        if {[catch {object invoke -flags +NonPublic \
                System.Data.SQLite.UnsafeNativeMethods \
                sqlite3_shutdown} result] == 0} then {
              System.Data.SQLite.UnsafeNativeMethods \
              sqlite3_shutdown} result] == 0} then {
          if {!$quiet} then {
            tputs $channel [appendArgs \
                "---- call sqlite3_shutdown()... ok: " $result \n]
          }
        } else {
          if {!$quiet} then {
            tputs $channel [appendArgs \
1489
1490
1491
1492
1493
1494
1495
1496

1497
1498
1499
1500

1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514


1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526

1527
1528
1529
1530
1531


1532
1533

1534
1535
1536
1537
1538




1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614

1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1224
1225
1226
1227
1228
1229
1230

1231


1232

1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245


1246
1247
1248
1249
1250
1251
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







-
+
-
-

-
+












-
-
+
+











-
+
-

-
-
-
+
+

-
+

-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-






-
+
-


-
-
-
-
-
-







            }
          }
        }
      } else {
        tputs $channel no\n

        #
        # NOTE: Does our caller want to reset the directories?  This can only
        # NOTE: Does our caller want to reset the directories?
        #       be performed if SQLite is loaded and ready for use by the test
        #       suite.
        #
        if {$reset && [isSQLiteReady]} then {
        if {$reset} then {
          #
          # NOTE: Now make sure the database and temporary directories are
          #       reset their default values, which should be null for both.
          #       Since the sqlite3_win32_set_directory function does not
          #       appear to be available, use the associated PRAGMA commands
          #       instead.
          #
          foreach directory [list data_store_directory temp_store_directory] {
            set sql [appendArgs "PRAGMA " $directory " = \"\";"]

            if {[catch {executeSql $sql} result] == 0} then {
              tputs $channel [appendArgs \
                  "---- execute PRAGMA " $directory "... ok: \"" \
                  $result \"\n]
                  "---- execute PRAGMA " $directory "... ok: " \
                  $result \n]
            } else {
              tputs $channel [appendArgs \
                  "---- execute PRAGMA " $directory "... error: " \
                  \n\t $result \n]
            }
          }
        }
      }

      #
      # NOTE: Finally, show the current value of the database and temporary
      #       directories.  This can only be performed if SQLite is loaded
      #       directories.
      #       and ready for use by the test suite.
      #
      if {[isSQLiteReady]} then {
        foreach directory [list data_store_directory temp_store_directory] {
          tputs $channel [appendArgs "---- checking " $directory "... "]
      foreach directory [list data_store_directory temp_store_directory] {
        tputs $channel [appendArgs "---- checking " $directory "... "]

          set sql [appendArgs "PRAGMA " $directory \;]
        set sql [appendArgs "PRAGMA " $directory \;]

          if {[catch {executeSql $sql scalar} result] == 0} then {
            tputs $channel [appendArgs "ok: \"" $result \"\n]
          } else {
            tputs $channel [appendArgs "error: " \n\t $result \n]
        if {[catch {executeSql $sql scalar} result] == 0} then {
          tputs $channel [appendArgs "ok: \"" $result \"\n]
        } else {
          tputs $channel [appendArgs "error: " \n\t $result \n]
          }
        }
      }
    }

    proc loadSQLiteTestSettings { channel {suffix ""} {quiet false} } {
      #
      # NOTE: Skip loading the settings if their usage has been disabled.
      #
      if {![info exists ::no(sqliteTestSettings)]} then {
        #
        # NOTE: Load custom per-user and/or per-host test settings now.
        #
        if {[info exists ::tcl_platform(user)]} then {
          set userSettingsFileName [file join [getCommonDirectory] \
              [appendArgs settings $suffix . $::tcl_platform(user) .eagle]]

          if {[file exists $userSettingsFileName]} then {
            if {!$quiet} then {
              tputs $channel [appendArgs \
                  "---- loading per-user test settings file \"" \
                  $userSettingsFileName \"...\n]
            }

            if {[catch {uplevel 1 [list source $userSettingsFileName]} \
                    error]} then {
              if {!$quiet} then {
                tputs $channel [appendArgs \
                    "==== WARNING: failed to load per-user settings file \"" \
                    $userSettingsFileName "\", error: " \n\t $error \n]
              }
            }
          } else {
            if {!$quiet} then {
              tputs $channel [appendArgs \
                  "---- skipped loading per-user test settings file \"" \
                  $userSettingsFileName "\", it does not exist\n"]
            }
          }
        }

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

        if {[info exists ::tcl_platform(host)]} then {
          set hostSettingsFileName [file join [getCommonDirectory] \
              [appendArgs settings $suffix . $::tcl_platform(host) .eagle]]

          if {[file exists $hostSettingsFileName]} then {
            if {!$quiet} then {
              tputs $channel [appendArgs \
                  "---- loading per-host test settings file \"" \
                  $hostSettingsFileName \"...\n]
            }

            if {[catch {uplevel 1 [list source $hostSettingsFileName]} \
                    error]} then {
              if {!$quiet} then {
                tputs $channel [appendArgs \
                    "==== WARNING: failed to load per-host settings file \"" \
                    $hostSettingsFileName "\", error: " \n\t $error \n]
              }
            }
          } else {
            if {!$quiet} then {
              tputs $channel [appendArgs \
                  "---- skipped loading per-host test settings file \"" \
                  $hostSettingsFileName "\", it does not exist\n"]
            }
          }
        }
      }
    }

    proc runSQLiteTestPrologue {} {
      #
      # NOTE: Skip running our custom prologue if the main one has been
      # NOTE: Skip running our custom prologue if the main one has been skipped.
      #       skipped.
      #
      if {![info exists ::no(prologue.eagle)]} then {
        #
        # NOTE: Load the "before-constraints" custom per-user and/or per-host
        #       test settings now.
        #
        uplevel 1 [list loadSQLiteTestSettings $::test_channel .before]

        #
        # NOTE: Skip all System.Data.SQLite related file handling (deleting,
        #       copying, and loading) if we are so instructed.
        #
        if {![info exists ::no(sqliteFiles)]} then {
          #
          # NOTE: Skip trying to delete any files if we are so instructed.
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1311
1312
1313
1314
1315
1316
1317
























1318
1319
1320
1321
1322
1323
1324







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







          #
          # NOTE: Skip trying to load any files if we are so instructed.
          #
          if {![info exists ::no(loadSqliteFiles)]} then {
            tryLoadAssembly System.Data.SQLite.dll
            tryLoadAssembly System.Data.SQLite.Linq.dll
          }

          #
          # NOTE: Skip trying to delete external files if we are so instructed.
          #
          if {![info exists ::no(deleteSqliteExternalFiles)]} then {
            tryDeleteBuildFile Installer.exe.mda.config
            tryDeleteBuildFile test.exe.mda.config
            tryDeleteBuildFile testlinq.exe.mda.config
          }

          #
          # NOTE: Skip trying to copy external files if we are so instructed.
          #
          if {![info exists ::no(copySqliteExternalFiles)]} then {
            #
            # NOTE: Copy the MDA configuration file for the Eagle shell to the
            #       build output directory; however, use the name of the legacy
            #       test executable.  This will make sure that the legacy tests
            #       run with the same set of MDAs configured.
            #
            tryCopyBinaryFile EagleShell.exe.mda.config Installer.exe.mda.config
            tryCopyBinaryFile EagleShell.exe.mda.config test.exe.mda.config
            tryCopyBinaryFile EagleShell.exe.mda.config testlinq.exe.mda.config
          }
        }

        catch {
          tputs $::test_channel [appendArgs \
              "---- file version of \"sqlite3.dll\"... " \
              [file version [getBinaryFileName sqlite3.dll]] \n]
        }
1744
1745
1746
1747
1748
1749
1750
1751

1752
1753
1754

1755
1756
1757

1758
1759


1760
1761
1762
1763



1764
1765
1766
1767
1768








1769
1770
1771
1772
1773
1774
1775
1375
1376
1377
1378
1379
1380
1381

1382



1383


1384
1385


1386
1387




1388
1389
1390





1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405







-
+
-
-
-
+
-
-

+
-
-
+
+
-
-
-
-
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+








        #
        # NOTE: Check the SQLite database and temporary directories.
        #
        checkForSQLiteDirectories $::test_channel

        #
        # NOTE: Attempt to determine if various compile-time options needed for
        # NOTE: Attempt to determine if the custom extension functions were
        #       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
        #       compiled into the SQLite interop assembly.
        #       options, it will be assumed that it was enabled for the interop
        #       assembly if it was enabled for the managed assembly.
        #
        checkForSQLiteDefineConstant $::test_channel \
        foreach defineConstant [list CHECK_STATE COUNT_HANDLE INTEROP_CODEC \
                                     INTEROP_DEBUG INTEROP_LOG \
            CHECK_STATE

                                     INTEROP_EXTENSION_FUNCTIONS \
                                     INTEROP_TEST_EXTENSION SQLITE_STANDARD \
                                     USE_INTEROP_DLL] {
          #
        checkForSQLiteDefineConstant $::test_channel \
            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
        }
        checkForSQLiteDefineConstant $::test_channel \
            INTEROP_EXTENSION_FUNCTIONS

        checkForSQLiteDefineConstant $::test_channel \
            INTEROP_TEST_EXTENSION

        checkForSQLiteDefineConstant $::test_channel \
            SQLITE_STANDARD

        #
        # NOTE: Check the current build year.  Basically, this indicates
        #       which version of MSBuild and/or Visual Studio was used to
        #       compile the assembly binaries under test.
        #
        tputs $::test_channel \
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857

1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1416
1417
1418
1419
1420
1421
1422









1423
1424
1425
1426
1427
1428












1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439















1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450

1451

1452
1453
1454
1455
1456
1457
1458
1459
1460






1461
1462
1463
1464
1465
1466
1467







-
-
-
-
-
-
-
-
-






-
-
-
-
-
-
-
-
-
-
-
-











-
-
-
-
-
-
-
-
-
-
-
-
-
-
-











-
+
-









-
-
-
-
-
-







        tputs $::test_channel \
            "---- checking for System.Data.SQLite build configuration... "

        set configuration [getBuildConfiguration]
        addConstraint [appendArgs buildConfiguration $configuration]
        tputs $::test_channel [appendArgs \" $configuration \"\n]

        #
        # NOTE: Try to setup an interrupt callback using the script debugger
        #       that will cancel all SQL queries in progress for all database
        #       connections known to this interpreter.
        #
        if {![info exists ::no(sqliteInterruptCallback)]} then {
          setupDbInterruptCallback $::test_channel $::test_log
        }

        #
        # NOTE: Check for the native runtime option, which would mean we are
        #       using the mixed-mode assembly.
        #
        checkForRuntimeOption $::test_channel native

        #
        # NOTE: Check if the test suite should count the number of connections
        #       "opened" and "closed" from the pool when determining if a test
        #       passed.  Disabling this behavior is sometimes necessary (e.g.
        #       during the release testing process) because there are several
        #       tests that rely on the "opened from pool" count being greater
        #       than zero.  These tests may fail due to the non-deterministic
        #       behavior of the CLR GC, even when there is no bug in the code
        #       being tested.
        #
        checkForRuntimeOption $::test_channel noPoolCounts

        #
        # NOTE: Report the resource usage prior to running any tests.
        #
        reportSQLiteResources $::test_channel

        #
        # NOTE: Show the active test constraints.
        #
        tputs $::test_channel [appendArgs "---- constraints: " \
            [formatList [lsort [getConstraints]]] \n]

        #
        # NOTE: Save the test constraints for use by threads created in this
        #       application domain.  This is necessary because all the Eagle
        #       "test context" information is per-thread.
        #
        if {![info exists ::test_constraints]} then {
          set ::test_constraints $::eagle_tests(constraints)
        }

        #
        # NOTE: Load the "after-constraints" custom per-user and/or per-host
        #       test settings now.
        #
        uplevel 1 [list loadSQLiteTestSettings $::test_channel .after]

        #
        # NOTE: Show when our tests actually began (now).
        #
        tputs $::test_channel [appendArgs \
            "---- System.Data.SQLite tests began at " \
            [clock format [clock seconds]] \n]
      }
    }

    proc runSQLiteTestEpilogue {} {
      #
      # NOTE: Skip running our custom epilogue if the main one has been
      # NOTE: Skip running our custom epilogue if the main one has been skipped.
      #       skipped.
      #
      if {![info exists ::no(epilogue.eagle)]} then {
        #
        # NOTE: Show when our tests actually ended (now).
        #
        tputs $::test_channel [appendArgs \
            "---- System.Data.SQLite tests ended at " \
            [clock format [clock seconds]] \n]

        #
        # BUGFIX: Before checking the final resources in use by SQLite, make
        #         sure both of the PRAGMA related directory names are freed.
        #
        checkForSQLiteDirectories $::test_channel true

        #
        # NOTE: Also report the resource usage after running the tests.
        #
        reportSQLiteResources $::test_channel
      }
    }

Deleted Tests/empty.eagle.
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






































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
###############################################################################
#
# empty.eagle --
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################

package require Eagle
package require Eagle.Library
package require Eagle.Test

runTestPrologue

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

package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

#
# NOTE: There are no unit tests in this file.  This file exists to serve two
#       purposes:
#
#       1. Provide a "template" script file that can be used when creating new
#          unit test files.
#
#       2. Provide a script file that can be evaluated to setup an interactive
#          environment for ad-hoc testing of System.Data.SQLite using the Eagle
#          Shell.
#

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

runSQLiteTestEpilogue
runTestEpilogue
Changes to Tests/stress.eagle.
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
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







-
-
-
-
-
-
-
-
-








-
-
-
-
-
-
-
-
-

-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-






-
-
-







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

package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

#
# NOTE: Report before test, before shutdown.
#
checkForSQLiteDirectories $test_channel
getSQLiteHandleCounts $test_channel
reportSQLiteResources $test_channel

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

#
# NOTE: Make sure that SQLite core library is completely shutdown prior to
#       starting any of the tests in this file.
#
shutdownSQLite $test_channel

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

#
# NOTE: Report before test, after shutdown.
#
checkForSQLiteDirectories $test_channel
getSQLiteHandleCounts $test_channel
reportSQLiteResources $test_channel

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

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 connection indicators iterations exitOnFail coTaskMem \
  unset -nocomplain result thread index workload noWorkload srcDb db \
      fileName compiled options count times logFileName logListener \
      connection indicators iterations exitOnFail failures
      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]
  }

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

  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]
  }

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

  proc formatWorkloadResult { index } {
    set result [appendArgs "---- iterations for workload (" $index "): "]

    append result [expr {[info exists ::iterations($index,total)] ? \
        $::iterations($index,total) : 0}] " total, "

    append result [expr {[info exists ::iterations($index,ok)] ? \
        $::iterations($index,ok) : 0}] " ok, "

    append result [expr {[info exists ::iterations($index,error)] ? \
        $::iterations($index,error) : 0}] " error, "

    #
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131

132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152

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

175

176
177
178
179
180
181

182
183
184
185
186
187
188
189
190
191
192
193
194
195

196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
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
100
101
102
103
104
105







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-


-
+
-
-
-
-
-
-
-
-
-
-
-
-
-







-
+
-
-
-
-
-
-
-
-
-
-
-
-
-









+
-
+

-



-
+

-
-
-
-
-







-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







        $::failures($indicator) : 0}] " failed\n"

    return $result
  }

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

  proc formatWorkloadTime { index } {
    if {[info exists ::times($index)]} then {
      set length [llength $::times($index)]

      if {$length > 0} then {
        set sum [expr [join $::times($index) +]]

        return [appendArgs "---- average time for workload (" $index \
            ") is about " [expr {int($sum / $length / 1000.0)}] \
            " milliseconds (" [expr {int($sum / ([info exists \
            ::iterations($index,total)] ? $::iterations($index,total) : \
            $length) / 1000.0)}] " milliseconds per iteration)\n"]
      }
    }

    return [appendArgs "---- no times for workload (" $index )\n]
  }

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

  proc isExpectedError { error } {
    return [expr {[regexp -- {\sno such table: t1\s} $error] || \
        [regexp -- {\sdatabase is locked\s} $error] || \
        [regexp -- {\sdatabase is locked\s} $error]}]
        [regexp -- {\sdatabase table is locked\s} $error]}]
  }

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

  proc initTest { indicator } {
    set ::eagle_tests(constraints) $::test_constraints
  }

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

  proc delayTest { {extra 0} } {
    after [expr {int((rand() * 1000) + $extra)}]
  }

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

  proc showTest { indicator } {
    tputs $::test_channel $indicator
    append ::indicators $indicator
    delayTest $::count(2)
    after [expr {int(rand() * 1000 + $::count(2))}]
  }

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

  proc doneTest { {indicator ""} } {
    if {[string length $indicator] > 0} then {
      lappend ::status(done) $indicator
    }
    if {[info exists ::status(done)]} then {
      host title $::status(done)
    } else {
      host title ""
    }
  }

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

  proc failTest { indicator error } {
    #
    # NOTE: Halt all testing and exit the process now
    #       -OR- just record the failure and continue?
    #
    if {$::exitOnFail} then {
    set level [expr {[info level] - 1}]
      set level [expr {[info level] - 1}]

    if {$::exitOnFail} then {
      tputs $::test_channel [appendArgs \
          \n [info level $level] ": " \n\t $error \n]

      exit failure
      exit Failure
    } else {
      tlog [appendArgs \
          "\n---- BEGIN TEST FAILURE OUTPUT\n" \
          \n [info level $level] ": " \n\t $error \n \
          "\n---- END TEST FAILURE OUTPUT\n"]

      tputs $::test_channel $indicator

      if {![info exists ::failures($indicator)]} then {
        set ::failures($indicator) 0
      }

      incr ::failures($indicator)
      delayTest $::count(2)
      after [expr {int(rand() * 1000 + $::count(2))}]
    }
  }

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

  proc allocMem { size } {
    if {$::coTaskMem} then {
      return [object invoke -create \
          System.Runtime.InteropServices.Marshal \
          AllocCoTaskMem $size]; # throw
    } else {
      set ptr [object invoke -create -flags +NonPublic \
          System.Data.SQLite.UnsafeNativeMethods \
          sqlite3_malloc $size]

      if {[object invoke $ptr ToInt64] != 0} then {
        return $ptr
      } else {
        error [appendArgs "sqlite3_malloc(" $size ") failed"]
      }
    }
  }

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

  proc useMem { ptr size } {
    if {![isMono]} then {
      #
      # HACK: The type signature of the ZeroMemory method changed as of the
      #       .NET Framework 4.5.  The second argument went from being of
      #       type UInt to type UIntPtr.
      #
      if {[haveConstraint dotNet40] && [haveConstraint dotNet45]} then {
        set newSize [object create UIntPtr $size]
      } else {
        set newSize $size
      }

      object invoke -flags +NonPublic Microsoft.Win32.Win32Native \
          ZeroMemory $ptr $newSize
    }
  }

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

  proc freeMem { ptr } {
    if {$::coTaskMem} then {
      object invoke System.Runtime.InteropServices.Marshal \
          FreeCoTaskMem $ptr
    } else {
      object invoke -flags +NonPublic \
          System.Data.SQLite.UnsafeNativeMethods \
          sqlite3_free $ptr
    }

    #
    # NOTE: Free extra opaque object handle reference added by the
    #       [return] command in [allocMem].
    #
    object dispose $ptr
  }

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

  proc setupLogging { fileName } {
    if {![info exists ::logListener]} then {
      set ::logListener [object create -alias \
293
294
295
296
297
298
299













300
301
302
303
304
305
306
307
308





309
310

311
312

313
314
315
316
317
318
319
320
321
322
323
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
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379

380
381
382

383
384
385

386
387
388
389

390
391
392

393
394
395
396
397
398



399
400

401
402
403
404
405
406
407
408


409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159





160
161
162
163
164


165


166


167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182

183


184


185
186
187
188
189
190

191

192



























193
194
195
196
197

198
199
200

201
202
203

204

205
206

207
208
209

210
211





212
213
214


215



216
217



218
219
















220
221
222
223
224
225
226







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




-
-
-
-
-
+
+
+
+
+
-
-
+
-
-
+
-
-
















-

-
-
+
-
-






-

-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-





-
+


-
+


-
+
-


-
+


-
+

-
-
-
-
-
+
+
+
-
-
+
-
-
-


-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








    tputs $::test_channel [appendArgs \
        "---- disabled SQLite trace logging to file \"" $fileName \"\n]
  }

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

  #
  # NOTE: The trace listener used with the SQLiteLog class to capture output
  #       from the core SQLite library requires its own log file because the
  #       TextWriterTraceListener class opens and locks the log file it uses
  #       as the basis of the output stream.  Before this test is complete,
  #       the entire contents of this trace log file will be copied into the
  #       main test log file and then deleted.
  #
  set logFileName [appendArgs [file rootname $test_log] .trace.log]
  setupLogging $logFileName

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

  #
  # NOTE: Setup the default values for the tunable workload parameters.  Any,
  #       all, or none of these may be overriden via the command line.
  #
  set count(0) 3;         # Workload repeat count (i.e. total full runs).
  set count(1) 5;         # Workload iteration count (i.e. within a run).
  set count(2) 200;       # Workload iteration delay, in milliseconds.
  set count(3) 57;        # Workload "small" data chunk size, in bytes.
  set count(4) 10000;     # Workload "big" data chunk size, in bytes.
  set count(0) 1;        # Workload repeat count (i.e. total full runs).
  set count(1) 20;       # Workload iteration count (i.e. within a run).
  set count(2) 500;      # Workload iteration delay, in milliseconds.
  set count(3) 2000;     # Workload "small" data chunk size, in bytes.
  set count(4) 10000000; # Workload "big" data chunk size, in bytes.
  set count(5) 209715200; # Maximum heap memory to exclude at one time.
  set noWorkload [list];  # Workloads to be omitted from the run, by index.
  set noWorkload [list]; # Workloads to be omitted from the run, by index.
  set priorities [list];  # Dictionary of workload thread priorities.
  set exitOnFail false;   # Halt testing and exit process on test failure?
  set exitOnFail true;   # Halt testing and exit process on test failure?
  set coTaskMem true;     # Use AllocCoTaskMem/FreeCoTaskMem for memory?
  set noTrace false;      # Disable SQLite trace logging to a file?

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

  #
  # NOTE: If command line arguments to the test suite are available, process
  #       them for any options that are applicable to this test (i.e. any of
  #       the tunable workload parameters listed above).
  #
  if {[info exists argv] && [llength $argv] > 0} then {
    parse options -flags \
        {-StopOnUnknownOption +IgnoreOnUnknownOption SkipOnUnknownOption} -- \
        [list [list null MustHaveIntegerValue -1 -1 -count0 $count(0)] \
        [list null MustHaveIntegerValue -1 -1 -count1 $count(1)] \
        [list null MustHaveIntegerValue -1 -1 -count2 $count(2)] \
        [list null MustHaveIntegerValue -1 -1 -count3 $count(3)] \
        [list null MustHaveIntegerValue -1 -1 -count4 $count(4)] \
        [list null MustHaveIntegerValue -1 -1 -count5 $count(5)] \
        [list null MustHaveListValue -1 -1 -noWorkload $noWorkload] \
        [list null MustHaveListValue -1 -1 -priorities $priorities] \
        [list null MustHaveBooleanValue -1 -1 -exitOnFail $exitOnFail] \
        [list null MustHaveBooleanValue -1 -1 -exitOnFail $exitOnFail]] $argv
        [list null MustHaveBooleanValue -1 -1 -coTaskMem $coTaskMem] \
        [list null MustHaveBooleanValue -1 -1 -noTrace $noTrace]] $argv

    set count(0) $options(-count0,value)
    set count(1) $options(-count1,value)
    set count(2) $options(-count2,value)
    set count(3) $options(-count3,value)
    set count(4) $options(-count4,value)
    set count(5) $options(-count5,value)
    set noWorkload $options(-noWorkload,value)
    set priorities $options(-priorities,value)
    set exitOnFail $options(-exitOnFail,value)
    set coTaskMem $options(-coTaskMem,value)
    set noTrace $options(-noTrace,value)
  }

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

  #
  # NOTE: Load custom per-user and/or per-host test settings.  Currently, this
  #       is done after processing the command line options.  The settings file
  #       should take into account the existing workload parameters and avoid
  #       changing any that may have already been overridden.
  #
  loadSQLiteTestSettings $test_channel .stress

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

  #
  # NOTE: The trace listener used with the SQLiteLog class to capture output
  #       from the core SQLite library requires its own log file because the
  #       TextWriterTraceListener class opens and locks the log file it uses
  #       as the basis of the output stream.  Before this test is complete,
  #       the entire contents of this trace log file will be copied into the
  #       main test log file and then deleted.
  #
  if {!$noTrace} then {
    set logFileName [appendArgs [file rootname $test_log] .trace.log]
    setupLogging $logFileName
  }

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

  tputs $test_channel [appendArgs \
      "---- workloads will repeat " $count(0) " time(s)\n"]
      "---- workloads will repeat " $count(0) " time(s)...\n"]

  tputs $test_channel [appendArgs \
      "---- workloads will have " $count(1) " iteration(s)\n"]
      "---- workloads will have " $count(1) " iteration(s)...\n"]

  tputs $test_channel [appendArgs \
      "---- workloads will wait at least " $count(2) \
      "---- workloads will wait at least " $count(2) " millisecond(s)...\n"]
      " millisecond(s) after each iteration\n"]

  tputs $test_channel [appendArgs \
      "---- small chunk size is " $count(3) " byte(s)\n"]
      "---- workload \"small\" chunk size is " $count(3) " byte(s)...\n"]

  tputs $test_channel [appendArgs \
      "---- big chunk size is " $count(4) " byte(s)\n"]
      "---- workload \"big\" chunk size is " $count(4) " byte(s)...\n"]

  tputs $test_channel [appendArgs \
      "---- maximum excluded heap memory is " $count(5) " byte(s)\n"]

  tputs $test_channel [appendArgs \
      "---- workloads to be skipped... " \
  if {[llength $noWorkload] > 0} then {
    tputs $test_channel [appendArgs \
        "---- workloads to be skipped... " $noWorkload \n]
      [expr {[llength $noWorkload] > 0 ? $noWorkload : "none"}] \n]

  }
  tputs $test_channel [appendArgs \
      "---- workloads priority overrides... " \
      [expr {[llength $priorities] > 0 ? $priorities : "none"}] \n]

  tputs $test_channel [appendArgs \
      "---- unexpected errors " \
      [expr {$exitOnFail ? "will" : "will not"}] \
      " halt testing and exit the process\n"]
      "---- workload failures " [expr {$exitOnFail ? "will" : "will not"}] \
      " halt testing and exit the process...\n"]

  tputs $test_channel [appendArgs \
      "---- the " [expr {$coTaskMem ? "CoTaskMem" : "SQLite"}] \
      " allocator will be used to exclude heap memory\n"]

  tputs $test_channel [appendArgs \
      "---- trace logging to a file is " \
      [expr {$noTrace ? "disabled" : "enabled"}] \n]

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

  #
  # NOTE: Create the workload priority array based on the priority list seen
  #       on the command line, if any.
  #
  array set priority $priorities

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

  #
  # NOTE: Workloads #12 and #13 contain C# code that should be compiled, but
  #       only once.  These variables keep track of that state information.
  #       An integer value in one of these variables means the compilation was
450
451
452
453
454
455
456
457
458


459
460
461
462
463
464
465
245
246
247
248
249
250
251


252
253
254
255
256
257
258
259
260







-
-
+
+







  # NOTE: This is a normal on-disk database.
  #
  set fileName(2) [file join [getDatabaseDirectory] [appendArgs \
      stress- [pid] - [string trim [clock seconds] -] .db]]

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

  setupWorkloadMemDb $fileName(1) srcDb
  setupWorkloadFileDb $fileName(2)
  setupDb $fileName(1) "" "" "" "" "" false false true true srcDb
  setupDb $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.
475
476
477
478
479
480
481
482
483

484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514

515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544

545
546


547
548

549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581

582
583


584
585

586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618

619
620
621
622
623




624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650

651
652
653
654



655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681

682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712

713
714
715
716
717



718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743

744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773

774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803

804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
270
271
272
273
274
275
276


277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292

293
294
295
296
297
298
299
300
301
302
303
304
305


306
307
308
309
310
311
312
313
314
315
316
317
318
319
320

321
322
323
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
358
359
360
361
362
363
364
365
366
367
368
369


370
371
372
373
374
375

376

377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392

393
394
395
396
397
398
399
400
401
402
403
404
405


406
407
408



409
410
411
412
413
414
415
416
417
418
419
420
421
422
423

424
425
426
427
428
429
430
431
432
433
434
435
436


437
438
439


440
441
442
443
444
445
446
447
448
449
450
451
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
480
481
482

483
484
485
486
487
488
489
490
491
492
493
494
495


496
497
498
499


500
501
502
503
504
505
506
507
508
509
510
511
512

513
514
515
516
517
518
519
520
521
522
523
524
525


526
527
528
529
530
531
532
533
534
535
536
537
538
539
540

541
542
543
544
545
546
547
548
549
550
551
552
553


554
555
556
557
558
559
560
561
562
563
564
565
566
567
568

569
570
571
572
573
574
575
576
577
578
579
580
581


582
583
584
585
586
587
588
589
590
591
592
593
594
595

596
597
598
599
600
601
602
603
604
605
606
607
608

609
610
611
612
613
614
615







-
-
+















-













-
-
+














-













-
-
+


+
+

-
+
-
















-













-
-
+


+
+

-
+
-
















-













-
-
+


-
-
-
+
+
+
+











-













-
-
+


-
-
+
+
+











-













-
-
+















-













-
-
+



-
-
+
+
+










-













-
-
+














-













-
-
+














-













-
-
+













-













-








  set workload(1) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #1, CREATE TABLE statements.
    #
    lappend ::times(1) [lindex [time {
      initTest A
      setupWorkloadFileDb $dstFileName
      setupDb $dstFileName "" "" "" "" "" true false
      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 {
          if {[isExpectedError $error]} then {
            showTest a
          } else {
            failTest a $error
          }
        }
      }
      cleanupDb $dstFileName db false true false
      doneTest A
    }] 0]
  }]

  #############################################################################
  #                              WORKLOAD #2 (B)                              #
  #############################################################################

  set workload(2) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #2, DROP TABLE statements.
    #
    lappend ::times(2) [lindex [time {
      initTest B
      setupWorkloadFileDb $dstFileName
      setupDb $dstFileName "" "" "" "" "" true false
      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 {
            showTest b
          } else {
            failTest b $error
          }
        }
      }
      cleanupDb $dstFileName db false true false
      doneTest B
    }] 0]
  }]

  #############################################################################
  #                              WORKLOAD #3 (C)                              #
  #############################################################################

  set workload(3) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #3, "small" SELECT statements.
    #
    lappend ::times(3) [lindex [time {
      initTest C
      setupWorkloadFileDb $dstFileName
      setupDb $dstFileName "" "" "" "" "" true false
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          set sql [appendArgs \
              "SELECT x, y FROM " $table " WHERE z = 'small';"]
          set reader [sql execute -execute reader \
              -format dataReader -alias $db [appendArgs \
              -format dataReader -alias $db $sql]
              "SELECT x, y FROM " $table " WHERE z = 'small';"]]
          while {[$reader Read]} {
            #
            # NOTE: Do nothing.
            #
          }
          unset -nocomplain reader
          showTest C
        } error]} then {
          if {[isExpectedError $error]} then {
            showTest c
          } else {
            failTest c $error
          }
        }
      }
      cleanupDb $dstFileName db false true false
      doneTest C
    }] 0]
  }]

  #############################################################################
  #                              WORKLOAD #4 (D)                              #
  #############################################################################

  set workload(4) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #4, "big" SELECT statements.
    #
    lappend ::times(4) [lindex [time {
      initTest D
      setupWorkloadFileDb $dstFileName
      setupDb $dstFileName "" "" "" "" "" true false
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          set sql [appendArgs \
              "SELECT x, y FROM " $table " WHERE z = 'big';"]
          set reader [sql execute -execute reader \
              -format dataReader -alias $db [appendArgs \
              -format dataReader -alias $db $sql]
              "SELECT x, y FROM " $table " WHERE z = 'big';"]]
          while {[$reader Read]} {
            #
            # NOTE: Do nothing.
            #
          }
          unset -nocomplain reader
          showTest D
        } error]} then {
          if {[isExpectedError $error]} then {
            showTest d
          } else {
            failTest d $error
          }
        }
      }
      cleanupDb $dstFileName db false true false
      doneTest D
    }] 0]
  }]

  #############################################################################
  #                              WORKLOAD #5 (E)                              #
  #############################################################################

  set workload(5) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #5, "small" INSERT statements.
    #
    lappend ::times(5) [lindex [time {
      initTest E
      setupWorkloadFileDb $dstFileName
      setupDb $dstFileName "" "" "" "" "" true false
      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)}]] \
          sql execute $db [appendArgs \
              "INSERT INTO " $table "(x, y, z) VALUES('" \
              [format %lX [expr {random()}]] "', '" \
              [base64 encode -- [expr {randstr($count2)}]] \
              "', 'small');"]
          showTest E
        } error]} then {
          if {[isExpectedError $error]} then {
            showTest e
          } else {
            failTest e $error
          }
        }
      }
      cleanupDb $dstFileName db false true false
      doneTest E
    }] 0]
  }]

  #############################################################################
  #                              WORKLOAD #6 (F)                              #
  #############################################################################

  set workload(6) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #6, "big" INSERT statements.
    #
    lappend ::times(6) [lindex [time {
      initTest F
      setupWorkloadFileDb $dstFileName
      setupDb $dstFileName "" "" "" "" "" true false
      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()}]] \
          sql execute $db [appendArgs \
              "INSERT INTO " $table "(x, y, z) VALUES('" \
              [format %lX [expr {random()}]] \
              "', RANDOMBLOB(" $count3 "), 'big');"]
          showTest F
        } error]} then {
          if {[isExpectedError $error]} then {
            showTest f
          } else {
            failTest f $error
          }
        }
      }
      cleanupDb $dstFileName db false true false
      doneTest F
    }] 0]
  }]

  #############################################################################
  #                              WORKLOAD #7 (G)                              #
  #############################################################################

  set workload(7) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #7, "small" UPDATE statements.
    #
    lappend ::times(7) [lindex [time {
      initTest G
      setupWorkloadFileDb $dstFileName
      setupDb $dstFileName "" "" "" "" "" true false
      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 {
          if {[isExpectedError $error]} then {
            showTest g
          } else {
            failTest g $error
          }
        }
      }
      cleanupDb $dstFileName db false true false
      doneTest G
    }] 0]
  }]

  #############################################################################
  #                              WORKLOAD #8 (H)                              #
  #############################################################################

  set workload(8) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #8, "big" UPDATE statements.
    #
    lappend ::times(8) [lindex [time {
      initTest H
      setupWorkloadFileDb $dstFileName
      setupDb $dstFileName "" "" "" "" "" true false
      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';"]
              " SET y = RANDOMBLOB(" $count3 \
              ") WHERE x LIKE '" [format %X $index] \
              "%' AND z = 'big';"]
          showTest H
        } error]} then {
          if {[isExpectedError $error]} then {
            showTest h
          } else {
            failTest h $error
          }
        }
      }
      cleanupDb $dstFileName db false true false
      doneTest H
    }] 0]
  }]

  #############################################################################
  #                              WORKLOAD #9 (I)                              #
  #############################################################################

  set workload(9) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #9, "small" DELETE statements.
    #
    lappend ::times(9) [lindex [time {
      initTest I
      setupWorkloadFileDb $dstFileName
      setupDb $dstFileName "" "" "" "" "" true false
      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 {
            showTest i
          } else {
            failTest i $error
          }
        }
      }
      cleanupDb $dstFileName db false true false
      doneTest I
    }] 0]
  }]

  #############################################################################
  #                              WORKLOAD #10 (J)                             #
  #############################################################################

  set workload(10) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #10, "big" DELETE statements.
    #
    lappend ::times(10) [lindex [time {
      initTest J
      setupWorkloadFileDb $dstFileName
      setupDb $dstFileName "" "" "" "" "" true false
      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 {
            showTest j
          } else {
            failTest j $error
          }
        }
      }
      cleanupDb $dstFileName db false true false
      doneTest J
    }] 0]
  }]

  #############################################################################
  #                              WORKLOAD #11 (K)                             #
  #############################################################################

  set workload(11) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #11, VACUUM statement.
    #
    lappend ::times(11) [lindex [time {
      initTest K
      setupWorkloadFileDb $dstFileName
      setupDb $dstFileName "" "" "" "" "" true false
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db "VACUUM;"
          showTest K
        } error]} then {
          if {[isExpectedError $error]} then {
            showTest k
          } else {
            failTest k $error
          }
        }
      }
      cleanupDb $dstFileName db false true false
      doneTest K
    }] 0]
  }]

  #############################################################################
  #                              WORKLOAD #12 (L)                             #
  #############################################################################

  set workload(12) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #12, backup to in-memory database.
    #
    lappend ::times(12) [lindex [time {
      initTest L
      for {set index 1} {$index <= $count1} {incr index} {
        if {[string is integer -strict $::compiled(12)]} then {
          set id $::compiled(12); # NOTE: Already compiled.
          if {[catch {
            object invoke _Dynamic${id}.Test${id} BackupAndGetData
            showTest L
          } error]} then {
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
669
670
671
672
673
674
675

676
677
678
679
680
681
682
683
684
685
686
687
688

689
690
691
692
693
694
695







-













-







              }
            }
          } else {
            error $errors
          }
        }
      }
      doneTest L
    }] 0]
  }]

  #############################################################################
  #                              WORKLOAD #13 (M)                             #
  #############################################################################

  set workload(13) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #13, backup from an in-memory database.
    #
    lappend ::times(13) [lindex [time {
      initTest M
      for {set index 1} {$index <= $count1} {incr index} {
        if {[string is integer -strict $::compiled(13)]} then {
          set id $::compiled(13); # NOTE: Already compiled.
          if {[catch {
            object invoke _Dynamic${id}.Test${id} BackupAndGetData
            showTest M
          } error]} then {
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
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
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216

1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231


1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261

1262
1263
1264
1265
1266
1267
1268
749
750
751
752
753
754
755

756
757
758
759
760
761
762
763
764
765
766
767
768


769
770
771
772
773

774
775
776
777
778

779
780
781
782
783
784
785
786
787

788
789
790
791
792
793
794
795
796
797
798
799
800

801
802
803
804
805
806
807
808
809
810
811
812

813
814








































































































































































815




816














817
818
819
820
821
822
823
824
825







826
827
828
829
830
831
832
833
834








835
836
837
838
839
840
841
842







-













-
-
+




-
+
+
+


-









-













-












-


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-

+
+






-
-
-
-
-
-
-









-
-
-
-
-
-
-
-
+







              }
            }
          } else {
            error $errors
          }
        }
      }
      doneTest M
    }] 0]
  }]

  #############################################################################
  #                              WORKLOAD #14 (N)                             #
  #############################################################################

  set workload(14) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #14, PRAGMA integrity check statement.
    #
    lappend ::times(14) [lindex [time {
      initTest N
      setupWorkloadFileDb $dstFileName
      setupDb $dstFileName "" "" "" "" "" true false
      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 {
          if {$result eq "ok"} then {
            showTest N
          } else {
            error [appendArgs "integrity check failed: " $result]
          }
          showTest N
        } error]} then {
          if {[isExpectedError $error]} then {
            showTest n
          } else {
            failTest n $error
          }
        }
      }
      cleanupDb $dstFileName db false true false
      doneTest N
    }] 0]
  }]

  #############################################################################
  #                              WORKLOAD #15 (O)                             #
  #############################################################################

  set workload(15) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #15, force managed garbage collection
    #
    lappend ::times(15) [lindex [time {
      initTest O
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          collectGarbage $::test_channel
          showTest O
        } error]} then {
          if {[isExpectedError $error]} then {
            showTest o
          } else {
            failTest o $error
          }
        }
      }
      doneTest O
    }] 0]
  }]

  #############################################################################
  #                              WORKLOAD #16 (P)                             #
  #############################################################################

  set workload(16) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #16, allocate (exclude) some native heap memory
    #
    lappend ::times(16) [lindex [time {
      initTest P
      set maxSize $::count(5)
      object invoke GC AddMemoryPressure $maxSize
      try {
        for {set index 1} {$index <= $count1} {incr index} {
          if {[catch {
            set size [expr {int(min($maxSize, abs($count3 * $index * 5.0)))}]
            set ptr [allocMem $size]; # throw
            useMem $ptr $size; delayTest $count2
            freeMem $ptr; unset -nocomplain ptr
            showTest P
          } error]} then {
            if {[isExpectedError $error]} then {
              showTest p
            } else {
              failTest p $error
            }
          }
        }
      } finally {
        if {[info exists ptr]} then {
          freeMem $ptr; unset -nocomplain ptr
        }
        object invoke GC RemoveMemoryPressure $maxSize
      }
      doneTest P
    }] 0]
  }]

  #############################################################################
  #                              WORKLOAD #17 (Q)                             #
  #############################################################################

  set workload(17) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #17, change the database journal mode
    #
    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 {
            showTest q
          } else {
            failTest q $error
          }
        }
      }
      cleanupDb $dstFileName db false true false
      doneTest Q
    }] 0]
  }]

  #############################################################################
  #                              WORKLOAD #18 (R)                             #
  #############################################################################

  set workload(18) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #18, execute queries against the in-memory database
    #
    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 \
              "SELECT x, y FROM " $table " WHERE z = 'small';"]]
          while {[$reader Read]} {
            #
            # NOTE: Do nothing.
            #
          }
          unset -nocomplain reader
          #
          # NOTE: Workload #18.4, "big" SELECT statements.
          #
          set reader [sql execute -execute reader \
              -format dataReader -alias $db [appendArgs \
              "SELECT x, y FROM " $table " WHERE z = 'big';"]]
          while {[$reader Read]} {
            #
            # NOTE: Do nothing.
            #
          }
          unset -nocomplain reader
          #
          # NOTE: Workload #18.5, "small" INSERT statements.
          #
          sql execute $db [appendArgs "INSERT INTO " $table \
              "(x, y, z) VALUES('" [format %lX [expr {random()}]] \
              "', '" [base64 encode -- [expr {randstr($count2)}]] \
              "', 'small');"]
          #
          # NOTE: Workload #18.6, "big" INSERT statements.
          #
          sql execute $db [appendArgs "INSERT INTO " $table \
              "(x, y, z) VALUES('" [format %lX [expr {random()}]] \
              "', RANDOMBLOB(" $count3 "), 'big');"]
          #
          # NOTE: Workload #18.7, "small" UPDATE statements.
          #
          sql execute $db [appendArgs "UPDATE " $table \
              " SET y = '" [base64 encode -- [expr {randstr($count2)}]] \
              "' WHERE x LIKE '" [format %X $index] "%' AND z = 'small';"]
          #
          # NOTE: Workload #18.8, "big" UPDATE statements.
          #
          sql execute $db [appendArgs "UPDATE " $table \
              " SET y = RANDOMBLOB(" $count3 ") WHERE x LIKE '" \
              [format %X $index] "%' AND z = 'big';"]
          #
          # NOTE: Workload #18.9, "small" DELETE statements.
          #
          sql execute $db [appendArgs "DELETE FROM " $table \
              " WHERE x LIKE '" [format %X $index] "%' AND z = 'small';"]
          #
          # NOTE: Workload #18.10, "big" DELETE statements.
          #
          sql execute $db [appendArgs "DELETE FROM " $table \
              " WHERE x LIKE '" [format %X $index] "%' AND z = 'big';"]
          #
          # NOTE: Workload #18.11, VACUUM statement.
          #
          sql execute $db "VACUUM;"
          #
          # NOTE: Workload #18.14, PRAGMA integrity check statement.
          #
          set result [sql execute -execute scalar $db \
              "PRAGMA integrity_check;"]
          if {$result ne "ok"} then {
            error [appendArgs "integrity check failed: " $result]
          }
          showTest R
        } error]} then {
          if {[isExpectedError $error]} then {
            showTest r
          } else {
            failTest r $error
          }
        }
      }
      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)} {
  for {set index(0) 0} {$index(0) < $count(0)} {incr index(0)} {
    if {$index(0) > 1} then {
      #
      # NOTE: Advance output to the next line due to the workload
      #       iteration progress indicators from the previous run.
      #
      tputs $test_channel \n
    }

    tputs $test_channel [appendArgs \
        "---- 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);"

    unset -nocomplain thread

    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) [list Start Join] {
      foreach index(2) [array names thread] {
        $thread($index(2)) $index(1)
      }
    }

    foreach index(1) [array names thread] {
      if {[info exists thread($index(1))] && \
          [cleanupThread $thread($index(1))]} then {
        unset -nocomplain thread($index(1))
      }
    }

    unset -nocomplain thread status; doneTest
    unset -nocomplain thread
  }

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

  foreach index(0) [split $indicators ""] {
    #
    # NOTE: See if this workload iteration raised an error.  If so, the
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
850
851
852
853
854
855
856




857

858
859
860
861
862


863
864
865
866
867
868
869



870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885


886
887
888
889
890
891
892
893
894







-
-
-
-

-





-
-
+
+





-
-
-
+
+
+
+
+
+
+
+
+
+
+





-
-
+
+








    set index(3) [expr {$index(1) ? "ok" : "error"}]

    if {![info exists iterations($index(2),$index(3))]} then {
      set iterations($index(2),$index(3)) 0
    }

    if {![info exists iterations($index(2),total)]} then {
      set iterations($index(2),total) 0
    }

    incr iterations($index(2),$index(3))
    incr iterations($index(2),total)
  }

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

  #
  # NOTE: Advance output to the next line due to the workload
  #       iteration progress indicators from the final run.
  # NOTE: Advance output to the next line due to the workload iteration
  #       progress indicators.
  #
  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]] {
    set times(length) [llength $times($index(0))]

    if {$times(length) > 0} then {
      tputs $test_channel [appendArgs \
          "---- average time for workload (" $index(0) ") is about " \
          [expr int(([join $times($index(0)) +])/$times(length)/1000.0)] \
          " milliseconds\n"]
    } else {
      tputs $test_channel [appendArgs \
          "---- no times for workload (" $index(0) ")\n"]
    }
  }

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

  foreach index(0) [lsort -integer [array names times]] {
    tputs $test_channel [formatWorkloadTime $index(0)]
  foreach index(0) [lsort -integer [array names workload]] {
    tputs $test_channel [formatWorkloadResult $index(0)]
  }

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

  set result [sql execute -execute scalar $srcDb "PRAGMA integrity_check;"]

  if {$result eq "ok"} then {
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
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
1376

1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387






1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
912
913
914
915
916
917
918










919

920


921

922


923
924
925
926
927
928
929
930
931
932
933
934
935


936

937
938
939
940






941
942
943
944
945
946









947
948
949
950
951







-
-
-
-
-
-
-
-
-
-

-

-
-

-

-
-













-
-
+
-




-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-





  #
  # NOTE: The overall test result is the total number of failures (i.e.
  #       "unexpected errors") encountered during a workload iteration.
  #
  expr {[array size failures] > 0 ? \
      [expr [join [array values failures] +]] : 0}
} -cleanup {
  foreach index(0) [array names thread] {
    if {[info exists thread($index(0))] && \
        [cleanupThread $thread($index(0))]} then {
      unset -nocomplain thread($index(0))
    }
  }

  rename freeMem ""
  rename useMem ""
  rename allocMem ""
  rename failTest ""
  rename doneTest ""
  rename showTest ""
  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
  cleanupLogging $logFileName
  }

  rename cleanupLogging ""
  rename setupLogging ""

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

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

#
# NOTE: Report after test.
#
checkForSQLiteDirectories $test_channel
getSQLiteHandleCounts $test_channel
reportSQLiteResources $test_channel

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

runSQLiteTestEpilogue
runTestEpilogue
Changes to Tests/thread.eagle.
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
100
101
102
103
104
105
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







-
-
+





-
-
-
+
+
+
-
-
+
-
-
-
-
-
-
+

-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







-
-
+
-
-
-
-
-
-
-
-

-
+

-
-
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
+
+


-








package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

checkForSQLiteDirectories $test_channel true
set handle_counts [getSQLiteHandleCounts $test_channel]
set memory_used [reportSQLiteResources $test_channel]
set memory_used [reportSQLiteResources $test_channel true]

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

#
# NOTE: How many test threads should be created and used for these tests?  This
#       value must be at least two.  The first test thread (at index 0) is
#       always the "master thread" and just repeatedly calls the Thread.Abort()
#       method on other random test threads that appear to be alive until all
#       value must be at least two.  The first test thread (at index 0) just
#       repeatedly calls the Thread.Abort() method on the other test threads
#       that appear to be alive until all test threads appear to be dead.  All
#       test threads appear to have died.  All other test threads will attempt
#       to open a connection, execute one or more queries against it, and then
#       other threads will attempt to open a connection, execute one or more
#       close it.
#
if {![info exists count(1)]} then {
  set count(1) 10
}

#       queries against it, and then close it.
#
# NOTE: How many milliseconds should the master thread initially wait until it
#       starts to abort the other test threads?
#
if {![info exists count(2)]} then {
  set count(2) 1000
set count 10
}

#
# NOTE: How many milliseconds (maximum) should the master thread wait between
#       aborting other random test threads?
#
if {![info exists count(3)]} then {
  set count(3) 1000
}

#
# NOTE: How many bytes should be used for the five random data blobs contained
#       in the test database?
#
if {![info exists count(4)]} then {
  set count(4) 1000
}

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

runTest {test thread-1.1 {Thread.Abort() impact on native resources} -setup {
  setupDb [set fileName thread-1.1.db]

  tputs $test_channel [appendArgs \
      "---- using " $count(1) " test threads (with one master thread)\n"]

      "---- using a total of " $count " threads...\n"]
  tputs $test_channel [appendArgs \
      "---- initial wait will be " $count(2) " milliseconds\n"]

  tputs $test_channel [appendArgs \
      "---- subsequent maximum wait will be " $count(3) " milliseconds\n"]

  tputs $test_channel [appendArgs \
      "---- random data blob size will be " $count(4) " bytes\n"]
} -body {
  sql execute $db [subst {
  sql execute $db {
    CREATE TABLE t1(x INTEGER PRIMARY KEY, y BLOB);
    INSERT INTO t1 (y) VALUES(RANDOMBLOB(${count(4)}));
    INSERT INTO t1 (y) VALUES(RANDOMBLOB(${count(4)}));
    INSERT INTO t1 (y) VALUES(RANDOMBLOB(${count(4)}));
    INSERT INTO t1 (y) VALUES(RANDOMBLOB(${count(4)}));
    INSERT INTO t1 (y) VALUES(RANDOMBLOB(${count(4)}));
    INSERT INTO t1 (y) VALUES(RANDOMBLOB(1000));
    INSERT INTO t1 (y) VALUES(RANDOMBLOB(1000));
    INSERT INTO t1 (y) VALUES(RANDOMBLOB(1000));
    INSERT INTO t1 (y) VALUES(RANDOMBLOB(1000));
    INSERT INTO t1 (y) VALUES(RANDOMBLOB(1000));
  }]

  #
  # NOTE: The data and temporary directories must be reset here (after the
  }

  #
  # NOTE: The temporary directory must be reset here because it allocates
  #       setupDb call above) because they allocate some SQLite memory and
  #       this test requires an extremely accurate reading.
  #       some SQLite memory and this test requires an extremely accurate
  #       reading.
  #
  sql execute $db {
    PRAGMA data_store_directory = "";
    PRAGMA temp_store_directory = "";
  }

  #
  # NOTE: Close the database now, freeing any native SQLite memory and/or
  #       resources that it may be using at this point; however, do not
  #       actually delete the database file because it is needed in the C#
128
129
130
131
132
133
134
135

136
137
138
139
140
141
142
143
144

145
146
147
148
149
150

151
152
153
154
155
156

157
158
159
160
161

162
163
164
165
166
167
168
90
91
92
93
94
95
96

97
98
99
100
101
102
103
104
105

106
107
108
109
110
111

112
113
114
115
116
117

118
119
120
121
122

123
124
125
126
127
128
129
130







-
+








-
+





-
+





-
+




-
+







    using System.Threading;
    using Eagle._Containers.Public;

    namespace _Dynamic${id}
    {
      public static class Test${id}
      {
        public static LongList RunTestThreads()
        public static IntList RunTestThreads()
        {
          //
          // NOTE: This is the total number of data bytes seen in the second
          //       column of the query result rows seen by all test threads.
          //       This value will vary greatly based upon how many loop
          //       iterations are performed prior to each test thread being
          //       aborted.
          //
          long sum = 0;
          int sum = 0;

          //
          // NOTE: This is the total number of query result rows seen by all
          //       the test threads.
          //
          long rows = 0;
          int rows = 0;

          //
          // NOTE: This is the total number of exceptions caught by all the
          //       test threads.
          //
          long errors = 0;
          int errors = 0;

          //
          // NOTE: This is the total number of test threads to create.
          //
          int count = ${count(1)};
          int count = ${count};

          //
          // NOTE: Create the array of thread objects.
          //
          Thread\[\] thread = new Thread\[count\];

          //
315
316
317
318
319
320
321
322

323
324
325
326
327
328
329
330
331
332
333

334
335
336
337
338
339
340
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







-
+










-
+







                goEvent.WaitOne();

                //
                // NOTE: Give the other test threads a slight head start to
                //       make sure that they are fully alive prior to trying
                //       to abort any of them.
                //
                Thread.Sleep(${count(2)});
                Thread.Sleep(1000);

                //
                // NOTE: Loop forever until all test threads appear to be dead.
                //
                while (true)
                {
                  //
                  // NOTE: Wait a random number of milliseconds, up to a full
                  //       second.
                  //
                  Thread.Sleep(random.Next(0, ${count(3)}));
                  Thread.Sleep(random.Next(0, 1000));

                  //
                  // NOTE: Select a random thread to abort.
                  //
                  int index = random.Next(1, count);

                  //
422
423
424
425
426
427
428
429

430
431
432
433
434
435
436
384
385
386
387
388
389
390

391
392
393
394
395
396
397
398







-
+







          }

          //
          // NOTE: Return a list of integers with total number of data bytes
          //       seen, total number of query result rows seen, and the total
          //       number of exceptions caught by all the test threads.
          //
          LongList counts = new LongList();
          IntList counts = new IntList();

          counts.Add(sum);
          counts.Add(rows);
          counts.Add(errors);

          return counts;
        }
446
447
448
449
450
451
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
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
433
434
435
436
437







-
+
-
-
+




-
-
-
-
+
+
+
+







-
+





  }] true true true results errors [list System.Data.SQLite.dll Eagle.dll]]

  list $code $results \
      [expr {[info exists errors] ? $errors : ""}] \
      [expr {$code eq "Ok" ? [catch {
        object invoke _Dynamic${id}.Test${id} RunTestThreads
      } result] : [set result ""]}] $result \
      [collectGarbage $test_channel [expr {$count(1) * 1000}] false] \
      [collectGarbage $test_channel] \
      [getSQLiteHandleCounts $test_channel] \
      [reportSQLiteResources $test_channel]
      [reportSQLiteResources $test_channel true]
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain result results errors code sql dataSource id db fileName
} -time true -constraints {eagle monoBug28 command.sql compile.DATA SQLite\
System.Data.SQLite} -match regexp -result [appendArgs "^Ok\
System#CodeDom#Compiler#CompilerResults#\\d+ \\{\\} 0 \\{\\d+ \\d+ " $count(1) \
"\\} \\{\\} \\{" $handle_counts "\\} " $memory_used \$]}
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -match \
regexp -result [appendArgs "^Ok System#CodeDom#Compiler#CompilerResults#\\d+\
\\{\\} 0 \\{\\d+ \\d+ " $count "\\} \\{\\} " $memory_used \$]}

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

unset -nocomplain count

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

unset -nocomplain memory_used handle_counts
unset -nocomplain memory_used

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

runSQLiteTestEpilogue
runTestEpilogue
Deleted Tests/tkt-6434e23a0f.eagle.
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






















































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
###############################################################################
#
# tkt-6434e23a0f.eagle --
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################

package require Eagle
package require Eagle.Library
package require Eagle.Test

runTestPrologue

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

package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

runTest {test tkt-6434e23a0f-1.1 {SQLiteDataAdapter command disposal} -setup {
  setupDb [set fileName tkt-6434e23a0f-1.1.db]
} -body {
  sql execute $db "CREATE TABLE t1(x);"
  sql execute $db "INSERT INTO t1 (x) VALUES(1);"
  sql execute $db "INSERT INTO t1 (x) VALUES(2);"

  cleanupDb $fileName db true false false

  set id [object invoke Interpreter.GetActive NextId]
  set dataSource [file join [getDatabaseDirectory] $fileName]

  set sql { \
    SELECT x FROM t1; \
  }

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {
    using System.Data;
    using System.Data.SQLite;
    using System.IO;

    namespace _Dynamic${id}
    {
      public static class Test${id}
      {
        public static void Main()
        {
          using (SQLiteConnection connection = new SQLiteConnection(
              "Data Source=${dataSource};"))
          {
            connection.Open();

            using (SQLiteDataAdapter dataAdapter = new SQLiteDataAdapter(
                "${sql}", connection))
            {
              dataAdapter.Fill(new DataSet());
            }
          }

          File.Delete("${dataSource}");
        }
      }
    }
  }] true true true results errors System.Data.SQLite.dll]

  list $code $results \
      [expr {[info exists errors] ? $errors : ""}] \
      [expr {$code eq "Ok" ? [catch {
        object invoke _Dynamic${id}.Test${id} Main
      } result] : [set result ""]}] $result
} -cleanup {
  cleanupDb $fileName

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

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

runSQLiteTestEpilogue
runTestEpilogue
Deleted Tests/tkt-6c6ecccc5f.eagle.
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


















































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
###############################################################################
#
# tkt-6c6ecccc5f.eagle --
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################

package require Eagle
package require Eagle.Library
package require Eagle.Test

runTestPrologue

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

package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

runTest {test tkt-6c6ecccc5f-1.1 {CloseConnection with extensions} -setup {
  setupDb [set fileName tkt-6c6ecccc5f-1.1.db]
} -body {
  sql execute $db {
    CREATE VIRTUAL TABLE t1 USING fts4(x TEXT);
    INSERT INTO t1 (x) VALUES('one');
    INSERT INTO t1 (x) VALUES('two');
  }

  set id [object invoke Interpreter.GetActive NextId]
  set dataSource [file join [getDatabaseDirectory] $fileName]
  set sql "SELECT x FROM t1 WHERE x MATCH 'one';"

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {
    using System.Data;
    using System.Data.SQLite;

    namespace _Dynamic${id}
    {
      public static class Test${id}
      {
        public static void Main()
        {
          using (SQLiteConnection connection = new SQLiteConnection(
              "Data Source=${dataSource};"))
          {
            connection.Open();

            using (SQLiteCommand command = new SQLiteCommand("${sql}",
                connection))
            {
              /* IGNORED */
              command.ExecuteReader(CommandBehavior.CloseConnection);
            }
          }
        }
      }
    }
  }] true true true results errors System.Data.SQLite.dll]

  list $code $results \
      [expr {[info exists errors] ? $errors : ""}] \
      [expr {$code eq "Ok" ? [catch {
        object invoke _Dynamic${id}.Test${id} Main
      } result] : [set result ""]}] $result
} -cleanup {
  cleanupDb $fileName

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

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

runSQLiteTestEpilogue
runTestEpilogue
Changes to Tests/tkt-72905c9a77.eagle.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
16
17
18
19
20
21
22








23
24
25
26
27
28
29







-
-
-
-
-
-
-
-







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

package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

#
# NOTE: Make sure that SQLite core library is completely shutdown prior to
#       starting any of the tests in this file.
#
shutdownSQLite $test_channel

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

#
# NOTE: This value is needed as part of the test result; therefore, it must be
#       set outside of the test setup.
#
set id [object invoke Interpreter.GetActive NextId]

###############################################################################
268
269
270
271
272
273
274
275
276
277


278
279
280
281
282
283
284
285
286
287
288
289
260
261
262
263
264
265
266



267
268
269
270
271
272
273
274
275
276
277
278
279
280







-
-
-
+
+












      [expr {$code eq "Ok" ? [catch {
        object invoke _Dynamic${id}.Test${id} GetTraceOutput
      } result] : [set result ""]}] [string map [list \r\n \n] $result]
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain result code results errors dataSource fileName
} -constraints [fixConstraints {eagle monoBug28 configuration.Release\
!defineConstant.System.Data.SQLite.INTEROP_LOG command.sql compile.DATA\
SQLite System.Data.SQLite}] -match regexp -result [appendArgs "^Ok\
} -constraints {eagle configuration.Release monoBug28 command.sql compile.DATA\
SQLite System.Data.SQLite} -match regexp -result [appendArgs "^Ok\
System#CodeDom#Compiler#CompilerResults#\\d+ \\{\\} 0 \\{" [string repeat \
"SQLite message \\(0\\): TEST $id
" [expr {4 * [info processors]}]] "\\}\$"]}

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

unset -nocomplain id

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

runSQLiteTestEpilogue
runTestEpilogue
Changes to Tests/tkt-996d13cd87.eagle.
27
28
29
30
31
32
33
34

35
36
37
38
39
40
41
27
28
29
30
31
32
33

34
35
36
37
38
39
40
41







-
+







  runTest {test [appendArgs tkt-996d13cd87-1. $i] {SQLiteConnection stress} \
      -setup {
    set fileName [appendArgs tkt-996d13cd87-1. $i .db]

    tputs $test_channel [appendArgs \
        "---- using a total of " $count " threads...\n"]

    if {![haveConstraint runtime.noPoolCounts] && [catch {
    if {[catch {
        object invoke -flags +NonPublic \
            System.Data.SQLite.SQLiteConnectionPool _poolOpened 0

        object invoke -flags +NonPublic \
            System.Data.SQLite.SQLiteConnectionPool _poolClosed 0
    }] == 0} then {
      set havePoolCounts true
Deleted Tests/tkt-ae5267b863.eagle.
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156




























































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
###############################################################################
#
# tkt-ae5267b863.eagle --
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################

package require Eagle
package require Eagle.Library
package require Eagle.Test

runTestPrologue

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

package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

#
# NOTE: For some reason, this test does not play nicely when all the managed
#       debugging assistants are enabled.
#
runTest {test tkt-ae5267b863-1.1 {segfault during command GC} -setup {
  setupDb [set fileName tkt-ae5267b863-1.1.db]
} -body {
  set id [object invoke Interpreter.GetActive NextId]
  set dataSource [file join [getDatabaseDirectory] $fileName]

  set sql(1) { \
    CREATE TABLE t1( \
      __rowid INTEGER PRIMARY KEY AUTOINCREMENT, \
      z STRING \
    ); \
  }

  set sql(2) { \
    CREATE VIRTUAL TABLE t2 USING RTREE( \
      id, minx, maxx, miny, maxy \
    ); \
  }

  set sql(3) { \
    INSERT INTO t1 VALUES({0}, \"value {0}\"); \
  }

  set sql(4) { \
    INSERT INTO t2 VALUES({0}, {0}, {0}, {0}, {0}); \
  }

  set sql(5) { \
    SELECT COUNT(*) FROM t1, t2 \
    WHERE t1.__rowid = t2.id AND \
    (t2.minx <= :xmax and t2.miny <= :ymax and \
     t2.maxx >= :xmin and t2.maxy >= :ymin); \
  }

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {
    using System;
    using System.Data.SQLite;

    namespace _Dynamic${id}
    {
      public static class Test${id}
      {
        public static void Main()
        {
          using (SQLiteConnection connection = new SQLiteConnection(
              "Data Source=${dataSource};"))
          {
            connection.Open();

            using (SQLiteCommand command = connection.CreateCommand())
            {
              command.CommandText = "${sql(1)}";
              command.ExecuteNonQuery();

              command.CommandText = "${sql(2)}";
              command.ExecuteNonQuery();
            }

            using (SQLiteCommand command = connection.CreateCommand())
            {
              using (SQLiteTransaction transaction =
                  connection.BeginTransaction())
              {
                for (int index = 0; index < 10; index++)
                {
                  command.CommandText = String.Format("${sql(3)}", index);
                  command.ExecuteNonQuery();

                  command.CommandText = String.Format("${sql(4)}", index);
                  command.ExecuteNonQuery();
                }

                transaction.Commit();
              }
            }

            //
            // NOTE: Perform a huge amount of command creation and execution
            //       cycles for a better chance to trigger the bug.
            //
            for (int index = 0; index < 100000; index++)
            {
              //
              // NOTE: Purposely omit the 'using' block here to test
              //       command disposal via the garbage collector.
              //
              SQLiteCommand command = connection.CreateCommand();

              command.CommandText = "${sql(5)}";
              command.Parameters.Add(new SQLiteParameter(":xmin", 2));
              command.Parameters.Add(new SQLiteParameter(":xmax", 8));
              command.Parameters.Add(new SQLiteParameter(":ymin", 2));
              command.Parameters.Add(new SQLiteParameter(":ymax", 8));

              using (SQLiteDataReader reader = command.ExecuteReader())
              {
                while (reader.Read()) {
                  //
                  // do nothing.
                  //
                }
              }
            }

            connection.Close();
          }
        }
      }
    }
  }] true true true results errors System.Data.SQLite.dll]

  list $code $results \
      [expr {[info exists errors] ? $errors : ""}] \
      [expr {$code eq "Ok" ? [catch {
        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
Changes to Tests/tkt-bb4b04d457.eagle.
16
17
18
19
20
21
22
23

24
25
26
27
28
29
30
16
17
18
19
20
21
22

23
24
25
26
27
28
29
30







-
+







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

package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

runTest {test tkt-bb4b04d457-1.1 {TIMESTAMP column with Ticks} -setup {
runTest {test tkt-bb4b04d457-1.1 {} -setup {
  setupDb [set fileName tkt-bb4b04d457-1.1.db] "" Ticks Utc
} -body {
  set dateTime [object invoke -alias DateTime Parse 2011-11-29T12:34:56Z]
  set dateTime [$dateTime -alias ToUniversalTime]

  sql execute $db "CREATE TABLE t1(x TIMESTAMP NOT NULL);"

Deleted Tests/tkt-d1fb769a8e.eagle.
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132




































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
###############################################################################
#
# tkt-d1fb769a8e.eagle --
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################

package require Eagle
package require Eagle.Library
package require Eagle.Test

runTestPrologue

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

package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

runTest {test tkt-d1fb769a8e-1.1 {R*Tree virtual table creation} -setup {
  unset -nocomplain errors thread index count
  setupDb [set fileName tkt-d1fb769a8e-1.1.db]

  proc writeToDb { fileName count delay } {
    setupDb $fileName "" "" "" "" "" true false

    try {
      for {set index 1} {$index <= $count} {incr index} {
        after [expr {int(rand() * $delay)}]
        if {[catch {
          sql execute $db "CREATE TABLE t${index}(x);"
          sql execute $db "INSERT INTO t1 (x) VALUES(${index});"
        } error]} then {
          incr ::errors(0)
          tputs $::test_channel [appendArgs \
              \n "---- INSERT error: " \n\t $error \n]
        }
      }
    } finally {
      cleanupDb $fileName db true false false
    }
  }

  proc createRTreeTable { fileName count delay } {
    setupDb $fileName "" "" "" "" "" true false

    try {
      for {set index 1} {$index <= $count} {incr index} {
        after [expr {int(rand() * $delay)}]
        if {[catch {
          sql execute $db [subst {
            CREATE VIRTUAL TABLE IF NOT EXISTS test${index} USING rtree(
              id, minX, maxX, minY, maxY
            );
          }]
        } error]} then {
          incr ::errors(1)
          tputs $::test_channel [appendArgs \
              \n "---- CREATE VIRTUAL TABLE error: " \n\t $error \n]
        }
      }
    } finally {
      cleanupDb $fileName db true false false
    }
  }
} -body {
  set errors(0) 0;   # total number of INSERT errors.
  set errors(1) 0;   # total number of R*Tree errors.
  set count(0) 2;    # total number of test threads.
  set count(1) 1000; # total number of iterations per test thread.
  set count(2) 500;  # maximum milliseconds between test thread iterations.

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

  for {set index(0) 1} {$index(0) <= $count(0)} {incr index(0)} {
    set thread($index(0)) [object create -alias System.Threading.Thread \
        [list [expr {$index(0) % 2 == 0 ? "createRTreeTable" : "writeToDb"}] \
        $fileName $count(1) $count(2)] 1048576]

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

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

  foreach index(0) [array names thread] {
    if {[info exists thread($index(0))] && \
        [cleanupThread $thread($index(0))]} then {
      unset -nocomplain thread($index(0))
    }
  }

  list $errors(0) $errors(1)
} -cleanup {
  foreach index [array names thread] {
    if {[info exists thread($index)] && \
        [cleanupThread $thread($index)]} then {
      unset -nocomplain thread($index)
    }
  }

  rename createRTreeTable ""
  rename writeToDb ""

  catch {
    object removecallback [list \
        createRTreeTable $fileName $count(1) $count(2)]
  }
  catch {
    object removecallback [list \
        writeToDb $fileName $count(1) $count(2)]
  }

  cleanupDb $fileName

  unset -nocomplain errors thread index count db fileName
} -time true -constraints \
{eagle monoBug28 defineConstant.System.Data.SQLite.INTEROP_TEST_EXTENSION\
command.sql compile.DATA SQLite System.Data.SQLite} -result {0 0}}

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

runSQLiteTestEpilogue
runTestEpilogue
Changes to Tests/tkt-e1b2e0f769.eagle.
120
121
122
123
124
125
126
127
128
129



130
131
132
133
134
135
120
121
122
123
124
125
126



127
128
129
130
131
132
133
134
135







-
-
-
+
+
+






  set result1
} -cleanup {
  cleanupDb $fileName

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

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

runSQLiteTestEpilogue
runTestEpilogue
Changes to Tests/version.eagle.
25
26
27
28
29
30
31
32

33
34
35
36
37
38
39
25
26
27
28
29
30
31

32
33
34
35
36
37
38
39







-
+







#
# NOTE: For these unit tests to be useful and accurate, the following version
#       numbers must be manually kept synchronized with the version numbers for
#       the source code files, the built binaries, and the release packages.
#
set version(major)             1
set version(minor)             0
set version(build)            84; # NOTE: Incremented with each release.
set version(build)            83; # NOTE: Incremented with each release.
set version(revision)          0

###############################################################################
# ********************* END VOLATILE VERSION INFORMATION **********************
###############################################################################

#
Changes to exclude_bin.txt.
1
2
3
4
5
6
7
1
2
3
4

5
6




-


*.done
*.exp
*.lib
*.map
*.mda.config
*EnvDTE.*
*Microsoft.*
Changes to exclude_src.txt.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1
2
3
4

5
6

7
8
9

10
11
12
13
14
15
16




-


-



-







*.cache
*.chw
*.docstates
*.fossil
*.mistachkin.eagle
*.ncb
*.nupkg
*.pdb
*.suo
*.user
*.zip
.fossil-settings/*
_FOSSIL_
bin/*
Doc/Output/*
Externals/Eagle/bin/Eagle.dll
Externals/Eagle/bin/EagleShell.exe
Externals/Eagle/bin/SQLite.Interop.*
Externals/Eagle/bin/sqlite3.*
34
35
36
37
38
39
40
41
42

43
44
45
46
47
48
49
50
51
52
53
31
32
33
34
35
36
37

38
39
40
41
42
43
44
45
46
47
48
49
50







-

+











Externals/MSVCPP/*
Externals/NDoc3/*
Membership/*
Membership/obj/*
Membership/Profile/*
Membership/SiteMap/*
obj/*
Setup/Output/*
Setup/set_user_*.bat
Setup/Output/*
SQLite.Designer/obj/*
SQLite.Designer/Properties/*
SQLite.Designer/VSDesign/*
System.Data.SQLite.Linq/obj/*
System.Data.SQLite/obj/*
System.Data.SQLite/Properties/*
test/obj/*
testce/obj/*
testlinq/obj/*
tools/install/obj/*
www/*
Changes to readme.htm.
1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
1
2
3
4
5
6
7


8
9
10
11
12
13
14
15
16







-
-
+
+







<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title></title>
</head>
<body>
ADO.NET SQLite Data Provider<br />
Version 1.0.84.0 January 9, 2013<br />
Using <a href="http://www.sqlite.org/releaselog/3_7_15_2.html">SQLite 3.7.15.2</a><br />
Version 1.0.83.0 December XX, 2012 <font color="red">(release scheduled)</font><br />
Using <a href="http://www.sqlite.org/src/info/trunk">SQLite 3.7.15</a><br />
Originally written by Robert Simpson<br />
Released to the public domain, use at your own risk!<br />
Official provider website:&nbsp;<a href="http://system.data.sqlite.org/">http://system.data.sqlite.org/</a><br />
Legacy versions:&nbsp;<a href="http://sqlite.phxsoftware.com/">http://sqlite.phxsoftware.com/</a><br />
<br />
The current development version can be downloaded from <a href="http://system.data.sqlite.org/index.html/timeline?y=ci">
http://system.data.sqlite.org/index.html/timeline?y=ci</a>
142
143
144
145
146
147
148
149

150
151
152
153
154
155
156
142
143
144
145
146
147
148

149
150
151
152
153
154
155
156







-
+







app.config file:<br />
<pre>
&lt;configuration&gt;
    &lt;system.data&gt;
        &lt;DbProviderFactories&gt;
            &lt;remove invariant="System.Data.SQLite" /&gt;
            &lt;add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite"
                 type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite, Version=1.0.84.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" /&gt;
                 type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite, Version=1.0.83.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" /&gt;
        &lt;/DbProviderFactories&gt;
    &lt;/system.data&gt;
&lt;/configuration&gt;
</pre>
<p>
See the help documentation for further details on implementing both version-specific
(GAC enabled) and version independent DBProviderFactories support.
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199

200
201
202

203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223

224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
183
184
185
186
187
188
189










190
191
192

193
194
195
196
197



198
199
200
201
202
203
204
205
206
207
208
209
210

211
212
213
214

215



216
217
218
219
220
221
222







-
-
-
-
-
-
-
-
-
-
+


-
+




-
-
-













-
+



-

-
-
-







it to extend its functionality, but the core engine's source is not changed.</p>
<p>
</p>

<h2><b>Version History</b></h2>

<p>
    <b>1.0.84.0 - January 9, 2013</b>
</p>
<ul>
    <li>Updated to <a href="http://www.sqlite.org/releaselog/3_7_15_2.html">SQLite 3.7.15.2</a>.</li>
    <li>Explicitly dispose of all SQLiteCommand objects managed by the DbDataAdapter class. Fix for [6434e23a0f].</li>
    <li>Add Cancel method to the SQLiteConnection class to interrupt a long running query.</li>
    <li>Improve thread safety of the SQLiteLog.LogMessage method.</li>
</ul>
<p>
    <b>1.0.83.0 - December 29, 2012</b>
    <b>1.0.83.0 - December XX, 2012</b>
</p>
<ul>
    <li>Updated to <a href="http://www.sqlite.org/releaselog/3_7_15_1.html">SQLite 3.7.15.1</a>.</li>
    <li>Updated to <a href="http://www.sqlite.org/src/info/trunk">SQLite 3.7.15</a>.</li>
    <li>Add Visual Studio 2012 support to all the applicable solution/project files, their associated supporting files, and the test suite.</li>
    <li>Add Visual Studio 2012 support to the redesigned designer support installer.</li>
    <li>Allow opened connections to skip adding the extension functions included in the interop assembly via the new NoExtensionFunctions connection flag.</li>
    <li>Support loading of SQLite extensions via the new EnableExtensions and LoadExtension methods of the SQLiteConnection class. Pursuant to [17045010df].</li>
    <li>Remove one set of surrounding single or double quotes from property names and values parsed from the connection string. Fix for [b4cc611998].</li>
    <li>Modify parsing of connection strings to allow property names and values to be quoted.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>Add ParseViaFramework property to the SQLiteConnection class to allow the built-in (i.e. framework provided) connection string parser to be used when opening a connection. Pursuant to [b4cc611998].</li>
    <li>Add notifications before and after any connection is opened and closed, as well as other related notifications, via the new static Changed event.</li>
    <li>Add an overload of the SQLiteLog.LogMessage method that takes a single string parameter.</li>
    <li>Add an overload of the SQLiteConnection.LogMessage method that takes a SQLiteErrorCode parameter.</li>
    <li>All applicable calls into the SQLite core library now return a SQLiteErrorCode instead of an integer error code.</li>
    <li>Make sure the error code of the SQLiteException class gets serialized.</li>
    <li>Make the test project for the .NET Compact Framework more flexible.</li>
    <li>When available, the new sqlite3_errstr function from the core library is used to get the error message for a specific return code.</li>
    <li>The SetMemoryStatus, Shutdown, ResultCode, ExtendedResultCode, and SetAvRetry methods of the SQLiteConnection class now return a SQLiteErrorCode instead of an integer error code.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>The public constructor for the SQLiteException now takes a SQLiteErrorCode instead of an integer error code.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>The ErrorCode property of the SQLiteException is now an Int32, to allow the property inherited from the base class to be properly overridden.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>The ErrorCode field of the LogEventArgs is now an object instead of an integer.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>The names and messages associated with the SQLiteErrorCode enumeration values have been normalized to match those in the SQLite core library.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>Implement more robust locking semantics for the CriticalHandle derived classes when compiled for the .NET Compact Framework.</li>
    <li>Cache column indexes as they are looked up when using the SQLiteDataReader to improve performance.</li>
    <li>Cache column indexes are they are looked up when using the SQLiteDataReader to improve performance.</li>
    <li>Prevent the SQLiteConnection.Close method from throwing non-fatal exceptions during its disposal.</li>
    <li>Rename the interop assembly functions sqlite3_cursor_rowid, sqlite3_context_collcompare, sqlite3_context_collseq, sqlite3_cursor_rowid, and sqlite3_table_cursor to include an &quot;_interop&quot; suffix.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>Prevent the LastInsertRowId, MemoryUsed, and MemoryHighwater connection properties from throwing NotSupportedException when running on the .NET Compact Framework. Fix for [dd45aba387].</li>
    <li>Improve automatic detection of the sqlite3_close_v2 function when compiled to use the standard SQLite library.</li>
    <li>Add protection against ThreadAbortException asynchronously interrupting native resource initialization and finalization.</li>
    <li>Add native logging callback for use with the sqlite3_log function to the interop assembly, enabled via the INTEROP_LOG preprocessor definition.</li>
    <li>Add various diagnostic messages to the interop assembly, enabled via flags in the INTEROP_DEBUG preprocessor definition.</li>
    <li>Further enhancements to the build and test automation.</li>
    <li>Add test automation for the Windows CE binaries.</li>
</ul>
<p>
    <b>1.0.82.0 - September 3, 2012</b>
</p>
<ul>
    <li>Updated to <a href="http://www.sqlite.org/releaselog/3_7_14.html">SQLite 3.7.14</a>.</li>
Changes to test/AssemblyInfo.cs.
34
35
36
37
38
39
40
41
42


34
35
36
37
38
39
40


41
42







-
-
+
+
// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version 
//      Build Number
//      Revision
//
[assembly: AssemblyVersion("1.0.84.0")]
[assembly: AssemblyFileVersion("1.0.84.0")]
[assembly: AssemblyVersion("1.0.83.0")]
[assembly: AssemblyFileVersion("1.0.83.0")]
Changes to test/TestCases.cs.
18
19
20
21
22
23
24
25
26
27
28

29
30
31
32
33
34
35
18
19
20
21
22
23
24


25

26
27
28
29
30
31
32
33







-
-

-
+







  internal class TestCases : TestCaseBase
  {
    private const int NumThreads = 8;
    private const int ThreadTimeout = 60000;

    private List<string> droptables = new List<string>();
    private List<string> maydroptable = new List<string>();

#if !INTEROP_LOG
    private long logevents = 0;
#endif
    

    internal TestCases()
    {
    }

    internal TestCases(DbProviderFactory factory, string connectionString)
      : base(factory, connectionString)
1361
1362
1363
1364
1365
1366
1367
1368

1369
1370
1371
1372
1373
1374
1375
1359
1360
1361
1362
1363
1364
1365

1366
1367
1368
1369
1370
1371
1372
1373







-
+







      System.Threading.WaitHandle.WaitAll(events, ThreadTimeout);

      bool failed = false;
      Exception e = null;

      for (int n = 0; n < arr.Length; n++)
      {
        if (!arr[n].t.Join(ThreadTimeout / arr.Length))
        if (arr[n].t.Join(0) == false)
        {
          failed = true;
          arr[n].t.Abort();
          arr[n].t.Join();
        }
        if (arr[n].e != null) e = arr[n].e;
        arr[n].cnn.Dispose();
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1625
1626
1627
1628
1629
1630
1631

1632
1633
1634
1635
1636
1637
1638







-







        SQLiteErrorCode rc = cnn.ResultCode();
        SQLiteErrorCode xrc = cnn.ExtendedResultCode();

        cnn.Close();
      }
    }

#if !INTEROP_LOG
    //Logging EventHandler
    public void OnLogEvent(object sender, LogEventArgs logEvent)
    {
        object errorCode = logEvent.ErrorCode;
        string err_msg = logEvent.Message;
        logevents++;
    }
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1666
1667
1668
1669
1670
1671
1672

1673
1674
1675
1676
1677
1678
1679







-







            cnn.Close();

            // remove the log handler before the connection is closed.
            sqlite_fact.Log -= logHandler;

        }
    }
#endif

    /// <summary>
    /// Open a reader and then attempt to write to test the writer's command timeout property
    /// SQLite doesn't allow a write when a reader is active.
    /// *** NOTE AS OF 3.3.8 this test no longer blocks because SQLite now allows you to update table(s)
    /// while a reader is active on the same connection.  Therefore the timeout test is invalid
    /// </summary>
Changes to test/app.config.
1
2
3
4
5

6
7
8
1
2
3
4

5
6
7
8




-
+



<configuration>
  <system.data>
    <DbProviderFactories>
      <remove invariant="System.Data.SQLite" />
      <add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite, Version=1.0.84.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" />
      <add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite, Version=1.0.83.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" />
    </DbProviderFactories>
  </system.data>
</configuration>
Changes to test/test.2005.csproj.
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
78
79
80
81
82
83
84

85
86
87
88
89
90
91







-







    <EmbeddedResource Include="TestCasesDialog.resx">
      <DependentUpon>TestCasesDialog.cs</DependentUpon>
    </EmbeddedResource>
  </ItemGroup>
  <ItemGroup>
    <None Include="app.config" />
  </ItemGroup>
  <Import Project="$(SQLiteNetDir)\System.Data.SQLite\System.Data.SQLite.Properties.targets" />
  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
Changes to test/test.2008.csproj.
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
79
80
81
82
83
84
85

86
87
88
89
90
91
92







-







    <EmbeddedResource Include="TestCasesDialog.resx">
      <DependentUpon>TestCasesDialog.cs</DependentUpon>
    </EmbeddedResource>
  </ItemGroup>
  <ItemGroup>
    <None Include="app.config" />
  </ItemGroup>
  <Import Project="$(SQLiteNetDir)\System.Data.SQLite\System.Data.SQLite.Properties.targets" />
  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
Changes to test/test.2010.csproj.
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
80
81
82
83
84
85
86

87
88
89
90
91
92
93







-







    <EmbeddedResource Include="TestCasesDialog.resx">
      <DependentUpon>TestCasesDialog.cs</DependentUpon>
    </EmbeddedResource>
  </ItemGroup>
  <ItemGroup>
    <None Include="app.config" />
  </ItemGroup>
  <Import Project="$(SQLiteNetDir)\System.Data.SQLite\System.Data.SQLite.Properties.targets" />
  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
Changes to test/test.2012.csproj.
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
79
80
81
82
83
84
85

86
87
88
89
90
91
92







-







    <EmbeddedResource Include="TestCasesDialog.resx">
      <DependentUpon>TestCasesDialog.cs</DependentUpon>
    </EmbeddedResource>
  </ItemGroup>
  <ItemGroup>
    <None Include="app.config" />
  </ItemGroup>
  <Import Project="$(SQLiteNetDir)\System.Data.SQLite\System.Data.SQLite.Properties.targets" />
  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
Changes to testce/AssemblyInfo.cs.
34
35
36
37
38
39
40
41
42


43
34
35
36
37
38
39
40


41
42
43







-
-
+
+

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version 
//      Build Number
//      Revision
//
[assembly: AssemblyVersion("1.0.84.0")]
// [assembly: AssemblyFileVersion("1.0.84.0")]
[assembly: AssemblyVersion("1.0.83.0")]
// [assembly: AssemblyFileVersion("1.0.83.0")]

Changes to testlinq/2008/App.config.
1
2
3
4
5
6

7
8
9
10
11
12
1
2
3
4
5

6
7
8
9
10
11
12





-
+






<?xml version="1.0"?>
<configuration>
  <system.data>
    <DbProviderFactories>
      <remove invariant="System.Data.SQLite" />
      <add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite, Version=1.0.84.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" />
      <add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite, Version=1.0.83.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" />
    </DbProviderFactories>
  </system.data>
  <connectionStrings>
    <add name="northwindEFEntities" connectionString="metadata=res://*/NorthwindModel2008.csdl|res://*/NorthwindModel2008.ssdl|res://*/NorthwindModel2008.msl;provider=System.Data.SQLite;provider connection string=&quot;data source=.\northwindEF.db&quot;" providerName="System.Data.EntityClient" />
  </connectionStrings>
</configuration>
Changes to testlinq/2010/App.config.
1
2
3
4
5
6

7
8
9
10
11
12
1
2
3
4
5

6
7
8
9
10
11
12





-
+






<?xml version="1.0"?>
<configuration>
  <system.data>
    <DbProviderFactories>
      <remove invariant="System.Data.SQLite" />
      <add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite, Version=1.0.84.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" />
      <add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite, Version=1.0.83.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" />
    </DbProviderFactories>
  </system.data>
  <connectionStrings>
    <add name="northwindEFEntities" connectionString="metadata=res://*/NorthwindModel2010.csdl|res://*/NorthwindModel2010.ssdl|res://*/NorthwindModel2010.msl;provider=System.Data.SQLite;provider connection string=&quot;data source=.\northwindEF.db&quot;" providerName="System.Data.EntityClient" />
  </connectionStrings>
</configuration>
Changes to testlinq/2012/App.config.
1
2
3
4
5
6

7
8
9
10
11
12
1
2
3
4
5

6
7
8
9
10
11
12





-
+






<?xml version="1.0"?>
<configuration>
  <system.data>
    <DbProviderFactories>
      <remove invariant="System.Data.SQLite" />
      <add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite, Version=1.0.84.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" />
      <add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite, Version=1.0.83.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" />
    </DbProviderFactories>
  </system.data>
  <connectionStrings>
    <add name="northwindEFEntities" connectionString="metadata=res://*/NorthwindModel2012.csdl|res://*/NorthwindModel2012.ssdl|res://*/NorthwindModel2012.msl;provider=System.Data.SQLite;provider connection string=&quot;data source=.\northwindEF.db&quot;" providerName="System.Data.EntityClient" />
  </connectionStrings>
</configuration>
Changes to testlinq/Program.cs.
322
323
324
325
326
327
328
329

330
331
332
333
334
335
336
322
323
324
325
326
327
328

329
330
331
332
333
334
335
336







-
+







      }

    private static int OldTests()
    {
      using (northwindEFEntities db = new northwindEFEntities())
      {
        {
          string entitySQL = "SELECT VALUE o FROM Orders AS o WHERE SQLite.DatePart('yyyy', o.OrderDate) = 1997 ORDER BY o.OrderID;";
          string entitySQL = "SELECT VALUE o FROM Orders AS o WHERE SQLite.DatePart('yyyy', o.OrderDate) = 1997;";
          ObjectQuery<Orders> query = db.CreateQuery<Orders>(entitySQL);

          foreach (Orders o in query)
          {
            Console.WriteLine(o.ShipPostalCode);
          }
        }
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
355
356
357
358
359
360
361

362
363
364
365
366
367
368







-







          Console.WriteLine(c.CompanyName);
        }

        {
          DateTime dt = new DateTime(1997, 1, 1);
          var query = from order in db.Orders
                      where order.OrderDate < dt
                      orderby order.OrderID
                      select order;

          foreach (Orders o in query)
          {
            Console.WriteLine(o.OrderDate.ToString());
          }
        }
397
398
399
400
401
402
403
404

405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426

427
428
429
430
431
432
433
434
435
436

437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
396
397
398
399
400
401
402

403

404
405
406
407
408
409
410
411
412
413

414
415
416
417
418
419
420
421
422

423
424
425
426
427
428
429
430
431
432

433
434
435
436
437
438
439
440
441
442
443
444
445

446
447
448
449
450
451
452







-
+
-










-









-
+









-
+












-








          db.DeleteObject(cust);
          db.SaveChanges();
        }

        {
          var query = db.Customers.Where(cust => cust.Country == "Denmark")
                          .SelectMany(cust => cust.Orders.Where(o => o.Freight > 5))
                          .SelectMany(cust => cust.Orders.Where(o => o.Freight > 5));
                          .OrderBy(o => o.Customers.CustomerID);

          foreach (Orders c in query)
          {
            Console.WriteLine(c.Freight);
          }
        }

        {
          var query = from c in db.Customers
                      where c.Orders.Any(o => o.OrderDate.HasValue == true && o.OrderDate.Value.Year == 1997)
                      orderby c.CustomerID
                      select c;

          foreach (Customers c in query)
          {
            Console.WriteLine(c.CompanyName);
          }
        }

        {
          string entitySQL = "SELECT VALUE o FROM Orders AS o WHERE o.Customers.Country <> 'UK' AND o.Customers.Country <> 'Mexico' AND Year(o.OrderDate) = 1997 ORDER BY o.OrderID;";
          string entitySQL = "SELECT VALUE o FROM Orders AS o WHERE o.Customers.Country <> 'UK' AND o.Customers.Country <> 'Mexico' AND Year(o.OrderDate) = 1997;";
          ObjectQuery<Orders> query = db.CreateQuery<Orders>(entitySQL);

          foreach (Orders o in query)
          {
            Console.WriteLine(o.ShipPostalCode);
          }
        }

        {
          string entitySQL = "SELECT VALUE o FROM Orders AS o WHERE NewGuid() <> NewGuid() ORDER BY o.OrderID;";
          string entitySQL = "SELECT VALUE o FROM Orders AS o WHERE NewGuid() <> NewGuid();";
          ObjectQuery<Orders> query = db.CreateQuery<Orders>(entitySQL);

          foreach (Orders o in query)
          {
            Console.WriteLine(o.ShipPostalCode);
          }
        }

        // This query requires SQLite 3.6.2 to function correctly
        {
          var query = from p in db.Products
                      where p.OrderDetails.Count(od => od.Orders.Customers.Country == p.Suppliers.Country) > 2
                      orderby p.ProductID
                      select p;

          foreach (Products p in query)
          {
            Console.WriteLine(p.ProductName);
          }
        }
Changes to testlinq/Properties/AssemblyInfo.cs.
37
38
39
40
41
42
43
44
45


37
38
39
40
41
42
43


44
45







-
-
+
+
//      Minor Version 
//      Build Number
//      Revision
//
// You can specify all the values or you can default the Build and Revision Numbers 
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.84.0")]
[assembly: AssemblyFileVersion("1.0.84.0")]
[assembly: AssemblyVersion("1.0.83.0")]
[assembly: AssemblyFileVersion("1.0.83.0")]
Changes to tools/install/Installer.cs.
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
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







-
















-















-







        string fileName,           /* in */
        string invariant,          /* in */
        string name,               /* in */
        string description,        /* in */
        string typeName,           /* in */
        AssemblyName assemblyName, /* in */
        object clientData,         /* in */
        bool perUser,              /* in */
        bool wow64,                /* in */
        bool throwOnMissing,       /* in */
        bool whatIf,               /* in */
        bool verbose,              /* in */
        ref bool saved,            /* out */
        ref string error           /* out */
    );

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

    internal delegate bool FrameworkRegistryCallback(
        Installer.MockRegistryKey rootKey, /* in */
        string frameworkName,              /* in */
        Version frameworkVersion,          /* in */
        string platformName,               /* in */
        object clientData,                 /* in */
        bool perUser,                      /* in */
        bool wow64,                        /* in */
        bool throwOnMissing,               /* in */
        bool whatIf,                       /* in */
        bool verbose,                      /* in */
        ref string error                   /* out */
    );

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

    internal delegate bool VisualStudioRegistryCallback(
        Installer.MockRegistryKey rootKey, /* in */
        Version vsVersion,                 /* in */
        string suffix,                     /* in, optional */
        Installer.Package package,         /* in */
        object clientData,                 /* in */
        bool perUser,                      /* in */
        bool wow64,                        /* in */
        bool throwOnMissing,               /* in */
        bool whatIf,                       /* in */
        bool verbose,                      /* in */
        ref string error                   /* out */
    );
    #endregion
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966

3967
3968
3969
3970
3971
3972
3973
3945
3946
3947
3948
3949
3950
3951

3952
3953
3954






3955

3956
3957
3958
3959
3960
3961
3962
3963







-



-
-
-
-
-
-

-
+







            return Object.ReferenceEquals(rootKey, registry.CurrentUser) ||
                Object.ReferenceEquals(rootKey, registry.LocalMachine);
        }

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

        private static string GetRootKeyName(
            bool perUser,
            bool wow64
            )
        {
            //
            // BUGFIX: Apparently, the per-user registry hive does not use
            //         the "Wow6432Node" node to store settings for 32-bit
            //         applications running on a 64-bit operating system.
            //         Ticket [a0677309f0] has further details.
            //
            return String.Format("{0}{1}", RootKeyName,
                !perUser && wow64 && Is64BitProcess() ?
                wow64 && Is64BitProcess() ?
                    "\\" + Wow64SubKeyName : String.Empty);
        }

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

        private static string GetSystemDirectory(
            bool wow64
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111

4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128

4129
4130
4131
4132
4133
4134
4135
4089
4090
4091
4092
4093
4094
4095

4096
4097
4098
4099

4100
4101
4102
4103
4104
4105
4106
4107
4108

4109
4110
4111
4112
4113
4114
4115

4116
4117
4118
4119
4120
4121
4122
4123







-




-
+








-







-
+







        }
        #endregion

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

        #region .NET Framework Handling
        private static string GetFrameworkRootKeyName(
            bool perUser,
            bool wow64
            )
        {
            return String.Format("{0}\\Microsoft\\.NETFramework",
                GetRootKeyName(perUser, wow64));
                GetRootKeyName(wow64));
        }

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

        private static string GetFrameworkKeyName(
            string frameworkName,
            Version frameworkVersion,
            string platformName,
            bool perUser,
            bool wow64
            )
        {
            string format = !String.IsNullOrEmpty(platformName) ?
                "{0}\\Microsoft\\{1}\\v{2}\\{3}" :
                "{0}\\Microsoft\\{1}\\v{2}";

            return String.Format(format, GetRootKeyName(perUser, wow64),
            return String.Format(format, GetRootKeyName(wow64),
                frameworkName, frameworkVersion, platformName);
        }

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

        private static string GetImageRuntimeVersion(
            string fileName
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167


4168
4169
4170
4171
4172
4173
4174
4140
4141
4142
4143
4144
4145
4146

4147
4148
4149
4150
4151
4152


4153
4154
4155
4156
4157
4158
4159
4160
4161







-






-
-
+
+







        }

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

        private static string GetFrameworkDirectory(
            MockRegistryKey rootKey,
            Version frameworkVersion,
            bool perUser,
            bool wow64,
            bool whatIf,
            bool verbose
            )
        {
            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, GetFrameworkRootKeyName(perUser, wow64),
                    false, whatIf, verbose))
                    rootKey, GetFrameworkRootKeyName(wow64), false,
                    whatIf, verbose))
            {
                if (key == null)
                    return null;

                object value = RegistryHelper.GetValue(
                    key, "InstallRoot", null, whatIf, verbose);

4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280

4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293

4294
4295
4296
4297
4298
4299
4300
4301
4253
4254
4255
4256
4257
4258
4259

4260
4261
4262
4263
4264
4265

4266

4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277

4278

4279
4280
4281
4282
4283
4284
4285







-






-
+
-











-
+
-







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

        private static bool HaveFrameworkDirectory(
            MockRegistryKey rootKey,
            string frameworkName,
            Version frameworkVersion,
            string platformName,
            bool perUser,
            bool wow64,
            bool whatIf,
            bool verbose
            )
        {
            string keyName = GetFrameworkKeyName(
                frameworkName, frameworkVersion, platformName, perUser,
                frameworkName, frameworkVersion, platformName, wow64);
                wow64);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, false, whatIf, verbose))
            {
                if (key == null)
                    return false;

                if (platformName != null) // NOTE: Skip non-desktop.
                    return true;

                string directory = GetFrameworkDirectory(
                    rootKey, frameworkVersion, perUser, wow64, whatIf,
                    rootKey, frameworkVersion, wow64, whatIf, verbose);
                    verbose);

                if (String.IsNullOrEmpty(directory))
                    return false;

                if (!Directory.Exists(directory))
                    return false;

4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326

4327
4328
4329
4330
4331
4332
4333
4334
4296
4297
4298
4299
4300
4301
4302

4303
4304
4305
4306
4307
4308

4309

4310
4311
4312
4313
4314
4315
4316







-






-
+
-







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

        private static bool HaveFrameworkRegistry(
            MockRegistryKey rootKey,
            string frameworkName,
            Version frameworkVersion,
            string platformName,
            bool perUser,
            bool wow64,
            bool whatIf,
            bool verbose
            )
        {
            string keyName = GetFrameworkKeyName(
                frameworkName, frameworkVersion, platformName, perUser,
                frameworkName, frameworkVersion, platformName, wow64);
                wow64);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, false, whatIf, verbose))
            {
                if (key == null)
                    return false;

4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4337
4338
4339
4340
4341
4342
4343

4344
4345
4346
4347
4348
4349
4350







-







            string version, /* NOTE: Optional. */
            string invariant,
            string name,
            string description,
            string typeName,
            AssemblyName assemblyName,
            object clientData,
            bool perUser,
            bool wow64,
            bool throwOnMissing,
            bool whatIf,
            bool verbose,
            ref bool saved,
            ref string error
            )
4469
4470
4471
4472
4473
4474
4475
4476

4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490

4491
4492
4493
4494
4495
4496
4497
4498
4450
4451
4452
4453
4454
4455
4456

4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470

4471

4472
4473
4474
4475
4476
4477
4478







-
+













-
+
-







                        "frameworkName = {0}, frameworkVersion = {1}, " +
                        "platformName = {2}", ForDisplay(frameworkName),
                        ForDisplay(frameworkVersion),
                        ForDisplay(platformName)), traceCategory);

                    if (!HaveFrameworkDirectory(
                            rootKey, frameworkName, frameworkVersion,
                            platformName, perUser, wow64, whatIf, verbose))
                            platformName, wow64, whatIf, verbose))
                    {
                        TraceOps.DebugAndTrace(TracePriority.Low,
                            debugCallback, traceCallback,
                            ".NET Framework directory not found, skipping...",
                            traceCategory);

                        continue;
                    }

                    if (callback == null)
                        continue;

                    string directory = GetFrameworkDirectory(
                        rootKey, frameworkVersion, perUser, wow64, whatIf,
                        rootKey, frameworkVersion, wow64, whatIf, verbose);
                        verbose);

                    if (String.IsNullOrEmpty(directory))
                    {
                        TraceOps.DebugAndTrace(TracePriority.Low,
                            debugCallback, traceCallback, String.Format(
                            ".NET Framework {0} directory is invalid, " +
                            "skipping...", ForDisplay(frameworkVersion)),
4527
4528
4529
4530
4531
4532
4533
4534
4535


4536
4537
4538
4539
4540
4541
4542
4543
4507
4508
4509
4510
4511
4512
4513


4514
4515

4516
4517
4518
4519
4520
4521
4522







-
-
+
+
-







                        continue;
                    }

                    bool localSaved = false;

                    if (!callback(
                            fileName, invariant, name, description, typeName,
                            assemblyName, clientData, perUser, wow64,
                            throwOnMissing, whatIf, verbose, ref localSaved,
                            assemblyName, clientData, wow64, throwOnMissing,
                            whatIf, verbose, ref localSaved, ref error))
                            ref error))
                    {
                        return false;
                    }
                    else
                    {
                        if (localSaved && !saved)
                            saved = true;
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4539
4540
4541
4542
4543
4544
4545

4546
4547
4548
4549
4550
4551
4552







-







        [MethodImpl(MethodImplOptions.NoInlining)]
        private static bool ForEachFrameworkRegistry(
            MockRegistry registry,
            FrameworkList frameworkList,
            FrameworkRegistryCallback callback,
            string version, /* NOTE: Optional. */
            object clientData,
            bool perUser,
            bool wow64,
            bool throwOnMissing,
            bool whatIf,
            bool verbose,
            ref string error
            )
        {
4666
4667
4668
4669
4670
4671
4672
4673

4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689


4690
4691
4692
4693
4694
4695
4696
4644
4645
4646
4647
4648
4649
4650

4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665


4666
4667
4668
4669
4670
4671
4672
4673
4674







-
+














-
-
+
+







                        "frameworkName = {0}, frameworkVersion = {1}, " +
                        "platformName = {2}", ForDisplay(frameworkName),
                        ForDisplay(frameworkVersion),
                        ForDisplay(platformName)), traceCategory);

                    if (!HaveFrameworkRegistry(
                            rootKey, frameworkName, frameworkVersion,
                            platformName, perUser, wow64, whatIf, verbose))
                            platformName, wow64, whatIf, verbose))
                    {
                        TraceOps.DebugAndTrace(TracePriority.Low,
                            debugCallback, traceCallback,
                            ".NET Framework registry not found, skipping...",
                            traceCategory);

                        continue;
                    }

                    if (callback == null)
                        continue;

                    if (!callback(
                            rootKey, frameworkName, frameworkVersion,
                            platformName, clientData, perUser, wow64,
                            throwOnMissing, whatIf, verbose, ref error))
                            platformName, clientData, wow64, throwOnMissing,
                            whatIf, verbose, ref error))
                    {
                        return false;
                    }
                }
            }

            return true;
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748

4749
4750
4751
4752
4753
4754
4755
4710
4711
4712
4713
4714
4715
4716

4717
4718
4719
4720
4721
4722
4723
4724

4725
4726
4727
4728
4729
4730
4731
4732







-








-
+








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

        private static bool HaveVsVersion(
            MockRegistryKey rootKey,
            Version vsVersion,
            string suffix,
            bool perUser,
            bool wow64,
            bool whatIf,
            bool verbose
            )
        {
            if (vsVersion == null)
                return false;

            string keyName = GetVsKeyName(vsVersion, suffix, perUser, wow64);
            string keyName = GetVsKeyName(vsVersion, suffix, wow64);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, false, whatIf, verbose))
            {
                if (key == null)
                    return false;

4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4760
4761
4762
4763
4764
4765
4766

4767
4768
4769
4770
4771
4772
4773







-







        private static bool ForEachVsVersionRegistry(
            MockRegistry registry,
            VsList vsList,
            VisualStudioRegistryCallback callback,
            string suffix,
            Package package,
            object clientData,
            bool perUser,
            bool wow64,
            bool throwOnMissing,
            bool whatIf,
            bool verbose,
            ref string error
            )
        {
4831
4832
4833
4834
4835
4836
4837
4838

4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854

4855
4856
4857
4858
4859
4860
4861
4862
4807
4808
4809
4810
4811
4812
4813

4814

4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828

4829

4830
4831
4832
4833
4834
4835
4836







-
+
-














-
+
-







            {
                TraceOps.DebugAndTrace(TracePriority.Lower,
                    debugCallback, traceCallback, String.Format(
                    "vsVersion = {0}", ForDisplay(vsVersion)),
                    traceCategory);

                if (!HaveVsVersion(
                        rootKey, vsVersion, suffix, perUser, wow64, whatIf,
                        rootKey, vsVersion, suffix, wow64, whatIf, verbose))
                        verbose))
                {
                    TraceOps.DebugAndTrace(TracePriority.Low,
                        debugCallback, traceCallback,
                        "Visual Studio version not found, skipping...",
                        traceCategory);

                    continue;
                }

                if (callback == null)
                    continue;

                if (!callback(
                        rootKey, vsVersion, suffix, package, clientData,
                        perUser, wow64, throwOnMissing, whatIf, verbose,
                        wow64, throwOnMissing, whatIf, verbose, ref error))
                        ref error))
                {
                    return false;
                }
            }

            return true;
        }
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5007
5008
5009
5010
5011
5012
5013

5014
5015
5016
5017
5018
5019
5020







-







            string fileName,
            string invariant,
            string name,
            string description,
            string typeName,
            AssemblyName assemblyName,
            object clientData,
            bool perUser,
            bool wow64,
            bool throwOnMissing,
            bool whatIf,
            bool verbose,
            ref bool saved,
            ref string error
            )
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095

5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116

5117
5118
5119
5120
5121
5122
5123
5124
5048
5049
5050
5051
5052
5053
5054

5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066

5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079

5080
5081
5082
5083
5084
5085
5086

5087

5088
5089
5090
5091
5092
5093
5094







-












-
+












-







-
+
-







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

        #region Assembly Folders Handling
        private static string GetAssemblyFoldersKeyName(
            string frameworkName,
            Version frameworkVersion,
            string platformName,
            bool perUser,
            bool wow64
            )
        {
            //
            // NOTE: This registry key appears to always be 32-bit only
            //       (i.e. probably because it is only used by Visual
            //       Studio, which is currently always 32-bit only).
            //
            string format = !String.IsNullOrEmpty(platformName) ?
                "{0}\\Microsoft\\{1}\\v{2}\\{3}\\AssemblyFoldersEx" :
                "{0}\\Microsoft\\{1}\\v{2}\\AssemblyFoldersEx";

            return String.Format(format, GetRootKeyName(perUser, wow64),
            return String.Format(format, GetRootKeyName(wow64),
                frameworkName, frameworkVersion, platformName);
        }

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

        private static bool AddToAssemblyFolders(
            MockRegistryKey rootKey,
            string frameworkName,
            Version frameworkVersion,
            string platformName,
            string subKeyName,
            string directory,
            bool perUser,
            bool wow64,
            bool whatIf,
            bool verbose,
            ref string error
            )
        {
            string keyName = GetAssemblyFoldersKeyName(
                frameworkName, frameworkVersion, platformName, perUser,
                frameworkName, frameworkVersion, platformName, wow64);
                wow64);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, true, whatIf, verbose))
            {
                if (key == null)
                {
                    error = String.Format(
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168

5169
5170
5171
5172
5173
5174
5175
5176
5122
5123
5124
5125
5126
5127
5128

5129
5130
5131
5132
5133
5134
5135
5136

5137

5138
5139
5140
5141
5142
5143
5144







-








-
+
-








        private static bool RemoveFromAssemblyFolders(
            MockRegistryKey rootKey,
            string frameworkName,
            Version frameworkVersion,
            string platformName,
            string subKeyName,
            bool perUser,
            bool wow64,
            bool throwOnMissing,
            bool whatIf,
            bool verbose,
            ref string error
            )
        {
            string keyName = GetAssemblyFoldersKeyName(
                frameworkName, frameworkVersion, platformName, perUser,
                frameworkName, frameworkVersion, platformName, wow64);
                wow64);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, true, whatIf, verbose))
            {
                if (key == null)
                {
                    error = String.Format(
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218

5219
5220
5221
5222

5223
5224
5225
5226
5227
5228
5229
5230


5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244

5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260

5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291

5292
5293
5294
5295
5296
5297
5298
5159
5160
5161
5162
5163
5164
5165

5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184

5185
5186
5187
5188

5189

5190
5191
5192
5193
5194


5195
5196
5197
5198
5199
5200
5201
5202
5203
5204

5205
5206
5207
5208

5209
5210
5211
5212
5213
5214
5215
5216

5217
5218
5219
5220
5221
5222
5223

5224

5225
5226
5227
5228
5229
5230
5231
5232
5233
5234

5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252

5253
5254
5255
5256
5257
5258
5259
5260







-



















-
+



-
+
-





-
-
+
+








-




-
+







-







-
+
-










-


















-
+








        private static bool ProcessAssemblyFolders(
            MockRegistryKey rootKey,
            string frameworkName,
            Version frameworkVersion,
            string platformName,
            object clientData,
            bool perUser,
            bool wow64,
            bool throwOnMissing,
            bool whatIf,
            bool verbose,
            ref string error
            )
        {
            AnyPair<string, bool> pair = clientData as AnyPair<string, bool>;

            if (pair == null)
            {
                error = "invalid framework callback data";
                return false;
            }

            if (pair.Y)
            {
                return RemoveFromAssemblyFolders(
                    rootKey, frameworkName, frameworkVersion, platformName,
                    LegacyProjectName, perUser, wow64, false, whatIf, verbose,
                    LegacyProjectName, wow64, false, whatIf, verbose,
                    ref error) &&
                AddToAssemblyFolders(
                    rootKey, frameworkName, frameworkVersion, platformName,
                    ProjectName, pair.X, perUser, wow64, whatIf, verbose,
                    ProjectName, pair.X, wow64, whatIf, verbose, ref error);
                    ref error);
            }
            else
            {
                return RemoveFromAssemblyFolders(
                    rootKey, frameworkName, frameworkVersion, platformName,
                    ProjectName, perUser, wow64, throwOnMissing, whatIf,
                    verbose, ref error);
                    ProjectName, wow64, throwOnMissing, whatIf, verbose,
                    ref error);
            }
        }
        #endregion

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

        #region Visual Studio Handling
        private static string GetVsRootKeyName(
            bool perUser,
            bool wow64
            )
        {
            return String.Format("{0}\\Microsoft\\VisualStudio",
                GetRootKeyName(perUser, wow64));
                GetRootKeyName(wow64));
        }

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

        private static string GetVsKeyName(
            Version vsVersion,
            string suffix,
            bool perUser,
            bool wow64
            )
        {
            if (vsVersion == null)
                return null;

            return String.Format(
                "{0}\\{1}{2}", GetVsRootKeyName(perUser, wow64), vsVersion,
                "{0}\\{1}{2}", GetVsRootKeyName(wow64), vsVersion, suffix);
                suffix);
        }

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

        #region Visual Studio Data Source Handling
        private static bool AddVsDataSource(
            MockRegistryKey rootKey,
            Version vsVersion,
            string suffix,
            Package package,
            bool perUser,
            bool wow64,
            bool whatIf,
            bool verbose,
            ref string error
            )
        {
            if (vsVersion == null)
            {
                error = "invalid VS version";
                return false;
            }

            if (package == null)
            {
                error = "invalid VS package";
                return false;
            }

            string keyName = GetVsKeyName(vsVersion, suffix, perUser, wow64);
            string keyName = GetVsKeyName(vsVersion, suffix, wow64);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, false, whatIf, verbose))
            {
                if (key == null)
                {
                    error = String.Format(
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381

5382
5383
5384
5385
5386
5387
5388
5317
5318
5319
5320
5321
5322
5323

5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341

5342
5343
5344
5345
5346
5347
5348
5349







-


















-
+







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

        private static bool RemoveVsDataSource(
            MockRegistryKey rootKey,
            Version vsVersion,
            string suffix,
            Package package,
            bool perUser,
            bool wow64,
            bool whatIf,
            bool verbose,
            ref string error
            )
        {
            if (vsVersion == null)
            {
                error = "invalid VS version";
                return false;
            }

            if (package == null)
            {
                error = "invalid VS package";
                return false;
            }

            string keyName = GetVsKeyName(vsVersion, suffix, perUser, wow64);
            string keyName = GetVsKeyName(vsVersion, suffix, wow64);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, false, whatIf, verbose))
            {
                if (key == null)
                {
                    error = String.Format(
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5378
5379
5380
5381
5382
5383
5384

5385
5386
5387
5388
5389
5390
5391







-








        private static bool ProcessVsDataSource(
            MockRegistryKey rootKey,
            Version vsVersion,
            string suffix,
            Package package,
            object clientData,
            bool perUser,
            bool wow64,
            bool throwOnMissing,
            bool whatIf,
            bool verbose,
            ref string error
            )
        {
5442
5443
5444
5445
5446
5447
5448
5449
5450


5451
5452
5453
5454
5455
5456


5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489

5490
5491
5492
5493
5494
5495
5496
5402
5403
5404
5405
5406
5407
5408


5409
5410
5411
5412
5413
5414


5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429

5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447

5448
5449
5450
5451
5452
5453
5454
5455







-
-
+
+




-
-
+
+













-


















-
+







                error = "invalid VS callback data";
                return false;
            }

            if (pair.Y)
            {
                return AddVsDataSource(
                    rootKey, vsVersion, suffix, package, perUser, wow64,
                    whatIf, verbose, ref error);
                    rootKey, vsVersion, suffix, package, wow64, whatIf,
                    verbose, ref error);
            }
            else
            {
                return RemoveVsDataSource(
                    rootKey, vsVersion, suffix, package, perUser, wow64,
                    whatIf, verbose, ref error);
                    rootKey, vsVersion, suffix, package, wow64, whatIf,
                    verbose, ref error);
            }
        }
        #endregion

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

        #region Visual Studio Data Provider Handling
        private static bool AddVsDataProvider(
            MockRegistryKey rootKey,
            Version vsVersion,
            string suffix,
            Package package,
            string fileName,
            bool perUser,
            bool wow64,
            bool whatIf,
            bool verbose,
            ref string error
            )
        {
            if (vsVersion == null)
            {
                error = "invalid VS version";
                return false;
            }

            if (package == null)
            {
                error = "invalid VS package";
                return false;
            }

            string keyName = GetVsKeyName(vsVersion, suffix, perUser, wow64);
            string keyName = GetVsKeyName(vsVersion, suffix, wow64);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, false, whatIf, verbose))
            {
                if (key == null)
                {
                    error = String.Format(
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619

5620
5621
5622
5623
5624
5625
5626
5558
5559
5560
5561
5562
5563
5564

5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576

5577
5578
5579
5580
5581
5582
5583
5584







-












-
+







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

        private static bool RemoveVsDataProvider(
            MockRegistryKey rootKey,
            Version vsVersion,
            string suffix,
            Package package,
            bool perUser,
            bool wow64,
            bool whatIf,
            bool verbose,
            ref string error
            )
        {
            if (vsVersion == null)
            {
                error = "invalid VS version";
                return false;
            }

            string keyName = GetVsKeyName(vsVersion, suffix, perUser, wow64);
            string keyName = GetVsKeyName(vsVersion, suffix, wow64);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, false, whatIf, verbose))
            {
                if (key == null)
                {
                    error = String.Format(
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682


5683
5684
5685
5686
5687
5688


5689
5690
5691
5692
5693
5694
5695
5613
5614
5615
5616
5617
5618
5619

5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637


5638
5639
5640
5641
5642
5643


5644
5645
5646
5647
5648
5649
5650
5651
5652







-


















-
-
+
+




-
-
+
+








        private static bool ProcessVsDataProvider(
            MockRegistryKey rootKey,
            Version vsVersion,
            string suffix,
            Package package,
            object clientData,
            bool perUser,
            bool wow64,
            bool throwOnMissing,
            bool whatIf,
            bool verbose,
            ref string error
            )
        {
            AnyPair<string, bool> pair = clientData as AnyPair<string, bool>;

            if (pair == null)
            {
                error = "invalid VS callback data";
                return false;
            }

            if (pair.Y)
            {
                return AddVsDataProvider(
                    rootKey, vsVersion, suffix, package, pair.X, perUser,
                    wow64, whatIf, verbose, ref error);
                    rootKey, vsVersion, suffix, package, pair.X, wow64,
                    whatIf, verbose, ref error);
            }
            else
            {
                return RemoveVsDataProvider(
                    rootKey, vsVersion, suffix, package, perUser, wow64,
                    whatIf, verbose, ref error);
                    rootKey, vsVersion, suffix, package, wow64, whatIf,
                    verbose, ref error);
            }
        }
        #endregion

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

        #region Visual Studio Package Handling
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753

5754
5755
5756
5757
5758
5759
5760
5684
5685
5686
5687
5688
5689
5690

5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708

5709
5710
5711
5712
5713
5714
5715
5716







-


















-
+








        private static bool AddVsPackage(
            MockRegistryKey rootKey,
            Version vsVersion,
            string suffix,
            Package package,
            string fileName,
            bool perUser,
            bool wow64,
            bool whatIf,
            bool verbose,
            ref string error
            )
        {
            if (vsVersion == null)
            {
                error = "invalid VS version";
                return false;
            }

            if (package == null)
            {
                error = "invalid VS package";
                return false;
            }

            string keyName = GetVsKeyName(vsVersion, suffix, perUser, wow64);
            string keyName = GetVsKeyName(vsVersion, suffix, wow64);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, false, whatIf, verbose))
            {
                if (key == null)
                {
                    error = String.Format(
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951

5952
5953
5954
5955
5956
5957
5958
5880
5881
5882
5883
5884
5885
5886

5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905

5906
5907
5908
5909
5910
5911
5912
5913







-



















-
+







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

        private static bool RemoveVsPackage(
            MockRegistryKey rootKey,
            Version vsVersion,
            string suffix,
            Package package,
            bool perUser,
            bool wow64,
            bool throwOnMissing,
            bool whatIf,
            bool verbose,
            ref string error
            )
        {
            if (vsVersion == null)
            {
                error = "invalid VS version";
                return false;
            }

            if (package == null)
            {
                error = "invalid VS package";
                return false;
            }

            string keyName = GetVsKeyName(vsVersion, suffix, perUser, wow64);
            string keyName = GetVsKeyName(vsVersion, suffix, wow64);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, false, whatIf, verbose))
            {
                if (key == null)
                {
                    error = String.Format(
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048


6049
6050
6051
6052
6053

6054
6055
6056
6057
6058
6059
6060
5976
5977
5978
5979
5980
5981
5982

5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000


6001
6002
6003
6004
6005
6006

6007
6008
6009
6010
6011
6012
6013
6014







-


















-
-
+
+




-
+








        private static bool ProcessVsPackage(
            MockRegistryKey rootKey,
            Version vsVersion,
            string suffix,
            Package package,
            object clientData,
            bool perUser,
            bool wow64,
            bool throwOnMissing,
            bool whatIf,
            bool verbose,
            ref string error
            )
        {
            AnyPair<string, bool> pair = clientData as AnyPair<string, bool>;

            if (pair == null)
            {
                error = "invalid VS callback data";
                return false;
            }

            if (pair.Y)
            {
                return AddVsPackage(
                    rootKey, vsVersion, suffix, package, pair.X, perUser,
                    wow64, whatIf, verbose, ref error);
                    rootKey, vsVersion, suffix, package, pair.X, wow64,
                    whatIf, verbose, ref error);
            }
            else
            {
                return RemoveVsPackage(
                    rootKey, vsVersion, suffix, package, perUser, wow64,
                    rootKey, vsVersion, suffix, package, wow64,
                    throwOnMissing, whatIf, verbose, ref error);
            }
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////
6176
6177
6178
6179
6180
6181
6182
6183

6184
6185
6186
6187
6188
6189
6190
6191
6130
6131
6132
6133
6134
6135
6136

6137

6138
6139
6140
6141
6142
6143
6144







-
+
-







                            InstallFlags.GlobalAssemblyCache, true) &&
                        configuration.HasFlags(
                            InstallFlags.VsPackageGlobalAssemblyCache, true),
                        ref package);

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

                    InitializeFrameworkList(configuration.PerUser ?
                    InitializeFrameworkList(registry.LocalMachine,
                        registry.CurrentUser : registry.LocalMachine,
                        configuration, ref frameworkList);

                    InitializeVsList(configuration.PerUser ?
                        registry.CurrentUser : registry.LocalMachine,
                        configuration, ref vsList);
                    #endregion

6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6249
6250
6251
6252
6253
6254
6255

6256
6257
6258
6259
6260
6261
6262







-







                    #region .NET AssemblyFolders
                    if (configuration.HasFlags(
                            InstallFlags.AssemblyFolders, true))
                    {
                        if (!ForEachFrameworkRegistry(registry,
                                frameworkList, ProcessAssemblyFolders,
                                configuration.RegistryVersion, directoryData,
                                configuration.PerUser,
                                NetFxIs32BitOnly || configuration.Wow64,
                                configuration.ThrowOnMissing,
                                configuration.WhatIf, configuration.Verbose,
                                ref error))
                        {
                            TraceOps.ShowMessage(TracePriority.Highest,
                                debugCallback, traceCallback, thisAssembly,
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6281
6282
6283
6284
6285
6286
6287

6288
6289
6290
6291
6292
6293
6294







-







                        bool saved = false;

                        if (!ForEachFrameworkConfig(registry,
                                frameworkList, ProcessDbProviderFactory,
                                configuration.ConfigVersion, InvariantName,
                                ProviderName, Description, FactoryTypeName,
                                coreAssemblyName, directoryData,
                                configuration.PerUser,
                                NetFxIs32BitOnly || configuration.Wow64,
                                configuration.ThrowOnMissing,
                                configuration.WhatIf, configuration.Verbose,
                                ref saved, ref error))
                        {
                            TraceOps.ShowMessage(TracePriority.Highest,
                                debugCallback, traceCallback, thisAssembly,
6358
6359
6360
6361
6362
6363
6364
6365

6366
6367
6368
6369
6370
6371
6372
6309
6310
6311
6312
6313
6314
6315

6316
6317
6318
6319
6320
6321
6322
6323







-
+







                    #region VS Package
                    if (configuration.HasFlags(
                            InstallFlags.VsPackage, true))
                    {
                        if (!ForEachVsVersionRegistry(registry,
                                vsList, ProcessVsPackage,
                                configuration.VsVersionSuffix, package,
                                fileNameData, configuration.PerUser,
                                fileNameData,
                                VsIs32BitOnly || configuration.Wow64,
                                configuration.ThrowOnMissing,
                                configuration.WhatIf, configuration.Verbose,
                                ref error))
                        {
                            TraceOps.ShowMessage(TracePriority.Highest,
                                debugCallback, traceCallback, thisAssembly,
6387
6388
6389
6390
6391
6392
6393
6394

6395
6396
6397
6398
6399
6400
6401
6338
6339
6340
6341
6342
6343
6344

6345
6346
6347
6348
6349
6350
6351
6352







-
+







                    #region VS DataSource
                    if (configuration.HasFlags(
                            InstallFlags.VsDataSource, true))
                    {
                        if (!ForEachVsVersionRegistry(registry,
                                vsList, ProcessVsDataSource,
                                configuration.VsVersionSuffix, package,
                                fileNameData, configuration.PerUser,
                                fileNameData,
                                VsIs32BitOnly || configuration.Wow64,
                                configuration.ThrowOnMissing,
                                configuration.WhatIf, configuration.Verbose,
                                ref error))
                        {
                            TraceOps.ShowMessage(TracePriority.Highest,
                                debugCallback, traceCallback, thisAssembly,
6416
6417
6418
6419
6420
6421
6422
6423

6424
6425
6426
6427
6428
6429
6430
6367
6368
6369
6370
6371
6372
6373

6374
6375
6376
6377
6378
6379
6380
6381







-
+







                    #region VS DataProvider
                    if (configuration.HasFlags(
                            InstallFlags.VsDataProvider, true))
                    {
                        if (!ForEachVsVersionRegistry(registry,
                                vsList, ProcessVsDataProvider,
                                configuration.VsVersionSuffix, package,
                                fileNameData, configuration.PerUser,
                                fileNameData,
                                VsIs32BitOnly || configuration.Wow64,
                                configuration.ThrowOnMissing,
                                configuration.WhatIf, configuration.Verbose,
                                ref error))
                        {
                            TraceOps.ShowMessage(TracePriority.Highest,
                                debugCallback, traceCallback, thisAssembly,
Changes to tools/install/Properties/AssemblyInfo.cs.
24
25
26
27
28
29
30
31
32


24
25
26
27
28
29
30


31
32







-
-
+
+
// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version 
//      Build Number
//      Revision
//
[assembly: AssemblyVersion("1.0.84.0")]
[assembly: AssemblyFileVersion("1.0.84.0")]
[assembly: AssemblyVersion("1.0.83.0")]
[assembly: AssemblyFileVersion("1.0.83.0")]
Changes to www/downloads.wiki.
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
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
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
358
359
360
361
362
363
364
365
366
367
368
369

370
371

372
373
374
375
376
377

378
379
380
381
382

383
384

385
386
387
388
389
390
391

392
393

394
395
396
397
398
399


400
401
402

403
404
405
406
407
408
409
410
411
412
413
414
415

416
417

418
419
420
421
422
423

424
425
426
427

428
429
430
431
432
433
434

435
436

437
438
439
440
441
442


443
444
445

446
447
448
449
450
451
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

480
481

482
483
484
485
486
487


488
489
490

491
492
493
494
495
496
497
498
499
500
501
502
503

504
505

506
507
508
509
510
511

512
513
514

515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535

536
537
538
539
540
541
542
543
544
545
546
547

548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617



618
619
620
621
622

623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714

715
716

717
718
719
720
721
722


723
724
725

726
727
728
729
730
731
732

733
734

735
736
737
738
739

740
741
742

743
744
745
746
747
748
749
750
751
752
753
754
755

756
757

758
759
760
761
762
763


764
765
766

767
768
769
770
771
772
773

774
775

776
777
778
779
780

781
782
783

784
785
786
787
788
789
790
791
792
793
794
795
796

797
798

799
800
801
802
803
804


805
806
807

808
809
810
811
812
813
814

815
816

817
818
819
820
821

822
823
824

825
826
827
828
829
830
831
832
833
834
835
836
837

838
839

840
841
842
843
844
845


846
847
848

849
850
851
852
853
854
855

856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880

881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945


946
947
948
949
950

951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
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
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044

1045
1046

1047
1048
1049
1050
1051
1052


1053
1054
1055

1056
1057
1058
1059
1060
1061
1062

1063
1064

1065
1066
1067
1068
1069

1070
1071
1072
1073

1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086

1087
1088

1089
1090
1091
1092
1093
1094


1095
1096
1097

1098
1099
1100
1101
1102
1103
1104

1105
1106

1107
1108
1109
1110
1111

1112
1113
1114
1115

1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128

1129
1130

1131
1132
1133
1134
1135
1136


1137
1138
1139

1140
1141
1142
1143
1144
1145
1146

1147
1148

1149
1150
1151
1152
1153

1154
1155
1156
1157

1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170

1171
1172

1173
1174
1175
1176
1177
1178


1179
1180
1181

1182
1183
1184
1185
1186
1187
1188

1189
1190

1191
1192
1193
1194
1195

1196
1197
1198
1199
1200
1201
1202

1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
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
1343
1344
1345

1346
1347
1348
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
1376
1377
1378
1379

1380
1381

1382
1383
1384
1385
1386
1387
1388
1389




1390
1391

1392
1393
1394
1395
1396
1397
1398
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
283
284
285
286
287

288
289
290
291
292

293
294

295
296
297
298
299
300
301

302
303

304
305
306
307
308


309
310
311
312

313
314
315
316
317
318
319
320
321
322
323
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
358
359
360
361
362
363
364
365
366
367
368

369
370

371
372
373
374
375
376

377
378
379
380
381
382

383
384
385
386
387
388
389

390
391

392
393
394
395
396


397
398
399
400

401
402
403
404
405
406
407
408
409
410
411
412
413

414
415

416
417
418
419
420
421

422
423
424

425
426
427
428
429
430
431















432










433

434































































435
436
437
438



439
440
441
442




443















































































444
445
446
447
448
449
450
451
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
480

481
482
483

484
485
486
487
488
489
490
491
492
493
494
495
496

497
498

499
500
501
502
503


504
505
506
507

508
509
510
511
512
513
514

515
516

517
518
519
520
521

522
523
524

525
526
527
528
529
530
531
532
533
534
535
536
537

538
539

540
541
542
543
544


545
546
547
548

549
550
551
552
553
554
555

556
557

558
559
560
561
562

563
564
565

566
567
568
569
570
571
572
573
574
575
576
577
578

579
580

581
582
583
584
585


586
587
588
589

590
591
592
593
594
595
596

597
598
























599
600
601
602



























































603


604
605
606




607

















































































608
609
610
611
612
613
614
615
616
617
618
619

620
621

622
623
624
625
626


627
628
629
630

631
632
633
634
635
636
637

638
639

640
641
642
643
644

645
646
647
648

649
650
651
652
653
654
655
656
657
658
659
660
661

662
663

664
665
666
667
668


669
670
671
672

673
674
675
676
677
678
679

680
681

682
683
684
685
686

687
688
689
690

691
692
693
694
695
696
697
698
699
700
701
702
703

704
705

706
707
708
709
710


711
712
713
714

715
716
717
718
719
720
721

722
723

724
725
726
727
728

729
730
731
732

733
734
735
736
737
738
739
740
741
742
743
744
745

746
747

748
749
750
751
752


753
754
755
756

757
758
759
760
761
762
763

764
765

766
767
768
769
770

771
772
773
774




775

















































































776
777
778
779
780
781
782
783
784
785
786
787

788
789

790
791
792
793
794

795
796
797

798
799
800
801
802
803
804
805
806
807
808
809
810

811
812

813
814
815
816
817


818
819
820
821
822

823
824
825
826
827
828
829

830
831

832
833
834
835
836

837
838
839
840
841
842
843
844

845
846
847
848
849
850
851

852
853

854
855
856
857
858




859
860
861
862
863

864
865
866
867
868
869
870

871
872

873
874
875
876
877




878
879
880
881
882

883
884
885
886
887
888
889
890







-
+

-
+




-
+

-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-












-
+

-
+





-
+




-
+

-
+






-
+

-
+




-
-
+
+


-
+












-
+

-
+





-
+



-
+






-
+

-
+




-
-
+
+


-
+












-
+

-
+





-
+





-
+






-
+

-
+




-
-
+
+


-
+












-
+

-
+





-
+


-
+






-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-

-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-




-
-
-
+
+
+

-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-












-
+

-
+




-
-
+
+


-
+






-
+

-
+




-
+


-
+












-
+

-
+




-
-
+
+


-
+






-
+

-
+




-
+


-
+












-
+

-
+




-
-
+
+


-
+






-
+

-
+




-
+


-
+












-
+

-
+




-
-
+
+


-
+






-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
+
+

-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-












-
+

-
+




-
-
+
+


-
+






-
+

-
+




-
+



-
+












-
+

-
+




-
-
+
+


-
+






-
+

-
+




-
+



-
+












-
+

-
+




-
-
+
+


-
+






-
+

-
+




-
+



-
+












-
+

-
+




-
-
+
+


-
+






-
+

-
+




-
+



-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-












-
+

-
+




-
+


-
+












-
+

-
+




-
-
+
+



-
+






-
+

-
+




-
+







-
+






-
+

-
+




-
-
-
-
+
+
+
+

-
+






-
+

-
+




-
-
-
-
+
+
+
+

-
+







        <b>Source Code</b>
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx-source-1.0.84.0.zip">sqlite-netFx-source-1.0.84.0.zip</a>
        <a href="/downloads/1.0.82.0/sqlite-netFx-source-1.0.82.0.zip">sqlite-netFx-source-1.0.82.0.zip</a>
        <br />
        (2.88 MiB)
        (2.74 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This ZIP archive contains all current source code for System.Data.SQLite
        1.0.84.0 (3.7.15.2) combined into a single archive file.
        1.0.82.0 (3.7.14) combined into a single archive file.
        <br />
        (sha1: 16ab3bdee2fa755af897daa8bc2b4edca75bd6b0)
      </td>
    </tr>

        (sha1: accec84da4a59815078e494afd398eb1b3c64898)
    <tr>
      <td colspan="4">
        <b>Setups for 32-bit Windows (.NET Framework 2.0 SP2)</b>
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx20-setup-bundle-x86-2005-1.0.84.0.exe">sqlite-netFx20-setup-bundle-x86-2005-1.0.84.0.exe</a>
        <br />
        (4.09 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This setup package features the mixed-mode assembly and will install all
        the necessary runtime components and dependencies for the x86 version of
        the System.Data.SQLite 1.0.84.0 (3.7.15.2) package.  The Visual C++ 2005
        SP1 runtime for x86 is included.  The .NET Framework 2.0 SP2 is
        required.
        <br />
        <big><b>This setup package is capable of installing the design-time
        components for Visual Studio 2005.</b></big>
        <br />
        (sha1: e1175e117d2425b683aaeaf94bb8f8d494e646ab)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx20-setup-x86-2005-1.0.84.0.exe">sqlite-netFx20-setup-x86-2005-1.0.84.0.exe</a>
        <br />
        (4.08 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This setup package will install all the necessary runtime components and
        dependencies for the x86 version of the System.Data.SQLite 1.0.84.0
        (3.7.15.2) package.  The Visual C++ 2005 SP1 runtime for x86 is included.
        The .NET Framework 2.0 SP2 is required.
        <br />
        (sha1: 165fba42640af3a3998593de5aae4d8491206cf2)
      </td>
    </tr>

    <tr>
      <td colspan="4">
        <b>Setups for 64-bit Windows (.NET Framework 2.0 SP2)</b>
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx20-setup-bundle-x64-2005-1.0.84.0.exe">sqlite-netFx20-setup-bundle-x64-2005-1.0.84.0.exe</a>
        <br />
        (4.67 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This setup package features the mixed-mode assembly and will install all
        the necessary runtime components and dependencies for the x64 version of
        the System.Data.SQLite 1.0.84.0 (3.7.15.2) package.  The Visual C++ 2005
        SP1 runtime for x64 is included.  The .NET Framework 2.0 SP2 is
        required.
        <br />
        (sha1: 4d9b2bce86f6e76c1ae918f6c90df96697557f63)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx20-setup-x64-2005-1.0.84.0.exe">sqlite-netFx20-setup-x64-2005-1.0.84.0.exe</a>
        <br />
        (4.66 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This setup package will install all the necessary runtime components and
        dependencies for the x64 version of the System.Data.SQLite 1.0.84.0
        (3.7.15.2) package.  The Visual C++ 2005 SP1 runtime for x64 is included.
        The .NET Framework 2.0 SP2 is required.
        <br />
        (sha1: 335f35ed4c320b270aae20c7bf8a96c2928dd9a1)
      </td>
    </tr>

    <tr>
      <td colspan="4">
        <b>Setups for 32-bit Windows (.NET Framework 3.5 SP1)</b>
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx35-setup-bundle-x86-2008-1.0.84.0.exe">sqlite-netFx35-setup-bundle-x86-2008-1.0.84.0.exe</a>
        <a href="/downloads/1.0.82.0/sqlite-netFx35-setup-bundle-x86-2008-1.0.82.0.exe">sqlite-netFx35-setup-bundle-x86-2008-1.0.82.0.exe</a>
        <br />
        (6.10 MiB)
        (6.07 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This setup package features the mixed-mode assembly and will install all
        the necessary runtime components and dependencies for the x86 version of
        the System.Data.SQLite 1.0.84.0 (3.7.15.2) package.  The Visual C++ 2008
        the System.Data.SQLite 1.0.82.0 (3.7.14) package.  The Visual C++ 2008
        SP1 runtime for x86 is included.  The .NET Framework 3.5 SP1 is
        required.
        <br />
        <big><b>This setup package is capable of installing the design-time
        components for Visual Studio 2008.</b></big>
        components for Visual Studio 2005 and/or Visual Studio 2008.</b></big>
        <br />
        (sha1: 1685f4bcd63ad8f3456978d2e788a27c2d5136ea)
        (sha1: e38165e4f45e4338d81f2da10050826406aa09b8)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx35-setup-x86-2008-1.0.84.0.exe">sqlite-netFx35-setup-x86-2008-1.0.84.0.exe</a>
        <a href="/downloads/1.0.82.0/sqlite-netFx35-setup-x86-2008-1.0.82.0.exe">sqlite-netFx35-setup-x86-2008-1.0.82.0.exe</a>
        <br />
        (6.09 MiB)
        (6.06 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This setup package will install all the necessary runtime components and
        dependencies for the x86 version of the System.Data.SQLite 1.0.84.0
        (3.7.15.2) package.  The Visual C++ 2008 SP1 runtime for x86 is included.
        dependencies for the x86 version of the System.Data.SQLite 1.0.82.0
        (3.7.14) package.  The Visual C++ 2008 SP1 runtime for x86 is included.
        The .NET Framework 3.5 SP1 is required.
        <br />
        (sha1: 82d48b5f9c032c81c85b85e227d4578f770e9803)
        (sha1: aed2059188e2ab66a341ce5167b2316c751fdbb1)
      </td>
    </tr>

    <tr>
      <td colspan="4">
        <b>Setups for 64-bit Windows (.NET Framework 3.5 SP1)</b>
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx35-setup-bundle-x64-2008-1.0.84.0.exe">sqlite-netFx35-setup-bundle-x64-2008-1.0.84.0.exe</a>
        <a href="/downloads/1.0.82.0/sqlite-netFx35-setup-bundle-x64-2008-1.0.82.0.exe">sqlite-netFx35-setup-bundle-x64-2008-1.0.82.0.exe</a>
        <br />
        (6.84 MiB)
        (6.81 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This setup package features the mixed-mode assembly and will install all
        the necessary runtime components and dependencies for the x64 version of
        the System.Data.SQLite 1.0.84.0 (3.7.15.2) package.  The Visual C++ 2008
        the System.Data.SQLite 1.0.82.0 (3.7.14) package.  The Visual C++ 2008
        SP1 runtime for x64 is included.  The .NET Framework 3.5 SP1 is
        required.
        <br />
        (sha1: d4a476cdd96a7d153b4502e74649bfb60b5bd11a)
        (sha1: aa0f1f958f9febf466807d79f03fae31508993dd)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx35-setup-x64-2008-1.0.84.0.exe">sqlite-netFx35-setup-x64-2008-1.0.84.0.exe</a>
        <a href="/downloads/1.0.82.0/sqlite-netFx35-setup-x64-2008-1.0.82.0.exe">sqlite-netFx35-setup-x64-2008-1.0.82.0.exe</a>
        <br />
        (6.83 MiB)
        (6.80 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This setup package will install all the necessary runtime components and
        dependencies for the x64 version of the System.Data.SQLite 1.0.84.0
        (3.7.15.2) package.  The Visual C++ 2008 SP1 runtime for x64 is included.
        dependencies for the x64 version of the System.Data.SQLite 1.0.82.0
        (3.7.14) package.  The Visual C++ 2008 SP1 runtime for x64 is included.
        The .NET Framework 3.5 SP1 is required.
        <br />
        (sha1: d0e17d8800a53f6bcedb965c2f8eec8f87f7894e)
        (sha1: b5fa5e9c3477a44724356816488ca3fa15a11d4b)
      </td>
    </tr>

    <tr>
      <td colspan="4">
        <b>Setups for 32-bit Windows (.NET Framework 4.0)</b>
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx40-setup-bundle-x86-2010-1.0.84.0.exe">sqlite-netFx40-setup-bundle-x86-2010-1.0.84.0.exe</a>
        <a href="/downloads/1.0.82.0/sqlite-netFx40-setup-bundle-x86-2010-1.0.82.0.exe">sqlite-netFx40-setup-bundle-x86-2010-1.0.82.0.exe</a>
        <br />
        (10.43 MiB)
        (10.40 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This setup package features the mixed-mode assembly and will install all
        the necessary runtime components and dependencies for the x86 version of
        the System.Data.SQLite 1.0.84.0 (3.7.15.2) package.  The Visual C++ 2010
        the System.Data.SQLite 1.0.82.0 (3.7.14) package.  The Visual C++ 2010
        SP1 runtime for x86 is included.  The .NET Framework 4.0 is required.
        <br />
        <big><b>This setup package is capable of installing the design-time
        components for Visual Studio 2010.</b></big>
        <br />
        (sha1: 60bab3d9f579fb070a271420b622127b795ce84c)
        (sha1: bf3defd3b4250e1aa94ea06e10c4b369416d0e2a)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx40-setup-x86-2010-1.0.84.0.exe">sqlite-netFx40-setup-x86-2010-1.0.84.0.exe</a>
        <a href="/downloads/1.0.82.0/sqlite-netFx40-setup-x86-2010-1.0.82.0.exe">sqlite-netFx40-setup-x86-2010-1.0.82.0.exe</a>
        <br />
        (10.42 MiB)
        (10.39 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This setup package will install all the necessary runtime components and
        dependencies for the x86 version of the System.Data.SQLite 1.0.84.0
        (3.7.15.2) package.  The Visual C++ 2010 SP1 runtime for x86 is included.
        dependencies for the x86 version of the System.Data.SQLite 1.0.82.0
        (3.7.14) package.  The Visual C++ 2010 SP1 runtime for x86 is included.
        The .NET Framework 4.0 is required.
        <br />
        (sha1: 344e0406dd463689768ed1055f07adc8c5f2cde7)
        (sha1: 8435fe9fd02655d3df95991e68391d487f6a8776)
      </td>
    </tr>

    <tr>
      <td colspan="4">
        <b>Setups for 64-bit Windows (.NET Framework 4.0)</b>
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx40-setup-bundle-x64-2010-1.0.84.0.exe">sqlite-netFx40-setup-bundle-x64-2010-1.0.84.0.exe</a>
        <a href="/downloads/1.0.82.0/sqlite-netFx40-setup-bundle-x64-2010-1.0.82.0.exe">sqlite-netFx40-setup-bundle-x64-2010-1.0.82.0.exe</a>
        <br />
        (11.68 MiB)
        (11.65 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This setup package features the mixed-mode assembly and will install all
        the necessary runtime components and dependencies for the x64 version of
        the System.Data.SQLite 1.0.84.0 (3.7.15.2) package.  The Visual C++ 2010
        the System.Data.SQLite 1.0.82.0 (3.7.14) package.  The Visual C++ 2010
        SP1 runtime for x64 is included.  The .NET Framework 4.0 is required.
        <br />
        (sha1: 753bd303e82f9267c607d3729cb1cd80aef89ada)
        (sha1: a7fcc7d410df97817eabbbc6f01e1e448f898aab)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx40-setup-x64-2010-1.0.84.0.exe">sqlite-netFx40-setup-x64-2010-1.0.84.0.exe</a>
        <br />
        (11.67 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This setup package will install all the necessary runtime components and
        dependencies for the x64 version of the System.Data.SQLite 1.0.84.0
        (3.7.15.2) package.  The Visual C++ 2010 SP1 runtime for x64 is included.
        The .NET Framework 4.0 is required.
        <br />
        (sha1: 190cc80906768905d726ee061e6a0c51a8b2d9cd)
      </td>
    </tr>

        <a href="/downloads/1.0.82.0/sqlite-netFx40-setup-x64-2010-1.0.82.0.exe">sqlite-netFx40-setup-x64-2010-1.0.82.0.exe</a>
    <tr>
      <td colspan="4">
        <b>Setups for 32-bit Windows (.NET Framework 4.5)</b>
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx45-setup-bundle-x86-2012-1.0.84.0.exe">sqlite-netFx45-setup-bundle-x86-2012-1.0.84.0.exe</a>
        <br />
        (7.82 MiB)
        (11.64 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This setup package features the mixed-mode assembly and will install all
        the necessary runtime components and dependencies for the x86 version of
        the System.Data.SQLite 1.0.84.0 (3.7.15.2) package.  The Visual C++ 2012
        SP1 runtime for x86 is included.  The .NET Framework 4.5 is required.
        <br />
        <big><b>This setup package is capable of installing the design-time
        components for Visual Studio 2012.</b></big>
        <br />
        (sha1: 6954e6ee073a5965fbac99408e485bf68c1d35cf)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx45-setup-x86-2012-1.0.84.0.exe">sqlite-netFx45-setup-x86-2012-1.0.84.0.exe</a>
        <br />
        (7.85 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This setup package will install all the necessary runtime components and
        dependencies for the x86 version of the System.Data.SQLite 1.0.84.0
        (3.7.15.2) package.  The Visual C++ 2012 SP1 runtime for x86 is included.
        The .NET Framework 4.5 is required.
        <br />
        (sha1: 6406842a3d916f2977f75ab5c6975debc232ce76)
      </td>
    </tr>

    <tr>
      <td colspan="4">
        <b>Setups for 64-bit Windows (.NET Framework 4.5)</b>
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx45-setup-bundle-x64-2012-1.0.84.0.exe">sqlite-netFx45-setup-bundle-x64-2012-1.0.84.0.exe</a>
        <br />
        (8.45 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This setup package features the mixed-mode assembly and will install all
        the necessary runtime components and dependencies for the x64 version of
        the System.Data.SQLite 1.0.84.0 (3.7.15.2) package.  The Visual C++ 2012
        SP1 runtime for x64 is included.  The .NET Framework 4.5 is required.
        <br />
        (sha1: 4ee62f74e45fd40ccaecbfe685fb6d08792c0cde)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx45-setup-x64-2012-1.0.84.0.exe">sqlite-netFx45-setup-x64-2012-1.0.84.0.exe</a>
        <br />
        (8.50 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This setup package will install all the necessary runtime components and
        dependencies for the x64 version of the System.Data.SQLite 1.0.84.0
        (3.7.15.2) package.  The Visual C++ 2012 SP1 runtime for x64 is included.
        The .NET Framework 4.5 is required.
        dependencies for the x64 version of the System.Data.SQLite 1.0.82.0
        (3.7.14) package.  The Visual C++ 2010 SP1 runtime for x64 is included.
        The .NET Framework 4.0 is required.
        <br />
        (sha1: 0e24f71a7f2bcdb74bbd7afd807dafeafc64a81e)
      </td>
    </tr>

        (sha1: 0c3d227a1b3c0f3aae1a0b687f17dba18bed6eeb)
    <tr>
      <td colspan="4">
        <b>Precompiled Binaries for 32-bit Windows (.NET Framework 2.0 SP2)</b>
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx20-binary-bundle-Win32-2005-1.0.84.0.zip">sqlite-netFx20-binary-bundle-Win32-2005-1.0.84.0.zip</a>
        <br />
        (1.23 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package features the mixed-mode assembly and contains all
        the binaries for the x86 version of the System.Data.SQLite 1.0.84.0
        (3.7.15.2) package.  The Visual C++ 2005 SP1 runtime for x86 and the .NET
        Framework 2.0 SP2 are required.
        <br />
        (sha1: 655ed614a42c479de46a880df47365297577fd59)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx20-binary-Win32-2005-1.0.84.0.zip">sqlite-netFx20-binary-Win32-2005-1.0.84.0.zip</a>
        <br />
        (1.23 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package contains all the binaries for the x86 version of the
        System.Data.SQLite 1.0.84.0 (3.7.15.2) package.  The Visual C++ 2005 SP1
        runtime for x86 and the .NET Framework 2.0 SP2 are required.
        <br />
        (sha1: 853c775833d8ff779a1010482eb8a8472c0df82a)
      </td>
    </tr>

    <tr>
      <td colspan="4">
        <b>Precompiled Binaries for 64-bit Windows (.NET Framework 2.0 SP2)</b>
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx20-binary-bundle-x64-2005-1.0.84.0.zip">sqlite-netFx20-binary-bundle-x64-2005-1.0.84.0.zip</a>
        <br />
        (1.42 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package features the mixed-mode assembly and contains all
        the binaries for the x64 version of the System.Data.SQLite 1.0.84.0
        (3.7.15.2) package.  The Visual C++ 2005 SP1 runtime for x64 and the .NET
        Framework 2.0 SP2 are required.
        <br />
        (sha1: 808001b9c03d94761c30e685ba299ed217b67f91)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx20-binary-x64-2005-1.0.84.0.zip">sqlite-netFx20-binary-x64-2005-1.0.84.0.zip</a>
        <br />
        (1.41 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package contains all the binaries for the x64 version of the
        System.Data.SQLite 1.0.84.0 (3.7.15.2) package.  The Visual C++ 2005 SP1
        runtime for x64 and the .NET Framework 2.0 SP2 are required.
        <br />
        (sha1: 9cc8f18efe14716d1bdfd8ff7ded356e47495e4b)
      </td>
    </tr>

    <tr>
      <td colspan="4">
        <b>Precompiled Binaries for 32-bit Windows (.NET Framework 3.5 SP1)</b>
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx35-binary-bundle-Win32-2008-1.0.84.0.zip">sqlite-netFx35-binary-bundle-Win32-2008-1.0.84.0.zip</a>
        <a href="/downloads/1.0.82.0/sqlite-netFx35-binary-bundle-Win32-2008-1.0.82.0.zip">sqlite-netFx35-binary-bundle-Win32-2008-1.0.82.0.zip</a>
        <br />
        (1.68 MiB)
        (1.66 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package features the mixed-mode assembly and contains all
        the binaries for the x86 version of the System.Data.SQLite 1.0.84.0
        (3.7.15.2) package.  The Visual C++ 2008 SP1 runtime for x86 and the .NET
        the binaries for the x86 version of the System.Data.SQLite 1.0.82.0
        (3.7.14) package.  The Visual C++ 2008 SP1 runtime for x86 and the .NET
        Framework 3.5 SP1 are required.
        <br />
        (sha1: 8f2f071cdbb5cf7b7035d4ed7f6a99c4253a7816)
        (sha1: cf6ec0622af7a16c5cf32c02d41a29060b91ec79)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx35-binary-Win32-2008-1.0.84.0.zip">sqlite-netFx35-binary-Win32-2008-1.0.84.0.zip</a>
        <a href="/downloads/1.0.82.0/sqlite-netFx35-binary-Win32-2008-1.0.82.0.zip">sqlite-netFx35-binary-Win32-2008-1.0.82.0.zip</a>
        <br />
        (1.67 MiB)
        (1.65 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package contains all the binaries for the x86 version of the
        System.Data.SQLite 1.0.84.0 (3.7.15.2) package.  The Visual C++ 2008 SP1
        System.Data.SQLite 1.0.82.0 (3.7.14) package.  The Visual C++ 2008 SP1
        runtime for x86 and the .NET Framework 3.5 SP1 are required.
        <br />
        (sha1: 55edb20a73da43ada0b6eb89d9fb66fe6cf5e51b)
        (sha1: 5e4724570d0a9e49450d2c0aac0601db4bebed11)
      </td>
    </tr>

    <tr>
      <td colspan="4">
        <b>Precompiled Binaries for 64-bit Windows (.NET Framework 3.5 SP1)</b>
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx35-binary-bundle-x64-2008-1.0.84.0.zip">sqlite-netFx35-binary-bundle-x64-2008-1.0.84.0.zip</a>
        <a href="/downloads/1.0.82.0/sqlite-netFx35-binary-bundle-x64-2008-1.0.82.0.zip">sqlite-netFx35-binary-bundle-x64-2008-1.0.82.0.zip</a>
        <br />
        (1.75 MiB)
        (1.73 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package features the mixed-mode assembly and contains all
        the binaries for the x64 version of the System.Data.SQLite 1.0.84.0
        (3.7.15.2) package.  The Visual C++ 2008 SP1 runtime for x64 and the .NET
        the binaries for the x64 version of the System.Data.SQLite 1.0.82.0
        (3.7.14) package.  The Visual C++ 2008 SP1 runtime for x64 and the .NET
        Framework 3.5 SP1 are required.
        <br />
        (sha1: c67a430533cf7c7776f4cff86041ee1afc856e4b)
        (sha1: 15b5625a7f5fa1a4a74c61c0c46e3969d2c6adc2)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx35-binary-x64-2008-1.0.84.0.zip">sqlite-netFx35-binary-x64-2008-1.0.84.0.zip</a>
        <a href="/downloads/1.0.82.0/sqlite-netFx35-binary-x64-2008-1.0.82.0.zip">sqlite-netFx35-binary-x64-2008-1.0.82.0.zip</a>
        <br />
        (1.74 MiB)
        (1.72 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package contains all the binaries for the x64 version of the
        System.Data.SQLite 1.0.84.0 (3.7.15.2) package.  The Visual C++ 2008 SP1
        System.Data.SQLite 1.0.82.0 (3.7.14) package.  The Visual C++ 2008 SP1
        runtime for x64 and the .NET Framework 3.5 SP1 are required.
        <br />
        (sha1: c32b05f6824071b62a99f7732fbfbcec0c2e4e87)
        (sha1: 25abc0ea78f8f45b93c9c2fc1381c2acd863638d)
      </td>
    </tr>

    <tr>
      <td colspan="4">
        <b>Precompiled Binaries for 32-bit Windows (.NET Framework 4.0)</b>
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx40-binary-bundle-Win32-2010-1.0.84.0.zip">sqlite-netFx40-binary-bundle-Win32-2010-1.0.84.0.zip</a>
        <a href="/downloads/1.0.82.0/sqlite-netFx40-binary-bundle-Win32-2010-1.0.82.0.zip">sqlite-netFx40-binary-bundle-Win32-2010-1.0.82.0.zip</a>
        <br />
        (1.73 MiB)
        (1.71 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package features the mixed-mode assembly and contains all
        the binaries for the x86 version of the System.Data.SQLite 1.0.84.0
        (3.7.15.2) package.  The Visual C++ 2010 SP1 runtime for x86 and the .NET
        the binaries for the x86 version of the System.Data.SQLite 1.0.82.0
        (3.7.14) package.  The Visual C++ 2010 SP1 runtime for x86 and the .NET
        Framework 4.0 are required.
        <br />
        (sha1: 8c673f05e5ca349425a4e46a1b0b13336f6056e7)
        (sha1: 6f6cdfddb08f254b744e7088b4825db02bec73da)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx40-binary-Win32-2010-1.0.84.0.zip">sqlite-netFx40-binary-Win32-2010-1.0.84.0.zip</a>
        <a href="/downloads/1.0.82.0/sqlite-netFx40-binary-Win32-2010-1.0.82.0.zip">sqlite-netFx40-binary-Win32-2010-1.0.82.0.zip</a>
        <br />
        (1.72 MiB)
        (1.70 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package contains all the binaries for the x86 version of the
        System.Data.SQLite 1.0.84.0 (3.7.15.2) package.  The Visual C++ 2010 SP1
        System.Data.SQLite 1.0.82.0 (3.7.14) package.  The Visual C++ 2010 SP1
        runtime for x86 and the .NET Framework 4.0 are required.
        <br />
        (sha1: cf4ead8c3337d595ff3cc8d1583c458084094793)
        (sha1: 12ffe8323fcf5af25ef6e6effb4f52300df819ee)
      </td>
    </tr>

    <tr>
      <td colspan="4">
        <b>Precompiled Binaries for 64-bit Windows (.NET Framework 4.0)</b>
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx40-binary-bundle-x64-2010-1.0.84.0.zip">sqlite-netFx40-binary-bundle-x64-2010-1.0.84.0.zip</a>
        <a href="/downloads/1.0.82.0/sqlite-netFx40-binary-bundle-x64-2010-1.0.82.0.zip">sqlite-netFx40-binary-bundle-x64-2010-1.0.82.0.zip</a>
        <br />
        (1.75 MiB)
        (1.73 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package features the mixed-mode assembly and contains all
        the binaries for the x64 version of the System.Data.SQLite 1.0.84.0
        (3.7.15.2) package.  The Visual C++ 2010 SP1 runtime for x64 and the .NET
        the binaries for the x64 version of the System.Data.SQLite 1.0.82.0
        (3.7.14) package.  The Visual C++ 2010 SP1 runtime for x64 and the .NET
        Framework 4.0 are required.
        <br />
        (sha1: 32440a943c56d291c9732195b066474d8bcaebca)
        (sha1: e1b79aa7763853a68068f43c9edb6382a2c67550)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx40-binary-x64-2010-1.0.84.0.zip">sqlite-netFx40-binary-x64-2010-1.0.84.0.zip</a>
        <a href="/downloads/1.0.82.0/sqlite-netFx40-binary-x64-2010-1.0.82.0.zip">sqlite-netFx40-binary-x64-2010-1.0.82.0.zip</a>
        <br />
        (1.75 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package contains all the binaries for the x64 version of the
        System.Data.SQLite 1.0.84.0 (3.7.15.2) package.  The Visual C++ 2010 SP1
        runtime for x64 and the .NET Framework 4.0 are required.
        <br />
        (sha1: 5c80b715f012d76a4d1f3c936c4b7c2e87032e77)
      </td>
    </tr>

    <tr>
      <td colspan="4">
        <b>Precompiled Binaries for 32-bit Windows (.NET Framework 4.5)</b>
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx45-binary-bundle-Win32-2012-1.0.84.0.zip">sqlite-netFx45-binary-bundle-Win32-2012-1.0.84.0.zip</a>
        <br />
        (1.66 MiB)
        (1.72 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package features the mixed-mode assembly and contains all
        the binaries for the x86 version of the System.Data.SQLite 1.0.84.0
        (3.7.15.2) package.  The Visual C++ 2012 SP1 runtime for x86 and the .NET
        Framework 4.5 are required.
        <br />
        (sha1: 0dc8d3533375f8589c85d29d3270912666ef61e4)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx45-binary-Win32-2012-1.0.84.0.zip">sqlite-netFx45-binary-Win32-2012-1.0.84.0.zip</a>
        <br />
        (1.70 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package contains all the binaries for the x86 version of the
        System.Data.SQLite 1.0.84.0 (3.7.15.2) package.  The Visual C++ 2012 SP1
        runtime for x86 and the .NET Framework 4.5 are required.
        <br />
        (sha1: 1d88fdb25802d6b6ad34d7fa2da2da7003a49e53)
      </td>
    </tr>

    <tr>
      <td colspan="4">
        <b>Precompiled Binaries for 64-bit Windows (.NET Framework 4.5)</b>
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx45-binary-bundle-x64-2012-1.0.84.0.zip">sqlite-netFx45-binary-bundle-x64-2012-1.0.84.0.zip</a>
        <br />
        (1.69 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package features the mixed-mode assembly and contains all
        the binaries for the x64 version of the System.Data.SQLite 1.0.84.0
        (3.7.15.2) package.  The Visual C++ 2012 SP1 runtime for x64 and the .NET
        Framework 4.5 are required.
        <br />
        (sha1: 33e865f0214fef3def4de4f18462832f9788ade4)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx45-binary-x64-2012-1.0.84.0.zip">sqlite-netFx45-binary-x64-2012-1.0.84.0.zip</a>
        <br />
        (1.75 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package contains all the binaries for the x64 version of the
        System.Data.SQLite 1.0.84.0 (3.7.15.2) package.  The Visual C++ 2012 SP1
        runtime for x64 and the .NET Framework 4.5 are required.
        System.Data.SQLite 1.0.82.0 (3.7.14) package.  The Visual C++ 2010 SP1
        runtime for x64 and the .NET Framework 4.0 are required.
        <br />
        (sha1: a3970b48c78ecbf9fb92553d52f2af5cbfe01e25)
      </td>
    </tr>

        (sha1: a91739243166b9ae27be244722acd480d1ce4537)
    <tr>
      <td colspan="4">
        <b>Precompiled Statically-Linked Binaries for 32-bit Windows (.NET Framework 2.0 SP2)</b>
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx20-static-binary-bundle-Win32-2005-1.0.84.0.zip">sqlite-netFx20-static-binary-bundle-Win32-2005-1.0.84.0.zip</a>
        <br />
        (1.44 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package features the mixed-mode assembly and contains all
        the binaries for the x86 version of the System.Data.SQLite 1.0.84.0
        (3.7.15.2) package.  The Visual C++ 2005 SP1 runtime for x86 is statically
        linked.  The .NET Framework 2.0 SP2 is required.
        <br />
        (sha1: 0a740fc8011b8a63e83a3ab98ae7952effb3b75e)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx20-static-binary-Win32-2005-1.0.84.0.zip">sqlite-netFx20-static-binary-Win32-2005-1.0.84.0.zip</a>
        <br />
        (1.44 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package contains all the binaries for the x86 version of the
        System.Data.SQLite 1.0.84.0 (3.7.15.2) package.  The Visual C++ 2005 SP1
        runtime for x86 is statically linked.  The .NET Framework 2.0 SP2 is
        required.
        <br />
        (sha1: e26b550a43026088101692cddac64938d26fce6a)
      </td>
    </tr>

    <tr>
      <td colspan="4">
        <b>Precompiled Statically-Linked Binaries for 64-bit Windows (.NET Framework 2.0 SP2)</b>
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx20-static-binary-bundle-x64-2005-1.0.84.0.zip">sqlite-netFx20-static-binary-bundle-x64-2005-1.0.84.0.zip</a>
        <br />
        (1.57 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package features the mixed-mode assembly and contains all
        the binaries for the x64 version of the System.Data.SQLite 1.0.84.0
        (3.7.15.2) package.  The Visual C++ 2005 SP1 runtime for x64 is statically
        linked.  The .NET Framework 2.0 SP2 is required.
        <br />
        (sha1: 2f00962575168ffeae32190d6890b6ff60e7230d)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx20-static-binary-x64-2005-1.0.84.0.zip">sqlite-netFx20-static-binary-x64-2005-1.0.84.0.zip</a>
        <br />
        (1.57 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package contains all the binaries for the x64 version of the
        System.Data.SQLite 1.0.84.0 (3.7.15.2) package.  The Visual C++ 2005 SP1
        runtime for x64 is statically linked.  The .NET Framework 2.0 SP2 is
        required.
        <br />
        (sha1: a16f147da6616a6475859355a7129915e3790108)
      </td>
    </tr>

    <tr>
      <td colspan="4">
        <b>Precompiled Statically-Linked Binaries for 32-bit Windows (.NET Framework 3.5 SP1)</b>
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx35-static-binary-bundle-Win32-2008-1.0.84.0.zip">sqlite-netFx35-static-binary-bundle-Win32-2008-1.0.84.0.zip</a>
        <a href="/downloads/1.0.82.0/sqlite-netFx35-static-binary-bundle-Win32-2008-1.0.82.0.zip">sqlite-netFx35-static-binary-bundle-Win32-2008-1.0.82.0.zip</a>
        <br />
        (1.89 MiB)
        (1.87 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package features the mixed-mode assembly and contains all
        the binaries for the x86 version of the System.Data.SQLite 1.0.84.0
        (3.7.15.2) package.  The Visual C++ 2008 SP1 runtime for x86 is statically
        the binaries for the x86 version of the System.Data.SQLite 1.0.82.0
        (3.7.14) package.  The Visual C++ 2008 SP1 runtime for x86 is statically
        linked.  The .NET Framework 3.5 SP1 is required.
        <br />
        (sha1: 60ed2d6a3d980af41e147e08357c285c8a3a1e20)
        (sha1: 43076280a7ee02b1574bb666d3a14c185d6fe84a)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx35-static-binary-Win32-2008-1.0.84.0.zip">sqlite-netFx35-static-binary-Win32-2008-1.0.84.0.zip</a>
        <a href="/downloads/1.0.82.0/sqlite-netFx35-static-binary-Win32-2008-1.0.82.0.zip">sqlite-netFx35-static-binary-Win32-2008-1.0.82.0.zip</a>
        <br />
        (1.89 MiB)
        (1.86 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package contains all the binaries for the x86 version of the
        System.Data.SQLite 1.0.84.0 (3.7.15.2) package.  The Visual C++ 2008 SP1
        System.Data.SQLite 1.0.82.0 (3.7.14) package.  The Visual C++ 2008 SP1
        runtime for x86 is statically linked.  The .NET Framework 3.5 SP1 is
        required.
        <br />
        (sha1: 7b57f575238156098153763a0473ed4e4a787dda)
        (sha1: 44f8225d4025d2014ded056b31a2b1a5a8de07cc)
      </td>
    </tr>

    <tr>
      <td colspan="4">
        <b>Precompiled Statically-Linked Binaries for 64-bit Windows (.NET Framework 3.5 SP1)</b>
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx35-static-binary-bundle-x64-2008-1.0.84.0.zip">sqlite-netFx35-static-binary-bundle-x64-2008-1.0.84.0.zip</a>
        <a href="/downloads/1.0.82.0/sqlite-netFx35-static-binary-bundle-x64-2008-1.0.82.0.zip">sqlite-netFx35-static-binary-bundle-x64-2008-1.0.82.0.zip</a>
        <br />
        (1.92 MiB)
        (1.90 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package features the mixed-mode assembly and contains all
        the binaries for the x64 version of the System.Data.SQLite 1.0.84.0
        (3.7.15.2) package.  The Visual C++ 2008 SP1 runtime for x64 is statically
        the binaries for the x64 version of the System.Data.SQLite 1.0.82.0
        (3.7.14) package.  The Visual C++ 2008 SP1 runtime for x64 is statically
        linked.  The .NET Framework 3.5 SP1 is required.
        <br />
        (sha1: bfed5c0a206fa433d308bae303eca1d56883c04d)
        (sha1: 1e29c539c75e106ddbdd18c83563fc0b9df7c1bf)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx35-static-binary-x64-2008-1.0.84.0.zip">sqlite-netFx35-static-binary-x64-2008-1.0.84.0.zip</a>
        <a href="/downloads/1.0.82.0/sqlite-netFx35-static-binary-x64-2008-1.0.82.0.zip">sqlite-netFx35-static-binary-x64-2008-1.0.82.0.zip</a>
        <br />
        (1.92 MiB)
        (1.90 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package contains all the binaries for the x64 version of the
        System.Data.SQLite 1.0.84.0 (3.7.15.2) package.  The Visual C++ 2008 SP1
        System.Data.SQLite 1.0.82.0 (3.7.14) package.  The Visual C++ 2008 SP1
        runtime for x64 is statically linked.  The .NET Framework 3.5 SP1 is
        required.
        <br />
        (sha1: a8d9cd5b94609f060a5f994dad0efa525c1744f9)
        (sha1: f10532c9c858465852d179dc88ea6c519212234f)
      </td>
    </tr>

    <tr>
      <td colspan="4">
        <b>Precompiled Statically-Linked Binaries for 32-bit Windows (.NET Framework 4.0)</b>
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx40-static-binary-bundle-Win32-2010-1.0.84.0.zip">sqlite-netFx40-static-binary-bundle-Win32-2010-1.0.84.0.zip</a>
        <a href="/downloads/1.0.82.0/sqlite-netFx40-static-binary-bundle-Win32-2010-1.0.82.0.zip">sqlite-netFx40-static-binary-bundle-Win32-2010-1.0.82.0.zip</a>
        <br />
        (1.94 MiB)
        (1.92 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package features the mixed-mode assembly and contains all
        the binaries for the x86 version of the System.Data.SQLite 1.0.84.0
        (3.7.15.2) package.  The Visual C++ 2010 SP1 runtime for x86 is statically
        the binaries for the x86 version of the System.Data.SQLite 1.0.82.0
        (3.7.14) package.  The Visual C++ 2010 SP1 runtime for x86 is statically
        linked.  The .NET Framework 4.0 is required.
        <br />
        (sha1: 9e829efcac6d05dee68f6d0a97a9342773dc9573)
        (sha1: 335da5c15d56b868f948dbf842ad97c94c5c148c)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx40-static-binary-Win32-2010-1.0.84.0.zip">sqlite-netFx40-static-binary-Win32-2010-1.0.84.0.zip</a>
        <a href="/downloads/1.0.82.0/sqlite-netFx40-static-binary-Win32-2010-1.0.82.0.zip">sqlite-netFx40-static-binary-Win32-2010-1.0.82.0.zip</a>
        <br />
        (1.94 MiB)
        (1.91 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package contains all the binaries for the x86 version of the
        System.Data.SQLite 1.0.84.0 (3.7.15.2) package.  The Visual C++ 2010 SP1
        System.Data.SQLite 1.0.82.0 (3.7.14) package.  The Visual C++ 2010 SP1
        runtime for x86 is statically linked.  The .NET Framework 4.0 is
        required.
        <br />
        (sha1: 67c7f69a31250db04440330385926df91710bd61)
        (sha1: 22d21e6b97b9b79cd51528fda938e3d601eb1ae4)
      </td>
    </tr>

    <tr>
      <td colspan="4">
        <b>Precompiled Statically-Linked Binaries for 64-bit Windows (.NET Framework 4.0)</b>
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx40-static-binary-bundle-x64-2010-1.0.84.0.zip">sqlite-netFx40-static-binary-bundle-x64-2010-1.0.84.0.zip</a>
        <a href="/downloads/1.0.82.0/sqlite-netFx40-static-binary-bundle-x64-2010-1.0.82.0.zip">sqlite-netFx40-static-binary-bundle-x64-2010-1.0.82.0.zip</a>
        <br />
        (1.95 MiB)
        (1.92 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package features the mixed-mode assembly and contains all
        the binaries for the x64 version of the System.Data.SQLite 1.0.84.0
        (3.7.15.2) package.  The Visual C++ 2010 SP1 runtime for x64 is statically
        the binaries for the x64 version of the System.Data.SQLite 1.0.82.0
        (3.7.14) package.  The Visual C++ 2010 SP1 runtime for x64 is statically
        linked.  The .NET Framework 4.0 is required.
        <br />
        (sha1: 09e43ce56de8e9db493f895d0440bf58c90867e8)
        (sha1: 929f1d2a0eb9bb697c4e8725bedef1f4042c076b)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx40-static-binary-x64-2010-1.0.84.0.zip">sqlite-netFx40-static-binary-x64-2010-1.0.84.0.zip</a>
        <a href="/downloads/1.0.82.0/sqlite-netFx40-static-binary-x64-2010-1.0.82.0.zip">sqlite-netFx40-static-binary-x64-2010-1.0.82.0.zip</a>
        <br />
        (1.94 MiB)
        (1.92 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package contains all the binaries for the x64 version of the
        System.Data.SQLite 1.0.84.0 (3.7.15.2) package.  The Visual C++ 2010 SP1
        System.Data.SQLite 1.0.82.0 (3.7.14) package.  The Visual C++ 2010 SP1
        runtime for x64 is statically linked.  The .NET Framework 4.0 is
        required.
        <br />
        (sha1: 9a439387fe8a836cc6acafa5b4510becc0846cbd)
      </td>
    </tr>

        (sha1: 4c12b0ad3aae3510bd573e49a6159f6a3405d312)
    <tr>
      <td colspan="4">
        <b>Precompiled Statically-Linked Binaries for 32-bit Windows (.NET Framework 4.5)</b>
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx45-static-binary-bundle-Win32-2012-1.0.84.0.zip">sqlite-netFx45-static-binary-bundle-Win32-2012-1.0.84.0.zip</a>
        <br />
        (1.98 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package features the mixed-mode assembly and contains all
        the binaries for the x86 version of the System.Data.SQLite 1.0.84.0
        (3.7.15.2) package.  The Visual C++ 2012 SP1 runtime for x86 is statically
        linked.  The .NET Framework 4.5 is required.
        <br />
        (sha1: 24a13024db3ef732cde9f128b43dcb0a9802dcdd)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx45-static-binary-Win32-2012-1.0.84.0.zip">sqlite-netFx45-static-binary-Win32-2012-1.0.84.0.zip</a>
        <br />
        (2.03 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package contains all the binaries for the x86 version of the
        System.Data.SQLite 1.0.84.0 (3.7.15.2) package.  The Visual C++ 2012 SP1
        runtime for x86 is statically linked.  The .NET Framework 4.5 is
        required.
        <br />
        (sha1: 40f7633bbe527802f13cb653dc13354d871e4bb7)
      </td>
    </tr>

    <tr>
      <td colspan="4">
        <b>Precompiled Statically-Linked Binaries for 64-bit Windows (.NET Framework 4.5)</b>
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx45-static-binary-bundle-x64-2012-1.0.84.0.zip">sqlite-netFx45-static-binary-bundle-x64-2012-1.0.84.0.zip</a>
        <br />
        (1.94 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package features the mixed-mode assembly and contains all
        the binaries for the x64 version of the System.Data.SQLite 1.0.84.0
        (3.7.15.2) package.  The Visual C++ 2012 SP1 runtime for x64 is statically
        linked.  The .NET Framework 4.5 is required.
        <br />
        (sha1: b41daf0cd84393651a8a68a6149dbd0193cdd838)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx45-static-binary-x64-2012-1.0.84.0.zip">sqlite-netFx45-static-binary-x64-2012-1.0.84.0.zip</a>
        <br />
        (2.01 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package contains all the binaries for the x64 version of the
        System.Data.SQLite 1.0.84.0 (3.7.15.2) package.  The Visual C++ 2012 SP1
        runtime for x64 is statically linked.  The .NET Framework 4.5 is
        required.
        <br />
        (sha1: 3516de01e430fbcda5625b8b52b76efd0a260875)
      </td>
    </tr>

    <tr>
      <td colspan="4">
        <b>Precompiled Binaries for Windows CE (.NET Compact Framework 3.5)</b>
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="/downloads/1.0.84.0/sqlite-netFx35-binary-PocketPC-2008-1.0.84.0.zip">sqlite-netFx35-binary-PocketPC-2008-1.0.84.0.zip</a>
        <a href="/downloads/1.0.82.0/sqlite-netFx35-binary-PocketPC-2008-1.0.82.0.zip">sqlite-netFx35-binary-PocketPC-2008-1.0.82.0.zip</a>
        <br />
        (0.87 MiB)
        (0.85 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This binary package contains all the binaries for the PocketPC version
        of the System.Data.SQLite 1.0.84.0 (3.7.15.2) package.  The .NET Compact
        of the System.Data.SQLite 1.0.82.0 (3.7.14) package.  The .NET Compact
        Framework 3.5 is required.
        <br />
        (sha1: b12956304f4bb770459f00827c450397d8473040)
        (sha1: f9b2393dde3ad5d2f507ebad26d2b81ea7544b70)
      </td>
    </tr>

    <tr>
      <td colspan="4">
        <b>Official NuGet Packages</b>
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="http://nuget.org/api/v2/package/System.Data.SQLite/1.0.84.0">System.Data.SQLite.1.0.84.0.nupkg</a>
        <a href="http://nuget.org/api/v2/package/System.Data.SQLite/1.0.82.0">System.Data.SQLite.1.0.82.0.nupkg</a>
        <br />
        (3.19 MiB)
        (2.85 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This NuGet package contains all the binaries for both the x86 and x64
        versions of System.Data.SQLite 1.0.84.0 (3.7.15.2).  The .NET Framework
        3.5 SP1, 4.0, or 4.5 is required.  For the included native binaries, the
        versions of System.Data.SQLite 1.0.82.0 (3.7.14).  The .NET Framework
        3.5 SP1 or 4.0 is required.  For the included native binaries, the
        version of the Visual C++ runtime corresponding to the .NET Framework
        used by the associated managed assembly is statically linked.
        <br />
        (sha1: b4d1c9498cf27cd7cfde55fe3ab745f66396e0ad)
        (sha1: 00192e51c6dda124d809c517125c99e46f7de620)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="http://nuget.org/api/v2/package/System.Data.SQLite.MSIL/1.0.84.0">System.Data.SQLite.MSIL.1.0.84.0.nupkg</a>
        <a href="http://nuget.org/api/v2/package/System.Data.SQLite.MSIL/1.0.82.0">System.Data.SQLite.MSIL.1.0.82.0.nupkg</a>
        <br />
        (0.33 MiB)
        (0.26 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This NuGet package contains the managed binaries for System.Data.SQLite
        1.0.84.0.  The .NET Framework 3.5 SP1, 4.0, or 4.5 is required.
        1.0.82.0.  The .NET Framework 3.5 SP1 or 4.0 is required.
        <br />
        <big><b>This NuGet package does not include any code from the native
        SQLite core library and will not work properly without the native
        assembly &quot;SQLite.Interop.dll&quot; compiled for the processor
        architecture of the host process being present in a directory in the
        native library search path.</b></big>
        <br />
        (sha1: fe4808f55e3b1f1231ba6b336792f0f8791cdf54)
        (sha1: 8d62c9ff2e22fac2ee0040f6fda49b270e7f27a3)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="http://nuget.org/api/v2/package/System.Data.SQLite.x86/1.0.84.0">System.Data.SQLite.x86.1.0.84.0.nupkg</a>
        <a href="http://nuget.org/api/v2/package/System.Data.SQLite.x86/1.0.82.0">System.Data.SQLite.x86.1.0.82.0.nupkg</a>
        <br />
        (1.59 MiB)
        (1.47 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This NuGet package contains all the binaries for the x86 version of
        System.Data.SQLite 1.0.84.0 (3.7.15.2).  The .NET Framework 3.5 SP1,
        4.0, or 4.5 is required.  For the included native binaries, the version
        of the Visual C++ runtime corresponding to the .NET Framework used by
        the associated managed assembly is statically linked.
        System.Data.SQLite 1.0.82.0 (3.7.14).  The .NET Framework 3.5 SP1 or 4.0
        is required.  For the included native binaries, the version of the
        Visual C++ runtime corresponding to the .NET Framework used by the
        associated managed assembly is statically linked.
        <br />
        (sha1: c10145217ed979efe53f5931d2e9b3a49b6c65d5)
        (sha1: 598242655955a8827cdab065d4224db8341782fc)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <a href="http://nuget.org/api/v2/package/System.Data.SQLite.x64/1.0.84.0">System.Data.SQLite.x64.1.0.84.0.nupkg</a>
        <a href="http://nuget.org/api/v2/package/System.Data.SQLite.x64/1.0.82.0">System.Data.SQLite.x64.1.0.82.0.nupkg</a>
        <br />
        (1.80 MiB)
        (1.67 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This NuGet package contains all the binaries for the x64 version of
        System.Data.SQLite 1.0.84.0 (3.7.15.2).  The .NET Framework 3.5 SP1,
        4.0, or 4.5 is required.  For the included native binaries, the version
        of the Visual C++ runtime corresponding to the .NET Framework used by
        the associated managed assembly is statically linked.
        System.Data.SQLite 1.0.82.0 (3.7.14).  The .NET Framework 3.5 SP1 or 4.0
        is required.  For the included native binaries, the version of the
        Visual C++ runtime corresponding to the .NET Framework used by the
        associated managed assembly is statically linked.
        <br />
        (sha1: 2e2cd4a194f5c308d46f8f70fc50ae3779afee79)
        (sha1: 1d0a1646f469ea63e74c9ad0778f9911dbde4d30)
      </td>
    </tr>

    <tr>
      <td colspan="4">
        <b>Legacy Versions</b>
      </td>
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
919
920
921
922
923
924
925


926
927
928
929
930
931
932
933
934
935
936
937
938
939
940

941
942
943
944
945
946
947







-
-















-







      <li><b>sqlite-</b>framework<b>-setup-</b>cpu<b>-</b>year<b>-</b>version<b>.exe</b></li>
      <li><b>sqlite-</b>framework<b>-setup-bundle-</b>cpu<b>-</b>year<b>-</b>version<b>.exe</b></li>
      <li><b>sqlite-</b>framework<b>-binary-</b>platform<b>-</b>year<b>-</b>version<b>.zip</b></li>
      <li><b>sqlite-</b>framework<b>-binary-bundle-</b>platform<b>-</b>year<b>-</b>version<b>.zip</b></li>
      <li><b>sqlite-</b>framework<b>-static-binary-</b>platform<b>-</b>year<b>-</b>version<b>.zip</b></li>
      <li><b>sqlite-</b>framework<b>-static-binary-bundle-</b>platform<b>-</b>year<b>-</b>version<b>.zip</b></li>
      <li><b>sqlite-netFx-source-</b>date<b>.zip</b></li>
      <li><b>System.Data.SQLite.</b>version<b>.nupkg</b></li>
      <li><b>System.Data.SQLite.</b>variant<b>.</b>version<b>.nupkg</b></li>
    </ol>
  </p>

  <p>
    Templates (1) and (2) are used for source-code packages.  Template (1) is
    used for generic source-code packages and template (2) is used for
    source-code packages that are generally only useful on unix-like platforms.
    Template (3) is used for the setup package.  Template (4) is used for the
    setup package containing the mixed-mode assembly.  Template (5) is used for
    the precompiled binary package.  Template (6) is used for the precompiled
    binary package containing the mixed-mode assembly.  Template (7) is used for
    the precompiled binary package statically linked to the Visual C++ runtime.
    Template (8) is used for the precompiled binary package containing the
    mixed-mode assembly statically linked to the Visual C++ runtime.  Template
    (9) is used for unofficial pre-release &quot;snapshots&quot; of source code.
    Templates (10) and (11) are used for the official NuGet packages.
  </p>

  <p>
    The <b>framework</b> in templates (3), (4), (5), (6), (7), and (8) will be
    one of netFx20, netFx35, netFx40, netFx45.
  </p>

1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
965
966
967
968
969
970
971




972
973
974
975
976
977
978







-
-
-
-







    assembly.
  </p>

  <p>
    The <b>date</b> in template (9) is of the form: YYYYMMDDHHMM
  </p>

  <p>
    The <b>variant</b> in template (11) will be one of Beta, MSIL, x86, x64.
  </p>

  <h3>Canonical Source Code</h3>

  <p>
    The canonical System.Data.SQLite source code is maintained in a Fossil
    repository that is available for anonymous read-only access. Anyone can view
    the repository contents and download historical versions of individual files
    or ZIP archives of historical check-ins.
Changes to www/index.wiki.
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
30
31
32
33
34
35
36









37
38
39
40
41
42
43







-
-
-
-
-
-
-
-
-







          options.
        </p>
        <p>
          Please refer to the
          <a href="downloads.wiki">download page</a> for a complete list of
          downloadable packages and information on their use.
        </p>
        <p>
          The current documentation for all public types, methods, properties,
          and events is checked into the repository, in
          <a href="http://en.wikipedia.org/wiki/Microsoft_Compiled_HTML_Help">
          <i>Microsoft Compiled HTML Help</i> (&quot;CHM&quot;) format</a>.  It
          can also be
          <a href="/index.html/doc/trunk/Doc/SQLite.NET.chm?mimetype=application/x-chm">
          downloaded directly</a> via the web interface to the repository.
        </p>
      </td>
      <td width="30%" valign="top">
        <table align="right" border="1" cellpadding="10" hspace="10" cellspacing="0">
          <tr>
            <td>
              <ul>
                <li><a href="features.wiki">Features</a></li>
Changes to www/news.wiki.
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
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





-
-
-
-
-
-
-
-
-
-
+


-
+




-
-
-













-
+



-

-
-
-







<title>News</title>

<b>Version History</b>

<p>
    <b>1.0.84.0 - January 9, 2013</b>
</p>
<ul>
    <li>Updated to <a href="http://www.sqlite.org/releaselog/3_7_15_2.html">SQLite 3.7.15.2</a>.</li>
    <li>Explicitly dispose of all SQLiteCommand objects managed by the DbDataAdapter class. Fix for [6434e23a0f].</li>
    <li>Add Cancel method to the SQLiteConnection class to interrupt a long running query.</li>
    <li>Improve thread safety of the SQLiteLog.LogMessage method.</li>
</ul>
<p>
    <b>1.0.83.0 - December 29, 2012</b>
    <b>1.0.83.0 - December XX, 2012 <font color="red">(release scheduled)</font></b>
</p>
<ul>
    <li>Updated to [http://www.sqlite.org/releaselog/3_7_15_1.html|SQLite 3.7.15.1].</li>
    <li>Updated to [http://www.sqlite.org/src/info/trunk|SQLite 3.7.15].</li>
    <li>Add Visual Studio 2012 support to all the applicable solution/project files, their associated supporting files, and the test suite.</li>
    <li>Add Visual Studio 2012 support to the redesigned designer support installer.</li>
    <li>Allow opened connections to skip adding the extension functions included in the interop assembly via the new NoExtensionFunctions connection flag.</li>
    <li>Support loading of SQLite extensions via the new EnableExtensions and LoadExtension methods of the SQLiteConnection class. Pursuant to [17045010df].</li>
    <li>Remove one set of surrounding single or double quotes from property names and values parsed from the connection string. Fix for [b4cc611998].</li>
    <li>Modify parsing of connection strings to allow property names and values to be quoted.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>Add ParseViaFramework property to the SQLiteConnection class to allow the built-in (i.e. framework provided) connection string parser to be used when opening a connection. Pursuant to [b4cc611998].</li>
    <li>Add notifications before and after any connection is opened and closed, as well as other related notifications, via the new static Changed event.</li>
    <li>Add an overload of the SQLiteLog.LogMessage method that takes a single string parameter.</li>
    <li>Add an overload of the SQLiteConnection.LogMessage method that takes a SQLiteErrorCode parameter.</li>
    <li>All applicable calls into the SQLite core library now return a SQLiteErrorCode instead of an integer error code.</li>
    <li>Make sure the error code of the SQLiteException class gets serialized.</li>
    <li>Make the test project for the .NET Compact Framework more flexible.</li>
    <li>When available, the new sqlite3_errstr function from the core library is used to get the error message for a specific return code.</li>
    <li>The SetMemoryStatus, Shutdown, ResultCode, ExtendedResultCode, and SetAvRetry methods of the SQLiteConnection class now return a SQLiteErrorCode instead of an integer error code.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>The public constructor for the SQLiteException now takes a SQLiteErrorCode instead of an integer error code.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>The ErrorCode property of the SQLiteException is now an Int32, to allow the property inherited from the base class to be properly overridden.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>The ErrorCode field of the LogEventArgs is now an object instead of an integer.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>The names and messages associated with the SQLiteErrorCode enumeration values have been normalized to match those in the SQLite core library.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>Implement more robust locking semantics for the CriticalHandle derived classes when compiled for the .NET Compact Framework.</li>
    <li>Cache column indexes as they are looked up when using the SQLiteDataReader to improve performance.</li>
    <li>Cache column indexes are they are looked up when using the SQLiteDataReader to improve performance.</li>
    <li>Prevent the SQLiteConnection.Close method from throwing non-fatal exceptions during its disposal.</li>
    <li>Rename the interop assembly functions sqlite3_cursor_rowid, sqlite3_context_collcompare, sqlite3_context_collseq, sqlite3_cursor_rowid, and sqlite3_table_cursor to include an &quot;_interop&quot; suffix.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>Prevent the LastInsertRowId, MemoryUsed, and MemoryHighwater connection properties from throwing NotSupportedException when running on the .NET Compact Framework. Fix for [dd45aba387].</li>
    <li>Improve automatic detection of the sqlite3_close_v2 function when compiled to use the standard SQLite library.</li>
    <li>Add protection against ThreadAbortException asynchronously interrupting native resource initialization and finalization.</li>
    <li>Add native logging callback for use with the sqlite3_log function to the interop assembly, enabled via the INTEROP_LOG preprocessor definition.</li>
    <li>Add various diagnostic messages to the interop assembly, enabled via flags in the INTEROP_DEBUG preprocessor definition.</li>
    <li>Further enhancements to the build and test automation.</li>
    <li>Add test automation for the Windows CE binaries.</li>
</ul>
<p>
    <b>1.0.82.0 - September 3, 2012</b>
</p>
<ul>
    <li>Updated to [http://www.sqlite.org/releaselog/3_7_14.html|SQLite 3.7.14].</li>