System.Data.SQLite

Check-in Differences
Login

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

Difference From 52bf1489f50cf1d8 To e34afc81002ef8f2

2013-02-27
07:26
Update SQLite core library to the latest trunk. check-in: 956d686069 user: mistachkin tags: trunk
07:08
Simplify the getBuildBaseDirectory test suite infrastructure helper procedure. check-in: e34afc8100 user: mistachkin tags: trunk
07:02
Enhance detection and handling of multiple sets of build output by the test suite. Update Eagle script library in externals to latest trunk. check-in: 7197d1e4c5 user: mistachkin tags: trunk
2012-12-29
17:49
Fix typo in comment. check-in: 5ccf6ab115 user: mistachkin tags: trunk
17:48
Add debug configurations to batch tools that build and test 'all' binaries. Adapt stress test so that it will work with the .NET Framework 4.5 installed. check-in: 52bf1489f5 user: mistachkin tags: trunk
13:45
Update Eagle in externals to the latest trunk. Modify connection pool test and infrastructure to prevent it from counting connections opened from the pool during the release process. check-in: 71ed45f357 user: mistachkin tags: trunk

Changes to .fossil-settings/ignore-glob.
1

2




*.mistachkin.eagle

Externals/Eagle/bin/Eagle*.pdb





>

>
>
>
>
1
2
3
4
5
6
7
*.mistachkin.eagle
*.sln
Externals/Eagle/bin/Eagle*.pdb
SQLite.Interop/*.vcxproj
SQLite.Interop/*.vcxproj.filters
System.Data.SQLite/*.csproj
testce/*.csproj
Changes to Doc/Extra/dbfactorysupport.html.
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.83.0, Culture=neutral,
                 PublicKeyToken=db937bc2d44ff139"/>
    </DbProviderFactories>
  </system.data>
</configuration>
</pre>
      </div>
      <p>







|







81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
&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.85.0, Culture=neutral,
                 PublicKeyToken=db937bc2d44ff139"/&gt;
    &lt;/DbProviderFactories&gt;
  &lt;/system.data&gt;
&lt;/configuration&gt;
</pre>
      </div>
      <p>
Changes to Doc/Extra/environment.html.
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
          <td>If this environment variable is set [to anything], the native
          library pre-loading functionality will be disabled.  By default,
          the native library pre-loading will attempt to load the native
          SQLite library from architecture-specific (e.g. "x86", "amd64",
          "x64") or platform-specific (e.g. "Win32") directories that reside
          underneath the application base directory.</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
          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>
        </tr>








        <tr valign="top">
          <td>PROCESSOR_ARCHITECTURE</td>
          <td>This environment variable is normally set by the operating
          system itself and should reflect the native processor architecture
          of the current process (e.g. a 32-bit x86 application running on a
          64-bit x64 operating system should have the value &quot;x86&quot;).
          </td>







>
>
>
>
>
>
>
>
>
















>
>
>
>
>
>
>
>







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
          <td>If this environment variable is set [to anything], the native
          library pre-loading functionality will be disabled.  By default,
          the native library pre-loading will attempt to load the native
          SQLite library from architecture-specific (e.g. "x86", "amd64",
          "x64") or platform-specific (e.g. "Win32") directories that reside
          underneath the application base directory.</td>
        </tr>
        <tr valign="top">
          <td>No_SQLiteFunctions</td>
          <td>If this environment variable is set [to anything], the initial
          search for types in all loaded assemblies that are tagged with the
          SQLiteFunction attribute will be skipped.  Normally, this search is
          conducted only once per application domain by the static constructor
          of the SQLiteFunction class; however, these implementation details
          are subject to change.</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
          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>
        </tr>
        <tr valign="top">
          <td>PreLoadSQLite_UseAssemblyDirectory</td>
          <td>If this environment variable is set [to anything], the location
          of the currently executing assembly (i.e. the one containing all the
          managed components for System.Data.SQLite) will be used as the basis
          for locating the the native library to pre-load (i.e. instead of
          using the application domain base directory).</td>
        </tr>
        <tr valign="top">
          <td>PROCESSOR_ARCHITECTURE</td>
          <td>This environment variable is normally set by the operating
          system itself and should reflect the native processor architecture
          of the current process (e.g. a 32-bit x86 application running on a
          64-bit x64 operating system should have the value &quot;x86&quot;).
          </td>
Changes to Doc/Extra/version.html.
39
40
41
42
43
44
45
























46
47
48
49
50
51
52
53
          </td>
        </tr>
      </table>
    </div>
    <div id="mainSection">
    <div id="mainBody">
    <h1 class="heading">Version History</h1>
























    <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>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>







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|







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.85.0 - March XX, 2013 <font color="red">(release scheduled)</font></b></p>
    <ul>
      <li>Updated to <a href="http://www.sqlite.org/src/info/trunk">SQLite 3.7.16</a>.</li>
      <li>Skip checking loaded assemblies for types tagged with the SQLiteFunction attribute when the No_SQLiteFunctions environment variable is set. Pursuant to <a href="http://system.data.sqlite.org/index.html/info/e4c8121f7b">[e4c8121f7b]</a>.</li>
      <li>Add HexPassword connection string property to work around the inability to include a literal semicolon in a connection string property value. Pursuant to <a href="http://system.data.sqlite.org/index.html/info/1c456ae75f">[1c456ae75f]</a>.</li>
      <li>Add static Execute method to the SQLiteCommand class.</li>
      <li>Support custom connection pool implementations by adding the ISQLiteConnectionPool interface, the static SQLiteConnection.ConnectionPool property, and the static CreateHandle method in addition to modifying the SQLiteConnectionPool class. Pursuant to <a href="http://system.data.sqlite.org/index.html/info/393d954be0">[393d954be0]</a>.</li>
      <li>Add public constructor to the SQLiteDataAdapter class that allows passing the parseViaFramework parameter to the SQLiteConnection constructor.</li>
      <li>When built with the CHECK_STATE compile-time option, skip throwing exceptions from the SQLiteDataReader class when the object is being disposed.</li>
      <li>Support automatic value conversions for columns with a declared type of BIGUINT, INTEGER8, INTEGER16, INTEGER32, INTEGER64, SMALLUINT, TINYSINT, UNSIGNEDINTEGER, UNSIGNEDINTEGER8, UNSIGNEDINTEGER16, UNSIGNEDINTEGER32, UNSIGNEDINTEGER64, INT8, INT16, INT32, INT64, UINT, UINT8, UINT16, UINT32, UINT64, or ULONG.</li>
      <li>Add BindUInt32AsInt64 connection flag to force binding of UInt32 values as Int64 instead. Pursuant to <a href="http://system.data.sqlite.org/index.html/info/c010fa6584">[c010fa6584]</a>.</li>
      <li>Add BindAllAsText connection flag to force binding of all values as text.</li>
      <li>Remove AUTOINCREMENT from the column type name map.&nbsp;<b>** Potentially Incompatible Change **</b></li>
      <li>Avoid throwing overflow exceptions from the SQLite3.GetValue method for integral column types. Partial fix for <a href="http://system.data.sqlite.org/index.html/info/c010fa6584">[c010fa6584]</a>.&nbsp;<b>** Potentially Incompatible Change **</b></li>
      <li>Use the legacy connection closing algorithm when built with the INTEROP_LEGACY_CLOSE compile-time option.</li>
      <li>Support using the directory containing the primary managed-only assembly as the basis for native library pre-loading.</li>
    </ul>
    <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 <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</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>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>
Changes to Doc/Extra/welcome.html.
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;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">







|







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;085&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/EagleShell.exe.mda.config.
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>
    <!--

    <bindingFailure />
    <callbackOnCollectedDelegate listSize="50" />
    <contextSwitchDeadlock enable="true" />
    <dangerousThreadingAPI />
    <dateTimeInvalidLocalFormat />
    <dirtyCastAndCallOnInterface />
    <disconnectedContext enable="true" />







|
>







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 * 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" />
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="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>







>













|


61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
    <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
    set result ""; eval append result $args
  }

  proc lappendArgs { args } {
    #
    # NOTE: This should work properly in both Tcl and Eagle.
    #
    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:
    #







|







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
  }

  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:
    #
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
              set components [list $baseUri releases $patchLevel]

              #
              # NOTE: Next, figure out what type of download is being
              #       requested.
              #
              switch -exact -nocase -- $type {
                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 {

                  #
                  # 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 EagleSetup $patchLevel .exe]
                  lappend components $fileName

                  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]]
                }
              }
            }
          }
        }
      }








|
<
<
<
<
<
<
<
<
<
<
<
|
>

|
<
|
|
|

|
<
|
<
<
>
|
<
|
<
<
<
<
<


|
|







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
              set components [list $baseUri releases $patchLevel]

              #
              # NOTE: Next, figure out what type of download is being
              #       requested.
              #
              switch -exact -nocase -- $type {
                source -











                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.
                  #
                  set fileName [appendArgs \

                      [info engine] [string totitle $type] $patchLevel \


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







                  lappend components $fileName

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

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

    proc tclLog { string } {
      #
      # NOTE: This should work properly in both Tcl and Eagle.
      #
      catch {puts stderr $string}
    }











    proc findDirectories { pattern } {







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







      foreach dir [split [exec -unicode $::env(ComSpec) /u /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]

          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 -exact -nocase $result $dir] == -1} then {
            lappend result $dir
          }
        }
      }

      return $result
    }

    proc findFiles { pattern } {







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







      foreach fileName [split [exec -unicode $::env(ComSpec) /u /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 -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] {
        set fileName [string trim $fileName]

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

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

      return $result
    }

    proc findFilesRecursive { pattern } {







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







      foreach fileName [split [exec -unicode $::env(ComSpec) /u /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 -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] {
        set fileName [string trim $fileName]

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

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

      return $result
    }








>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>



|
>
>
>
>
>
>








|












|









>
>
>
>
>
>
>



|
>
>
>
>
>
>








|












|









>
>
>
>
>
>
>



|
>
>
>
>
>
>








|












|







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

      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]

      #
      # 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] {
        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 {
            lappend result $fileName
          }
        }
      }

      foreach fileName [split [exec -unicode $::env(ComSpec) /u /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 {
            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]

      #
      # 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] {
        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 {
            lappend result $fileName
          }
        }
      }

      foreach fileName [split [exec -unicode $::env(ComSpec) /u /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 {
            lappend result $fileName
          }
        }
      }

      return $result
    }
1707
1708
1709
1710
1711
1712
1713







1714
1715
1716
1717
1718
1719
1720
      eval lappend result [glob -nocomplain -types {f hidden} \
          [file normalize $pattern]]

      return $result
    }

    proc findFilesRecursive { pattern } {







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

      catch {
        foreach fileName [split [exec $::env(ComSpec) /c dir /a-d /s /b \







>
>
>
>
>
>
>







1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
      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 \
1794
1795
1796
1797
1798
1799
1800
1801

1802
1803




1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
    }

    #
    # NOTE: Exports the necessary commands from this package and import them
    #       into the global namespace.
    #
    exportAndImportPackageCommands [namespace current] [list \
        exportAndImportPackageCommands isEagle isMono getEnvironmentVariable \

        getPluginPath getDictionaryValue getColumnValue getRowColumnValue \
        appendArgs haveGaruda lappendArgs readFile writeFile filter map \




        reduce 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"}]
}








|
>
|
|
>
>
>
>
|













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

    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







|
|







384
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 -machine -match -no -notFile -platform -postTest -preTest \
        -skip -stopOnFailure -suffix -tclsh -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
486
487
488
489
490
491
492


493






494
495
496
497
498
499
500
501
502
503
      #
      return [file normalize [file dirname [info nameofexecutable]]]
    }
  }

  proc getFiles { directory pattern } {
    if {[isEagle]} then {


      return [lsort -dictionary [file list $directory $pattern]]






    } else {
      return [lsort -dictionary [glob -directory $directory -types \
          {b c f p s} -nocomplain -- $pattern]]
    }
  }

  proc getTestFiles { directories matchFilePatterns skipFilePatterns } {
    set result [list]

    foreach directory $directories {







>
>
|
>
>
>
>
>
>


|







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
      #
      return [file normalize [file dirname [info nameofexecutable]]]
    }
  }

  proc getFiles { directory pattern } {
    if {[isEagle]} then {
      set result [list]

      foreach fileName [lsort -dictionary [file list $directory $pattern]] {
        if {[file isfile $fileName] && [file readable $fileName]} then {
          lappend result $fileName
        }
      }

      return $result
    } else {
      return [lsort -dictionary [glob -directory $directory -types \
          {f r} -nocomplain -- $pattern]]
    }
  }

  proc getTestFiles { directories matchFilePatterns skipFilePatterns } {
    set result [list]

    foreach directory $directories {
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
          }

          #
          # NOTE: We evaluated another test file.
          #
          incr count

          #
          # NOTE: In terms of files, not tests, what percent done are we now?
          #
          set percent [formatDecimal \
              [expr {$total != 0 ? 100.0 * ($count / double($total)) : 100}]]

          if {$percent != $lastPercent} then {
            reportTestPercent $channel $percent \
                [llength $failed] [llength $leaked]

            set lastPercent $percent
          }

          #
          # NOTE: Record failed test count after this file.
          #
          if {[isEagle]} then {
            set after $::eagle_tests(failed)
          } else {
            set after $::tcltest::numTests(Failed)
          }

          #
          # NOTE: Did this file have any failing tests?
          #
          if {$after > $before} then {
            lappend failed [file tail $fileName]
          }














          #
          # NOTE: Unset the current test file name, it is no longer
          #       needed.
          #
          unset -nocomplain ::test_file








<
<
<
<
<
<
<
<
<
<
<
<
<















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







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
          }

          #
          # NOTE: We evaluated another test file.
          #
          incr count














          #
          # NOTE: Record failed test count after this file.
          #
          if {[isEagle]} then {
            set after $::eagle_tests(failed)
          } else {
            set after $::tcltest::numTests(Failed)
          }

          #
          # NOTE: Did this file have any failing tests?
          #
          if {$after > $before} then {
            lappend failed [file tail $fileName]
          }

          #
          # NOTE: In terms of files, not tests, what percent done are we now?
          #
          set percent [formatDecimal \
              [expr {$total != 0 ? 100.0 * ($count / double($total)) : 100}]]

          if {$percent != $lastPercent} then {
            reportTestPercent $channel $percent \
                [llength $failed] [llength $leaked]

            set lastPercent $percent
          }

          #
          # NOTE: Unset the current test file name, it is no longer
          #       needed.
          #
          unset -nocomplain ::test_file

1316
1317
1318
1319
1320
1321
1322






1323
1324
1325
1326
1327
1328
1329
            #
            # NOTE: Determine if any resource leaks have occurred and
            #       output diagnostics as necessary if they have.
            #
            reportTestStatistics $channel $fileName leaks leaked
          }
        } else {






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








>
>
>
>
>
>







1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
            #
            # 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
        }

1345
1346
1347
1348
1349
1350
1351






1352
1353
1354
1355
1356
1357
1358
        #       test failure with the stop-on-failure flag enabled),
        #       break out of the test loop now.
        #
        if {$stop} then {
          break
        }
      } else {






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








>
>
>
>
>
>







1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
        #       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
      }

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
    }

    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 ""







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
















|
|
<





|







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
1869
1870
1871

1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
    }

    proc getTkVersion {} {
      return [testExecTclScript {
        puts -nonewline stdout [package require Tk]; exit
      }]
    }

    proc getTestMachine {} {
      #
      # NOTE: Determine the effective test machine and return it.  If the
      #       test machine cannot be determined, return an empty string.
      #
      if {[info exists ::test_flags(-machine)] && \
          [string length $::test_flags(-machine)] > 0} then {
        #
        # NOTE: The test machine has been manually overridden via the test
        #       flags; therefore, use it.
        #
        return $::test_flags(-machine)
      } elseif {[info exists ::test_machine]} then {
        #
        # NOTE: Use the test machine.  The default value is set by the test
        #       suite prologue; however, this may have been overridden.
        #
        return $::test_machine
      } elseif {[info exists ::tcl_platform(machine)]} then {
        #
        # NOTE: Use the build machine of Eagle itself.
        #
        return $::tcl_platform(machine)
      } else {
        #
        # NOTE: We are missing the machine, return nothing.
        #
        return ""
      }
    }

    proc getTestPlatform {} {
      #
      # NOTE: Determine the effective test platform and return it.  If the
      #       test platform cannot be determined, return an empty string.
      #
      if {[info exists ::test_flags(-platform)] && \
          [string length $::test_flags(-platform)] > 0} then {
        #
        # NOTE: The test platform has been manually overridden via the test
        #       flags; therefore, use it.
        #
        return $::test_flags(-platform)
      } elseif {[info exists ::test_platform]} then {
        #
        # NOTE: Use the test platform.  The default value is set by the test
        #       suite prologue; however, this may have been overridden.
        #
        return $::test_platform
      } else {
        set machine [getTestMachine]

        if {[string length $machine] > 0} then {
          #
          # NOTE: Use the machine architecture to figure out the platform
          #       and then return it.
          #
          return [machineToPlatform $machine]
        } else {
          #
          # NOTE: We are missing the machine and we cannot figure out the
          #       platform without it; therefore, return nothing.
          #
          return ""
        }
      }
    }

    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 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
        #       most likely be either "Debug" or "Release".
        #
        return $::eagle_platform(configuration)
      } else {
        #
        # NOTE: We are missing the configuration, return nothing.
        #
        return ""
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
      configureTcltest [list] [list test testConstraint] false
    }

    #
    # NOTE: We need several of our test related commands in the global
    #       namespace as well.
    #
    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

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

  #
  # NOTE: Provide the Eagle test package to the interpreter.
  #
  package provide Eagle.Test \
    [expr {[isEagle] ? [info engine PatchLevel] : "1.0"}]
}








|
>
>
|
|
|
<
|
>
>
>
|
|
|













2138
2139
2140
2141
2142
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
      configureTcltest [list] [list test testConstraint] false
    }

    #
    # NOTE: We need several of our test related commands in the global
    #       namespace as well.
    #
    exportAndImportPackageCommands [namespace current] [list \
        tputs tlog getSoftwareRegistryKey haveConstraint addConstraint \
        haveOrAddConstraint getConstraints removeConstraint fixConstraints \
        calculateBogoCops calculateRelativePerformance sourceIfValid \
        processTestArguments getTclShellFileName getTemporaryPath getFiles \
        getTestFiles getTestRunId getTestLogId getTestLog testExec \

        testClrExec execTestShell isStopOnFailure isExitOnComplete \
        returnInfoScript runTestPrologue runTestEpilogue hookPuts unhookPuts \
        runTest testShim tsource recordTestStatistics reportTestStatistics \
        formatList formatListAsDict pathToRegexp inverseLsearchGlob \
        removePathFromFileNames formatDecimal clearTestPercent \
        reportTestPercent runAllTests configureTcltest machineToPlatform \
        getPassPercentage getSkipPercentage] 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
        if {![uplevel 1 [list info exists $varName]]} then {
          continue
        }

        incr result

        if {!$quiet} then {

          tqputs $channel [appendArgs \
              "---- found vendor-specific test override \"" $varName \
              "\" 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







>
|
|
|
>







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
        if {![uplevel 1 [list info exists $varName]]} then {
          continue
        }

        incr result

        if {!$quiet} then {
          catch {
            tqputs $channel [appendArgs \
                "---- found vendor-specific test override \"" $varName \
                "\" 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
106
107
108
109
110
111
112

113
114
115

116
117
118
119
120
121
122
          #
          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 {

              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).
            #







>
|
|
|
>







108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
          #
          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"]
              }
            }

            #
            # 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).
            #
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 {

        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 {

          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

    #
    # 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.







>
|
|
>
















>
|
|
>












|
>







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
        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"
        }
      }

      #
      # 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]
          }
        }
      }
    }

    #
    # 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_configurations test_constraints \
        test_machine test_overrides test_platform test_year test_years \
        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.
16
17
18
19
20
21
22











23
24
25
26
27
28
29

#
# NOTE: Use our own namespace here because even though we do not directly
#       support namespaces ourselves, we do not want to pollute the global
#       namespace if this script actually ends up being evaluated in Tcl.
#
namespace eval ::Eagle {











  proc checkForPlatform { channel } {
    tputs $channel "---- checking for platform... "

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

      tputs $channel [appendArgs $::tcl_platform(platform) \n]







>
>
>
>
>
>
>
>
>
>
>







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

#
# NOTE: Use our own namespace here because even though we do not directly
#       support namespaces ourselves, we do not want to pollute the global
#       namespace if this script actually ends up being evaluated in Tcl.
#
namespace eval ::Eagle {
  proc getKnownMonoVersions {} {
    #
    # NOTE: This job of this procedure is to return the list of "known"
    #       versions of Mono supported by the test suite infrastructure.
    #
    return [list \
        [list 2 0] [list 2 2] [list 2 4] [list 2 6] [list 2 8] [list 2 10] \
        [list 2 11] [list 2 12] [list 3 0] [list 3 1] [list 3 2] [list 3 3] \
        [list 3 4] [list 3 5] [list 3 6]]
  }

  proc checkForPlatform { channel } {
    tputs $channel "---- checking for platform... "

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

      tputs $channel [appendArgs $::tcl_platform(platform) \n]
40
41
42
43
44
45
46


47
48
49
50
51
52
53
54
55
56
57
      if {![info exists ::no(runtimeVersion)]} then {
        set constraints [list monoToDo monoBug monoCrash]

        #
        # NOTE: Add the necessary constraints for each version of Mono that
        #       we know about.
        #


        foreach version [list 20 22 24 26 28 210 211 212 30] {
          addConstraint [appendArgs monoToDo $version]
          addConstraint [appendArgs monoBug $version]
          addConstraint [appendArgs monoCrash $version]
        }

        #
        # NOTE: Also add just the generic Mono constraints that do not have
        #       a trailing version.
        #
        foreach constraint $constraints {







>
>
|
|
|
|







51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
      if {![info exists ::no(runtimeVersion)]} then {
        set constraints [list monoToDo monoBug monoCrash]

        #
        # NOTE: Add the necessary constraints for each version of Mono that
        #       we know about.
        #
        foreach monoVersion [getKnownMonoVersions] {
          set constraintVersion [join $monoVersion ""]

          addConstraint [appendArgs monoToDo $constraintVersion]
          addConstraint [appendArgs monoBug $constraintVersion]
          addConstraint [appendArgs monoCrash $constraintVersion]
        }

        #
        # NOTE: Also add just the generic Mono constraints that do not have
        #       a trailing version.
        #
        foreach constraint $constraints {
592
593
594
595
596
597
598


























599
600
601
602
603
604
605
      addConstraint [appendArgs command. $name]

      tputs $channel yes\n
    } else {
      tputs $channel no\n
    }
  }



























  proc checkForTestConfiguration { channel } {
    tputs $channel "---- checking for test configuration... "

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







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







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
      addConstraint [appendArgs command. $name]

      tputs $channel yes\n
    } else {
      tputs $channel no\n
    }
  }

  proc checkForTestMachine { channel } {
    tputs $channel "---- checking for test machine... "

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

      tputs $channel [appendArgs $::test_machine \n]
    } else {
      tputs $channel unknown\n
    }
  }

  proc checkForTestPlatform { channel } {
    tputs $channel "---- checking for test platform... "

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

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

    if {[info exists ::test_configuration] && \
        [string length $::test_configuration] > 0} then {
      addConstraint [appendArgs configuration. $::test_configuration]
939
940
941
942
943
944
945















946
947
948
949
950
951
952
      addConstraint performance

      tputs $channel yes\n
    } else {
      tputs $channel no\n
    }
  }
















  proc checkForInteractive { channel } {
    tputs $channel "---- checking for interactive user... "

    #
    # NOTE: Is there an interactive user?
    #







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







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
      addConstraint performance

      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?
    #
1114
1115
1116
1117
1118
1119
1120


























































































1121
1122
1123
1124
1125
1126
1127
        addConstraint softwareUpdate

        tputs $channel trusted\n
      } else {
        tputs $channel untrusted\n
      }
    }


























































































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

      if {[catch {object invoke Interpreter.GetActive GetStrongName} \
              strongName] == 0 && \
          [string length $strongName] > 0} then {







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







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
        addConstraint softwareUpdate

        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.
            #
            if {![info exists ::no(setMdas)]} then {
              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 {
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
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
1435
1436
1437

        tputs $channel [appendArgs $::eagle_platform(imageRuntimeVersion) \
            " " ( $dotVersion ) \n]
      } else {
        tputs $channel no\n
      }
    }

































    proc checkForRuntimeVersion { channel } {
      tputs $channel "---- checking for runtime version... "

      if {[info exists ::eagle_platform(runtimeVersion)] && \
          [string length $::eagle_platform(runtimeVersion)] > 0} then {
        #
        # NOTE: Get the major and minor portions of the version only.
        #
        set dotVersion [join [lrange [split \
            $::eagle_platform(runtimeVersion) .] 0 1] .]

        #
        # NOTE: Now create a version string for use in the constraint name
        #       (remove the periods).
        #
        set version [string map [list . ""] $dotVersion]

        if {[isMono]} then {




          if {[string length $version] > 0} then {
              #
              # NOTE: We are running on Mono.  Keep track of the specific
              #       version for usage in test constraints.
              #
              addConstraint [appendArgs mono $version]
          }

          if {[string length $dotVersion] > 0 && \
              [regexp -- {^(\d+)\.(\d+)$} $dotVersion dummy \
                  majorVersion minorVersion]} then {
            set monoVersions [list]

            #
            # NOTE: Check for any Mono version 2.x or higher.
            #
            if {$majorVersion >= 2} then {
              #
              # NOTE: Check for any Mono version higher than 2.0.
              #
              if {$majorVersion > 2 || $minorVersion > 0} then {
                lappend monoVersions 20
              }

              #
              # NOTE: Check for any Mono version higher than 2.2.

              #
              if {$majorVersion > 2 || $minorVersion > 2} then {
                lappend monoVersions 22
              }

              #
              # NOTE: Check for any Mono version higher than 2.4.
              #
              if {$majorVersion > 2 || $minorVersion > 4} then {
                lappend monoVersions 24
              }

              #
              # NOTE: Check for any Mono version higher than 2.6.
              #
              if {$majorVersion > 2 || $minorVersion > 6} then {
                lappend monoVersions 26
              }

              #
              # NOTE: Check for any Mono version higher than 2.8.
              #
              if {$majorVersion > 2 || $minorVersion > 8} then {
                lappend monoVersions 28
              }

              #
              # NOTE: Check for any Mono version higher than 2.10.
              #
              if {$majorVersion > 2 || $minorVersion > 10} then {
                lappend monoVersions 210
              }

              #
              # NOTE: Check for any Mono version higher than 2.11.
              #
              if {$majorVersion > 2 || $minorVersion > 11} then {
                lappend monoVersions 211
              }

              #
              # NOTE: Check for any Mono version higher than 2.12.
              #
              if {$majorVersion > 2 || $minorVersion > 12} then {
                lappend monoVersions 212
              }
            }



            #
            # NOTE: Check for any Mono version 3.x or higher.
            #
            if {$majorVersion >= 3} then {
              #
              # NOTE: Check for any Mono version higher than 3.0.
              #
              if {$majorVersion > 3 || $minorVersion > 0} then {
                lappend monoVersions 30
              }
            }

            #
            # NOTE: Add the necessary constraints for each version of Mono we
            #       should NOT skip bugs for.
            #
            foreach monoVersion $monoVersions {
              addConstraint [appendArgs monoToDo $monoVersion]
              addConstraint [appendArgs monoBug $monoVersion]
              addConstraint [appendArgs monoCrash $monoVersion]
            }
          }
        } else {




          if {[string length $version] > 0} then {
            #
            # NOTE: We are running on the .NET Framework.  Keep track of the
            #       specific version for usage in test constraints.
            #
            addConstraint [appendArgs dotNet $version]

          }

          #
          # NOTE: We do not want to skip any Mono bugs on .NET.  Add the
          #       necessary constraints for each version of Mono we know
          #       about.
          #
          foreach monoVersion [list 20 22 24 26 28 210 211 212 30] {


            addConstraint [appendArgs monoToDo $monoVersion]
            addConstraint [appendArgs monoBug $monoVersion]
            addConstraint [appendArgs monoCrash $monoVersion]
          }
        }

        tputs $channel [appendArgs $::eagle_platform(runtimeVersion) \
            " " ( $dotVersion ) \n]
      } else {
        tputs $channel no\n







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



















>
>
>
>






<
|
<
<
<
<
|
|
<
|
|
|
<
|
<
|
<
|
|
|
>
|
<
|
|
|
<
|
|
<
|
<
|
<
|

|
<
<
|
<
|
|
<
<
<
|
<
<
<
|
<
<
|
|
|
|
<
|
|
|
<
<
<
<
<
|
|
|
>
>

<
<
<
<
<
<
<
|
<
<
|
|
<
<
<
|
|
|
|



>
>
>
>






>







|
>
>
|
|
|







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
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502

1503




1504
1505

1506
1507
1508

1509

1510

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

        tputs $channel [appendArgs $::eagle_platform(imageRuntimeVersion) \
            " " ( $dotVersion ) \n]
      } else {
        tputs $channel no\n
      }
    }

    proc checkForFrameworkVersion { channel } {
      tputs $channel "---- checking for framework version... "

      if {[info exists ::eagle_platform(frameworkVersion)] && \
          [string length $::eagle_platform(frameworkVersion)] > 0} then {
        #
        # NOTE: Get the major and minor portions of the version only.
        #
        set dotVersion [join [lrange [split \
            $::eagle_platform(frameworkVersion) .] 0 1] .]

        #
        # NOTE: Now create a version string for use in the constraint name
        #       (remove the periods).
        #
        set version [string map [list . ""] $dotVersion]

        #
        # NOTE: If the framework version was found, add a test constraint
        #       for it now.
        #
        if {[string length $version] > 0} then {
          addConstraint [appendArgs framework $version]
        }

        tputs $channel [appendArgs $::eagle_platform(frameworkVersion) \
            " " ( $dotVersion ) \n]
      } else {
        tputs $channel no\n
      }
    }

    proc checkForRuntimeVersion { channel } {
      tputs $channel "---- checking for runtime version... "

      if {[info exists ::eagle_platform(runtimeVersion)] && \
          [string length $::eagle_platform(runtimeVersion)] > 0} then {
        #
        # NOTE: Get the major and minor portions of the version only.
        #
        set dotVersion [join [lrange [split \
            $::eagle_platform(runtimeVersion) .] 0 1] .]

        #
        # NOTE: Now create a version string for use in the constraint name
        #       (remove the periods).
        #
        set version [string map [list . ""] $dotVersion]

        if {[isMono]} then {
          #
          # NOTE: If the runtime version was found, add a test constraint
          #       for it now.
          #
          if {[string length $version] > 0} then {
              #
              # NOTE: We are running on Mono.  Keep track of the specific
              #       version for usage in test constraints.
              #
              addConstraint [appendArgs mono $version]

              addConstraint [appendArgs mono $version OrHigher]




          }


          #
          # NOTE: Attempt to parse the version into its major and minor
          #       components.

          #

          if {[string length $dotVersion] > 0 && [regexp -- {^(\d+)\.(\d+)$} \

              $dotVersion dummy majorVersion minorVersion]} then {
            #
            # NOTE: This is the list of Mono versions to add test
            #       constraints for.
            #

            set monoVersions [list]

            #

            # NOTE: Check each Mono version "known" to the test suite.
            #

            foreach monoVersion [getKnownMonoVersions] {

              #

              # NOTE: Check for any Mono major version X or higher.
              #
              if {$majorVersion >= [lindex $monoVersion 0]} then {


                #

                # NOTE: Check for any Mono major/minor version higher
                #       than X.Y.



                #



                if {$majorVersion > [lindex $monoVersion 0] || \


                    $minorVersion > [lindex $monoVersion 1]} then {
                  #
                  # NOTE: Add this "known" version of Mono.
                  #

                  lappend monoVersions $monoVersion
                }
              }





            }

            #
            # NOTE: Add the necessary constraints for each version of Mono
            #       we should NOT skip bugs for.
            #







            foreach monoVersion $monoVersions {


              set constraintVersion [join $monoVersion ""]




              addConstraint [appendArgs mono $constraintVersion OrHigher]
              addConstraint [appendArgs monoToDo $constraintVersion]
              addConstraint [appendArgs monoBug $constraintVersion]
              addConstraint [appendArgs monoCrash $constraintVersion]
            }
          }
        } else {
          #
          # NOTE: If the runtime version was found, add a test constraint
          #       for it now.
          #
          if {[string length $version] > 0} then {
            #
            # NOTE: We are running on the .NET Framework.  Keep track of the
            #       specific version for usage in test constraints.
            #
            addConstraint [appendArgs dotNet $version]
            addConstraint [appendArgs dotNet $version OrHigher]
          }

          #
          # NOTE: We do not want to skip any Mono bugs on .NET.  Add the
          #       necessary constraints for each version of Mono we know
          #       about.
          #
          foreach monoVersion [getKnownMonoVersions] {
            set constraintVersion [join $monoVersion ""]

            addConstraint [appendArgs monoToDo $constraintVersion]
            addConstraint [appendArgs monoBug $constraintVersion]
            addConstraint [appendArgs monoCrash $constraintVersion]
          }
        }

        tputs $channel [appendArgs $::eagle_platform(runtimeVersion) \
            " " ( $dotVersion ) \n]
      } else {
        tputs $channel no\n
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
          #
          addConstraint wix

          #
          # NOTE: Save the directory for later usage by
          #       the test itself.
          #

          set ::test_wix $directory


          #
          # NOTE: Show where we found it.
          #
          tputs $channel [appendArgs "yes (" $version ", via " $where ", \"" \
              $directory "\")\n"]

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

      tputs $channel no\n
    }




























    proc checkForNetFx45 { channel } {
      tputs $channel "---- checking for .NET Framework 4.5... "

      #
      # NOTE: Platform must be Windows for this constraint to even be
      #       checked (i.e. we require the registry).







>
|
>
















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







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
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
          #
          addConstraint wix

          #
          # NOTE: Save the directory for later usage by
          #       the test itself.
          #
          if {![info exists ::no(setWix)]} then {
            set ::test_wix $directory
          }

          #
          # NOTE: Show where we found it.
          #
          tputs $channel [appendArgs "yes (" $version ", via " $where ", \"" \
              $directory "\")\n"]

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

      tputs $channel no\n
    }

    proc checkForTargetFramework { channel } {
      tputs $channel "---- checking for target framework... "

      if {[info exists ::eagle_platform(targetFramework)] && \
          [string length $::eagle_platform(targetFramework)] > 0} then {
        #
        # NOTE: Now create a string for use in the constraint name (remove
        #       the invalid characters).  For example:
        #
        #       ".NETFramework,Version=v2.0" --> "NETFramework.Version.v2.0"
        #
        set targetFramework [string trimleft [string map [list , . = .] \
            $::eagle_platform(targetFramework)] .]

        #
        # NOTE: Keep track of the specific target framework for usage in test
        #       constraints.
        #
        addConstraint [appendArgs targetFramework. $targetFramework]

        tputs $channel [appendArgs $::eagle_platform(targetFramework) \
            " " ( $targetFramework ) \n]
      } else {
        tputs $channel no\n
      }
    }

    proc checkForNetFx45 { channel } {
      tputs $channel "---- checking for .NET Framework 4.5... "

      #
      # NOTE: Platform must be Windows for this constraint to even be
      #       checked (i.e. we require the registry).
2144
2145
2146
2147
2148
2149
2150

2151

2152
2153
2154
2155
2156
2157
2158
            #
            lappend visualStudioVersions [lindex $version 1]

            #
            # NOTE: Save the directory for later usage by
            #       the test itself.
            #

            set ::test_visual_studio [file dirname $fileName]

          }
        }
      }

      if {[llength $visualStudioVersions] > 0} then {
        #
        # NOTE: Show where we found the latest version.







>
|
>







2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
            #
            lappend visualStudioVersions [lindex $version 1]

            #
            # NOTE: Save the directory for later usage by
            #       the test itself.
            #
            if {![info exists ::no(setVisualStudio)]} then {
              set ::test_visual_studio [file dirname $fileName]
            }
          }
        }
      }

      if {[llength $visualStudioVersions] > 0} then {
        #
        # NOTE: Show where we found the latest version.
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
2292
2293
2294
2295
2296
    ############################# BEGIN Tcl ONLY ##############################
    ###########################################################################

    #
    # 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 \
        checkForTestSuffix checkForVariable checkForScriptLibrary \
        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"}]
}








|
>
>
>
|
|
>
>
|
|
<
|
<
<
|













2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461

2462


2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
    ############################# BEGIN Tcl ONLY ##############################
    ###########################################################################

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

        checkForInteractiveCommand checkForUserInteraction checkForNetwork \


        checkForCompileOption] 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.
236
237
238
239
240
241
242


243
244
245
246
247
248
249
  }

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

  #
  # NOTE: If command line arguments were supplied, process them now.
  #


  set test_flags(-configuration) ""; # build configuration, default to empty.
  set test_flags(-suffix) ""; # build suffix, default to empty.
  set test_flags(-file) [list *.eagle]; # default to running all test files.
  set test_flags(-notFile) [list l.*.eagle]; # COMPAT: Tcl.
  set test_flags(-match) [list *]; # default to running all tests.
  set test_flags(-skip) [list]; # default to skipping no tests.
  set test_flags(-constraints) [list]; # default to no manual constraints.







>
>







236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
  }

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

  #
  # NOTE: If command line arguments were supplied, process them now.
  #
  set test_flags(-machine) ""; # machine architecture, default to empty.
  set test_flags(-platform) ""; # build platform, default to empty.
  set test_flags(-configuration) ""; # build configuration, default to empty.
  set test_flags(-suffix) ""; # build suffix, default to empty.
  set test_flags(-file) [list *.eagle]; # default to running all test files.
  set test_flags(-notFile) [list l.*.eagle]; # COMPAT: Tcl.
  set test_flags(-match) [list *]; # default to running all tests.
  set test_flags(-skip) [list]; # default to skipping no tests.
  set test_flags(-constraints) [list]; # default to no manual constraints.
322
323
324
325
326
327
328















329
330
331
332
333
334
335
        [string length $test_flags(-postTest)] > 0} then {
      #
      # NOTE: Set the pre-test script to the one provided by the command line.
      #
      set test_script(post) $test_flags(-postTest)
    }
  }
















  #
  # NOTE: Set the default test configuration (i.e. Debug or Release), if
  #       necessary.
  #
  if {![info exists test_configuration]} then {
    set test_configuration [getPlatformInfo configuration Release]







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







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
        [string length $test_flags(-postTest)] > 0} then {
      #
      # NOTE: Set the pre-test script to the one provided by the command line.
      #
      set test_script(post) $test_flags(-postTest)
    }
  }

  #
  # NOTE: Set the default test machine (e.g. amd64, intel, etc), if necessary.
  #
  if {![info exists test_machine]} then {
    set test_machine [expr {[info exists tcl_platform(machine)] ? \
        $tcl_platform(machine) : ""}]
  }

  #
  # NOTE: Set the default test platform (e.g. x86, x64, etc), if necessary.
  #
  if {![info exists test_platform]} then {
    set test_platform [machineToPlatform $test_machine true]
  }

  #
  # NOTE: Set the default test configuration (i.e. Debug or Release), if
  #       necessary.
  #
  if {![info exists test_configuration]} then {
    set test_configuration [getPlatformInfo configuration Release]
440
441
442
443
444
445
446








447
448
449
450
451
452
453
      [getTestRunId] \n]

  tputs $test_channel [appendArgs "---- processId: " \
      [pid] \n]

  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] ? \







>
>
>
>
>
>
>
>







457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
      [getTestRunId] \n]

  tputs $test_channel [appendArgs "---- processId: " \
      [pid] \n]

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

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

  tputs $test_channel [appendArgs "---- test platform: " \
      [expr {[info exists test_platform] ? \
          $test_platform : "<none>"}] \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] ? \
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695








696
697
698
699
700
701
702
703
704
    #       checking [nearly] first as it may skip other constraints.
    #
    if {![info exists no(runtime)]} then {
      checkForRuntime $test_channel
    }

    #
    # NOTE: Check the runtime version (i.e. what version of the runtime
    #       are we currently running on?).
    #
    if {![info exists no(runtimeVersion)]} then {
      checkForRuntimeVersion $test_channel
    }

    #








    # NOTE: Check the image runtime version (i.e. what version of the
    #       runtime was this assembly compiled against?).
    #
    if {![info exists no(imageRuntimeVersion)]} then {
      checkForImageRuntimeVersion $test_channel
    }

    #
    # NOTE: Has machine detection support been disabled?







|
|






>
>
>
>
>
>
>
>
|
|







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
    #       checking [nearly] first as it may skip other constraints.
    #
    if {![info exists no(runtime)]} then {
      checkForRuntime $test_channel
    }

    #
    # NOTE: Check the variant and/or version of the CLR that we are
    #       currently running on.
    #
    if {![info exists no(runtimeVersion)]} then {
      checkForRuntimeVersion $test_channel
    }

    #
    # NOTE: Check the framework version (i.e. regardless of runtime) that
    #       we are currently running on.
    #
    if {![info exists no(frameworkVersion)]} then {
      checkForFrameworkVersion $test_channel
    }

    #
    # NOTE: Check the image runtime version (i.e. the runtime version that
    #       this assembly compiled against).
    #
    if {![info exists no(imageRuntimeVersion)]} then {
      checkForImageRuntimeVersion $test_channel
    }

    #
    # NOTE: Has machine detection support been disabled?
1367
1368
1369
1370
1371
1372
1373









1374
1375
1376
1377
1378
1379
1380

        #
        # NOTE: For test "object-4.1".
        #
        checkForObjectMember $test_channel Eagle._Tests.Default \
            *TestExpr*










        #
        # NOTE: For test "object-7.1".
        #
        checkForObjectMember $test_channel Eagle._Tests.Default \
            *TestByRefValueTypeMethod*

        checkForObjectMember $test_channel Eagle._Tests.Default \







>
>
>
>
>
>
>
>
>







1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422

        #
        # NOTE: For test "object-4.1".
        #
        checkForObjectMember $test_channel Eagle._Tests.Default \
            *TestExpr*

        #
        # NOTE: For test "array-4.1".
        #
        checkForObjectMember $test_channel Eagle._Tests.Default \
            *TestTwoByteArrays*

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

        #
        # NOTE: For test "object-7.1".
        #
        checkForObjectMember $test_channel Eagle._Tests.Default \
            *TestByRefValueTypeMethod*

        checkForObjectMember $test_channel Eagle._Tests.Default \
1521
1522
1523
1524
1525
1526
1527







1528
1529
1530
1531
1532
1533
1534
    if {![info exists no(netFx45)]} then {
      #
      # NOTE: For test "object-12.1.*".
      #
      checkForNetFx45 $test_channel
    }








    #
    # NOTE: Has Visual Studio testing support been disabled?
    #
    if {![info exists no(visualStudio)]} then {
      checkForVisualStudio $test_channel
    }








>
>
>
>
>
>
>







1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
    if {![info exists no(netFx45)]} then {
      #
      # NOTE: For test "object-12.1.*".
      #
      checkForNetFx45 $test_channel
    }

    #
    # NOTE: Has target framework testing support been disabled?
    #
    if {![info exists no(targetFramework)]} then {
      checkForTargetFramework $test_channel
    }

    #
    # NOTE: Has Visual Studio testing support been disabled?
    #
    if {![info exists no(visualStudio)]} then {
      checkForVisualStudio $test_channel
    }

1544
1545
1546
1547
1548
1549
1550








1551
1552
1553
1554
1555
1556
1557

    #
    # NOTE: Has managed debugger testing support been disabled?
    #
    if {![info exists no(managedDebugger)]} then {
      checkForManagedDebugger $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







>
>
>
>
>
>
>
>







1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614

    #
    # 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
1653
1654
1655
1656
1657
1658
1659














1660
1661
1662
1663
1664
1665
1666

  #############################################################################
  ####################### BEGIN Tcl & Eagle Constraints #######################
  #############################################################################

  tputs $test_channel [appendArgs \
      "---- start of common (Tcl & Eagle) test constraints...\n"]















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







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







1710
1711
1712
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

  #############################################################################
  ####################### BEGIN Tcl & Eagle Constraints #######################
  #############################################################################

  tputs $test_channel [appendArgs \
      "---- start of common (Tcl & Eagle) test constraints...\n"]

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

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

  #
  # NOTE: Has checking for the test configuration been disabled?
  #
  if {![info exists no(testConfiguration)]} then {
    checkForTestConfiguration $test_channel
  }
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
    if {![info exists no(sqlite3.dll)]} then {
      checkForFile $test_channel [file join $bin_path sqlite3.dll]

      #
      # NOTE: Did we manage to find the native SQLite library?  If not, do we
      #       at least know the machine type?
      #
      if {![haveConstraint file_sqlite3.dll] && \
          [info exists tcl_platform(machine)]} then {
        #
        # NOTE: Ok, now try to check for the machine specific native SQLite
        #       library.
        #
        checkForFile $test_channel [file join $bin_path [machineToPlatform \
            $tcl_platform(machine) true] sqlite3.dll]

        #
        # NOTE: Did we manage to find the native SQLite library yet?
        #
        if {![haveConstraint file_sqlite3.dll]} then {
          #
          # NOTE: Ok, now try to check for the platform specific native SQLite
          #       library.
          #
          checkForFile $test_channel [file join $bin_path [machineToPlatform \
              $tcl_platform(machine) false] sqlite3.dll]
        }
      }
    }

    if {![info exists no(System.Data.SQLite.dll)]} then {
      checkForFile $test_channel [file join $bin_path System.Data.SQLite.dll]
    }







|
<





|










|







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
    if {![info exists no(sqlite3.dll)]} then {
      checkForFile $test_channel [file join $bin_path sqlite3.dll]

      #
      # NOTE: Did we manage to find the native SQLite library?  If not, do we
      #       at least know the machine type?
      #
      if {![haveConstraint file_sqlite3.dll]} then {

        #
        # NOTE: Ok, now try to check for the machine specific native SQLite
        #       library.
        #
        checkForFile $test_channel [file join $bin_path [machineToPlatform \
            $test_machine true] sqlite3.dll]

        #
        # NOTE: Did we manage to find the native SQLite library yet?
        #
        if {![haveConstraint file_sqlite3.dll]} then {
          #
          # NOTE: Ok, now try to check for the platform specific native SQLite
          #       library.
          #
          checkForFile $test_channel [file join $bin_path [machineToPlatform \
              $test_machine false] sqlite3.dll]
        }
      }
    }

    if {![info exists no(System.Data.SQLite.dll)]} then {
      checkForFile $test_channel [file join $bin_path System.Data.SQLite.dll]
    }
1893
1894
1895
1896
1897
1898
1899




1900
1901
1902
1903
1904
1905
1906
  if {![info exists no(scriptLibrary)]} then {
    checkForScriptLibrary $test_channel
  }

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





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

  if {![info exists no(fossil)]} then {
    checkForFossil $test_channel







>
>
>
>







1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
  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
2208
2209
2210
2211
2212
2213
2214



2215
2216
2217
2218
2219
2220
2221
        [formatList [getPlatformInfo compileOptions <none>]] \n]

    tputs $test_channel [appendArgs "---- strongName: " \
        [getPlatformInfo strongName <none>] \n]

    tputs $test_channel [appendArgs "---- certificate: " \
        [getPlatformInfo certificate <none>] \n]



  }

  #
  # NOTE: Show the current test file name, if any.
  #
  tputs $test_channel [appendArgs "---- test file: " \
      [expr {[info exists test_file] && [string length $test_file] > 0 ? \







>
>
>







2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
        [formatList [getPlatformInfo compileOptions <none>]] \n]

    tputs $test_channel [appendArgs "---- strongName: " \
        [getPlatformInfo strongName <none>] \n]

    tputs $test_channel [appendArgs "---- certificate: " \
        [getPlatformInfo certificate <none>] \n]

    tputs $test_channel [appendArgs "---- targetFramework: " \
        [getPlatformInfo targetFramework <none>] \n]
  }

  #
  # NOTE: Show the current test file name, if any.
  #
  tputs $test_channel [appendArgs "---- test file: " \
      [expr {[info exists test_file] && [string length $test_file] > 0 ? \
Changes to Membership/Properties/AssemblyInfo.cs.
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.83.0")]
[assembly: AssemblyFileVersion("1.0.83.0")]







|
|
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.85.0")]
[assembly: AssemblyFileVersion("1.0.85.0")]
Added 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.85.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
//      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.83.0")]
[assembly: AssemblyFileVersion("1.0.83.0")]







|
|
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.85.0")]
[assembly: AssemblyFileVersion("1.0.85.0")]
Changes to SQLite.Designer/source.extension.vsixmanifest.
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.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>





|







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.85.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/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
	<UserMacro
		Name="ConfigurationYear"
		Value="2005"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_BUILD_NUMBER"
		Value="083"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_LINKER_VERSION"
		Value="1.0"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_MANIFEST_VERSION"
		Value="1.0.83.0"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_RC_VERSION"
		Value="1,0,83,0"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_DEBUG_DEFINES"
		Value="INTEROP_DEBUG=0x31F;INTEROP_LOG=1;INTEROP_TEST_EXTENSION=1"
		PerformEnvironmentSet="true"
	/>







|









|




|







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
	<UserMacro
		Name="ConfigurationYear"
		Value="2005"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_BUILD_NUMBER"
		Value="085"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_LINKER_VERSION"
		Value="1.0"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_MANIFEST_VERSION"
		Value="1.0.85.0"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_RC_VERSION"
		Value="1,0,85,0"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_DEBUG_DEFINES"
		Value="INTEROP_DEBUG=0x31F;INTEROP_LOG=1;INTEROP_TEST_EXTENSION=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
	<UserMacro
		Name="ConfigurationYear"
		Value="2008"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_BUILD_NUMBER"
		Value="083"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_LINKER_VERSION"
		Value="1.0"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_MANIFEST_VERSION"
		Value="1.0.83.0"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_RC_VERSION"
		Value="1,0,83,0"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_DEBUG_DEFINES"
		Value="INTEROP_DEBUG=0x31F;INTEROP_LOG=1;INTEROP_TEST_EXTENSION=1"
		PerformEnvironmentSet="true"
	/>







|









|




|







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
	<UserMacro
		Name="ConfigurationYear"
		Value="2008"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_BUILD_NUMBER"
		Value="085"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_LINKER_VERSION"
		Value="1.0"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_MANIFEST_VERSION"
		Value="1.0.85.0"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_RC_VERSION"
		Value="1,0,85,0"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_DEBUG_DEFINES"
		Value="INTEROP_DEBUG=0x31F;INTEROP_LOG=1;INTEROP_TEST_EXTENSION=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
<?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>083</INTEROP_BUILD_NUMBER>
    <INTEROP_LINKER_VERSION>1.0</INTEROP_LINKER_VERSION>
    <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=0x31F;INTEROP_LOG=1;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>












|

|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?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>085</INTEROP_BUILD_NUMBER>
    <INTEROP_LINKER_VERSION>1.0</INTEROP_LINKER_VERSION>
    <INTEROP_MANIFEST_VERSION>1.0.85.0</INTEROP_MANIFEST_VERSION>
    <INTEROP_RC_VERSION>1,0,85,0</INTEROP_RC_VERSION>
    <INTEROP_DEBUG_DEFINES>INTEROP_DEBUG=0x31F;INTEROP_LOG=1;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>
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
<?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>083</INTEROP_BUILD_NUMBER>
    <INTEROP_LINKER_VERSION>1.0</INTEROP_LINKER_VERSION>
    <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=0x31F;INTEROP_LOG=1;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>












|

|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?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>085</INTEROP_BUILD_NUMBER>
    <INTEROP_LINKER_VERSION>1.0</INTEROP_LINKER_VERSION>
    <INTEROP_MANIFEST_VERSION>1.0.85.0</INTEROP_MANIFEST_VERSION>
    <INTEROP_RC_VERSION>1,0,85,0</INTEROP_RC_VERSION>
    <INTEROP_DEBUG_DEFINES>INTEROP_DEBUG=0x31F;INTEROP_LOG=1;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>
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
<?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.15.1</SQLITE_MANIFEST_VERSION>
    <SQLITE_RC_VERSION>3,7,15,1</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>











|
|







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_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
<VisualStudioPropertySheet
	ProjectType="Visual C++"
	Version="8.00"
	Name="sqlite3"
	>
	<UserMacro
		Name="SQLITE_MANIFEST_VERSION"
		Value="3.7.15.1"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="SQLITE_RC_VERSION"
		Value="3,7,15,1"
		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"
	/>







|




|







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"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="SQLITE_RC_VERSION"
		Value="3,7,16"
		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/contrib/extension-functions.c.
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127

#include <ctype.h>
/* relicoder */
#include <math.h>
#include <string.h>
#include <stdio.h>

#ifndef _WIN32_WCE
#include <errno.h>		/* LMH 2007-03-25 */
#else
int errno;
#define strerror(x) ""
#endif

#include <stdlib.h>







|







113
114
115
116
117
118
119
120
121
122
123
124
125
126
127

#include <ctype.h>
/* relicoder */
#include <math.h>
#include <string.h>
#include <stdio.h>

#if !defined(_WIN32_WCE) || defined(HAVE_ERRNO_H)
#include <errno.h>		/* LMH 2007-03-25 */
#else
int errno;
#define strerror(x) ""
#endif

#include <stdlib.h>
Changes to SQLite.Interop/src/core/sqlite3.c.
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.15.1.  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


|







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 
** 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
** 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.15.1"
#define SQLITE_VERSION_NUMBER 3007015
#define SQLITE_SOURCE_ID      "2012-12-19 20:39:10 6b85b767d0ff7975146156a99ad673f2c1a23318"

/*
** 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







|
|
|







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-02-15 04:21:01 843e1c543aabab8cd62f28742d5818887d36bcb7"

/*
** 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
1046
1047
1048
1049
1050
1051
1052









1053
1054
1055
1056
1057
1058
1059
#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))
#define SQLITE_READONLY_CANTLOCK       (SQLITE_READONLY | (2<<8))
#define SQLITE_ABORT_ROLLBACK          (SQLITE_ABORT | (2<<8))










/*
** CAPI3REF: Flags For File Open Operations
**
** These bit values are intended for use in the
** 3rd parameter to the [sqlite3_open_v2()] interface and
** in the 4th parameter to the [sqlite3_vfs.xOpen] method.







>
>
>
>
>
>
>
>
>







1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
#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))
#define SQLITE_READONLY_CANTLOCK       (SQLITE_READONLY | (2<<8))
#define SQLITE_ABORT_ROLLBACK          (SQLITE_ABORT | (2<<8))
#define SQLITE_CONSTRAINT_CHECK        (SQLITE_CONSTRAINT | (1<<8))
#define SQLITE_CONSTRAINT_COMMITHOOK   (SQLITE_CONSTRAINT | (2<<8))
#define SQLITE_CONSTRAINT_FOREIGNKEY   (SQLITE_CONSTRAINT | (3<<8))
#define SQLITE_CONSTRAINT_FUNCTION     (SQLITE_CONSTRAINT | (4<<8))
#define SQLITE_CONSTRAINT_NOTNULL      (SQLITE_CONSTRAINT | (5<<8))
#define SQLITE_CONSTRAINT_PRIMARYKEY   (SQLITE_CONSTRAINT | (6<<8))
#define SQLITE_CONSTRAINT_TRIGGER      (SQLITE_CONSTRAINT | (7<<8))
#define SQLITE_CONSTRAINT_UNIQUE       (SQLITE_CONSTRAINT | (8<<8))
#define SQLITE_CONSTRAINT_VTAB         (SQLITE_CONSTRAINT | (9<<8))

/*
** CAPI3REF: Flags For File Open Operations
**
** These bit values are intended for use in the
** 3rd parameter to the [sqlite3_open_v2()] interface and
** in the 4th parameter to the [sqlite3_vfs.xOpen] method.
8236
8237
8238
8239
8240
8241
8242





8243
8244
8245
8246
8247
8248
8249

/*
** A convenience macro that returns the number of elements in
** an array.
*/
#define ArraySize(X)    ((int)(sizeof(X)/sizeof(X[0])))






/*
** The following value as a destructor means to use sqlite3DbFree().
** The sqlite3DbFree() routine requires two parameters instead of the 
** one parameter that destructors normally want.  So we have to introduce 
** this magic value that the code knows to handle differently.  Any 
** pointer will work here as long as it is distinct from SQLITE_STATIC
** and SQLITE_TRANSIENT.







>
>
>
>
>







8245
8246
8247
8248
8249
8250
8251
8252
8253
8254
8255
8256
8257
8258
8259
8260
8261
8262
8263

/*
** A convenience macro that returns the number of elements in
** an array.
*/
#define ArraySize(X)    ((int)(sizeof(X)/sizeof(X[0])))

/*
** Determine if the argument is a power of two
*/
#define IsPowerOfTwo(X) (((X)&((X)-1))==0)

/*
** The following value as a destructor means to use sqlite3DbFree().
** The sqlite3DbFree() routine requires two parameters instead of the 
** one parameter that destructors normally want.  So we have to introduce 
** this magic value that the code knows to handle differently.  Any 
** pointer will work here as long as it is distinct from SQLITE_STATIC
** and SQLITE_TRANSIENT.
10011
10012
10013
10014
10015
10016
10017
10018
10019
10020
10021
10022
10023
10024
10025
                                          /*   DELETE, or UPDATE and return */
                                          /*   the count using a callback. */
#define SQLITE_NullCallback   0x00000020  /* Invoke the callback once if the */
                                          /*   result set is empty */
#define SQLITE_SqlTrace       0x00000040  /* Debug print SQL as it executes */
#define SQLITE_VdbeListing    0x00000080  /* Debug listings of VDBE programs */
#define SQLITE_WriteSchema    0x00000100  /* OK to update SQLITE_MASTER */
                         /*   0x00000200  Unused */
#define SQLITE_IgnoreChecks   0x00000400  /* Do not enforce check constraints */
#define SQLITE_ReadUncommitted 0x0000800  /* For shared-cache mode */
#define SQLITE_LegacyFileFmt  0x00001000  /* Create new databases in format 1 */
#define SQLITE_FullFSync      0x00002000  /* Use full fsync on the backend */
#define SQLITE_CkptFullFSync  0x00004000  /* Use full fsync for checkpoint */
#define SQLITE_RecoveryMode   0x00008000  /* Ignore schema errors */
#define SQLITE_ReverseOrder   0x00010000  /* Reverse unordered SELECTs */







|







10025
10026
10027
10028
10029
10030
10031
10032
10033
10034
10035
10036
10037
10038
10039
                                          /*   DELETE, or UPDATE and return */
                                          /*   the count using a callback. */
#define SQLITE_NullCallback   0x00000020  /* Invoke the callback once if the */
                                          /*   result set is empty */
#define SQLITE_SqlTrace       0x00000040  /* Debug print SQL as it executes */
#define SQLITE_VdbeListing    0x00000080  /* Debug listings of VDBE programs */
#define SQLITE_WriteSchema    0x00000100  /* OK to update SQLITE_MASTER */
#define SQLITE_VdbeAddopTrace 0x00000200  /* Trace sqlite3VdbeAddOp() calls */
#define SQLITE_IgnoreChecks   0x00000400  /* Do not enforce check constraints */
#define SQLITE_ReadUncommitted 0x0000800  /* For shared-cache mode */
#define SQLITE_LegacyFileFmt  0x00001000  /* Create new databases in format 1 */
#define SQLITE_FullFSync      0x00002000  /* Use full fsync on the backend */
#define SQLITE_CkptFullFSync  0x00004000  /* Use full fsync for checkpoint */
#define SQLITE_RecoveryMode   0x00008000  /* Ignore schema errors */
#define SQLITE_ReverseOrder   0x00010000  /* Reverse unordered SELECTs */
10040
10041
10042
10043
10044
10045
10046

10047
10048
10049
10050
10051
10052
10053
#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 */

/*
** Macros for testing whether or not optimizations are enabled or disabled.
*/
#ifndef SQLITE_OMIT_BUILTIN_TEST
#define OptimizationDisabled(db, mask)  (((db)->dbOptFlags&(mask))!=0)







>







10054
10055
10056
10057
10058
10059
10060
10061
10062
10063
10064
10065
10066
10067
10068
#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_Transitive     0x0200   /* Transitive constraints */
#define SQLITE_AllOpts        0xffff   /* 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)
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
** 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; /* 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 */

  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
};








|
|
|
|
|
|
|
|
|
<
|
>
|
|
|







10566
10567
10568
10569
10570
10571
10572
10573
10574
10575
10576
10577
10578
10579
10580
10581

10582
10583
10584
10585
10586
10587
10588
10589
10590
10591
10592
10593
** 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 */
  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 */
#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
};

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
/*
** 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.








*/
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 */
    u8 done;               /* A flag to indicate when processing is finished */

    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.







>
>
>
>
>
>
>
>





|
|
|
|
|
>
|
|







10853
10854
10855
10856
10857
10858
10859
10860
10861
10862
10863
10864
10865
10866
10867
10868
10869
10870
10871
10872
10873
10874
10875
10876
10877
10878
10879
10880
10881
10882
10883
10884
10885
10886
10887
/*
** 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 */
    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 */
  } *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.
11017
11018
11019
11020
11021
11022
11023

11024
11025
11026
11027
11028
11029
11030
  int p1, p2;           /* Operands of the opcode used to ends the loop */
  union {               /* Information that depends on plan.wsFlags */
    struct {
      int nIn;              /* Number of entries in aInLoop[] */
      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







>







11041
11042
11043
11044
11045
11046
11047
11048
11049
11050
11051
11052
11053
11054
11055
  int p1, p2;           /* Operands of the opcode used to ends the loop */
  union {               /* Information that depends on plan.wsFlags */
    struct {
      int nIn;              /* Number of entries in aInLoop[] */
      struct InLoop {
        int iCur;              /* The VDBE cursor used by this IN operator */
        int addrInTop;         /* Top of the IN loop */
        u8 eEndLoopOp;         /* IN Loop terminator. OP_Next or OP_Prev */
      } *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
11169
11170
11171
11172
11173
11174
11175

11176
11177
11178
11179
11180
11181
11182
#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_Materialize     0x0100  /* Force materialization of views */



/*
** 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 */







>







11194
11195
11196
11197
11198
11199
11200
11201
11202
11203
11204
11205
11206
11207
11208
#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_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 */
11881
11882
11883
11884
11885
11886
11887
11888
11889
11890
11891
11892
11893
11894
11895
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*,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







|







11907
11908
11909
11910
11911
11912
11913
11914
11915
11916
11917
11918
11919
11920
11921
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*);
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
11955
11956
11957
11958
11959
11960
11961
11962
11963
11964
11965
11966
11967
11968
11969
SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int,int,
                                     int*,int,int,int,int,int*);
SQLITE_PRIVATE void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*, int, int, int);
SQLITE_PRIVATE int sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse*, int, int);
SQLITE_PRIVATE void sqlite3MultiWrite(Parse*);
SQLITE_PRIVATE void sqlite3MayAbort(Parse*);
SQLITE_PRIVATE void sqlite3HaltConstraint(Parse*, int, char*, int);
SQLITE_PRIVATE Expr *sqlite3ExprDup(sqlite3*,Expr*,int);
SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int);
SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int);
SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3*,IdList*);
SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,Select*,int);
SQLITE_PRIVATE void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*);
SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,u8);







|







11981
11982
11983
11984
11985
11986
11987
11988
11989
11990
11991
11992
11993
11994
11995
SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int,int,
                                     int*,int,int,int,int,int*);
SQLITE_PRIVATE void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*, int, int, int);
SQLITE_PRIVATE int sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse*, int, int);
SQLITE_PRIVATE void sqlite3MultiWrite(Parse*);
SQLITE_PRIVATE void sqlite3MayAbort(Parse*);
SQLITE_PRIVATE void sqlite3HaltConstraint(Parse*, int, int, char*, int);
SQLITE_PRIVATE Expr *sqlite3ExprDup(sqlite3*,Expr*,int);
SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int);
SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int);
SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3*,IdList*);
SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,Select*,int);
SQLITE_PRIVATE void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*);
SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,u8);
12138
12139
12140
12141
12142
12143
12144

12145
12146
12147
12148
12149
12150
12151
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 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*);







>







12164
12165
12166
12167
12168
12169
12170
12171
12172
12173
12174
12175
12176
12177
12178
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*);
12276
12277
12278
12279
12280
12281
12282

12283
12284

12285
12286
12287
12288
12289
12290
12291
  #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*);

#else
  #define sqlite3FkDelete(a,b)

#endif


/*
** Available fault injectors.  Should be numbered beginning with 0.
*/
#define SQLITE_FAULTINJECTOR_MALLOC     0







>


>







12303
12304
12305
12306
12307
12308
12309
12310
12311
12312
12313
12314
12315
12316
12317
12318
12319
12320
  #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
13187
13188
13189
13190
13191
13192
13193
13194
13195
13196
13197
13198
13199
13200
13201
  VdbeFrame *pParent;     /* Parent of this frame, or NULL if parent is main */
  Op *aOp;                /* Program instructions for parent frame */
  Mem *aMem;              /* Array of memory cells for parent frame */
  u8 *aOnceFlag;          /* Array of OP_Once flags for parent frame */
  VdbeCursor **apCsr;     /* Array of Vdbe cursors for parent frame */
  void *token;            /* Copy of SubProgram.token */
  i64 lastRowid;          /* Last insert rowid (sqlite3.lastRowid) */
  u16 nCursor;            /* Number of entries in apCsr */
  int pc;                 /* Program Counter in parent (calling) frame */
  int nOp;                /* Size of aOp array */
  int nMem;               /* Number of entries in aMem */
  int nOnceFlag;          /* Number of entries in aOnceFlag */
  int nChildMem;          /* Number of memory cells for child frame */
  int nChildCsr;          /* Number of cursors for child frame */
  int nChange;            /* Statement changes (Vdbe.nChanges)     */







|







13216
13217
13218
13219
13220
13221
13222
13223
13224
13225
13226
13227
13228
13229
13230
  VdbeFrame *pParent;     /* Parent of this frame, or NULL if parent is main */
  Op *aOp;                /* Program instructions for parent frame */
  Mem *aMem;              /* Array of memory cells for parent frame */
  u8 *aOnceFlag;          /* Array of OP_Once flags for parent frame */
  VdbeCursor **apCsr;     /* Array of Vdbe cursors for parent frame */
  void *token;            /* Copy of SubProgram.token */
  i64 lastRowid;          /* Last insert rowid (sqlite3.lastRowid) */
  int nCursor;            /* Number of entries in apCsr */
  int pc;                 /* Program Counter in parent (calling) frame */
  int nOp;                /* Size of aOp array */
  int nMem;               /* Number of entries in aMem */
  int nOnceFlag;          /* Number of entries in aOnceFlag */
  int nChildMem;          /* Number of memory cells for child frame */
  int nChildCsr;          /* Number of cursors for child frame */
  int nChange;            /* Statement changes (Vdbe.nChanges)     */
13373
13374
13375
13376
13377
13378
13379
13380
13381
13382
13383
13384
13385
13386
13387
  Mem *pResultSet;        /* Pointer to an array of results */
  int nMem;               /* Number of memory locations currently allocated */
  int nOp;                /* Number of instructions in the program */
  int nOpAlloc;           /* Number of slots allocated for aOp[] */
  int nLabel;             /* Number of labels used */
  int *aLabel;            /* Space to hold the labels */
  u16 nResColumn;         /* Number of columns in one row of the result set */
  u16 nCursor;            /* Number of slots in apCsr[] */
  u32 magic;              /* Magic number for sanity checking */
  char *zErrMsg;          /* Error message written here */
  Vdbe *pPrev,*pNext;     /* Linked list of VDBEs with the same Vdbe.db */
  VdbeCursor **apCsr;     /* One element of this array for each open cursor */
  Mem *aVar;              /* Values for the OP_Variable opcode. */
  char **azVar;           /* Name of variables */
  ynVar nVar;             /* Number of entries in aVar[] */







|







13402
13403
13404
13405
13406
13407
13408
13409
13410
13411
13412
13413
13414
13415
13416
  Mem *pResultSet;        /* Pointer to an array of results */
  int nMem;               /* Number of memory locations currently allocated */
  int nOp;                /* Number of instructions in the program */
  int nOpAlloc;           /* Number of slots allocated for aOp[] */
  int nLabel;             /* Number of labels used */
  int *aLabel;            /* Space to hold the labels */
  u16 nResColumn;         /* Number of columns in one row of the result set */
  int nCursor;            /* Number of slots in apCsr[] */
  u32 magic;              /* Magic number for sanity checking */
  char *zErrMsg;          /* Error message written here */
  Vdbe *pPrev,*pNext;     /* Linked list of VDBEs with the same Vdbe.db */
  VdbeCursor **apCsr;     /* One element of this array for each open cursor */
  Mem *aVar;              /* Values for the OP_Variable opcode. */
  char **azVar;           /* Name of variables */
  ynVar nVar;             /* Number of entries in aVar[] */
23284
23285
23286
23287
23288
23289
23290
23291
23292
23293
23294
23295
23296
23297
23298
23299
23300
23301
23302
  { "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







<

<
<
<







23313
23314
23315
23316
23317
23318
23319

23320



23321
23322
23323
23324
23325
23326
23327
  { "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)


  { "fchmod",       (sqlite3_syscall_ptr)fchmod,     0  },



#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
23313
23314
23315
23316
23317
23318
23319
23320
23321
23322
23323
23324
23325
23326
23327
23328
23329

  { "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
** system call named zName.







<
<
<







23338
23339
23340
23341
23342
23343
23344



23345
23346
23347
23348
23349
23350
23351

  { "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)




}; /* 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
** system call named zName.
23420
23421
23422
23423
23424
23425
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
** 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 ){
    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( m ){


    osUmask(origM);
  }

#if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0)
  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 







<
<
<
|
<
<
<
<







>
|
>
>
|
|
>

|

>







23442
23443
23444
23445
23446
23447
23448



23449




23450
23451
23452
23453
23454
23455
23456
23457
23458
23459
23460
23461
23462
23463
23464
23465
23466
23467
23468
23469
23470
23471
23472
23473
23474
** 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 = m ? m : SQLITE_DEFAULT_FILE_PERMISSIONS;




  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 ){
      struct stat statbuf;
      if( osFstat(fd, &statbuf)==0 && (statbuf.st_mode&0777)!=m ){
        osFchmod(fd, m);
      }
    }
#if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==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 
29866
29867
29868
29869
29870
29871
29872
29873
29874
29875
29876
29877
29878
29879
29880
    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)==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; 
}







|







29886
29887
29888
29889
29890
29891
29892
29893
29894
29895
29896
29897
29898
29899
29900
    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 );

  /* 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; 
}
31087
31088
31089
31090
31091
31092
31093
31094
31095
31096
31097
31098
31099
31100
31101
}

/*
** This function outputs the specified (ANSI) string to the Win32 debugger
** (if available).
*/

SQLITE_API void sqlite3_win32_write_debug(char *zBuf, int nBuf){
  char zDbgBuf[SQLITE_WIN32_DBG_BUF_SIZE];
  int nMin = MIN(nBuf, (SQLITE_WIN32_DBG_BUF_SIZE - 1)); /* may be negative. */
  if( nMin<-1 ) nMin = -1; /* all negative values become -1. */
  assert( nMin==-1 || nMin==0 || nMin<SQLITE_WIN32_DBG_BUF_SIZE );
#if defined(SQLITE_WIN32_HAS_ANSI)
  if( nMin>0 ){
    memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE);







|







31107
31108
31109
31110
31111
31112
31113
31114
31115
31116
31117
31118
31119
31120
31121
}

/*
** This function outputs the specified (ANSI) string to the Win32 debugger
** (if available).
*/

SQLITE_API void sqlite3_win32_write_debug(const char *zBuf, int nBuf){
  char zDbgBuf[SQLITE_WIN32_DBG_BUF_SIZE];
  int nMin = MIN(nBuf, (SQLITE_WIN32_DBG_BUF_SIZE - 1)); /* may be negative. */
  if( nMin<-1 ) nMin = -1; /* all negative values become -1. */
  assert( nMin==-1 || nMin==0 || nMin<SQLITE_WIN32_DBG_BUF_SIZE );
#if defined(SQLITE_WIN32_HAS_ANSI)
  if( nMin>0 ){
    memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE);
31720
31721
31722
31723
31724
31725
31726

31727
31728
31729
31730
31731
31732
31733
31734
31735
31736
  }
}

#if SQLITE_OS_WINCE
/*************************************************************************
** This section contains code for WinCE only.
*/

/*
** Windows CE does not have a localtime() function.  So create a
** substitute.
*/
/* #include <time.h> */
struct tm *__cdecl localtime(const time_t *t)
{
  static struct tm y;
  FILETIME uTm, lTm;
  SYSTEMTIME pTm;







>

|
|







31740
31741
31742
31743
31744
31745
31746
31747
31748
31749
31750
31751
31752
31753
31754
31755
31756
31757
  }
}

#if SQLITE_OS_WINCE
/*************************************************************************
** This section contains code for WinCE only.
*/
#if !defined(SQLITE_MSVC_LOCALTIME_API) || !SQLITE_MSVC_LOCALTIME_API
/*
** The MSVC CRT on Windows CE may not have a localtime() function.  So
** create a substitute.
*/
/* #include <time.h> */
struct tm *__cdecl localtime(const time_t *t)
{
  static struct tm y;
  FILETIME uTm, lTm;
  SYSTEMTIME pTm;
31746
31747
31748
31749
31750
31751
31752

31753
31754
31755
31756
31757
31758
31759
  y.tm_wday = pTm.wDayOfWeek;
  y.tm_mday = pTm.wDay;
  y.tm_hour = pTm.wHour;
  y.tm_min = pTm.wMinute;
  y.tm_sec = pTm.wSecond;
  return &y;
}


#define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-(int)offsetof(winFile,h)]

/*
** Acquire a lock on the handle h
*/
static void winceMutexAcquire(HANDLE h){







>







31767
31768
31769
31770
31771
31772
31773
31774
31775
31776
31777
31778
31779
31780
31781
  y.tm_wday = pTm.wDayOfWeek;
  y.tm_mday = pTm.wDay;
  y.tm_hour = pTm.wHour;
  y.tm_min = pTm.wMinute;
  y.tm_sec = pTm.wSecond;
  return &y;
}
#endif

#define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-(int)offsetof(winFile,h)]

/*
** Acquire a lock on the handle h
*/
static void winceMutexAcquire(HANDLE h){
31767
31768
31769
31770
31771
31772
31773
31774
31775
31776


31777
31778
31779
31780
31781
31782
31783
31784
31785
31786
31787
31788
31789
31790
31791
31792
31793
31794
31795
31796
31797
31798

31799
31800
31801
31802
31803
31804
31805
31806
31807
31808
31809
31810
31811
31812
31813
31814
31815
31816
31817

31818
31819
31820
31821
31822
31823
31824
31825
31826
31827
31828
31829
31830
31831
31832

31833
31834
31835
31836
31837
31838
31839






31840
31841
31842
31843
31844
31845
31846
31847
31848
31849
31850
31851
31852
31853
31854
31855
31856
31857
31858
31859
*/
#define winceMutexRelease(h) ReleaseMutex(h)

/*
** Create the mutex and shared memory used for locking in the file
** descriptor pFile
*/
static BOOL winceCreateLock(const char *zFilename, winFile *pFile){
  LPWSTR zTok;
  LPWSTR zName;


  BOOL bInit = TRUE;

  zName = utf8ToUnicode(zFilename);
  if( zName==0 ){
    /* out of memory */
    return FALSE;
  }

  /* Initialize the local lockdata */
  memset(&pFile->local, 0, sizeof(pFile->local));

  /* Replace the backslashes from the filename and lowercase it
  ** to derive a mutex name. */
  zTok = osCharLowerW(zName);
  for (;*zTok;zTok++){
    if (*zTok == '\\') *zTok = '_';
  }

  /* Create/open the named mutex */
  pFile->hMutex = osCreateMutexW(NULL, FALSE, zName);
  if (!pFile->hMutex){
    pFile->lastErrno = osGetLastError();

    winLogError(SQLITE_ERROR, pFile->lastErrno, "winceCreateLock1", zFilename);
    sqlite3_free(zName);
    return FALSE;
  }

  /* Acquire the mutex before continuing */
  winceMutexAcquire(pFile->hMutex);
  
  /* Since the names of named mutexes, semaphores, file mappings etc are 
  ** case-sensitive, take advantage of that by uppercasing the mutex name
  ** and using that as the shared filemapping name.
  */
  osCharUpperW(zName);
  pFile->hShared = osCreateFileMappingW(INVALID_HANDLE_VALUE, NULL,
                                        PAGE_READWRITE, 0, sizeof(winceLock),
                                        zName);  

  /* Set a flag that indicates we're the first to create the memory so it 
  ** must be zero-initialized */

  if (osGetLastError() == ERROR_ALREADY_EXISTS){
    bInit = FALSE;
  }

  sqlite3_free(zName);

  /* If we succeeded in making the shared memory handle, map it. */
  if (pFile->hShared){
    pFile->shared = (winceLock*)osMapViewOfFile(pFile->hShared, 
             FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock));
    /* If mapping failed, close the shared memory handle and erase it */
    if (!pFile->shared){
      pFile->lastErrno = osGetLastError();
      winLogError(SQLITE_ERROR, pFile->lastErrno,
               "winceCreateLock2", zFilename);

      osCloseHandle(pFile->hShared);
      pFile->hShared = NULL;
    }
  }

  /* If shared memory could not be created, then close the mutex and fail */
  if (pFile->hShared == NULL){






    winceMutexRelease(pFile->hMutex);
    osCloseHandle(pFile->hMutex);
    pFile->hMutex = NULL;
    return FALSE;
  }
  
  /* Initialize the shared memory if we're supposed to */
  if (bInit) {
    memset(pFile->shared, 0, sizeof(winceLock));
  }

  winceMutexRelease(pFile->hMutex);
  return TRUE;
}

/*
** Destroy the part of winFile that deals with wince locks
*/
static void winceDestroyLock(winFile *pFile){
  if (pFile->hMutex){







|


>
>





|
















>
|

|
















>
|






|



|

|
|
>






|
>
>
>
>
>
>



|



|




|







31789
31790
31791
31792
31793
31794
31795
31796
31797
31798
31799
31800
31801
31802
31803
31804
31805
31806
31807
31808
31809
31810
31811
31812
31813
31814
31815
31816
31817
31818
31819
31820
31821
31822
31823
31824
31825
31826
31827
31828
31829
31830
31831
31832
31833
31834
31835
31836
31837
31838
31839
31840
31841
31842
31843
31844
31845
31846
31847
31848
31849
31850
31851
31852
31853
31854
31855
31856
31857
31858
31859
31860
31861
31862
31863
31864
31865
31866
31867
31868
31869
31870
31871
31872
31873
31874
31875
31876
31877
31878
31879
31880
31881
31882
31883
31884
31885
31886
31887
31888
31889
31890
31891
31892
*/
#define winceMutexRelease(h) ReleaseMutex(h)

/*
** Create the mutex and shared memory used for locking in the file
** descriptor pFile
*/
static int winceCreateLock(const char *zFilename, winFile *pFile){
  LPWSTR zTok;
  LPWSTR zName;
  DWORD lastErrno;
  BOOL bLogged = FALSE;
  BOOL bInit = TRUE;

  zName = utf8ToUnicode(zFilename);
  if( zName==0 ){
    /* out of memory */
    return SQLITE_IOERR_NOMEM;
  }

  /* Initialize the local lockdata */
  memset(&pFile->local, 0, sizeof(pFile->local));

  /* Replace the backslashes from the filename and lowercase it
  ** to derive a mutex name. */
  zTok = osCharLowerW(zName);
  for (;*zTok;zTok++){
    if (*zTok == '\\') *zTok = '_';
  }

  /* Create/open the named mutex */
  pFile->hMutex = osCreateMutexW(NULL, FALSE, zName);
  if (!pFile->hMutex){
    pFile->lastErrno = osGetLastError();
    winLogError(SQLITE_IOERR, pFile->lastErrno,
                "winceCreateLock1", zFilename);
    sqlite3_free(zName);
    return SQLITE_IOERR;
  }

  /* Acquire the mutex before continuing */
  winceMutexAcquire(pFile->hMutex);
  
  /* Since the names of named mutexes, semaphores, file mappings etc are 
  ** case-sensitive, take advantage of that by uppercasing the mutex name
  ** and using that as the shared filemapping name.
  */
  osCharUpperW(zName);
  pFile->hShared = osCreateFileMappingW(INVALID_HANDLE_VALUE, NULL,
                                        PAGE_READWRITE, 0, sizeof(winceLock),
                                        zName);  

  /* Set a flag that indicates we're the first to create the memory so it 
  ** must be zero-initialized */
  lastErrno = osGetLastError();
  if (lastErrno == ERROR_ALREADY_EXISTS){
    bInit = FALSE;
  }

  sqlite3_free(zName);

  /* If we succeeded in making the shared memory handle, map it. */
  if( pFile->hShared ){
    pFile->shared = (winceLock*)osMapViewOfFile(pFile->hShared, 
             FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock));
    /* If mapping failed, close the shared memory handle and erase it */
    if( !pFile->shared ){
      pFile->lastErrno = osGetLastError();
      winLogError(SQLITE_IOERR, pFile->lastErrno,
                  "winceCreateLock2", zFilename);
      bLogged = TRUE;
      osCloseHandle(pFile->hShared);
      pFile->hShared = NULL;
    }
  }

  /* If shared memory could not be created, then close the mutex and fail */
  if( pFile->hShared==NULL ){
    if( !bLogged ){
      pFile->lastErrno = lastErrno;
      winLogError(SQLITE_IOERR, pFile->lastErrno,
                  "winceCreateLock3", zFilename);
      bLogged = TRUE;
    }
    winceMutexRelease(pFile->hMutex);
    osCloseHandle(pFile->hMutex);
    pFile->hMutex = NULL;
    return SQLITE_IOERR;
  }
  
  /* Initialize the shared memory if we're supposed to */
  if( bInit ){
    memset(pFile->shared, 0, sizeof(winceLock));
  }

  winceMutexRelease(pFile->hMutex);
  return SQLITE_OK;
}

/*
** Destroy the part of winFile that deals with wince locks
*/
static void winceDestroyLock(winFile *pFile){
  if (pFile->hMutex){
32162
32163
32164
32165
32166
32167
32168

32169
32170
32171
32172
32173
32174
32175
  winFile *pFile = (winFile*)id;

  assert( id!=0 );
#ifndef SQLITE_OMIT_WAL
  assert( pFile->pShm==0 );
#endif
  OSTRACE(("CLOSE %d\n", pFile->h));

  do{
    rc = osCloseHandle(pFile->h);
    /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */
  }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (sqlite3_win32_sleep(100), 1) );
#if SQLITE_OS_WINCE
#define WINCE_DELETION_ATTEMPTS 3
  winceDestroyLock(pFile);







>







32195
32196
32197
32198
32199
32200
32201
32202
32203
32204
32205
32206
32207
32208
32209
  winFile *pFile = (winFile*)id;

  assert( id!=0 );
#ifndef SQLITE_OMIT_WAL
  assert( pFile->pShm==0 );
#endif
  OSTRACE(("CLOSE %d\n", pFile->h));
  assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE );
  do{
    rc = osCloseHandle(pFile->h);
    /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */
  }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (sqlite3_win32_sleep(100), 1) );
#if SQLITE_OS_WINCE
#define WINCE_DELETION_ATTEMPTS 3
  winceDestroyLock(pFile);
32854
32855
32856
32857
32858
32859
32860
32861
32862
32863
32864
32865
32866
32867
32868
        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;
    }
  }







|







32888
32889
32890
32891
32892
32893
32894
32895
32896
32897
32898
32899
32900
32901
32902
        win32IoerrRetryDelay = a[1];
      }else{
        a[1] = win32IoerrRetryDelay;
      }
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_TEMPFILENAME: {
      char *zTFile = sqlite3MallocZero( pFile->pVfs->mxPathname );
      if( zTFile ){
        getTempname(pFile->pVfs->mxPathname, zTFile);
        *(char**)pArg = zTFile;
      }
      return SQLITE_OK;
    }
  }
33078
33079
33080
33081
33082
33083
33084
33085
33086
33087
33088
33089
33090
33091
33092
                 (int)osGetCurrentProcessId(), i,
                 bRc ? "ok" : "failed"));
        bRc = osCloseHandle(p->aRegion[i].hMap);
        OSTRACE(("SHM-PURGE pid-%d close region=%d %s\n",
                 (int)osGetCurrentProcessId(), i,
                 bRc ? "ok" : "failed"));
      }
      if( p->hFile.h != INVALID_HANDLE_VALUE ){
        SimulateIOErrorBenign(1);
        winClose((sqlite3_file *)&p->hFile);
        SimulateIOErrorBenign(0);
      }
      if( deleteFlag ){
        SimulateIOErrorBenign(1);
        sqlite3BeginBenignMalloc();







|







33112
33113
33114
33115
33116
33117
33118
33119
33120
33121
33122
33123
33124
33125
33126
                 (int)osGetCurrentProcessId(), i,
                 bRc ? "ok" : "failed"));
        bRc = osCloseHandle(p->aRegion[i].hMap);
        OSTRACE(("SHM-PURGE pid-%d close region=%d %s\n",
                 (int)osGetCurrentProcessId(), i,
                 bRc ? "ok" : "failed"));
      }
      if( p->hFile.h!=NULL && p->hFile.h!=INVALID_HANDLE_VALUE ){
        SimulateIOErrorBenign(1);
        winClose((sqlite3_file *)&p->hFile);
        SimulateIOErrorBenign(0);
      }
      if( deleteFlag ){
        SimulateIOErrorBenign(1);
        sqlite3BeginBenignMalloc();
33773
33774
33775
33776
33777
33778
33779
33780
33781

33782
33783
33784
33785
33786
33787
33788
33789
33790
33791
33792
33793
33794
33795
33796

33797
33798
33799
33800
33801
33802
33803
  /* Assert that the upper layer has set one of the "file-type" flags. */
  assert( eType==SQLITE_OPEN_MAIN_DB      || eType==SQLITE_OPEN_TEMP_DB 
       || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL 
       || eType==SQLITE_OPEN_SUBJOURNAL   || eType==SQLITE_OPEN_MASTER_JOURNAL 
       || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
  );

  assert( id!=0 );
  UNUSED_PARAMETER(pVfs);


#if SQLITE_OS_WINRT
  if( !sqlite3_temp_directory ){
    sqlite3_log(SQLITE_ERROR,
        "sqlite3_temp_directory variable should be set for WinRT");
  }
#endif

  pFile->h = INVALID_HANDLE_VALUE;

  /* If the second argument to this function is NULL, generate a 
  ** temporary file name to use 
  */
  if( !zUtf8Name ){
    assert(isDelete && !isOpenJournal);

    rc = getTempname(MAX_PATH+2, zTmpname);
    if( rc!=SQLITE_OK ){
      return rc;
    }
    zUtf8Name = zTmpname;
  }








|
|
>








<
<





>







33807
33808
33809
33810
33811
33812
33813
33814
33815
33816
33817
33818
33819
33820
33821
33822
33823
33824


33825
33826
33827
33828
33829
33830
33831
33832
33833
33834
33835
33836
33837
  /* Assert that the upper layer has set one of the "file-type" flags. */
  assert( eType==SQLITE_OPEN_MAIN_DB      || eType==SQLITE_OPEN_TEMP_DB 
       || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL 
       || eType==SQLITE_OPEN_SUBJOURNAL   || eType==SQLITE_OPEN_MASTER_JOURNAL 
       || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
  );

  assert( pFile!=0 );
  memset(pFile, 0, sizeof(winFile));
  pFile->h = INVALID_HANDLE_VALUE;

#if SQLITE_OS_WINRT
  if( !sqlite3_temp_directory ){
    sqlite3_log(SQLITE_ERROR,
        "sqlite3_temp_directory variable should be set for WinRT");
  }
#endif



  /* If the second argument to this function is NULL, generate a 
  ** temporary file name to use 
  */
  if( !zUtf8Name ){
    assert(isDelete && !isOpenJournal);
    memset(zTmpname, 0, MAX_PATH+2);
    rc = getTempname(MAX_PATH+2, zTmpname);
    if( rc!=SQLITE_OK ){
      return rc;
    }
    zUtf8Name = zTmpname;
  }

33926
33927
33928
33929
33930
33931
33932
33933
33934
33935
33936
33937
33938
33939
33940
33941
33942
33943
33944
33945
33946
33947
33948
33949
33950
33951
33952
33953
33954
33955
33956
33957
33958
33959
33960









33961
33962
33963
33964
33965
33966
33967
    if( isReadWrite ){
      *pOutFlags = SQLITE_OPEN_READWRITE;
    }else{
      *pOutFlags = SQLITE_OPEN_READONLY;
    }
  }

  memset(pFile, 0, sizeof(*pFile));
  pFile->pMethod = &winIoMethod;
  pFile->h = h;
  pFile->lastErrno = NO_ERROR;
  pFile->pVfs = pVfs;
#ifndef SQLITE_OMIT_WAL
  pFile->pShm = 0;
#endif
  pFile->zPath = zName;
  if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
    pFile->ctrlFlags |= WINFILE_PSOW;
  }

#if SQLITE_OS_WINCE
  if( isReadWrite && eType==SQLITE_OPEN_MAIN_DB
       && !winceCreateLock(zName, pFile)
  ){
    osCloseHandle(h);
    sqlite3_free(zConverted);
    return SQLITE_CANTOPEN_BKPT;
  }
  if( isTemp ){
    pFile->zDeleteOnClose = zConverted;
  }else
#endif
  {
    sqlite3_free(zConverted);
  }










  OpenCounter(+1);
  return rc;
}

/*
** Delete the named file.







<
<
<
<
<
<
<
<
<
<
<
<
<


|



|








>
>
>
>
>
>
>
>
>







33960
33961
33962
33963
33964
33965
33966













33967
33968
33969
33970
33971
33972
33973
33974
33975
33976
33977
33978
33979
33980
33981
33982
33983
33984
33985
33986
33987
33988
33989
33990
33991
33992
33993
33994
33995
33996
33997
    if( isReadWrite ){
      *pOutFlags = SQLITE_OPEN_READWRITE;
    }else{
      *pOutFlags = SQLITE_OPEN_READONLY;
    }
  }














#if SQLITE_OS_WINCE
  if( isReadWrite && eType==SQLITE_OPEN_MAIN_DB
       && (rc = winceCreateLock(zName, pFile))!=SQLITE_OK
  ){
    osCloseHandle(h);
    sqlite3_free(zConverted);
    return rc;
  }
  if( isTemp ){
    pFile->zDeleteOnClose = zConverted;
  }else
#endif
  {
    sqlite3_free(zConverted);
  }

  pFile->pMethod = &winIoMethod;
  pFile->pVfs = pVfs;
  pFile->h = h;
  if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
    pFile->ctrlFlags |= WINFILE_PSOW;
  }
  pFile->lastErrno = NO_ERROR;
  pFile->zPath = zName;

  OpenCounter(+1);
  return rc;
}

/*
** Delete the named file.
56332
56333
56334
56335
56336
56337
56338
56339
56340
56341
56342
56343
56344
56345
56346
  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), 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: ");








|







56362
56363
56364
56365
56366
56367
56368
56369
56370
56371
56372
56373
56374
56375
56376
  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);
  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: ");

56867
56868
56869
56870
56871
56872
56873
56874





56875
56876
56877
56878
56879
56880
56881
}

/*
** 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(sqlite3_backup *p, Pgno iSrcPg, const u8 *zSrcData){





  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







|
>
>
>
>
>







56897
56898
56899
56900
56901
56902
56903
56904
56905
56906
56907
56908
56909
56910
56911
56912
56913
56914
56915
56916
}

/*
** 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(
  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
56940
56941
56942
56943
56944
56945
56946



56947
56948
56949
56950
56951
56952
56953
      ** 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;



    }
    sqlite3PagerUnref(pDestPg);
  }

  return rc;
}








>
>
>







56975
56976
56977
56978
56979
56980
56981
56982
56983
56984
56985
56986
56987
56988
56989
56990
56991
      ** 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;
}

57046
57047
57048
57049
57050
57051
57052
57053
57054
57055
57056
57057
57058
57059
57060
    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));
          sqlite3PagerUnref(pSrcPg);
        }
      }
      p->iNext++;
    }
    if( rc==SQLITE_OK ){
      p->nPagecount = nSrcPage;







|







57084
57085
57086
57087
57088
57089
57090
57091
57092
57093
57094
57095
57096
57097
57098
    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);
          sqlite3PagerUnref(pSrcPg);
        }
      }
      p->iNext++;
    }
    if( rc==SQLITE_OK ){
      p->nPagecount = nSrcPage;
57294
57295
57296
57297
57298
57299
57300
57301
57302
57303
57304
57305
57306
57307
57308
      /* 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);
      sqlite3_mutex_leave(p->pDestDb->mutex);
      assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED );
      if( rc!=SQLITE_OK ){
        p->rc = rc;
      }
    }
  }







|







57332
57333
57334
57335
57336
57337
57338
57339
57340
57341
57342
57343
57344
57345
57346
      /* 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);
      sqlite3_mutex_leave(p->pDestDb->mutex);
      assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED );
      if( rc!=SQLITE_OK ){
        p->rc = rc;
      }
    }
  }
58562
58563
58564
58565
58566
58567
58568
58569
58570
58571
58572
58573
58574
58575
58576
58577
58578
58579
58580
58581
58582
58583
58584
58585
58586
58587
*************************************************************************
** This file contains code used for creating, destroying, and populating
** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.)  Prior
** to version 2.8.7, all this code was combined into the vdbe.c source file.
** But that file was getting too big so this subroutines were split out.
*/



/*
** When debugging the code generator in a symbolic debugger, one can
** set the sqlite3VdbeAddopTrace to 1 and all opcodes will be printed
** as they are added to the instruction stream.
*/
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE int sqlite3VdbeAddopTrace = 0;
#endif


/*
** Create a new virtual database engine.
*/
SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(sqlite3 *db){
  Vdbe *p;
  p = sqlite3DbMallocZero(db, sizeof(Vdbe) );
  if( p==0 ) return 0;







<
<
<
<
<
<
<
<
<
<
<
<







58600
58601
58602
58603
58604
58605
58606












58607
58608
58609
58610
58611
58612
58613
*************************************************************************
** This file contains code used for creating, destroying, and populating
** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.)  Prior
** to version 2.8.7, all this code was combined into the vdbe.c source file.
** But that file was getting too big so this subroutines were split out.
*/













/*
** Create a new virtual database engine.
*/
SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(sqlite3 *db){
  Vdbe *p;
  p = sqlite3DbMallocZero(db, sizeof(Vdbe) );
  if( p==0 ) return 0;
58703
58704
58705
58706
58707
58708
58709

58710

58711
58712
58713
58714
58715
58716
58717
  pOp->p1 = p1;
  pOp->p2 = p2;
  pOp->p3 = p3;
  pOp->p4.p = 0;
  pOp->p4type = P4_NOTUSED;
#ifdef SQLITE_DEBUG
  pOp->zComment = 0;

  if( sqlite3VdbeAddopTrace ) sqlite3VdbePrintOp(0, i, &p->aOp[i]);

#endif
#ifdef VDBE_PROFILE
  pOp->cycles = 0;
  pOp->cnt = 0;
#endif
  return i;
}







>
|
>







58729
58730
58731
58732
58733
58734
58735
58736
58737
58738
58739
58740
58741
58742
58743
58744
58745
  pOp->p1 = p1;
  pOp->p2 = p2;
  pOp->p3 = p3;
  pOp->p4.p = 0;
  pOp->p4type = P4_NOTUSED;
#ifdef SQLITE_DEBUG
  pOp->zComment = 0;
  if( p->db->flags & SQLITE_VdbeAddopTrace ){
    sqlite3VdbePrintOp(0, i, &p->aOp[i]);
  }
#endif
#ifdef VDBE_PROFILE
  pOp->cycles = 0;
  pOp->cnt = 0;
#endif
  return i;
}
58922
58923
58924
58925
58926
58927
58928
58929
58930
58931
58932
58933
58934
58935
58936
  while( (pOp = opIterNext(&sIter))!=0 ){
    int opcode = pOp->opcode;
    if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename 
#ifndef SQLITE_OMIT_FOREIGN_KEY
     || (opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1) 
#endif
     || ((opcode==OP_Halt || opcode==OP_HaltIfNull) 
      && (pOp->p1==SQLITE_CONSTRAINT && pOp->p2==OE_Abort))
    ){
      hasAbort = 1;
      break;
    }
  }
  sqlite3DbFree(v->db, sIter.apSub);








|







58950
58951
58952
58953
58954
58955
58956
58957
58958
58959
58960
58961
58962
58963
58964
  while( (pOp = opIterNext(&sIter))!=0 ){
    int opcode = pOp->opcode;
    if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename 
#ifndef SQLITE_OMIT_FOREIGN_KEY
     || (opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1) 
#endif
     || ((opcode==OP_Halt || opcode==OP_HaltIfNull) 
      && ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort))
    ){
      hasAbort = 1;
      break;
    }
  }
  sqlite3DbFree(v->db, sIter.apSub);

59057
59058
59059
59060
59061
59062
59063
59064
59065
59066
59067
59068
59069
59070
59071
      }
      pOut->p3 = pIn->p3;
      pOut->p4type = P4_NOTUSED;
      pOut->p4.p = 0;
      pOut->p5 = 0;
#ifdef SQLITE_DEBUG
      pOut->zComment = 0;
      if( sqlite3VdbeAddopTrace ){
        sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]);
      }
#endif
    }
    p->nOp += nOp;
  }
  return addr;







|







59085
59086
59087
59088
59089
59090
59091
59092
59093
59094
59095
59096
59097
59098
59099
      }
      pOut->p3 = pIn->p3;
      pOut->p4type = P4_NOTUSED;
      pOut->p4.p = 0;
      pOut->p5 = 0;
#ifdef SQLITE_DEBUG
      pOut->zComment = 0;
      if( p->db->flags & SQLITE_VdbeAddopTrace ){
        sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]);
      }
#endif
    }
    p->nOp += nOp;
  }
  return addr;
60083
60084
60085
60086
60087
60088
60089
60090
60091
60092
60093
60094
60095
60096
60097
    if( nByte ){
      p->pFree = sqlite3DbMallocZero(db, nByte);
    }
    zCsr = p->pFree;
    zEnd = &zCsr[nByte];
  }while( nByte && !db->mallocFailed );

  p->nCursor = (u16)nCursor;
  p->nOnceFlag = nOnce;
  if( p->aVar ){
    p->nVar = (ynVar)nVar;
    for(n=0; n<nVar; n++){
      p->aVar[n].flags = MEM_Null;
      p->aVar[n].db = db;
    }







|







60111
60112
60113
60114
60115
60116
60117
60118
60119
60120
60121
60122
60123
60124
60125
    if( nByte ){
      p->pFree = sqlite3DbMallocZero(db, nByte);
    }
    zCsr = p->pFree;
    zEnd = &zCsr[nByte];
  }while( nByte && !db->mallocFailed );

  p->nCursor = nCursor;
  p->nOnceFlag = nOnce;
  if( p->aVar ){
    p->nVar = (ynVar)nVar;
    for(n=0; n<nVar; n++){
      p->aVar[n].flags = MEM_Null;
      p->aVar[n].db = db;
    }
60325
60326
60327
60328
60329
60330
60331
60332
60333
60334
60335
60336
60337
60338
60339
    return rc;
  }

  /* If there are any write-transactions at all, invoke the commit hook */
  if( needXcommit && db->xCommitCallback ){
    rc = db->xCommitCallback(db->pCommitArg);
    if( rc ){
      return SQLITE_CONSTRAINT;
    }
  }

  /* The simple case - no more than one database file (not counting the
  ** TEMP database) has a transaction active.   There is no need for the
  ** master-journal.
  **







|







60353
60354
60355
60356
60357
60358
60359
60360
60361
60362
60363
60364
60365
60366
60367
    return rc;
  }

  /* If there are any write-transactions at all, invoke the commit hook */
  if( needXcommit && db->xCommitCallback ){
    rc = db->xCommitCallback(db->pCommitArg);
    if( rc ){
      return SQLITE_CONSTRAINT_COMMITHOOK;
    }
  }

  /* The simple case - no more than one database file (not counting the
  ** TEMP database) has a transaction active.   There is no need for the
  ** master-journal.
  **
60617
60618
60619
60620
60621
60622
60623
60624
60625
60626
60627
60628
60629
60630
60631
60632
60633
60634
60635
60636
60637
60638
/*
** This function is called when a transaction opened by the database 
** handle associated with the VM passed as an argument is about to be 
** committed. If there are outstanding deferred foreign key constraint
** violations, return SQLITE_ERROR. Otherwise, SQLITE_OK.
**
** If there are outstanding FK violations and this function returns 
** SQLITE_ERROR, set the result of the VM to SQLITE_CONSTRAINT and write
** an error message to it. Then return SQLITE_ERROR.
*/
#ifndef SQLITE_OMIT_FOREIGN_KEY
SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *p, int deferred){
  sqlite3 *db = p->db;
  if( (deferred && db->nDeferredCons>0) || (!deferred && p->nFkConstraint>0) ){
    p->rc = SQLITE_CONSTRAINT;
    p->errorAction = OE_Abort;
    sqlite3SetString(&p->zErrMsg, db, "foreign key constraint failed");
    return SQLITE_ERROR;
  }
  return SQLITE_OK;
}
#endif







|
|





|







60645
60646
60647
60648
60649
60650
60651
60652
60653
60654
60655
60656
60657
60658
60659
60660
60661
60662
60663
60664
60665
60666
/*
** This function is called when a transaction opened by the database 
** handle associated with the VM passed as an argument is about to be 
** committed. If there are outstanding deferred foreign key constraint
** violations, return SQLITE_ERROR. Otherwise, SQLITE_OK.
**
** If there are outstanding FK violations and this function returns 
** SQLITE_ERROR, set the result of the VM to SQLITE_CONSTRAINT_FOREIGNKEY
** and write an error message to it. Then return SQLITE_ERROR.
*/
#ifndef SQLITE_OMIT_FOREIGN_KEY
SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *p, int deferred){
  sqlite3 *db = p->db;
  if( (deferred && db->nDeferredCons>0) || (!deferred && p->nFkConstraint>0) ){
    p->rc = SQLITE_CONSTRAINT_FOREIGNKEY;
    p->errorAction = OE_Abort;
    sqlite3SetString(&p->zErrMsg, db, "foreign key constraint failed");
    return SQLITE_ERROR;
  }
  return SQLITE_OK;
}
#endif
60739
60740
60741
60742
60743
60744
60745
60746
60747
60748
60749
60750
60751
60752
60753
      if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){
        rc = sqlite3VdbeCheckFk(p, 1);
        if( rc!=SQLITE_OK ){
          if( NEVER(p->readOnly) ){
            sqlite3VdbeLeave(p);
            return SQLITE_ERROR;
          }
          rc = SQLITE_CONSTRAINT;
        }else{ 
          /* The auto-commit flag is true, the vdbe program was successful 
          ** or hit an 'OR FAIL' constraint and there are no deferred foreign
          ** key constraints to hold up the transaction. This means a commit 
          ** is required. */
          rc = vdbeCommit(db, p);
        }







|







60767
60768
60769
60770
60771
60772
60773
60774
60775
60776
60777
60778
60779
60780
60781
      if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){
        rc = sqlite3VdbeCheckFk(p, 1);
        if( rc!=SQLITE_OK ){
          if( NEVER(p->readOnly) ){
            sqlite3VdbeLeave(p);
            return SQLITE_ERROR;
          }
          rc = SQLITE_CONSTRAINT_FOREIGNKEY;
        }else{ 
          /* The auto-commit flag is true, the vdbe program was successful 
          ** or hit an 'OR FAIL' constraint and there are no deferred foreign
          ** key constraints to hold up the transaction. This means a commit 
          ** is required. */
          rc = vdbeCommit(db, p);
        }
60782
60783
60784
60785
60786
60787
60788
60789
60790
60791
60792
60793
60794
60795
60796
    ** do so. If this operation returns an error, and the current statement
    ** error code is SQLITE_OK or SQLITE_CONSTRAINT, then promote the
    ** current statement error code.
    */
    if( eStatementOp ){
      rc = sqlite3VdbeCloseStatement(p, eStatementOp);
      if( rc ){
        if( p->rc==SQLITE_OK || p->rc==SQLITE_CONSTRAINT ){
          p->rc = rc;
          sqlite3DbFree(db, p->zErrMsg);
          p->zErrMsg = 0;
        }
        sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
        sqlite3CloseSavepoints(db);
        db->autoCommit = 1;







|







60810
60811
60812
60813
60814
60815
60816
60817
60818
60819
60820
60821
60822
60823
60824
    ** do so. If this operation returns an error, and the current statement
    ** error code is SQLITE_OK or SQLITE_CONSTRAINT, then promote the
    ** current statement error code.
    */
    if( eStatementOp ){
      rc = sqlite3VdbeCloseStatement(p, eStatementOp);
      if( rc ){
        if( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT ){
          p->rc = rc;
          sqlite3DbFree(db, p->zErrMsg);
          p->zErrMsg = 0;
        }
        sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
        sqlite3CloseSavepoints(db);
        db->autoCommit = 1;
61023
61024
61025
61026
61027
61028
61029
61030
61031
61032
61033
61034
61035
61036
61037
  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->pExplain);
#endif
}

/*
** Delete an entire VDBE.
*/







|







61051
61052
61053
61054
61055
61056
61057
61058
61059
61060
61061
61062
61063
61064
61065
  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)
  sqlite3DbFree(db, p->zExplain);
  sqlite3DbFree(db, p->pExplain);
#endif
}

/*
** Delete an entire VDBE.
*/
64779
64780
64781
64782
64783
64784
64785
64786
64787
64788
64789
64790
64791
64792
64793
    sqlite3_log(pOp->p1, "constraint failed at %d in [%s]", pc, p->zSql);
  }
  rc = sqlite3VdbeHalt(p);
  assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR );
  if( rc==SQLITE_BUSY ){
    p->rc = rc = SQLITE_BUSY;
  }else{
    assert( rc==SQLITE_OK || p->rc==SQLITE_CONSTRAINT );
    assert( rc==SQLITE_OK || db->nDeferredCons>0 );
    rc = p->rc ? SQLITE_ERROR : SQLITE_DONE;
  }
  goto vdbe_return;
}

/* Opcode: Integer P1 P2 * * *







|







64807
64808
64809
64810
64811
64812
64813
64814
64815
64816
64817
64818
64819
64820
64821
    sqlite3_log(pOp->p1, "constraint failed at %d in [%s]", pc, p->zSql);
  }
  rc = sqlite3VdbeHalt(p);
  assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR );
  if( rc==SQLITE_BUSY ){
    p->rc = rc = SQLITE_BUSY;
  }else{
    assert( rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT );
    assert( rc==SQLITE_OK || db->nDeferredCons>0 );
    rc = p->rc ? SQLITE_ERROR : SQLITE_DONE;
  }
  goto vdbe_return;
}

/* Opcode: Integer P1 P2 * * *
70111
70112
70113
70114
70115
70116
70117
70118
70119
70120
70121
70122
70123
70124
70125
    rc = u.cr.pModule->xUpdate(u.cr.pVtab, u.cr.nArg, u.cr.apArg, &u.cr.rowid);
    db->vtabOnConflict = vtabOnConflict;
    importVtabErrMsg(p, u.cr.pVtab);
    if( rc==SQLITE_OK && pOp->p1 ){
      assert( u.cr.nArg>1 && u.cr.apArg[0] && (u.cr.apArg[0]->flags&MEM_Null) );
      db->lastRowid = lastRowid = u.cr.rowid;
    }
    if( rc==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
      if( pOp->p5==OE_Ignore ){
        rc = SQLITE_OK;
      }else{
        p->errorAction = ((pOp->p5==OE_Replace) ? OE_Abort : pOp->p5);
      }
    }else{
      p->nChange++;







|







70139
70140
70141
70142
70143
70144
70145
70146
70147
70148
70149
70150
70151
70152
70153
    rc = u.cr.pModule->xUpdate(u.cr.pVtab, u.cr.nArg, u.cr.apArg, &u.cr.rowid);
    db->vtabOnConflict = vtabOnConflict;
    importVtabErrMsg(p, u.cr.pVtab);
    if( rc==SQLITE_OK && pOp->p1 ){
      assert( u.cr.nArg>1 && u.cr.apArg[0] && (u.cr.apArg[0]->flags&MEM_Null) );
      db->lastRowid = lastRowid = u.cr.rowid;
    }
    if( (rc&0xff)==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
      if( pOp->p5==OE_Ignore ){
        rc = SQLITE_OK;
      }else{
        p->errorAction = ((pOp->p5==OE_Replace) ? OE_Abort : pOp->p5);
      }
    }else{
      p->nChange++;
71888
71889
71890
71891
71892
71893
71894








71895
71896
71897
71898
71899
71900
71901
    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);
      }








    }
  }
  return rc;
}

/*
** Close the file.







>
>
>
>
>
>
>
>







71916
71917
71918
71919
71920
71921
71922
71923
71924
71925
71926
71927
71928
71929
71930
71931
71932
71933
71934
71935
71936
71937
    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.
72634
72635
72636
72637
72638
72639
72640





























72641
72642
72643
72644
72645
72646
72647
    for(k=0; k<pUsing->nId; k++){
      if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ) return 1;
    }
  }
  return 0;
}































/*
** 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:
**







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







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
72697
72698
72699
72700
72701
72702
72703
72704
72705
72706
72707
72708
72709
72710
72711
72712
    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:
**
72689
72690
72691
72692
72693
72694
72695














72696
72697
72698
72699
72700
72701
72702
72703
72704
72705
72706
72707
72708
72709
72710
72711
72712
72713

72714

72715


72716

72717
72718


72719
72720
72721
72722
72723





72724
72725
72726
72727
72728
72729
72730
72731
72732
72733
72734
72735
72736
72737
72738
72739
72740
72741
72742
72743
72744
72745
72746
72747
72748
72749
72750
72751
72752




72753

72754
72755
72756
72757
72758
72759
72760
  assert( zCol );    /* The Z in X.Y.Z cannot be NULL */
  assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );

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















  /* 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( zTab ){
          if( pItem->zAlias ){

            char *zTabName = pItem->zAlias;

            if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue;


          }else{

            char *zTabName = pTab->zName;
            if( NEVER(zTabName==0) || 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;
          }
        }
      }




    }


#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;







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









<




<

<
|
>
|
>
|
>
>
|
>
|
<
>
>
|
|
|
|
|
>
>
>
>
>



<
<
<













<
<

<






>
>
>
>
|
>







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
72831
72832
72833
72834
72835
72836
72837
72838
72839
72840
72841
72842
72843
72844
72845
72846
  assert( zCol );    /* The Z in X.Y.Z cannot be NULL */
  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;

        Column *pCol;
  
        pTab = pItem->pTab;
        assert( pTab!=0 && pTab->zName!=0 );

        assert( pTab->nCol>0 );

        if( pItem->pSelect && (pItem->pSelect->selFlags & SF_NestedFrom)!=0 ){
          int hit = 0;
          pEList = pItem->pSelect->pEList;
          for(j=0; j<pEList->nExpr; j++){
            if( sqlite3MatchSpanName(pEList->a[j].zSpan, zCol, zTab, zDb) ){
              cnt++;
              cntTab = 2;
              pMatch = pItem;
              pExpr->iColumn = j;
              hit = 1;

            }
          }
          if( hit || zTab==0 ) continue;
        }
        if( zDb && pTab->pSchema!=pSchema ){
          continue;
        }
        if( zTab ){
          const char *zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName;
          assert( zTabName!=0 );
          if( sqlite3StrICmp(zTabName, zTab)!=0 ){
            continue;
          }
        }
        if( 0==(cntTab++) ){



          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++;


            pMatch = pItem;

            /* 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;
73081
73082
73083
73084
73085
73086
73087
73088
73089
73090
73091
73092
73093
73094
73095
        }
      }
#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 ){
        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++;
      }







|







73167
73168
73169
73170
73171
73172
73173
73174
73175
73176
73177
73178
73179
73180
73181
        }
      }
#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 ){
        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++;
      }
73517
73518
73519
73520
73521
73522
73523
73524
73525
73526
73527
73528
73529
73530
73531
73532
73533
73534
73535
73536
73537
73538
73539
73540
73541
73542
73543
73544
73545
73546
73547
    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 */
        int nRef = 0;             /* Refcount for pOuterNC and outer contexts */







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







73603
73604
73605
73606
73607
73608
73609

















73610
73611
73612
73613
73614
73615
73616
    memset(&sNC, 0, sizeof(sNC));
    sNC.pParse = pParse;
    if( sqlite3ResolveExprNames(&sNC, p->pLimit) ||
        sqlite3ResolveExprNames(&sNC, p->pOffset) ){
      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 */
        int nRef = 0;             /* Refcount for pOuterNC and outer contexts */
73560
73561
73562
73563
73564
73565
73566

















73567
73568
73569
73570
73571
73572
73573
        if( pParse->nErr || db->mallocFailed ) return WRC_Abort;

        for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef;
        assert( pItem->isCorrelated==0 && nRef<=0 );
        pItem->isCorrelated = (nRef!=0);
      }
    }

















  
    /* 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 ){







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







73629
73630
73631
73632
73633
73634
73635
73636
73637
73638
73639
73640
73641
73642
73643
73644
73645
73646
73647
73648
73649
73650
73651
73652
73653
73654
73655
73656
73657
73658
73659
        if( pParse->nErr || db->mallocFailed ) return WRC_Abort;

        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 ){
76698
76699
76700
76701
76702
76703
76704
76705

76706
76707
76708
76709
76710
76711
76712
        sqlite3MayAbort(pParse);
      }
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
      if( pExpr->affinity==OE_Ignore ){
        sqlite3VdbeAddOp4(
            v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0);
      }else{
        sqlite3HaltConstraint(pParse, pExpr->affinity, pExpr->u.zToken, 0);

      }

      break;
    }
#endif
  }
  sqlite3ReleaseTempReg(pParse, regFree1);







|
>







76784
76785
76786
76787
76788
76789
76790
76791
76792
76793
76794
76795
76796
76797
76798
76799
        sqlite3MayAbort(pParse);
      }
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
      if( pExpr->affinity==OE_Ignore ){
        sqlite3VdbeAddOp4(
            v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0);
      }else{
        sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_TRIGGER,
                              pExpr->affinity, pExpr->u.zToken, 0);
      }

      break;
    }
#endif
  }
  sqlite3ReleaseTempReg(pParse, regFree1);
77044
77045
77046
77047
77048
77049
77050






77051
77052
77053
77054
77055
77056
77057
  }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( i<pList->nExpr-1 ){
        sqlite3ExplainNL(pOut);
      }
    }
    sqlite3ExplainPop(pOut);
  }
}







>
>
>
>
>
>







77131
77132
77133
77134
77135
77136
77137
77138
77139
77140
77141
77142
77143
77144
77145
77146
77147
77148
77149
77150
  }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);
  }
}
83163
83164
83165
83166
83167
83168
83169
83170
83171
83172
83173
83174
83175
83176
83177
83178
  sqlite3VdbeJumpHere(v, addr1);
  addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0);
  if( pIndex->onError!=OE_None ){
    int j2 = sqlite3VdbeCurrentAddr(v) + 3;
    sqlite3VdbeAddOp2(v, OP_Goto, 0, j2);
    addr2 = sqlite3VdbeCurrentAddr(v);
    sqlite3VdbeAddOp3(v, OP_SorterCompare, iSorter, j2, regRecord);
    sqlite3HaltConstraint(
        pParse, OE_Abort, "indexed columns are not unique", P4_STATIC
    );
  }else{
    addr2 = sqlite3VdbeCurrentAddr(v);
  }
  sqlite3VdbeAddOp2(v, OP_SorterData, iSorter, regRecord);
  sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 1);
  sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);







|
|







83256
83257
83258
83259
83260
83261
83262
83263
83264
83265
83266
83267
83268
83269
83270
83271
  sqlite3VdbeJumpHere(v, addr1);
  addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0);
  if( pIndex->onError!=OE_None ){
    int j2 = sqlite3VdbeCurrentAddr(v) + 3;
    sqlite3VdbeAddOp2(v, OP_Goto, 0, j2);
    addr2 = sqlite3VdbeCurrentAddr(v);
    sqlite3VdbeAddOp3(v, OP_SorterCompare, iSorter, j2, regRecord);
    sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_UNIQUE,
        OE_Abort, "indexed columns are not unique", P4_STATIC
    );
  }else{
    addr2 = sqlite3VdbeCurrentAddr(v);
  }
  sqlite3VdbeAddOp2(v, OP_SorterData, iSorter, regRecord);
  sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 1);
  sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
83190
83191
83192
83193
83194
83195
83196
83197
83198
83199
83200
83201
83202
83203
83204
83205
    ** (made available to the compiler for reuse) using 
    ** sqlite3ReleaseTempRange(). So in some ways having the OP_IsUnique
    ** opcode use the values stored within seems dangerous. However, since
    ** we can be sure that no other temp registers have been allocated
    ** since sqlite3ReleaseTempRange() was called, it is safe to do so.
    */
    sqlite3VdbeAddOp4(v, OP_IsUnique, iIdx, j2, regRowid, pRegKey, P4_INT32);
    sqlite3HaltConstraint(
        pParse, OE_Abort, "indexed columns are not unique", P4_STATIC);
  }
  sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 0);
  sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
#endif
  sqlite3ReleaseTempReg(pParse, regRecord);
  sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2);
  sqlite3VdbeJumpHere(v, addr1);







|
|







83283
83284
83285
83286
83287
83288
83289
83290
83291
83292
83293
83294
83295
83296
83297
83298
    ** (made available to the compiler for reuse) using 
    ** sqlite3ReleaseTempRange(). So in some ways having the OP_IsUnique
    ** opcode use the values stored within seems dangerous. However, since
    ** we can be sure that no other temp registers have been allocated
    ** since sqlite3ReleaseTempRange() was called, it is safe to do so.
    */
    sqlite3VdbeAddOp4(v, OP_IsUnique, iIdx, j2, regRowid, pRegKey, P4_INT32);
    sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_UNIQUE,
        "indexed columns are not unique", P4_STATIC);
  }
  sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 0);
  sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
#endif
  sqlite3ReleaseTempReg(pParse, regRecord);
  sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2);
  sqlite3VdbeJumpHere(v, addr1);
84408
84409
84410
84411
84412
84413
84414
84415






84416

84417
84418
84419
84420
84421
84422
84423
84424
84425
84426
84427
}

/*
** Code an OP_Halt that causes the vdbe to return an SQLITE_CONSTRAINT
** error. The onError parameter determines which (if any) of the statement
** and/or current transaction is rolled back.
*/
SQLITE_PRIVATE void sqlite3HaltConstraint(Parse *pParse, int onError, char *p4, int p4type){






  Vdbe *v = sqlite3GetVdbe(pParse);

  if( onError==OE_Abort ){
    sqlite3MayAbort(pParse);
  }
  sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0, p4, p4type);
}

/*
** Check to see if pIndex uses the collating sequence pColl.  Return
** true if it does and false if it does not.
*/
#ifndef SQLITE_OMIT_REINDEX







|
>
>
>
>
>
>

>



|







84501
84502
84503
84504
84505
84506
84507
84508
84509
84510
84511
84512
84513
84514
84515
84516
84517
84518
84519
84520
84521
84522
84523
84524
84525
84526
84527
}

/*
** Code an OP_Halt that causes the vdbe to return an SQLITE_CONSTRAINT
** error. The onError parameter determines which (if any) of the statement
** and/or current transaction is rolled back.
*/
SQLITE_PRIVATE void sqlite3HaltConstraint(
  Parse *pParse,    /* Parsing context */
  int errCode,      /* extended error code */
  int onError,      /* Constraint type */
  char *p4,         /* Error message */
  int p4type        /* P4_STATIC or P4_TRANSIENT */
){
  Vdbe *v = sqlite3GetVdbe(pParse);
  assert( (errCode&0xff)==SQLITE_CONSTRAINT );
  if( onError==OE_Abort ){
    sqlite3MayAbort(pParse);
  }
  sqlite3VdbeAddOp4(v, OP_Halt, errCode, onError, 0, p4, p4type);
}

/*
** Check to see if pIndex uses the collating sequence pColl.  Return
** true if it does and false if it does not.
*/
#ifndef SQLITE_OMIT_REINDEX
87400
87401
87402
87403
87404
87405
87406
87407

87408
87409
87410
87411
87412
87413
87414
87415
#ifndef SQLITE_OMIT_TRIGGER

/*
** Deferred and Immediate FKs
** --------------------------
**
** Foreign keys in SQLite come in two flavours: deferred and immediate.
** If an immediate foreign key constraint is violated, SQLITE_CONSTRAINT

** is returned and the current statement transaction rolled back. If a 
** deferred foreign key constraint is violated, no action is taken 
** immediately. However if the application attempts to commit the 
** transaction before fixing the constraint violation, the attempt fails.
**
** Deferred constraints are implemented using a simple counter associated
** with the database handle. The counter is set to zero each time a 
** database transaction is opened. Each time a statement is executed 







|
>
|







87500
87501
87502
87503
87504
87505
87506
87507
87508
87509
87510
87511
87512
87513
87514
87515
87516
#ifndef SQLITE_OMIT_TRIGGER

/*
** Deferred and Immediate FKs
** --------------------------
**
** Foreign keys in SQLite come in two flavours: deferred and immediate.
** If an immediate foreign key constraint is violated,
** SQLITE_CONSTRAINT_FOREIGNKEY is returned and the current
** statement transaction rolled back. If a 
** deferred foreign key constraint is violated, no action is taken 
** immediately. However if the application attempts to commit the 
** transaction before fixing the constraint violation, the attempt fails.
**
** Deferred constraints are implemented using a simple counter associated
** with the database handle. The counter is set to zero each time a 
** database transaction is opened. Each time a statement is executed 
87465
87466
87467
87468
87469
87470
87471
87472

87473
87474
87475
87476
87477
87478
87479
** If a delete caused by OR REPLACE violates an FK constraint, an exception
** is thrown, even if the FK constraint would be satisfied after the new 
** row is inserted.
**
** Immediate constraints are usually handled similarly. The only difference 
** is that the counter used is stored as part of each individual statement
** object (struct Vdbe). If, after the statement has run, its immediate
** constraint counter is greater than zero, it returns SQLITE_CONSTRAINT

** and the statement transaction is rolled back. An exception is an INSERT
** statement that inserts a single row only (no triggers). In this case,
** instead of using a counter, an exception is thrown immediately if the
** INSERT violates a foreign key constraint. This is necessary as such
** an INSERT does not open a statement transaction.
**
** TODO: How should dropping a table be handled? How should renaming a 







|
>







87566
87567
87568
87569
87570
87571
87572
87573
87574
87575
87576
87577
87578
87579
87580
87581
** If a delete caused by OR REPLACE violates an FK constraint, an exception
** is thrown, even if the FK constraint would be satisfied after the new 
** row is inserted.
**
** Immediate constraints are usually handled similarly. The only difference 
** is that the counter used is stored as part of each individual statement
** object (struct Vdbe). If, after the statement has run, its immediate
** constraint counter is greater than zero,
** it returns SQLITE_CONSTRAINT_FOREIGNKEY
** and the statement transaction is rolled back. An exception is an INSERT
** statement that inserts a single row only (no triggers). In this case,
** instead of using a counter, an exception is thrown immediately if the
** INSERT violates a foreign key constraint. This is necessary as such
** an INSERT does not open a statement transaction.
**
** TODO: How should dropping a table be handled? How should renaming a 
87521
87522
87523
87524
87525
87526
87527
87528
87529
87530
87531
87532
87533
87534
87535
**   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 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.







|







87623
87624
87625
87626
87627
87628
87629
87630
87631
87632
87633
87634
87635
87636
87637
**   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. 
**
** 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.
87557
87558
87559
87560
87561
87562
87563
87564
87565
87566
87567
87568
87569
87570
87571
**      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.
*/
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 */







|







87659
87660
87661
87662
87663
87664
87665
87666
87667
87668
87669
87670
87671
87672
87673
**      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(
  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 */
87654
87655
87656
87657
87658
87659
87660
87661


87662
87663
87664
87665
87666
87667
87668
        if( i==nCol ) break;      /* pIdx is usable */
      }
    }
  }

  if( !pIdx ){
    if( !pParse->disableTriggers ){
      sqlite3ErrorMsg(pParse, "foreign key mismatch");


    }
    sqlite3DbFree(pParse->db, aiCol);
    return 1;
  }

  *ppIdx = pIdx;
  return 0;







|
>
>







87756
87757
87758
87759
87760
87761
87762
87763
87764
87765
87766
87767
87768
87769
87770
87771
87772
        if( i==nCol ) break;      /* pIdx is usable */
      }
    }
  }

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

  *ppIdx = pIdx;
  return 0;
87803
87804
87805
87806
87807
87808
87809
87810
87811
87812
87813
87814
87815
87816
87817
87818

  if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){
    /* Special case: If this is an INSERT statement that will insert exactly
    ** one row into the table, raise a constraint immediately instead of
    ** incrementing a counter. This is necessary as the VM code is being
    ** generated for will not open a statement transaction.  */
    assert( nIncr==1 );
    sqlite3HaltConstraint(
        pParse, OE_Abort, "foreign key constraint failed", P4_STATIC
    );
  }else{
    if( nIncr>0 && pFKey->isDeferred==0 ){
      sqlite3ParseToplevel(pParse)->mayAbort = 1;
    }
    sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
  }







|
|







87907
87908
87909
87910
87911
87912
87913
87914
87915
87916
87917
87918
87919
87920
87921
87922

  if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){
    /* Special case: If this is an INSERT statement that will insert exactly
    ** one row into the table, raise a constraint immediately instead of
    ** incrementing a counter. This is necessary as the VM code is being
    ** generated for will not open a statement transaction.  */
    assert( nIncr==1 );
    sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
        OE_Abort, "foreign key constraint failed", P4_STATIC
    );
  }else{
    if( nIncr>0 && pFKey->isDeferred==0 ){
      sqlite3ParseToplevel(pParse)->mayAbort = 1;
    }
    sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
  }
88044
88045
88046
88047
88048
88049
88050
88051
88052
88053
88054
88055
88056
88057
88058
88059
    pParse->disableTriggers = 0;

    /* If the DELETE has generated immediate foreign key constraint 
    ** violations, halt the VDBE and return an error at this point, before
    ** any modifications to the schema are made. This is because statement
    ** transactions are not able to rollback schema changes.  */
    sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2);
    sqlite3HaltConstraint(
        pParse, OE_Abort, "foreign key constraint failed", P4_STATIC
    );

    if( iSkip ){
      sqlite3VdbeResolveLabel(v, iSkip);
    }
  }
}







|
|







88148
88149
88150
88151
88152
88153
88154
88155
88156
88157
88158
88159
88160
88161
88162
88163
    pParse->disableTriggers = 0;

    /* If the DELETE has generated immediate foreign key constraint 
    ** violations, halt the VDBE and return an error at this point, before
    ** any modifications to the schema are made. This is because statement
    ** transactions are not able to rollback schema changes.  */
    sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2);
    sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
        OE_Abort, "foreign key constraint failed", P4_STATIC
    );

    if( iSkip ){
      sqlite3VdbeResolveLabel(v, iSkip);
    }
  }
}
88115
88116
88117
88118
88119
88120
88121
88122
88123
88124
88125
88126
88127
88128
88129
    ** 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 || 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







|







88219
88220
88221
88222
88223
88224
88225
88226
88227
88228
88229
88230
88231
88232
88233
    ** 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) ){
      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
88195
88196
88197
88198
88199
88200
88201
88202
88203
88204
88205
88206
88207
88208
88209
    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( 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







|







88299
88300
88301
88302
88303
88304
88305
88306
88307
88308
88309
88310
88311
88312
88313
    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( !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
88250
88251
88252
88253
88254
88255
88256
88257
88258
88259
88260
88261
88262
88263
88264
    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;
      locateFkeyIndex(pParse, pTab, p, &pIdx, 0);
      if( pIdx ){
        for(i=0; i<pIdx->nColumn; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]);
      }
    }
  }
  return mask;
}







|







88354
88355
88356
88357
88358
88359
88360
88361
88362
88363
88364
88365
88366
88367
88368
    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);
      if( pIdx ){
        for(i=0; i<pIdx->nColumn; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]);
      }
    }
  }
  return mask;
}
88376
88377
88378
88379
88380
88381
88382
88383
88384
88385
88386
88387
88388
88389
88390
    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( 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 */







|







88480
88481
88482
88483
88484
88485
88486
88487
88488
88489
88490
88491
88492
88493
88494
    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;
    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 */
89849
89850
89851
89852
89853
89854
89855
89856
89857
89858
89859
89860
89861
89862
89863
    switch( onError ){
      case OE_Abort:
        sqlite3MayAbort(pParse);
      case OE_Rollback:
      case OE_Fail: {
        char *zMsg;
        sqlite3VdbeAddOp3(v, OP_HaltIfNull,
                                  SQLITE_CONSTRAINT, onError, regData+i);
        zMsg = sqlite3MPrintf(db, "%s.%s may not be NULL",
                              pTab->zName, pTab->aCol[i].zName);
        sqlite3VdbeChangeP4(v, -1, zMsg, P4_DYNAMIC);
        break;
      }
      case OE_Ignore: {
        sqlite3VdbeAddOp2(v, OP_IsNull, regData+i, ignoreDest);







|







89953
89954
89955
89956
89957
89958
89959
89960
89961
89962
89963
89964
89965
89966
89967
    switch( onError ){
      case OE_Abort:
        sqlite3MayAbort(pParse);
      case OE_Rollback:
      case OE_Fail: {
        char *zMsg;
        sqlite3VdbeAddOp3(v, OP_HaltIfNull,
                          SQLITE_CONSTRAINT_NOTNULL, onError, regData+i);
        zMsg = sqlite3MPrintf(db, "%s.%s may not be NULL",
                              pTab->zName, pTab->aCol[i].zName);
        sqlite3VdbeChangeP4(v, -1, zMsg, P4_DYNAMIC);
        break;
      }
      case OE_Ignore: {
        sqlite3VdbeAddOp2(v, OP_IsNull, regData+i, ignoreDest);
89889
89890
89891
89892
89893
89894
89895
89896

89897
89898
89899
89900
89901
89902
89903
        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);
    }
  }
#endif /* !defined(SQLITE_OMIT_CHECK) */

  /* If we have an INTEGER PRIMARY KEY, make sure the primary key







|
>







89993
89994
89995
89996
89997
89998
89999
90000
90001
90002
90003
90004
90005
90006
90007
90008
        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, SQLITE_CONSTRAINT_CHECK,
                              onError, zConsName, P4_DYNAMIC);
      }
      sqlite3VdbeResolveLabel(v, allOk);
    }
  }
#endif /* !defined(SQLITE_OMIT_CHECK) */

  /* If we have an INTEGER PRIMARY KEY, make sure the primary key
89920
89921
89922
89923
89924
89925
89926
89927
89928
89929
89930
89931
89932
89933
89934
89935
      default: {
        onError = OE_Abort;
        /* Fall thru into the next case */
      }
      case OE_Rollback:
      case OE_Abort:
      case OE_Fail: {
        sqlite3HaltConstraint(
          pParse, onError, "PRIMARY KEY must be unique", P4_STATIC);
        break;
      }
      case OE_Replace: {
        /* If there are DELETE triggers on this table and the
        ** recursive-triggers flag is set, call GenerateRowDelete() to
        ** remove the conflicting row from the table. This will fire
        ** the triggers and remove both the table and index b-tree entries.







|
|







90025
90026
90027
90028
90029
90030
90031
90032
90033
90034
90035
90036
90037
90038
90039
90040
      default: {
        onError = OE_Abort;
        /* Fall thru into the next case */
      }
      case OE_Rollback:
      case OE_Abort:
      case OE_Fail: {
        sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_PRIMARYKEY,
           onError, "PRIMARY KEY must be unique", P4_STATIC);
        break;
      }
      case OE_Replace: {
        /* If there are DELETE triggers on this table and the
        ** recursive-triggers flag is set, call GenerateRowDelete() to
        ** remove the conflicting row from the table. This will fire
        ** the triggers and remove both the table and index b-tree entries.
90048
90049
90050
90051
90052
90053
90054
90055

90056
90057
90058
90059
90060
90061
90062
          sqlite3StrAccumAppend(&errMsg, zSep, -1);
          zSep = ", ";
          sqlite3StrAccumAppend(&errMsg, zCol, -1);
        }
        sqlite3StrAccumAppend(&errMsg,
            pIdx->nColumn>1 ? " are not unique" : " is not unique", -1);
        zErr = sqlite3StrAccumFinish(&errMsg);
        sqlite3HaltConstraint(pParse, onError, zErr, 0);

        sqlite3DbFree(errMsg.db, zErr);
        break;
      }
      case OE_Ignore: {
        assert( seenReplace==0 );
        sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
        break;







|
>







90153
90154
90155
90156
90157
90158
90159
90160
90161
90162
90163
90164
90165
90166
90167
90168
          sqlite3StrAccumAppend(&errMsg, zSep, -1);
          zSep = ", ";
          sqlite3StrAccumAppend(&errMsg, zCol, -1);
        }
        sqlite3StrAccumAppend(&errMsg,
            pIdx->nColumn>1 ? " are not unique" : " is not unique", -1);
        zErr = sqlite3StrAccumFinish(&errMsg);
        sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_UNIQUE,
                              onError, zErr, 0);
        sqlite3DbFree(errMsg.db, zErr);
        break;
      }
      case OE_Ignore: {
        assert( seenReplace==0 );
        sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
        break;
90456
90457
90458
90459
90460
90461
90462
90463
90464
90465
90466
90467
90468
90469
90470
90471
  sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead);
  emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);
  regData = sqlite3GetTempReg(pParse);
  regRowid = sqlite3GetTempReg(pParse);
  if( pDest->iPKey>=0 ){
    addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
    addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);
    sqlite3HaltConstraint(
        pParse, onError, "PRIMARY KEY must be unique", P4_STATIC);
    sqlite3VdbeJumpHere(v, addr2);
    autoIncStep(pParse, regAutoinc, regRowid);
  }else if( pDest->pIndex==0 ){
    addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid);
  }else{
    addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
    assert( (pDest->tabFlags & TF_Autoincrement)==0 );







|
|







90562
90563
90564
90565
90566
90567
90568
90569
90570
90571
90572
90573
90574
90575
90576
90577
  sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead);
  emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);
  regData = sqlite3GetTempReg(pParse);
  regRowid = sqlite3GetTempReg(pParse);
  if( pDest->iPKey>=0 ){
    addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
    addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);
    sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_PRIMARYKEY,
        onError, "PRIMARY KEY must be unique", P4_STATIC);
    sqlite3VdbeJumpHere(v, addr2);
    autoIncStep(pParse, regAutoinc, regRowid);
  }else if( pDest->pIndex==0 ){
    addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid);
  }else{
    addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
    assert( (pDest->tabFlags & TF_Autoincrement)==0 );
90914
90915
90916
90917
90918
90919
90920














90921
90922
90923
90924
90925
90926
90927
  int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*);
  int (*wal_autocheckpoint)(sqlite3*,int);
  int (*wal_checkpoint)(sqlite3*,const char*);
  void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*);
  int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
  int (*vtab_config)(sqlite3*,int op,...);
  int (*vtab_on_conflict)(sqlite3*);














};

/*
** The following macros redefine the API routines so that they are
** redirected throught the global sqlite3_api structure.
**
** This header file is also used by the loadext.c source file







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







91020
91021
91022
91023
91024
91025
91026
91027
91028
91029
91030
91031
91032
91033
91034
91035
91036
91037
91038
91039
91040
91041
91042
91043
91044
91045
91046
91047
  int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*);
  int (*wal_autocheckpoint)(sqlite3*,int);
  int (*wal_checkpoint)(sqlite3*,const char*);
  void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*);
  int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
  int (*vtab_config)(sqlite3*,int op,...);
  int (*vtab_on_conflict)(sqlite3*);
  /* Version 3.7.16 and later */
  int (*close_v2)(sqlite3*);
  const char *(*db_filename)(sqlite3*,const char*);
  int (*db_readonly)(sqlite3*,const char*);
  int (*db_release_memory)(sqlite3*);
  const char *(*errstr)(int);
  int (*stmt_busy)(sqlite3_stmt*);
  int (*stmt_readonly)(sqlite3_stmt*);
  int (*stricmp)(const char*,const char*);
  int (*uri_boolean)(const char*,const char*,int);
  sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64);
  const char *(*uri_parameter)(const char*,const char*);
  char *(*vsnprintf)(int,char*,const char*,va_list);
  int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
};

/*
** The following macros redefine the API routines so that they are
** redirected throught the global sqlite3_api structure.
**
** This header file is also used by the loadext.c source file
91117
91118
91119
91120
91121
91122
91123














91124
91125
91126
91127
91128
91129
91130
#define sqlite3_unlock_notify          sqlite3_api->unlock_notify
#define sqlite3_wal_autocheckpoint     sqlite3_api->wal_autocheckpoint
#define sqlite3_wal_checkpoint         sqlite3_api->wal_checkpoint
#define sqlite3_wal_hook               sqlite3_api->wal_hook
#define sqlite3_blob_reopen            sqlite3_api->blob_reopen
#define sqlite3_vtab_config            sqlite3_api->vtab_config
#define sqlite3_vtab_on_conflict       sqlite3_api->vtab_on_conflict














#endif /* SQLITE_CORE */

#define SQLITE_EXTENSION_INIT1     const sqlite3_api_routines *sqlite3_api = 0;
#define SQLITE_EXTENSION_INIT2(v)  sqlite3_api = v;

#endif /* _SQLITE3EXT_H_ */








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







91237
91238
91239
91240
91241
91242
91243
91244
91245
91246
91247
91248
91249
91250
91251
91252
91253
91254
91255
91256
91257
91258
91259
91260
91261
91262
91263
91264
#define sqlite3_unlock_notify          sqlite3_api->unlock_notify
#define sqlite3_wal_autocheckpoint     sqlite3_api->wal_autocheckpoint
#define sqlite3_wal_checkpoint         sqlite3_api->wal_checkpoint
#define sqlite3_wal_hook               sqlite3_api->wal_hook
#define sqlite3_blob_reopen            sqlite3_api->blob_reopen
#define sqlite3_vtab_config            sqlite3_api->vtab_config
#define sqlite3_vtab_on_conflict       sqlite3_api->vtab_on_conflict
/* Version 3.7.16 and later */
#define sqlite3_close_v2               sqlite3_api->close_v2
#define sqlite3_db_filename            sqlite3_api->db_filename
#define sqlite3_db_readonly            sqlite3_api->db_readonly
#define sqlite3_db_release_memory      sqlite3_api->db_release_memory
#define sqlite3_errstr                 sqlite3_api->errstr
#define sqlite3_stmt_busy              sqlite3_api->stmt_busy
#define sqlite3_stmt_readonly          sqlite3_api->stmt_readonly
#define sqlite3_stricmp                sqlite3_api->stricmp
#define sqlite3_uri_boolean            sqlite3_api->uri_boolean
#define sqlite3_uri_int64              sqlite3_api->uri_int64
#define sqlite3_uri_parameter          sqlite3_api->uri_parameter
#define sqlite3_uri_vsnprintf          sqlite3_api->vsnprintf
#define sqlite3_wal_checkpoint_v2      sqlite3_api->wal_checkpoint_v2
#endif /* SQLITE_CORE */

#define SQLITE_EXTENSION_INIT1     const sqlite3_api_routines *sqlite3_api = 0;
#define SQLITE_EXTENSION_INIT2(v)  sqlite3_api = v;

#endif /* _SQLITE3EXT_H_ */

91952
91953
91954
91955
91956
91957
91958



91959
91960
91961
91962
91963
91964
91965
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
    { "automatic_index",          SQLITE_AutoIndex     },
#endif
#ifdef SQLITE_DEBUG
    { "sql_trace",                SQLITE_SqlTrace      },
    { "vdbe_listing",             SQLITE_VdbeListing   },
    { "vdbe_trace",               SQLITE_VdbeTrace     },



#endif
#ifndef SQLITE_OMIT_CHECK
    { "ignore_check_constraints", SQLITE_IgnoreChecks  },
#endif
    /* The following is VERY experimental */
    { "writable_schema",          SQLITE_WriteSchema|SQLITE_RecoveryMode },








>
>
>







92086
92087
92088
92089
92090
92091
92092
92093
92094
92095
92096
92097
92098
92099
92100
92101
92102
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
    { "automatic_index",          SQLITE_AutoIndex     },
#endif
#ifdef SQLITE_DEBUG
    { "sql_trace",                SQLITE_SqlTrace      },
    { "vdbe_listing",             SQLITE_VdbeListing   },
    { "vdbe_trace",               SQLITE_VdbeTrace     },
    { "vdbe_addoptrace",          SQLITE_VdbeAddopTrace},
    { "vdbe_debug",    SQLITE_SqlTrace | SQLITE_VdbeListing
                               | SQLITE_VdbeTrace      },
#endif
#ifndef SQLITE_OMIT_CHECK
    { "ignore_check_constraints", SQLITE_IgnoreChecks  },
#endif
    /* The following is VERY experimental */
    { "writable_schema",          SQLITE_WriteSchema|SQLITE_RecoveryMode },

92716
92717
92718
92719
92720
92721
92722
92723
92724
92725


92726
92727

92728
92729
92730
92731
92732
92733
92734
  ** 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;
      int nHidden = 0;
      Column *pCol;


      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);
      sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "pk", SQLITE_STATIC);
      sqlite3ViewGetColumnNames(pParse, pTab);







|


>
>


>







92853
92854
92855
92856
92857
92858
92859
92860
92861
92862
92863
92864
92865
92866
92867
92868
92869
92870
92871
92872
92873
92874
  ** 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 nHidden = 0;
      Column *pCol;
      Index *pPk;
      for(pPk=pTab->pIndex; pPk && pPk->autoIndex!=2; pPk=pPk->pNext){}
      sqlite3VdbeSetNumCols(v, 6);
      pParse->nMem = 6;
      sqlite3CodeVerifySchema(pParse, iDb);
      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);
      sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "pk", SQLITE_STATIC);
      sqlite3ViewGetColumnNames(pParse, pTab);
92743
92744
92745
92746
92747
92748
92749







92750
92751
92752
92753
92754
92755
92756
92757
92758
92759
92760
92761
92762
92763
92764
92765
92766

92767
92768
92769
92770
92771
92772
92773
           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);
        }







        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;
    Table *pTab;
    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
    pIdx = sqlite3FindIndex(db, zRight, zDb);
    if( pIdx ){
      int i;
      pTab = pIdx->pTable;
      sqlite3VdbeSetNumCols(v, 3);
      pParse->nMem = 3;

      sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", SQLITE_STATIC);
      sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", SQLITE_STATIC);
      sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", SQLITE_STATIC);
      for(i=0; i<pIdx->nColumn; i++){
        int cnum = pIdx->aiColumn[i];
        sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
        sqlite3VdbeAddOp2(v, OP_Integer, cnum, 2);







>
>
>
>
>
>
>
|
<















>







92883
92884
92885
92886
92887
92888
92889
92890
92891
92892
92893
92894
92895
92896
92897

92898
92899
92900
92901
92902
92903
92904
92905
92906
92907
92908
92909
92910
92911
92912
92913
92914
92915
92916
92917
92918
92919
92920
           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_ResultRow, 1, 6);
      }
    }
  }else

  if( sqlite3StrICmp(zLeft, "index_info")==0 && zRight ){
    Index *pIdx;
    Table *pTab;
    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
    pIdx = sqlite3FindIndex(db, zRight, zDb);
    if( pIdx ){
      int i;
      pTab = pIdx->pTable;
      sqlite3VdbeSetNumCols(v, 3);
      pParse->nMem = 3;
      sqlite3CodeVerifySchema(pParse, iDb);
      sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", SQLITE_STATIC);
      sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", SQLITE_STATIC);
      sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", SQLITE_STATIC);
      for(i=0; i<pIdx->nColumn; i++){
        int cnum = pIdx->aiColumn[i];
        sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
        sqlite3VdbeAddOp2(v, OP_Integer, cnum, 2);
92786
92787
92788
92789
92790
92791
92792

92793
92794
92795
92796
92797
92798
92799
    if( pTab ){
      v = sqlite3GetVdbe(pParse);
      pIdx = pTab->pIndex;
      if( pIdx ){
        int i = 0; 
        sqlite3VdbeSetNumCols(v, 3);
        pParse->nMem = 3;

        sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
        sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
        sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC);
        while(pIdx){
          sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
          sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
          sqlite3VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3);







>







92933
92934
92935
92936
92937
92938
92939
92940
92941
92942
92943
92944
92945
92946
92947
    if( pTab ){
      v = sqlite3GetVdbe(pParse);
      pIdx = pTab->pIndex;
      if( pIdx ){
        int i = 0; 
        sqlite3VdbeSetNumCols(v, 3);
        pParse->nMem = 3;
        sqlite3CodeVerifySchema(pParse, iDb);
        sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
        sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
        sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC);
        while(pIdx){
          sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
          sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
          sqlite3VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3);
92849
92850
92851
92852
92853
92854
92855

92856
92857
92858
92859
92860
92861
92862
    if( pTab ){
      v = sqlite3GetVdbe(pParse);
      pFK = pTab->pFKey;
      if( pFK ){
        int i = 0; 
        sqlite3VdbeSetNumCols(v, 8);
        pParse->nMem = 8;

        sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "id", SQLITE_STATIC);
        sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "seq", SQLITE_STATIC);
        sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "table", SQLITE_STATIC);
        sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "from", SQLITE_STATIC);
        sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "to", SQLITE_STATIC);
        sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "on_update", SQLITE_STATIC);
        sqlite3VdbeSetColName(v, 6, COLNAME_NAME, "on_delete", SQLITE_STATIC);







>







92997
92998
92999
93000
93001
93002
93003
93004
93005
93006
93007
93008
93009
93010
93011
    if( pTab ){
      v = sqlite3GetVdbe(pParse);
      pFK = pTab->pFKey;
      if( pFK ){
        int i = 0; 
        sqlite3VdbeSetNumCols(v, 8);
        pParse->nMem = 8;
        sqlite3CodeVerifySchema(pParse, iDb);
        sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "id", SQLITE_STATIC);
        sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "seq", SQLITE_STATIC);
        sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "table", SQLITE_STATIC);
        sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "from", SQLITE_STATIC);
        sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "to", SQLITE_STATIC);
        sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "on_update", SQLITE_STATIC);
        sqlite3VdbeSetColName(v, 6, COLNAME_NAME, "on_delete", SQLITE_STATIC);
92879
92880
92881
92882
92883
92884
92885


















































































































92886
92887
92888
92889
92890
92891
92892
            sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 8);
          }
          ++i;
          pFK = pFK->pNextFrom;
        }
      }
    }


















































































































  }else
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */

#ifndef NDEBUG
  if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){
    if( zRight ){
      if( sqlite3GetBoolean(zRight, 0) ){







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







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
93093
93094
93095
93096
93097
93098
93099
93100
93101
93102
93103
93104
93105
93106
93107
93108
93109
93110
93111
93112
93113
93114
93115
93116
93117
93118
93119
93120
93121
93122
93123
93124
93125
93126
93127
93128
93129
93130
93131
93132
93133
93134
93135
93136
93137
93138
93139
93140
93141
93142
93143
93144
93145
93146
93147
93148
93149
93150
93151
93152
93153
93154
93155
            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) ){
93379
93380
93381
93382
93383
93384
93385
93386
93387
93388
93389
93390
93391
93392
93393
      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 ){
#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 ){







|







93642
93643
93644
93645
93646
93647
93648
93649
93650
93651
93652
93653
93654
93655
93656
      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 ){
#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 ){
94338
94339
94340
94341
94342
94343
94344
94345
94346
94347
94348
94349
94350
94351
94352
  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 */
  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) );







|







94601
94602
94603
94604
94605
94606
94607
94608
94609
94610
94611
94612
94613
94614
94615
  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 */
  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) );
94362
94363
94364
94365
94366
94367
94368
94369
94370
94371
94372
94373
94374
94375
94376
  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 = 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;







|







94625
94626
94627
94628
94629
94630
94631
94632
94633
94634
94635
94636
94637
94638
94639
  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->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;
95619
95620
95621
95622
95623
95624
95625
95626
95627
95628
95629
95630
95631
95632
95633
95634
  *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);
    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 ){







<
<







95882
95883
95884
95885
95886
95887
95888


95889
95890
95891
95892
95893
95894
95895
  *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);


    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 ){
95658
95659
95660
95661
95662
95663
95664



95665
95666
95667
95668
95669
95670
95671
    /* 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;



        zName[nName] = 0;
        zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt);
        sqlite3DbFree(db, zName);
        zName = zNewName;
        j = -1;
        if( zName==0 ) break;
      }







>
>
>







95919
95920
95921
95922
95923
95924
95925
95926
95927
95928
95929
95930
95931
95932
95933
95934
95935
    /* 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;
      }
95989
95990
95991
95992
95993
95994
95995


95996
95997
95998
95999
96000
96001
96002
  /* Generate code for the left and right SELECT statements.
  */
  switch( p->op ){
    case TK_ALL: {
      int addr = 0;
      int nLimit;
      assert( !pPrior->pLimit );


      pPrior->pLimit = p->pLimit;
      pPrior->pOffset = p->pOffset;
      explainSetInteger(iSub1, pParse->iNextSelectId);
      rc = sqlite3Select(pParse, pPrior, &dest);
      p->pLimit = 0;
      p->pOffset = 0;
      if( rc ){







>
>







96253
96254
96255
96256
96257
96258
96259
96260
96261
96262
96263
96264
96265
96266
96267
96268
  /* Generate code for the left and right SELECT statements.
  */
  switch( p->op ){
    case TK_ALL: {
      int addr = 0;
      int nLimit;
      assert( !pPrior->pLimit );
      pPrior->iLimit = p->iLimit;
      pPrior->iOffset = p->iOffset;
      pPrior->pLimit = p->pLimit;
      pPrior->pOffset = p->pOffset;
      explainSetInteger(iSub1, pParse->iNextSelectId);
      rc = sqlite3Select(pParse, pPrior, &dest);
      p->pLimit = 0;
      p->pOffset = 0;
      if( rc ){
97245
97246
97247
97248
97249
97250
97251

97252
97253
97254
97255
97256

97257

97258
97259
97260
97261
97262
97263
97264
  **
  ** We call this the "compound-subquery flattening".
  */
  for(pSub=pSub->pPrior; pSub; pSub=pSub->pPrior){
    Select *pNew;
    ExprList *pOrderBy = p->pOrderBy;
    Expr *pLimit = p->pLimit;

    Select *pPrior = p->pPrior;
    p->pOrderBy = 0;
    p->pSrc = 0;
    p->pPrior = 0;
    p->pLimit = 0;

    pNew = sqlite3SelectDup(db, p, 0);

    p->pLimit = pLimit;
    p->pOrderBy = pOrderBy;
    p->pSrc = pSrc;
    p->op = TK_ALL;
    p->pRightmost = 0;
    if( pNew==0 ){
      pNew = pPrior;







>





>

>







97511
97512
97513
97514
97515
97516
97517
97518
97519
97520
97521
97522
97523
97524
97525
97526
97527
97528
97529
97530
97531
97532
97533
  **
  ** We call this the "compound-subquery flattening".
  */
  for(pSub=pSub->pPrior; pSub; pSub=pSub->pPrior){
    Select *pNew;
    ExprList *pOrderBy = p->pOrderBy;
    Expr *pLimit = p->pLimit;
    Expr *pOffset = p->pOffset;
    Select *pPrior = p->pPrior;
    p->pOrderBy = 0;
    p->pSrc = 0;
    p->pPrior = 0;
    p->pLimit = 0;
    p->pOffset = 0;
    pNew = sqlite3SelectDup(db, p, 0);
    p->pOffset = pOffset;
    p->pLimit = pLimit;
    p->pOrderBy = pOrderBy;
    p->pSrc = pSrc;
    p->op = TK_ALL;
    p->pRightmost = 0;
    if( pNew==0 ){
      pNew = pPrior;
97443
97444
97445
97446
97447
97448
97449

97450
97451
97452
97453
97454


97455
97456
97457
97458




97459
97460




97461
97462
97463
97464
97465
97466
97467
97468
97469
97470
97471
97472
97473

97474
97475

97476




97477
97478
97479
97480
97481
97482
97483
97484
  sqlite3SelectDelete(db, pSub1);

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

/*

** 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:
**


**   1. There is a single object in the FROM clause.
**
**   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.




*/
static u8 minMaxQuery(Select *p){




  Expr *pExpr;
  ExprList *pEList = p->pEList;

  if( pEList->nExpr!=1 ) return WHERE_ORDERBY_NORMAL;
  pExpr = pEList->a[0].pExpr;
  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;

  }else if( sqlite3StrICmp(pExpr->u.zToken,"max")==0 ){
    return WHERE_ORDERBY_MAX;

  }




  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:
**







>
|
<
<
<

>
>
|

|
|
>
>
>
>

|
>
>
>
>
|
|

<
<
|
<
<
<
|
|
|
|
>
|
|
>
|
>
>
>
>
|







97712
97713
97714
97715
97716
97717
97718
97719
97720



97721
97722
97723
97724
97725
97726
97727
97728
97729
97730
97731
97732
97733
97734
97735
97736
97737
97738
97739
97740


97741



97742
97743
97744
97745
97746
97747
97748
97749
97750
97751
97752
97753
97754
97755
97756
97757
97758
97759
97760
97761
97762
  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:



**
**    * the query contains just a single aggregate function,
**    * 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 
** 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){
  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 */



    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;
        *ppMinMax = pEList;
      }else if( sqlite3StrICmp(zFunc, "max")==0 ){
        eRet = WHERE_ORDERBY_MAX;
        *ppMinMax = pEList;
      }
    }
  }

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

/*
** 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:
**
97565
97566
97567
97568
97569
97570
97571


97572

97573
97574
97575
97576
97577
97578
97579
97580
97581
97582
97583
97584
97585
97586
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;




  if( db->mallocFailed  ){
    return WRC_Abort;
  }
  if( NEVER(p->pSrc==0) || (p->selFlags & SF_Expanded)!=0 ){
    return WRC_Prune;
  }
  p->selFlags |= SF_Expanded;
  pTabList = p->pSrc;
  pEList = p->pEList;

  /* Make sure cursor numbers have been assigned to all entries in
  ** the FROM clause of the SELECT statement.
  */
  sqlite3SrcListAssignCursors(pParse, pTabList);







>
>

>



|


<







97843
97844
97845
97846
97847
97848
97849
97850
97851
97852
97853
97854
97855
97856
97857
97858
97859

97860
97861
97862
97863
97864
97865
97866
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;
  u16 selFlags = p->selFlags;

  p->selFlags |= SF_Expanded;
  if( db->mallocFailed  ){
    return WRC_Abort;
  }
  if( NEVER(p->pSrc==0) || (selFlags & SF_Expanded)!=0 ){
    return WRC_Prune;
  }

  pTabList = p->pSrc;
  pEList = p->pEList;

  /* Make sure cursor numbers have been assigned to all entries in
  ** the FROM clause of the SELECT statement.
  */
  sqlite3SrcListAssignCursors(pParse, pTabList);
97615
97616
97617
97618
97619
97620
97621






97622
97623
97624
97625
97626
97627
97628
      pTab->tabFlags |= TF_Ephemeral;
#endif
    }else{
      /* An ordinary table or view name in the FROM clause */
      assert( pFrom->pTab==0 );
      pFrom->pTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom);
      if( pTab==0 ) return WRC_Abort;






      pTab->nRef++;
#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
      if( pTab->pSelect || IsVirtual(pTab) ){
        /* We reach here if the named table is a really a view */
        if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
        assert( pFrom->pSelect==0 );
        pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0);







>
>
>
>
>
>







97895
97896
97897
97898
97899
97900
97901
97902
97903
97904
97905
97906
97907
97908
97909
97910
97911
97912
97913
97914
      pTab->tabFlags |= TF_Ephemeral;
#endif
    }else{
      /* An ordinary table or view name in the FROM clause */
      assert( pFrom->pTab==0 );
      pFrom->pTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom);
      if( pTab==0 ) return WRC_Abort;
      if( pTab->nRef==0xffff ){
        sqlite3ErrorMsg(pParse, "too many references to \"%s\": max 65535",
           pTab->zName);
        pFrom->pTab = 0;
        return WRC_Abort;
      }
      pTab->nRef++;
#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
      if( pTab->pSelect || IsVirtual(pTab) ){
        /* We reach here if the named table is a really a view */
        if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
        assert( pFrom->pSelect==0 );
        pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0);
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
97695
97696
97697
97698
97699
97700
97701
97702

97703


97704
97705
97706
97707


97708
97709
97710
97711


97712
97713
97714
97715
97716
97717







97718
97719
97720
97721
97722
97723
97724
97725
97726

97727
97728
97729
97730
97731
97732
97733
  ** 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++){
    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;








    for(k=0; k<pEList->nExpr; k++){
      Expr *pE = a[k].pExpr;

      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;            /* 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;

          char *zTabName = pFrom->zAlias;


          if( zTabName==0 ){
            zTabName = pTab->zName;
          }
          if( db->mallocFailed ) break;


          if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
            continue;
          }
          tableSeen = 1;


          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 */








            /* 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;
            }


            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 */







|

















>
>
>
>
>
>
>

|
>
|
|














|




<
<



>

>
>




>
>
|
|
|
|
>
>

<




>
>
>
>
>
>
>









>







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
97965
97966
97967
97968
97969
97970
97971
97972
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
98014
98015
98016
98017
98018
98019
98020
98021
98022
98023
98024
98025
98026
98027
98028
98029
98030
98031
98032
98033
98034
98035
98036
98037
98038
98039
  ** 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;
    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;
      pRight = pE->pRight;
      assert( pE->op!=TK_DOT || pRight!=0 );
      if( pE->op!=TK_ALL && (pE->op!=TK_DOT || 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 */
        if( pE->op==TK_DOT ){
          assert( pE->pLeft!=0 );
          assert( !ExprHasProperty(pE->pLeft, EP_IntValue) );
          zTName = pE->pLeft->u.zToken;


        }
        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);
            zSchemaName = iDb>=0 ? db->aDb[iDb].zName : "*";
          }
          for(j=0; j<pTab->nCol; j++){

            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 */
97742
97743
97744
97745
97746
97747
97748




97749
97750
97751
97752
97753
97754
97755
97756
97757
97758
97759












97760
97761
97762
97763
97764
97765
97766
            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( 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);












            sqlite3DbFree(db, zToFree);
          }
        }
        if( !tableSeen ){
          if( zTName ){
            sqlite3ErrorMsg(pParse, "no such table: %s", zTName);
          }else{







>
>
>
>











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







98048
98049
98050
98051
98052
98053
98054
98055
98056
98057
98058
98059
98060
98061
98062
98063
98064
98065
98066
98067
98068
98069
98070
98071
98072
98073
98074
98075
98076
98077
98078
98079
98080
98081
98082
98083
98084
98085
98086
98087
98088
            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{
97891
97892
97893
97894
97895
97896
97897

97898
97899
97900
97901
97902
97903
97904
  Parse *pParse,         /* The parser context */
  Select *p,             /* The SELECT statement being coded. */
  NameContext *pOuterNC  /* Name context for container */
){
  sqlite3 *db;
  if( NEVER(p==0) ) return;
  db = pParse->db;

  if( p->selFlags & SF_HasTypeInfo ) return;
  sqlite3SelectExpand(pParse, p);
  if( pParse->nErr || db->mallocFailed ) return;
  sqlite3ResolveSelectNames(pParse, p, pOuterNC);
  if( pParse->nErr || db->mallocFailed ) return;
  sqlite3SelectAddTypeInfo(pParse, p);
}







>







98213
98214
98215
98216
98217
98218
98219
98220
98221
98222
98223
98224
98225
98226
98227
  Parse *pParse,         /* The parser context */
  Select *p,             /* The SELECT statement being coded. */
  NameContext *pOuterNC  /* Name context for container */
){
  sqlite3 *db;
  if( NEVER(p==0) ) return;
  db = pParse->db;
  if( db->mallocFailed ) return;
  if( p->selFlags & SF_HasTypeInfo ) return;
  sqlite3SelectExpand(pParse, p);
  if( pParse->nErr || db->mallocFailed ) return;
  sqlite3ResolveSelectNames(pParse, p, pOuterNC);
  if( pParse->nErr || db->mallocFailed ) return;
  sqlite3SelectAddTypeInfo(pParse, p);
}
98810
98811
98812
98813
98814
98815
98816





98817



98818
98819
98820
98821
98822
98823
98824
98825
98826
98827
98828
        **
        **   + 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 = minMaxQuery(p);



        if( flag ){
          assert( !ExprHasProperty(p->pEList->a[0].pExpr, EP_xIsSelect) );
          assert( p->pEList->a[0].pExpr->x.pList->nExpr==1 );
          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;
          }
        }
  







>
>
>
>
>
|
>
>
>

<
<
|







99133
99134
99135
99136
99137
99138
99139
99140
99141
99142
99143
99144
99145
99146
99147
99148
99149


99150
99151
99152
99153
99154
99155
99156
99157
        **
        **   + 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);
        }
        assert( flag==0 || (pMinMax!=0 && pMinMax->nExpr==1) );

        if( flag ){


          pMinMax = sqlite3ExprListDup(db, pMinMax, 0);
          pDel = pMinMax;
          if( pMinMax && !db->mallocFailed ){
            pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0;
            pMinMax->a[0].pExpr->op = TK_COLUMN;
          }
        }
  
98970
98971
98972
98973
98974
98975
98976
98977



98978
98979
98980
98981
98982
98983
98984
  }
}
SQLITE_PRIVATE void sqlite3ExplainSelect(Vdbe *pVdbe, Select *p){
  if( p==0 ){
    sqlite3ExplainPrintf(pVdbe, "(null-select)");
    return;
  }
  while( p->pPrior ) p = p->pPrior;



  sqlite3ExplainPush(pVdbe);
  while( p ){
    explainOneSelect(pVdbe, p);
    p = p->pNext;
    if( p==0 ) break;
    sqlite3ExplainNL(pVdbe);
    sqlite3ExplainPrintf(pVdbe, "%s\n", selectOpName(p->op));







|
>
>
>







99299
99300
99301
99302
99303
99304
99305
99306
99307
99308
99309
99310
99311
99312
99313
99314
99315
99316
  }
}
SQLITE_PRIVATE void sqlite3ExplainSelect(Vdbe *pVdbe, Select *p){
  if( p==0 ){
    sqlite3ExplainPrintf(pVdbe, "(null-select)");
    return;
  }
  while( p->pPrior ){
    p->pPrior->pNext = p;
    p = p->pPrior;
  }
  sqlite3ExplainPush(pVdbe);
  while( p ){
    explainOneSelect(pVdbe, p);
    p = p->pNext;
    if( p==0 ) break;
    sqlite3ExplainNL(pVdbe);
    sqlite3ExplainPrintf(pVdbe, "%s\n", selectOpName(p->op));
102547
102548
102549
102550
102551
102552
102553
102554
102555
102556
102557
102558
102559
102560
102561
102562
typedef struct WhereTerm WhereTerm;
struct WhereTerm {
  Expr *pExpr;            /* Pointer to the subexpression that is this term */
  int iParent;            /* Disable pWC->a[iParent] when this term disabled */
  int leftCursor;         /* Cursor number of X in "X <op> <expr>" */
  union {
    int leftColumn;         /* Column number of X in "X <op> <expr>" */
    WhereOrInfo *pOrInfo;   /* Extra information if eOperator==WO_OR */
    WhereAndInfo *pAndInfo; /* Extra information if eOperator==WO_AND */
  } u;
  u16 eOperator;          /* A WO_xx value describing <op> */
  u8 wtFlags;             /* TERM_xxx bit flags.  See below */
  u8 nChild;              /* Number of children that must disable us */
  WhereClause *pWC;       /* The clause this term is part of */
  Bitmask prereqRight;    /* Bitmask of tables used by pExpr->pRight */
  Bitmask prereqAll;      /* Bitmask of tables referenced by pExpr */







|
|







102879
102880
102881
102882
102883
102884
102885
102886
102887
102888
102889
102890
102891
102892
102893
102894
typedef struct WhereTerm WhereTerm;
struct WhereTerm {
  Expr *pExpr;            /* Pointer to the subexpression that is this term */
  int iParent;            /* Disable pWC->a[iParent] when this term disabled */
  int leftCursor;         /* Cursor number of X in "X <op> <expr>" */
  union {
    int leftColumn;         /* Column number of X in "X <op> <expr>" */
    WhereOrInfo *pOrInfo;   /* Extra information if (eOperator & WO_OR)!=0 */
    WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
  } u;
  u16 eOperator;          /* A WO_xx value describing <op> */
  u8 wtFlags;             /* TERM_xxx bit flags.  See below */
  u8 nChild;              /* Number of children that must disable us */
  WhereClause *pWC;       /* The clause this term is part of */
  Bitmask prereqRight;    /* Bitmask of tables used by pExpr->pRight */
  Bitmask prereqAll;      /* Bitmask of tables referenced by pExpr */
102589
102590
102591
102592
102593
102594
102595
102596
102597
102598
102599
102600
102601
102602
102603
** There are separate WhereClause objects for the whole clause and for
** the subclauses "(b AND c)" and "(d AND e)".  The pOuter field of the
** subclauses points to the WhereClause object for the whole clause.
*/
struct WhereClause {
  Parse *pParse;           /* The parser context */
  WhereMaskSet *pMaskSet;  /* Mapping of table cursor numbers to bitmasks */
  Bitmask vmask;           /* Bitmask identifying virtual table cursors */
  WhereClause *pOuter;     /* Outer conjunction */
  u8 op;                   /* Split operator.  TK_AND or TK_OR */
  u16 wctrlFlags;          /* Might include WHERE_AND_ONLY */
  int nTerm;               /* Number of terms */
  int nSlot;               /* Number of entries in a[] */
  WhereTerm *a;            /* Each a[] describes a term of the WHERE cluase */
#if defined(SQLITE_SMALL_STACK)







<







102921
102922
102923
102924
102925
102926
102927

102928
102929
102930
102931
102932
102933
102934
** There are separate WhereClause objects for the whole clause and for
** the subclauses "(b AND c)" and "(d AND e)".  The pOuter field of the
** subclauses points to the WhereClause object for the whole clause.
*/
struct WhereClause {
  Parse *pParse;           /* The parser context */
  WhereMaskSet *pMaskSet;  /* Mapping of table cursor numbers to bitmasks */

  WhereClause *pOuter;     /* Outer conjunction */
  u8 op;                   /* Split operator.  TK_AND or TK_OR */
  u16 wctrlFlags;          /* Might include WHERE_AND_ONLY */
  int nTerm;               /* Number of terms */
  int nSlot;               /* Number of entries in a[] */
  WhereTerm *a;            /* Each a[] describes a term of the WHERE cluase */
#if defined(SQLITE_SMALL_STACK)
102676
102677
102678
102679
102680
102681
102682

102683
102684
102685
102686
102687
102688
102689
#define WO_LE     (WO_EQ<<(TK_LE-TK_EQ))
#define WO_GT     (WO_EQ<<(TK_GT-TK_EQ))
#define WO_GE     (WO_EQ<<(TK_GE-TK_EQ))
#define WO_MATCH  0x040
#define WO_ISNULL 0x080
#define WO_OR     0x100       /* Two or more OR-connected terms */
#define WO_AND    0x200       /* Two or more AND-connected terms */

#define WO_NOOP   0x800       /* This term does not restrict search space */

#define WO_ALL    0xfff       /* Mask of all possible WO_* values */
#define WO_SINGLE 0x0ff       /* Mask of all non-compound WO_* values */

/*
** Value for wsFlags returned by bestIndex() and stored in







>







103007
103008
103009
103010
103011
103012
103013
103014
103015
103016
103017
103018
103019
103020
103021
#define WO_LE     (WO_EQ<<(TK_LE-TK_EQ))
#define WO_GT     (WO_EQ<<(TK_GT-TK_EQ))
#define WO_GE     (WO_EQ<<(TK_GE-TK_EQ))
#define WO_MATCH  0x040
#define WO_ISNULL 0x080
#define WO_OR     0x100       /* Two or more OR-connected terms */
#define WO_AND    0x200       /* Two or more AND-connected terms */
#define WO_EQUIV  0x400       /* Of the form A==B, both columns */
#define WO_NOOP   0x800       /* This term does not restrict search space */

#define WO_ALL    0xfff       /* Mask of all possible WO_* values */
#define WO_SINGLE 0x0ff       /* Mask of all non-compound WO_* values */

/*
** Value for wsFlags returned by bestIndex() and stored in
102702
102703
102704
102705
102706
102707
102708
102709
102710
102711
102712
102713
102714
102715
102716
#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      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 */







|







103034
103035
103036
103037
103038
103039
103040
103041
103042
103043
103044
103045
103046
103047
103048
#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_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 */
102765
102766
102767
102768
102769
102770
102771
102772
102773
102774
102775
102776
102777
102778
102779
){
  pWC->pParse = pParse;
  pWC->pMaskSet = pMaskSet;
  pWC->pOuter = 0;
  pWC->nTerm = 0;
  pWC->nSlot = ArraySize(pWC->aStatic);
  pWC->a = pWC->aStatic;
  pWC->vmask = 0;
  pWC->wctrlFlags = wctrlFlags;
}

/* Forward reference */
static void whereClauseClear(WhereClause*);

/*







<







103097
103098
103099
103100
103101
103102
103103

103104
103105
103106
103107
103108
103109
103110
){
  pWC->pParse = pParse;
  pWC->pMaskSet = pMaskSet;
  pWC->pOuter = 0;
  pWC->nTerm = 0;
  pWC->nSlot = ArraySize(pWC->aStatic);
  pWC->a = pWC->aStatic;

  pWC->wctrlFlags = wctrlFlags;
}

/* Forward reference */
static void whereClauseClear(WhereClause*);

/*
103078
103079
103080
103081
103082
103083
103084


















103085
103086
103087
103088
103089
103090
103091
103092
103093
103094









103095
103096
103097


103098
103099
103100
103101
103102


103103
103104
103105
103106
103107
103108
103109

103110
103111
103112
103113


103114
103115
103116
103117
103118
103119
103120
103121
103122
103123
103124
103125
103126

103127

103128

103129







103130




103131









103132
103133
103134
103135
103136
103137
103138
103139
}

/*
** Search for a term in the WHERE clause that is of the form "X <op> <expr>"
** where X is a reference to the iColumn of table iCur and <op> is one of
** the WO_xx operator codes specified by the op parameter.
** Return a pointer to the term.  Return 0 if not found.


















*/
static WhereTerm *findTerm(
  WhereClause *pWC,     /* The WHERE clause to be searched */
  int iCur,             /* Cursor number of LHS */
  int iColumn,          /* Column number of LHS */
  Bitmask notReady,     /* RHS must not overlap with this mask */
  u32 op,               /* Mask of WO_xx values describing operator */
  Index *pIdx           /* Must be compatible with this index, if not NULL */
){
  WhereTerm *pTerm;









  int k;
  assert( iCur>=0 );
  op &= WO_ALL;


  for(; pWC; pWC=pWC->pOuter){
    for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){
      if( pTerm->leftCursor==iCur
         && (pTerm->prereqRight & notReady)==0
         && pTerm->u.leftColumn==iColumn


         && (pTerm->eOperator & op)!=0
      ){
        if( iColumn>=0 && pIdx && pTerm->eOperator!=WO_ISNULL ){
          Expr *pX = pTerm->pExpr;
          CollSeq *pColl;
          char idxaff;
          int j;

          Parse *pParse = pWC->pParse;
  
          idxaff = pIdx->pTable->aCol[iColumn].affinity;
          if( !sqlite3IndexAffinityOk(pX, idxaff) ) continue;


  
          /* 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;
  
          for(j=0; pIdx->aiColumn[j]!=iColumn; j++){
            if( NEVER(j>=pIdx->nColumn) ) return 0;
          }
          if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue;

        }

        return pTerm;

      }







    }




  }









  return 0;
}

/* Forward reference */
static void exprAnalyze(SrcList*, WhereClause*, int);

/*
** Call exprAnalyze on all terms in a WHERE clause.  







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









|
>
>
>
>
>
>
>
>
>
|

|
>
>
|
|
|
<
|
>
>
|
|
|
<
|
|
|
>
|
<
|
|
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
>
|
>
|
>
>
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
|







103409
103410
103411
103412
103413
103414
103415
103416
103417
103418
103419
103420
103421
103422
103423
103424
103425
103426
103427
103428
103429
103430
103431
103432
103433
103434
103435
103436
103437
103438
103439
103440
103441
103442
103443
103444
103445
103446
103447
103448
103449
103450
103451
103452
103453
103454
103455
103456
103457
103458
103459
103460

103461
103462
103463
103464
103465
103466

103467
103468
103469
103470
103471

103472
103473
103474
103475
103476
103477
103478
103479
103480
103481
103482
103483
103484
103485
103486
103487
103488
103489
103490
103491
103492
103493
103494
103495
103496
103497
103498
103499
103500
103501
103502
103503
103504
103505
103506
103507
103508
103509
103510
103511
103512
103513
103514
103515
103516
103517
103518
103519
103520
103521
103522
103523
103524
}

/*
** Search for a term in the WHERE clause that is of the form "X <op> <expr>"
** where X is a reference to the iColumn of table iCur and <op> is one of
** the WO_xx operator codes specified by the op parameter.
** Return a pointer to the term.  Return 0 if not found.
**
** The term returned might by Y=<expr> if there is another constraint in
** the WHERE clause that specifies that X=Y.  Any such constraints will be
** identified by the WO_EQUIV bit in the pTerm->eOperator field.  The
** aEquiv[] array holds X and all its equivalents, with each SQL variable
** taking up two slots in aEquiv[].  The first slot is for the cursor number
** and the second is for the column number.  There are 22 slots in aEquiv[]
** so that means we can look for X plus up to 10 other equivalent values.
** Hence a search for X will return <expr> if X=A1 and A1=A2 and A2=A3
** and ... and A9=A10 and A10=<expr>.
**
** If there are multiple terms in the WHERE clause of the form "X <op> <expr>"
** then try for the one with no dependencies on <expr> - in other words where
** <expr> is a constant expression of some kind.  Only return entries of
** the form "X <op> Y" where Y is a column in another table if no terms of
** the form "X <op> <const-expr>" exist.  Other than this priority, if there
** are two or more terms that match, then the choice of which term to return
** is arbitrary.
*/
static WhereTerm *findTerm(
  WhereClause *pWC,     /* The WHERE clause to be searched */
  int iCur,             /* Cursor number of LHS */
  int iColumn,          /* Column number of LHS */
  Bitmask notReady,     /* RHS must not overlap with this mask */
  u32 op,               /* Mask of WO_xx values describing operator */
  Index *pIdx           /* Must be compatible with this index, if not NULL */
){
  WhereTerm *pTerm;            /* Term being examined as possible result */
  WhereTerm *pResult = 0;      /* The answer to return */
  WhereClause *pWCOrig = pWC;  /* Original pWC value */
  int j, k;                    /* Loop counters */
  Expr *pX;                /* Pointer to an expression */
  Parse *pParse;           /* Parsing context */
  int iOrigCol = iColumn;  /* Original value of iColumn */
  int nEquiv = 2;          /* Number of entires in aEquiv[] */
  int iEquiv = 2;          /* Number of entries of aEquiv[] processed so far */
  int aEquiv[22];          /* iCur,iColumn and up to 10 other equivalents */

  assert( iCur>=0 );
  aEquiv[0] = iCur;
  aEquiv[1] = iColumn;
  for(;;){
    for(pWC=pWCOrig; pWC; pWC=pWC->pOuter){
      for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){
        if( pTerm->leftCursor==iCur

          && pTerm->u.leftColumn==iColumn
        ){
          if( (pTerm->prereqRight & notReady)==0
           && (pTerm->eOperator & op & WO_ALL)!=0
          ){
            if( iOrigCol>=0 && pIdx && (pTerm->eOperator & WO_ISNULL)==0 ){

              CollSeq *pColl;
              char idxaff;
      
              pX = pTerm->pExpr;
              pParse = pWC->pParse;

              idxaff = pIdx->pTable->aCol[iOrigCol].affinity;
              if( !sqlite3IndexAffinityOk(pX, idxaff) ){
                continue;
              }
      
              /* 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;
      
              for(j=0; pIdx->aiColumn[j]!=iOrigCol; j++){
                if( NEVER(j>=pIdx->nColumn) ) return 0;
              }
              if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ){
                continue;
              }
            }
            pResult = pTerm;
            if( pTerm->prereqRight==0 ) goto findTerm_success;
          }
          if( (pTerm->eOperator & WO_EQUIV)!=0
           && nEquiv<ArraySize(aEquiv)
          ){
            pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight);
            assert( pX->op==TK_COLUMN );
            for(j=0; j<nEquiv; j+=2){
              if( aEquiv[j]==pX->iTable && aEquiv[j+1]==pX->iColumn ) break;
            }
            if( j==nEquiv ){
              aEquiv[j] = pX->iTable;
              aEquiv[j+1] = pX->iColumn;
              nEquiv += 2;
            }
          }
        }
      }
    }
    if( iEquiv>=nEquiv ) break;
    iCur = aEquiv[iEquiv++];
    iColumn = aEquiv[iEquiv++];
  }
findTerm_success:
  return pResult;
}

/* Forward reference */
static void exprAnalyze(SrcList*, WhereClause*, int);

/*
** Call exprAnalyze on all terms in a WHERE clause.  
103311
103312
103313
103314
103315
103316
103317
103318
103319
103320
103321
103322
103323
103324
103325
**     (B)     x=expr1 OR expr2=x OR x=expr3
**     (C)     t1.x=t2.y OR (t1.x=t2.z AND t1.y=15)
**     (D)     x=expr1 OR (y>11 AND y<22 AND z LIKE '*hello*')
**     (E)     (p.a=1 AND q.b=2 AND r.c=3) OR (p.x=4 AND q.y=5 AND r.z=6)
**
** CASE 1:
**
** If all subterms are of the form T.C=expr for some single column of C
** a single table T (as shown in example B above) then create a new virtual
** term that is an equivalent IN expression.  In other words, if the term
** being analyzed is:
**
**      x = expr1  OR  expr2 = x  OR  x = expr3
**
** then create a new virtual term like this:







|







103696
103697
103698
103699
103700
103701
103702
103703
103704
103705
103706
103707
103708
103709
103710
**     (B)     x=expr1 OR expr2=x OR x=expr3
**     (C)     t1.x=t2.y OR (t1.x=t2.z AND t1.y=15)
**     (D)     x=expr1 OR (y>11 AND y<22 AND z LIKE '*hello*')
**     (E)     (p.a=1 AND q.b=2 AND r.c=3) OR (p.x=4 AND q.y=5 AND r.z=6)
**
** CASE 1:
**
** If all subterms are of the form T.C=expr for some single column of C and
** a single table T (as shown in example B above) then create a new virtual
** term that is an equivalent IN expression.  In other words, if the term
** being analyzed is:
**
**      x = expr1  OR  expr2 = x  OR  x = expr3
**
** then create a new virtual term like this:
103399
103400
103401
103402
103403
103404
103405
103406
103407
103408
103409
103410
103411
103412
103413
103414
103415
103416
103417
  if( db->mallocFailed ) return;
  assert( pOrWc->nTerm>=2 );

  /*
  ** Compute the set of tables that might satisfy cases 1 or 2.
  */
  indexable = ~(Bitmask)0;
  chngToIN = ~(pWC->vmask);
  for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0 && indexable; i--, pOrTerm++){
    if( (pOrTerm->eOperator & WO_SINGLE)==0 ){
      WhereAndInfo *pAndInfo;
      assert( pOrTerm->eOperator==0 );
      assert( (pOrTerm->wtFlags & (TERM_ANDINFO|TERM_ORINFO))==0 );
      chngToIN = 0;
      pAndInfo = sqlite3DbMallocRaw(db, sizeof(*pAndInfo));
      if( pAndInfo ){
        WhereClause *pAndWC;
        WhereTerm *pAndTerm;
        int j;







|



<







103784
103785
103786
103787
103788
103789
103790
103791
103792
103793
103794

103795
103796
103797
103798
103799
103800
103801
  if( db->mallocFailed ) return;
  assert( pOrWc->nTerm>=2 );

  /*
  ** Compute the set of tables that might satisfy cases 1 or 2.
  */
  indexable = ~(Bitmask)0;
  chngToIN = ~(Bitmask)0;
  for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0 && indexable; i--, pOrTerm++){
    if( (pOrTerm->eOperator & WO_SINGLE)==0 ){
      WhereAndInfo *pAndInfo;

      assert( (pOrTerm->wtFlags & (TERM_ANDINFO|TERM_ORINFO))==0 );
      chngToIN = 0;
      pAndInfo = sqlite3DbMallocRaw(db, sizeof(*pAndInfo));
      if( pAndInfo ){
        WhereClause *pAndWC;
        WhereTerm *pAndTerm;
        int j;
103442
103443
103444
103445
103446
103447
103448
103449
103450
103451
103452
103453
103454
103455
103456
      Bitmask b;
      b = getMask(pMaskSet, pOrTerm->leftCursor);
      if( pOrTerm->wtFlags & TERM_VIRTUAL ){
        WhereTerm *pOther = &pOrWc->a[pOrTerm->iParent];
        b |= getMask(pMaskSet, pOther->leftCursor);
      }
      indexable &= b;
      if( pOrTerm->eOperator!=WO_EQ ){
        chngToIN = 0;
      }else{
        chngToIN &= b;
      }
    }
  }








|







103826
103827
103828
103829
103830
103831
103832
103833
103834
103835
103836
103837
103838
103839
103840
      Bitmask b;
      b = getMask(pMaskSet, pOrTerm->leftCursor);
      if( pOrTerm->wtFlags & TERM_VIRTUAL ){
        WhereTerm *pOther = &pOrWc->a[pOrTerm->iParent];
        b |= getMask(pMaskSet, pOther->leftCursor);
      }
      indexable &= b;
      if( (pOrTerm->eOperator & WO_EQ)==0 ){
        chngToIN = 0;
      }else{
        chngToIN &= b;
      }
    }
  }

103493
103494
103495
103496
103497
103498
103499
103500
103501
103502
103503
103504
103505
103506
103507
    ** will be recorded in iCursor and iColumn.  There might not be any
    ** such table and column.  Set okToChngToIN if an appropriate table
    ** and column is found but leave okToChngToIN false if not found.
    */
    for(j=0; j<2 && !okToChngToIN; j++){
      pOrTerm = pOrWc->a;
      for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){
        assert( pOrTerm->eOperator==WO_EQ );
        pOrTerm->wtFlags &= ~TERM_OR_OK;
        if( pOrTerm->leftCursor==iCursor ){
          /* This is the 2-bit case and we are on the second iteration and
          ** current term is from the first iteration.  So skip this term. */
          assert( j==1 );
          continue;
        }







|







103877
103878
103879
103880
103881
103882
103883
103884
103885
103886
103887
103888
103889
103890
103891
    ** will be recorded in iCursor and iColumn.  There might not be any
    ** such table and column.  Set okToChngToIN if an appropriate table
    ** and column is found but leave okToChngToIN false if not found.
    */
    for(j=0; j<2 && !okToChngToIN; j++){
      pOrTerm = pOrWc->a;
      for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){
        assert( pOrTerm->eOperator & WO_EQ );
        pOrTerm->wtFlags &= ~TERM_OR_OK;
        if( pOrTerm->leftCursor==iCursor ){
          /* This is the 2-bit case and we are on the second iteration and
          ** current term is from the first iteration.  So skip this term. */
          assert( j==1 );
          continue;
        }
103519
103520
103521
103522
103523
103524
103525
103526
103527
103528
103529
103530
103531
103532
103533
103534
103535
103536
103537
103538
103539
103540
103541
103542
103543
        iCursor = pOrTerm->leftCursor;
        break;
      }
      if( i<0 ){
        /* No candidate table+column was found.  This can only occur
        ** on the second iteration */
        assert( j==1 );
        assert( (chngToIN&(chngToIN-1))==0 );
        assert( chngToIN==getMask(pMaskSet, iCursor) );
        break;
      }
      testcase( j==1 );

      /* We have found a candidate table and column.  Check to see if that
      ** table and column is common to every term in the OR clause */
      okToChngToIN = 1;
      for(; i>=0 && okToChngToIN; i--, pOrTerm++){
        assert( pOrTerm->eOperator==WO_EQ );
        if( pOrTerm->leftCursor!=iCursor ){
          pOrTerm->wtFlags &= ~TERM_OR_OK;
        }else if( pOrTerm->u.leftColumn!=iColumn ){
          okToChngToIN = 0;
        }else{
          int affLeft, affRight;
          /* If the right-hand side is also a column, then the affinities







|









|







103903
103904
103905
103906
103907
103908
103909
103910
103911
103912
103913
103914
103915
103916
103917
103918
103919
103920
103921
103922
103923
103924
103925
103926
103927
        iCursor = pOrTerm->leftCursor;
        break;
      }
      if( i<0 ){
        /* No candidate table+column was found.  This can only occur
        ** on the second iteration */
        assert( j==1 );
        assert( IsPowerOfTwo(chngToIN) );
        assert( chngToIN==getMask(pMaskSet, iCursor) );
        break;
      }
      testcase( j==1 );

      /* We have found a candidate table and column.  Check to see if that
      ** table and column is common to every term in the OR clause */
      okToChngToIN = 1;
      for(; i>=0 && okToChngToIN; i--, pOrTerm++){
        assert( pOrTerm->eOperator & WO_EQ );
        if( pOrTerm->leftCursor!=iCursor ){
          pOrTerm->wtFlags &= ~TERM_OR_OK;
        }else if( pOrTerm->u.leftColumn!=iColumn ){
          okToChngToIN = 0;
        }else{
          int affLeft, affRight;
          /* If the right-hand side is also a column, then the affinities
103565
103566
103567
103568
103569
103570
103571
103572
103573
103574
103575
103576
103577
103578
103579
      Expr *pDup;            /* A transient duplicate expression */
      ExprList *pList = 0;   /* The RHS of the IN operator */
      Expr *pLeft = 0;       /* The LHS of the IN operator */
      Expr *pNew;            /* The complete IN operator */

      for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){
        if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue;
        assert( pOrTerm->eOperator==WO_EQ );
        assert( pOrTerm->leftCursor==iCursor );
        assert( pOrTerm->u.leftColumn==iColumn );
        pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
        pList = sqlite3ExprListAppend(pWC->pParse, pList, pDup);
        pLeft = pOrTerm->pExpr->pLeft;
      }
      assert( pLeft!=0 );







|







103949
103950
103951
103952
103953
103954
103955
103956
103957
103958
103959
103960
103961
103962
103963
      Expr *pDup;            /* A transient duplicate expression */
      ExprList *pList = 0;   /* The RHS of the IN operator */
      Expr *pLeft = 0;       /* The LHS of the IN operator */
      Expr *pNew;            /* The complete IN operator */

      for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){
        if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue;
        assert( pOrTerm->eOperator & WO_EQ );
        assert( pOrTerm->leftCursor==iCursor );
        assert( pOrTerm->u.leftColumn==iColumn );
        pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
        pList = sqlite3ExprListAppend(pWC->pParse, pList, pDup);
        pLeft = pOrTerm->pExpr->pLeft;
      }
      assert( pLeft!=0 );
103594
103595
103596
103597
103598
103599
103600
103601
103602
103603
103604
103605
103606
103607
103608
        sqlite3ExprListDelete(db, pList);
      }
      pTerm->eOperator = WO_NOOP;  /* case 1 trumps case 2 */
    }
  }
}
#endif /* !SQLITE_OMIT_OR_OPTIMIZATION && !SQLITE_OMIT_SUBQUERY */


/*
** The input to this routine is an WhereTerm structure with only the
** "pExpr" field filled in.  The job of this routine is to analyze the
** subexpression and populate all the other fields of the WhereTerm
** structure.
**







<







103978
103979
103980
103981
103982
103983
103984

103985
103986
103987
103988
103989
103990
103991
        sqlite3ExprListDelete(db, pList);
      }
      pTerm->eOperator = WO_NOOP;  /* case 1 trumps case 2 */
    }
  }
}
#endif /* !SQLITE_OMIT_OR_OPTIMIZATION && !SQLITE_OMIT_SUBQUERY */


/*
** The input to this routine is an WhereTerm structure with only the
** "pExpr" field filled in.  The job of this routine is to analyze the
** subexpression and populate all the other fields of the WhereTerm
** structure.
**
103664
103665
103666
103667
103668
103669
103670
103671
103672
103673

103674
103675
103676
103677
103678
103679
103680
103681

103682
103683
103684
103685
103686
103687
103688
103689
103690
103691
103692
103693
103694
103695







103696
103697
103698
103699
103700
103701
103702
103703
103704
103705
103706
103707
103708
103709
103710
103711
103712
103713
103714
    extraRight = x-1;  /* ON clause terms may not be used with an index
                       ** 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);

    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;
      Expr *pDup;

      if( pTerm->leftCursor>=0 ){
        int idxNew;
        pDup = sqlite3ExprDup(db, pExpr, 0);
        if( db->mallocFailed ){
          sqlite3ExprDelete(db, pDup);
          return;
        }
        idxNew = whereClauseInsert(pWC, pDup, TERM_VIRTUAL|TERM_DYNAMIC);
        if( idxNew==0 ) return;
        pNew = &pWC->a[idxNew];
        pNew->iParent = idxTerm;
        pTerm = &pWC->a[idxTerm];
        pTerm->nChild = 1;
        pTerm->wtFlags |= TERM_COPIED;







      }else{
        pDup = pExpr;
        pNew = pTerm;
      }
      exprCommute(pParse, pDup);
      pLeft = sqlite3ExprSkipCollate(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);
    }
  }

#ifndef SQLITE_OMIT_BETWEEN_OPTIMIZATION
  /* If a term is the BETWEEN operator, create two new virtual terms
  ** that define the range that the BETWEEN implements.  For example:
  **







|


>



|




>














>
>
>
>
>
>
>











|







104047
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
104075
104076
104077
104078
104079
104080
104081
104082
104083
104084
104085
104086
104087
104088
104089
104090
104091
104092
104093
104094
104095
104096
104097
104098
104099
104100
104101
104102
104103
104104
104105
104106
    extraRight = x-1;  /* ON clause terms may not be used with an index
                       ** on left table of a LEFT JOIN.  Ticket #3015 */
  }
  pTerm->prereqAll = prereqAll;
  pTerm->leftCursor = -1;
  pTerm->iParent = -1;
  pTerm->eOperator = 0;
  if( allowedOp(op) ){
    Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft);
    Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight);
    u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV;
    if( pLeft->op==TK_COLUMN ){
      pTerm->leftCursor = pLeft->iTable;
      pTerm->u.leftColumn = pLeft->iColumn;
      pTerm->eOperator = operatorMask(op) & opMask;
    }
    if( pRight && pRight->op==TK_COLUMN ){
      WhereTerm *pNew;
      Expr *pDup;
      u16 eExtraOp = 0;        /* Extra bits for pNew->eOperator */
      if( pTerm->leftCursor>=0 ){
        int idxNew;
        pDup = sqlite3ExprDup(db, pExpr, 0);
        if( db->mallocFailed ){
          sqlite3ExprDelete(db, pDup);
          return;
        }
        idxNew = whereClauseInsert(pWC, pDup, TERM_VIRTUAL|TERM_DYNAMIC);
        if( idxNew==0 ) return;
        pNew = &pWC->a[idxNew];
        pNew->iParent = idxTerm;
        pTerm = &pWC->a[idxTerm];
        pTerm->nChild = 1;
        pTerm->wtFlags |= TERM_COPIED;
        if( pExpr->op==TK_EQ
         && !ExprHasProperty(pExpr, EP_FromJoin)
         && OptimizationEnabled(db, SQLITE_Transitive)
        ){
          pTerm->eOperator |= WO_EQUIV;
          eExtraOp = WO_EQUIV;
        }
      }else{
        pDup = pExpr;
        pNew = pTerm;
      }
      exprCommute(pParse, pDup);
      pLeft = sqlite3ExprSkipCollate(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) + eExtraOp) & opMask;
    }
  }

#ifndef SQLITE_OMIT_BETWEEN_OPTIMIZATION
  /* If a term is the BETWEEN operator, create two new virtual terms
  ** that define the range that the BETWEEN implements.  For example:
  **
104159
104160
104161
104162
104163
104164
104165
104166
104167
104168
104169
104170
104171
104172
104173
104174
104175
104176
104177
104178
104179
104180
104181
104182
104183
104184
104185
104186
104187
104188
104189
104190
104191
104192
104193
104194
  }
  if( pWC->wctrlFlags & WHERE_AND_ONLY ){
    return;
  }

  /* Search the WHERE clause terms for a usable WO_OR term. */
  for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
    if( pTerm->eOperator==WO_OR 
     && ((pTerm->prereqAll & ~maskSrc) & p->notReady)==0
     && (pTerm->u.pOrInfo->indexable & maskSrc)!=0 
    ){
      WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc;
      WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
      WhereTerm *pOrTerm;
      int flags = WHERE_MULTI_OR;
      double rTotal = 0;
      double nRow = 0;
      Bitmask used = 0;
      WhereBestIdx sBOI;

      sBOI = *p;
      sBOI.pOrderBy = 0;
      sBOI.pDistinct = 0;
      sBOI.ppIdxInfo = 0;
      for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
        WHERETRACE(("... Multi-index OR testing for term %d of %d....\n", 
          (pOrTerm - pOrWC->a), (pTerm - pWC->a)
        ));
        if( pOrTerm->eOperator==WO_AND ){
          sBOI.pWC = &pOrTerm->u.pAndInfo->wc;
          bestIndex(&sBOI);
        }else if( pOrTerm->leftCursor==iCur ){
          WhereClause tempWC;
          tempWC.pParse = pWC->pParse;
          tempWC.pMaskSet = pWC->pMaskSet;
          tempWC.pOuter = pWC;







|




















|







104551
104552
104553
104554
104555
104556
104557
104558
104559
104560
104561
104562
104563
104564
104565
104566
104567
104568
104569
104570
104571
104572
104573
104574
104575
104576
104577
104578
104579
104580
104581
104582
104583
104584
104585
104586
  }
  if( pWC->wctrlFlags & WHERE_AND_ONLY ){
    return;
  }

  /* Search the WHERE clause terms for a usable WO_OR term. */
  for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
    if( (pTerm->eOperator & WO_OR)!=0
     && ((pTerm->prereqAll & ~maskSrc) & p->notReady)==0
     && (pTerm->u.pOrInfo->indexable & maskSrc)!=0 
    ){
      WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc;
      WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
      WhereTerm *pOrTerm;
      int flags = WHERE_MULTI_OR;
      double rTotal = 0;
      double nRow = 0;
      Bitmask used = 0;
      WhereBestIdx sBOI;

      sBOI = *p;
      sBOI.pOrderBy = 0;
      sBOI.pDistinct = 0;
      sBOI.ppIdxInfo = 0;
      for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
        WHERETRACE(("... Multi-index OR testing for term %d of %d....\n", 
          (pOrTerm - pOrWC->a), (pTerm - pWC->a)
        ));
        if( (pOrTerm->eOperator& WO_AND)!=0 ){
          sBOI.pWC = &pOrTerm->u.pAndInfo->wc;
          bestIndex(&sBOI);
        }else if( pOrTerm->leftCursor==iCur ){
          WhereClause tempWC;
          tempWC.pParse = pWC->pParse;
          tempWC.pMaskSet = pWC->pMaskSet;
          tempWC.pOuter = pWC;
104241
104242
104243
104244
104245
104246
104247
104248
104249
104250
104251
104252
104253
104254
104255
static int termCanDriveIndex(
  WhereTerm *pTerm,              /* WHERE clause term to check */
  struct SrcList_item *pSrc,     /* Table we are trying to access */
  Bitmask notReady               /* Tables in outer loops of the join */
){
  char aff;
  if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
  if( pTerm->eOperator!=WO_EQ ) return 0;
  if( (pTerm->prereqRight & notReady)!=0 ) return 0;
  aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity;
  if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0;
  return 1;
}
#endif








|







104633
104634
104635
104636
104637
104638
104639
104640
104641
104642
104643
104644
104645
104646
104647
static int termCanDriveIndex(
  WhereTerm *pTerm,              /* WHERE clause term to check */
  struct SrcList_item *pSrc,     /* Table we are trying to access */
  Bitmask notReady               /* Tables in outer loops of the join */
){
  char aff;
  if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
  if( (pTerm->eOperator & WO_EQ)==0 ) return 0;
  if( (pTerm->prereqRight & notReady)!=0 ) return 0;
  aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity;
  if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0;
  return 1;
}
#endif

104503
104504
104505
104506
104507
104508
104509
104510
104511
104512
104513
104514
104515
104516
104517
104518
104519
104520

  WHERETRACE(("Recomputing index info for %s...\n", pSrc->pTab->zName));

  /* 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_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.







|
|
|
|







104895
104896
104897
104898
104899
104900
104901
104902
104903
104904
104905
104906
104907
104908
104909
104910
104911
104912

  WHERETRACE(("Recomputing index info for %s...\n", pSrc->pTab->zName));

  /* 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( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
    testcase( pTerm->eOperator & WO_IN );
    testcase( pTerm->eOperator & WO_ISNULL );
    if( pTerm->eOperator & (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.
104554
104555
104556
104557
104558
104559
104560

104561
104562
104563
104564
104565
104566
104567
104568


104569
104570
104571
104572
104573
104574
104575
104576
104577
104578
104579
104580
104581
104582
104583
104584
104585
104586
  *(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++){

    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_IN|WO_ISNULL) ) continue;
    if( pTerm->wtFlags & TERM_VNULL ) continue;
    pIdxCons[j].iColumn = pTerm->u.leftColumn;
    pIdxCons[j].iTermOffset = i;


    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_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;
  }







>

|
|
|
|



>
>
|









|







104946
104947
104948
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
  *(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( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
    testcase( pTerm->eOperator & WO_IN );
    testcase( pTerm->eOperator & WO_ISNULL );
    if( pTerm->eOperator & (WO_ISNULL) ) continue;
    if( pTerm->wtFlags & TERM_VNULL ) continue;
    pIdxCons[j].iColumn = pTerm->u.leftColumn;
    pIdxCons[j].iTermOffset = i;
    op = (u8)pTerm->eOperator & WO_ALL;
    if( op==WO_IN ) op = WO_EQ;
    pIdxCons[j].op = op;
    /* 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) );
    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;
  }
104656
104657
104658
104659
104660
104661
104662
104663
104664


104665
104666
104667
104668
104669
104670
104671
  WhereClause *pWC = p->pWC;      /* The WHERE clause */
  struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */
  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;


  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));







|

>
>







105051
105052
105053
105054
105055
105056
105057
105058
105059
105060
105061
105062
105063
105064
105065
105066
105067
105068
  WhereClause *pWC = p->pWC;      /* The WHERE clause */
  struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */
  Table *pTab = pSrc->pTab;
  sqlite3_index_info *pIdxInfo;
  struct sqlite3_index_constraint *pIdxCons;
  struct sqlite3_index_constraint_usage *pUsage;
  WhereTerm *pTerm;
  int i, j, k;
  int nOrderBy;
  int sortOrder;                  /* Sort order for IN clauses */
  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));
104692
104693
104694
104695
104696
104697
104698











104699
104700
104701
104702
104703
104704
104705
104706
104707
104708
104709
104710
104711
104712
104713
104714
104715
104716
104717
104718
104719
104720
104721
104722
104723



104724



104725
104726
104727
104728
104729
104730
104731
104732
104733
104734
104735
104736
104737
104738
104739
104740
104741
104742
104743
104744

104745
104746
104747


104748







104749




104750
104751






104752
104753
104754
104755
104756
104757
104758
  /* 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) );












  /* 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];



    pIdxCons->usable = (pTerm->prereqRight&p->notReady) ? 0 : 1;



  }
  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 ){


      p->cost.used |= pWC->a[pIdxCons[i].iTermOffset].prereqRight;







    }




  }







  /* 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;







>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
|
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
|
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
|
|
>
>
>
>
>
>







105089
105090
105091
105092
105093
105094
105095
105096
105097
105098
105099
105100
105101
105102
105103
105104
105105
105106
105107
105108
105109
105110
105111
105112
105113
105114
105115
105116
105117
105118
105119
105120
105121
105122
105123
105124
105125
105126
105127
105128
105129
105130
105131
105132
105133
105134
105135
105136
105137
105138
105139
105140
105141
105142
105143
105144
105145
105146
105147
105148
105149
105150
105151
105152
105153
105154
105155
105156
105157
105158
105159
105160
105161
105162
105163
105164
105165
105166
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
  /* 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];
      if( (pTerm->prereqRight&p->notReady)==0
       && (bAllowIN || (pTerm->eOperator & WO_IN)==0)
      ){
        pIdxCons->usable = 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;
    }
  
    sortOrder = SQLITE_SO_ASC;
    pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
    for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
      if( pUsage[i].argvIndex>0 ){
        j = pIdxCons->iTermOffset;
        pTerm = &pWC->a[j];
        p->cost.used |= pTerm->prereqRight;
        if( (pTerm->eOperator & WO_IN)!=0 ){
          if( 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;
          }
          for(k=0; k<pIdxInfo->nOrderBy; k++){
            if( pIdxInfo->aOrderBy[k].iColumn==pIdxCons->iColumn ){
              sortOrder = pIdxInfo->aOrderBy[k].desc;
              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;
104768
104769
104770
104771
104772
104773
104774

104775
104776
104777
104778
104779
104780
104781
104782
  if( (SQLITE_BIG_DBL/((double)2))<rCost ){
    p->cost.rCost = (SQLITE_BIG_DBL/((double)2));
  }else{
    p->cost.rCost = rCost;
  }
  p->cost.plan.u.pVtabIdx = pIdxInfo;
  if( pIdxInfo->orderByConsumed ){

    p->cost.plan.wsFlags |= WHERE_ORDERED;
    p->cost.plan.nOBSat = nOrderBy;
  }else{
    p->cost.plan.nOBSat = p->i ? p->aLevel[p->i-1].plan.nOBSat : 0;
  }
  p->cost.plan.nEq = 0;
  pIdxInfo->nOrderBy = nOrderBy;








>
|







105202
105203
105204
105205
105206
105207
105208
105209
105210
105211
105212
105213
105214
105215
105216
105217
  if( (SQLITE_BIG_DBL/((double)2))<rCost ){
    p->cost.rCost = (SQLITE_BIG_DBL/((double)2));
  }else{
    p->cost.rCost = rCost;
  }
  p->cost.plan.u.pVtabIdx = pIdxInfo;
  if( pIdxInfo->orderByConsumed ){
    assert( sortOrder==0 || sortOrder==1 );
    p->cost.plan.wsFlags |= WHERE_ORDERED + sortOrder*WHERE_REVERSE;
    p->cost.plan.nOBSat = nOrderBy;
  }else{
    p->cost.plan.nOBSat = p->i ? p->aLevel[p->i-1].plan.nOBSat : 0;
  }
  p->cost.plan.nEq = 0;
  pIdxInfo->nOrderBy = nOrderBy;

105039
105040
105041
105042
105043
105044
105045
105046
105047
105048
105049
105050
105051
105052
105053
105054
105055
105056
105057
105058
105059
105060
105061
105062
105063
105064
105065
105066
105067
105068
105069
105070
    tRowcnt iUpper = p->aiRowEst[0];
    tRowcnt a[2];
    u8 aff = p->pTable->aCol[p->aiColumn[0]].affinity;

    if( pLower ){
      Expr *pExpr = pLower->pExpr->pRight;
      rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal);
      assert( pLower->eOperator==WO_GT || pLower->eOperator==WO_GE );
      if( rc==SQLITE_OK
       && whereKeyStats(pParse, p, pRangeVal, 0, a)==SQLITE_OK
      ){
        iLower = a[0];
        if( pLower->eOperator==WO_GT ) iLower += a[1];
      }
      sqlite3ValueFree(pRangeVal);
    }
    if( rc==SQLITE_OK && pUpper ){
      Expr *pExpr = pUpper->pExpr->pRight;
      rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal);
      assert( pUpper->eOperator==WO_LT || pUpper->eOperator==WO_LE );
      if( rc==SQLITE_OK
       && whereKeyStats(pParse, p, pRangeVal, 1, a)==SQLITE_OK
      ){
        iUpper = a[0];
        if( pUpper->eOperator==WO_LE ) iUpper += a[1];
      }
      sqlite3ValueFree(pRangeVal);
    }
    if( rc==SQLITE_OK ){
      if( iUpper<=iLower ){
        *pRangeDiv = (double)p->aiRowEst[0];
      }else{







|




|






|




|







105474
105475
105476
105477
105478
105479
105480
105481
105482
105483
105484
105485
105486
105487
105488
105489
105490
105491
105492
105493
105494
105495
105496
105497
105498
105499
105500
105501
105502
105503
105504
105505
    tRowcnt iUpper = p->aiRowEst[0];
    tRowcnt a[2];
    u8 aff = p->pTable->aCol[p->aiColumn[0]].affinity;

    if( pLower ){
      Expr *pExpr = pLower->pExpr->pRight;
      rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal);
      assert( (pLower->eOperator & (WO_GT|WO_GE))!=0 );
      if( rc==SQLITE_OK
       && whereKeyStats(pParse, p, pRangeVal, 0, a)==SQLITE_OK
      ){
        iLower = a[0];
        if( (pLower->eOperator & WO_GT)!=0 ) iLower += a[1];
      }
      sqlite3ValueFree(pRangeVal);
    }
    if( rc==SQLITE_OK && pUpper ){
      Expr *pExpr = pUpper->pExpr->pRight;
      rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal);
      assert( (pUpper->eOperator & (WO_LT|WO_LE))!=0 );
      if( rc==SQLITE_OK
       && whereKeyStats(pParse, p, pRangeVal, 1, a)==SQLITE_OK
      ){
        iUpper = a[0];
        if( (pUpper->eOperator & WO_LE)!=0 ) iUpper += a[1];
      }
      sqlite3ValueFree(pRangeVal);
    }
    if( rc==SQLITE_OK ){
      if( iUpper<=iLower ){
        *pRangeDiv = (double)p->aiRowEst[0];
      }else{
105364
105365
105366
105367
105368
105369
105370
105371
105372
105373
105374
105375
105376
105377
105378
105379
105380
105381
105382
105383

    /* If X is the column in the index and ORDER BY clause, check to see
    ** if there are any X= or X IS NULL constraints in the WHERE clause. */
    pConstraint = findTerm(p->pWC, base, iColumn, p->notReady,
                           WO_EQ|WO_ISNULL|WO_IN, pIdx);
    if( pConstraint==0 ){
      isEq = 0;
    }else if( pConstraint->eOperator==WO_IN ){
      /* Constraints of the form: "X IN ..." cannot be used with an ORDER BY
      ** because we do not know in what order the values on the RHS of the IN
      ** operator will occur. */
      break;
    }else if( pConstraint->eOperator==WO_ISNULL ){
      uniqueNotNull = 0;
      isEq = 1;  /* "X IS NULL" means X has only a single value */
    }else if( pConstraint->prereqRight==0 ){
      isEq = 1;  /* Constraint "X=constant" means X has only a single value */
    }else{
      Expr *pRight = pConstraint->pExpr->pRight;
      if( pRight->op==TK_COLUMN ){







|
|
<
<
<
|







105799
105800
105801
105802
105803
105804
105805
105806
105807



105808
105809
105810
105811
105812
105813
105814
105815

    /* If X is the column in the index and ORDER BY clause, check to see
    ** if there are any X= or X IS NULL constraints in the WHERE clause. */
    pConstraint = findTerm(p->pWC, base, iColumn, p->notReady,
                           WO_EQ|WO_ISNULL|WO_IN, pIdx);
    if( pConstraint==0 ){
      isEq = 0;
    }else if( (pConstraint->eOperator & WO_IN)!=0 ){
      isEq = 0;



    }else if( (pConstraint->eOperator & WO_ISNULL)!=0 ){
      uniqueNotNull = 0;
      isEq = 1;  /* "X IS NULL" means X has only a single value */
    }else if( pConstraint->prereqRight==0 ){
      isEq = 1;  /* Constraint "X=constant" means X has only a single value */
    }else{
      Expr *pRight = pConstraint->pExpr->pRight;
      if( pRight->op==TK_COLUMN ){
105672
105673
105674
105675
105676
105677
105678
105679
105680
105681
105682
105683
105684
105685
105686
105687
 
    /* If the index being considered is UNIQUE, and there is an equality 
    ** constraint for all columns in the index, then this search will find
    ** at most a single row. In this case set the WHERE_UNIQUE flag to 
    ** indicate this to the caller.
    **
    ** Otherwise, if the search may find more than one row, test to see if
    ** there is a range constraint on indexed column (pc.plan.nEq+1) that can be 
    ** optimized using the index. 
    */
    if( pc.plan.nEq==pProbe->nColumn && pProbe->onError!=OE_None ){
      testcase( pc.plan.wsFlags & WHERE_COLUMN_IN );
      testcase( pc.plan.wsFlags & WHERE_COLUMN_NULL );
      if( (pc.plan.wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_NULL))==0 ){
        pc.plan.wsFlags |= WHERE_UNIQUE;
        if( p->i==0 || (p->aLevel[p->i-1].plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){







|
|







106104
106105
106106
106107
106108
106109
106110
106111
106112
106113
106114
106115
106116
106117
106118
106119
 
    /* If the index being considered is UNIQUE, and there is an equality 
    ** constraint for all columns in the index, then this search will find
    ** at most a single row. In this case set the WHERE_UNIQUE flag to 
    ** indicate this to the caller.
    **
    ** Otherwise, if the search may find more than one row, test to see if
    ** there is a range constraint on indexed column (pc.plan.nEq+1) that
    ** can be optimized using the index. 
    */
    if( pc.plan.nEq==pProbe->nColumn && pProbe->onError!=OE_None ){
      testcase( pc.plan.wsFlags & WHERE_COLUMN_IN );
      testcase( pc.plan.wsFlags & WHERE_COLUMN_NULL );
      if( (pc.plan.wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_NULL))==0 ){
        pc.plan.wsFlags |= WHERE_UNIQUE;
        if( p->i==0 || (p->aLevel[p->i-1].plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
105719
105720
105721
105722
105723
105724
105725
105726
105727
105728
105729
105730
105731
105732
105733
    ** 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_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;







|







106151
106152
106153
106154
106155
106156
106157
106158
106159
106160
106161
106162
106163
106164
106165
    ** 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 ){
        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;
105782
105783
105784
105785
105786
105787
105788
105789
105790

105791
105792
105793
105794
105795
105796
105797
105798
105799
105800
105801
    ** to get a better estimate on the number of rows based on
    ** VALUE and how common that value is according to the histogram.
    */
    if( pc.plan.nRow>(double)1 && pc.plan.nEq==1
     && pFirstTerm!=0 && aiRowEst[1]>1 ){
      assert( (pFirstTerm->eOperator & (WO_EQ|WO_ISNULL|WO_IN))!=0 );
      if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){
        testcase( pFirstTerm->eOperator==WO_EQ );
        testcase( pFirstTerm->eOperator==WO_ISNULL );

        whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight,
                          &pc.plan.nRow);
      }else if( bInEst==0 ){
        assert( pFirstTerm->eOperator==WO_IN );
        whereInScanEst(pParse, pProbe, pFirstTerm->pExpr->x.pList,
                       &pc.plan.nRow);
      }
    }
#endif /* SQLITE_ENABLE_STAT3 */

    /* Adjust the number of output rows and downward to reflect rows







|
|
>



|







106214
106215
106216
106217
106218
106219
106220
106221
106222
106223
106224
106225
106226
106227
106228
106229
106230
106231
106232
106233
106234
    ** to get a better estimate on the number of rows based on
    ** VALUE and how common that value is according to the histogram.
    */
    if( pc.plan.nRow>(double)1 && pc.plan.nEq==1
     && pFirstTerm!=0 && aiRowEst[1]>1 ){
      assert( (pFirstTerm->eOperator & (WO_EQ|WO_ISNULL|WO_IN))!=0 );
      if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){
        testcase( pFirstTerm->eOperator & WO_EQ );
        testcase( pFirstTerm->eOperator & WO_EQUIV );
        testcase( pFirstTerm->eOperator & WO_ISNULL );
        whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight,
                          &pc.plan.nRow);
      }else if( bInEst==0 ){
        assert( pFirstTerm->eOperator & WO_IN );
        whereInScanEst(pParse, pProbe, pFirstTerm->pExpr->x.pList,
                       &pc.plan.nRow);
      }
    }
#endif /* SQLITE_ENABLE_STAT3 */

    /* Adjust the number of output rows and downward to reflect rows
105934
105935
105936
105937
105938
105939
105940
105941
105942
105943
105944
105945
105946
105947
105948
            ** set size by a factor of 3.  Indexed range constraints reduce
            ** the search space by a larger factor: 4.  We make indexed range
            ** more selective intentionally because of the subjective 
            ** observation that indexed range constraints really are more
            ** selective in practice, on average. */
            pc.plan.nRow /= 3;
          }
        }else if( pTerm->eOperator!=WO_NOOP ){
          /* Any other expression lowers the output row count by half */
          pc.plan.nRow /= 2;
        }
      }
      if( pc.plan.nRow<2 ) pc.plan.nRow = 2;
    }








|







106367
106368
106369
106370
106371
106372
106373
106374
106375
106376
106377
106378
106379
106380
106381
            ** set size by a factor of 3.  Indexed range constraints reduce
            ** the search space by a larger factor: 4.  We make indexed range
            ** more selective intentionally because of the subjective 
            ** observation that indexed range constraints really are more
            ** selective in practice, on average. */
            pc.plan.nRow /= 3;
          }
        }else if( (pTerm->eOperator & WO_NOOP)==0 ){
          /* Any other expression lowers the output row count by half */
          pc.plan.nRow /= 2;
        }
      }
      if( pc.plan.nRow<2 ) pc.plan.nRow = 2;
    }

105986
105987
105988
105989
105990
105991
105992
105993
105994

105995
105996
105997
105998
105999
106000
106001
  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\n",
         p->cost.plan.u.pIdx ? p->cost.plan.u.pIdx->zName : "ipk"));

  
  bestOrClauseIndex(p);
  bestAutomaticIndex(p);
  p->cost.plan.wsFlags |= eqTermMask;
}

/*







|
|
>







106419
106420
106421
106422
106423
106424
106425
106426
106427
106428
106429
106430
106431
106432
106433
106434
106435
  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",
         p->cost.rCost));
  
  bestOrClauseIndex(p);
  bestAutomaticIndex(p);
  p->cost.plan.wsFlags |= eqTermMask;
}

/*
106012
106013
106014
106015
106016
106017
106018

106019
106020
106021
106022
106023
106024
106025
106026
*/
static void bestIndex(WhereBestIdx *p){
#ifndef SQLITE_OMIT_VIRTUALTABLE
  if( IsVirtual(p->pSrc->pTab) ){
    sqlite3_index_info *pIdxInfo = 0;
    p->ppIdxInfo = &pIdxInfo;
    bestVirtualIndex(p);

    if( pIdxInfo->needToFreeIdxStr ){
      sqlite3_free(pIdxInfo->idxStr);
    }
    sqlite3DbFree(p->pParse->db, pIdxInfo);
  }else
#endif
  {
    bestBtreeIndex(p);







>
|







106446
106447
106448
106449
106450
106451
106452
106453
106454
106455
106456
106457
106458
106459
106460
106461
*/
static void bestIndex(WhereBestIdx *p){
#ifndef SQLITE_OMIT_VIRTUALTABLE
  if( IsVirtual(p->pSrc->pTab) ){
    sqlite3_index_info *pIdxInfo = 0;
    p->ppIdxInfo = &pIdxInfo;
    bestVirtualIndex(p);
    assert( pIdxInfo!=0 || p->pParse->db->mallocFailed );
    if( pIdxInfo && pIdxInfo->needToFreeIdxStr ){
      sqlite3_free(pIdxInfo->idxStr);
    }
    sqlite3DbFree(p->pParse->db, pIdxInfo);
  }else
#endif
  {
    bestBtreeIndex(p);
106136
106137
106138
106139
106140
106141
106142

106143
106144
106145
106146
106147
106148
106149
106150
106151
106152
106153
106154
106155
106156
106157
106158
106159
106160
106161
106162
106163
106164
106165

106166
106167
106168
106169
106170
106171
106172
    iReg = iTarget;
    sqlite3VdbeAddOp2(v, OP_Null, 0, iReg);
#ifndef SQLITE_OMIT_SUBQUERY
  }else{
    int eType;
    int iTab;
    struct InLoop *pIn;


    assert( pX->op==TK_IN );
    iReg = iTarget;
    eType = sqlite3FindInIndex(pParse, pX, 0);
    iTab = pX->iTable;
    sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
    assert( pLevel->plan.wsFlags & WHERE_IN_ABLE );
    if( pLevel->u.in.nIn==0 ){
      pLevel->addrNxt = sqlite3VdbeMakeLabel(v);
    }
    pLevel->u.in.nIn++;
    pLevel->u.in.aInLoop =
       sqlite3DbReallocOrFree(pParse->db, pLevel->u.in.aInLoop,
                              sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn);
    pIn = pLevel->u.in.aInLoop;
    if( pIn ){
      pIn += pLevel->u.in.nIn - 1;
      pIn->iCur = iTab;
      if( eType==IN_INDEX_ROWID ){
        pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iReg);
      }else{
        pIn->addrInTop = sqlite3VdbeAddOp3(v, OP_Column, iTab, 0, iReg);
      }

      sqlite3VdbeAddOp1(v, OP_IsNull, iReg);
    }else{
      pLevel->u.in.nIn = 0;
    }
#endif
  }
  disableTerm(pLevel, pTerm);







>





|

















>







106571
106572
106573
106574
106575
106576
106577
106578
106579
106580
106581
106582
106583
106584
106585
106586
106587
106588
106589
106590
106591
106592
106593
106594
106595
106596
106597
106598
106599
106600
106601
106602
106603
106604
106605
106606
106607
106608
106609
    iReg = iTarget;
    sqlite3VdbeAddOp2(v, OP_Null, 0, iReg);
#ifndef SQLITE_OMIT_SUBQUERY
  }else{
    int eType;
    int iTab;
    struct InLoop *pIn;
    u8 bRev = (pLevel->plan.wsFlags & WHERE_REVERSE)!=0;

    assert( pX->op==TK_IN );
    iReg = iTarget;
    eType = sqlite3FindInIndex(pParse, pX, 0);
    iTab = pX->iTable;
    sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
    assert( pLevel->plan.wsFlags & WHERE_IN_ABLE );
    if( pLevel->u.in.nIn==0 ){
      pLevel->addrNxt = sqlite3VdbeMakeLabel(v);
    }
    pLevel->u.in.nIn++;
    pLevel->u.in.aInLoop =
       sqlite3DbReallocOrFree(pParse->db, pLevel->u.in.aInLoop,
                              sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn);
    pIn = pLevel->u.in.aInLoop;
    if( pIn ){
      pIn += pLevel->u.in.nIn - 1;
      pIn->iCur = iTab;
      if( eType==IN_INDEX_ROWID ){
        pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iReg);
      }else{
        pIn->addrInTop = sqlite3VdbeAddOp3(v, OP_Column, iTab, 0, iReg);
      }
      pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next;
      sqlite3VdbeAddOp1(v, OP_IsNull, iReg);
    }else{
      pLevel->u.in.nIn = 0;
    }
#endif
  }
  disableTerm(pLevel, pTerm);
106513
106514
106515
106516
106517
106518
106519

106520
106521
106522
106523
106524
106525
106526
106527
106528

106529
106530
106531

106532




106533

106534
106535
106536
106537
106538
106539
106540
106541
106542
106543
106544
106545
106546
106547
106548

#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 */

    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);

    for(j=1; j<=nConstraint; j++){
      for(k=0; k<nConstraint; k++){
        if( aUsage[k].argvIndex==j ){

          int iTerm = aConstraint[k].iTermOffset;




          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, 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]);
      }







>









>



>
|
>
>
>
>
|
>







|







106950
106951
106952
106953
106954
106955
106956
106957
106958
106959
106960
106961
106962
106963
106964
106965
106966
106967
106968
106969
106970
106971
106972
106973
106974
106975
106976
106977
106978
106979
106980
106981
106982
106983
106984
106985
106986
106987
106988
106989
106990
106991
106992
106993

#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 ){
          int iTarget = iReg+j+1;
          pTerm = &pWC->a[aConstraint[k].iTermOffset];
          if( pTerm->eOperator & WO_IN ){
            codeEqualityTerm(pParse, pTerm, pLevel, iTarget);
            addrNotFound = pLevel->addrNxt;
          }else{
            sqlite3ExprCode(pParse, pTerm->pExpr->pRight, iTarget);
          }
          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,
                      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]);
      }
106561
106562
106563
106564
106565
106566
106567
106568
106569
106570
106571
106572
106573
106574
106575
    **          we reference multiple rows using a "rowid IN (...)"
    **          construct.
    */
    iReleaseReg = sqlite3GetTempReg(pParse);
    pTerm = findTerm(pWC, iCur, -1, notReady, WO_EQ|WO_IN, 0);
    assert( pTerm!=0 );
    assert( pTerm->pExpr!=0 );
    assert( pTerm->leftCursor==iCur );
    assert( omitTable==0 );
    testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
    iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, iReleaseReg);
    addrNxt = pLevel->addrNxt;
    sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt);
    sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, iRowidReg);
    sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);







<







107006
107007
107008
107009
107010
107011
107012

107013
107014
107015
107016
107017
107018
107019
    **          we reference multiple rows using a "rowid IN (...)"
    **          construct.
    */
    iReleaseReg = sqlite3GetTempReg(pParse);
    pTerm = findTerm(pWC, iCur, -1, notReady, WO_EQ|WO_IN, 0);
    assert( pTerm!=0 );
    assert( pTerm->pExpr!=0 );

    assert( omitTable==0 );
    testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
    iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, iReleaseReg);
    addrNxt = pLevel->addrNxt;
    sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt);
    sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, iRowidReg);
    sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
106952
106953
106954
106955
106956
106957
106958
106959
106960
106961
106962
106963
106964
106965
106966
    int iRetInit;                             /* Address of regReturn init */
    int untestedTerms = 0;             /* Some terms not completely tested */
    int ii;                            /* Loop counter */
    Expr *pAndExpr = 0;                /* An ".. AND (...)" expression */
   
    pTerm = pLevel->plan.u.pTerm;
    assert( pTerm!=0 );
    assert( pTerm->eOperator==WO_OR );
    assert( (pTerm->wtFlags & TERM_ORINFO)!=0 );
    pOrWc = &pTerm->u.pOrInfo->wc;
    pLevel->op = OP_Return;
    pLevel->p1 = regReturn;

    /* Set up a new SrcList in pOrTab containing the table being scanned
    ** by this loop in the a[0] slot and all notReady tables in a[1..] slots.







|







107396
107397
107398
107399
107400
107401
107402
107403
107404
107405
107406
107407
107408
107409
107410
    int iRetInit;                             /* Address of regReturn init */
    int untestedTerms = 0;             /* Some terms not completely tested */
    int ii;                            /* Loop counter */
    Expr *pAndExpr = 0;                /* An ".. AND (...)" expression */
   
    pTerm = pLevel->plan.u.pTerm;
    assert( pTerm!=0 );
    assert( pTerm->eOperator & WO_OR );
    assert( (pTerm->wtFlags & TERM_ORINFO)!=0 );
    pOrWc = &pTerm->u.pOrInfo->wc;
    pLevel->op = OP_Return;
    pLevel->p1 = regReturn;

    /* Set up a new SrcList in pOrTab containing the table being scanned
    ** by this loop in the a[0] slot and all notReady tables in a[1..] slots.
107025
107026
107027
107028
107029
107030
107031
107032
107033
107034
107035
107036
107037
107038
107039
      if( pAndExpr ){
        pAndExpr = sqlite3PExpr(pParse, TK_AND, 0, pAndExpr, 0);
      }
    }

    for(ii=0; ii<pOrWc->nTerm; ii++){
      WhereTerm *pOrTerm = &pOrWc->a[ii];
      if( pOrTerm->leftCursor==iCur || pOrTerm->eOperator==WO_AND ){
        WhereInfo *pSubWInfo;          /* Info for single OR-term scan */
        Expr *pOrExpr = pOrTerm->pExpr;
        if( pAndExpr ){
          pAndExpr->pLeft = pOrExpr;
          pOrExpr = pAndExpr;
        }
        /* Loop through table entries that match term pOrTerm. */







|







107469
107470
107471
107472
107473
107474
107475
107476
107477
107478
107479
107480
107481
107482
107483
      if( pAndExpr ){
        pAndExpr = sqlite3PExpr(pParse, TK_AND, 0, pAndExpr, 0);
      }
    }

    for(ii=0; ii<pOrWc->nTerm; ii++){
      WhereTerm *pOrTerm = &pOrWc->a[ii];
      if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
        WhereInfo *pSubWInfo;          /* Info for single OR-term scan */
        Expr *pOrExpr = pOrTerm->pExpr;
        if( pAndExpr ){
          pAndExpr->pLeft = pOrExpr;
          pOrExpr = pAndExpr;
        }
        /* Loop through table entries that match term pOrTerm. */
107403
107404
107405
107406
107407
107408
107409
107410
107411
107412
107413
107414
107415
107416
107417
107418
107419
107420
107421
107422
107423
107424
107425
107426
107427
107428
107429
107430
107431
107432
107433
107434
  ** the bitmask for all FROM clause terms to the left of the N-th term
  ** is (X-1).   An expression from the ON clause of a LEFT JOIN can use
  ** its Expr.iRightJoinTable value to find the bitmask of the right table
  ** of the join.  Subtracting one from the right table bitmask gives a
  ** bitmask for all tables to the left of the join.  Knowing the bitmask
  ** for all tables to the left of a left join is important.  Ticket #3015.
  **
  ** Configure the WhereClause.vmask variable so that bits that correspond
  ** to virtual table cursors are set. This is used to selectively disable 
  ** the OR-to-IN transformation in exprAnalyzeOrTerm(). It is not helpful 
  ** with virtual tables.
  **
  ** Note that bitmasks are created for all pTabList->nSrc tables in
  ** pTabList, not just the first nTabList tables.  nTabList is normally
  ** equal to pTabList->nSrc but might be shortened to 1 if the
  ** WHERE_ONETABLE_ONLY flag is set.
  */
  assert( sWBI.pWC->vmask==0 && pMaskSet->n==0 );
  for(ii=0; ii<pTabList->nSrc; ii++){
    createMask(pMaskSet, pTabList->a[ii].iCursor);
#ifndef SQLITE_OMIT_VIRTUALTABLE
    if( ALWAYS(pTabList->a[ii].pTab) && IsVirtual(pTabList->a[ii].pTab) ){
      sWBI.pWC->vmask |= ((Bitmask)1 << ii);
    }
#endif
  }
#ifndef NDEBUG
  {
    Bitmask toTheLeft = 0;
    for(ii=0; ii<pTabList->nSrc; ii++){
      Bitmask m = getMask(pMaskSet, pTabList->a[ii].iCursor);
      assert( (m-1)==toTheLeft );







<
<
<
<
<





<


<
<
<
<
<







107847
107848
107849
107850
107851
107852
107853





107854
107855
107856
107857
107858

107859
107860





107861
107862
107863
107864
107865
107866
107867
  ** the bitmask for all FROM clause terms to the left of the N-th term
  ** is (X-1).   An expression from the ON clause of a LEFT JOIN can use
  ** its Expr.iRightJoinTable value to find the bitmask of the right table
  ** of the join.  Subtracting one from the right table bitmask gives a
  ** bitmask for all tables to the left of the join.  Knowing the bitmask
  ** for all tables to the left of a left join is important.  Ticket #3015.
  **





  ** Note that bitmasks are created for all pTabList->nSrc tables in
  ** pTabList, not just the first nTabList tables.  nTabList is normally
  ** equal to pTabList->nSrc but might be shortened to 1 if the
  ** WHERE_ONETABLE_ONLY flag is set.
  */

  for(ii=0; ii<pTabList->nSrc; ii++){
    createMask(pMaskSet, pTabList->a[ii].iCursor);





  }
#ifndef NDEBUG
  {
    Bitmask toTheLeft = 0;
    for(ii=0; ii<pTabList->nSrc; ii++){
      Bitmask m = getMask(pMaskSet, pTabList->a[ii].iCursor);
      assert( (m-1)==toTheLeft );
107480
107481
107482
107483
107484
107485
107486

107487
107488
107489
107490
107491
107492
107493
  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 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));








>







107913
107914
107915
107916
107917
107918
107919
107920
107921
107922
107923
107924
107925
107926
107927
  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));

107514
107515
107516
107517
107518
107519
107520
107521
107522
107523
107524
107525
107526
107527
107528
107529
107530
107531
107532
107533
107534
107535
107536
107537
107538
107539






107540
107541
107542
107543
107544
107545
107546
107547
107548






















107549
107550
107551
107552
107553
107554
107555
    ** 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.
    **
    ** 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--){






      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;






















        }
        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 );







|
<
<
|














|
>
>
>
>
>
>

<
<
<
<




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







107948
107949
107950
107951
107952
107953
107954
107955


107956
107957
107958
107959
107960
107961
107962
107963
107964
107965
107966
107967
107968
107969
107970
107971
107972
107973
107974
107975
107976
107977
107978




107979
107980
107981
107982
107983
107984
107985
107986
107987
107988
107989
107990
107991
107992
107993
107994
107995
107996
107997
107998
107999
108000
108001
108002
108003
108004
108005
108006
108007
108008
108009
108010
108011
    ** 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:
    **   
    **   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;

    /* 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++){




        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 );
107571
107572
107573
107574
107575
107576
107577
107578
107579
107580
107581
107582
107583
107584
107585
107586
                  || 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( iFrom<nTabList-1 ){
          /* If two or more tables have nearly the same outer loop cost,
          ** 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));







|
|







108027
108028
108029
108030
108031
108032
108033
108034
108035
108036
108037
108038
108039
108040
108041
108042
                  || 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));
107617
107618
107619
107620
107621
107622
107623
107624




107625
107626
107627
107628




107629
107630
107631
107632
107633
107634
107635
                      "       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;




      }
    }
    assert( bestJ>=0 );
    assert( sWBI.notValid & getMask(pMaskSet, pTabList->a[bestJ].iCursor) );




    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 );







|
>
>
>
>




>
>
>
>







108073
108074
108075
108076
108077
108078
108079
108080
108081
108082
108083
108084
108085
108086
108087
108088
108089
108090
108091
108092
108093
108094
108095
108096
108097
108098
108099
                      "       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;
        }

        /* 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 );
107873
107874
107875
107876
107877
107878
107879
107880
107881
107882
107883
107884
107885
107886
107887
    }
    if( pLevel->plan.wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){
      struct InLoop *pIn;
      int j;
      sqlite3VdbeResolveLabel(v, pLevel->addrNxt);
      for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){
        sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
        sqlite3VdbeAddOp2(v, OP_Next, pIn->iCur, pIn->addrInTop);
        sqlite3VdbeJumpHere(v, pIn->addrInTop-1);
      }
      sqlite3DbFree(db, pLevel->u.in.aInLoop);
    }
    sqlite3VdbeResolveLabel(v, pLevel->addrBrk);
    if( pLevel->iLeftJoin ){
      int addr;







|







108337
108338
108339
108340
108341
108342
108343
108344
108345
108346
108347
108348
108349
108350
108351
    }
    if( pLevel->plan.wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){
      struct InLoop *pIn;
      int j;
      sqlite3VdbeResolveLabel(v, pLevel->addrNxt);
      for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){
        sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
        sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
        sqlite3VdbeJumpHere(v, pIn->addrInTop-1);
      }
      sqlite3DbFree(db, pLevel->u.in.aInLoop);
    }
    sqlite3VdbeResolveLabel(v, pLevel->addrBrk);
    if( pLevel->iLeftJoin ){
      int addr;
108181
108182
108183
108184
108185
108186
108187

108188
108189
108190
108191
108192
108193
108194
  sqlite3ParserTOKENTYPE yy0;
  struct LimitVal yy64;
  Expr* yy122;
  Select* yy159;
  IdList* yy180;
  struct {int value; int mask;} yy207;
  u8 yy258;

  struct LikeOp yy318;
  TriggerStep* yy327;
  ExprSpan yy342;
  SrcList* yy347;
  int yy392;
  struct TrigEvent yy410;
  ExprList* yy442;







>







108645
108646
108647
108648
108649
108650
108651
108652
108653
108654
108655
108656
108657
108658
108659
  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;
110131
110132
110133
110134
110135
110136
110137
110138
110139
110140
110141
110142
110143
110144
110145
110146
110147
110148
110149
110150
110151
110152
110153
110154
110155
110156
      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);







<
<









<







110596
110597
110598
110599
110600
110601
110602


110603
110604
110605
110606
110607
110608
110609
110610
110611

110612
110613
110614
110615
110616
110617
110618
      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 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 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);
110382
110383
110384
110385
110386
110387
110388
110389
110390







110391
110392
110393
110394
110395
110396
110397
}
        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.yy392,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset);
}







        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);







|

>
>
>
>
>
>
>







110844
110845
110846
110847
110848
110849
110850
110851
110852
110853
110854
110855
110856
110857
110858
110859
110860
110861
110862
110863
110864
110865
110866
}
        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);
}
        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);
110453
110454
110455
110456
110457
110458
110459










110460
110461
110462
110463
110464
110465
110466
110467
110468
110469
110470
    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{
      Select *pSubquery;
      sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy347);
      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;}







>
>
>
>
>
>
>
>
>
>



|







110922
110923
110924
110925
110926
110927
110928
110929
110930
110931
110932
110933
110934
110935
110936
110937
110938
110939
110940
110941
110942
110943
110944
110945
110946
110947
110948
110949
    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);
      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;}
110689
110690
110691
110692
110693
110694
110695
110696
110697
110698
110699
110700
110701
110702
110703
      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.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);







|







111168
111169
111170
111171
111172
111173
111174
111175
111176
111177
111178
111179
111180
111181
111182
      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 ){
    yygotominor.yy342.pExpr->flags |= EP_Distinct;
  }
}
        break;
      case 197: /* expr ::= ID LP STAR RP */
{
  yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0);
136336
136337
136338
136339
136340
136341
136342
136343

136344
136345
136346
136347
136348
136349
136350
136351
136352
136353
136354
136355


136356
136357
136358
136359
136360
136361
136362



136363
136364
136365
136366
136367
136368
136369
** 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 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{
    zSql = sqlite3_mprintf(
        "SELECT length(data) FROM '%q'.'%q_node' WHERE nodeno = 1",
        pRtree->zDb, pRtree->zName
    );
    rc = getIntFromStmt(db, zSql, &pRtree->iNodeSize);



  }

  sqlite3_free(zSql);
  return rc;
}

/* 







|
>












>
>







>
>
>







136815
136816
136817
136818
136819
136820
136821
136822
136823
136824
136825
136826
136827
136828
136829
136830
136831
136832
136833
136834
136835
136836
136837
136838
136839
136840
136841
136842
136843
136844
136845
136846
136847
136848
136849
136850
136851
136852
136853
136854
** 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 */
  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;
}

/* 
136419
136420
136421
136422
136423
136424
136425
136426
136427
136428
136429
136430
136431
136432
136433
  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);

  /* 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)) ){







|







136904
136905
136906
136907
136908
136909
136910
136911
136912
136913
136914
136915
136916
136917
136918
  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);

  /* 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)) ){
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
** 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.15.1"
#define SQLITE_VERSION_NUMBER 3007015
#define SQLITE_SOURCE_ID      "2012-12-19 20:39:10 6b85b767d0ff7975146156a99ad673f2c1a23318"

/*
** 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







|
|
|







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-02-15 04:21:01 843e1c543aabab8cd62f28742d5818887d36bcb7"

/*
** 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
480
481
482
483
484
485
486









487
488
489
490
491
492
493
#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))
#define SQLITE_READONLY_CANTLOCK       (SQLITE_READONLY | (2<<8))
#define SQLITE_ABORT_ROLLBACK          (SQLITE_ABORT | (2<<8))










/*
** CAPI3REF: Flags For File Open Operations
**
** These bit values are intended for use in the
** 3rd parameter to the [sqlite3_open_v2()] interface and
** in the 4th parameter to the [sqlite3_vfs.xOpen] method.







>
>
>
>
>
>
>
>
>







480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
#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))
#define SQLITE_READONLY_CANTLOCK       (SQLITE_READONLY | (2<<8))
#define SQLITE_ABORT_ROLLBACK          (SQLITE_ABORT | (2<<8))
#define SQLITE_CONSTRAINT_CHECK        (SQLITE_CONSTRAINT | (1<<8))
#define SQLITE_CONSTRAINT_COMMITHOOK   (SQLITE_CONSTRAINT | (2<<8))
#define SQLITE_CONSTRAINT_FOREIGNKEY   (SQLITE_CONSTRAINT | (3<<8))
#define SQLITE_CONSTRAINT_FUNCTION     (SQLITE_CONSTRAINT | (4<<8))
#define SQLITE_CONSTRAINT_NOTNULL      (SQLITE_CONSTRAINT | (5<<8))
#define SQLITE_CONSTRAINT_PRIMARYKEY   (SQLITE_CONSTRAINT | (6<<8))
#define SQLITE_CONSTRAINT_TRIGGER      (SQLITE_CONSTRAINT | (7<<8))
#define SQLITE_CONSTRAINT_UNIQUE       (SQLITE_CONSTRAINT | (8<<8))
#define SQLITE_CONSTRAINT_VTAB         (SQLITE_CONSTRAINT | (9<<8))

/*
** CAPI3REF: Flags For File Open Operations
**
** These bit values are intended for use in the
** 3rd parameter to the [sqlite3_open_v2()] interface and
** in the 4th parameter to the [sqlite3_vfs.xOpen] method.
Changes to SQLite.Interop/src/core/sqlite3ext.h.
232
233
234
235
236
237
238














239
240
241
242
243
244
245
  int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*);
  int (*wal_autocheckpoint)(sqlite3*,int);
  int (*wal_checkpoint)(sqlite3*,const char*);
  void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*);
  int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
  int (*vtab_config)(sqlite3*,int op,...);
  int (*vtab_on_conflict)(sqlite3*);














};

/*
** The following macros redefine the API routines so that they are
** redirected throught the global sqlite3_api structure.
**
** This header file is also used by the loadext.c source file







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







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
  int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*);
  int (*wal_autocheckpoint)(sqlite3*,int);
  int (*wal_checkpoint)(sqlite3*,const char*);
  void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*);
  int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
  int (*vtab_config)(sqlite3*,int op,...);
  int (*vtab_on_conflict)(sqlite3*);
  /* Version 3.7.16 and later */
  int (*close_v2)(sqlite3*);
  const char *(*db_filename)(sqlite3*,const char*);
  int (*db_readonly)(sqlite3*,const char*);
  int (*db_release_memory)(sqlite3*);
  const char *(*errstr)(int);
  int (*stmt_busy)(sqlite3_stmt*);
  int (*stmt_readonly)(sqlite3_stmt*);
  int (*stricmp)(const char*,const char*);
  int (*uri_boolean)(const char*,const char*,int);
  sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64);
  const char *(*uri_parameter)(const char*,const char*);
  char *(*vsnprintf)(int,char*,const char*,va_list);
  int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
};

/*
** The following macros redefine the API routines so that they are
** redirected throught the global sqlite3_api structure.
**
** This header file is also used by the loadext.c source file
435
436
437
438
439
440
441














442
443
444
445
446
447
#define sqlite3_unlock_notify          sqlite3_api->unlock_notify
#define sqlite3_wal_autocheckpoint     sqlite3_api->wal_autocheckpoint
#define sqlite3_wal_checkpoint         sqlite3_api->wal_checkpoint
#define sqlite3_wal_hook               sqlite3_api->wal_hook
#define sqlite3_blob_reopen            sqlite3_api->blob_reopen
#define sqlite3_vtab_config            sqlite3_api->vtab_config
#define sqlite3_vtab_on_conflict       sqlite3_api->vtab_on_conflict














#endif /* SQLITE_CORE */

#define SQLITE_EXTENSION_INIT1     const sqlite3_api_routines *sqlite3_api = 0;
#define SQLITE_EXTENSION_INIT2(v)  sqlite3_api = v;

#endif /* _SQLITE3EXT_H_ */







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






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
#define sqlite3_unlock_notify          sqlite3_api->unlock_notify
#define sqlite3_wal_autocheckpoint     sqlite3_api->wal_autocheckpoint
#define sqlite3_wal_checkpoint         sqlite3_api->wal_checkpoint
#define sqlite3_wal_hook               sqlite3_api->wal_hook
#define sqlite3_blob_reopen            sqlite3_api->blob_reopen
#define sqlite3_vtab_config            sqlite3_api->vtab_config
#define sqlite3_vtab_on_conflict       sqlite3_api->vtab_on_conflict
/* Version 3.7.16 and later */
#define sqlite3_close_v2               sqlite3_api->close_v2
#define sqlite3_db_filename            sqlite3_api->db_filename
#define sqlite3_db_readonly            sqlite3_api->db_readonly
#define sqlite3_db_release_memory      sqlite3_api->db_release_memory
#define sqlite3_errstr                 sqlite3_api->errstr
#define sqlite3_stmt_busy              sqlite3_api->stmt_busy
#define sqlite3_stmt_readonly          sqlite3_api->stmt_readonly
#define sqlite3_stricmp                sqlite3_api->stricmp
#define sqlite3_uri_boolean            sqlite3_api->uri_boolean
#define sqlite3_uri_int64              sqlite3_api->uri_int64
#define sqlite3_uri_parameter          sqlite3_api->uri_parameter
#define sqlite3_uri_vsnprintf          sqlite3_api->vsnprintf
#define sqlite3_wal_checkpoint_v2      sqlite3_api->wal_checkpoint_v2
#endif /* SQLITE_CORE */

#define SQLITE_EXTENSION_INIT1     const sqlite3_api_routines *sqlite3_api = 0;
#define SQLITE_EXTENSION_INIT2(v)  sqlite3_api = v;

#endif /* _SQLITE3EXT_H_ */
Changes to SQLite.Interop/src/win/AssemblyInfo.cpp.
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("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







|







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: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/crypt.c.
39
40
41
42
43
44
45



46




47
48
49

50
51


52
53
54
55
56
57
58
}

/* Create a cryptographic context.  Use the enhanced provider because it is available on
** most platforms
*/
static BOOL InitializeProvider()
{



  if (g_hProvider) return TRUE;





  if (!CryptAcquireContext(&g_hProvider, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
  {

    return FALSE;
  }


  return TRUE;
}

/* Create or update a cryptographic context for a pager.
** This function will automatically determine if the encryption algorithm requires
** extra padding, and if it does, will create a temp buffer big enough to provide
** space to hold it.







>
>
>
|
>
>
>
>



>


>
>







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
}

/* Create a cryptographic context.  Use the enhanced provider because it is available on
** most platforms
*/
static BOOL InitializeProvider()
{
  MUTEX_LOGIC( sqlite3_mutex *pMaster = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); )
  sqlite3_mutex_enter(pMaster);

  if (g_hProvider)
  {
    sqlite3_mutex_leave(pMaster);
    return TRUE;
  }

  if (!CryptAcquireContext(&g_hProvider, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
  {
    sqlite3_mutex_leave(pMaster);
    return FALSE;
  }

  sqlite3_mutex_leave(pMaster);
  return TRUE;
}

/* Create or update a cryptographic context for a pager.
** This function will automatically determine if the encryption algorithm requires
** extra padding, and if it does, will create a temp buffer big enough to provide
** space to hold it.
224
225
226
227
228
229
230




231
232
233
234
235
236
237
238




239
240
241
242
243
244
245
  if (!pKey || !nKeyLen) return 0;

  if (!InitializeProvider())
  {
    return MAXDWORD;
  }





  if (CryptCreateHash(g_hProvider, CALG_SHA1, 0, 0, &hHash))
  {
    if (CryptHashData(hHash, (LPBYTE)pKey, nKeyLen, 0))
    {
      CryptDeriveKey(g_hProvider, CALG_RC4, hHash, 0, &hKey);
    }
    CryptDestroyHash(hHash);
  }




  return hKey;
}

/* Called by sqlite and sqlite3_key_interop to attach a key to a database. */
int sqlite3CodecAttach(sqlite3 *db, int nDb, const void *pKey, int nKeyLen)
{
  int rc = SQLITE_ERROR;







>
>
>
>
|
|
|
|
|
|
|
|
>
>
>
>







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
263
  if (!pKey || !nKeyLen) return 0;

  if (!InitializeProvider())
  {
    return MAXDWORD;
  }

  {
    MUTEX_LOGIC( sqlite3_mutex *pMaster = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); )
    sqlite3_mutex_enter(pMaster);

    if (CryptCreateHash(g_hProvider, CALG_SHA1, 0, 0, &hHash))
    {
      if (CryptHashData(hHash, (LPBYTE)pKey, nKeyLen, 0))
      {
        CryptDeriveKey(g_hProvider, CALG_RC4, hHash, 0, &hKey);
      }
      CryptDestroyHash(hHash);
    }

    sqlite3_mutex_leave(pMaster);
  }

  return hKey;
}

/* Called by sqlite and sqlite3_key_interop to attach a key to a database. */
int sqlite3CodecAttach(sqlite3 *db, int nDb, const void *pKey, int nKeyLen)
{
  int rc = SQLITE_ERROR;
Changes to SQLite.Interop/src/win/interop.c.
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
SQLITE_PRIVATE int logConfigured = 0;

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

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







|







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

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

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

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

  ret = sqlite3_close_v2(db);








|







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

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

  ret = sqlite3_close_v2(db);

401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
  *plen = (pval != 0) ? wcslen((wchar_t *)pval) * sizeof(wchar_t): 0;
  return pval;
}

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

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

  ret = sqlite3_finalize(stmt);

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

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

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

    if (db != NULL)







|
















|







401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
  *plen = (pval != 0) ? wcslen((wchar_t *)pval) * sizeof(wchar_t): 0;
  return pval;
}

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

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

  ret = sqlite3_finalize(stmt);

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

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

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

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

  return ret;
}

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

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

  ret = sqlite3_reset(stmt);








|







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

  return ret;
}

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

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

  ret = sqlite3_reset(stmt);

773
774
775
776
777
778
779























780
781
782
783
784
785
786
787
788
789
790

791
792
793



794


795
  z = sqlite3_value_text(argv[0]);
  if( z ){
    sqlite3_result_text(context, (char*)z, -1, SQLITE_STATIC);
  }else{
    sqlite3_result_null(context);
  }
}
























/* 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
){

  SQLITE_EXTENSION_INIT2(pApi)
  return sqlite3_create_function(db, "interopTest", -1, SQLITE_ANY, 0,
      interopTestFunc, 0, 0);



}


#endif







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











>

|

>
>
>
|
>
>

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
  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]);
#if SQLITE_OS_WINCE
  Sleep(m);
  sqlite3_result_int(context, WAIT_OBJECT_0);
#else
  sqlite3_result_int(context, SleepEx(m, TRUE));
#endif
}

/* 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,
      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
/*
 * interop.h -
 *
 * Written by Joe Mistachkin.
 * Released to the public domain, use at your own risk!
 */

#ifndef INTEROP_VERSION
#define INTEROP_VERSION       "1.0.83.0"
#endif








|

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.85.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
<?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.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\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" />

  </files>
</package>












|












>


>


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
<?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.85.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.
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
  <!--
      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                        **
  ******************************************************************************
  -->







>




>




>




>







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
  <!--
      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
                     ('$(NetFx20Settings)' == '' Or '$(NetFx20Settings)' != 'false') And
                     Exists('$(SQLiteNetDir)\SQLite.NET.Settings.targets.netFx20')" />

  <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets.netFx35"
          Condition="'$(NetFx35)' != '' And '$(NetFx35)' != 'false' And
                     ('$(NetFx35Settings)' == '' Or '$(NetFx35Settings)' != 'false') And
                     Exists('$(SQLiteNetDir)\SQLite.NET.Settings.targets.netFx35')" />

  <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets.netFx40"
          Condition="'$(NetFx40)' != '' And '$(NetFx40)' != 'false' And
                     ('$(NetFx40Settings)' == '' Or '$(NetFx40Settings)' != 'false') And
                     Exists('$(SQLiteNetDir)\SQLite.NET.Settings.targets.netFx40')" />

  <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets.netFx45"
          Condition="'$(NetFx45)' != '' And '$(NetFx45)' != 'false' And
                     ('$(NetFx45Settings)' == '' Or '$(NetFx45Settings)' != 'false') And
                     Exists('$(SQLiteNetDir)\SQLite.NET.Settings.targets.netFx45')" />

  <!--
  ******************************************************************************
  **                       [Fairly] Generic Properties                        **
  ******************************************************************************
  -->
121
122
123
124
125
126
127








































128
129
130
131
132
133
134
        NOTE: Only use functionality available in the .NET Framework 4.5?  By
              default, this is disabled.  This must be enabled to successfully
              build the project using Visual Studio 2012 and/or the .NET
              Framework 4.5 (if necessary, it will typically be enabled from
              within the project file itself).
    -->
    <NetFx45 Condition="'$(NetFx45)' == ''">false</NetFx45>








































  </PropertyGroup>

  <!--
  ******************************************************************************
  **                            Feature Properties                            **
  ******************************************************************************
  -->







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







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
        NOTE: Only use functionality available in the .NET Framework 4.5?  By
              default, this is disabled.  This must be enabled to successfully
              build the project using Visual Studio 2012 and/or the .NET
              Framework 4.5 (if necessary, it will typically be enabled from
              within the project file itself).
    -->
    <NetFx45 Condition="'$(NetFx45)' == ''">false</NetFx45>

    <!--
        NOTE: Load the version-specific settings for the .NET Framework 2.0?
              By default, this is disabled.  If this is enabled when compiling
              for the .NET Framework 2.0, the version-specific settings file
              "SQLite.NET.Settings.targets.netFx20" will be loaded if it is
              actually present, before any other settings in this file are
              processed.
    -->
    <NetFx20Settings Condition="'$(NetFx20Settings)' == ''">false</NetFx20Settings>

    <!--
        NOTE: Load the version-specific settings for the .NET Framework 3.5?
              By default, this is disabled.  If this is enabled when compiling
              for the .NET Framework 3.5, the version-specific settings file
              "SQLite.NET.Settings.targets.netFx35" will be loaded if it is
              actually present, before any other settings in this file are
              processed.
    -->
    <NetFx35Settings Condition="'$(NetFx35Settings)' == ''">false</NetFx35Settings>

    <!--
        NOTE: Load the version-specific settings for the .NET Framework 4.0?
              By default, this is disabled.  If this is enabled when compiling
              for the .NET Framework 4.0, the version-specific settings file
              "SQLite.NET.Settings.targets.netFx40" will be loaded if it is
              actually present, before any other settings in this file are
              processed.
    -->
    <NetFx40Settings Condition="'$(NetFx40Settings)' == ''">false</NetFx40Settings>

    <!--
        NOTE: Load the version-specific settings for the .NET Framework 4.5?
              By default, this is disabled.  If this is enabled when compiling
              for the .NET Framework 4.5, the version-specific settings file
              "SQLite.NET.Settings.targets.netFx45" will be loaded if it is
              actually present, before any other settings in this file are
              processed.
    -->
    <NetFx45Settings Condition="'$(NetFx45Settings)' == ''">false</NetFx45Settings>
  </PropertyGroup>

  <!--
  ******************************************************************************
  **                            Feature Properties                            **
  ******************************************************************************
  -->
276
277
278
279
280
281
282














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















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







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







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

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

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

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

    <!--
        NOTE: Enable the logging callback in the custom built interop DLL (i.e.
              "SQLite.Interop.dll")?  By default, this is enabled in the Debug
              build configuration.  If this is disabled, the logging callback
              will be unavailable and diagnostic messages may not be seen if
              another native logging callback is not configured.  If this is
              enabled, it must also be enabled via the "INTEROP_LOG=1"
Changes to 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
<?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.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\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\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="install.ps1" target="tools\install.ps1" />
  </files>
</package>













|












>


>




>
>



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.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.85.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
<?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.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\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" />

  </files>
</package>












|












>


>


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
<?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.85.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
<?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.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\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" />

  </files>
</package>












|












>


>


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
<?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.85.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
#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" || 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()







|







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"
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

#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" || 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 -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 -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" || 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)







|










|






|








|







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"
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()
#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: "-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"
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
)

SET TOOLS=%~dp0
SET TOOLS=%TOOLS:~0,-1%

%_VECHO% Tools = '%TOOLS%'

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







|







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 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/verify.lst.
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/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







>







78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
  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
126
127
128
129
130
131
132

133
134
135
136

137
138
139
140
141
142
143
  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/updateFileInfo.tcl
  Setup/verify.eagle
  Setup/verify.lst
  Setup/vsSp.bat

  SQLite.Designer/
  SQLite.Designer/AssemblyInfo.cs
  SQLite.Designer/ChangePasswordDialog.cs
  SQLite.Designer/ChangePasswordDialog.Designer.cs
  SQLite.Designer/ChangePasswordDialog.resx
  SQLite.Designer/ChangeScriptDialog.cs
  SQLite.Designer/ChangeScriptDialog.Designer.cs







>




>







127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
  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.Beta.nuspec
  SQLite.Designer/
  SQLite.Designer/AssemblyInfo.cs
  SQLite.Designer/ChangePasswordDialog.cs
  SQLite.Designer/ChangePasswordDialog.Designer.cs
  SQLite.Designer/ChangePasswordDialog.resx
  SQLite.Designer/ChangeScriptDialog.cs
  SQLite.Designer/ChangeScriptDialog.Designer.cs
243
244
245
246
247
248
249

250
251
252
253
254
255
256
  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.targets
  SQLite.nuspec
  SQLite.x64.nuspec
  SQLite.x86.nuspec
  System.Data.SQLite/
  System.Data.SQLite/AssemblyInfo.cs
  System.Data.SQLite/DataTypes.xml







>







246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
  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
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/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/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-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-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







>









>











>
>








>







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
  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
//      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.83.0")]
[assembly: AssemblyFileVersion("1.0.83.0")]







|
|
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.85.0")]
[assembly: AssemblyFileVersion("1.0.85.0")]
Changes to System.Data.SQLite/AssemblyInfo.cs.
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.83.0")]
#if !PLATFORM_COMPACTFRAMEWORK
[assembly: AssemblyFileVersion("1.0.83.0")]
#endif







|

|

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.85.0")]
#if !PLATFORM_COMPACTFRAMEWORK
[assembly: AssemblyFileVersion("1.0.85.0")]
#endif
Changes to System.Data.SQLite/LINQ/SQLiteFactory_Linq.cs.
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36


37
38
39
40
41
42
43

    static SQLiteFactory()
    {
#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";







<
<
|





>
>







22
23
24
25
26
27
28


29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

    static SQLiteFactory()
    {
#if (SQLITE_STANDARD || USE_INTEROP_DLL || PLATFORM_COMPACTFRAMEWORK) && PRELOAD_NATIVE_LIBRARY
        UnsafeNativeMethods.Initialize();
#endif



#if INTEROP_LOG
        if (UnsafeNativeMethods.sqlite3_config_log_interop() == SQLiteErrorCode.Ok)
        {
            UnsafeNativeMethods.sqlite3_log(
                SQLiteErrorCode.Ok, SQLiteConvert.ToUTF8("logging initialized."));
        }
#else
        SQLiteLog.Initialize();
#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
    internal const string PublicKey =
        "002400000480000094000000060200000024000052534131000400000100010005a288de5687c4e1" +
        "b621ddff5d844727418956997f475eb829429e411aff3e93f97b70de698b972640925bdd44280df0" +
        "a25a843266973704137cbb0e7441c1fe7cae4e2440ae91ab8cde3933febcb1ac48dd33b40e13c421" +
        "d8215c18a4349a436dd499e3c385cc683015f886f6c10bd90115eb2bd61b67750839e3a19941dc9c";

#if !PLATFORM_COMPACTFRAMEWORK
    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;







|







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.85.0";
#endif

    /// <summary>
    /// The opaque pointer returned to us by the sqlite provider
    /// </summary>
    protected internal SQLiteConnectionHandle _sql;
    protected string _fileName;
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
              "{0}.", baseSchemaName), String.Empty);
        }
      }

      SQLiteConnectionFlags flags =
          (cnn != null) ? cnn.Flags : SQLiteConnectionFlags.Default;

#if !PLATFORM_COMPACTFRAMEWORK
      if ((flags & SQLiteConnectionFlags.LogPrepare) == SQLiteConnectionFlags.LogPrepare)
      {
          if ((strSql == null) || (strSql.Length == 0) || (strSql.Trim().Length == 0))
              SQLiteLog.LogMessage("Preparing {<nothing>}...");
          else
              SQLiteLog.LogMessage(String.Format(
                  CultureInfo.CurrentCulture, "Preparing {{{0}}}...", strSql));
      }
#endif

      IntPtr stmt = IntPtr.Zero;
      IntPtr ptr = IntPtr.Zero;
      int len = 0;
      SQLiteErrorCode n = SQLiteErrorCode.Schema;
      int retries = 0;
      byte[] b = ToUTF8(strSql);







<








<







514
515
516
517
518
519
520

521
522
523
524
525
526
527
528

529
530
531
532
533
534
535
              "{0}.", baseSchemaName), String.Empty);
        }
      }

      SQLiteConnectionFlags flags =
          (cnn != null) ? cnn.Flags : SQLiteConnectionFlags.Default;


      if ((flags & SQLiteConnectionFlags.LogPrepare) == SQLiteConnectionFlags.LogPrepare)
      {
          if ((strSql == null) || (strSql.Length == 0) || (strSql.Trim().Length == 0))
              SQLiteLog.LogMessage("Preparing {<nothing>}...");
          else
              SQLiteLog.LogMessage(String.Format(
                  CultureInfo.CurrentCulture, "Preparing {{{0}}}...", strSql));
      }


      IntPtr stmt = IntPtr.Zero;
      IntPtr ptr = IntPtr.Zero;
      int len = 0;
      SQLiteErrorCode n = SQLiteErrorCode.Schema;
      int retries = 0;
      byte[] b = ToUTF8(strSql);
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
      }
      finally
      {
        handle.Free();
      }
    }

#if !PLATFORM_COMPACTFRAMEWORK
    protected static void LogBind(SQLiteStatementHandle handle, int index)
    {
        IntPtr handleIntPtr = handle;

        SQLiteLog.LogMessage(String.Format(
            "Binding statement {0} paramter #{1} as NULL...",
            handleIntPtr, index));







<







647
648
649
650
651
652
653

654
655
656
657
658
659
660
      }
      finally
      {
        handle.Free();
      }
    }


    protected static void LogBind(SQLiteStatementHandle handle, int index)
    {
        IntPtr handleIntPtr = handle;

        SQLiteLog.LogMessage(String.Format(
            "Binding statement {0} paramter #{1} as NULL...",
            handleIntPtr, index));
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
    {
        IntPtr handleIntPtr = handle;

        SQLiteLog.LogMessage(String.Format(
            "Binding statement {0} paramter #{1} as type {2} with value {{{3}}}...",
            handleIntPtr, index, typeof(Byte[]), (value != null) ? ToHexadecimalString(value) : "<null>"));
    }
#endif

    internal override void Bind_Double(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, double value)
    {
        SQLiteStatementHandle handle = stmt._sqlite_stmt;

#if !PLATFORM_COMPACTFRAMEWORK
        if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
        {
            LogBind(handle, index, value);
        }


        SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_bind_double(handle, index, value);
#else
        SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_bind_double_interop(handle, index, ref value);
#endif
        if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError());
    }

    internal override void Bind_Int32(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, int value)
    {
        SQLiteStatementHandle handle = stmt._sqlite_stmt;

#if !PLATFORM_COMPACTFRAMEWORK
        if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
        {
            LogBind(handle, index, value);
        }
#endif

        SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_bind_int(handle, index, value);
        if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError());
    }

    internal override void Bind_UInt32(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, uint value)
    {
        SQLiteStatementHandle handle = stmt._sqlite_stmt;

#if !PLATFORM_COMPACTFRAMEWORK
        if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
        {
            LogBind(handle, index, value);
        }
#endif















        SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_bind_uint(handle, index, value);

        if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError());
    }

    internal override void Bind_Int64(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, long value)
    {
        SQLiteStatementHandle handle = stmt._sqlite_stmt;








<





<





>











<




<
















>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>







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
    {
        IntPtr handleIntPtr = handle;

        SQLiteLog.LogMessage(String.Format(
            "Binding statement {0} paramter #{1} as type {2} with value {{{3}}}...",
            handleIntPtr, index, typeof(Byte[]), (value != null) ? ToHexadecimalString(value) : "<null>"));
    }


    internal override void Bind_Double(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, double value)
    {
        SQLiteStatementHandle handle = stmt._sqlite_stmt;


        if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
        {
            LogBind(handle, index, value);
        }

#if !PLATFORM_COMPACTFRAMEWORK
        SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_bind_double(handle, index, value);
#else
        SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_bind_double_interop(handle, index, ref value);
#endif
        if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError());
    }

    internal override void Bind_Int32(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, int value)
    {
        SQLiteStatementHandle handle = stmt._sqlite_stmt;


        if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
        {
            LogBind(handle, index, value);
        }


        SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_bind_int(handle, index, value);
        if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError());
    }

    internal override void Bind_UInt32(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, uint value)
    {
        SQLiteStatementHandle handle = stmt._sqlite_stmt;

#if !PLATFORM_COMPACTFRAMEWORK
        if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
        {
            LogBind(handle, index, value);
        }
#endif

        SQLiteErrorCode n;

        if ((flags & SQLiteConnectionFlags.BindUInt32AsInt64) == SQLiteConnectionFlags.BindUInt32AsInt64)
        {
            long value2 = value;

#if !PLATFORM_COMPACTFRAMEWORK
            n = UnsafeNativeMethods.sqlite3_bind_int64(handle, index, value2);
#else
            n = UnsafeNativeMethods.sqlite3_bind_int64_interop(handle, index, ref value2);
#endif
        }
        else
        {
            n = UnsafeNativeMethods.sqlite3_bind_uint(handle, index, value);
        }
        if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError());
    }

    internal override void Bind_Int64(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, long value)
    {
        SQLiteStatementHandle handle = stmt._sqlite_stmt;

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
    }

    internal override int Bind_ParamCount(SQLiteStatement stmt, SQLiteConnectionFlags flags)
    {
        SQLiteStatementHandle handle = stmt._sqlite_stmt;
        int value = UnsafeNativeMethods.sqlite3_bind_parameter_count(handle);

#if !PLATFORM_COMPACTFRAMEWORK
        if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
        {
            IntPtr handleIntPtr = handle;

            SQLiteLog.LogMessage(String.Format(
                "Statement {0} paramter count is {1}.",
                handleIntPtr, value));
        }
#endif

        return value;
    }

    internal override string Bind_ParamName(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index)
    {
        SQLiteStatementHandle handle = stmt._sqlite_stmt;
        string name;

#if !SQLITE_STANDARD
        int len;
        name = UTF8ToString(UnsafeNativeMethods.sqlite3_bind_parameter_name_interop(handle, index, out len), len);
#else
        name = UTF8ToString(UnsafeNativeMethods.sqlite3_bind_parameter_name(handle, index), -1);
#endif

#if !PLATFORM_COMPACTFRAMEWORK
        if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
        {
            IntPtr handleIntPtr = handle;

            SQLiteLog.LogMessage(String.Format(
                "Statement {0} paramter #{1} name is {{{2}}}.",
                handleIntPtr, index, name));
        }
#endif

        return name;
    }

    internal override int Bind_ParamIndex(SQLiteStatement stmt, SQLiteConnectionFlags flags, string paramName)
    {
        SQLiteStatementHandle handle = stmt._sqlite_stmt;
        int index = UnsafeNativeMethods.sqlite3_bind_parameter_index(handle, ToUTF8(paramName));

#if !PLATFORM_COMPACTFRAMEWORK
        if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
        {
            IntPtr handleIntPtr = handle;

            SQLiteLog.LogMessage(String.Format(
                "Statement {0} paramter index of name {{{1}}} is #{2}.",
                handleIntPtr, paramName, index));
        }
#endif

        return index;
    }

    internal override int ColumnCount(SQLiteStatement stmt)
    {
      return UnsafeNativeMethods.sqlite3_column_count(stmt._sqlite_stmt);







<








<
















<








<









<








<







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
    }

    internal override int Bind_ParamCount(SQLiteStatement stmt, SQLiteConnectionFlags flags)
    {
        SQLiteStatementHandle handle = stmt._sqlite_stmt;
        int value = UnsafeNativeMethods.sqlite3_bind_parameter_count(handle);


        if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
        {
            IntPtr handleIntPtr = handle;

            SQLiteLog.LogMessage(String.Format(
                "Statement {0} paramter count is {1}.",
                handleIntPtr, value));
        }


        return value;
    }

    internal override string Bind_ParamName(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index)
    {
        SQLiteStatementHandle handle = stmt._sqlite_stmt;
        string name;

#if !SQLITE_STANDARD
        int len;
        name = UTF8ToString(UnsafeNativeMethods.sqlite3_bind_parameter_name_interop(handle, index, out len), len);
#else
        name = UTF8ToString(UnsafeNativeMethods.sqlite3_bind_parameter_name(handle, index), -1);
#endif


        if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
        {
            IntPtr handleIntPtr = handle;

            SQLiteLog.LogMessage(String.Format(
                "Statement {0} paramter #{1} name is {{{2}}}.",
                handleIntPtr, index, name));
        }


        return name;
    }

    internal override int Bind_ParamIndex(SQLiteStatement stmt, SQLiteConnectionFlags flags, string paramName)
    {
        SQLiteStatementHandle handle = stmt._sqlite_stmt;
        int index = UnsafeNativeMethods.sqlite3_bind_parameter_index(handle, ToUTF8(paramName));


        if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind)
        {
            IntPtr handleIntPtr = handle;

            SQLiteLog.LogMessage(String.Format(
                "Statement {0} paramter index of name {{{1}}} is #{2}.",
                handleIntPtr, paramName, index));
        }


        return index;
    }

    internal override int ColumnCount(SQLiteStatement stmt)
    {
      return UnsafeNativeMethods.sqlite3_column_count(stmt._sqlite_stmt);
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
#if !PLATFORM_COMPACTFRAMEWORK
      value = UnsafeNativeMethods.sqlite3_column_double(stmt._sqlite_stmt, index);
#else
      UnsafeNativeMethods.sqlite3_column_double_interop(stmt._sqlite_stmt, index, out value);
#endif
      return value;
    }





















    internal override int GetInt32(SQLiteStatement stmt, int index)
    {
      return UnsafeNativeMethods.sqlite3_column_int(stmt._sqlite_stmt, index);
    }






    internal override long GetInt64(SQLiteStatement stmt, int index)
    {
      long value;
#if !PLATFORM_COMPACTFRAMEWORK
      value = UnsafeNativeMethods.sqlite3_column_int64(stmt._sqlite_stmt, index);
#else
      UnsafeNativeMethods.sqlite3_column_int64_interop(stmt._sqlite_stmt, index, out value);
#endif
      return value;
    }






    internal override string GetText(SQLiteStatement stmt, int index)
    {
#if !SQLITE_STANDARD
      int len;
      return UTF8ToString(UnsafeNativeMethods.sqlite3_column_text_interop(stmt._sqlite_stmt, index, out len), len);
#else







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





>
>
>
>
>











>
>
>
>
>







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
#if !PLATFORM_COMPACTFRAMEWORK
      value = UnsafeNativeMethods.sqlite3_column_double(stmt._sqlite_stmt, index);
#else
      UnsafeNativeMethods.sqlite3_column_double_interop(stmt._sqlite_stmt, index, out value);
#endif
      return value;
    }

    internal override sbyte GetSByte(SQLiteStatement stmt, int index)
    {
      return unchecked((sbyte)(GetInt32(stmt, index) & byte.MaxValue));
    }

    internal override byte GetByte(SQLiteStatement stmt, int index)
    {
      return unchecked((byte)(GetInt32(stmt, index) & byte.MaxValue));
    }

    internal override short GetInt16(SQLiteStatement stmt, int index)
    {
      return unchecked((short)(GetInt32(stmt, index) & ushort.MaxValue));
    }

    internal override ushort GetUInt16(SQLiteStatement stmt, int index)
    {
      return unchecked((ushort)(GetInt32(stmt, index) & ushort.MaxValue));
    }

    internal override int GetInt32(SQLiteStatement stmt, int index)
    {
      return UnsafeNativeMethods.sqlite3_column_int(stmt._sqlite_stmt, index);
    }

    internal override uint GetUInt32(SQLiteStatement stmt, int index)
    {
      return unchecked((uint)GetInt32(stmt, index));
    }

    internal override long GetInt64(SQLiteStatement stmt, int index)
    {
      long value;
#if !PLATFORM_COMPACTFRAMEWORK
      value = UnsafeNativeMethods.sqlite3_column_int64(stmt._sqlite_stmt, index);
#else
      UnsafeNativeMethods.sqlite3_column_int64_interop(stmt._sqlite_stmt, index, out value);
#endif
      return value;
    }

    internal override ulong GetUInt64(SQLiteStatement stmt, int index)
    {
      return unchecked((ulong)GetInt64(stmt, index));
    }

    internal override string GetText(SQLiteStatement stmt, int index)
    {
#if !SQLITE_STANDARD
      int len;
      return UTF8ToString(UnsafeNativeMethods.sqlite3_column_text_interop(stmt._sqlite_stmt, index, out len), len);
#else
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
    {
        //
        // BUGFIX: Prevent races with other threads for this entire block, due
        //         to the try/finally semantics.  See ticket [72905c9a77].
        //
        lock (syncRoot)
        {
#if !PLATFORM_COMPACTFRAMEWORK
            //
            // NOTE: Save the state of the logging class and then restore it
            //       after we are done to avoid logging too many false errors.
            //
            bool savedEnabled = SQLiteLog.Enabled;
            SQLiteLog.Enabled = false;

            try
            {
#endif
                //
                // NOTE: This method [ab]uses the fact that SQLite will always
                //       return SQLITE_ERROR for any unknown configuration option
                //       *unless* the SQLite library has already been initialized.
                //       In that case it will always return SQLITE_MISUSE.
                //
                SQLiteErrorCode rc = UnsafeNativeMethods.sqlite3_config_none(
                    SQLiteConfigOpsEnum.SQLITE_CONFIG_NONE);

                return (rc == SQLiteErrorCode.Misuse);
#if !PLATFORM_COMPACTFRAMEWORK
            }
            finally
            {
                SQLiteLog.Enabled = savedEnabled;
            }
#endif
        }
    }

    /// <summary>
    /// Helper function to retrieve a column of data from an active statement.
    /// </summary>
    /// <param name="stmt">The statement being step()'d through</param>







<









<










<





<







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
    {
        //
        // BUGFIX: Prevent races with other threads for this entire block, due
        //         to the try/finally semantics.  See ticket [72905c9a77].
        //
        lock (syncRoot)
        {

            //
            // NOTE: Save the state of the logging class and then restore it
            //       after we are done to avoid logging too many false errors.
            //
            bool savedEnabled = SQLiteLog.Enabled;
            SQLiteLog.Enabled = false;

            try
            {

                //
                // NOTE: This method [ab]uses the fact that SQLite will always
                //       return SQLITE_ERROR for any unknown configuration option
                //       *unless* the SQLite library has already been initialized.
                //       In that case it will always return SQLITE_MISUSE.
                //
                SQLiteErrorCode rc = UnsafeNativeMethods.sqlite3_config_none(
                    SQLiteConfigOpsEnum.SQLITE_CONFIG_NONE);

                return (rc == SQLiteErrorCode.Misuse);

            }
            finally
            {
                SQLiteLog.Enabled = savedEnabled;
            }

        }
    }

    /// <summary>
    /// Helper function to retrieve a column of data from an active statement.
    /// </summary>
    /// <param name="stmt">The statement being step()'d through</param>
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920

1921





1922
1923
1924
1925
1926
1927
1928
1929
            return new Guid(b);

          return b;
        case TypeAffinity.DateTime:
          return GetDateTime(stmt, index);
        case TypeAffinity.Double:
          if (t == null) return GetDouble(stmt, index);
          else
            return Convert.ChangeType(GetDouble(stmt, index), t, null);
        case TypeAffinity.Int64:
          if (t == null) return GetInt64(stmt, index);

          else





            return Convert.ChangeType(GetInt64(stmt, index), t, null);
        default:
          return GetText(stmt, index);
      }
    }

    internal override int GetCursorForTable(SQLiteStatement stmt, int db, int rootPage)
    {







<
|


>
|
>
>
>
>
>
|







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
            return new Guid(b);

          return b;
        case TypeAffinity.DateTime:
          return GetDateTime(stmt, index);
        case TypeAffinity.Double:
          if (t == null) return GetDouble(stmt, index);

          return Convert.ChangeType(GetDouble(stmt, index), t, null);
        case TypeAffinity.Int64:
          if (t == null) return GetInt64(stmt, index);
          if (t == typeof(SByte)) return GetSByte(stmt, index);
          if (t == typeof(Byte)) return GetByte(stmt, index);
          if (t == typeof(Int16)) return GetInt16(stmt, index);
          if (t == typeof(UInt16)) return GetUInt16(stmt, index);
          if (t == typeof(Int32)) return GetInt32(stmt, index);
          if (t == typeof(UInt32)) return GetUInt32(stmt, index);
          if (t == typeof(UInt64)) return GetUInt64(stmt, index);
          return Convert.ChangeType(GetInt64(stmt, index), t, null);
        default:
          return GetText(stmt, index);
      }
    }

    internal override int GetCursorForTable(SQLiteStatement stmt, int db, int rootPage)
    {
Changes to System.Data.SQLite/SQLiteBase.cs.
159
160
161
162
163
164
165




166

167

168
169
170
171
172
173
174
    internal abstract string ColumnOriginalName(SQLiteStatement stmt, int index);
    internal abstract string ColumnDatabaseName(SQLiteStatement stmt, int index);
    internal abstract string ColumnTableName(SQLiteStatement stmt, int index);
    internal abstract void ColumnMetaData(string dataBase, string table, string column, out string dataType, out string collateSequence, out bool notNull, out bool primaryKey, out bool autoIncrement);
    internal abstract void GetIndexColumnExtendedInfo(string database, string index, string column, out int sortMode, out int onError, out string collationSequence);

    internal abstract double GetDouble(SQLiteStatement stmt, int index);




    internal abstract Int32 GetInt32(SQLiteStatement stmt, int index);

    internal abstract Int64 GetInt64(SQLiteStatement stmt, int index);

    internal abstract string GetText(SQLiteStatement stmt, int index);
    internal abstract long GetBytes(SQLiteStatement stmt, int index, int nDataoffset, byte[] bDest, int nStart, int nLength);
    internal abstract long GetChars(SQLiteStatement stmt, int index, int nDataoffset, char[] bDest, int nStart, int nLength);
    internal abstract DateTime GetDateTime(SQLiteStatement stmt, int index);
    internal abstract bool IsNull(SQLiteStatement stmt, int index);

    internal abstract void CreateCollation(string strCollation, SQLiteCollation func, SQLiteCollation func16);







>
>
>
>

>

>







159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
    internal abstract string ColumnOriginalName(SQLiteStatement stmt, int index);
    internal abstract string ColumnDatabaseName(SQLiteStatement stmt, int index);
    internal abstract string ColumnTableName(SQLiteStatement stmt, int index);
    internal abstract void ColumnMetaData(string dataBase, string table, string column, out string dataType, out string collateSequence, out bool notNull, out bool primaryKey, out bool autoIncrement);
    internal abstract void GetIndexColumnExtendedInfo(string database, string index, string column, out int sortMode, out int onError, out string collationSequence);

    internal abstract double GetDouble(SQLiteStatement stmt, int index);
    internal abstract SByte GetSByte(SQLiteStatement stmt, int index);
    internal abstract Byte GetByte(SQLiteStatement stmt, int index);
    internal abstract Int16 GetInt16(SQLiteStatement stmt, int index);
    internal abstract UInt16 GetUInt16(SQLiteStatement stmt, int index);
    internal abstract Int32 GetInt32(SQLiteStatement stmt, int index);
    internal abstract UInt32 GetUInt32(SQLiteStatement stmt, int index);
    internal abstract Int64 GetInt64(SQLiteStatement stmt, int index);
    internal abstract UInt64 GetUInt64(SQLiteStatement stmt, int index);
    internal abstract string GetText(SQLiteStatement stmt, int index);
    internal abstract long GetBytes(SQLiteStatement stmt, int index, int nDataoffset, byte[] bDest, int nStart, int nLength);
    internal abstract long GetChars(SQLiteStatement stmt, int index, int nDataoffset, char[] bDest, int nStart, int nLength);
    internal abstract DateTime GetDateTime(SQLiteStatement stmt, int index);
    internal abstract bool IsNull(SQLiteStatement stmt, int index);

    internal abstract void CreateCollation(string strCollation, SQLiteCollation func, SQLiteCollation func16);
586
587
588
589
590
591
592

593
594
595
596
597
598
599
                SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_close(db);
#endif
                if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError(hdl, db));
            }
        }
    }


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

        try
        {
            // do nothing.







>







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

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

        try
        {
            // do nothing.
613
614
615
616
617
618
619

620
621
622
623
624
625
626

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


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

        bool result = false;








>







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

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

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

        bool result = false;

772
773
774
775
776
777
778














779
780
781
782
783
784
785

      /// <summary>
      /// Skip adding the extension functions provided by the native
      /// interop assembly.
      /// </summary>
      NoExtensionFunctions = 0x20,















      /// <summary>
      /// Enable all logging.
      /// </summary>
      LogAll = LogPrepare | LogPreBind | LogBind |
               LogCallbackException | LogBackup,

      /// <summary>







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







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

      /// <summary>
      /// Skip adding the extension functions provided by the native
      /// interop assembly.
      /// </summary>
      NoExtensionFunctions = 0x20,

      /// <summary>
      /// When binding parameter values with the <see cref="UInt32" />
      /// type, use the interop method that accepts an <see cref="Int64" />
      /// value.
      /// </summary>
      BindUInt32AsInt64 = 0x40,

      /// <summary>
      /// When binding parameter values, always bind them as though they were
      /// plain text (i.e. no numeric, date/time, or other conversions should
      /// be attempted).
      /// </summary>
      BindAllAsText = 0x80,

      /// <summary>
      /// Enable all logging.
      /// </summary>
      LogAll = LogPrepare | LogPreBind | LogBind |
               LogCallbackException | LogBackup,

      /// <summary>
Changes to System.Data.SQLite/SQLiteCommand.cs.
18
19
20
21
22
23
24







25
26
27
28
29
30
31
  /// SQLite implementation of DbCommand.
  /// </summary>
#if !PLATFORM_COMPACTFRAMEWORK
  [Designer("SQLite.Designer.SQLiteCommandDesigner, SQLite.Designer, Version=" + SQLite3.DesignerVersion + ", Culture=neutral, PublicKeyToken=db937bc2d44ff139"), ToolboxItem(true)]
#endif
  public sealed class SQLiteCommand : DbCommand, ICloneable
  {







    /// <summary>
    /// The command text this command is based on
    /// </summary>
    private string _commandText;
    /// <summary>
    /// The connection the command is associated with
    /// </summary>







>
>
>
>
>
>
>







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
  /// SQLite implementation of DbCommand.
  /// </summary>
#if !PLATFORM_COMPACTFRAMEWORK
  [Designer("SQLite.Designer.SQLiteCommandDesigner, SQLite.Designer, Version=" + SQLite3.DesignerVersion + ", Culture=neutral, PublicKeyToken=db937bc2d44ff139"), ToolboxItem(true)]
#endif
  public sealed class SQLiteCommand : DbCommand, ICloneable
  {
    /// <summary>
    /// The default connection string to be used when creating a temporary
    /// connection to execute a command via the static <see cref="Execute" />
    /// method.
    /// </summary>
    private static readonly string DefaultConnectionString = "Data Source=:memory:;";

    /// <summary>
    /// The command text this command is based on
    /// </summary>
    private string _commandText;
    /// <summary>
    /// The connection the command is associated with
    /// </summary>
591
592
593
594
595
596
597



















































































598
599
600
601
602
603
604
    /// </summary>
    /// <param name="behavior">The behavior the data reader should adopt</param>
    /// <returns>Returns a SQLiteDataReader object</returns>
    protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior)
    {
      return ExecuteReader(behavior);
    }




















































































    /// <summary>
    /// Overrides the default behavior to return a SQLiteDataReader specialization class
    /// </summary>
    /// <param name="behavior">The flags to be associated with the reader</param>
    /// <returns>A SQLiteDataReader</returns>
    public new SQLiteDataReader ExecuteReader(CommandBehavior behavior)







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







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
    /// </summary>
    /// <param name="behavior">The behavior the data reader should adopt</param>
    /// <returns>Returns a SQLiteDataReader object</returns>
    protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior)
    {
      return ExecuteReader(behavior);
    }

    /// <summary>
    /// This method creates a new connection, executes the query using the given
    /// execution type, closes the connection, and returns the results.  If the
    /// connection string is null, a temporary in-memory database connection will
    /// be used.
    /// </summary>
    /// <param name="commandText">
    /// The text of the command to be executed.
    /// </param>
    /// <param name="executeType">
    /// The execution type for the command.  This is used to determine which method
    /// of the command object to call, which then determines the type of results
    /// returned, if any.
    /// </param>
    /// <param name="connectionString">
    /// The connection string to the database to be opened, used, and closed.  If
    /// this parameter is null, a temporary in-memory databse will be used.
    /// </param>
    /// <param name="args">
    /// The SQL parameter values to be used when building the command object to be
    /// executed, if any.
    /// </param>
    /// <returns>
    /// The results of the query -OR- null if no results were produced from the
    /// given execution type.
    /// </returns>
    public static object Execute(
        string commandText,
        SQLiteExecuteType executeType,
        string connectionString,
        params object[] args
        )
    {
        if (connectionString == null)
            connectionString = DefaultConnectionString;

        using (SQLiteConnection connection = new SQLiteConnection(connectionString))
        {
            connection.Open();

            using (SQLiteCommand command = connection.CreateCommand())
            {
                command.CommandText = commandText;

                if (args != null)
                {
                    foreach (object arg in args)
                    {
                        if (arg is SQLiteParameter)
                            command.Parameters.Add((SQLiteParameter)arg);
                        else
                            command.Parameters.Add(new SQLiteParameter(DbType.Object, arg));
                    }
                }

                switch (executeType)
                {
                    case SQLiteExecuteType.None:
                        {
                            //
                            // NOTE: Do nothing.
                            //
                            break;
                        }
                    case SQLiteExecuteType.NonQuery:
                        {
                            return command.ExecuteNonQuery();
                        }
                    case SQLiteExecuteType.Scalar:
                        {
                            return command.ExecuteScalar();
                        }
                    case SQLiteExecuteType.Reader:
                        {
                            return command.ExecuteReader();
                        }
                }
            }
        }

        return null;
    }

    /// <summary>
    /// Overrides the default behavior to return a SQLiteDataReader specialization class
    /// </summary>
    /// <param name="behavior">The flags to be associated with the reader</param>
    /// <returns>A SQLiteDataReader</returns>
    public new SQLiteDataReader ExecuteReader(CommandBehavior behavior)
Changes to System.Data.SQLite/SQLiteConnection.cs.
12
13
14
15
16
17
18

19
20
21
22
23
24
25
  using System.Data.Common;
  using System.Diagnostics;
  using System.Collections.Generic;
  using System.Globalization;
  using System.ComponentModel;
  using System.Runtime.InteropServices;
  using System.IO;


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

  /// <summary>
  /// Event data for connection event handlers.
  /// </summary>
  public class ConnectionEventArgs : EventArgs







>







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  using System.Data.Common;
  using System.Diagnostics;
  using System.Collections.Generic;
  using System.Globalization;
  using System.ComponentModel;
  using System.Runtime.InteropServices;
  using System.IO;
  using System.Text;

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

  /// <summary>
  /// Event data for connection event handlers.
  /// </summary>
  public class ConnectionEventArgs : EventArgs
177
178
179
180
181
182
183






184
185
186
187
188
189
190
191


192





193
194
195
196
197
198
199
  /// </item>
  /// <item>
  /// <description>Password</description>
  /// <description>{password} - Using this parameter requires that the CryptoAPI based codec be enabled at compile-time for both the native interop assembly and the core managed assemblies; otherwise, using this parameter may result in an exception being thrown when attempting to open the connection.</description>
  /// <description>N</description>
  /// <description></description>
  /// </item>






  /// <item>
  /// <description>Enlist</description>
  /// <description><b>Y</b> - Automatically enlist in distributed transactions<br/><b>N</b> - No automatic enlistment</description>
  /// <description>N</description>
  /// <description>Y</description>
  /// </item>
  /// <item>
  /// <description>Pooling</description>


  /// <description><b>True</b> - Use connection pooling<br/><b>False</b> - Do not use connection pooling</description>





  /// <description>N</description>
  /// <description>False</description>
  /// </item>
  /// <item>
  /// <description>FailIfMissing</description>
  /// <description><b>True</b> - Don't create the database if it does not exist, throw an error instead<br/><b>False</b> - Automatically create the database if it does not exist</description>
  /// <description>N</description>







>
>
>
>
>
>








>
>
|
>
>
>
>
>







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
  /// </item>
  /// <item>
  /// <description>Password</description>
  /// <description>{password} - Using this parameter requires that the CryptoAPI based codec be enabled at compile-time for both the native interop assembly and the core managed assemblies; otherwise, using this parameter may result in an exception being thrown when attempting to open the connection.</description>
  /// <description>N</description>
  /// <description></description>
  /// </item>
  /// <item>
  /// <description>HexPassword</description>
  /// <description>{hexPassword} - Must contain a sequence of zero or more hexadecimal encoded byte values without a leading "0x" prefix.  Using this parameter requires that the CryptoAPI based codec be enabled at compile-time for both the native interop assembly and the core managed assemblies; otherwise, using this parameter may result in an exception being thrown when attempting to open the connection.</description>
  /// <description>N</description>
  /// <description></description>
  /// </item>
  /// <item>
  /// <description>Enlist</description>
  /// <description><b>Y</b> - Automatically enlist in distributed transactions<br/><b>N</b> - No automatic enlistment</description>
  /// <description>N</description>
  /// <description>Y</description>
  /// </item>
  /// <item>
  /// <description>Pooling</description>
  /// <description>
  /// <b>True</b> - Use connection pooling.<br/>
  /// <b>False</b> - Do not use connection pooling.<br/><br/>
  /// <b>WARNING:</b> When using the default connection pool implementation,
  /// setting this property to True should be avoided by applications that make
  /// use of COM (either directly or indirectly) due to possible deadlocks that
  /// can occur during the finalization of some COM objects.
  /// </description>
  /// <description>N</description>
  /// <description>False</description>
  /// </item>
  /// <item>
  /// <description>FailIfMissing</description>
  /// <description><b>True</b> - Don't create the database if it does not exist, throw an error instead<br/><b>False</b> - Automatically create the database if it does not exist</description>
  /// <description>N</description>
292
293
294
295
296
297
298

299
300
301
302
303
304
305
    private const SQLiteJournalModeEnum DefaultJournalMode = SQLiteJournalModeEnum.Default;
    private const IsolationLevel DefaultIsolationLevel = IsolationLevel.Serializable;
    private const SQLiteDateFormats DefaultDateTimeFormat = SQLiteDateFormats.ISO8601;
    private const DateTimeKind DefaultDateTimeKind = DateTimeKind.Unspecified;
    private const string DefaultDataSource = null;
    private const string DefaultUri = null;
    private const string DefaultFullUri = null;

    private const string DefaultPassword = null;
    private const int DefaultVersion = 3;
    private const int DefaultPageSize = 1024;
    private const int DefaultMaxPageCount = 0;
    private const int DefaultCacheSize = 2000;
    private const int DefaultMaxPoolSize = 100;
    private const int DefaultConnectionTimeout = 30;







>







306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
    private const SQLiteJournalModeEnum DefaultJournalMode = SQLiteJournalModeEnum.Default;
    private const IsolationLevel DefaultIsolationLevel = IsolationLevel.Serializable;
    private const SQLiteDateFormats DefaultDateTimeFormat = SQLiteDateFormats.ISO8601;
    private const DateTimeKind DefaultDateTimeKind = DateTimeKind.Unspecified;
    private const string DefaultDataSource = null;
    private const string DefaultUri = null;
    private const string DefaultFullUri = null;
    private const string DefaultHexPassword = null;
    private const string DefaultPassword = null;
    private const int DefaultVersion = 3;
    private const int DefaultPageSize = 1024;
    private const int DefaultMaxPageCount = 0;
    private const int DefaultCacheSize = 2000;
    private const int DefaultMaxPoolSize = 100;
    private const int DefaultConnectionTimeout = 30;
472
473
474
475
476
477
478
479
480

481
482
483
484
485
486
487
488
489
    /// </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







|

>

|







487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
    /// </param>
    public SQLiteConnection(string connectionString, bool parseViaFramework)
    {
#if (SQLITE_STANDARD || USE_INTEROP_DLL || PLATFORM_COMPACTFRAMEWORK) && PRELOAD_NATIVE_LIBRARY
      UnsafeNativeMethods.Initialize();
#endif

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

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

505
506
507
508
509
510
511
512
              _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








>
|







514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
              _versionNumber = SQLite3.SQLiteVersionNumber;

              if (_versionNumber >= 3007014)
                  SQLiteConnectionHandle.closeConnection = SQLiteBase.CloseConnectionV2;
          }
      }
#endif

#if INTEROP_LOG
      if (UnsafeNativeMethods.sqlite3_config_log_interop() == SQLiteErrorCode.Ok)
      {
          UnsafeNativeMethods.sqlite3_log(
              SQLiteErrorCode.Ok, SQLiteConvert.ToUTF8("logging initialized."));
      }
#endif

620
621
622
623
624
625
626






































627
628
629
630
631
632
633
                _handlers -= value;
            }
        }
    }

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







































    #region Backup API Members
    /// <summary>
    /// Backs up the database, using the specified database connection as the
    /// destination.
    /// </summary>
    /// <param name="destination">The destination database connection.</param>
    /// <param name="destinationName">The destination database name.</param>







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







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
                _handlers -= value;
            }
        }
    }

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

    /// <summary>
    /// This property is used to obtain or set the custom connection pool
    /// implementation to use, if any.  Setting this property to null will
    /// cause the default connection pool implementation to be used.
    /// </summary>
    public static ISQLiteConnectionPool ConnectionPool
    {
        get { return SQLiteConnectionPool.GetConnectionPool(); }
        set { SQLiteConnectionPool.SetConnectionPool(value); }
    }

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

    /// <summary>
    /// Creates and returns a new managed database connection handle.  This
    /// method is intended to be used by implementations of the
    /// <see cref="ISQLiteConnectionPool" /> interface only.  In theory, it
    /// could be used by other classes; however, that usage is not supported.
    /// </summary>
    /// <param name="nativeHandle">
    /// This must be a native database connection handle returned by the
    /// SQLite core library and it must remain valid and open during the
    /// entire duration of the calling method.
    /// </param>
    /// <returns>
    /// The new managed database connection handle or null if it cannot be
    /// created.
    /// </returns>
    public static object CreateHandle(
        IntPtr nativeHandle
        )
    {
        if (nativeHandle == IntPtr.Zero) return null;
        return new SQLiteConnectionHandle(nativeHandle);
    }

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

    #region Backup API Members
    /// <summary>
    /// Backs up the database, using the specified database connection as the
    /// destination.
    /// </summary>
    /// <param name="destination">The destination database connection.</param>
    /// <param name="destinationName">The destination database name.</param>
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
                // NOTE: There is no point in calling the native API to copy
                //       zero pages as it does nothing; therefore, stop now.
                //
                if (pages == 0)
                    break;
            }
        }
#if !PLATFORM_COMPACTFRAMEWORK
        catch (Exception e)
        {
            if ((_flags & SQLiteConnectionFlags.LogBackup) == SQLiteConnectionFlags.LogBackup)
            {
                SQLiteLog.LogMessage(String.Format(
                    CultureInfo.CurrentCulture,
                    "Caught exception while backing up database: {0}", e));
            }

            throw;
        }
#endif
        finally
        {
            if (backup != null)
                sqliteBase.FinishBackup(backup); /* throw */
        }
    }
    #endregion







<











<







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
                // NOTE: There is no point in calling the native API to copy
                //       zero pages as it does nothing; therefore, stop now.
                //
                if (pages == 0)
                    break;
            }
        }

        catch (Exception e)
        {
            if ((_flags & SQLiteConnectionFlags.LogBackup) == SQLiteConnectionFlags.LogBackup)
            {
                SQLiteLog.LogMessage(String.Format(
                    CultureInfo.CurrentCulture,
                    "Caught exception while backing up database: {0}", e));
            }

            throw;
        }

        finally
        {
            if (backup != null)
                sqliteBase.FinishBackup(backup); /* throw */
        }
    }
    #endregion
1141
1142
1143
1144
1145
1146
1147






1148
1149
1150
1151
1152
1153
1154
1155


1156





1157
1158
1159
1160
1161
1162
1163
    /// </item>
    /// <item>
    /// <description>Password</description>
    /// <description>{password} - Using this parameter requires that the CryptoAPI based codec be enabled at compile-time for both the native interop assembly and the core managed assemblies; otherwise, using this parameter may result in an exception being thrown when attempting to open the connection.</description>
    /// <description>N</description>
    /// <description></description>
    /// </item>






    /// <item>
    /// <description>Enlist</description>
    /// <description><b>Y</b> - Automatically enlist in distributed transactions<br/><b>N</b> - No automatic enlistment</description>
    /// <description>N</description>
    /// <description>Y</description>
    /// </item>
    /// <item>
    /// <description>Pooling</description>


    /// <description><b>True</b> - Use connection pooling<br/><b>False</b> - Do not use connection pooling</description>





    /// <description>N</description>
    /// <description>False</description>
    /// </item>
    /// <item>
    /// <description>FailIfMissing</description>
    /// <description><b>True</b> - Don't create the database if it does not exist, throw an error instead<br/><b>False</b> - Automatically create the database if it does not exist</description>
    /// <description>N</description>







>
>
>
>
>
>








>
>
|
>
>
>
>
>







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
    /// </item>
    /// <item>
    /// <description>Password</description>
    /// <description>{password} - Using this parameter requires that the CryptoAPI based codec be enabled at compile-time for both the native interop assembly and the core managed assemblies; otherwise, using this parameter may result in an exception being thrown when attempting to open the connection.</description>
    /// <description>N</description>
    /// <description></description>
    /// </item>
    /// <item>
    /// <description>HexPassword</description>
    /// <description>{hexPassword} - Must contain a sequence of zero or more hexadecimal encoded byte values without a leading "0x" prefix.  Using this parameter requires that the CryptoAPI based codec be enabled at compile-time for both the native interop assembly and the core managed assemblies; otherwise, using this parameter may result in an exception being thrown when attempting to open the connection.</description>
    /// <description>N</description>
    /// <description></description>
    /// </item>
    /// <item>
    /// <description>Enlist</description>
    /// <description><b>Y</b> - Automatically enlist in distributed transactions<br/><b>N</b> - No automatic enlistment</description>
    /// <description>N</description>
    /// <description>Y</description>
    /// </item>
    /// <item>
    /// <description>Pooling</description>
    /// <description>
    /// <b>True</b> - Use connection pooling.<br/>
    /// <b>False</b> - Do not use connection pooling.<br/><br/>
    /// <b>WARNING:</b> When using the default connection pool implementation,
    /// setting this property to True should be avoided by applications that
    /// make use of COM (either directly or indirectly) due to possible
    /// deadlocks that can occur during the finalization of some COM objects.
    /// </description>
    /// <description>N</description>
    /// <description>False</description>
    /// </item>
    /// <item>
    /// <description>FailIfMissing</description>
    /// <description><b>True</b> - Don't create the database if it does not exist, throw an error instead<br/><b>False</b> - Automatically create the database if it does not exist</description>
    /// <description>N</description>
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
    /// <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(';');

      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)







|
<







1397
1398
1399
1400
1401
1402
1403
1404

1405
1406
1407
1408
1409
1410
1411
    /// <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.

      string[] arParts = s.Split(';');

      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)
1487
1488
1489
1490
1491
1492
1493






































1494
1495
1496
1497
1498
1499
1500
        catch
        {
            // do nothing.
        }

        return null;
    }







































    /// <summary>
    /// Enables or disabled extension loading.
    /// </summary>
    /// <param name="enable">
    /// True to enable loading of extensions, false to disable.
    /// </param>







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







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
        catch
        {
            // do nothing.
        }

        return null;
    }

    /// <summary>
    /// Attempts to convert an input string into a byte value.
    /// </summary>
    /// <param name="value">
    /// The string value to be converted.
    /// </param>
    /// <param name="style">
    /// The number styles to use for the conversion.
    /// </param>
    /// <param name="result">
    /// Upon sucess, this will contain the parsed byte value.
    /// Upon failure, the value of this parameter is undefined.
    /// </param>
    /// <returns>
    /// Non-zero upon success; zero on failure.
    /// </returns>
    private static bool TryParseByte(
        string value,
        NumberStyles style,
        out byte result
        )
    {
#if !PLATFORM_COMPACTFRAMEWORK
        return byte.TryParse(value, style, null, out result);
#else
        try
        {
            result = byte.Parse(value, style);
            return true;
        }
        catch
        {
            result = 0;
            return false;
        }
#endif
    }

    /// <summary>
    /// Enables or disabled extension loading.
    /// </summary>
    /// <param name="enable">
    /// True to enable loading of extensions, false to disable.
    /// </param>
1546
1547
1548
1549
1550
1551
1552






































































































1553
1554
1555
1556
1557
1558
1559

        if (_sql == null)
            throw new InvalidOperationException(
                "Database connection not valid for loading extensions.");

        _sql.LoadExtension(fileName, procName);
    }







































































































    /// <summary>
    /// Opens the connection using the parameters found in the <see cref="ConnectionString" />.
    /// </summary>
    public override void Open()
    {
      CheckDisposed();







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







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
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
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

        if (_sql == null)
            throw new InvalidOperationException(
                "Database connection not valid for loading extensions.");

        _sql.LoadExtension(fileName, procName);
    }

    /// <summary>
    /// Parses a string containing a sequence of zero or more hexadecimal
    /// encoded byte values and returns the resulting byte array.  The
    /// "0x" prefix is not allowed on the input string.
    /// </summary>
    /// <param name="text">
    /// The input string containing zero or more hexadecimal encoded byte
    /// values.
    /// </param>
    /// <returns>
    /// A byte array containing the parsed byte values or null if an error
    /// was encountered.
    /// </returns>
    internal static byte[] FromHexString(
        string text
        )
    {
        string error = null;

        return FromHexString(text, ref error);
    }

    /// <summary>
    /// Creates and returns a string containing the hexadecimal encoded byte
    /// values from the input array.
    /// </summary>
    /// <param name="array">
    /// The input array of bytes.
    /// </param>
    /// <returns>
    /// The resulting string or null upon failure.
    /// </returns>
    internal static string ToHexString(
        byte[] array
        )
    {
        if (array == null)
            return null;

        StringBuilder result = new StringBuilder();

        int length = array.Length;

        for (int index = 0; index < length; index++)
            result.AppendFormat("{0:x2}", array[index]);

        return result.ToString();
    }

    /// <summary>
    /// Parses a string containing a sequence of zero or more hexadecimal
    /// encoded byte values and returns the resulting byte array.  The
    /// "0x" prefix is not allowed on the input string.
    /// </summary>
    /// <param name="text">
    /// The input string containing zero or more hexadecimal encoded byte
    /// values.
    /// </param>
    /// <param name="error">
    /// Upon failure, this will contain an appropriate error message.
    /// </param>
    /// <returns>
    /// A byte array containing the parsed byte values or null if an error
    /// was encountered.
    /// </returns>
    private static byte[] FromHexString(
        string text,
        ref string error
        )
    {
        if (String.IsNullOrEmpty(text))
        {
            error = "string is null or empty";
            return null;
        }

        if (text.Length % 2 != 0)
        {
            error = "string contains an odd number of characters";
            return null;
        }

        byte[] result = new byte[text.Length / 2];

        for (int index = 0; index < text.Length; index += 2)
        {
            string value = text.Substring(index, 2);

            if (!TryParseByte(value,
                    NumberStyles.HexNumber, out result[index / 2]))
            {
                error = String.Format(
                    "string contains \"{0}\", which cannot be converted to a byte value",
                    value);

                return null;
            }
        }

        return result;
    }

    /// <summary>
    /// Opens the connection using the parameters found in the <see cref="ConnectionString" />.
    /// </summary>
    public override void Open()
    {
      CheckDisposed();
1682
1683
1684
1685
1686
1687
1688


















1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
            flags |= SQLiteOpenFlagsEnum.Uri;

        _sql.Open(fileName, _flags, flags, maxPoolSize, usePooling);

        _binaryGuid = SQLiteConvert.ToBoolean(FindKey(opts, "BinaryGUID", DefaultBinaryGUID.ToString()));

#if INTEROP_CODEC


















        string password = FindKey(opts, "Password", DefaultPassword);

        if (!String.IsNullOrEmpty(password))
          _sql.SetPassword(System.Text.UTF8Encoding.UTF8.GetBytes(password));
        else if (_password != null)
          _sql.SetPassword(_password);

        _password = null;
#endif

        if (!fullUri)
          _dataSource = Path.GetFileNameWithoutExtension(fileName);
        else
          _dataSource = fileName;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

|
|
|
|
|







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
            flags |= SQLiteOpenFlagsEnum.Uri;

        _sql.Open(fileName, _flags, flags, maxPoolSize, usePooling);

        _binaryGuid = SQLiteConvert.ToBoolean(FindKey(opts, "BinaryGUID", DefaultBinaryGUID.ToString()));

#if INTEROP_CODEC
        string hexPassword = FindKey(opts, "HexPassword", DefaultHexPassword);

        if (!String.IsNullOrEmpty(hexPassword))
        {
            string error = null;
            byte[] hexPasswordBytes = FromHexString(hexPassword, ref error);

            if (hexPasswordBytes == null)
            {
                throw new FormatException(String.Format(
                    "Cannot parse 'HexPassword' property value into byte values: {0}",
                    error));
            }

            _sql.SetPassword(hexPasswordBytes);
        }
        else
        {
            string password = FindKey(opts, "Password", DefaultPassword);

            if (!String.IsNullOrEmpty(password))
                _sql.SetPassword(UTF8Encoding.UTF8.GetBytes(password));
            else if (_password != null)
                _sql.SetPassword(_password);
        }
        _password = null;
#endif

        if (!fullUri)
          _dataSource = Path.GetFileNameWithoutExtension(fileName);
        else
          _dataSource = fileName;
1895
1896
1897
1898
1899
1900
1901



















1902
1903
1904
1905
1906
1907
1908

        if (_sql == null)
          throw new InvalidOperationException("Database connection not valid for getting last insert rowid.");

        return _sql.LastInsertRowId;
      }
    }




















    /// <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)]







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







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

        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)]
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
    /// and if it already was password protected, the existing password must already have been supplied.
    /// </remarks>
    /// <param name="newPassword">The new password to assign to the database</param>
    public void ChangePassword(string newPassword)
    {
      CheckDisposed();

      ChangePassword(String.IsNullOrEmpty(newPassword) ? null : System.Text.UTF8Encoding.UTF8.GetBytes(newPassword));
    }

    /// <summary>
    /// Change the password (or assign a password) to an open database.
    /// </summary>
    /// <remarks>
    /// No readers or writers may be active for this process.  The database must already be open







|







2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
    /// and if it already was password protected, the existing password must already have been supplied.
    /// </remarks>
    /// <param name="newPassword">The new password to assign to the database</param>
    public void ChangePassword(string newPassword)
    {
      CheckDisposed();

      ChangePassword(String.IsNullOrEmpty(newPassword) ? null : UTF8Encoding.UTF8.GetBytes(newPassword));
    }

    /// <summary>
    /// Change the password (or assign a password) to an open database.
    /// </summary>
    /// <remarks>
    /// No readers or writers may be active for this process.  The database must already be open
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
    /// unusable for any operation until the password has been set.
    /// </summary>
    /// <param name="databasePassword">The password for the database</param>
    public void SetPassword(string databasePassword)
    {
      CheckDisposed();

      SetPassword(String.IsNullOrEmpty(databasePassword) ? null : System.Text.UTF8Encoding.UTF8.GetBytes(databasePassword));
    }

    /// <summary>
    /// Sets the password for a password-protected database.  A password-protected database is
    /// unusable for any operation until the password has been set.
    /// </summary>
    /// <param name="databasePassword">The password for the database</param>







|







2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
    /// unusable for any operation until the password has been set.
    /// </summary>
    /// <param name="databasePassword">The password for the database</param>
    public void SetPassword(string databasePassword)
    {
      CheckDisposed();

      SetPassword(String.IsNullOrEmpty(databasePassword) ? null : UTF8Encoding.UTF8.GetBytes(databasePassword));
    }

    /// <summary>
    /// Sets the password for a password-protected database.  A password-protected database is
    /// unusable for any operation until the password has been set.
    /// </summary>
    /// <param name="databasePassword">The password for the database</param>
Changes to System.Data.SQLite/SQLiteConnectionPool.cs.
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
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
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
/********************************************************
 * 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.Collections.Generic;





  using System.Threading;






































































































































































  internal static class SQLiteConnectionPool





  {









    /// <summary>
    /// Keeps track of connections made on a specified file.  The PoolVersion dictates whether old objects get
    /// returned to the pool or discarded when no longer in use.


    /// </summary>

















    internal class Pool


    {
      internal readonly Queue<WeakReference> Queue = new Queue<WeakReference>();
      internal int PoolVersion;
      internal int MaxPoolSize;






      internal Pool(int version, int maxSize)



      {

        PoolVersion = version;



















        MaxPoolSize = maxSize;

      }



























    }



























































    /// <summary>















































































    /// The connection pool object

    /// </summary>








    private static SortedList<string, Pool> _connections = new SortedList<string, Pool>(StringComparer.OrdinalIgnoreCase);




    /// <summary>
    /// The default version number new pools will get
    /// </summary>
    private static int _poolVersion = 1;



    /// <summary>
    /// The number of connections successfully opened from any pool.
    /// This value is incremented by the Remove method.
    /// </summary>
    private static int _poolOpened = 0;



    /// <summary>
    /// The number of connections successfully closed from any pool.
    /// This value is incremented by the Add method.
    /// </summary>
    private static int _poolClosed = 0;





    /// <summary>
    /// Counts the number of pool entries matching the specified file name.
    /// </summary>

    /// <param name="fileName">The file name to match or null to match all files.</param>

    /// <param name="counts">The pool entry counts for each matching file.</param>



    /// <param name="openCount">The total number of connections successfully opened from any pool.</param>


    /// <param name="closeCount">The total number of connections successfully closed from any pool.</param>


    /// <param name="totalCount">The total number of pool entries for all matching files.</param>

    internal static void GetCounts(
        string fileName,
        ref Dictionary<string, int> counts,
        ref int openCount,
        ref int closeCount,
        ref int totalCount
        )
    {




        lock (_connections)






        {
            openCount = _poolOpened;
            closeCount = _poolClosed;

            if (counts == null)
            {
                counts = new Dictionary<string, int>(
                    StringComparer.OrdinalIgnoreCase);
            }

            if (fileName != null)
            {
                Pool queue;

                if (_connections.TryGetValue(fileName, out queue))
                {
                    Queue<WeakReference> poolQueue = queue.Queue;
                    int count = (poolQueue != null) ? poolQueue.Count : 0;

                    counts.Add(fileName, count);
                    totalCount += count;
                }
            }
            else
            {
                foreach (KeyValuePair<string, Pool> pair in _connections)
                {
                    if (pair.Value == null)
                        continue;

                    Queue<WeakReference> poolQueue = pair.Value.Queue;
                    int count = (poolQueue != null) ? poolQueue.Count : 0;

                    counts.Add(pair.Key, count);
                    totalCount += count;
                }
            }
        }
    }



















































































































    /// <summary>






















    /// Attempt to pull a pooled connection out of the queue for active duty










































    /// </summary>
    /// <param name="fileName">The filename for a desired connection</param>


    /// <param name="maxPoolSize">The maximum size the connection pool for the filename can be</param>



    /// <param name="version">The pool version the returned connection will belong to</param>



    /// <returns>Returns NULL if no connections were available.  Even if none are, the poolversion will still be a valid pool version</returns>



    internal static SQLiteConnectionHandle Remove(string fileName, int maxPoolSize, out int version)













    {
        int localVersion;
        Queue<WeakReference> poolQueue;

        //
        // NOTE: This lock cannot be held while checking the queue for available
        //       connections because other methods of this class are called from

        //       the GC finalizer thread and we use the WaitForPendingFinalizers
        //       method (below).  Holding this lock while calling that method
        //       would therefore result in a deadlock.  Instead, this lock is
        //       held only while a temporary copy of the queue is created, and
        //       if necessary, when committing changes back to that original
        //       queue prior to returning from this method.

        //
        lock (_connections)
        {
            Pool queue;


            // Default to the highest pool version

            version = _poolVersion;


            // If we didn't find a pool for this file, create one even though it will be empty.

            // We have to do this here because otherwise calling ClearPool() on the file will not work for active connections

            // that have never seen the pool yet.

            if (_connections.TryGetValue(fileName, out queue) == false)
            {
                queue = new Pool(_poolVersion, maxPoolSize);
                _connections.Add(fileName, queue);

                return null;
            }


            // We found a pool for this file, so use its version number


            version = localVersion = queue.PoolVersion;
            queue.MaxPoolSize = maxPoolSize;





            ResizePool(queue, false);


            // Try and get a pooled connection from the queue

            poolQueue = queue.Queue;
            if (poolQueue == null) return null;

            //
            // NOTE: Temporarily tranfer the queue for this file into a local
            //       variable.  The queue for this file will be modified and
            //       then committed back to the real pool list (below) prior

            //       to returning from this method.
            //
            _connections.Remove(fileName);
            poolQueue = new Queue<WeakReference>(poolQueue);
        }

        try
        {
            while (poolQueue.Count > 0)
            {
                WeakReference cnn = poolQueue.Dequeue();

                if (cnn == null) continue;

                SQLiteConnectionHandle hdl = cnn.Target as SQLiteConnectionHandle;


                if (hdl == null) continue;

                //
                // BUGFIX: For ticket [996d13cd87], step #1.  After this point,
                //         make sure that the finalizer for the connection
                //         handle just obtained from the queue cannot START

                //         running (i.e. it may still be pending but it will no
                //         longer start after this point).
                //
                GC.SuppressFinalize(hdl);

                try
                {
                    //
                    // BUGFIX: For ticket [996d13cd87], step #2.  Now, we must wait
                    //         for all pending finalizers which have STARTED running

                    //         and have not yet COMPLETED.  This must be done just
                    //         in case the finalizer for the connection handle just
                    //         obtained from the queue has STARTED running at some

                    //         point before SuppressFinalize was called on it.
                    //
                    //         After this point, checking properties of the
                    //         connection handle (e.g. IsClosed) should work
                    //         reliably without having to worry that they will

                    //         (due to the finalizer) change out from under us.
                    //
                    GC.WaitForPendingFinalizers();

                    //
                    // BUGFIX: For ticket [996d13cd87], step #3.  Next, verify that

                    //         the connection handle is actually valid and [still?]
                    //         not closed prior to actually returning it to our
                    //         caller.
                    //
                    if (!hdl.IsInvalid && !hdl.IsClosed)
                    {
                        Interlocked.Increment(ref _poolOpened);
                        return hdl;
















                    }
                }
                finally
                {
                    //
                    // BUGFIX: For ticket [996d13cd87], step #4.  Next, we must
                    //         re-register the connection handle for finalization
                    //         now that we have a strong reference to it (i.e. the
                    //         finalizer will not run at least until the connection
                    //         is subsequently closed).
                    //
                    GC.ReRegisterForFinalize(hdl);
                }

                GC.KeepAlive(hdl);
            }
        }
        finally
        {
            //
            // BUGFIX: For ticket [996d13cd87], step #5.  Finally, commit any
            //         changes to the pool/queue for this database file.
            //
            lock (_connections)
            {
                //
                // NOTE: We must check [again] if a pool exists for this file
                //       because one may have been added while the search for

                //       an available connection was in progress (above).
                //
                Pool queue;
                Queue<WeakReference> newPoolQueue;
                bool addPool;

                if (_connections.TryGetValue(fileName, out queue))
                {
                    addPool = false;
                }
                else
                {
                    addPool = true;
                    queue = new Pool(localVersion, maxPoolSize);
                }

                newPoolQueue = queue.Queue;

                while (poolQueue.Count > 0)
                    newPoolQueue.Enqueue(poolQueue.Dequeue());

                ResizePool(queue, false);

                if (addPool)
                    _connections.Add(fileName, queue);
            }
        }

        return null;
    }

    /// <summary>
    /// Clears out all pooled connections and rev's up the default pool version to force all old active objects
    /// not in the pool to get discarded rather than returned to their pools.
    /// </summary>
    internal static void ClearAllPools()
    {
      lock (_connections)
      {
        foreach (KeyValuePair<string, Pool> pair in _connections)

        {
          if (pair.Value == null)
            continue;

          Queue<WeakReference> poolQueue = pair.Value.Queue;




          while (poolQueue.Count > 0)


          {
            WeakReference cnn = poolQueue.Dequeue();
            if (cnn == null) continue;
            SQLiteConnectionHandle hdl = cnn.Target as SQLiteConnectionHandle;
            if (hdl != null)
            {
              hdl.Dispose();

            }
            GC.KeepAlive(hdl);
          }
          
          // Keep track of the highest revision so we can go one higher when we're finished
          if (_poolVersion <= pair.Value.PoolVersion)
            _poolVersion = pair.Value.PoolVersion + 1;
        }
        // All pools are cleared and we have a new highest version number to force all old version active items to get discarded
        // instead of going back to the queue when they are closed.
        // We can get away with this because we've pumped up the _poolVersion out of range of all active connections, so they
        // will all get discarded when they try to put themselves back in their pool.
        _connections.Clear();

      }
    }

    /// <summary>
    /// Clear a given pool for a given filename.  Discards anything in the pool for the given file, and revs the pool
    /// version so current active objects on the old version of the pool will get discarded rather than be returned to the pool.


    /// </summary>
    /// <param name="fileName">The filename of the pool to clear</param>



    internal static void ClearPool(string fileName)
    {
      lock (_connections)
      {
        Pool queue;
        if (_connections.TryGetValue(fileName, out queue) == true)
        {
          queue.PoolVersion++;

          Queue<WeakReference> poolQueue = queue.Queue;
          if (poolQueue == null) return;

          while (poolQueue.Count > 0)
          {
            WeakReference cnn = poolQueue.Dequeue();
            if (cnn == null) continue;
            SQLiteConnectionHandle hdl = cnn.Target as SQLiteConnectionHandle;
            if (hdl != null)
            {
              hdl.Dispose();

            }
            GC.KeepAlive(hdl);
          }
        }
      }
    }

    /// <summary>
    /// Return a connection to the pool for someone else to use.
    /// </summary>
    /// <param name="fileName">The filename of the pool to use</param>
    /// <param name="hdl">The connection handle to pool</param>
    /// <param name="version">The pool version the handle was created under</param>
    /// <remarks>
    /// If the version numbers don't match between the connection and the pool, then the handle is discarded.
    /// </remarks>
    internal static void Add(string fileName, SQLiteConnectionHandle hdl, int version)
    {
      lock (_connections)
      {
        // If the queue doesn't exist in the pool, then it must've been cleared sometime after the connection was created.
        Pool queue;
        if (_connections.TryGetValue(fileName, out queue) == true && version == queue.PoolVersion)
        {
          ResizePool(queue, true);

          Queue<WeakReference> poolQueue = queue.Queue;
          if (poolQueue == null) return;

          poolQueue.Enqueue(new WeakReference(hdl, false));
          Interlocked.Increment(ref _poolClosed);
        }
        else
        {
          hdl.Close();
        }
        GC.KeepAlive(hdl);
      }
    }

    /// <summary>
    /// We don't have to thread-lock anything in this function, because it's only called by other functions above
    /// which already have a thread-safe lock.
    /// </summary>
    /// <param name="queue">The queue to resize</param>



    /// <param name="forAdding">If a function intends to add to the pool, this is true, which forces the resize
    /// to take one more than it needs from the pool</param>

    private static void ResizePool(Pool queue, bool forAdding)



    {
      int target = queue.MaxPoolSize;

      if (forAdding && target > 0) target--;

      Queue<WeakReference> poolQueue = queue.Queue;
      if (poolQueue == null) return;

      while (poolQueue.Count > target)
      {
        WeakReference cnn = poolQueue.Dequeue();

        if (cnn == null) continue;

        SQLiteConnectionHandle hdl = cnn.Target as SQLiteConnectionHandle;
        if (hdl != null)

        {

          hdl.Dispose();
        }
        GC.KeepAlive(hdl);
      }
    }

  }

}









|
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
|
<
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
<
|
|
>
>
>
>
>
|
|
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
|
>

>
>
|
|
|
|
>
>

|
|
|
|
|

>
>
|
|
|
|
|
>

>
>
>
|
|
|
>
|
>
|
>
>
>
|
>
>
|
>
>
|
>
|
|
|
|
|
|
|
|
>
>
>
>
|
>
>
>
>
>
>
|
|
|

|
|
|
|
|

|
|
|

|
|
|
|

|
|
|
|
|
|
|
|
|
|

|
|

|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
|
>
>
>
|
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|

|
|
|
>
|
|
|
|
|
|
>
|
|
|
|

>
|
>
|

>
|
>
|
>
|
>
|
|
|
|

|
|

>
|
>
>
|
|

>
>
>
>
|

>
|
>
|
|

|
|
|
|
>
|
|
|
|
|

|
|
|
|
|
>
|

|
>
>
|

|
|
|
|
>
|
|
|
|

|
|
|
|
|
>
|
|
|
>
|
|
|
|
|
>
|
|
|

|
|
>
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





|
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
|
|
|
|
|
|
|
>
|
|
|
|
|

|
|
|
|
|
|
|
|
|

|

|
|

|

|
|
|
|

|
|
|
<
<
<
<
<
<
|
|
<
>
|
<
|
|
|
|
>
>
>
|
>
>
|
<
<
<
|

<
>

<
|
<
<
<
<
|
<
<
<
<
<
>
|
<
<
|
<
<
>
>
|
|
>
>
>
|
<
|
<
<
<
<
<
|
<
<
<
<
|
<
<
<
|

<
>

<
|
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
|
|
>
>
>
|
|
>
|
>
>
>
|
|

|

|
|

|
|
|
>
|
>
|
<
>
|
>
|
|
|
|
|
>
|
>

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
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
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
/********************************************************
 * 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.Collections.Generic;

#if !PLATFORM_COMPACTFRAMEWORK && DEBUG
    using System.Text;
#endif

    using System.Threading;

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

    #region Null Connection Pool Class
#if !PLATFORM_COMPACTFRAMEWORK && DEBUG
    /// <summary>
    /// This class implements a connection pool where all methods of the
    /// <see cref="ISQLiteConnectionPool" /> interface are NOPs.  This class
    /// is used for testing purposes only.
    /// </summary>
    internal sealed class NullConnectionPool : ISQLiteConnectionPool
    {
        #region Private Data
        /// <summary>
        /// This field keeps track of all method calls made into the
        /// <see cref="ISQLiteConnectionPool" /> interface methods of this
        /// class.
        /// </summary>
        private StringBuilder log;

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

        /// <summary>
        /// Non-zero to dispose of database connection handles received via the
        /// <see cref="Add" /> method.
        /// </summary>
        private bool dispose;
        #endregion

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

        #region Private Constructors
        /// <summary>
        /// Constructs a connection pool object where all methods of the
        /// <see cref="ISQLiteConnectionPool" /> interface are NOPs.  This
        /// class is used for testing purposes only.
        /// </summary>
        private NullConnectionPool()
        {
            log = new StringBuilder();
        }
        #endregion

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

        #region Public Constructors
        /// <summary>
        /// Constructs a connection pool object where all methods of the
        /// <see cref="ISQLiteConnectionPool" /> interface are NOPs.  This
        /// class is used for testing purposes only.
        /// </summary>
        /// <param name="dispose">
        /// Non-zero to dispose of database connection handles received via the
        /// <see cref="Add" /> method.
        /// </param>
        public NullConnectionPool(
            bool dispose
            )
            : this()
        {
            this.dispose = dispose;
        }
        #endregion

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

        #region ISQLiteConnectionPool Members
        /// <summary>
        /// Counts the number of pool entries matching the specified file name.
        /// </summary>
        /// <param name="fileName">
        /// The file name to match or null to match all files.
        /// </param>
        /// <param name="counts">
        /// The pool entry counts for each matching file.
        /// </param>
        /// <param name="openCount">
        /// The total number of connections successfully opened from any pool.
        /// </param>
        /// <param name="closeCount">
        /// The total number of connections successfully closed from any pool.
        /// </param>
        /// <param name="totalCount">
        /// The total number of pool entries for all matching files.
        /// </param>
        public void GetCounts(
            string fileName,
            ref Dictionary<string, int> counts,
            ref int openCount,
            ref int closeCount,
            ref int totalCount
            )
        {
            if (log != null)
            {
                log.AppendFormat(
                    "GetCounts(\"{0}\", {1}, {2}, {3}, {4}){5}", fileName,
                    counts, openCount, closeCount, totalCount,
                    Environment.NewLine);
            }
        }

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

        /// <summary>
        /// Disposes of all pooled connections associated with the specified
        /// database file name.
        /// </summary>
        /// <param name="fileName">
        /// The database file name.
        /// </param>
        public void ClearPool(
            string fileName
            )
        {
            if (log != null)
            {
                log.AppendFormat(
                    "ClearPool(\"{0}\"){1}", fileName, Environment.NewLine);
            }
        }

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

        /// <summary>
        /// Disposes of all pooled connections.
        /// </summary>
        public void ClearAllPools()
        {
            if (log != null)
            {
                log.AppendFormat(
                    "ClearAllPools(){0}", Environment.NewLine);
            }
        }

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

        /// <summary>
        /// Adds a connection to the pool of those associated with the
        /// specified database file name.
        /// </summary>
        /// <param name="fileName">
        /// The database file name.
        /// </param>
        /// <param name="handle">
        /// The database connection handle.
        /// </param>
        /// <param name="version">
        /// The connection pool version at the point the database connection
        /// handle was received from the connection pool.  This is also the
        /// connection pool version that the database connection handle was
        /// created under.
        /// </param>
        public void Add(
            string fileName,
            object handle,
            int version
            )
        {
            if (log != null)
            {
                log.AppendFormat(
                    "Add(\"{0}\", {1}, {2}){3}", fileName, handle, version,
                    Environment.NewLine);
            }

            //
            // NOTE: If configured to do so, dispose of the received connection
            //       handle now.
            //
            if (dispose)
            {
                IDisposable disposable = handle as IDisposable;

                if (disposable != null)
                    disposable.Dispose();
            }
        }

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

        /// <summary>

        /// Removes a connection from the pool of those associated with the
        /// specified database file name with the intent of using it to
        /// interact with the database.
        /// </summary>
        /// <param name="fileName">
        /// The database file name.
        /// </param>
        /// <param name="maxPoolSize">
        /// The new maximum size of the connection pool for the specified
        /// database file name.
        /// </param>
        /// <param name="version">
        /// The connection pool version associated with the returned database
        /// connection handle, if any.
        /// </param>
        /// <returns>
        /// The database connection handle associated with the specified
        /// database file name or null if it cannot be obtained.
        /// </returns>
        public object Remove(
            string fileName,
            int maxPoolSize,
            out int version
            )
        {

            version = 0;

            if (log != null)
            {
                log.AppendFormat(
                    "Remove(\"{0}\", {1}, {2}){3}", fileName, maxPoolSize,
                    version, Environment.NewLine);
            }

            return null;
        }
        #endregion

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

        #region System.Object Overrides
        /// <summary>
        /// Overrides the default <see cref="System.Object.ToString" /> method
        /// to provide a log of all methods called on the
        /// <see cref="ISQLiteConnectionPool" /> interface.
        /// </summary>
        /// <returns>
        /// A string containing a log of all method calls into the
        /// <see cref="ISQLiteConnectionPool" /> interface, along with their
        /// parameters, delimited by <see cref="Environment.NewLine" />.
        /// </returns>
        public override string ToString()
        {
            return (log != null) ? log.ToString() : String.Empty;
        }
        #endregion
    }
#endif
    #endregion

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

    #region Public Connection Pool Interface
    /// <summary>
    /// This interface represents a custom connection pool implementation
    /// usable by System.Data.SQLite.
    /// </summary>
    public interface ISQLiteConnectionPool
    {
        /// <summary>
        /// Counts the number of pool entries matching the specified file name.
        /// </summary>
        /// <param name="fileName">
        /// The file name to match or null to match all files.
        /// </param>
        /// <param name="counts">
        /// The pool entry counts for each matching file.
        /// </param>
        /// <param name="openCount">
        /// The total number of connections successfully opened from any pool.
        /// </param>
        /// <param name="closeCount">
        /// The total number of connections successfully closed from any pool.
        /// </param>
        /// <param name="totalCount">
        /// The total number of pool entries for all matching files.
        /// </param>
        void GetCounts(string fileName, ref Dictionary<string, int> counts,
            ref int openCount, ref int closeCount, ref int totalCount);

        /// <summary>
        /// Disposes of all pooled connections associated with the specified
        /// database file name.
        /// </summary>
        /// <param name="fileName">
        /// The database file name.
        /// </param>
        void ClearPool(string fileName);

        /// <summary>
        /// Disposes of all pooled connections.
        /// </summary>
        void ClearAllPools();

        /// <summary>
        /// Adds a connection to the pool of those associated with the
        /// specified database file name.
        /// </summary>
        /// <param name="fileName">
        /// The database file name.
        /// </param>
        /// <param name="handle">
        /// The database connection handle.
        /// </param>
        /// <param name="version">
        /// The connection pool version at the point the database connection
        /// handle was received from the connection pool.  This is also the
        /// connection pool version that the database connection handle was
        /// created under.
        /// </param>
        void Add(string fileName, object handle, int version);

        /// <summary>
        /// Removes a connection from the pool of those associated with the
        /// specified database file name with the intent of using it to
        /// interact with the database.
        /// </summary>
        /// <param name="fileName">
        /// The database file name.
        /// </param>
        /// <param name="maxPoolSize">
        /// The new maximum size of the connection pool for the specified
        /// database file name.
        /// </param>
        /// <param name="version">
        /// The connection pool version associated with the returned database
        /// connection handle, if any.
        /// </param>
        /// <returns>
        /// The database connection handle associated with the specified
        /// database file name or null if it cannot be obtained.
        /// </returns>
        object Remove(string fileName, int maxPoolSize, out int version);
    }
    #endregion

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

    #region Connection Pool Subsystem & Default Implementation
    /// <summary>
    /// This default method implementations in this class should not be used by
    /// applications that make use of COM (either directly or indirectly) due
    /// to possible deadlocks that can occur during finalization of some COM
    /// objects.
    /// </summary>
    internal static class SQLiteConnectionPool
    {
        #region Private Pool Class
        /// <summary>
        /// Keeps track of connections made on a specified file.  The PoolVersion
        /// dictates whether old objects get returned to the pool or discarded
        /// when no longer in use.
        /// </summary>
        private sealed class PoolQueue
        {
            #region Private Data
            /// <summary>
            /// The queue of weak references to the actual database connection
            /// handles.
            /// </summary>
            internal readonly Queue<WeakReference> Queue =
                new Queue<WeakReference>();

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

            /// <summary>
            /// This pool version associated with the database connection
            /// handles in this pool queue.
            /// </summary>
            internal int PoolVersion;

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

            /// <summary>
            /// The maximum size of this pool queue.
            /// </summary>
            internal int MaxPoolSize;
            #endregion

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

            #region Private Constructors
            /// <summary>
            /// Constructs a connection pool queue using the specified version
            /// and maximum size.  Normally, all the database connection
            /// handles in this pool are associated with a single database file
            /// name.
            /// </summary>
            /// <param name="version">
            /// The initial pool version for this connection pool queue.
            /// </param>
            /// <param name="maxSize">
            /// The initial maximum size for this connection pool queue.
            /// </param>
            internal PoolQueue(
                int version,
                int maxSize
                )
            {
                PoolVersion = version;
                MaxPoolSize = maxSize;
            }
            #endregion
        }
        #endregion

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

        #region Private Static Data
        /// <summary>
        /// This field is used to synchronize access to the private static data
        /// in this class.
        /// </summary>
        private static readonly object _syncRoot = new object();

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

        /// <summary>
        /// When this field is non-null, it will be used to provide the
        /// implementation of all the connection pool methods; otherwise,
        /// the default method implementations will be used.
        /// </summary>
        private static ISQLiteConnectionPool _connectionPool = null;

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

        /// <summary>
        /// The dictionary of connection pools, based on the normalized file
        /// name of the SQLite database.
        /// </summary>
        private static SortedList<string, PoolQueue> _queueList =
            new SortedList<string, PoolQueue>(StringComparer.OrdinalIgnoreCase);

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

        /// <summary>
        /// The default version number new pools will get.
        /// </summary>
        private static int _poolVersion = 1;

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

        /// <summary>
        /// The number of connections successfully opened from any pool.
        /// This value is incremented by the Remove method.
        /// </summary>
        private static int _poolOpened = 0;

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

        /// <summary>
        /// The number of connections successfully closed from any pool.
        /// This value is incremented by the Add method.
        /// </summary>
        private static int _poolClosed = 0;
        #endregion

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

        #region ISQLiteConnectionPool Members (Static, Non-Formal)
        /// <summary>
        /// Counts the number of pool entries matching the specified file name.
        /// </summary>
        /// <param name="fileName">
        /// The file name to match or null to match all files.
        /// </param>
        /// <param name="counts">
        /// The pool entry counts for each matching file.
        /// </param>
        /// <param name="openCount">
        /// The total number of connections successfully opened from any pool.
        /// </param>
        /// <param name="closeCount">
        /// The total number of connections successfully closed from any pool.
        /// </param>
        /// <param name="totalCount">
        /// The total number of pool entries for all matching files.
        /// </param>
        internal static void GetCounts(
            string fileName,
            ref Dictionary<string, int> counts,
            ref int openCount,
            ref int closeCount,
            ref int totalCount
            )
        {
            ISQLiteConnectionPool connectionPool = GetConnectionPool();

            if (connectionPool != null)
            {
                connectionPool.GetCounts(
                    fileName, ref counts, ref openCount, ref closeCount,
                    ref totalCount);
            }
            else
            {
                lock (_syncRoot)
                {
                    openCount = _poolOpened;
                    closeCount = _poolClosed;

                    if (counts == null)
                    {
                        counts = new Dictionary<string, int>(
                            StringComparer.OrdinalIgnoreCase);
                    }

                    if (fileName != null)
                    {
                        PoolQueue queue;

                        if (_queueList.TryGetValue(fileName, out queue))
                        {
                            Queue<WeakReference> poolQueue = queue.Queue;
                            int count = (poolQueue != null) ? poolQueue.Count : 0;

                            counts.Add(fileName, count);
                            totalCount += count;
                        }
                    }
                    else
                    {
                        foreach (KeyValuePair<string, PoolQueue> pair in _queueList)
                        {
                            if (pair.Value == null)
                                continue;

                            Queue<WeakReference> poolQueue = pair.Value.Queue;
                            int count = (poolQueue != null) ? poolQueue.Count : 0;

                            counts.Add(pair.Key, count);
                            totalCount += count;
                        }
                    }
                }
            }
        }

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

        /// <summary>
        /// Disposes of all pooled connections associated with the specified
        /// database file name.
        /// </summary>
        /// <param name="fileName">
        /// The database file name.
        /// </param>
        internal static void ClearPool(string fileName)
        {
            ISQLiteConnectionPool connectionPool = GetConnectionPool();

            if (connectionPool != null)
            {
                connectionPool.ClearPool(fileName);
            }
            else
            {
                lock (_syncRoot)
                {
                    PoolQueue queue;

                    if (_queueList.TryGetValue(fileName, out queue))
                    {
                        queue.PoolVersion++;

                        Queue<WeakReference> poolQueue = queue.Queue;
                        if (poolQueue == null) return;

                        while (poolQueue.Count > 0)
                        {
                            WeakReference connection = poolQueue.Dequeue();

                            if (connection == null) continue;

                            SQLiteConnectionHandle handle =
                                connection.Target as SQLiteConnectionHandle;

                            if (handle != null)
                                handle.Dispose();

                            GC.KeepAlive(handle);
                        }
                    }
                }
            }
        }

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

        /// <summary>
        /// Disposes of all pooled connections.
        /// </summary>
        internal static void ClearAllPools()
        {
            ISQLiteConnectionPool connectionPool = GetConnectionPool();

            if (connectionPool != null)
            {
                connectionPool.ClearAllPools();
            }
            else
            {
                lock (_syncRoot)
                {
                    foreach (KeyValuePair<string, PoolQueue> pair in _queueList)
                    {
                        if (pair.Value == null)
                            continue;

                        Queue<WeakReference> poolQueue = pair.Value.Queue;

                        while (poolQueue.Count > 0)
                        {
                            WeakReference connection = poolQueue.Dequeue();

                            if (connection == null) continue;

                            SQLiteConnectionHandle handle =
                                connection.Target as SQLiteConnectionHandle;

                            if (handle != null)
                                handle.Dispose();

                            GC.KeepAlive(handle);
                        }

                        //
                        // NOTE: Keep track of the highest revision so we can
                        //       go one higher when we are finished.
                        //
                        if (_poolVersion <= pair.Value.PoolVersion)
                            _poolVersion = pair.Value.PoolVersion + 1;
                    }

                    //
                    // NOTE: All pools are cleared and we have a new highest
                    //       version number to force all old version active
                    //       items to get discarded instead of going back to
                    //       the queue when they are closed.  We can get away
                    //       with this because we have pumped up the pool
                    //       version out of range of all active connections,
                    //       so they will all get discarded when they try to
                    //       put themselves back into their pools.
                    //
                    _queueList.Clear();
                }
            }
        }

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

        /// <summary>
        /// Adds a connection to the pool of those associated with the
        /// specified database file name.
        /// </summary>
        /// <param name="fileName">
        /// The database file name.
        /// </param>
        /// <param name="handle">
        /// The database connection handle.
        /// </param>
        /// <param name="version">
        /// The connection pool version at the point the database connection
        /// handle was received from the connection pool.  This is also the
        /// connection pool version that the database connection handle was
        /// created under.
        /// </param>
        internal static void Add(
            string fileName,
            SQLiteConnectionHandle handle,
            int version
            )
        {
            ISQLiteConnectionPool connectionPool = GetConnectionPool();

            if (connectionPool != null)
            {
                connectionPool.Add(fileName, handle, version);
            }
            else
            {
                lock (_syncRoot)
                {
                    //
                    // NOTE: If the queue does not exist in the pool, then it
                    //       must have been cleared sometime after the
                    //       connection was created.
                    //
                    PoolQueue queue;

                    if (_queueList.TryGetValue(fileName, out queue) &&
                        (version == queue.PoolVersion))
                    {
                        ResizePool(queue, true);

                        Queue<WeakReference> poolQueue = queue.Queue;
                        if (poolQueue == null) return;

                        poolQueue.Enqueue(new WeakReference(handle, false));
                        Interlocked.Increment(ref _poolClosed);
                    }
                    else
                    {
                        handle.Close();
                    }

                    GC.KeepAlive(handle);
                }
            }
        }

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

        /// <summary>
        /// Removes a connection from the pool of those associated with the
        /// specified database file name with the intent of using it to
        /// interact with the database.
        /// </summary>
        /// <param name="fileName">
        /// The database file name.
        /// </param>
        /// <param name="maxPoolSize">
        /// The new maximum size of the connection pool for the specified
        /// database file name.
        /// </param>
        /// <param name="version">
        /// The connection pool version associated with the returned database
        /// connection handle, if any.
        /// </param>
        /// <returns>
        /// The database connection handle associated with the specified
        /// database file name or null if it cannot be obtained.
        /// </returns>
        internal static SQLiteConnectionHandle Remove(
            string fileName,
            int maxPoolSize,
            out int version
            )
        {
            ISQLiteConnectionPool connectionPool = GetConnectionPool();

            if (connectionPool != null)
            {
                return connectionPool.Remove(fileName, maxPoolSize,
                    out version) as SQLiteConnectionHandle;
            }
            else
            {
                int localVersion;
                Queue<WeakReference> poolQueue;

                //
                // NOTE: This lock cannot be held while checking the queue for
                //       available connections because other methods of this
                //       class are called from the GC finalizer thread and we
                //       use the WaitForPendingFinalizers method (below).
                //       Holding this lock while calling that method would
                //       therefore result in a deadlock.  Instead, this lock
                //       is held only while a temporary copy of the queue is
                //       created, and if necessary, when committing changes
                //       back to that original queue prior to returning from
                //       this method.
                //
                lock (_syncRoot)
                {
                    PoolQueue queue;

                    //
                    // NOTE: Default to the highest pool version.
                    //
                    version = _poolVersion;

                    //
                    // NOTE: If we didn't find a pool for this file, create one
                    //       even though it will be empty.  We have to do this
                    //       here because otherwise calling ClearPool() on the
                    //       file will not work for active connections that have
                    //       never seen the pool yet.
                    //
                    if (!_queueList.TryGetValue(fileName, out queue))
                    {
                        queue = new PoolQueue(_poolVersion, maxPoolSize);
                        _queueList.Add(fileName, queue);

                        return null;
                    }

                    //
                    // NOTE: We found a pool for this file, so use its version
                    //       number.
                    //
                    version = localVersion = queue.PoolVersion;
                    queue.MaxPoolSize = maxPoolSize;

                    //
                    // NOTE: Now, resize the pool to the new maximum size, if
                    //       necessary.
                    //
                    ResizePool(queue, false);

                    //
                    // NOTE: Try and get a pooled connection from the queue.
                    //
                    poolQueue = queue.Queue;
                    if (poolQueue == null) return null;

                    //
                    // NOTE: Temporarily tranfer the queue for this file into
                    //       a local variable.  The queue for this file will
                    //       be modified and then committed back to the real
                    //       pool list (below) prior to returning from this
                    //       method.
                    //
                    _queueList.Remove(fileName);
                    poolQueue = new Queue<WeakReference>(poolQueue);
                }

                try
                {
                    while (poolQueue.Count > 0)
                    {
                        WeakReference connection = poolQueue.Dequeue();

                        if (connection == null) continue;

                        SQLiteConnectionHandle handle =
                            connection.Target as SQLiteConnectionHandle;

                        if (handle == null) continue;

                        //
                        // BUGFIX: For ticket [996d13cd87], step #1.  After
                        //         this point, make sure that the finalizer for
                        //         the connection handle just obtained from the
                        //         queue cannot START running (i.e. it may
                        //         still be pending but it will no longer start
                        //         after this point).
                        //
                        GC.SuppressFinalize(handle);

                        try
                        {
                            //
                            // BUGFIX: For ticket [996d13cd87], step #2.  Now,
                            //         we must wait for all pending finalizers
                            //         which have STARTED running and have not
                            //         yet COMPLETED.  This must be done just
                            //         in case the finalizer for the connection
                            //         handle just obtained from the queue has
                            //         STARTED running at some point before
                            //         SuppressFinalize was called on it.
                            //
                            //         After this point, checking properties of
                            //         the connection handle (e.g. IsClosed)
                            //         should work reliably without having to
                            //         worry that they will (due to the
                            //         finalizer) change out from under us.
                            //
                            GC.WaitForPendingFinalizers();

                            //
                            // BUGFIX: For ticket [996d13cd87], step #3.  Next,
                            //         verify that the connection handle is
                            //         actually valid and [still?] not closed
                            //         prior to actually returning it to our
                            //         caller.
                            //
                            if (!handle.IsInvalid && !handle.IsClosed)
                            {
                                Interlocked.Increment(ref _poolOpened);
                                return handle;
                            }
                        }
                        finally
                        {
                            //
                            // BUGFIX: For ticket [996d13cd87], step #4.  Next,
                            //         we must re-register the connection
                            //         handle for finalization now that we have
                            //         a strong reference to it (i.e. the
                            //         finalizer will not run at least until
                            //         the connection is subsequently closed).
                            //
                            GC.ReRegisterForFinalize(handle);
                        }

                        GC.KeepAlive(handle);
                    }
                }
                finally
                {
                    //
                    // BUGFIX: For ticket [996d13cd87], step #5.  Finally,







                    //         commit any changes to the pool/queue for this







                    //         database file.
                    //
                    lock (_syncRoot)
                    {
                        //
                        // NOTE: We must check [again] if a pool exists for
                        //       this file because one may have been added
                        //       while the search for an available connection
                        //       was in progress (above).
                        //
                        PoolQueue queue;
                        Queue<WeakReference> newPoolQueue;
                        bool addPool;

                        if (_queueList.TryGetValue(fileName, out queue))
                        {
                            addPool = false;
                        }
                        else
                        {
                            addPool = true;
                            queue = new PoolQueue(localVersion, maxPoolSize);
                        }

                        newPoolQueue = queue.Queue;

                        while (poolQueue.Count > 0)
                            newPoolQueue.Enqueue(poolQueue.Dequeue());

                        ResizePool(queue, false);

                        if (addPool)
                            _queueList.Add(fileName, queue);
                    }
                }

                return null;
            }
        }






        #endregion


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


        #region Private Helper Methods
        /// <summary>
        /// This method is used to obtain a reference to the custom connection
        /// pool implementation currently in use, if any.
        /// </summary>
        /// <returns>
        /// The custom connection pool implementation or null if the default
        /// connection pool implementation should be used.
        /// </returns>
        internal static ISQLiteConnectionPool GetConnectionPool()
        {



            lock (_syncRoot)
            {

                return _connectionPool;
            }

        }










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



        /// <summary>


        /// This method is used to set the reference to the custom connection
        /// pool implementation to use, if any.
        /// </summary>
        /// <param name="connectionPool">
        /// The custom connection pool implementation to use or null if the
        /// default connection pool implementation should be used.
        /// </param>
        internal static void SetConnectionPool(

            ISQLiteConnectionPool connectionPool





            )




        {



            lock (_syncRoot)
            {

                _connectionPool = connectionPool;
            }

        }



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

































        /// <summary>
        /// We do not have to thread-lock anything in this function, because it
        /// is only called by other functions above which already take the lock.
        /// </summary>
        /// <param name="queue">
        /// The pool queue to resize.
        /// </param>
        /// <param name="add">
        /// If a function intends to add to the pool, this is true, which
        /// forces the resize to take one more than it needs from the pool.
        /// </param>
        private static void ResizePool(
            PoolQueue queue,
            bool add
            )
        {
            int target = queue.MaxPoolSize;

            if (add && target > 0) target--;

            Queue<WeakReference> poolQueue = queue.Queue;
            if (poolQueue == null) return;

            while (poolQueue.Count > target)
            {
                WeakReference connection = poolQueue.Dequeue();

                if (connection == null) continue;

                SQLiteConnectionHandle handle =

                    connection.Target as SQLiteConnectionHandle;

                if (handle != null)
                    handle.Dispose();

                GC.KeepAlive(handle);
            }
        }
        #endregion
    }
    #endregion
}
Changes to System.Data.SQLite/SQLiteConnectionStringBuilder.cs.
342
343
344
345
346
347
348




























349
350
351
352
353
354
355
        return value.ToString();
      }
      set
      {
        this["password"] = value;
      }
    }





























    /// <summary>
    /// Gets/Sets the page size for the connection.
    /// </summary>
    [DisplayName("Page Size")]
    [Browsable(true)]
    [DefaultValue(1024)]







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







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
        return value.ToString();
      }
      set
      {
        this["password"] = value;
      }
    }

    /// <summary>
    /// Gets/sets the database encryption hexadecimal password
    /// </summary>
    [Browsable(true)]
    [PasswordPropertyText(true)]
    [DefaultValue(null)]
    public byte[] HexPassword
    {
        get
        {
            object value;

            if (TryGetValue("hexpassword", out value))
            {
                if (value is string)
                    return SQLiteConnection.FromHexString((string)value);
                else if (value != null)
                    return (byte[])value;
            }

            return null;
        }
        set
        {
            this["hexpassword"] = SQLiteConnection.ToHexString(value);
        }
    }

    /// <summary>
    /// Gets/Sets the page size for the connection.
    /// </summary>
    [DisplayName("Page Size")]
    [Browsable(true)]
    [DefaultValue(1024)]
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
      if (pd == null) return b;

      // Attempt to coerce the value into something more solid
      if (b)
      {
        if (pd.PropertyType == typeof(Boolean))
          value = SQLiteConvert.ToBoolean(value);
        else
          value = TypeDescriptor.GetConverter(pd.PropertyType).ConvertFrom(value);
      }
      else
      {
        DefaultValueAttribute att = pd.Attributes[typeof(DefaultValueAttribute)] as DefaultValueAttribute;
        if (att != null)
        {







|







671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
      if (pd == null) return b;

      // Attempt to coerce the value into something more solid
      if (b)
      {
        if (pd.PropertyType == typeof(Boolean))
          value = SQLiteConvert.ToBoolean(value);
        else if (pd.PropertyType != typeof(byte[]))
          value = TypeDescriptor.GetConverter(pd.PropertyType).ConvertFrom(value);
      }
      else
      {
        DefaultValueAttribute att = pd.Attributes[typeof(DefaultValueAttribute)] as DefaultValueAttribute;
        if (att != null)
        {
Changes to System.Data.SQLite/SQLiteConvert.cs.
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;




|







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;

168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
        do
        {
          nativestringlen++;
        } while (Marshal.ReadByte(nativestring, nativestringlen) != 0);
      }

      byte[] byteArray = new byte[nativestringlen];
      
      Marshal.Copy(nativestring, byteArray, 0, nativestringlen);

      return _utf8.GetString(byteArray, 0, nativestringlen);
    }


    #endregion







|







168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
        do
        {
          nativestringlen++;
        } while (Marshal.ReadByte(nativestring, nativestringlen) != 0);
      }

      byte[] byteArray = new byte[nativestringlen];

      Marshal.Copy(nativestring, byteArray, 0, nativestringlen);

      return _utf8.GetString(byteArray, 0, nativestringlen);
    }


    #endregion
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
      if (t.Type == DbType.Object)
        return _affinitytotype[(int)t.Affinity];
      else
        return SQLiteConvert.DbTypeToType(t.Type);
    }

    private static Type[] _affinitytotype = {
      typeof(object),
      typeof(Int64),
      typeof(Double),
      typeof(string),
      typeof(byte[]),
      typeof(object),
      typeof(DateTime),
      typeof(object)
    };

    /// <summary>
    /// For a given intrinsic type, return a DbType
    /// </summary>
    /// <param name="typ">The native type to convert</param>
    /// <returns>The corresponding (closest match) DbType</returns>
    internal static DbType TypeToDbType(Type typ)
    {
      TypeCode tc = Type.GetTypeCode(typ);
      if (tc == TypeCode.Object)
      {
        if (typ == typeof(byte[])) return DbType.Binary;
        if (typ == typeof(Guid)) return DbType.Guid;
        return DbType.String;
      }
      return _typetodbtype[(int)tc];
    }

    private static DbType[] _typetodbtype = {
      DbType.Object,
      DbType.Binary,
      DbType.Object,
      DbType.Boolean,
      DbType.SByte,
      DbType.SByte,
      DbType.Byte,
      DbType.Int16, // 7
      DbType.UInt16,
      DbType.Int32,
      DbType.UInt32,
      DbType.Int64, // 11
      DbType.UInt64,
      DbType.Single,
      DbType.Double,
      DbType.Decimal,
      DbType.DateTime,
      DbType.Object,
      DbType.String,
    };

    /// <summary>
    /// Returns the ColumnSize for the given DbType
    /// </summary>
    /// <param name="typ">The DbType to get the size of</param>
    /// <returns></returns>
    internal static int DbTypeToColumnSize(DbType typ)
    {
      return _dbtypetocolumnsize[(int)typ];
    }

    private static int[] _dbtypetocolumnsize = {
      2147483647,   // 0
      2147483647,   // 1
      1,     // 2
      1,     // 3
      8,  // 4
      8, // 5
      8, // 6
      8,  // 7
      8,   // 8
      16,     // 9
      2,
      4,
      8,
      2147483647,
      1,
      4,
      2147483647,
      8,
      2,
      4,
      8,
      8,
      2147483647,
      2147483647,
      2147483647,
      2147483647,   // 25 (Xml)
    };

    internal static object DbTypeToNumericPrecision(DbType typ)
    {
      return _dbtypetonumericprecision[(int)typ];
    }

    private static object[] _dbtypetonumericprecision = {
      DBNull.Value, // 0
      DBNull.Value, // 1
      3,
      DBNull.Value,
      19,
      DBNull.Value, // 5
      DBNull.Value, // 6
      53,
      53,
      DBNull.Value,
      5,
      10,
      19,
      DBNull.Value,
      3,
      24,
      DBNull.Value,
      DBNull.Value,
      5,
      10,
      19,
      53,

      DBNull.Value,
      DBNull.Value,
      DBNull.Value
    };

    internal static object DbTypeToNumericScale(DbType typ)
    {
      return _dbtypetonumericscale[(int)typ];
    }

    private static object[] _dbtypetonumericscale = {
      DBNull.Value, // 0
      DBNull.Value, // 1
      0,
      DBNull.Value,
      4,
      DBNull.Value, // 5
      DBNull.Value, // 6
      DBNull.Value,
      DBNull.Value,
      DBNull.Value,
      0,
      0,
      0,
      DBNull.Value,
      0,
      DBNull.Value,
      DBNull.Value,
      DBNull.Value,
      0,
      0,
      0,
      0,

      DBNull.Value,
      DBNull.Value,
      DBNull.Value
    };

    internal static string DbTypeToTypeName(DbType typ)
    {
      for (int n = 0; n < _dbtypeNames.Length; n++)
      {
        if (_dbtypeNames[n].dataType == typ)







|
|
|
|
|
|
|
|




















|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|













|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|








|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
|








|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
|







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
      if (t.Type == DbType.Object)
        return _affinitytotype[(int)t.Affinity];
      else
        return SQLiteConvert.DbTypeToType(t.Type);
    }

    private static Type[] _affinitytotype = {
      typeof(object),   // Uninitialized (0)
      typeof(Int64),    // Int64 (1)
      typeof(Double),   // Double (2)
      typeof(string),   // Text (3)
      typeof(byte[]),   // Blob (4)
      typeof(DBNull),   // Null (5)
      typeof(DateTime), // DateTime (10)
      typeof(object)    // None (11)
    };

    /// <summary>
    /// For a given intrinsic type, return a DbType
    /// </summary>
    /// <param name="typ">The native type to convert</param>
    /// <returns>The corresponding (closest match) DbType</returns>
    internal static DbType TypeToDbType(Type typ)
    {
      TypeCode tc = Type.GetTypeCode(typ);
      if (tc == TypeCode.Object)
      {
        if (typ == typeof(byte[])) return DbType.Binary;
        if (typ == typeof(Guid)) return DbType.Guid;
        return DbType.String;
      }
      return _typetodbtype[(int)tc];
    }

    private static DbType[] _typetodbtype = {
      DbType.Object,   // Empty (0)
      DbType.Binary,   // Object (1)
      DbType.Object,   // DBNull (2)
      DbType.Boolean,  // Boolean (3)
      DbType.SByte,    // Char (4)
      DbType.SByte,    // SByte (5)
      DbType.Byte,     // Byte (6)
      DbType.Int16,    // Int16 (7)
      DbType.UInt16,   // UInt16 (8)
      DbType.Int32,    // Int32 (9)
      DbType.UInt32,   // UInt32 (10)
      DbType.Int64,    // Int64 (11)
      DbType.UInt64,   // UInt64 (12)
      DbType.Single,   // Single (13)
      DbType.Double,   // Double (14)
      DbType.Decimal,  // Decimal (15)
      DbType.DateTime, // DateTime (16)
      DbType.Object,   // ?? (17)
      DbType.String    // String (18)
    };

    /// <summary>
    /// Returns the ColumnSize for the given DbType
    /// </summary>
    /// <param name="typ">The DbType to get the size of</param>
    /// <returns></returns>
    internal static int DbTypeToColumnSize(DbType typ)
    {
      return _dbtypetocolumnsize[(int)typ];
    }

    private static int[] _dbtypetocolumnsize = {
      int.MaxValue, // AnsiString (0)
      int.MaxValue, // Binary (1)
      1,            // Byte (2)
      1,            // Boolean (3)
      8,            // Currency (4)
      8,            // Date (5)
      8,            // DateTime (6)
      8,            // Decimal (7)
      8,            // Double (8)
      16,           // Guid (9)
      2,            // Int16 (10)
      4,            // Int32 (11)
      8,            // Int64 (12)
      int.MaxValue, // Object (13)
      1,            // SByte (14)
      4,            // Single (15)
      int.MaxValue, // String (16)
      8,            // Time (17)
      2,            // UInt16 (18)
      4,            // UInt32 (19)
      8,            // UInt64 (20)
      8,            // VarNumeric (21)
      int.MaxValue, // AnsiStringFixedLength (22)
      int.MaxValue, // StringFixedLength (23)
      int.MaxValue, // ?? (24)
      int.MaxValue  // Xml (25)
    };

    internal static object DbTypeToNumericPrecision(DbType typ)
    {
      return _dbtypetonumericprecision[(int)typ];
    }

    private static object[] _dbtypetonumericprecision = {
      DBNull.Value, // AnsiString (0)
      DBNull.Value, // Binary (1)
      3,            // Byte (2)
      DBNull.Value, // Boolean (3)
      19,           // Currency (4)
      DBNull.Value, // Date (5)
      DBNull.Value, // DateTime (6)
      53,           // Decimal (7)
      53,           // Double (8)
      DBNull.Value, // Guid (9)
      5,            // Int16 (10)
      10,           // Int32 (11)
      19,           // Int64 (12)
      DBNull.Value, // Object (13)
      3,            // SByte (14)
      24,           // Single (15)
      DBNull.Value, // String (16)
      DBNull.Value, // Time (17)
      5,            // UInt16 (18)
      10,           // UInt32 (19)
      19,           // UInt64 (20)
      53,           // VarNumeric (21)
      DBNull.Value, // AnsiStringFixedLength (22)
      DBNull.Value, // StringFixedLength (23)
      DBNull.Value, // ?? (24)
      DBNull.Value  // Xml (25)
    };

    internal static object DbTypeToNumericScale(DbType typ)
    {
      return _dbtypetonumericscale[(int)typ];
    }

    private static object[] _dbtypetonumericscale = {
      DBNull.Value, // AnsiString (0)
      DBNull.Value, // Binary (1)
      0,            // Byte (2)
      DBNull.Value, // Boolean (3)
      4,            // Currency (4)
      DBNull.Value, // Date (5)
      DBNull.Value, // DateTime (6)
      DBNull.Value, // Decimal (7)
      DBNull.Value, // Double (8)
      DBNull.Value, // Guid (9)
      0,            // Int16 (10)
      0,            // Int32 (11)
      0,            // Int64 (12)
      DBNull.Value, // Object (13)
      0,            // SByte (14)
      DBNull.Value, // Single (15)
      DBNull.Value, // String (16)
      DBNull.Value, // Time (17)
      0,            // UInt16 (18)
      0,            // UInt32 (19)
      0,            // UInt64 (20)
      0,            // VarNumeric (21)
      DBNull.Value, // AnsiStringFixedLength (22)
      DBNull.Value, // StringFixedLength (23)
      DBNull.Value, // ?? (24)
      DBNull.Value  // Xml (25)
    };

    internal static string DbTypeToTypeName(DbType typ)
    {
      for (int n = 0; n < _dbtypeNames.Length; n++)
      {
        if (_dbtypeNames[n].dataType == typ)
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
          "WARNING: Type mapping failed, returning default name \"{0}\" for type {1}.",
          defaultTypeName, typ));
#endif

      return defaultTypeName;
    }

    private static SQLiteTypeNames[] _dbtypeNames = {
      new SQLiteTypeNames("INTEGER", DbType.Int64),
      new SQLiteTypeNames("TINYINT", DbType.Byte),
      new SQLiteTypeNames("INT", DbType.Int32),
      new SQLiteTypeNames("VARCHAR", DbType.AnsiString),
      new SQLiteTypeNames("NVARCHAR", DbType.String),
      new SQLiteTypeNames("CHAR", DbType.AnsiStringFixedLength),
      new SQLiteTypeNames("NCHAR", DbType.StringFixedLength),
      new SQLiteTypeNames("FLOAT", DbType.Double),
      new SQLiteTypeNames("REAL", DbType.Double),
      new SQLiteTypeNames("BIT", DbType.Boolean),
      new SQLiteTypeNames("DECIMAL", DbType.Decimal),
      new SQLiteTypeNames("DATETIME", DbType.DateTime),
      new SQLiteTypeNames("BLOB", DbType.Binary),
      new SQLiteTypeNames("UNIQUEIDENTIFIER", DbType.Guid),
      new SQLiteTypeNames("SMALLINT", DbType.Int16),
    };
    /// <summary>
    /// Convert a DbType to a Type
    /// </summary>
    /// <param name="typ">The DbType to convert from</param>
    /// <returns>The closest-match .NET type</returns>
    internal static Type DbTypeToType(DbType typ)
    {
      return _dbtypeToType[(int)typ];
    }

    private static Type[] _dbtypeToType = {
      typeof(string),   // 0
      typeof(byte[]),   // 1
      typeof(byte),     // 2
      typeof(bool),     // 3
      typeof(decimal),  // 4
      typeof(DateTime), // 5
      typeof(DateTime), // 6
      typeof(decimal),  // 7
      typeof(double),   // 8
      typeof(Guid),     // 9
      typeof(Int16),
      typeof(Int32),
      typeof(Int64),
      typeof(object),
      typeof(sbyte),
      typeof(float),
      typeof(string),
      typeof(DateTime),
      typeof(UInt16),
      typeof(UInt32),
      typeof(UInt64),
      typeof(double),
      typeof(string),
      typeof(string),
      typeof(string),
      typeof(string),   // 25 (Xml)
    };

    /// <summary>
    /// For a given type, return the closest-match SQLite TypeAffinity, which only understands a very limited subset of types.
    /// </summary>
    /// <param name="typ">The type to evaluate</param>
    /// <returns>The SQLite type affinity for that type.</returns>







|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<











|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







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
          "WARNING: Type mapping failed, returning default name \"{0}\" for type {1}.",
          defaultTypeName, typ));
#endif

      return defaultTypeName;
    }

    private static SQLiteTypeNames[] _dbtypeNames = GetSQLiteTypeNames();
















    /// <summary>
    /// Convert a DbType to a Type
    /// </summary>
    /// <param name="typ">The DbType to convert from</param>
    /// <returns>The closest-match .NET type</returns>
    internal static Type DbTypeToType(DbType typ)
    {
      return _dbtypeToType[(int)typ];
    }

    private static Type[] _dbtypeToType = {
      typeof(string),   // AnsiString (0)
      typeof(byte[]),   // Binary (1)
      typeof(byte),     // Byte (2)
      typeof(bool),     // Boolean (3)
      typeof(decimal),  // Currency (4)
      typeof(DateTime), // Date (5)
      typeof(DateTime), // DateTime (6)
      typeof(decimal),  // Decimal (7)
      typeof(double),   // Double (8)
      typeof(Guid),     // Guid (9)
      typeof(Int16),    // Int16 (10)
      typeof(Int32),    // Int32 (11)
      typeof(Int64),    // Int64 (12)
      typeof(object),   // Object (13)
      typeof(sbyte),    // SByte (14)
      typeof(float),    // Single (15)
      typeof(string),   // String (16)
      typeof(DateTime), // Time (17)
      typeof(UInt16),   // UInt16 (18)
      typeof(UInt32),   // UInt32 (19)
      typeof(UInt64),   // UInt64 (20)
      typeof(double),   // VarNumeric (21)
      typeof(string),   // AnsiStringFixedLength (22)
      typeof(string),   // StringFixedLength (23)
      typeof(string),   // ?? (24)
      typeof(string),   // Xml (25)
    };

    /// <summary>
    /// For a given type, return the closest-match SQLite TypeAffinity, which only understands a very limited subset of types.
    /// </summary>
    /// <param name="typ">The type to evaluate</param>
    /// <returns>The SQLite type affinity for that type.</returns>
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
        else
          return TypeAffinity.Text;
      }
      return _typecodeAffinities[(int)tc];
    }

    private static TypeAffinity[] _typecodeAffinities = {
      TypeAffinity.Null,
      TypeAffinity.Blob,
      TypeAffinity.Null,
      TypeAffinity.Int64,
      TypeAffinity.Int64,
      TypeAffinity.Int64,
      TypeAffinity.Int64,
      TypeAffinity.Int64, // 7
      TypeAffinity.Int64,
      TypeAffinity.Int64,
      TypeAffinity.Int64,
      TypeAffinity.Int64, // 11
      TypeAffinity.Int64,
      TypeAffinity.Double,
      TypeAffinity.Double,
      TypeAffinity.Double,
      TypeAffinity.DateTime,
      TypeAffinity.Null,
      TypeAffinity.Text,
    };


















































































    /// <summary>
    /// For a given type name, return a closest-match .NET type
    /// </summary>
    /// <param name="Name">The name of the type to match</param>
    /// <returns>The .NET DBType the text evaluates to.</returns>
    internal static DbType TypeNameToDbType(string Name)
    {
      lock (_syncRoot)
      {
        if (_typeNames == null)
        {
          _typeNames = new Dictionary<string, SQLiteTypeNames>(
              new TypeNameStringComparer());

          foreach (SQLiteTypeNames typeName in new SQLiteTypeNames[] {
              new SQLiteTypeNames("COUNTER", DbType.Int64),
              new SQLiteTypeNames("AUTOINCREMENT", DbType.Int64),
              new SQLiteTypeNames("IDENTITY", DbType.Int64),
              new SQLiteTypeNames("LONGTEXT", DbType.String),
              new SQLiteTypeNames("LONGCHAR", DbType.String),
              new SQLiteTypeNames("LONGVARCHAR", DbType.String),
              new SQLiteTypeNames("LONG", DbType.Int64),
              new SQLiteTypeNames("TINYINT", DbType.Byte),
              new SQLiteTypeNames("INTEGER", DbType.Int64),
              new SQLiteTypeNames("INT", DbType.Int32),
              new SQLiteTypeNames("VARCHAR", DbType.String),
              new SQLiteTypeNames("NVARCHAR", DbType.String),
              new SQLiteTypeNames("CHAR", DbType.String),
              new SQLiteTypeNames("NCHAR", DbType.String),
              new SQLiteTypeNames("TEXT", DbType.String),
              new SQLiteTypeNames("NTEXT", DbType.String),
              new SQLiteTypeNames("STRING", DbType.String),
              new SQLiteTypeNames("DOUBLE", DbType.Double),
              new SQLiteTypeNames("FLOAT", DbType.Double),
              new SQLiteTypeNames("REAL", DbType.Double),
              new SQLiteTypeNames("BIT", DbType.Boolean),
              new SQLiteTypeNames("YESNO", DbType.Boolean),
              new SQLiteTypeNames("LOGICAL", DbType.Boolean),
              new SQLiteTypeNames("BOOL", DbType.Boolean),
              new SQLiteTypeNames("BOOLEAN", DbType.Boolean),
              new SQLiteTypeNames("NUMERIC", DbType.Decimal),
              new SQLiteTypeNames("DECIMAL", DbType.Decimal),
              new SQLiteTypeNames("MONEY", DbType.Decimal),
              new SQLiteTypeNames("CURRENCY", DbType.Decimal),
              new SQLiteTypeNames("TIME", DbType.DateTime),
              new SQLiteTypeNames("DATE", DbType.DateTime),
              new SQLiteTypeNames("DATETIME", DbType.DateTime),
              new SQLiteTypeNames("SMALLDATE", DbType.DateTime),
              new SQLiteTypeNames("TIMESTAMP", DbType.DateTime),
              new SQLiteTypeNames("BLOB", DbType.Binary),
              new SQLiteTypeNames("BINARY", DbType.Binary),
              new SQLiteTypeNames("VARBINARY", DbType.Binary),
              new SQLiteTypeNames("IMAGE", DbType.Binary),
              new SQLiteTypeNames("GENERAL", DbType.Binary),
              new SQLiteTypeNames("OLEOBJECT", DbType.Binary),
              new SQLiteTypeNames("GUID", DbType.Guid),
              new SQLiteTypeNames("UNIQUEIDENTIFIER", DbType.Guid),
              new SQLiteTypeNames("MEMO", DbType.String),
              new SQLiteTypeNames("NOTE", DbType.String),
              new SQLiteTypeNames("SMALLINT", DbType.Int16),
              new SQLiteTypeNames("BIGINT", DbType.Int64)
            })
          {
            _typeNames.Add(typeName.typeName, typeName);
          }
        }
      }

      if (String.IsNullOrEmpty(Name)) return DbType.Object;

      SQLiteTypeNames value;








|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

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















|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<







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
        else
          return TypeAffinity.Text;
      }
      return _typecodeAffinities[(int)tc];
    }

    private static TypeAffinity[] _typecodeAffinities = {
      TypeAffinity.Null,     // Empty (0)
      TypeAffinity.Blob,     // Object (1)
      TypeAffinity.Null,     // DBNull (2)
      TypeAffinity.Int64,    // Boolean (3)
      TypeAffinity.Int64,    // Char (4)
      TypeAffinity.Int64,    // SByte (5)
      TypeAffinity.Int64,    // Byte (6)
      TypeAffinity.Int64,    // Int16 (7)
      TypeAffinity.Int64,    // UInt16 (8)
      TypeAffinity.Int64,    // Int32 (9)
      TypeAffinity.Int64,    // UInt32 (10)
      TypeAffinity.Int64,    // Int64 (11)
      TypeAffinity.Int64,    // UInt64 (12)
      TypeAffinity.Double,   // Single (13)
      TypeAffinity.Double,   // Double (14)
      TypeAffinity.Double,   // Decimal (15)
      TypeAffinity.DateTime, // DateTime (16)
      TypeAffinity.Null,     // ?? (17)
      TypeAffinity.Text      // String (18)
    };

    /// <summary>
    /// Builds and returns an array containing the database column types
    /// recognized by this provider.
    /// </summary>
    /// <returns>
    /// An array containing the database column types recognized by this
    /// provider.
    /// </returns>
    private static SQLiteTypeNames[] GetSQLiteTypeNames()
    {
        return new SQLiteTypeNames[] {
            new SQLiteTypeNames("BIGINT", DbType.Int64),
            new SQLiteTypeNames("BIGUINT", DbType.UInt64),
            new SQLiteTypeNames("BINARY", DbType.Binary),
            new SQLiteTypeNames("BIT", DbType.Boolean),
            new SQLiteTypeNames("BLOB", DbType.Binary),
            new SQLiteTypeNames("BOOL", DbType.Boolean),
            new SQLiteTypeNames("BOOLEAN", DbType.Boolean),
            new SQLiteTypeNames("CHAR", DbType.AnsiStringFixedLength),
            new SQLiteTypeNames("COUNTER", DbType.Int64),
            new SQLiteTypeNames("CURRENCY", DbType.Decimal),
            new SQLiteTypeNames("DATE", DbType.DateTime),
            new SQLiteTypeNames("DATETIME", DbType.DateTime),
            new SQLiteTypeNames("DECIMAL", DbType.Decimal),
            new SQLiteTypeNames("DOUBLE", DbType.Double),
            new SQLiteTypeNames("FLOAT", DbType.Double),
            new SQLiteTypeNames("GENERAL", DbType.Binary),
            new SQLiteTypeNames("GUID", DbType.Guid),
            new SQLiteTypeNames("IDENTITY", DbType.Int64),
            new SQLiteTypeNames("IMAGE", DbType.Binary),
            new SQLiteTypeNames("INT", DbType.Int32),
            new SQLiteTypeNames("INT8", DbType.SByte),
            new SQLiteTypeNames("INT16", DbType.Int16),
            new SQLiteTypeNames("INT32", DbType.Int32),
            new SQLiteTypeNames("INT64", DbType.Int64),
            new SQLiteTypeNames("INTEGER", DbType.Int64),
            new SQLiteTypeNames("INTEGER8", DbType.SByte),
            new SQLiteTypeNames("INTEGER16", DbType.Int16),
            new SQLiteTypeNames("INTEGER32", DbType.Int32),
            new SQLiteTypeNames("INTEGER64", DbType.Int64),
            new SQLiteTypeNames("LOGICAL", DbType.Boolean),
            new SQLiteTypeNames("LONG", DbType.Int64),
            new SQLiteTypeNames("LONGCHAR", DbType.String),
            new SQLiteTypeNames("LONGTEXT", DbType.String),
            new SQLiteTypeNames("LONGVARCHAR", DbType.String),
            new SQLiteTypeNames("MEMO", DbType.String),
            new SQLiteTypeNames("MONEY", DbType.Decimal),
            new SQLiteTypeNames("NCHAR", DbType.StringFixedLength),
            new SQLiteTypeNames("NOTE", DbType.String),
            new SQLiteTypeNames("NTEXT", DbType.String),
            new SQLiteTypeNames("NUMERIC", DbType.Decimal),
            new SQLiteTypeNames("NVARCHAR", DbType.String),
            new SQLiteTypeNames("OLEOBJECT", DbType.Binary),
            new SQLiteTypeNames("REAL", DbType.Double),
            new SQLiteTypeNames("SMALLDATE", DbType.DateTime),
            new SQLiteTypeNames("SMALLINT", DbType.Int16),
            new SQLiteTypeNames("SMALLUINT", DbType.UInt16),
            new SQLiteTypeNames("STRING", DbType.String),
            new SQLiteTypeNames("TEXT", DbType.String),
            new SQLiteTypeNames("TIME", DbType.DateTime),
            new SQLiteTypeNames("TIMESTAMP", DbType.DateTime),
            new SQLiteTypeNames("TINYINT", DbType.Byte),
            new SQLiteTypeNames("TINYSINT", DbType.SByte),
            new SQLiteTypeNames("UINT", DbType.UInt32),
            new SQLiteTypeNames("UINT8", DbType.Byte),
            new SQLiteTypeNames("UINT16", DbType.UInt16),
            new SQLiteTypeNames("UINT32", DbType.UInt32),
            new SQLiteTypeNames("UINT64", DbType.UInt64),
            new SQLiteTypeNames("ULONG", DbType.UInt64),
            new SQLiteTypeNames("UNIQUEIDENTIFIER", DbType.Guid),
            new SQLiteTypeNames("UNSIGNEDINTEGER", DbType.UInt64),
            new SQLiteTypeNames("UNSIGNEDINTEGER8", DbType.Byte),
            new SQLiteTypeNames("UNSIGNEDINTEGER16", DbType.UInt16),
            new SQLiteTypeNames("UNSIGNEDINTEGER32", DbType.UInt32),
            new SQLiteTypeNames("UNSIGNEDINTEGER64", DbType.UInt64),
            new SQLiteTypeNames("VARBINARY", DbType.Binary),
            new SQLiteTypeNames("VARCHAR", DbType.AnsiString),
            new SQLiteTypeNames("YESNO", DbType.Boolean)
        };
    }

    /// <summary>
    /// For a given type name, return a closest-match .NET type
    /// </summary>
    /// <param name="Name">The name of the type to match</param>
    /// <returns>The .NET DBType the text evaluates to.</returns>
    internal static DbType TypeNameToDbType(string Name)
    {
      lock (_syncRoot)
      {
        if (_typeNames == null)
        {
          _typeNames = new Dictionary<string, SQLiteTypeNames>(
              new TypeNameStringComparer());

          foreach (SQLiteTypeNames typeName in GetSQLiteTypeNames())
















































            _typeNames.Add(typeName.typeName, typeName);

        }
      }

      if (String.IsNullOrEmpty(Name)) return DbType.Object;

      SQLiteTypeNames value;

1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
  /// and JulianDay.
  /// </summary>
  /// <remarks>
  /// ISO8601 is more compatible, readable, fully-processable, but less accurate as it doesn't provide time down to fractions of a second.
  /// JulianDay is the numeric format the SQLite uses internally and is arguably the most compatible with 3rd party tools.  It is
  /// not readable as text without post-processing.
  /// Ticks less compatible with 3rd party tools that query the database, and renders the DateTime field unreadable as text without post-processing.
  /// 
  /// The preferred order of choosing a datetime format is JulianDay, ISO8601, and then Ticks.  Ticks is mainly present for legacy 
  /// code support.
  /// </remarks>
  public enum SQLiteDateFormats
  {
    /// <summary>
    /// Use the value of DateTime.Ticks.  This value is not recommended and is not well supported with LINQ.
    /// </summary>







|
|







1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
  /// and JulianDay.
  /// </summary>
  /// <remarks>
  /// ISO8601 is more compatible, readable, fully-processable, but less accurate as it doesn't provide time down to fractions of a second.
  /// JulianDay is the numeric format the SQLite uses internally and is arguably the most compatible with 3rd party tools.  It is
  /// not readable as text without post-processing.
  /// Ticks less compatible with 3rd party tools that query the database, and renders the DateTime field unreadable as text without post-processing.
  ///
  /// The preferred order of choosing a datetime format is JulianDay, ISO8601, and then Ticks.  Ticks is mainly present for legacy
  /// code support.
  /// </remarks>
  public enum SQLiteDateFormats
  {
    /// <summary>
    /// Use the value of DateTime.Ticks.  This value is not recommended and is not well supported with LINQ.
    /// </summary>
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
  /// <summary>
  /// This enum determines how SQLite treats its journal file.
  /// </summary>
  /// <remarks>
  /// By default SQLite will create and delete the journal file when needed during a transaction.
  /// However, for some computers running certain filesystem monitoring tools, the rapid
  /// creation and deletion of the journal file can cause those programs to fail, or to interfere with SQLite.
  /// 
  /// If a program or virus scanner is interfering with SQLite's journal file, you may receive errors like "unable to open database file"
  /// when starting a transaction.  If this is happening, you may want to change the default journal mode to Persist.
  /// </remarks>
  public enum SQLiteJournalModeEnum
  {
    /// <summary>
    /// The default mode, this causes SQLite to use the existing journaling mode for the database.







|







1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
  /// <summary>
  /// This enum determines how SQLite treats its journal file.
  /// </summary>
  /// <remarks>
  /// By default SQLite will create and delete the journal file when needed during a transaction.
  /// However, for some computers running certain filesystem monitoring tools, the rapid
  /// creation and deletion of the journal file can cause those programs to fail, or to interfere with SQLite.
  ///
  /// If a program or virus scanner is interfering with SQLite's journal file, you may receive errors like "unable to open database file"
  /// when starting a transaction.  If this is happening, you may want to change the default journal mode to Persist.
  /// </remarks>
  public enum SQLiteJournalModeEnum
  {
    /// <summary>
    /// The default mode, this causes SQLite to use the existing journaling mode for the database.
1180
1181
1182
1183
1184
1185
1186






































1187
1188
1189
1190
1191
1192
1193
      /// all content is safely written to the disk surface prior to continuing.
      /// This ensures that an operating system crash or power failure will not
      /// corrupt the database.  FULL synchronous is very safe, but it is also
      /// slower.
      /// </summary>
      Full = 2
  }







































  /// <summary>
  /// Struct used internally to determine the datatype of a column in a resultset
  /// </summary>
  internal class SQLiteType
  {
    /// <summary>







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







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
      /// all content is safely written to the disk surface prior to continuing.
      /// This ensures that an operating system crash or power failure will not
      /// corrupt the database.  FULL synchronous is very safe, but it is also
      /// slower.
      /// </summary>
      Full = 2
  }

  /// <summary>
  /// The requested command execution type.  This controls which method of the
  /// <see cref="SQLiteCommand" /> object will be called.
  /// </summary>
  public enum SQLiteExecuteType
  {
      /// <summary>
      /// Do nothing.  No method will be called.
      /// </summary>
      None = 0,

      /// <summary>
      /// The command is not expected to return a result -OR- the result is not
      /// needed.  The <see cref="SQLiteCommand.ExecuteNonQuery" /> method will
      /// be called.
      /// </summary>
      NonQuery = 1,

      /// <summary>
      /// The command is expected to return a scalar result -OR- the result should
      /// be limited to a scalar result.  The <see cref="SQLiteCommand.ExecuteScalar" />
      /// method will be called.
      /// </summary>
      Scalar = 2,

      /// <summary>
      /// The command is expected to return <see cref="SQLiteDataReader"/> result.
      /// The <see cref="SQLiteCommand.ExecuteReader()" /> method will be called.
      /// </summary>
      Reader = 3,

      /// <summary>
      /// Use the default command execution type.  Using this value is the same
      /// as using the <see cref="SQLiteExecuteType.None" /> value.
      /// </summary>
      Default = NonQuery /* TODO: Good default? */
  }

  /// <summary>
  /// Struct used internally to determine the datatype of a column in a resultset
  /// </summary>
  internal class SQLiteType
  {
    /// <summary>
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242

    public int GetHashCode(
      string value
      )
    {
      //
      // NOTE: The only thing that we must guarantee here, according
      //       to the MSDN documentation for IEqualityComparer, is 
      //       that for two given strings, if Equals return true then 
      //       the two strings must hash to the same value.
      //
      if (value != null)
#if !PLATFORM_COMPACTFRAMEWORK
        return value.ToLowerInvariant().GetHashCode();
#else
        return value.ToLower().GetHashCode();







|
|







1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299

    public int GetHashCode(
      string value
      )
    {
      //
      // NOTE: The only thing that we must guarantee here, according
      //       to the MSDN documentation for IEqualityComparer, is
      //       that for two given strings, if Equals return true then
      //       the two strings must hash to the same value.
      //
      if (value != null)
#if !PLATFORM_COMPACTFRAMEWORK
        return value.ToLowerInvariant().GetHashCode();
#else
        return value.ToLower().GetHashCode();
Changes to System.Data.SQLite/SQLiteDataAdapter.cs.
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
  [Designer("Microsoft.VSDesigner.Data.VS.SqlDataAdapterDesigner, Microsoft.VSDesigner, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
#endif
  public sealed class SQLiteDataAdapter : DbDataAdapter
  {
    private static object _updatingEventPH = new object();
    private static object _updatedEventPH = new object();




    /// <overloads>
    /// This class is just a shell around the DbDataAdapter.  Nothing from DbDataAdapter is overridden here, just a few constructors are defined.

    /// </overloads>
    /// <summary>
    /// Default constructor.
    /// </summary>
    public SQLiteDataAdapter()
    {
    }



    /// <summary>
    /// Constructs a data adapter using the specified select command.
    /// </summary>

    /// <param name="cmd">The select command to associate with the adapter.</param>

    public SQLiteDataAdapter(SQLiteCommand cmd)
    {
      SelectCommand = cmd;
    }



    /// <summary>
    /// Constructs a data adapter with the supplied select command text and associated with the specified connection.

    /// </summary>

    /// <param name="commandText">The select command text to associate with the data adapter.</param>

    /// <param name="connection">The connection to associate with the select command.</param>


    public SQLiteDataAdapter(string commandText, SQLiteConnection connection)
    {
      SelectCommand = new SQLiteCommand(commandText, connection);
    }



    /// <summary>
    /// Constructs a data adapter with the specified select command text, and using the specified database connection string.

    /// </summary>

    /// <param name="commandText">The select command text to use to construct a select command.</param>


    /// <param name="connectionString">A connection string suitable for passing to a new SQLiteConnection, which is associated with the select command.</param>


    public SQLiteDataAdapter(string commandText, string connectionString)




    {


























      SQLiteConnection cnn = new SQLiteConnection(connectionString);


      SelectCommand = new SQLiteCommand(commandText, cnn);
    }


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

    #region IDisposable "Pattern" Members
    private bool disposed;
    private void CheckDisposed() /* throw */
    {







>
>
>

|
>








>
>



>
|
>





>
>

|
>

>
|
>
|
>
>





>
>

|
>

>
|
>
>
|
>
>
|
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>


>







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
  [Designer("Microsoft.VSDesigner.Data.VS.SqlDataAdapterDesigner, Microsoft.VSDesigner, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
#endif
  public sealed class SQLiteDataAdapter : DbDataAdapter
  {
    private static object _updatingEventPH = new object();
    private static object _updatedEventPH = new object();

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

    #region Public Constructors
    /// <overloads>
    /// This class is just a shell around the DbDataAdapter.  Nothing from
    /// DbDataAdapter is overridden here, just a few constructors are defined.
    /// </overloads>
    /// <summary>
    /// Default constructor.
    /// </summary>
    public SQLiteDataAdapter()
    {
    }

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

    /// <summary>
    /// Constructs a data adapter using the specified select command.
    /// </summary>
    /// <param name="cmd">
    /// The select command to associate with the adapter.
    /// </param>
    public SQLiteDataAdapter(SQLiteCommand cmd)
    {
      SelectCommand = cmd;
    }

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

    /// <summary>
    /// Constructs a data adapter with the supplied select command text and
    /// associated with the specified connection.
    /// </summary>
    /// <param name="commandText">
    /// The select command text to associate with the data adapter.
    /// </param>
    /// <param name="connection">
    /// The connection to associate with the select command.
    /// </param>
    public SQLiteDataAdapter(string commandText, SQLiteConnection connection)
    {
      SelectCommand = new SQLiteCommand(commandText, connection);
    }

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

    /// <summary>
    /// Constructs a data adapter with the specified select command text,
    /// and using the specified database connection string.
    /// </summary>
    /// <param name="commandText">
    /// The select command text to use to construct a select command.
    /// </param>
    /// <param name="connectionString">
    /// A connection string suitable for passing to a new SQLiteConnection,
    /// which is associated with the select command.
    /// </param>
    public SQLiteDataAdapter(
        string commandText,
        string connectionString
        )
        : this(commandText, connectionString, false)
    {
        // do nothing.
    }

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

    /// <summary>
    /// Constructs a data adapter with the specified select command text,
    /// and using the specified database connection string.
    /// </summary>
    /// <param name="commandText">
    /// The select command text to use to construct a select command.
    /// </param>
    /// <param name="connectionString">
    /// A connection string suitable for passing to a new SQLiteConnection,
    /// which is associated with the select command.
    /// </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 SQLiteDataAdapter(
        string commandText,
        string connectionString,
        bool parseViaFramework
        )
    {
      SQLiteConnection cnn = new SQLiteConnection(
          connectionString, parseViaFramework);

      SelectCommand = new SQLiteCommand(commandText, cnn);
    }
    #endregion

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

    #region IDisposable "Pattern" Members
    private bool disposed;
    private void CheckDisposed() /* throw */
    {
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)
                //{

                //    ////////////////////////////////////
                //    // dispose managed resources here...
                //    ////////////////////////////////////
                //}

























                //////////////////////////////////////
                // release unmanaged resources here...
                //////////////////////////////////////

                disposed = true;
            }







|
<
>
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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

    protected override void Dispose(bool disposing)
    {
        try
        {
            if (!disposed)
            {
                if (disposing)

                {
                    ////////////////////////////////////
                    // 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/SQLiteDataReader.cs.
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
    /// </summary>
    /// <param name="name">The name of the column to retrieve</param>
    /// <returns>The int i of the column</returns>
    public override int GetOrdinal(string name)
    {
      CheckDisposed();
      CheckClosed();
      SQLiteCommand.Check(_command);

      //
      // NOTE: First, check if the column name cache has been initialized yet.
      //       If not, do it now.
      //
      if (_fieldIndexes == null)
          _fieldIndexes = new Dictionary<string, int>(new ColumnNameComparer());







|







642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
    /// </summary>
    /// <param name="name">The name of the column to retrieve</param>
    /// <returns>The int i of the column</returns>
    public override int GetOrdinal(string name)
    {
      CheckDisposed();
      CheckClosed();
      if (_throwOnDisposed) SQLiteCommand.Check(_command);

      //
      // NOTE: First, check if the column name cache has been initialized yet.
      //       If not, do it now.
      //
      if (_fieldIndexes == null)
          _fieldIndexes = new Dictionary<string, int>(new ColumnNameComparer());
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
            columnToParent.Add(n, value);
        }
    }

    internal DataTable GetSchemaTable(bool wantUniqueInfo, bool wantDefaultValue)
    {
      CheckClosed();
      SQLiteCommand.Check(_command);

     //
     // BUGFIX: We need to quickly scan all the fields in the current
     //         "result set" to see how many distinct tables are actually
     //         involved.  This information is necessary so that some
     //         intelligent decisions can be made when constructing the
     //         metadata below.  For example, we need to be very careful







|







850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
            columnToParent.Add(n, value);
        }
    }

    internal DataTable GetSchemaTable(bool wantUniqueInfo, bool wantDefaultValue)
    {
      CheckClosed();
      if (_throwOnDisposed) SQLiteCommand.Check(_command);

     //
     // BUGFIX: We need to quickly scan all the fields in the current
     //         "result set" to see how many distinct tables are actually
     //         involved.  This information is necessary so that some
     //         intelligent decisions can be made when constructing the
     //         metadata below.  For example, we need to be very careful
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
    /// Moves to the next resultset in multiple row-returning SQL command.
    /// </summary>
    /// <returns>True if the command was successful and a new resultset is available, False otherwise.</returns>
    public override bool NextResult()
    {
      CheckDisposed();
      CheckClosed();
      SQLiteCommand.Check(_command);

      SQLiteStatement stmt = null;
      int fieldCount;

      while (true)
      {
        if (stmt == null && _activeStatement != null && _activeStatement._sql != null && _activeStatement._sql.IsOpen())







|







1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
    /// Moves to the next resultset in multiple row-returning SQL command.
    /// </summary>
    /// <returns>True if the command was successful and a new resultset is available, False otherwise.</returns>
    public override bool NextResult()
    {
      CheckDisposed();
      CheckClosed();
      if (_throwOnDisposed) SQLiteCommand.Check(_command);

      SQLiteStatement stmt = null;
      int fieldCount;

      while (true)
      {
        if (stmt == null && _activeStatement != null && _activeStatement._sql != null && _activeStatement._sql.IsOpen())
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
    /// Reads the next row from the resultset
    /// </summary>
    /// <returns>True if a new row was successfully loaded and is ready for processing</returns>
    public override bool Read()
    {
      CheckDisposed();
      CheckClosed();
      SQLiteCommand.Check(_command);

      if (_readingState == -1) // First step was already done at the NextResult() level, so don't step again, just return true.
      {
        _readingState = 0;
        return true;
      }
      else if (_readingState == 0) // Actively reading rows







|







1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
    /// Reads the next row from the resultset
    /// </summary>
    /// <returns>True if a new row was successfully loaded and is ready for processing</returns>
    public override bool Read()
    {
      CheckDisposed();
      CheckClosed();
      if (_throwOnDisposed) SQLiteCommand.Check(_command);

      if (_readingState == -1) // First step was already done at the NextResult() level, so don't step again, just return true.
      {
        _readingState = 0;
        return true;
      }
      else if (_readingState == 0) // Actively reading rows
Changes to System.Data.SQLite/SQLiteDefineConstants.cs.
31
32
33
34
35
36
37




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

#if INTEROP_EXTENSION_FUNCTIONS
            "INTEROP_EXTENSION_FUNCTIONS",
#endif





#if INTEROP_LOG
            "INTEROP_LOG",
#endif

#if INTEROP_TEST_EXTENSION
            "INTEROP_TEST_EXTENSION",







>
>
>
>







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

#if INTEROP_EXTENSION_FUNCTIONS
            "INTEROP_EXTENSION_FUNCTIONS",
#endif

#if INTEROP_LEGACY_CLOSE
            "INTEROP_LEGACY_CLOSE",
#endif

#if INTEROP_LOG
            "INTEROP_LOG",
#endif

#if INTEROP_TEST_EXTENSION
            "INTEROP_TEST_EXTENSION",
Changes to System.Data.SQLite/SQLiteException.cs.
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;



|







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
    private static string GetStockErrorMessage(
        SQLiteErrorCode errorCode,
        string message
        )
    {
        return String.Format("{0}{1}{2}",
            GetErrorString(errorCode),

            Environment.NewLine, message).Trim();



    }
  }

  /// <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







>

>
>
>







180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
    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/SQLiteFunction.cs.
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
/********************************************************
 * 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.Collections.Generic;
  using System.Runtime.InteropServices;
  using System.Globalization;

  /// <summary>
  /// This abstract class is designed to handle user-defined functions easily.  An instance of the derived class is made for each
  /// connection to the database.
  /// </summary>
  /// <remarks>
  /// Although there is one instance of a class derived from SQLiteFunction per database connection, the derived class has no access
  /// to the underlying connection.  This is necessary to deter implementers from thinking it would be a good idea to make database
  /// calls during processing.
  /// 
  /// It is important to distinguish between a per-connection instance, and a per-SQL statement context.  One instance of this class
  /// services all SQL statements being stepped through on that connection, and there can be many.  One should never store per-statement
  /// information in member variables of user-defined function classes.
  /// 
  /// For aggregate functions, always create and store your per-statement data in the contextData object on the 1st step.  This data will
  /// be automatically freed for you (and Dispose() called if the item supports IDisposable) when the statement completes.
  /// </remarks>
  public abstract class SQLiteFunction : IDisposable
  {
    private class AggregateData
    {



|


















|



|







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
/********************************************************
 * 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.Collections.Generic;
  using System.Runtime.InteropServices;
  using System.Globalization;

  /// <summary>
  /// This abstract class is designed to handle user-defined functions easily.  An instance of the derived class is made for each
  /// connection to the database.
  /// </summary>
  /// <remarks>
  /// Although there is one instance of a class derived from SQLiteFunction per database connection, the derived class has no access
  /// to the underlying connection.  This is necessary to deter implementers from thinking it would be a good idea to make database
  /// calls during processing.
  ///
  /// It is important to distinguish between a per-connection instance, and a per-SQL statement context.  One instance of this class
  /// services all SQL statements being stepped through on that connection, and there can be many.  One should never store per-statement
  /// information in member variables of user-defined function classes.
  ///
  /// For aggregate functions, always create and store your per-statement data in the contextData object on the 1st step.  This data will
  /// be automatically freed for you (and Dispose() called if the item supports IDisposable) when the statement completes.
  /// </remarks>
  public abstract class SQLiteFunction : IDisposable
  {
    private class AggregateData
    {
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
    {
        try
        {
            _context = context;
            SetReturnValue(context,
                Invoke(ConvertParams(nArgs, argsptr))); /* throw */
        }
#if !PLATFORM_COMPACTFRAMEWORK
        catch (Exception e) /* NOTE: Must catch ALL. */
        {
            try
            {
                if ((_flags & SQLiteConnectionFlags.LogCallbackException) ==
                        SQLiteConnectionFlags.LogCallbackException)
                {
                    SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format(
                        CultureInfo.CurrentCulture,
                        "Caught exception in \"Invoke\" method: {0}",
                        e)); /* throw */
                }
            }
            catch
            {
                // do nothing.
            }
        }
#else
        catch /* NOTE: Must catch ALL. */
        {
            // do nothing (Windows CE).
        }
#endif
    }

    /// <summary>
    /// Internal collation sequence function, which wraps up the raw string pointers and executes the Compare() virtual function.
    /// WARNING: Must not throw exceptions.
    /// </summary>
    /// <param name="ptr">Not used</param>
    /// <param name="len1">Length of the string pv1</param>
    /// <param name="ptr1">Pointer to the first string to compare</param>
    /// <param name="len2">Length of the string pv2</param>
    /// <param name="ptr2">Pointer to the second string to compare</param>
    /// <returns>Returns -1 if the first string is less than the second.  0 if they are equal, or 1 if the first string is greater
    /// than the second.  Returns 0 if an exception is caught.</returns>
    internal int CompareCallback(IntPtr ptr, int len1, IntPtr ptr1, int len2, IntPtr ptr2)
    {
        try
        {
            return Compare(SQLiteConvert.UTF8ToString(ptr1, len1),
                SQLiteConvert.UTF8ToString(ptr2, len2)); /* throw */
        }
#if !PLATFORM_COMPACTFRAMEWORK
        catch (Exception e) /* NOTE: Must catch ALL. */
        {
            try
            {
                if ((_flags & SQLiteConnectionFlags.LogCallbackException) ==
                        SQLiteConnectionFlags.LogCallbackException)
                {
                    SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format(
                        CultureInfo.CurrentCulture,
                        "Caught exception in \"Compare\" (UTF8) method: {0}",
                        e)); /* throw */
                }
            }
            catch
            {
                // do nothing.
            }
        }
#else
        catch /* NOTE: Must catch ALL. */
        {
            // do nothing (Windows CE).
        }
#endif

        //
        // NOTE: This must be done to prevent the core SQLite library from
        //       using our (invalid) result.
        //
        if (_base != null)
            _base.Cancel();







<


















<
<
<
<
<
<




















<


















<
<
<
<
<
<







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
    {
        try
        {
            _context = context;
            SetReturnValue(context,
                Invoke(ConvertParams(nArgs, argsptr))); /* throw */
        }

        catch (Exception e) /* NOTE: Must catch ALL. */
        {
            try
            {
                if ((_flags & SQLiteConnectionFlags.LogCallbackException) ==
                        SQLiteConnectionFlags.LogCallbackException)
                {
                    SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format(
                        CultureInfo.CurrentCulture,
                        "Caught exception in \"Invoke\" method: {0}",
                        e)); /* throw */
                }
            }
            catch
            {
                // do nothing.
            }
        }






    }

    /// <summary>
    /// Internal collation sequence function, which wraps up the raw string pointers and executes the Compare() virtual function.
    /// WARNING: Must not throw exceptions.
    /// </summary>
    /// <param name="ptr">Not used</param>
    /// <param name="len1">Length of the string pv1</param>
    /// <param name="ptr1">Pointer to the first string to compare</param>
    /// <param name="len2">Length of the string pv2</param>
    /// <param name="ptr2">Pointer to the second string to compare</param>
    /// <returns>Returns -1 if the first string is less than the second.  0 if they are equal, or 1 if the first string is greater
    /// than the second.  Returns 0 if an exception is caught.</returns>
    internal int CompareCallback(IntPtr ptr, int len1, IntPtr ptr1, int len2, IntPtr ptr2)
    {
        try
        {
            return Compare(SQLiteConvert.UTF8ToString(ptr1, len1),
                SQLiteConvert.UTF8ToString(ptr2, len2)); /* throw */
        }

        catch (Exception e) /* NOTE: Must catch ALL. */
        {
            try
            {
                if ((_flags & SQLiteConnectionFlags.LogCallbackException) ==
                        SQLiteConnectionFlags.LogCallbackException)
                {
                    SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format(
                        CultureInfo.CurrentCulture,
                        "Caught exception in \"Compare\" (UTF8) method: {0}",
                        e)); /* throw */
                }
            }
            catch
            {
                // do nothing.
            }
        }







        //
        // NOTE: This must be done to prevent the core SQLite library from
        //       using our (invalid) result.
        //
        if (_base != null)
            _base.Cancel();
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
    internal int CompareCallback16(IntPtr ptr, int len1, IntPtr ptr1, int len2, IntPtr ptr2)
    {
        try
        {
            return Compare(SQLite3_UTF16.UTF16ToString(ptr1, len1),
                SQLite3_UTF16.UTF16ToString(ptr2, len2)); /* throw */
        }
#if !PLATFORM_COMPACTFRAMEWORK
        catch (Exception e) /* NOTE: Must catch ALL. */
        {
            try
            {
                if ((_flags & SQLiteConnectionFlags.LogCallbackException) ==
                        SQLiteConnectionFlags.LogCallbackException)
                {
                    SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format(
                        CultureInfo.CurrentCulture,
                        "Caught exception in \"Compare\" (UTF16) method: {0}",
                        e)); /* throw */
                }
            }
            catch
            {
                // do nothing.
            }
        }
#else
        catch /* NOTE: Must catch ALL. */
        {
            // do nothing (Windows CE).
        }
#endif

        //
        // NOTE: This must be done to prevent the core SQLite library from
        //       using our (invalid) result.
        //
        if (_base != null)
            _base.Cancel();







<


















<
<
<
<
<
<







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
    internal int CompareCallback16(IntPtr ptr, int len1, IntPtr ptr1, int len2, IntPtr ptr2)
    {
        try
        {
            return Compare(SQLite3_UTF16.UTF16ToString(ptr1, len1),
                SQLite3_UTF16.UTF16ToString(ptr2, len2)); /* throw */
        }

        catch (Exception e) /* NOTE: Must catch ALL. */
        {
            try
            {
                if ((_flags & SQLiteConnectionFlags.LogCallbackException) ==
                        SQLiteConnectionFlags.LogCallbackException)
                {
                    SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format(
                        CultureInfo.CurrentCulture,
                        "Caught exception in \"Compare\" (UTF16) method: {0}",
                        e)); /* throw */
                }
            }
            catch
            {
                // do nothing.
            }
        }







        //
        // NOTE: This must be done to prevent the core SQLite library from
        //       using our (invalid) result.
        //
        if (_base != null)
            _base.Cancel();
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
                    data._count, ref data._data); /* throw */
            }
            finally
            {
                data._count++;
            }
        }
#if !PLATFORM_COMPACTFRAMEWORK
        catch (Exception e) /* NOTE: Must catch ALL. */
        {
            try
            {
                if ((_flags & SQLiteConnectionFlags.LogCallbackException) ==
                        SQLiteConnectionFlags.LogCallbackException)
                {
                    SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format(
                        CultureInfo.CurrentCulture,
                        "Caught exception in \"Step\" method: {1}",
                        e)); /* throw */
                }
            }
            catch
            {
                // do nothing.
            }
        }
#else
        catch /* NOTE: Must catch ALL. */
        {
            // do nothing (Windows CE).
        }
#endif
    }

    /// <summary>
    /// An internal aggregate Final function callback, which wraps the context pointer and calls the virtual Final() method.
    /// WARNING: Must not throw exceptions.
    /// </summary>
    /// <param name="context">A raw context pointer</param>







<


















<
<
<
<
<
<







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
                    data._count, ref data._data); /* throw */
            }
            finally
            {
                data._count++;
            }
        }

        catch (Exception e) /* NOTE: Must catch ALL. */
        {
            try
            {
                if ((_flags & SQLiteConnectionFlags.LogCallbackException) ==
                        SQLiteConnectionFlags.LogCallbackException)
                {
                    SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format(
                        CultureInfo.CurrentCulture,
                        "Caught exception in \"Step\" method: {1}",
                        e)); /* throw */
                }
            }
            catch
            {
                // do nothing.
            }
        }






    }

    /// <summary>
    /// An internal aggregate Final function callback, which wraps the context pointer and calls the virtual Final() method.
    /// WARNING: Must not throw exceptions.
    /// </summary>
    /// <param name="context">A raw context pointer</param>
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
            }
            finally
            {
                IDisposable disp = obj as IDisposable;
                if (disp != null) disp.Dispose(); /* throw */
            }
        }
#if !PLATFORM_COMPACTFRAMEWORK
        catch (Exception e) /* NOTE: Must catch ALL. */
        {
            try
            {
                if ((_flags & SQLiteConnectionFlags.LogCallbackException) ==
                        SQLiteConnectionFlags.LogCallbackException)
                {
                    SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format(
                        CultureInfo.CurrentCulture,
                        "Caught exception in \"Final\" method: {1}",
                        e)); /* throw */
                }
            }
            catch
            {
                // do nothing.
            }
        }
#else
        catch /* NOTE: Must catch ALL. */
        {
            // do nothing (Windows CE).
        }
#endif
    }

    /// <summary>
    /// Using reflection, enumerate all assemblies in the current appdomain looking for classes that
    /// have a SQLiteFunctionAttribute attribute, and registering them accordingly.
    /// </summary>
#if !PLATFORM_COMPACTFRAMEWORK
    [Security.Permissions.FileIOPermission(Security.Permissions.SecurityAction.Assert, AllFiles = Security.Permissions.FileIOPermissionAccess.PathDiscovery)]
#endif
    static SQLiteFunction()
    {
      _registeredFunctions = new List<SQLiteFunctionAttribute>();
      try
      {
#if !PLATFORM_COMPACTFRAMEWORK







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

        for (int n = 0; n < w; n++)
        {







<


















<
<
<
<
<
<















>
>
>
>
>
>
>







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
            }
            finally
            {
                IDisposable disp = obj as IDisposable;
                if (disp != null) disp.Dispose(); /* throw */
            }
        }

        catch (Exception e) /* NOTE: Must catch ALL. */
        {
            try
            {
                if ((_flags & SQLiteConnectionFlags.LogCallbackException) ==
                        SQLiteConnectionFlags.LogCallbackException)
                {
                    SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format(
                        CultureInfo.CurrentCulture,
                        "Caught exception in \"Final\" method: {1}",
                        e)); /* throw */
                }
            }
            catch
            {
                // do nothing.
            }
        }






    }

    /// <summary>
    /// Using reflection, enumerate all assemblies in the current appdomain looking for classes that
    /// have a SQLiteFunctionAttribute attribute, and registering them accordingly.
    /// </summary>
#if !PLATFORM_COMPACTFRAMEWORK
    [Security.Permissions.FileIOPermission(Security.Permissions.SecurityAction.Assert, AllFiles = Security.Permissions.FileIOPermissionAccess.PathDiscovery)]
#endif
    static SQLiteFunction()
    {
      _registeredFunctions = new List<SQLiteFunctionAttribute>();
      try
      {
#if !PLATFORM_COMPACTFRAMEWORK
        //
        // NOTE: If the "No_SQLiteFunctions" environment variable is set,
        //       skip all our special code and simply return.
        //
        if (Environment.GetEnvironmentVariable("No_SQLiteFunctions") != null)
          return;

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

        for (int n = 0; n < w; n++)
        {
Changes to System.Data.SQLite/SQLiteLog.cs.
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
157

158
159
160
161
162
163
164
    /// </summary>
    /// <param name="sender">The current connection</param>
    /// <param name="e">Event arguments of the trace</param>
    public delegate void SQLiteLogEventHandler(object sender, LogEventArgs e);

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

#if !PLATFORM_COMPACTFRAMEWORK
    /// <summary>
    /// Manages the SQLite custom logging functionality and the associated
    /// callback for the whole process.
    /// </summary>
    public static class SQLiteLog
    {
        /// <summary>
        /// Object used to synchronize access to the static instance data
        /// for this class.
        /// </summary>
        private static object syncRoot = new object();




        /// <summary>
        /// Member variable to store the AppDomain.DomainUnload event handler.
        /// </summary>
        private static EventHandler _domainUnload;




        /// <summary>
        /// Member variable to store the application log handler to call.
        /// </summary>
        private static event SQLiteLogEventHandler _handlers;




        /// <summary>
        /// The default log event handler.
        /// </summary>
        private static SQLiteLogEventHandler _defaultHandler;



        /// <summary>
        /// The log callback passed to native SQLite engine.  This must live
        /// as long as the SQLite library has a pointer to it.
        /// </summary>
        private static SQLiteLogCallback _callback;



        /// <summary>
        /// The base SQLite object to interop with.
        /// </summary>
        private static SQLiteBase _sql;



        /// <summary>
        /// This will be non-zero if logging is currently enabled.
        /// </summary>
        private static bool _enabled;



        /// <summary>
        /// Initializes the SQLite logging facilities.
        /// </summary>
        public static void Initialize()
        {
            //
            // BUFXIX: We cannot initialize the logging interface if the SQLite
            //         core library has already been initialized anywhere in
            //         the process (see ticket [2ce0870fad]).
            //
            if (SQLite3.StaticIsInitialized())
                return;


            //
            // BUGFIX: To avoid nasty situations where multiple AppDomains are
            //         attempting to initialize and/or shutdown what is really
            //         a shared native resource (i.e. the SQLite core library
            //         is loaded per-process and has only one logging callback,
            //         not one per-AppDomain, which it knows nothing about),
            //         prevent all non-default AppDomains from registering a
            //         log handler unless the "Force_SQLiteLog" environment
            //         variable is used to manually override this safety check.
            //
            if (!AppDomain.CurrentDomain.IsDefaultAppDomain() &&
                Environment.GetEnvironmentVariable("Force_SQLiteLog") == null)
            {
                return;
            }


            lock (syncRoot)
            {

                //
                // NOTE: Add an event handler for the DomainUnload event so
                //       that we can unhook our logging managed function
                //       pointer from the native SQLite code prior to it
                //       being invalidated.
                //
                // BUGFIX: Make sure this event handler is only added one
                //         time (per-AppDomain).
                //
                if (_domainUnload == null)
                {
                    _domainUnload = new EventHandler(DomainUnload);
                    AppDomain.CurrentDomain.DomainUnload += _domainUnload;
                }


                //
                // NOTE: Create an instance of the SQLite wrapper class.
                //
                if (_sql == null)
                    _sql = new SQLite3(SQLiteDateFormats.Default,
                        DateTimeKind.Unspecified);







<












>
>
>




>
>
>






>
>
>




>
>







>
>





>
>




>
>














>















>



>














>







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
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
    /// </summary>
    /// <param name="sender">The current connection</param>
    /// <param name="e">Event arguments of the trace</param>
    public delegate void SQLiteLogEventHandler(object sender, LogEventArgs e);

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


    /// <summary>
    /// Manages the SQLite custom logging functionality and the associated
    /// callback for the whole process.
    /// </summary>
    public static class SQLiteLog
    {
        /// <summary>
        /// Object used to synchronize access to the static instance data
        /// for this class.
        /// </summary>
        private static object syncRoot = new object();

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

#if !PLATFORM_COMPACTFRAMEWORK
        /// <summary>
        /// Member variable to store the AppDomain.DomainUnload event handler.
        /// </summary>
        private static EventHandler _domainUnload;
#endif

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

        /// <summary>
        /// Member variable to store the application log handler to call.
        /// </summary>
        private static event SQLiteLogEventHandler _handlers;


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

        /// <summary>
        /// The default log event handler.
        /// </summary>
        private static SQLiteLogEventHandler _defaultHandler;

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

        /// <summary>
        /// The log callback passed to native SQLite engine.  This must live
        /// as long as the SQLite library has a pointer to it.
        /// </summary>
        private static SQLiteLogCallback _callback;

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

        /// <summary>
        /// The base SQLite object to interop with.
        /// </summary>
        private static SQLiteBase _sql;

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

        /// <summary>
        /// This will be non-zero if logging is currently enabled.
        /// </summary>
        private static bool _enabled;

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

        /// <summary>
        /// Initializes the SQLite logging facilities.
        /// </summary>
        public static void Initialize()
        {
            //
            // BUFXIX: We cannot initialize the logging interface if the SQLite
            //         core library has already been initialized anywhere in
            //         the process (see ticket [2ce0870fad]).
            //
            if (SQLite3.StaticIsInitialized())
                return;

#if !PLATFORM_COMPACTFRAMEWORK
            //
            // BUGFIX: To avoid nasty situations where multiple AppDomains are
            //         attempting to initialize and/or shutdown what is really
            //         a shared native resource (i.e. the SQLite core library
            //         is loaded per-process and has only one logging callback,
            //         not one per-AppDomain, which it knows nothing about),
            //         prevent all non-default AppDomains from registering a
            //         log handler unless the "Force_SQLiteLog" environment
            //         variable is used to manually override this safety check.
            //
            if (!AppDomain.CurrentDomain.IsDefaultAppDomain() &&
                Environment.GetEnvironmentVariable("Force_SQLiteLog") == null)
            {
                return;
            }
#endif

            lock (syncRoot)
            {
#if !PLATFORM_COMPACTFRAMEWORK
                //
                // NOTE: Add an event handler for the DomainUnload event so
                //       that we can unhook our logging managed function
                //       pointer from the native SQLite code prior to it
                //       being invalidated.
                //
                // BUGFIX: Make sure this event handler is only added one
                //         time (per-AppDomain).
                //
                if (_domainUnload == null)
                {
                    _domainUnload = new EventHandler(DomainUnload);
                    AppDomain.CurrentDomain.DomainUnload += _domainUnload;
                }
#endif

                //
                // NOTE: Create an instance of the SQLite wrapper class.
                //
                if (_sql == null)
                    _sql = new SQLite3(SQLiteDateFormats.Default,
                        DateTimeKind.Unspecified);
188
189
190
191
192
193
194



195
196
197
198
199
200
201
                //
                // NOTE: For now, always setup the default log event handler.
                //
                AddDefaultHandler();
            }
        }




        /// <summary>
        /// Handles the AppDomain being unloaded.
        /// </summary>
        /// <param name="sender">Should be null.</param>
        /// <param name="e">The data associated with this event.</param>
        private static void DomainUnload(
            object sender,







>
>
>







208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
                //
                // NOTE: For now, always setup the default log event handler.
                //
                AddDefaultHandler();
            }
        }

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

#if !PLATFORM_COMPACTFRAMEWORK
        /// <summary>
        /// Handles the AppDomain being unloaded.
        /// </summary>
        /// <param name="sender">Should be null.</param>
        /// <param name="e">The data associated with this event.</param>
        private static void DomainUnload(
            object sender,
254
255
256
257
258
259
260



261
262
263
264
265
266
267
                if (_domainUnload != null)
                {
                    AppDomain.CurrentDomain.DomainUnload -= _domainUnload;
                    _domainUnload = null;
                }
            }
        }




        /// <summary>
        /// This event is raised whenever SQLite raises a logging event.
        /// Note that this should be set as one of the first things in the
        /// application.
        /// </summary>
        public static event SQLiteLogEventHandler Log







>
>
>







277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
                if (_domainUnload != null)
                {
                    AppDomain.CurrentDomain.DomainUnload -= _domainUnload;
                    _domainUnload = null;
                }
            }
        }
#endif

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

        /// <summary>
        /// This event is raised whenever SQLite raises a logging event.
        /// Note that this should be set as one of the first things in the
        /// application.
        /// </summary>
        public static event SQLiteLogEventHandler Log
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
                lock (syncRoot)
                {
                    _handlers -= value;
                }
            }
        }



        /// <summary>
        /// If this property is true, logging is enabled; otherwise, logging is
        /// disabled.  When logging is disabled, no logging events will fire.
        /// </summary>
        public static bool Enabled
        {
            get { lock (syncRoot) { return _enabled; } }
            set { lock (syncRoot) { _enabled = value; } }
        }



        /// <summary>
        /// Log a message to all the registered log event handlers without going
        /// through the SQLite library.
        /// </summary>
        /// <param name="message">The message to be logged.</param>
        public static void LogMessage(
            string message
            )
        {
            LogMessage(null, message);
        }



        /// <summary>
        /// Log a message to all the registered log event handlers without going
        /// through the SQLite library.
        /// </summary>
        /// <param name="errorCode">The SQLite error code.</param>
        /// <param name="message">The message to be logged.</param>
        public static void LogMessage(
            SQLiteErrorCode errorCode,
            string message
            )
        {
            LogMessage((object)errorCode, message);
        }



        /// <summary>
        /// Log a message to all the registered log event handlers without going
        /// through the SQLite library.
        /// </summary>
        /// <param name="errorCode">The integer error code.</param>
        /// <param name="message">The message to be logged.</param>
        public static void LogMessage(
            int errorCode,
            string message
            )
        {
            LogMessage((object)errorCode, message);
        }



        /// <summary>
        /// Log a message to all the registered log event handlers without going
        /// through the SQLite library.
        /// </summary>
        /// <param name="errorCode">
        /// The error code.  The type of this object value should be







>
>









>
>












>
>















>
>













>
>







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
                lock (syncRoot)
                {
                    _handlers -= value;
                }
            }
        }

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

        /// <summary>
        /// If this property is true, logging is enabled; otherwise, logging is
        /// disabled.  When logging is disabled, no logging events will fire.
        /// </summary>
        public static bool Enabled
        {
            get { lock (syncRoot) { return _enabled; } }
            set { lock (syncRoot) { _enabled = value; } }
        }

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

        /// <summary>
        /// Log a message to all the registered log event handlers without going
        /// through the SQLite library.
        /// </summary>
        /// <param name="message">The message to be logged.</param>
        public static void LogMessage(
            string message
            )
        {
            LogMessage(null, message);
        }

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

        /// <summary>
        /// Log a message to all the registered log event handlers without going
        /// through the SQLite library.
        /// </summary>
        /// <param name="errorCode">The SQLite error code.</param>
        /// <param name="message">The message to be logged.</param>
        public static void LogMessage(
            SQLiteErrorCode errorCode,
            string message
            )
        {
            LogMessage((object)errorCode, message);
        }

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

        /// <summary>
        /// Log a message to all the registered log event handlers without going
        /// through the SQLite library.
        /// </summary>
        /// <param name="errorCode">The integer error code.</param>
        /// <param name="message">The message to be logged.</param>
        public static void LogMessage(
            int errorCode,
            string message
            )
        {
            LogMessage((object)errorCode, message);
        }

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

        /// <summary>
        /// Log a message to all the registered log event handlers without going
        /// through the SQLite library.
        /// </summary>
        /// <param name="errorCode">
        /// The error code.  The type of this object value should be
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
        {
            bool enabled;
            SQLiteLogEventHandler handlers;

            lock (syncRoot)
            {
                enabled = _enabled;




                handlers = _handlers;
            }

            if (enabled && (handlers != null))
                handlers(null, new LogEventArgs(
                    IntPtr.Zero, errorCode, message, null));
        }



        /// <summary>
        /// Creates and initializes the default log event handler.
        /// </summary>
        private static void InitializeDefaultHandler()
        {
            lock (syncRoot)
            {
                if (_defaultHandler == null)
                    _defaultHandler = new SQLiteLogEventHandler(LogEventHandler);
            }
        }



        /// <summary>
        /// Adds the default log event handler to the list of handlers.
        /// </summary>
        public static void AddDefaultHandler()
        {
            InitializeDefaultHandler();
            Log += _defaultHandler;
        }



        /// <summary>
        /// Removes the default log event handler from the list of handlers.
        /// </summary>
        public static void RemoveDefaultHandler()
        {
            InitializeDefaultHandler();
            Log -= _defaultHandler;
        }



        /// <summary>
        /// Internal proxy function that calls any registered application log
        /// event handlers.
        ///
        /// WARNING: This method is used more-or-less directly by native code,
        ///          do not modify its type signature.







>
>
>
>
|






>
>













>
>









>
>








>
>







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
        {
            bool enabled;
            SQLiteLogEventHandler handlers;

            lock (syncRoot)
            {
                enabled = _enabled;

                if (_handlers != null)
                    handlers = _handlers.Clone() as SQLiteLogEventHandler;
                else
                    handlers = null;
            }

            if (enabled && (handlers != null))
                handlers(null, new LogEventArgs(
                    IntPtr.Zero, errorCode, message, null));
        }

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

        /// <summary>
        /// Creates and initializes the default log event handler.
        /// </summary>
        private static void InitializeDefaultHandler()
        {
            lock (syncRoot)
            {
                if (_defaultHandler == null)
                    _defaultHandler = new SQLiteLogEventHandler(LogEventHandler);
            }
        }

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

        /// <summary>
        /// Adds the default log event handler to the list of handlers.
        /// </summary>
        public static void AddDefaultHandler()
        {
            InitializeDefaultHandler();
            Log += _defaultHandler;
        }

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

        /// <summary>
        /// Removes the default log event handler from the list of handlers.
        /// </summary>
        public static void RemoveDefaultHandler()
        {
            InitializeDefaultHandler();
            Log -= _defaultHandler;
        }

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

        /// <summary>
        /// Internal proxy function that calls any registered application log
        /// event handlers.
        ///
        /// WARNING: This method is used more-or-less directly by native code,
        ///          do not modify its type signature.
432
433
434
435
436
437
438


439
440
441
442
443
444
445
            }

            if (enabled && (handlers != null))
                handlers(null, new LogEventArgs(pUserData, errorCode,
                    SQLiteBase.UTF8ToString(pMessage, -1), null));
        }



        /// <summary>
        /// Default logger.  Currently, uses the Trace class (i.e. sends events
        /// to the current trace listeners, if any).
        /// </summary>
        /// <param name="sender">Should be null.</param>
        /// <param name="e">The data associated with this event.</param>
        private static void LogEventHandler(







>
>







480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
            }

            if (enabled && (handlers != null))
                handlers(null, new LogEventArgs(pUserData, errorCode,
                    SQLiteBase.UTF8ToString(pMessage, -1), null));
        }

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

        /// <summary>
        /// Default logger.  Currently, uses the Trace class (i.e. sends events
        /// to the current trace listeners, if any).
        /// </summary>
        /// <param name="sender">Should be null.</param>
        /// <param name="e">The data associated with this event.</param>
        private static void LogEventHandler(
472
473
474
475
476
477
478
479
480
            else if (errorCode is int)
                success = ((int)errorCode == 0);

            Trace.WriteLine(String.Format("SQLite {0} ({1}): {2}",
                success ? "message" : "error", errorCode, message));
        }
    }
#endif
}







<

522
523
524
525
526
527
528

529
            else if (errorCode is int)
                success = ((int)errorCode == 0);

            Trace.WriteLine(String.Format("SQLite {0} ({1}): {2}",
                success ? "message" : "error", errorCode, message));
        }
    }

}
Changes to System.Data.SQLite/SQLiteStatement.cs.
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

      object obj = param.Value;
      DbType objType = param.DbType;

      if ((obj != null) && (objType == DbType.Object))
          objType = SQLiteConvert.TypeToDbType(obj.GetType());

#if !PLATFORM_COMPACTFRAMEWORK
      if ((_flags & SQLiteConnectionFlags.LogPreBind) == SQLiteConnectionFlags.LogPreBind)
      {
          IntPtr handle = _sqlite_stmt;

          SQLiteLog.LogMessage(String.Format(
              "Binding statement {0} paramter #{1} with database type {2} and raw value {{{3}}}...",
              handle, index, objType, obj));
      }
#endif

      if ((obj == null) || Convert.IsDBNull(obj))
      {
          _sql.Bind_Null(this, _flags, index);
        return;
      }







      switch (objType)
      {
        case DbType.Date:
        case DbType.Time:
        case DbType.DateTime:
          //







<








<






>
>
>
>
>
>







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

      object obj = param.Value;
      DbType objType = param.DbType;

      if ((obj != null) && (objType == DbType.Object))
          objType = SQLiteConvert.TypeToDbType(obj.GetType());


      if ((_flags & SQLiteConnectionFlags.LogPreBind) == SQLiteConnectionFlags.LogPreBind)
      {
          IntPtr handle = _sqlite_stmt;

          SQLiteLog.LogMessage(String.Format(
              "Binding statement {0} paramter #{1} with database type {2} and raw value {{{3}}}...",
              handle, index, objType, obj));
      }


      if ((obj == null) || Convert.IsDBNull(obj))
      {
          _sql.Bind_Null(this, _flags, index);
        return;
      }

      if ((_flags & SQLiteConnectionFlags.BindAllAsText) == SQLiteConnectionFlags.BindAllAsText)
      {
          _sql.Bind_Text(this, _flags, index, obj.ToString());
          return;
      }

      switch (objType)
      {
        case DbType.Date:
        case DbType.Time:
        case DbType.DateTime:
          //
Changes to System.Data.SQLite/System.Data.SQLite.Properties.targets.
149
150
151
152
153
154
155








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









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







>
>
>
>
>
>
>
>







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

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

  <!--
      NOTE: Enable the logging callback in the custom built interop DLL (see
            the "SQLite.NET.Settings.targets" file for more information)?
  -->
  <PropertyGroup Condition="'$(InteropLog)' != 'false'">
    <DefineConstants>$(DefineConstants);INTEROP_LOG</DefineConstants>
  </PropertyGroup>
Changes to System.Data.SQLite/UnsafeNativeMethods.cs.
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

#if !PLATFORM_COMPACTFRAMEWORK && !DEBUG
  using System.Security;
#endif

  using System.Runtime.InteropServices;

#if !PLATFORM_COMPACTFRAMEWORK
  using System.Threading;
#endif

#if !PLATFORM_COMPACTFRAMEWORK && !DEBUG
  [SuppressUnmanagedCodeSecurity]
#endif
  internal static class UnsafeNativeMethods







|







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

#if !PLATFORM_COMPACTFRAMEWORK && !DEBUG
  using System.Security;
#endif

  using System.Runtime.InteropServices;

#if !PLATFORM_COMPACTFRAMEWORK || COUNT_HANDLE
  using System.Threading;
#endif

#if !PLATFORM_COMPACTFRAMEWORK && !DEBUG
  [SuppressUnmanagedCodeSecurity]
#endif
  internal static class UnsafeNativeMethods
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
      /// Attempts to initialize this class by pre-loading the native SQLite
      /// library for the processor architecture of the current process.
      /// </summary>
      internal static void Initialize()
      {
#if !PLATFORM_COMPACTFRAMEWORK
          //
          // NOTE: If the "NoPreLoadSQLite" environment variable is set, skip
          //       all our special code and simply return.
          //
          if (Environment.GetEnvironmentVariable("No_PreLoadSQLite") != null)
              return;
#endif

          lock (staticSyncRoot)
          {







|
|







137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
      /// Attempts to initialize this class by pre-loading the native SQLite
      /// library for the processor architecture of the current process.
      /// </summary>
      internal static void Initialize()
      {
#if !PLATFORM_COMPACTFRAMEWORK
          //
          // NOTE: If the "No_PreLoadSQLite" environment variable is set (to
          //       anything), skip all our special code and simply return.
          //
          if (Environment.GetEnvironmentVariable("No_PreLoadSQLite") != null)
              return;
#endif

          lock (staticSyncRoot)
          {
200
201
202
203
204
205
206




























207
208
209
210
211
212
213
          //       is set, use it verbatim for the base directory.
          //
          string directory = Environment.GetEnvironmentVariable(
              "PreLoadSQLite_BaseDirectory");

          if (directory != null)
              return directory;





























          //
          // NOTE: Otherwise, fallback on using the base directory of the
          //       current application domain.
          //
          return AppDomain.CurrentDomain.BaseDirectory;
#else







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







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
          //       is set, use it verbatim for the base directory.
          //
          string directory = Environment.GetEnvironmentVariable(
              "PreLoadSQLite_BaseDirectory");

          if (directory != null)
              return directory;

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

                  if (assembly != null)
                  {
                      directory = Path.GetDirectoryName(assembly.Location);

                      if (!String.IsNullOrEmpty(directory))
                          return directory;
                  }
              }
              catch
              {
                  // do nothing.
              }
          }

          //
          // NOTE: Otherwise, fallback on using the base directory of the
          //       current application domain.
          //
          return AppDomain.CurrentDomain.BaseDirectory;
#else
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
    //
    // 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.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
    //







|







532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
    //
    // 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.085.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
    //
639
640
641
642
643
644
645

646
647
648
649
650
651

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


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


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







>






>







667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern SQLiteErrorCode sqlite3_close(IntPtr db);

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

#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern SQLiteErrorCode sqlite3_create_function(IntPtr db, byte[] strName, int nArgs, int nType, IntPtr pvUser, SQLiteCallback func, SQLiteCallback fstep, SQLiteFinalCallback ffinal);
Changes to Tests/backup.eagle.
16
17
18
19
20
21
22

23
24
25
26
27
28
29
###############################################################################

package require System.Data.SQLite.Test
runSQLiteTestPrologue

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


getSQLiteHandleCounts $test_channel
reportSQLiteResources $test_channel

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

set params(pages) [list -1 -1 0 0 1 1 2 2 1000 1000]








>







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
###############################################################################

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]

231
232
233
234
235
236
237

238
239
240
241
242
243
244

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

unset -nocomplain i params pages callback

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


getSQLiteHandleCounts $test_channel
reportSQLiteResources $test_channel

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

runSQLiteTestEpilogue
runTestEpilogue







>







232
233
234
235
236
237
238
239
240
241
242
243
244
245
246

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

unset -nocomplain i params pages callback

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

checkForSQLiteDirectories $test_channel
getSQLiteHandleCounts $test_channel
reportSQLiteResources $test_channel

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

runSQLiteTestEpilogue
runTestEpilogue
Changes to Tests/basic.eagle.
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
} -body {
  set id [object invoke Interpreter.GetActive NextId]
  set dataSource [file join [getDatabaseDirectory] $fileName]

  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 bool TestSetAvRetry(







<







310
311
312
313
314
315
316

317
318
319
320
321
322
323
} -body {
  set id [object invoke Interpreter.GetActive NextId]
  set dataSource [file join [getDatabaseDirectory] $fileName]

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {

    using System.Data.SQLite;

    namespace _Dynamic${id}
    {
      public static class Test${id}
      {
        public static bool TestSetAvRetry(
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
    INSERT INTO t1 (x) VALUES(1); \
    SELECT x FROM t1; \
  }

  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()







<







418
419
420
421
422
423
424

425
426
427
428
429
430
431
    INSERT INTO t1 (x) VALUES(1); \
    SELECT x FROM t1; \
  }

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {

    using System.Data.SQLite;

    namespace _Dynamic${id}
    {
      public static class Test${id}
      {
        public static void Main()
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
    INSERT INTO t1 (x) VALUES(1); \
    SELECT x FROM t1; \
  }

  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()







<







475
476
477
478
479
480
481

482
483
484
485
486
487
488
    INSERT INTO t1 (x) VALUES(1); \
    SELECT x FROM t1; \
  }

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {

    using System.Data.SQLite;

    namespace _Dynamic${id}
    {
      public static class Test${id}
      {
        public static void Main()
933
934
935
936
937
938
939

940
941
942
943
944



















945
946
947
948
949
950
951

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {
    using System;
    using System.Data.SQLite;
    using System.Reflection;


    namespace _Dynamic${id}
    {
      public static class Test${id}
      {



















        public static string GetConnectionString(
          string key,
          string value,
          string propertyName
          )
        {
          SQLiteConnectionStringBuilder builder =







>





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







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

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {
    using System;
    using System.Data.SQLite;
    using System.Reflection;
    using System.Text;

    namespace _Dynamic${id}
    {
      public static class Test${id}
      {
        private static string ToHexString(
          byte\[\] array
          )
        {
          if (array == null)
            return null;

          StringBuilder result = new StringBuilder();

          int length = array.Length;

          for (int index = 0; index < length; index++)
            result.AppendFormat("{0:x2}", array\[index\]);

          return result.ToString();
        }

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

        public static string GetConnectionString(
          string key,
          string value,
          string propertyName
          )
        {
          SQLiteConnectionStringBuilder builder =
959
960
961
962
963
964
965
966

967
968
969
970
971
972
973
          if (propertyName != null)
          {
            propertyValue = typeof(SQLiteConnectionStringBuilder).InvokeMember(
                propertyName, BindingFlags.Instance | BindingFlags.Public |
                BindingFlags.GetProperty, null, builder, null);
          }

          return String.Format("{0}, {1}", propertyValue, builder);

        }

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

        public static void Main()
        {
          // do nothing.







|
>







976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
          if (propertyName != null)
          {
            propertyValue = typeof(SQLiteConnectionStringBuilder).InvokeMember(
                propertyName, BindingFlags.Instance | BindingFlags.Public |
                BindingFlags.GetProperty, null, builder, null);
          }

          return String.Format("{0}, {1}", (propertyValue is byte\[\]) ?
              ToHexString((byte\[\])propertyValue) : propertyValue, builder);
        }

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

        public static void Main()
        {
          // do nothing.
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
  if {$code eq "Ok"} then {
    set keys [list null Version Synchronous UseUTF16Encoding Pooling \
                   BinaryGUID "Data Source" Uri FullUri "Default Timeout" \
                   Enlist FailIfMissing "Legacy Format" "Read Only" \
                   Password "Page Size" "Max Page Count" "Cache Size" \
                   DateTimeFormat DateTimeKind BaseSchemaName \
                   "Journal Mode" "Default IsolationLevel" "Foreign Keys" \
                   Flags SetDefaults ToFullPath]

    set values [list null 3 Normal True False \
                     True test.db test.db file:test.db 60 \
                     False True False True \
                     secret 4096 1024 8192 \
                     UnixEpoch Utc sqlite_schema \
                     Memory Serializable False \
                     Default False False]

    set propertyNames [list null Version SyncMode UseUTF16Encoding Pooling \
                            BinaryGUID DataSource Uri FullUri DefaultTimeout \
                            Enlist FailIfMissing LegacyFormat ReadOnly \
                            Password PageSize MaxPageCount CacheSize \
                            DateTimeFormat DateTimeKind BaseSchemaName \
                            JournalMode DefaultIsolationLevel ForeignKeys \
                            Flags SetDefaults ToFullPath]

    foreach key $keys value $values propertyName $propertyNames {
      set code [catch {
        object invoke _Dynamic${id}.Test${id} GetConnectionString \
            $key $value $propertyName
      } result]








|







|







|







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
  if {$code eq "Ok"} then {
    set keys [list null Version Synchronous UseUTF16Encoding Pooling \
                   BinaryGUID "Data Source" Uri FullUri "Default Timeout" \
                   Enlist FailIfMissing "Legacy Format" "Read Only" \
                   Password "Page Size" "Max Page Count" "Cache Size" \
                   DateTimeFormat DateTimeKind BaseSchemaName \
                   "Journal Mode" "Default IsolationLevel" "Foreign Keys" \
                   Flags SetDefaults ToFullPath HexPassword]

    set values [list null 3 Normal True False \
                     True test.db test.db file:test.db 60 \
                     False True False True \
                     secret 4096 1024 8192 \
                     UnixEpoch Utc sqlite_schema \
                     Memory Serializable False \
                     Default False False 736563726574]

    set propertyNames [list null Version SyncMode UseUTF16Encoding Pooling \
                            BinaryGUID DataSource Uri FullUri DefaultTimeout \
                            Enlist FailIfMissing LegacyFormat ReadOnly \
                            Password PageSize MaxPageCount CacheSize \
                            DateTimeFormat DateTimeKind BaseSchemaName \
                            JournalMode DefaultIsolationLevel ForeignKeys \
                            Flags SetDefaults ToFullPath HexPassword]

    foreach key $keys value $values propertyName $propertyNames {
      set code [catch {
        object invoke _Dynamic${id}.Test${id} GetConnectionString \
            $key $value $propertyName
      } result]

1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
0 \{True, Read Only=True\} 0 \{secret, Password=secret\} 0 \{4096, Page\
Size=4096\} 0 \{1024, Max Page Count=1024\} 0 \{8192, Cache Size=8192\} 0\
\{UnixEpoch, DateTimeFormat=UnixEpoch\} 0 \{Utc, DateTimeKind=Utc\} 0\
\{sqlite_schema, BaseSchemaName=sqlite_schema\} 0 \{Memory, Journal\
Mode=Memory\} 0 \{Serializable, Default IsolationLevel=Serializable\} 0\
\{False, Foreign Keys=False\} 0 \{(?:Default|LogCallbackException),\
Flags=(?:Default|LogCallbackException)\} 0 \{False, SetDefaults=False\} 0\
\{False, ToFullPath=False\}$}}

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

runTest {test data-1.17 {SQLiteConvert ToDateTime (Julian Day)} -body {
  set dateTime [object invoke System.Data.SQLite.SQLiteConvert ToDateTime \
      2455928.0 Utc]








|







1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
0 \{True, Read Only=True\} 0 \{secret, Password=secret\} 0 \{4096, Page\
Size=4096\} 0 \{1024, Max Page Count=1024\} 0 \{8192, Cache Size=8192\} 0\
\{UnixEpoch, DateTimeFormat=UnixEpoch\} 0 \{Utc, DateTimeKind=Utc\} 0\
\{sqlite_schema, BaseSchemaName=sqlite_schema\} 0 \{Memory, Journal\
Mode=Memory\} 0 \{Serializable, Default IsolationLevel=Serializable\} 0\
\{False, Foreign Keys=False\} 0 \{(?:Default|LogCallbackException),\
Flags=(?:Default|LogCallbackException)\} 0 \{False, SetDefaults=False\} 0\
\{False, ToFullPath=False\} 0 {736563726574, HexPassword=736563726574}$}}

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

runTest {test data-1.17 {SQLiteConvert ToDateTime (Julian Day)} -body {
  set dateTime [object invoke System.Data.SQLite.SQLiteConvert ToDateTime \
      2455928.0 Utc]

1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
      [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \
      TypeNameToDbType "NVARCHAR(1)"] \
      [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \
      TypeNameToDbType "VARCHAR (1)"] \
      [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \
      TypeNameToDbType "NVARCHAR (1)"] \
} -constraints {eagle System.Data.SQLite} -result \
{String String String String String String}}

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

runTest {test data-1.28 {SetMemoryStatus method} -setup {
  #
  # NOTE: Make sure that SQLite core library is completely shutdown prior to
  #       starting this test.







|







1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
      [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \
      TypeNameToDbType "NVARCHAR(1)"] \
      [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \
      TypeNameToDbType "VARCHAR (1)"] \
      [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \
      TypeNameToDbType "NVARCHAR (1)"] \
} -constraints {eagle System.Data.SQLite} -result \
{AnsiString String AnsiString String AnsiString String}}

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

runTest {test data-1.28 {SetMemoryStatus method} -setup {
  #
  # NOTE: Make sure that SQLite core library is completely shutdown prior to
  #       starting this test.
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 < 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 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) $found(temp); 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







|









|











>
|
>







1706
1707
1708
1709
1710
1711
1712
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

  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} {
    #
    # 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)}]

    #
    # 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)] ? \
      $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
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240



























































































2241
2242
2243
2244
2245
2246
2247

  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}}}

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




























































































unset -nocomplain systemDataSQLiteDllFile systemDataSQLiteLinqDllFile \
    testExeFile testLinqExeFile northwindEfDbFile testLinqOutFile

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

runSQLiteTestEpilogue
runTestEpilogue










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







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
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358

  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\}$}}

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

runTest {test data-1.48 {static SQLiteCommand.Execute method} -setup {
  unset -nocomplain result sql
} -body {
  set sql(1) { \
    CREATE TABLE t1(x); \
    INSERT INTO t1 (x) VALUES (NULL); \
    SELECT x FROM t1 ORDER BY x; \
  }

  set sql(2) { \
    CREATE TABLE t1(x); \
    INSERT INTO t1 (x) VALUES (?); \
    SELECT x FROM t1 ORDER BY x; \
  }

  set result(1) [object invoke System.Data.SQLite.SQLiteCommand Execute \
      "this will not execute" None null]

  set result(2) [object invoke System.Data.SQLite.SQLiteCommand Execute \
      $sql(1) NonQuery null]

  set result(3) [object invoke System.Data.SQLite.SQLiteCommand Execute \
      $sql(1) Scalar null]

  set result(4) [object invoke System.Data.SQLite.SQLiteCommand Execute \
      $sql(1) Reader null]

  set result(5) [object invoke System.Data.SQLite.SQLiteCommand Execute \
      "this will not execute" None null 1]

  set result(6) [object invoke System.Data.SQLite.SQLiteCommand Execute \
      $sql(2) NonQuery null 1]

  set result(7) [object invoke System.Data.SQLite.SQLiteCommand Execute \
      $sql(2) Scalar null 1]

  set result(8) [object invoke System.Data.SQLite.SQLiteCommand Execute \
      $sql(2) Reader null 1]

  list $result(1) $result(2) $result(3) $result(4) $result(5) $result(6) \
      $result(7) $result(8)
} -cleanup {
  unset -nocomplain result sql
} -constraints {eagle monoBug28 SQLite System.Data.SQLite} -match regexp \
-result {^\{\} 1 System#DBNull#\d+ System#Data#SQLite#SQLiteDataReader#\d+ \{\}\
1 1 System#Data#SQLite#SQLiteDataReader#\d+$}}

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

unset -nocomplain systemDataSQLiteDllFile systemDataSQLiteLinqDllFile \
    testExeFile testLinqExeFile northwindEfDbFile testLinqOutFile

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

runSQLiteTestEpilogue
runTestEpilogue
Changes to Tests/common.eagle.
85
86
87
88
89
90
91

















































92
93
94
95
96
97
98
            # NOTE: Use the default test year for the CLR v2.0.
            #
            return 2008; # TODO: Good "fallback" default?
          }
        }
      }
    }


















































    proc getBuildConfiguration {} {
      #
      # NOTE: See if the "configuration" setting has been overridden by the user
      #       (e.g. on the command line).  This helps control exactly which set
      #       of binaries we are testing (i.e. those built in the "Debug" or
      #       "Release" build configurations).  To override this value via the







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







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
            # NOTE: Use the default test year for the CLR v2.0.
            #
            return 2008; # TODO: Good "fallback" default?
          }
        }
      }
    }

    proc getBuildYears {} {
      #
      # NOTE: See if the list of test years has been overridden by the user
      #       (e.g. on the command line).
      #
      if {[info exists ::test_years] && [llength $::test_years] > 0} then {
        #
        # NOTE: Use the specified list of test years.
        #
        return $::test_years
      } else {
        #
        # NOTE: Use the default list of test years.
        #
        return [list 2005 2008 2010 2012]
      }
    }

    proc getBuildPlatform { native } {
      if {[info exists ::test_platform] && \
          [string length $::test_platform] > 0} then {
        #
        # NOTE: Use the specified test platform.  If this variable is not set,
        #       the default value will be based on the machine architecture.
        #
        return [expr {$native ? $::test_platform : ""}]
      } elseif {[info exists ::test_machine] && \
          [string length $::test_machine] > 0} then {
        #
        # NOTE: For native builds, return the platform name corresponding to
        #       the test machine architecture; otherwise, return an empty
        #       string.
        #
        return [expr {$native ? [machineToPlatform $::test_machine] : ""}]
      } elseif {[info exists ::tcl_platform(machine)]} then {
        #
        # NOTE: For native builds, return the platform name corresponding to
        #       the machine architecture; otherwise, return an empty string.
        #
        return [expr {$native ? \
            [machineToPlatform $::tcl_platform(machine)] : ""}]
      } else {
        #
        # NOTE: No machine architecture is available, return an empty string.
        #
        return ""
      }
    }

    proc getBuildConfiguration {} {
      #
      # NOTE: See if the "configuration" setting has been overridden by the user
      #       (e.g. on the command line).  This helps control exactly which set
      #       of binaries we are testing (i.e. those built in the "Debug" or
      #       "Release" build configurations).  To override this value via the
121
122
123
124
125
126
127





































































128
129
130
131
132
133
134
        #       test configuration variable is always set by the test suite
        #       itself; however, it can be overridden using the unset command
        #       from the -preTest option to the test suite.
        #
        return $::eagle_platform(configuration)
      }
    }






































































    proc getBuildDirectory {} {
      #
      # NOTE: See if the "native" runtime option has been set.  If so, use the
      #       directory for the mixed-mode assembly (a.k.a. the native interop
      #       assembly).  To enable this option via the command line, enter a
      #       command similar to one of the following (all on one line):







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







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
        #       test configuration variable is always set by the test suite
        #       itself; however, it can be overridden using the unset command
        #       from the -preTest option to the test suite.
        #
        return $::eagle_platform(configuration)
      }
    }

    proc getBuildConfigurations {} {
      #
      # NOTE: See if the list of test configurations has been overridden by
      #       the user (e.g. on the command line).
      #
      if {[info exists ::test_configurations] && \
          [llength $::test_configurations] > 0} then {
        #
        # NOTE: Use the specified list of test configurations.
        #
        return $::test_configurations
      } else {
        #
        # NOTE: Use the default list of test configurations.
        #
        return [list Debug Release]
      }
    }

    proc getBuildBaseDirectory {} {
      #
      # NOTE: Figure out the base directory where all the builds should be
      #       located.  This will be the directory that contains the actual
      #       build output directory (e.g. parent of "bin").
      #
      if {[info exists ::build_base_directory] && \
          [string length $::build_base_directory] > 0} then {
        #
        # NOTE: The location of the build base directory has been overridden;
        #       therefore, use it verbatim.
        #
        return $::build_base_directory
      } elseif {[info exists ::common_directory] && \
          [string length $::common_directory] > 0} then {
        #
        # NOTE: Next, fallback to the parent directory of the one containing
        #       this file (i.e. "common.eagle"), if available.
        #
        return [file dirname $::common_directory]
      } elseif {[info exists ::path] && \
          [string length $::path] > 0} then {
        #
        # NOTE: Finally, fallback to the parent directory of the EagleTest
        #       path.  The EagleTest package guarantees that this variable
        #       will be set to the directory containing the first file to
        #       execute the [runTestPrologue] script library procedure.
        #
        return [file dirname $::path]
      } else {
        #
        # NOTE: No path is available, return an empty string.  This point
        #       should not be reached.
        #
        return ""
      }
    }

    proc joinBuildDirectory { path native year platform configuration } {
      #
      # NOTE: Figure out and then return the fully qualified path to the build
      #       directory based on all the arguments provided by our caller.
      #
      if {$native} then {
        return [file join $path bin $year $platform $configuration]
      } else {
        return [file join $path bin $year $configuration bin]
      }
    }

    proc getBuildDirectory {} {
      #
      # NOTE: See if the "native" runtime option has been set.  If so, use the
      #       directory for the mixed-mode assembly (a.k.a. the native interop
      #       assembly).  To enable this option via the command line, enter a
      #       command similar to one of the following (all on one line):
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
          [string length $::build_directory] > 0} then {
        #
        # NOTE: The location of the build directory has been overridden;
        #       therefore, use it verbatim.
        #
        return $::build_directory
      } else {
        #
        # NOTE: Figure out the build base directory.  This will be the directory
        #       that contains the actual build output directory (e.g. "bin").
        #
        if {[info exists ::build_base_directory] && \
            [string length $::build_base_directory] > 0} then {
          #
          # NOTE: The location of the build base directory has been overridden;
          #       therefore, use it verbatim.
          #
          set path $::build_base_directory
        } elseif {[info exists ::common_directory] && \
            [string length $::common_directory] > 0} then {
          #
          # NOTE: Next, fallback to the parent directory of the one containing
          #       this file (i.e. "common.eagle"), if available.
          #
          set path [file dirname $::common_directory]
        } else {
          #
          # NOTE: Finally, fallback to the parent directory of the EagleTest
          #       path.  The EagleTest package guarantees that this variable
          #       will be set to the directory containing the first file to
          #       execute the [runTestPrologue] script library procedure.
          #
          set path [file dirname $::path]
        }

        #
        # NOTE: If the "native" runtime option is set, the mixed-mode assembly
        #       is being tested.  In that case, the path to the build directory
        #       will contain the platform name and all the binaries under test
        #       should be present in that directory.  If the "native" runtime
        #       option is not set, the build directory will be considered to be
        #       "platform-neutral", with the notable exception of any native







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







266
267
268
269
270
271
272




























273
274
275
276
277
278
279
          [string length $::build_directory] > 0} then {
        #
        # NOTE: The location of the build directory has been overridden;
        #       therefore, use it verbatim.
        #
        return $::build_directory
      } else {




























        #
        # NOTE: If the "native" runtime option is set, the mixed-mode assembly
        #       is being tested.  In that case, the path to the build directory
        #       will contain the platform name and all the binaries under test
        #       should be present in that directory.  If the "native" runtime
        #       option is not set, the build directory will be considered to be
        #       "platform-neutral", with the notable exception of any native
216
217
218
219
220
221
222
223
224
225
226
227
228
229


230
231
232
233
234
235
236
        #
        #       Note that all of the build commands above will default to using
        #       the latest version of MSBuild available and the "test_year" may
        #       need to be adjusted accordingly to actually run the test suite.
        #       Refer to the comments in [getBuildYear] for more information on
        #       how to set this variable.
        #
        if {[hasRuntimeOption native]} then {
          return [file join $path bin [getBuildYear] [machineToPlatform \
              $::tcl_platform(machine)] [getBuildConfiguration]]
        } else {
          return [file join $path bin [getBuildYear] [getBuildConfiguration] \
              bin]
        }


      }
    }

    proc getBuildFileName { fileName } {
      #
      # NOTE: Returns the specified file name as if it were located in the
      #       build directory, discarding any directory information present







|
<
<
<
<
<
|
>
>







306
307
308
309
310
311
312
313





314
315
316
317
318
319
320
321
322
323
        #
        #       Note that all of the build commands above will default to using
        #       the latest version of MSBuild available and the "test_year" may
        #       need to be adjusted accordingly to actually run the test suite.
        #       Refer to the comments in [getBuildYear] for more information on
        #       how to set this variable.
        #
        set native [hasRuntimeOption native]






        return [joinBuildDirectory [getBuildBaseDirectory] $native \
            [getBuildYear] [getBuildPlatform $native] [getBuildConfiguration]]
      }
    }

    proc getBuildFileName { fileName } {
      #
      # NOTE: Returns the specified file name as if it were located in the
      #       build directory, discarding any directory information present
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
      return [uplevel 1 [list subst [appendArgs $prefix {
        if {[hasRuntimeOption native]} then {
          object invoke Interpreter.GetActive AddRuntimeOption native
        }
      } [getTestOverridesPreamble [list path test_channel]] $suffix]]]
    }

    proc tryCopyBuildFile { fileName } {

      #




      # NOTE: If we cannot copy the assembly then it is probably already loaded.


      #



















      set sourceFileName [getBuildFileName $fileName]

      if {![file exists $sourceFileName]} then {
        tputs $::test_channel [appendArgs \
            "---- skipped copying build file \"" $sourceFileName \
            "\", it does not exist\n"]

        return
      }




      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 {







|
>
|
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>










>
>
>
|
>







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
      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 ""} } {
      set sourceFileName [getBinaryFileName $fileName]

      if {![file exists $sourceFileName]} then {
        tputs $::test_channel [appendArgs \
            "---- skipped copying binary file \"" $sourceFileName \
            "\", it does not exist\n"]

        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]
      }

      if {[catch {
              file copy -force $sourceFileName $targetFileName}] == 0} then {
        tputs $::test_channel [appendArgs \
            "---- copied build file from \"" $sourceFileName "\" to \"" \
            $targetFileName \"\n]
      } else {
515
516
517
518
519
520
521




















522
523
524
525
526
527
528
        tputs $::test_channel [appendArgs \
            "---- deleted binary file \"" $fileName \"\n]
      } else {
        tputs $::test_channel [appendArgs \
            "---- failed to delete binary file \"" $fileName \"\n]
      }
    }





















    proc tryCopyAssembly { fileName {pdb true} } {
      tryCopyBuildFile $fileName

      if {$pdb} then {
        tryCopyBuildFile [appendArgs [file rootname $fileName] .pdb]
      }







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







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
        tputs $::test_channel [appendArgs \
            "---- 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]
      }
572
573
574
575
576
577
578



























579
580
581
582
583
584
585
      #       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 {







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







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
      #       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 checkForSQLiteBuilds { channel } {
      #
      # NOTE: Check for every possible valid combination of values used when
      #       locating out the build output directory, showing each available
      #       build variation along the way.
      #
      foreach native [list false true] {
        foreach year [getBuildYears] {
          foreach configuration [getBuildConfigurations] {
            tputs $channel [appendArgs \
                "---- checking for System.Data.SQLite build \"" [expr \
                {$native ? "native/" : ""}] $year / $configuration "\"... "]

            set fileName [file nativename [file join [joinBuildDirectory \
                [getBuildBaseDirectory] $native $year [getBuildPlatform \
                $native] $configuration] System.Data.SQLite.dll]]

            if {[file exists $fileName]} then {
              tputs $channel yes\n
            } else {
              tputs $channel no\n
            }
          }
        }
      }
    }

    proc checkForSQLite { channel } {
      tputs $channel "---- checking for core SQLite library... "

      if {[catch {
              object invoke -flags +NonPublic System.Data.SQLite.SQLite3 \
              SQLiteVersion} version] == 0} then {
1074
1075
1076
1077
1078
1079
1080






























































1081
1082
1083
1084
1085
1086
1087
        # NOTE: The file does not exist, success!
        #
        set code 0
      }

      return $code
    }































































    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.
      #







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







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
        # NOTE: The file does not exist, success!
        #
        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.
      #
1218
1219
1220
1221
1222
1223
1224






1225
1226
1227
1228
1229
1230
1231
      #       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 {[catch {object invoke -flags +NonPublic \
                System.Data.SQLite.UnsafeNativeMethods \
                sqlite3_shutdown} result] == 0} then {
          if {!$quiet} then {
            tputs $channel [appendArgs \
                "---- call sqlite3_shutdown()... ok: " $result \n]
          }







>
>
>
>
>
>







1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
      #       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 {
        #
        # 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 {
          if {!$quiet} then {
            tputs $channel [appendArgs \
                "---- call sqlite3_shutdown()... ok: " $result \n]
          }
1446
1447
1448
1449
1450
1451
1452






1453
1454
1455
1456
1457
1458
1459
                    error]} then {
              if {!$quiet} then {
                tputs $channel [appendArgs \
                    "==== WARNING: failed to load per-user settings file \"" \
                    $userSettingsFileName "\", error: " \n\t $error \n]
              }
            }






          }
        }

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

        if {[info exists ::tcl_platform(host)]} then {
          set hostSettingsFileName [file join [getCommonDirectory] \







>
>
>
>
>
>







1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
                    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] \
1470
1471
1472
1473
1474
1475
1476






1477
1478
1479
1480
1481
1482
1483
                    error]} then {
              if {!$quiet} then {
                tputs $channel [appendArgs \
                    "==== WARNING: failed to load per-host settings file \"" \
                    $hostSettingsFileName "\", error: " \n\t $error \n]
              }
            }






          }
        }
      }
    }

    proc runSQLiteTestPrologue {} {
      #







>
>
>
>
>
>







1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
                    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 {} {
      #
1526
1527
1528
1529
1530
1531
1532
























1533
1534
1535
1536
1537
1538
1539
          #
          # 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
          }
























        }

        catch {
          tputs $::test_channel [appendArgs \
              "---- file version of \"sqlite3.dll\"... " \
              [file version [getBinaryFileName sqlite3.dll]] \n]
        }







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







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
          #
          # 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]
        }
1575
1576
1577
1578
1579
1580
1581





1582
1583
1584
1585
1586
1587
1588
            tputs $::test_channel [appendArgs [formatList [lsort \
                $defineConstants]] \n]
          } else {
            tputs $::test_channel unknown\n
          }
        }






        #
        # NOTE: Now, we need to know if the SQLite core library is available
        #       (i.e. because the managed-only System.Data.SQLite assembly can
        #       load without it; however, it cannot do anything useful without
        #       it).  If we are using the mixed-mode assembly and we already
        #       found it (above), this should always succeed.
        #







>
>
>
>
>







1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
            tputs $::test_channel [appendArgs [formatList [lsort \
                $defineConstants]] \n]
          } else {
            tputs $::test_channel unknown\n
          }
        }

        #
        # NOTE: Check the available builds of SQLite and System.Data.SQLite.
        #
        checkForSQLiteBuilds $::test_channel

        #
        # NOTE: Now, we need to know if the SQLite core library is available
        #       (i.e. because the managed-only System.Data.SQLite assembly can
        #       load without it; however, it cannot do anything useful without
        #       it).  If we are using the mixed-mode assembly and we already
        #       found it (above), this should always succeed.
        #
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
        #       test constraints were enabled for the managed assembly.  There
        #       are some compile-time options that must also have been enabled
        #       for the interop assembly in order to be effective.  For those
        #       options, it will be assumed that it was enabled for the interop
        #       assembly if it was enabled for the managed assembly.
        #
        foreach defineConstant [list CHECK_STATE COUNT_HANDLE INTEROP_CODEC \
                                     INTEROP_DEBUG INTEROP_LOG \
                                     INTEROP_EXTENSION_FUNCTIONS \
                                     INTEROP_TEST_EXTENSION SQLITE_STANDARD \
                                     USE_INTEROP_DLL] {
          #
          # NOTE: Check if the compile-time option is listed in the list of
          #       "define constants" kept track of by the managed assembly.
          #
          checkForSQLiteDefineConstant $::test_channel $defineConstant







|
|







1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
        #       test constraints were enabled for the managed assembly.  There
        #       are some compile-time options that must also have been enabled
        #       for the interop assembly in order to be effective.  For those
        #       options, it will be assumed that it was enabled for the interop
        #       assembly if it was enabled for the managed assembly.
        #
        foreach defineConstant [list CHECK_STATE COUNT_HANDLE INTEROP_CODEC \
                                     INTEROP_DEBUG INTEROP_LEGACY_CLOSE \
                                     INTEROP_LOG INTEROP_EXTENSION_FUNCTIONS \
                                     INTEROP_TEST_EXTENSION SQLITE_STANDARD \
                                     USE_INTEROP_DLL] {
          #
          # NOTE: Check if the compile-time option is listed in the list of
          #       "define constants" kept track of by the managed assembly.
          #
          checkForSQLiteDefineConstant $::test_channel $defineConstant
1629
1630
1631
1632
1633
1634
1635
1636
1637









1638
1639
1640
1641
1642
1643
1644
        # NOTE: Check the current build configuration.  This should normally
        #       be either "Debug" or "Release".
        #
        tputs $::test_channel \
            "---- checking for System.Data.SQLite build configuration... "

        set configuration [getBuildConfiguration]
        addConstraint [appendArgs buildConfiguration $configuration]
        tputs $::test_channel [appendArgs \" $configuration \"\n]










        #
        # NOTE: Check for the native runtime option, which would mean we are
        #       using the mixed-mode assembly.
        #
        checkForRuntimeOption $::test_channel native








|

>
>
>
>
>
>
>
>
>







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
        # NOTE: Check the current build configuration.  This should normally
        #       be either "Debug" or "Release".
        #
        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

1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
        #
        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







|







1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
        #
        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
1698
1699
1700
1701
1702
1703
1704






1705
1706
1707
1708
1709
1710
1711
        #
        # NOTE: Show when our tests actually ended (now).
        #
        tputs $::test_channel [appendArgs \
            "---- System.Data.SQLite tests ended at " \
            [clock format [clock seconds]] \n]







        #
        # NOTE: Also report the resource usage after running the tests.
        #
        reportSQLiteResources $::test_channel
      }
    }








>
>
>
>
>
>







1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
        #
        # 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
      }
    }

Changes to Tests/stress.eagle.
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
runSQLiteTestPrologue

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

#
# NOTE: Report before test, before shutdown.
#

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.
#

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 \
      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







>
















>








|
|







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
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 event timeout connection indicators iterations exitOnFail \
      coTaskMem noTrace failures status

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

  proc setupWorkloadMemDb { fileName {varName db} } {
    #
    # NOTE: This should be an in-memory database; therefore, skip attempting
    #       to delete the underlying database file as that would not make any
137
138
139
140
141
142
143









144
145
146
147
148
149
150
  }

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

  proc delayTest { {extra 0} } {
    after [expr {int((rand() * 1000) + $extra)}]
  }










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

  proc showTest { indicator } {
    tputs $::test_channel $indicator
    append ::indicators $indicator
    delayTest $::count(2)







>
>
>
>
>
>
>
>
>







139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
  }

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

  proc delayTest { {extra 0} } {
    after [expr {int((rand() * 1000) + $extra)}]
  }

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

  proc waitTest { indicator } {
    if {![$::event WaitOne $::timeout]} then {
      error [appendArgs "timeout while starting workload #" \
          [expr {[string ordinal $indicator 0] - [string ordinal A 0] + 1}]]
    }
  }

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

  proc showTest { indicator } {
    tputs $::test_channel $indicator
    append ::indicators $indicator
    delayTest $::count(2)
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364

  #
  # 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

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

  #
  # 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







|







361
362
363
364
365
366
367
368
369
370
371
372
373
374
375

  #
  # 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
462
463
464
465
466
467
468














469
470
471
472
473
474
475
476
477
478

479
480
481
482
483
484
485
  #       logging subsystem is working properly.  Second, it places the file
  #       name for the associated database file into the trace log file.
  #
  set connection [getDbConnection]

  $connection LogMessage 0 [appendArgs \
      "starting stress test using database \"" $fileName(2) \"...]















  #############################################################################
  #                              WORKLOAD #1 (A)                              #
  #############################################################################

  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
      for {set index 2} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db [appendArgs \
              "CREATE TABLE IF NOT EXISTS t" \







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










>







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
  #       logging subsystem is working properly.  Second, it places the file
  #       name for the associated database file into the trace log file.
  #
  set connection [getDbConnection]

  $connection LogMessage 0 [appendArgs \
      "starting stress test using database \"" $fileName(2) \"...]

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

  set timeout [object invoke -flags +NonPublic \
      Eagle._Components.Private.ThreadOps DefaultJoinTimeout]

  tputs $test_channel [appendArgs \
      "---- workloads will start before or timeout after " $timeout \
      " millisecond(s)\n"]

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

  set event [object create -alias \
      System.Threading.EventWaitHandle false ManualReset]

  #############################################################################
  #                              WORKLOAD #1 (A)                              #
  #############################################################################

  set workload(1) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #1, CREATE TABLE statements.
    #
    waitTest A
    lappend ::times(1) [lindex [time {
      initTest A
      setupWorkloadFileDb $dstFileName
      for {set index 2} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db [appendArgs \
              "CREATE TABLE IF NOT EXISTS t" \
503
504
505
506
507
508
509

510
511
512
513
514
515
516
  #############################################################################

  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
      for {set index 2} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db [appendArgs \
              "DROP TABLE IF EXISTS t" $index \;]







>







529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
  #############################################################################

  set workload(2) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #2, DROP TABLE statements.
    #
    waitTest B
    lappend ::times(2) [lindex [time {
      initTest B
      setupWorkloadFileDb $dstFileName
      for {set index 2} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db [appendArgs \
              "DROP TABLE IF EXISTS t" $index \;]
533
534
535
536
537
538
539

540
541
542
543
544
545
546
  #############################################################################

  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
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          set reader [sql execute -execute reader \
              -format dataReader -alias $db [appendArgs \







>







560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
  #############################################################################

  set workload(3) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #3, "small" SELECT statements.
    #
    waitTest C
    lappend ::times(3) [lindex [time {
      initTest C
      setupWorkloadFileDb $dstFileName
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          set reader [sql execute -execute reader \
              -format dataReader -alias $db [appendArgs \
570
571
572
573
574
575
576

577
578
579
580
581
582
583
  #############################################################################

  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
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          set reader [sql execute -execute reader \
              -format dataReader -alias $db [appendArgs \







>







598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
  #############################################################################

  set workload(4) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #4, "big" SELECT statements.
    #
    waitTest D
    lappend ::times(4) [lindex [time {
      initTest D
      setupWorkloadFileDb $dstFileName
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          set reader [sql execute -execute reader \
              -format dataReader -alias $db [appendArgs \
607
608
609
610
611
612
613

614
615
616
617
618
619
620
  #############################################################################

  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
      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()}]] \







>







636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
  #############################################################################

  set workload(5) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #5, "small" INSERT statements.
    #
    waitTest E
    lappend ::times(5) [lindex [time {
      initTest E
      setupWorkloadFileDb $dstFileName
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db [appendArgs "INSERT INTO " $table \
              "(x, y, z) VALUES('" [format %lX [expr {random()}]] \
639
640
641
642
643
644
645

646
647
648
649
650
651
652
  #############################################################################

  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
      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()}]] \







>







669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
  #############################################################################

  set workload(6) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #6, "big" INSERT statements.
    #
    waitTest F
    lappend ::times(6) [lindex [time {
      initTest F
      setupWorkloadFileDb $dstFileName
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db [appendArgs "INSERT INTO " $table \
              "(x, y, z) VALUES('" [format %lX [expr {random()}]] \
670
671
672
673
674
675
676

677
678
679
680
681
682
683
  #############################################################################

  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
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db [appendArgs "UPDATE " $table \
              " SET y = '" [base64 encode -- [expr {randstr($count2)}]] \







>







701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
  #############################################################################

  set workload(7) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #7, "small" UPDATE statements.
    #
    waitTest G
    lappend ::times(7) [lindex [time {
      initTest G
      setupWorkloadFileDb $dstFileName
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db [appendArgs "UPDATE " $table \
              " SET y = '" [base64 encode -- [expr {randstr($count2)}]] \
701
702
703
704
705
706
707

708
709
710
711
712
713
714
  #############################################################################

  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
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db [appendArgs "UPDATE " $table \
              " SET y = RANDOMBLOB(" $count3 ") WHERE x LIKE '" \







>







733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
  #############################################################################

  set workload(8) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #8, "big" UPDATE statements.
    #
    waitTest H
    lappend ::times(8) [lindex [time {
      initTest H
      setupWorkloadFileDb $dstFileName
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db [appendArgs "UPDATE " $table \
              " SET y = RANDOMBLOB(" $count3 ") WHERE x LIKE '" \
732
733
734
735
736
737
738

739
740
741
742
743
744
745
  #############################################################################

  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
      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';"]







>







765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
  #############################################################################

  set workload(9) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #9, "small" DELETE statements.
    #
    waitTest I
    lappend ::times(9) [lindex [time {
      initTest I
      setupWorkloadFileDb $dstFileName
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db [appendArgs "DELETE FROM " $table \
              " WHERE x LIKE '" [format %X $index] "%' AND z = 'small';"]
762
763
764
765
766
767
768

769
770
771
772
773
774
775
  #############################################################################

  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
      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';"]







>







796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
  #############################################################################

  set workload(10) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #10, "big" DELETE statements.
    #
    waitTest J
    lappend ::times(10) [lindex [time {
      initTest J
      setupWorkloadFileDb $dstFileName
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db [appendArgs "DELETE FROM " $table \
              " WHERE x LIKE '" [format %X $index] "%' AND z = 'big';"]
792
793
794
795
796
797
798

799
800
801
802
803
804
805
  #############################################################################

  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
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db "VACUUM;"
          showTest K







>







827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
  #############################################################################

  set workload(11) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #11, VACUUM statement.
    #
    waitTest K
    lappend ::times(11) [lindex [time {
      initTest K
      setupWorkloadFileDb $dstFileName
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db "VACUUM;"
          showTest K
821
822
823
824
825
826
827

828
829
830
831
832
833
834
  #############################################################################

  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







>







857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
  #############################################################################

  set workload(12) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #12, backup to in-memory database.
    #
    waitTest L
    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
903
904
905
906
907
908
909

910
911
912
913
914
915
916
  #############################################################################

  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







>







940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
  #############################################################################

  set workload(13) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #13, backup from an in-memory database.
    #
    waitTest M
    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
985
986
987
988
989
990
991

992
993
994
995
996
997
998
  #############################################################################

  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
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          set result [sql execute -execute scalar $db \
              "PRAGMA integrity_check;"]







>







1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
  #############################################################################

  set workload(14) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #14, PRAGMA integrity check statement.
    #
    waitTest N
    lappend ::times(14) [lindex [time {
      initTest N
      setupWorkloadFileDb $dstFileName
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          set result [sql execute -execute scalar $db \
              "PRAGMA integrity_check;"]
1018
1019
1020
1021
1022
1023
1024

1025
1026
1027
1028
1029
1030
1031
  #############################################################################

  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 {







>







1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
  #############################################################################

  set workload(15) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #15, force managed garbage collection
    #
    waitTest O
    lappend ::times(15) [lindex [time {
      initTest O
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          collectGarbage $::test_channel
          showTest O
        } error]} then {
1045
1046
1047
1048
1049
1050
1051

1052
1053
1054
1055
1056
1057
1058
  #############################################################################

  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 {







>







1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
  #############################################################################

  set workload(16) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #16, allocate (exclude) some native heap memory
    #
    waitTest P
    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 {
1084
1085
1086
1087
1088
1089
1090

1091
1092
1093
1094
1095
1096
1097
  #############################################################################

  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"}] \"\;]







>







1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
  #############################################################################

  set workload(17) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #17, change the database journal mode
    #
    waitTest Q
    lappend ::times(17) [lindex [time {
      initTest Q
      setupWorkloadFileDb $dstFileName
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          sql execute $db [appendArgs "PRAGMA journal_mode = \"" \
              [expr {$index % 2 == 0 ? "delete" : "wal"}] \"\;]
1114
1115
1116
1117
1118
1119
1120

1121
1122
1123
1124
1125
1126
1127
  #############################################################################

  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.







>







1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
  #############################################################################

  set workload(18) [list \
      [list srcFileName dstFileName table count1 count2 count3] {
    #
    # NOTE: Workload #18, execute queries against the in-memory database
    #
    waitTest R
    lappend ::times(18) [lindex [time {
      initTest R
      setupWorkloadMemDb $srcFileName
      for {set index 1} {$index <= $count1} {incr index} {
        if {[catch {
          #
          # NOTE: Workload #18.3, "small" SELECT statements.
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
    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))
      }







|







<
|
|
|
>
>
>
>
>







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

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

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


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

    $event Set; # GO

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

    foreach index(1) [array names thread] {
      if {[info exists thread($index(1))] && \
          [cleanupThread $thread($index(1))]} then {
        unset -nocomplain thread($index(1))
      }
1346
1347
1348
1349
1350
1351
1352

1353
1354
1355
1356
1357
1358
1359

  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 ""







>







1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407

  rename freeMem ""
  rename useMem ""
  rename allocMem ""
  rename failTest ""
  rename doneTest ""
  rename showTest ""
  rename waitTest ""
  rename delayTest ""
  rename initTest ""
  rename isExpectedError ""
  rename formatWorkloadTime ""
  rename formatWorkloadResult ""
  rename setupWorkloadFileDb ""
  rename setupWorkloadMemDb ""
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391

1392
1393
1394
1395
1396
1397
1398
  }

  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}}

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

#
# NOTE: Report after test.
#

getSQLiteHandleCounts $test_channel
reportSQLiteResources $test_channel

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

runSQLiteTestEpilogue
runTestEpilogue







|
|








>







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
  }

  rename cleanupLogging ""
  rename setupLogging ""

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

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

#
# NOTE: Report after test.
#
checkForSQLiteDirectories $test_channel
getSQLiteHandleCounts $test_channel
reportSQLiteResources $test_channel

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

runSQLiteTestEpilogue
runTestEpilogue
Changes to Tests/thread.eagle.
86
87
88
89
90
91
92
93

94
95
96
97

98
99
100
101
102
103
104
    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)}));
  }]

  #
  # NOTE: The temporary directory must be reset here because it allocates

  #       some SQLite memory and this test requires an extremely accurate
  #       reading.
  #
  sql execute $db {

    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#







|
>
|
<


>







86
87
88
89
90
91
92
93
94
95

96
97
98
99
100
101
102
103
104
105
    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)}));
  }]

  #
  # NOTE: The data and temporary directories must be reset here (after the
  #       setupDb call above) because they allocate 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#
Added Tests/tkt-1c456ae75f.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
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
###############################################################################
#
# tkt-1c456ae75f.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-1c456ae75f-1.1 {unencrypted database, hex password} -setup {
  setupDb [set fileName tkt-1c456ae75f-1.1.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 "" "" "" "" "HexPassword=3132333435;" 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$}}

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

runTest {test tkt-1c456ae75f-1.2 {database, hex password} -setup {
  setupDb [set fileName tkt-1c456ae75f-1.2.db] "" "" "" "" \
      "HexPassword=3132333435;"
} -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 "" "" "" "" "HexPassword=3132333435;" 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 tkt-1c456ae75f-1.3 {database, wrong hex password} -setup {
  setupDb [set fileName tkt-1c456ae75f-1.3.db] "" "" "" "" \
      "HexPassword=3132333435;"
} -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 "" "" "" "" "HexPassword=3132333436;" 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 "" "" "" "" "HexPassword=3132333435;" 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 tkt-1c456ae75f-1.4 {database, hex password via builder} -setup {
  setupDb [set fileName tkt-1c456ae75f-1.4.db] "" "" "" "" \
      "HexPassword=3132333435;"
} -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 HexPassword [list 0x31 0x32 0x33 0x34 0x35]

  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=\"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 {
  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}}

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

runSQLiteTestEpilogue
runTestEpilogue
Added Tests/tkt-393d954be0.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
###############################################################################
#
# tkt-393d954be0.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-393d954be0-1.1 {custom connection pool} -setup {
  set nullPool [object create -flags +NonPublic -alias \
      System.Data.SQLite.NullConnectionPool true]

  object invoke System.Data.SQLite.SQLiteConnection ConnectionPool $nullPool

  setupDb [set fileName tkt-393d954be0-1.1.db] "" "" "" "" "Pooling=True;"
} -body {
  set exists(0) [file exists [file join [getDatabaseDirectory] [file tail \
      $fileName]]]

  cleanupDb $fileName

  set exists(1) [file exists [file join [getDatabaseDirectory] [file tail \
      $fileName]]]

  set counts null; set openCount 0; set closeCount 0; set totalCount 0
  object invoke -flags +NonPublic System.Data.SQLite.SQLiteConnectionPool \
      GetCounts $fileName counts openCount closeCount totalCount

  object invoke -flags +NonPublic System.Data.SQLite.SQLiteConnectionPool \
      ClearPool $fileName

  object invoke -flags +NonPublic System.Data.SQLite.SQLiteConnectionPool \
      ClearAllPools

  list $exists(0) $exists(1) $counts $openCount $closeCount $totalCount \
      [object invoke $nullPool ToString]
} -cleanup {
  cleanupDb $fileName

  catch {object invoke System.Data.SQLite.SQLiteConnection ConnectionPool null}

  unset -nocomplain db fileName exists counts openCount closeCount totalCount \
      nullPool
} -constraints {eagle monoBug28 buildConfiguration.Debug command.sql\
compile.DATA SQLite System.Data.SQLite} -match regexp -result [string map \
[list \n \r\n] {^True False \{\} 0 0 0\
\{Remove\(".*?\\tkt-393d954be0-1\.1\.db",\
100, 0\)
Add\(".*?\\tkt-393d954be0-1\.1\.db", -?\d+, 0\)
GetCounts\("tkt-393d954be0-1\.1\.db", , 0, 0, 0\)
ClearPool\("tkt-393d954be0-1\.1\.db"\)
ClearAllPools\(\)
\}$}]}

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

runSQLiteTestEpilogue
runTestEpilogue
Added 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
Changes to Tests/tkt-ae5267b863.eagle.
16
17
18
19
20
21
22




23
24
25
26
27
28
29
###############################################################################

package require System.Data.SQLite.Test
runSQLiteTestPrologue

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





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) { \







>
>
>
>







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
###############################################################################

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) { \
138
139
140
141
142
143
144
145
146

147
148
149
150
151
152
      [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 \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -match \

regexp -result {^Ok System#CodeDom#Compiler#CompilerResults#\d+ \{\} 0 \{\}$}}

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

runSQLiteTestEpilogue
runTestEpilogue







|
|
>
|





142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
      [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\
!defineConstant.System.Data.SQLite.INTEROP_LEGACY_CLOSE}] -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
###############################################################################

package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

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);"








|







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 {
  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);"

Added Tests/tkt-c010fa6584.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
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
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
###############################################################################
#
# tkt-c010fa6584.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-c010fa6584-1.1 {column "integral" type handling} -setup {
  setupDb [set fileName tkt-c010fa6584-1.1.db]
} -body {
  #
  # NOTE: Create a database table with all the integral type names that are
  #       recognized by System.Data.SQLite.  Subsequently, each column will
  #       be tested against a list of values that meet and/or exceed the
  #       bounds for the underlying primitive integral CLR type.
  #
  sql execute $db {
    CREATE TABLE t1(
      a00 SYSNAME,           -- This is the 'payload' column name.
      a01,                   -- String
      a02 TEXT,              -- String
      a03 BIGINT,            -- Int64
      a04 BIGUINT,           -- UInt64
      a05 COUNTER,           -- Int64
      a06 IDENTITY,          -- Int64
      a07 INT,               -- Int32
      a08 INT8,              -- SByte
      a09 INT16,             -- Int16
      a10 INT32,             -- Int32
      a11 INT64,             -- Int64
      a12 INTEGER,           -- Int64
      a13 INTEGER8,          -- SByte
      a14 INTEGER16,         -- Int16
      a15 INTEGER32,         -- Int32
      a16 INTEGER64,         -- Int64
      a17 LONG,              -- Int64
      a18 SMALLINT,          -- Int16
      a19 SMALLUINT,         -- UInt16
      a20 TINYINT,           -- Byte
      a21 TINYSINT,          -- SByte
      a22 UINT,              -- UInt32
      a23 UINT8,             -- Byte
      a24 UINT16,            -- UInt16
      a25 UINT32,            -- UInt32
      a26 UINT64,            -- UInt64
      a27 ULONG,             -- UInt64
      a28 UNSIGNEDINTEGER,   -- UInt32
      a29 UNSIGNEDINTEGER8,  -- Byte
      a30 UNSIGNEDINTEGER16, -- UInt16
      a31 UNSIGNEDINTEGER32, -- UInt32
      a32 UNSIGNEDINTEGER64  -- UInt64
    );
  }

  #
  # NOTE: These are the numeric values being tested against all the types in
  #       the database table defined above.  This list includes values that
  #       are out-of-bounds for each primitive integral type.
  #
  set values [list \
      -9223372036854775809 -9223372036854775808 \
      -2147483649 -2147483648 \
      -32769 -32768 \
      -129 -128 \
      -1 0 1 \
      127 128 \
      255 256 \
      32767 32768 \
      65535 65536 \
      2147483647 2147483648 \
      4294967295 4294967296 \
      9223372036854775807 9223372036854775808 \
      18446744073709551615 18446744073709551616]

  for {set index 1} {$index <= 32} {incr index} {
    set name [appendArgs a [format %02d $index]]
    foreach value $values {
      sql execute $db [subst {
        INSERT INTO t1 (a00, $name) VALUES('$name', $value);
      }]
    }
  }

  set results [list]

  for {set index 1} {$index <= 32} {incr index} {
    set name [appendArgs a [format %02d $index]]
    set count [sql execute -execute scalar $db [subst {
      SELECT COUNT(*) FROM t1 WHERE a00 = '$name';
    }]]
    for {set offset 0} {$offset < $count} {incr offset} {
      set code [catch {
        sql execute -execute scalar $db [subst {
          SELECT $name FROM t1 WHERE a00 = '$name' LIMIT 1 OFFSET $offset;
        }]
      } result]

      set match [expr {$result eq [lindex $values $offset]}]

      lappend results [list \
          $name $offset $match [lindex $values $offset] \
          $code [expr {$code == 0 ? $result : $errorCode}]]
    }
  }

  set results
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain match result code offset count results value name index \
      values db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{{a01 0 False -9223372036854775809 0 -9.22337203685478E+18} {a01 1 True\
-9223372036854775808 0 -9223372036854775808} {a01 2 True -2147483649 0\
-2147483649} {a01 3 True -2147483648 0 -2147483648} {a01 4 True -32769 0\
-32769} {a01 5 True -32768 0 -32768} {a01 6 True -129 0 -129} {a01 7 True -128\
0 -128} {a01 8 True -1 0 -1} {a01 9 True 0 0 0} {a01 10 True 1 0 1} {a01 11\
True 127 0 127} {a01 12 True 128 0 128} {a01 13 True 255 0 255} {a01 14 True\
256 0 256} {a01 15 True 32767 0 32767} {a01 16 True 32768 0 32768} {a01 17 True\
65535 0 65535} {a01 18 True 65536 0 65536} {a01 19 True 2147483647 0\
2147483647} {a01 20 True 2147483648 0 2147483648} {a01 21 True 4294967295 0\
4294967295} {a01 22 True 4294967296 0 4294967296} {a01 23 True\
9223372036854775807 0 9223372036854775807} {a01 24 False 9223372036854775808 0\
9.22337203685478E+18} {a01 25 False 18446744073709551615 0\
1.84467440737096E+19} {a01 26 False 18446744073709551616 0\
1.84467440737096E+19} {a02 0 False -9223372036854775809 0\
-9.22337203685478e+18} {a02 1 True -9223372036854775808 0 -9223372036854775808}\
{a02 2 True -2147483649 0 -2147483649} {a02 3 True -2147483648 0 -2147483648}\
{a02 4 True -32769 0 -32769} {a02 5 True -32768 0 -32768} {a02 6 True -129 0\
-129} {a02 7 True -128 0 -128} {a02 8 True -1 0 -1} {a02 9 True 0 0 0} {a02 10\
True 1 0 1} {a02 11 True 127 0 127} {a02 12 True 128 0 128} {a02 13 True 255 0\
255} {a02 14 True 256 0 256} {a02 15 True 32767 0 32767} {a02 16 True 32768 0\
32768} {a02 17 True 65535 0 65535} {a02 18 True 65536 0 65536} {a02 19 True\
2147483647 0 2147483647} {a02 20 True 2147483648 0 2147483648} {a02 21 True\
4294967295 0 4294967295} {a02 22 True 4294967296 0 4294967296} {a02 23 True\
9223372036854775807 0 9223372036854775807} {a02 24 False 9223372036854775808 0\
9.22337203685478e+18} {a02 25 False 18446744073709551615 0\
1.84467440737096e+19} {a02 26 False 18446744073709551616 0\
1.84467440737096e+19} {a03 0 False -9223372036854775809 0 -9223372036854775808}\
{a03 1 True -9223372036854775808 0 -9223372036854775808} {a03 2 True\
-2147483649 0 -2147483649} {a03 3 True -2147483648 0 -2147483648} {a03 4 True\
-32769 0 -32769} {a03 5 True -32768 0 -32768} {a03 6 True -129 0 -129} {a03 7\
True -128 0 -128} {a03 8 True -1 0 -1} {a03 9 True 0 0 0} {a03 10 True 1 0 1}\
{a03 11 True 127 0 127} {a03 12 True 128 0 128} {a03 13 True 255 0 255} {a03 14\
True 256 0 256} {a03 15 True 32767 0 32767} {a03 16 True 32768 0 32768} {a03 17\
True 65535 0 65535} {a03 18 True 65536 0 65536} {a03 19 True 2147483647 0\
2147483647} {a03 20 True 2147483648 0 2147483648} {a03 21 True 4294967295 0\
4294967295} {a03 22 True 4294967296 0 4294967296} {a03 23 True\
9223372036854775807 0 9223372036854775807} {a03 24 False 9223372036854775808 0\
-9223372036854775808} {a03 25 False 18446744073709551615 0\
-9223372036854775808} {a03 26 False 18446744073709551616 0\
-9223372036854775808} {a04 0 False -9223372036854775809 0 9223372036854775808}\
{a04 1 False -9223372036854775808 0 9223372036854775808} {a04 2 False\
-2147483649 0 18446744071562067967} {a04 3 False -2147483648 0\
18446744071562067968} {a04 4 False -32769 0 18446744073709518847} {a04 5 False\
-32768 0 18446744073709518848} {a04 6 False -129 0 18446744073709551487} {a04 7\
False -128 0 18446744073709551488} {a04 8 False -1 0 18446744073709551615} {a04\
9 True 0 0 0} {a04 10 True 1 0 1} {a04 11 True 127 0 127} {a04 12 True 128 0\
128} {a04 13 True 255 0 255} {a04 14 True 256 0 256} {a04 15 True 32767 0\
32767} {a04 16 True 32768 0 32768} {a04 17 True 65535 0 65535} {a04 18 True\
65536 0 65536} {a04 19 True 2147483647 0 2147483647} {a04 20 True 2147483648 0\
2147483648} {a04 21 True 4294967295 0 4294967295} {a04 22 True 4294967296 0\
4294967296} {a04 23 True 9223372036854775807 0 9223372036854775807} {a04 24\
True 9223372036854775808 0 9223372036854775808} {a04 25 False\
18446744073709551615 0 9223372036854775808} {a04 26 False 18446744073709551616\
0 9223372036854775808} {a05 0 False -9223372036854775809 0\
-9223372036854775808} {a05 1 True -9223372036854775808 0 -9223372036854775808}\
{a05 2 True -2147483649 0 -2147483649} {a05 3 True -2147483648 0 -2147483648}\
{a05 4 True -32769 0 -32769} {a05 5 True -32768 0 -32768} {a05 6 True -129 0\
-129} {a05 7 True -128 0 -128} {a05 8 True -1 0 -1} {a05 9 True 0 0 0} {a05 10\
True 1 0 1} {a05 11 True 127 0 127} {a05 12 True 128 0 128} {a05 13 True 255 0\
255} {a05 14 True 256 0 256} {a05 15 True 32767 0 32767} {a05 16 True 32768 0\
32768} {a05 17 True 65535 0 65535} {a05 18 True 65536 0 65536} {a05 19 True\
2147483647 0 2147483647} {a05 20 True 2147483648 0 2147483648} {a05 21 True\
4294967295 0 4294967295} {a05 22 True 4294967296 0 4294967296} {a05 23 True\
9223372036854775807 0 9223372036854775807} {a05 24 False 9223372036854775808 0\
-9223372036854775808} {a05 25 False 18446744073709551615 0\
-9223372036854775808} {a05 26 False 18446744073709551616 0\
-9223372036854775808} {a06 0 False -9223372036854775809 0 -9223372036854775808}\
{a06 1 True -9223372036854775808 0 -9223372036854775808} {a06 2 True\
-2147483649 0 -2147483649} {a06 3 True -2147483648 0 -2147483648} {a06 4 True\
-32769 0 -32769} {a06 5 True -32768 0 -32768} {a06 6 True -129 0 -129} {a06 7\
True -128 0 -128} {a06 8 True -1 0 -1} {a06 9 True 0 0 0} {a06 10 True 1 0 1}\
{a06 11 True 127 0 127} {a06 12 True 128 0 128} {a06 13 True 255 0 255} {a06 14\
True 256 0 256} {a06 15 True 32767 0 32767} {a06 16 True 32768 0 32768} {a06 17\
True 65535 0 65535} {a06 18 True 65536 0 65536} {a06 19 True 2147483647 0\
2147483647} {a06 20 True 2147483648 0 2147483648} {a06 21 True 4294967295 0\
4294967295} {a06 22 True 4294967296 0 4294967296} {a06 23 True\
9223372036854775807 0 9223372036854775807} {a06 24 False 9223372036854775808 0\
-9223372036854775808} {a06 25 False 18446744073709551615 0\
-9223372036854775808} {a06 26 False 18446744073709551616 0\
-9223372036854775808} {a07 0 False -9223372036854775809 0 0} {a07 1 False\
-9223372036854775808 0 0} {a07 2 False -2147483649 0 2147483647} {a07 3 True\
-2147483648 0 -2147483648} {a07 4 True -32769 0 -32769} {a07 5 True -32768 0\
-32768} {a07 6 True -129 0 -129} {a07 7 True -128 0 -128} {a07 8 True -1 0 -1}\
{a07 9 True 0 0 0} {a07 10 True 1 0 1} {a07 11 True 127 0 127} {a07 12 True 128\
0 128} {a07 13 True 255 0 255} {a07 14 True 256 0 256} {a07 15 True 32767 0\
32767} {a07 16 True 32768 0 32768} {a07 17 True 65535 0 65535} {a07 18 True\
65536 0 65536} {a07 19 True 2147483647 0 2147483647} {a07 20 False 2147483648 0\
-2147483648} {a07 21 False 4294967295 0 -1} {a07 22 False 4294967296 0 0} {a07\
23 False 9223372036854775807 0 -1} {a07 24 False 9223372036854775808 0 0} {a07\
25 False 18446744073709551615 0 0} {a07 26 False 18446744073709551616 0 0} {a08\
0 False -9223372036854775809 0 0} {a08 1 False -9223372036854775808 0 0} {a08 2\
False -2147483649 0 -1} {a08 3 False -2147483648 0 0} {a08 4 False -32769 0 -1}\
{a08 5 False -32768 0 0} {a08 6 False -129 0 127} {a08 7 True -128 0 -128} {a08\
8 True -1 0 -1} {a08 9 True 0 0 0} {a08 10 True 1 0 1} {a08 11 True 127 0 127}\
{a08 12 False 128 0 -128} {a08 13 False 255 0 -1} {a08 14 False 256 0 0} {a08\
15 False 32767 0 -1} {a08 16 False 32768 0 0} {a08 17 False 65535 0 -1} {a08 18\
False 65536 0 0} {a08 19 False 2147483647 0 -1} {a08 20 False 2147483648 0 0}\
{a08 21 False 4294967295 0 -1} {a08 22 False 4294967296 0 0} {a08 23 False\
9223372036854775807 0 -1} {a08 24 False 9223372036854775808 0 0} {a08 25 False\
18446744073709551615 0 0} {a08 26 False 18446744073709551616 0 0} {a09 0 False\
-9223372036854775809 0 0} {a09 1 False -9223372036854775808 0 0} {a09 2 False\
-2147483649 0 -1} {a09 3 False -2147483648 0 0} {a09 4 False -32769 0 32767}\
{a09 5 True -32768 0 -32768} {a09 6 True -129 0 -129} {a09 7 True -128 0 -128}\
{a09 8 True -1 0 -1} {a09 9 True 0 0 0} {a09 10 True 1 0 1} {a09 11 True 127 0\
127} {a09 12 True 128 0 128} {a09 13 True 255 0 255} {a09 14 True 256 0 256}\
{a09 15 True 32767 0 32767} {a09 16 False 32768 0 -32768} {a09 17 False 65535 0\
-1} {a09 18 False 65536 0 0} {a09 19 False 2147483647 0 -1} {a09 20 False\
2147483648 0 0} {a09 21 False 4294967295 0 -1} {a09 22 False 4294967296 0 0}\
{a09 23 False 9223372036854775807 0 -1} {a09 24 False 9223372036854775808 0 0}\
{a09 25 False 18446744073709551615 0 0} {a09 26 False 18446744073709551616 0 0}\
{a10 0 False -9223372036854775809 0 0} {a10 1 False -9223372036854775808 0 0}\
{a10 2 False -2147483649 0 2147483647} {a10 3 True -2147483648 0 -2147483648}\
{a10 4 True -32769 0 -32769} {a10 5 True -32768 0 -32768} {a10 6 True -129 0\
-129} {a10 7 True -128 0 -128} {a10 8 True -1 0 -1} {a10 9 True 0 0 0} {a10 10\
True 1 0 1} {a10 11 True 127 0 127} {a10 12 True 128 0 128} {a10 13 True 255 0\
255} {a10 14 True 256 0 256} {a10 15 True 32767 0 32767} {a10 16 True 32768 0\
32768} {a10 17 True 65535 0 65535} {a10 18 True 65536 0 65536} {a10 19 True\
2147483647 0 2147483647} {a10 20 False 2147483648 0 -2147483648} {a10 21 False\
4294967295 0 -1} {a10 22 False 4294967296 0 0} {a10 23 False\
9223372036854775807 0 -1} {a10 24 False 9223372036854775808 0 0} {a10 25 False\
18446744073709551615 0 0} {a10 26 False 18446744073709551616 0 0} {a11 0 False\
-9223372036854775809 0 -9223372036854775808} {a11 1 True -9223372036854775808 0\
-9223372036854775808} {a11 2 True -2147483649 0 -2147483649} {a11 3 True\
-2147483648 0 -2147483648} {a11 4 True -32769 0 -32769} {a11 5 True -32768 0\
-32768} {a11 6 True -129 0 -129} {a11 7 True -128 0 -128} {a11 8 True -1 0 -1}\
{a11 9 True 0 0 0} {a11 10 True 1 0 1} {a11 11 True 127 0 127} {a11 12 True 128\
0 128} {a11 13 True 255 0 255} {a11 14 True 256 0 256} {a11 15 True 32767 0\
32767} {a11 16 True 32768 0 32768} {a11 17 True 65535 0 65535} {a11 18 True\
65536 0 65536} {a11 19 True 2147483647 0 2147483647} {a11 20 True 2147483648 0\
2147483648} {a11 21 True 4294967295 0 4294967295} {a11 22 True 4294967296 0\
4294967296} {a11 23 True 9223372036854775807 0 9223372036854775807} {a11 24\
False 9223372036854775808 0 -9223372036854775808} {a11 25 False\
18446744073709551615 0 -9223372036854775808} {a11 26 False 18446744073709551616\
0 -9223372036854775808} {a12 0 False -9223372036854775809 0\
-9223372036854775808} {a12 1 True -9223372036854775808 0 -9223372036854775808}\
{a12 2 True -2147483649 0 -2147483649} {a12 3 True -2147483648 0 -2147483648}\
{a12 4 True -32769 0 -32769} {a12 5 True -32768 0 -32768} {a12 6 True -129 0\
-129} {a12 7 True -128 0 -128} {a12 8 True -1 0 -1} {a12 9 True 0 0 0} {a12 10\
True 1 0 1} {a12 11 True 127 0 127} {a12 12 True 128 0 128} {a12 13 True 255 0\
255} {a12 14 True 256 0 256} {a12 15 True 32767 0 32767} {a12 16 True 32768 0\
32768} {a12 17 True 65535 0 65535} {a12 18 True 65536 0 65536} {a12 19 True\
2147483647 0 2147483647} {a12 20 True 2147483648 0 2147483648} {a12 21 True\
4294967295 0 4294967295} {a12 22 True 4294967296 0 4294967296} {a12 23 True\
9223372036854775807 0 9223372036854775807} {a12 24 False 9223372036854775808 0\
-9223372036854775808} {a12 25 False 18446744073709551615 0\
-9223372036854775808} {a12 26 False 18446744073709551616 0\
-9223372036854775808} {a13 0 False -9223372036854775809 0 0} {a13 1 False\
-9223372036854775808 0 0} {a13 2 False -2147483649 0 -1} {a13 3 False\
-2147483648 0 0} {a13 4 False -32769 0 -1} {a13 5 False -32768 0 0} {a13 6\
False -129 0 127} {a13 7 True -128 0 -128} {a13 8 True -1 0 -1} {a13 9 True 0 0\
0} {a13 10 True 1 0 1} {a13 11 True 127 0 127} {a13 12 False 128 0 -128} {a13\
13 False 255 0 -1} {a13 14 False 256 0 0} {a13 15 False 32767 0 -1} {a13 16\
False 32768 0 0} {a13 17 False 65535 0 -1} {a13 18 False 65536 0 0} {a13 19\
False 2147483647 0 -1} {a13 20 False 2147483648 0 0} {a13 21 False 4294967295 0\
-1} {a13 22 False 4294967296 0 0} {a13 23 False 9223372036854775807 0 -1} {a13\
24 False 9223372036854775808 0 0} {a13 25 False 18446744073709551615 0 0} {a13\
26 False 18446744073709551616 0 0} {a14 0 False -9223372036854775809 0 0} {a14\
1 False -9223372036854775808 0 0} {a14 2 False -2147483649 0 -1} {a14 3 False\
-2147483648 0 0} {a14 4 False -32769 0 32767} {a14 5 True -32768 0 -32768} {a14\
6 True -129 0 -129} {a14 7 True -128 0 -128} {a14 8 True -1 0 -1} {a14 9 True 0\
0 0} {a14 10 True 1 0 1} {a14 11 True 127 0 127} {a14 12 True 128 0 128} {a14\
13 True 255 0 255} {a14 14 True 256 0 256} {a14 15 True 32767 0 32767} {a14 16\
False 32768 0 -32768} {a14 17 False 65535 0 -1} {a14 18 False 65536 0 0} {a14\
19 False 2147483647 0 -1} {a14 20 False 2147483648 0 0} {a14 21 False\
4294967295 0 -1} {a14 22 False 4294967296 0 0} {a14 23 False\
9223372036854775807 0 -1} {a14 24 False 9223372036854775808 0 0} {a14 25 False\
18446744073709551615 0 0} {a14 26 False 18446744073709551616 0 0} {a15 0 False\
-9223372036854775809 0 0} {a15 1 False -9223372036854775808 0 0} {a15 2 False\
-2147483649 0 2147483647} {a15 3 True -2147483648 0 -2147483648} {a15 4 True\
-32769 0 -32769} {a15 5 True -32768 0 -32768} {a15 6 True -129 0 -129} {a15 7\
True -128 0 -128} {a15 8 True -1 0 -1} {a15 9 True 0 0 0} {a15 10 True 1 0 1}\
{a15 11 True 127 0 127} {a15 12 True 128 0 128} {a15 13 True 255 0 255} {a15 14\
True 256 0 256} {a15 15 True 32767 0 32767} {a15 16 True 32768 0 32768} {a15 17\
True 65535 0 65535} {a15 18 True 65536 0 65536} {a15 19 True 2147483647 0\
2147483647} {a15 20 False 2147483648 0 -2147483648} {a15 21 False 4294967295 0\
-1} {a15 22 False 4294967296 0 0} {a15 23 False 9223372036854775807 0 -1} {a15\
24 False 9223372036854775808 0 0} {a15 25 False 18446744073709551615 0 0} {a15\
26 False 18446744073709551616 0 0} {a16 0 False -9223372036854775809 0\
-9223372036854775808} {a16 1 True -9223372036854775808 0 -9223372036854775808}\
{a16 2 True -2147483649 0 -2147483649} {a16 3 True -2147483648 0 -2147483648}\
{a16 4 True -32769 0 -32769} {a16 5 True -32768 0 -32768} {a16 6 True -129 0\
-129} {a16 7 True -128 0 -128} {a16 8 True -1 0 -1} {a16 9 True 0 0 0} {a16 10\
True 1 0 1} {a16 11 True 127 0 127} {a16 12 True 128 0 128} {a16 13 True 255 0\
255} {a16 14 True 256 0 256} {a16 15 True 32767 0 32767} {a16 16 True 32768 0\
32768} {a16 17 True 65535 0 65535} {a16 18 True 65536 0 65536} {a16 19 True\
2147483647 0 2147483647} {a16 20 True 2147483648 0 2147483648} {a16 21 True\
4294967295 0 4294967295} {a16 22 True 4294967296 0 4294967296} {a16 23 True\
9223372036854775807 0 9223372036854775807} {a16 24 False 9223372036854775808 0\
-9223372036854775808} {a16 25 False 18446744073709551615 0\
-9223372036854775808} {a16 26 False 18446744073709551616 0\
-9223372036854775808} {a17 0 False -9223372036854775809 0 -9223372036854775808}\
{a17 1 True -9223372036854775808 0 -9223372036854775808} {a17 2 True\
-2147483649 0 -2147483649} {a17 3 True -2147483648 0 -2147483648} {a17 4 True\
-32769 0 -32769} {a17 5 True -32768 0 -32768} {a17 6 True -129 0 -129} {a17 7\
True -128 0 -128} {a17 8 True -1 0 -1} {a17 9 True 0 0 0} {a17 10 True 1 0 1}\
{a17 11 True 127 0 127} {a17 12 True 128 0 128} {a17 13 True 255 0 255} {a17 14\
True 256 0 256} {a17 15 True 32767 0 32767} {a17 16 True 32768 0 32768} {a17 17\
True 65535 0 65535} {a17 18 True 65536 0 65536} {a17 19 True 2147483647 0\
2147483647} {a17 20 True 2147483648 0 2147483648} {a17 21 True 4294967295 0\
4294967295} {a17 22 True 4294967296 0 4294967296} {a17 23 True\
9223372036854775807 0 9223372036854775807} {a17 24 False 9223372036854775808 0\
-9223372036854775808} {a17 25 False 18446744073709551615 0\
-9223372036854775808} {a17 26 False 18446744073709551616 0\
-9223372036854775808} {a18 0 False -9223372036854775809 0 0} {a18 1 False\
-9223372036854775808 0 0} {a18 2 False -2147483649 0 -1} {a18 3 False\
-2147483648 0 0} {a18 4 False -32769 0 32767} {a18 5 True -32768 0 -32768} {a18\
6 True -129 0 -129} {a18 7 True -128 0 -128} {a18 8 True -1 0 -1} {a18 9 True 0\
0 0} {a18 10 True 1 0 1} {a18 11 True 127 0 127} {a18 12 True 128 0 128} {a18\
13 True 255 0 255} {a18 14 True 256 0 256} {a18 15 True 32767 0 32767} {a18 16\
False 32768 0 -32768} {a18 17 False 65535 0 -1} {a18 18 False 65536 0 0} {a18\
19 False 2147483647 0 -1} {a18 20 False 2147483648 0 0} {a18 21 False\
4294967295 0 -1} {a18 22 False 4294967296 0 0} {a18 23 False\
9223372036854775807 0 -1} {a18 24 False 9223372036854775808 0 0} {a18 25 False\
18446744073709551615 0 0} {a18 26 False 18446744073709551616 0 0} {a19 0 False\
-9223372036854775809 0 0} {a19 1 False -9223372036854775808 0 0} {a19 2 False\
-2147483649 0 65535} {a19 3 False -2147483648 0 0} {a19 4 False -32769 0 32767}\
{a19 5 False -32768 0 32768} {a19 6 False -129 0 65407} {a19 7 False -128 0\
65408} {a19 8 False -1 0 65535} {a19 9 True 0 0 0} {a19 10 True 1 0 1} {a19 11\
True 127 0 127} {a19 12 True 128 0 128} {a19 13 True 255 0 255} {a19 14 True\
256 0 256} {a19 15 True 32767 0 32767} {a19 16 True 32768 0 32768} {a19 17 True\
65535 0 65535} {a19 18 False 65536 0 0} {a19 19 False 2147483647 0 65535} {a19\
20 False 2147483648 0 0} {a19 21 False 4294967295 0 65535} {a19 22 False\
4294967296 0 0} {a19 23 False 9223372036854775807 0 65535} {a19 24 False\
9223372036854775808 0 0} {a19 25 False 18446744073709551615 0 0} {a19 26 False\
18446744073709551616 0 0} {a20 0 False -9223372036854775809 0 0} {a20 1 False\
-9223372036854775808 0 0} {a20 2 False -2147483649 0 255} {a20 3 False\
-2147483648 0 0} {a20 4 False -32769 0 255} {a20 5 False -32768 0 0} {a20 6\
False -129 0 127} {a20 7 False -128 0 128} {a20 8 False -1 0 255} {a20 9 True 0\
0 0} {a20 10 True 1 0 1} {a20 11 True 127 0 127} {a20 12 True 128 0 128} {a20\
13 True 255 0 255} {a20 14 False 256 0 0} {a20 15 False 32767 0 255} {a20 16\
False 32768 0 0} {a20 17 False 65535 0 255} {a20 18 False 65536 0 0} {a20 19\
False 2147483647 0 255} {a20 20 False 2147483648 0 0} {a20 21 False 4294967295\
0 255} {a20 22 False 4294967296 0 0} {a20 23 False 9223372036854775807 0 255}\
{a20 24 False 9223372036854775808 0 0} {a20 25 False 18446744073709551615 0 0}\
{a20 26 False 18446744073709551616 0 0} {a21 0 False -9223372036854775809 0 0}\
{a21 1 False -9223372036854775808 0 0} {a21 2 False -2147483649 0 -1} {a21 3\
False -2147483648 0 0} {a21 4 False -32769 0 -1} {a21 5 False -32768 0 0} {a21\
6 False -129 0 127} {a21 7 True -128 0 -128} {a21 8 True -1 0 -1} {a21 9 True 0\
0 0} {a21 10 True 1 0 1} {a21 11 True 127 0 127} {a21 12 False 128 0 -128} {a21\
13 False 255 0 -1} {a21 14 False 256 0 0} {a21 15 False 32767 0 -1} {a21 16\
False 32768 0 0} {a21 17 False 65535 0 -1} {a21 18 False 65536 0 0} {a21 19\
False 2147483647 0 -1} {a21 20 False 2147483648 0 0} {a21 21 False 4294967295 0\
-1} {a21 22 False 4294967296 0 0} {a21 23 False 9223372036854775807 0 -1} {a21\
24 False 9223372036854775808 0 0} {a21 25 False 18446744073709551615 0 0} {a21\
26 False 18446744073709551616 0 0} {a22 0 False -9223372036854775809 0 0} {a22\
1 False -9223372036854775808 0 0} {a22 2 False -2147483649 0 2147483647} {a22 3\
False -2147483648 0 2147483648} {a22 4 False -32769 0 4294934527} {a22 5 False\
-32768 0 4294934528} {a22 6 False -129 0 4294967167} {a22 7 False -128 0\
4294967168} {a22 8 False -1 0 4294967295} {a22 9 True 0 0 0} {a22 10 True 1 0\
1} {a22 11 True 127 0 127} {a22 12 True 128 0 128} {a22 13 True 255 0 255} {a22\
14 True 256 0 256} {a22 15 True 32767 0 32767} {a22 16 True 32768 0 32768} {a22\
17 True 65535 0 65535} {a22 18 True 65536 0 65536} {a22 19 True 2147483647 0\
2147483647} {a22 20 True 2147483648 0 2147483648} {a22 21 True 4294967295 0\
4294967295} {a22 22 False 4294967296 0 0} {a22 23 False 9223372036854775807 0\
4294967295} {a22 24 False 9223372036854775808 0 0} {a22 25 False\
18446744073709551615 0 0} {a22 26 False 18446744073709551616 0 0} {a23 0 False\
-9223372036854775809 0 0} {a23 1 False -9223372036854775808 0 0} {a23 2 False\
-2147483649 0 255} {a23 3 False -2147483648 0 0} {a23 4 False -32769 0 255}\
{a23 5 False -32768 0 0} {a23 6 False -129 0 127} {a23 7 False -128 0 128} {a23\
8 False -1 0 255} {a23 9 True 0 0 0} {a23 10 True 1 0 1} {a23 11 True 127 0\
127} {a23 12 True 128 0 128} {a23 13 True 255 0 255} {a23 14 False 256 0 0}\
{a23 15 False 32767 0 255} {a23 16 False 32768 0 0} {a23 17 False 65535 0 255}\
{a23 18 False 65536 0 0} {a23 19 False 2147483647 0 255} {a23 20 False\
2147483648 0 0} {a23 21 False 4294967295 0 255} {a23 22 False 4294967296 0 0}\
{a23 23 False 9223372036854775807 0 255} {a23 24 False 9223372036854775808 0 0}\
{a23 25 False 18446744073709551615 0 0} {a23 26 False 18446744073709551616 0 0}\
{a24 0 False -9223372036854775809 0 0} {a24 1 False -9223372036854775808 0 0}\
{a24 2 False -2147483649 0 65535} {a24 3 False -2147483648 0 0} {a24 4 False\
-32769 0 32767} {a24 5 False -32768 0 32768} {a24 6 False -129 0 65407} {a24 7\
False -128 0 65408} {a24 8 False -1 0 65535} {a24 9 True 0 0 0} {a24 10 True 1\
0 1} {a24 11 True 127 0 127} {a24 12 True 128 0 128} {a24 13 True 255 0 255}\
{a24 14 True 256 0 256} {a24 15 True 32767 0 32767} {a24 16 True 32768 0 32768}\
{a24 17 True 65535 0 65535} {a24 18 False 65536 0 0} {a24 19 False 2147483647 0\
65535} {a24 20 False 2147483648 0 0} {a24 21 False 4294967295 0 65535} {a24 22\
False 4294967296 0 0} {a24 23 False 9223372036854775807 0 65535} {a24 24 False\
9223372036854775808 0 0} {a24 25 False 18446744073709551615 0 0} {a24 26 False\
18446744073709551616 0 0} {a25 0 False -9223372036854775809 0 0} {a25 1 False\
-9223372036854775808 0 0} {a25 2 False -2147483649 0 2147483647} {a25 3 False\
-2147483648 0 2147483648} {a25 4 False -32769 0 4294934527} {a25 5 False -32768\
0 4294934528} {a25 6 False -129 0 4294967167} {a25 7 False -128 0 4294967168}\
{a25 8 False -1 0 4294967295} {a25 9 True 0 0 0} {a25 10 True 1 0 1} {a25 11\
True 127 0 127} {a25 12 True 128 0 128} {a25 13 True 255 0 255} {a25 14 True\
256 0 256} {a25 15 True 32767 0 32767} {a25 16 True 32768 0 32768} {a25 17 True\
65535 0 65535} {a25 18 True 65536 0 65536} {a25 19 True 2147483647 0\
2147483647} {a25 20 True 2147483648 0 2147483648} {a25 21 True 4294967295 0\
4294967295} {a25 22 False 4294967296 0 0} {a25 23 False 9223372036854775807 0\
4294967295} {a25 24 False 9223372036854775808 0 0} {a25 25 False\
18446744073709551615 0 0} {a25 26 False 18446744073709551616 0 0} {a26 0 False\
-9223372036854775809 0 9223372036854775808} {a26 1 False -9223372036854775808 0\
9223372036854775808} {a26 2 False -2147483649 0 18446744071562067967} {a26 3\
False -2147483648 0 18446744071562067968} {a26 4 False -32769 0\
18446744073709518847} {a26 5 False -32768 0 18446744073709518848} {a26 6 False\
-129 0 18446744073709551487} {a26 7 False -128 0 18446744073709551488} {a26 8\
False -1 0 18446744073709551615} {a26 9 True 0 0 0} {a26 10 True 1 0 1} {a26 11\
True 127 0 127} {a26 12 True 128 0 128} {a26 13 True 255 0 255} {a26 14 True\
256 0 256} {a26 15 True 32767 0 32767} {a26 16 True 32768 0 32768} {a26 17 True\
65535 0 65535} {a26 18 True 65536 0 65536} {a26 19 True 2147483647 0\
2147483647} {a26 20 True 2147483648 0 2147483648} {a26 21 True 4294967295 0\
4294967295} {a26 22 True 4294967296 0 4294967296} {a26 23 True\
9223372036854775807 0 9223372036854775807} {a26 24 True 9223372036854775808 0\
9223372036854775808} {a26 25 False 18446744073709551615 0 9223372036854775808}\
{a26 26 False 18446744073709551616 0 9223372036854775808} {a27 0 False\
-9223372036854775809 0 9223372036854775808} {a27 1 False -9223372036854775808 0\
9223372036854775808} {a27 2 False -2147483649 0 18446744071562067967} {a27 3\
False -2147483648 0 18446744071562067968} {a27 4 False -32769 0\
18446744073709518847} {a27 5 False -32768 0 18446744073709518848} {a27 6 False\
-129 0 18446744073709551487} {a27 7 False -128 0 18446744073709551488} {a27 8\
False -1 0 18446744073709551615} {a27 9 True 0 0 0} {a27 10 True 1 0 1} {a27 11\
True 127 0 127} {a27 12 True 128 0 128} {a27 13 True 255 0 255} {a27 14 True\
256 0 256} {a27 15 True 32767 0 32767} {a27 16 True 32768 0 32768} {a27 17 True\
65535 0 65535} {a27 18 True 65536 0 65536} {a27 19 True 2147483647 0\
2147483647} {a27 20 True 2147483648 0 2147483648} {a27 21 True 4294967295 0\
4294967295} {a27 22 True 4294967296 0 4294967296} {a27 23 True\
9223372036854775807 0 9223372036854775807} {a27 24 True 9223372036854775808 0\
9223372036854775808} {a27 25 False 18446744073709551615 0 9223372036854775808}\
{a27 26 False 18446744073709551616 0 9223372036854775808} {a28 0 False\
-9223372036854775809 0 9223372036854775808} {a28 1 False -9223372036854775808 0\
9223372036854775808} {a28 2 False -2147483649 0 18446744071562067967} {a28 3\
False -2147483648 0 18446744071562067968} {a28 4 False -32769 0\
18446744073709518847} {a28 5 False -32768 0 18446744073709518848} {a28 6 False\
-129 0 18446744073709551487} {a28 7 False -128 0 18446744073709551488} {a28 8\
False -1 0 18446744073709551615} {a28 9 True 0 0 0} {a28 10 True 1 0 1} {a28 11\
True 127 0 127} {a28 12 True 128 0 128} {a28 13 True 255 0 255} {a28 14 True\
256 0 256} {a28 15 True 32767 0 32767} {a28 16 True 32768 0 32768} {a28 17 True\
65535 0 65535} {a28 18 True 65536 0 65536} {a28 19 True 2147483647 0\
2147483647} {a28 20 True 2147483648 0 2147483648} {a28 21 True 4294967295 0\
4294967295} {a28 22 True 4294967296 0 4294967296} {a28 23 True\
9223372036854775807 0 9223372036854775807} {a28 24 True 9223372036854775808 0\
9223372036854775808} {a28 25 False 18446744073709551615 0 9223372036854775808}\
{a28 26 False 18446744073709551616 0 9223372036854775808} {a29 0 False\
-9223372036854775809 0 0} {a29 1 False -9223372036854775808 0 0} {a29 2 False\
-2147483649 0 255} {a29 3 False -2147483648 0 0} {a29 4 False -32769 0 255}\
{a29 5 False -32768 0 0} {a29 6 False -129 0 127} {a29 7 False -128 0 128} {a29\
8 False -1 0 255} {a29 9 True 0 0 0} {a29 10 True 1 0 1} {a29 11 True 127 0\
127} {a29 12 True 128 0 128} {a29 13 True 255 0 255} {a29 14 False 256 0 0}\
{a29 15 False 32767 0 255} {a29 16 False 32768 0 0} {a29 17 False 65535 0 255}\
{a29 18 False 65536 0 0} {a29 19 False 2147483647 0 255} {a29 20 False\
2147483648 0 0} {a29 21 False 4294967295 0 255} {a29 22 False 4294967296 0 0}\
{a29 23 False 9223372036854775807 0 255} {a29 24 False 9223372036854775808 0 0}\
{a29 25 False 18446744073709551615 0 0} {a29 26 False 18446744073709551616 0 0}\
{a30 0 False -9223372036854775809 0 0} {a30 1 False -9223372036854775808 0 0}\
{a30 2 False -2147483649 0 65535} {a30 3 False -2147483648 0 0} {a30 4 False\
-32769 0 32767} {a30 5 False -32768 0 32768} {a30 6 False -129 0 65407} {a30 7\
False -128 0 65408} {a30 8 False -1 0 65535} {a30 9 True 0 0 0} {a30 10 True 1\
0 1} {a30 11 True 127 0 127} {a30 12 True 128 0 128} {a30 13 True 255 0 255}\
{a30 14 True 256 0 256} {a30 15 True 32767 0 32767} {a30 16 True 32768 0 32768}\
{a30 17 True 65535 0 65535} {a30 18 False 65536 0 0} {a30 19 False 2147483647 0\
65535} {a30 20 False 2147483648 0 0} {a30 21 False 4294967295 0 65535} {a30 22\
False 4294967296 0 0} {a30 23 False 9223372036854775807 0 65535} {a30 24 False\
9223372036854775808 0 0} {a30 25 False 18446744073709551615 0 0} {a30 26 False\
18446744073709551616 0 0} {a31 0 False -9223372036854775809 0 0} {a31 1 False\
-9223372036854775808 0 0} {a31 2 False -2147483649 0 2147483647} {a31 3 False\
-2147483648 0 2147483648} {a31 4 False -32769 0 4294934527} {a31 5 False -32768\
0 4294934528} {a31 6 False -129 0 4294967167} {a31 7 False -128 0 4294967168}\
{a31 8 False -1 0 4294967295} {a31 9 True 0 0 0} {a31 10 True 1 0 1} {a31 11\
True 127 0 127} {a31 12 True 128 0 128} {a31 13 True 255 0 255} {a31 14 True\
256 0 256} {a31 15 True 32767 0 32767} {a31 16 True 32768 0 32768} {a31 17 True\
65535 0 65535} {a31 18 True 65536 0 65536} {a31 19 True 2147483647 0\
2147483647} {a31 20 True 2147483648 0 2147483648} {a31 21 True 4294967295 0\
4294967295} {a31 22 False 4294967296 0 0} {a31 23 False 9223372036854775807 0\
4294967295} {a31 24 False 9223372036854775808 0 0} {a31 25 False\
18446744073709551615 0 0} {a31 26 False 18446744073709551616 0 0} {a32 0 False\
-9223372036854775809 0 9223372036854775808} {a32 1 False -9223372036854775808 0\
9223372036854775808} {a32 2 False -2147483649 0 18446744071562067967} {a32 3\
False -2147483648 0 18446744071562067968} {a32 4 False -32769 0\
18446744073709518847} {a32 5 False -32768 0 18446744073709518848} {a32 6 False\
-129 0 18446744073709551487} {a32 7 False -128 0 18446744073709551488} {a32 8\
False -1 0 18446744073709551615} {a32 9 True 0 0 0} {a32 10 True 1 0 1} {a32 11\
True 127 0 127} {a32 12 True 128 0 128} {a32 13 True 255 0 255} {a32 14 True\
256 0 256} {a32 15 True 32767 0 32767} {a32 16 True 32768 0 32768} {a32 17 True\
65535 0 65535} {a32 18 True 65536 0 65536} {a32 19 True 2147483647 0\
2147483647} {a32 20 True 2147483648 0 2147483648} {a32 21 True 4294967295 0\
4294967295} {a32 22 True 4294967296 0 4294967296} {a32 23 True\
9223372036854775807 0 9223372036854775807} {a32 24 True 9223372036854775808 0\
9223372036854775808} {a32 25 False 18446744073709551615 0 9223372036854775808}\
{a32 26 False 18446744073709551616 0 9223372036854775808}}}

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

runTest {test tkt-c010fa6584-1.2 {UInt32 parameter} -setup {
  setupDb [set fileName tkt-c010fa6584-1.2.db]
} -body {
  sql execute $db "CREATE TABLE t1(x UINT32);"

  sql execute $db "INSERT INTO t1 (x) VALUES(?);" \
      [list param1 UInt32 0xFFFFFFFF]

  sql execute -execute scalar $db "SELECT x FROM t1;"
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{4294967295}}

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

runTest {test tkt-c010fa6584-1.3 {UInt32 parameter (Int64)} -setup {
  setupDb [set fileName tkt-c010fa6584-1.3.db]
} -body {
  sql execute $db "CREATE TABLE t1(x INTEGER);"

  sql execute $db "INSERT INTO t1 (x) VALUES(?);" \
      [list param1 UInt32 0xFFFFFFFF]

  sql execute -execute scalar $db "SELECT x FROM t1;"
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{-1}}

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

runTest {test tkt-c010fa6584-1.4 {UInt32 parameter (Int64) w/flag} -setup {
  setupDb [set fileName tkt-c010fa6584-1.4.db] "" "" "" BindUInt32AsInt64
} -body {
  sql execute $db "CREATE TABLE t1(x INTEGER);"

  sql execute $db "INSERT INTO t1 (x) VALUES(?);" \
      [list param1 UInt32 0xFFFFFFFF]

  sql execute -execute scalar $db "SELECT x FROM t1;"
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{4294967295}}

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

runSQLiteTestEpilogue
runTestEpilogue
Changes to Tests/version.eagle.
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)            83; # NOTE: Incremented with each release.
set version(revision)          0

###############################################################################
# ********************* END VOLATILE VERSION INFORMATION **********************
###############################################################################

#







|







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)            85; # NOTE: Incremented with each release.
set version(revision)          0

###############################################################################
# ********************* END VOLATILE VERSION INFORMATION **********************
###############################################################################

#
173
174
175
176
177
178
179


180
181
182
183
184
185
186
    [appendArgs <version> [string map [list . \\.] $version(full)] \
        </version>] \
    [appendArgs <version> [string map [list . \\.] $version(full)] \
        </version>] \
    [appendArgs <version> [string map [list . \\.] $version(full)] \
        </version>] \
    [appendArgs <version> [string map [list . \\.] $version(full)] \


        </version>] \
    [appendArgs Version= [string map [list . \\.] $version(full)] ,] \
    [appendArgs &quot\; [format %03d $version(build)] &quot\;] \
    [appendArgs AssemblyVersion\\(\" [string map [list . \\.] \
        $version(full)] \"\\)] \
    [appendArgs AssemblyFileVersion\\(\" [string map [list . \\.] \
        $version(full)] \"\\)] \







>
>







173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
    [appendArgs <version> [string map [list . \\.] $version(full)] \
        </version>] \
    [appendArgs <version> [string map [list . \\.] $version(full)] \
        </version>] \
    [appendArgs <version> [string map [list . \\.] $version(full)] \
        </version>] \
    [appendArgs <version> [string map [list . \\.] $version(full)] \
        </version>] \
    [appendArgs <version> [string map [list . \\.] $version(full)] \
        </version>] \
    [appendArgs Version= [string map [list . \\.] $version(full)] ,] \
    [appendArgs &quot\; [format %03d $version(build)] &quot\;] \
    [appendArgs AssemblyVersion\\(\" [string map [list . \\.] \
        $version(full)] \"\\)] \
    [appendArgs AssemblyFileVersion\\(\" [string map [list . \\.] \
        $version(full)] \"\\)] \
239
240
241
242
243
244
245

246
247
248
249
250
251
252
        $version(full)] \"\\)] \
    [appendArgs AssemblyFileVersion\\(\" [string map [list . \\.] \
        $version(full)] \"\\)]]

set fileNames [list \
    readme.htm \
    SQLite.nuspec \

    SQLite.MSIL.nuspec \
    SQLite.x64.nuspec \
    SQLite.x86.nuspec \
    [file join Doc Extra dbfactorysupport.html] \
    [file join Doc Extra welcome.html] \
    [file join Membership Properties AssemblyInfo.cs] \
    [file join Membership Properties AssemblyInfo.cs] \







>







241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
        $version(full)] \"\\)] \
    [appendArgs AssemblyFileVersion\\(\" [string map [list . \\.] \
        $version(full)] \"\\)]]

set fileNames [list \
    readme.htm \
    SQLite.nuspec \
    SQLite.Beta.nuspec \
    SQLite.MSIL.nuspec \
    SQLite.x64.nuspec \
    SQLite.x86.nuspec \
    [file join Doc Extra dbfactorysupport.html] \
    [file join Doc Extra welcome.html] \
    [file join Membership Properties AssemblyInfo.cs] \
    [file join Membership Properties AssemblyInfo.cs] \
Changes to exclude_bin.txt.
1
2
3
4

5
6
*.done
*.exp
*.lib
*.map

*EnvDTE.*
*Microsoft.*




>


1
2
3
4
5
6
7
*.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
*.cache
*.chw
*.docstates
*.fossil

*.ncb
*.nupkg

*.suo
*.user
*.zip

_FOSSIL_
bin/*
Doc/Output/*
Externals/Eagle/bin/Eagle.dll
Externals/Eagle/bin/EagleShell.exe
Externals/Eagle/bin/SQLite.Interop.*
Externals/Eagle/bin/sqlite3.*




>


>



>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
*.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.*
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/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/*







<

>











34
35
36
37
38
39
40

41
42
43
44
45
46
47
48
49
50
51
52
53
Externals/MSVCPP/*
Externals/NDoc3/*
Membership/*
Membership/obj/*
Membership/Profile/*
Membership/SiteMap/*
obj/*

Setup/Output/*
Setup/set_user_*.bat
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
<!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.83.0 December XX, 2012 <font color="red">(release scheduled)</font><br />
Using <a href="http://www.sqlite.org/releaselog/3_7_15_1.html">SQLite 3.7.15.1</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>







|
|







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.85.0 March XX, 2013 <font color="red">(release scheduled)</font><br />
Using <a href="http://www.sqlite.org/src/info/trunk">SQLite 3.7.16</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
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.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.







|







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.85.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
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.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>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>







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|







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
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.85.0 - March XX, 2013 <font color="red">(release scheduled)</font></b>
</p>
<ul>
    <li>Updated to <a href="http://www.sqlite.org/src/info/trunk">SQLite 3.7.16</a>.</li>
    <li>Skip checking loaded assemblies for types tagged with the SQLiteFunction attribute when the No_SQLiteFunctions environment variable is set. Pursuant to [e4c8121f7b].</li>
    <li>Add HexPassword connection string property to work around the inability to include a literal semicolon in a connection string property value. Pursuant to [1c456ae75f].</li>
    <li>Add static Execute method to the SQLiteCommand class.</li>
    <li>Support custom connection pool implementations by adding the ISQLiteConnectionPool interface, the static SQLiteConnection.ConnectionPool property, and the static CreateHandle method in addition to modifying the SQLiteConnectionPool class. Pursuant to [393d954be0].</li>
    <li>Add public constructor to the SQLiteDataAdapter class that allows passing the parseViaFramework parameter to the SQLiteConnection constructor.</li>
    <li>When built with the CHECK_STATE compile-time option, skip throwing exceptions from the SQLiteDataReader class when the object is being disposed.</li>
    <li>Support automatic value conversions for columns with a declared type of BIGUINT, INTEGER8, INTEGER16, INTEGER32, INTEGER64, SMALLUINT, TINYSINT, UNSIGNEDINTEGER, UNSIGNEDINTEGER8, UNSIGNEDINTEGER16, UNSIGNEDINTEGER32, UNSIGNEDINTEGER64, INT8, INT16, INT32, INT64, UINT, UINT8, UINT16, UINT32, UINT64, or ULONG.</li>
    <li>Add BindUInt32AsInt64 connection flag to force binding of UInt32 values as Int64 instead. Pursuant to [c010fa6584].</li>
    <li>Add BindAllAsText connection flag to force binding of all values as text.</li>
    <li>Remove AUTOINCREMENT from the column type name map.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>Avoid throwing overflow exceptions from the SQLite3.GetValue method for integral column types. Partial fix for [c010fa6584].&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>Use the legacy connection closing algorithm when built with the INTEROP_LEGACY_CLOSE compile-time option.</li>
    <li>Support using the directory containing the primary managed-only assembly as the basis for native library pre-loading.</li>
</ul>
<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>
</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>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>
Changes to test/AssemblyInfo.cs.
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.83.0")]
[assembly: AssemblyFileVersion("1.0.83.0")]







|
|
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.85.0")]
[assembly: AssemblyFileVersion("1.0.85.0")]
Changes to test/app.config.
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.83.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" />
    </DbProviderFactories>
  </system.data>
</configuration>




|



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.85.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" />
    </DbProviderFactories>
  </system.data>
</configuration>
Changes to testce/AssemblyInfo.cs.
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.83.0")]
// [assembly: AssemblyFileVersion("1.0.83.0")]








|
|

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.85.0")]
// [assembly: AssemblyFileVersion("1.0.85.0")]

Changes to testce/Program.cs.
30
31
32
33
34
35
36

37

38
39
40
41
42
43
44
      bool autoClose = false;
      int exitCode = 2; /* INCOMPLETE */
      Assembly assembly = Assembly.GetExecutingAssembly();
      AssemblyName assemblyName = assembly.GetName();
      string directory = Path.GetDirectoryName(assemblyName.CodeBase);

      if (args.Length > 0)

          autoClose = bool.Parse(args[0]);


      try { File.Delete(directory + "\\test.db"); } catch { }

      SQLiteFunction.RegisterFunction(typeof(TestFunc));
      SQLiteFunction.RegisterFunction(typeof(MyCount));
      SQLiteFunction.RegisterFunction(typeof(MySequence));








>
|
>







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
      bool autoClose = false;
      int exitCode = 2; /* INCOMPLETE */
      Assembly assembly = Assembly.GetExecutingAssembly();
      AssemblyName assemblyName = assembly.GetName();
      string directory = Path.GetDirectoryName(assemblyName.CodeBase);

      if (args.Length > 0)
      {
          try { autoClose = bool.Parse(args[0]); } catch { }
      }

      try { File.Delete(directory + "\\test.db"); } catch { }

      SQLiteFunction.RegisterFunction(typeof(TestFunc));
      SQLiteFunction.RegisterFunction(typeof(MyCount));
      SQLiteFunction.RegisterFunction(typeof(MySequence));

Changes to testlinq/2008/App.config.
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.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>





|






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.85.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
<?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.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>





|






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.85.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
<?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.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>





|






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.85.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/Properties/AssemblyInfo.cs.
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.83.0")]
[assembly: AssemblyFileVersion("1.0.83.0")]







|
|
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.85.0")]
[assembly: AssemblyFileVersion("1.0.85.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
        string fileName,           /* in */
        string invariant,          /* in */
        string name,               /* in */
        string description,        /* in */
        string typeName,           /* in */
        AssemblyName assemblyName, /* in */
        object clientData,         /* 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 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 wow64,                        /* in */
        bool throwOnMissing,               /* in */
        bool whatIf,                       /* in */
        bool verbose,                      /* in */
        ref string error                   /* out */
    );
    #endregion







>
















>















>







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
        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
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 wow64
            )
        {






            return String.Format("{0}{1}", RootKeyName,
                wow64 && Is64BitProcess() ?
                    "\\" + Wow64SubKeyName : String.Empty);
        }

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

        private static string GetSystemDirectory(
            bool wow64







>



>
>
>
>
>
>

|







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
            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() ?
                    "\\" + Wow64SubKeyName : String.Empty);
        }

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

        private static string GetSystemDirectory(
            bool wow64
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 wow64
            )
        {
            return String.Format("{0}\\Microsoft\\.NETFramework",
                GetRootKeyName(wow64));
        }

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

        private static string GetFrameworkKeyName(
            string frameworkName,
            Version frameworkVersion,
            string platformName,

            bool wow64
            )
        {
            string format = !String.IsNullOrEmpty(platformName) ?
                "{0}\\Microsoft\\{1}\\v{2}\\{3}" :
                "{0}\\Microsoft\\{1}\\v{2}";

            return String.Format(format, GetRootKeyName(wow64),
                frameworkName, frameworkVersion, platformName);
        }

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

        private static string GetImageRuntimeVersion(
            string fileName







>




|








>







|







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
        }
        #endregion

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

        #region .NET Framework Handling
        private static string GetFrameworkRootKeyName(
            bool perUser,
            bool wow64
            )
        {
            return String.Format("{0}\\Microsoft\\.NETFramework",
                GetRootKeyName(perUser, 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),
                frameworkName, frameworkVersion, platformName);
        }

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

        private static string GetImageRuntimeVersion(
            string fileName
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 wow64,
            bool whatIf,
            bool verbose
            )
        {
            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, GetFrameworkRootKeyName(wow64), false,
                    whatIf, verbose))
            {
                if (key == null)
                    return null;

                object value = RegistryHelper.GetValue(
                    key, "InstallRoot", null, whatIf, verbose);








>






|
|







4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
        }

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

        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))
            {
                if (key == null)
                    return null;

                object value = RegistryHelper.GetValue(
                    key, "InstallRoot", null, whatIf, verbose);

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 wow64,
            bool whatIf,
            bool verbose
            )
        {
            string keyName = GetFrameworkKeyName(
                frameworkName, frameworkVersion, platformName, 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, wow64, whatIf, verbose);


                if (String.IsNullOrEmpty(directory))
                    return false;

                if (!Directory.Exists(directory))
                    return false;








>






|
>











|
>







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
        ///////////////////////////////////////////////////////////////////////

        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,
                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,
                    verbose);

                if (String.IsNullOrEmpty(directory))
                    return false;

                if (!Directory.Exists(directory))
                    return false;

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 wow64,
            bool whatIf,
            bool verbose
            )
        {
            string keyName = GetFrameworkKeyName(
                frameworkName, frameworkVersion, platformName, wow64);


            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, false, whatIf, verbose))
            {
                if (key == null)
                    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
        ///////////////////////////////////////////////////////////////////////

        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,
                wow64);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, false, whatIf, verbose))
            {
                if (key == null)
                    return false;

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 wow64,
            bool throwOnMissing,
            bool whatIf,
            bool verbose,
            ref bool saved,
            ref string error
            )







>







4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
            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
            )
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, 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, wow64, whatIf, verbose);


                    if (String.IsNullOrEmpty(directory))
                    {
                        TraceOps.DebugAndTrace(TracePriority.Low,
                            debugCallback, traceCallback, String.Format(
                            ".NET Framework {0} directory is invalid, " +
                            "skipping...", ForDisplay(frameworkVersion)),







|













|
>







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
                        "frameworkName = {0}, frameworkVersion = {1}, " +
                        "platformName = {2}", ForDisplay(frameworkName),
                        ForDisplay(frameworkVersion),
                        ForDisplay(platformName)), traceCategory);

                    if (!HaveFrameworkDirectory(
                            rootKey, frameworkName, frameworkVersion,
                            platformName, perUser, 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,
                        verbose);

                    if (String.IsNullOrEmpty(directory))
                    {
                        TraceOps.DebugAndTrace(TracePriority.Low,
                            debugCallback, traceCallback, String.Format(
                            ".NET Framework {0} directory is invalid, " +
                            "skipping...", ForDisplay(frameworkVersion)),
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, wow64, throwOnMissing,
                            whatIf, verbose, ref localSaved, ref error))

                    {
                        return false;
                    }
                    else
                    {
                        if (localSaved && !saved)
                            saved = true;







|
|
>







4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
                        continue;
                    }

                    bool localSaved = false;

                    if (!callback(
                            fileName, invariant, name, description, typeName,
                            assemblyName, clientData, perUser, wow64,
                            throwOnMissing, whatIf, verbose, ref localSaved,
                            ref error))
                    {
                        return false;
                    }
                    else
                    {
                        if (localSaved && !saved)
                            saved = true;
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 wow64,
            bool throwOnMissing,
            bool whatIf,
            bool verbose,
            ref string error
            )
        {







>







4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
        [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
            )
        {
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, 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, wow64, throwOnMissing,
                            whatIf, verbose, ref error))
                    {
                        return false;
                    }
                }
            }

            return true;







|














|
|







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
                        "frameworkName = {0}, frameworkVersion = {1}, " +
                        "platformName = {2}", ForDisplay(frameworkName),
                        ForDisplay(frameworkVersion),
                        ForDisplay(platformName)), traceCategory);

                    if (!HaveFrameworkRegistry(
                            rootKey, frameworkName, frameworkVersion,
                            platformName, perUser, 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))
                    {
                        return false;
                    }
                }
            }

            return true;
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 wow64,
            bool whatIf,
            bool verbose
            )
        {
            if (vsVersion == null)
                return false;

            string keyName = GetVsKeyName(vsVersion, suffix, wow64);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, false, whatIf, verbose))
            {
                if (key == null)
                    return false;








>








|







4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755

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

        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);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, false, whatIf, verbose))
            {
                if (key == null)
                    return false;

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 wow64,
            bool throwOnMissing,
            bool whatIf,
            bool verbose,
            ref string error
            )
        {







>







4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
        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
            )
        {
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, wow64, whatIf, 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,
                        wow64, throwOnMissing, whatIf, verbose, ref error))

                {
                    return false;
                }
            }

            return true;
        }







|
>














|
>







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
            {
                TraceOps.DebugAndTrace(TracePriority.Lower,
                    debugCallback, traceCallback, String.Format(
                    "vsVersion = {0}", ForDisplay(vsVersion)),
                    traceCategory);

                if (!HaveVsVersion(
                        rootKey, vsVersion, suffix, perUser, wow64, whatIf,
                        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,
                        ref error))
                {
                    return false;
                }
            }

            return true;
        }
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 wow64,
            bool throwOnMissing,
            bool whatIf,
            bool verbose,
            ref bool saved,
            ref string error
            )







>







5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
            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
            )
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 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(wow64),
                frameworkName, frameworkVersion, platformName);
        }

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

        private static bool AddToAssemblyFolders(
            MockRegistryKey rootKey,
            string frameworkName,
            Version frameworkVersion,
            string platformName,
            string subKeyName,
            string directory,

            bool wow64,
            bool whatIf,
            bool verbose,
            ref string error
            )
        {
            string keyName = GetAssemblyFoldersKeyName(
                frameworkName, frameworkVersion, platformName, wow64);


            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, true, whatIf, verbose))
            {
                if (key == null)
                {
                    error = String.Format(







>












|












>







|
>







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
        ///////////////////////////////////////////////////////////////////////

        #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),
                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,
                wow64);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, true, whatIf, verbose))
            {
                if (key == null)
                {
                    error = String.Format(
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 wow64,
            bool throwOnMissing,
            bool whatIf,
            bool verbose,
            ref string error
            )
        {
            string keyName = GetAssemblyFoldersKeyName(
                frameworkName, frameworkVersion, platformName, 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

        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,
                wow64);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, true, whatIf, verbose))
            {
                if (key == null)
                {
                    error = String.Format(
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 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, wow64, false, whatIf, verbose,
                    ref error) &&
                AddToAssemblyFolders(
                    rootKey, frameworkName, frameworkVersion, platformName,
                    ProjectName, pair.X, wow64, whatIf, verbose, ref error);

            }
            else
            {
                return RemoveFromAssemblyFolders(
                    rootKey, frameworkName, frameworkVersion, platformName,
                    ProjectName, wow64, throwOnMissing, whatIf, verbose,
                    ref error);
            }
        }
        #endregion

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

        #region Visual Studio Handling
        private static string GetVsRootKeyName(

            bool wow64
            )
        {
            return String.Format("{0}\\Microsoft\\VisualStudio",
                GetRootKeyName(wow64));
        }

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

        private static string GetVsKeyName(
            Version vsVersion,
            string suffix,

            bool wow64
            )
        {
            if (vsVersion == null)
                return null;

            return String.Format(
                "{0}\\{1}{2}", GetVsRootKeyName(wow64), vsVersion, suffix);

        }

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

        #region Visual Studio Data Source Handling
        private static bool AddVsDataSource(
            MockRegistryKey rootKey,
            Version vsVersion,
            string suffix,
            Package package,

            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, wow64);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, false, 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

        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,
                    ref error) &&
                AddToAssemblyFolders(
                    rootKey, frameworkName, frameworkVersion, platformName,
                    ProjectName, pair.X, perUser, wow64, whatIf, verbose,
                    ref error);
            }
            else
            {
                return RemoveFromAssemblyFolders(
                    rootKey, frameworkName, frameworkVersion, platformName,
                    ProjectName, perUser, 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));
        }

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

        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,
                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);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, false, whatIf, verbose))
            {
                if (key == null)
                {
                    error = String.Format(
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 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, 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
        ///////////////////////////////////////////////////////////////////////

        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);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, false, whatIf, verbose))
            {
                if (key == null)
                {
                    error = String.Format(
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 wow64,
            bool throwOnMissing,
            bool whatIf,
            bool verbose,
            ref string error
            )
        {







>







5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431

        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
            )
        {
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, wow64, whatIf,
                    verbose, ref error);
            }
            else
            {
                return RemoveVsDataSource(
                    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 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, wow64);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, false, whatIf, verbose))
            {
                if (key == null)
                {
                    error = String.Format(







|
|




|
|













>


















|







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
                error = "invalid VS callback data";
                return false;
            }

            if (pair.Y)
            {
                return AddVsDataSource(
                    rootKey, vsVersion, suffix, package, perUser, wow64,
                    whatIf, verbose, ref error);
            }
            else
            {
                return RemoveVsDataSource(
                    rootKey, vsVersion, suffix, package, perUser, 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);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, false, whatIf, verbose))
            {
                if (key == null)
                {
                    error = String.Format(
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 wow64,
            bool whatIf,
            bool verbose,
            ref string error
            )
        {
            if (vsVersion == null)
            {
                error = "invalid VS version";
                return false;
            }

            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
        ///////////////////////////////////////////////////////////////////////

        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);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, false, whatIf, verbose))
            {
                if (key == null)
                {
                    error = String.Format(
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 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, wow64,
                    whatIf, verbose, ref error);
            }
            else
            {
                return RemoveVsDataProvider(
                    rootKey, vsVersion, suffix, package, wow64, whatIf,
                    verbose, ref error);
            }
        }
        #endregion

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

        #region Visual Studio Package Handling







>


















|
|




|
|







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

        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);
            }
            else
            {
                return RemoveVsDataProvider(
                    rootKey, vsVersion, suffix, package, perUser, wow64,
                    whatIf, verbose, ref error);
            }
        }
        #endregion

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

        #region Visual Studio Package Handling
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 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, wow64);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, false, whatIf, verbose))
            {
                if (key == null)
                {
                    error = String.Format(







>


















|







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

        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);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, false, whatIf, verbose))
            {
                if (key == null)
                {
                    error = String.Format(
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 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, 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
        ///////////////////////////////////////////////////////////////////////

        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);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, false, whatIf, verbose))
            {
                if (key == null)
                {
                    error = String.Format(
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 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, wow64,
                    whatIf, verbose, ref error);
            }
            else
            {
                return RemoveVsPackage(
                    rootKey, vsVersion, suffix, package, wow64,
                    throwOnMissing, whatIf, verbose, ref error);
            }
        }
        #endregion
        #endregion

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







>


















|
|




|







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

        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);
            }
            else
            {
                return RemoveVsPackage(
                    rootKey, vsVersion, suffix, package, perUser, wow64,
                    throwOnMissing, whatIf, verbose, ref error);
            }
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////
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(registry.LocalMachine,

                        configuration, ref frameworkList);

                    InitializeVsList(configuration.PerUser ?
                        registry.CurrentUser : registry.LocalMachine,
                        configuration, ref vsList);
                    #endregion








|
>







6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
                            InstallFlags.GlobalAssemblyCache, true) &&
                        configuration.HasFlags(
                            InstallFlags.VsPackageGlobalAssemblyCache, true),
                        ref package);

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

                    InitializeFrameworkList(configuration.PerUser ?
                        registry.CurrentUser : registry.LocalMachine,
                        configuration, ref frameworkList);

                    InitializeVsList(configuration.PerUser ?
                        registry.CurrentUser : registry.LocalMachine,
                        configuration, ref vsList);
                    #endregion

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,

                                NetFxIs32BitOnly || configuration.Wow64,
                                configuration.ThrowOnMissing,
                                configuration.WhatIf, configuration.Verbose,
                                ref error))
                        {
                            TraceOps.ShowMessage(TracePriority.Highest,
                                debugCallback, traceCallback, thisAssembly,







>







6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
                    #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,
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,

                                NetFxIs32BitOnly || configuration.Wow64,
                                configuration.ThrowOnMissing,
                                configuration.WhatIf, configuration.Verbose,
                                ref saved, ref error))
                        {
                            TraceOps.ShowMessage(TracePriority.Highest,
                                debugCallback, traceCallback, thisAssembly,







>







6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
                        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,
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,
                                VsIs32BitOnly || configuration.Wow64,
                                configuration.ThrowOnMissing,
                                configuration.WhatIf, configuration.Verbose,
                                ref error))
                        {
                            TraceOps.ShowMessage(TracePriority.Highest,
                                debugCallback, traceCallback, thisAssembly,







|







6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
                    #region VS Package
                    if (configuration.HasFlags(
                            InstallFlags.VsPackage, true))
                    {
                        if (!ForEachVsVersionRegistry(registry,
                                vsList, ProcessVsPackage,
                                configuration.VsVersionSuffix, package,
                                fileNameData, configuration.PerUser,
                                VsIs32BitOnly || configuration.Wow64,
                                configuration.ThrowOnMissing,
                                configuration.WhatIf, configuration.Verbose,
                                ref error))
                        {
                            TraceOps.ShowMessage(TracePriority.Highest,
                                debugCallback, traceCallback, thisAssembly,
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,
                                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
                    #region VS DataSource
                    if (configuration.HasFlags(
                            InstallFlags.VsDataSource, true))
                    {
                        if (!ForEachVsVersionRegistry(registry,
                                vsList, ProcessVsDataSource,
                                configuration.VsVersionSuffix, package,
                                fileNameData, configuration.PerUser,
                                VsIs32BitOnly || configuration.Wow64,
                                configuration.ThrowOnMissing,
                                configuration.WhatIf, configuration.Verbose,
                                ref error))
                        {
                            TraceOps.ShowMessage(TracePriority.Highest,
                                debugCallback, traceCallback, thisAssembly,
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,
                                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
                    #region VS DataProvider
                    if (configuration.HasFlags(
                            InstallFlags.VsDataProvider, true))
                    {
                        if (!ForEachVsVersionRegistry(registry,
                                vsList, ProcessVsDataProvider,
                                configuration.VsVersionSuffix, package,
                                fileNameData, configuration.PerUser,
                                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
// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version 
//      Build Number
//      Revision
//
[assembly: AssemblyVersion("1.0.83.0")]
[assembly: AssemblyFileVersion("1.0.83.0")]







|
|
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.85.0")]
[assembly: AssemblyFileVersion("1.0.85.0")]
Changes to www/build.wiki.
120
121
122
123
124
125
126

127
128
129
130
131
132
133
    <li>
      Make sure the version information is correct for System.Data.SQLite in the
      following files:

      <ul>
        <li>&lt;root&gt;\readme.htm</li>
        <li>&lt;root&gt;\SQLite.nuspec</li>

        <li>&lt;root&gt;\SQLite.MSIL.nuspec</li>
        <li>&lt;root&gt;\SQLite.x86.nuspec</li>
        <li>&lt;root&gt;\SQLite.x64.nuspec</li>
        <li>&lt;root&gt;\Doc\Extra\dbfactorysupport.html</li>
        <li>&lt;root&gt;\Doc\Extra\welcome.html</li>
        <li>&lt;root&gt;\Membership\Properties\AssemblyInfo.cs</li>
        <li>&lt;root&gt;\SQLite.Designer\AssemblyInfo.cs</li>







>







120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
    <li>
      Make sure the version information is correct for System.Data.SQLite in the
      following files:

      <ul>
        <li>&lt;root&gt;\readme.htm</li>
        <li>&lt;root&gt;\SQLite.nuspec</li>
        <li>&lt;root&gt;\SQLite.Beta.nuspec</li>
        <li>&lt;root&gt;\SQLite.MSIL.nuspec</li>
        <li>&lt;root&gt;\SQLite.x86.nuspec</li>
        <li>&lt;root&gt;\SQLite.x64.nuspec</li>
        <li>&lt;root&gt;\Doc\Extra\dbfactorysupport.html</li>
        <li>&lt;root&gt;\Doc\Extra\welcome.html</li>
        <li>&lt;root&gt;\Membership\Properties\AssemblyInfo.cs</li>
        <li>&lt;root&gt;\SQLite.Designer\AssemblyInfo.cs</li>
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
        <b>Source Code</b>
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <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.74 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This ZIP archive contains all current source code for System.Data.SQLite
        1.0.82.0 (3.7.14) combined into a single archive file.
        <br />



        (sha1: accec84da4a59815078e494afd398eb1b3c64898)






















































































      </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.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.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.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 2005 and/or Visual Studio 2008.</b></big>
        <br />
        (sha1: e38165e4f45e4338d81f2da10050826406aa09b8)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <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.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.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: 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.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.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.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: aa0f1f958f9febf466807d79f03fae31508993dd)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <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.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.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: 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.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.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.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: bf3defd3b4250e1aa94ea06e10c4b369416d0e2a)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <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.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.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: 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.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.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.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: a7fcc7d410df97817eabbbc6f01e1e448f898aab)




















































































      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <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>
        <br />
        (11.64 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.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: 0c3d227a1b3c0f3aae1a0b687f17dba18bed6eeb)















































































      </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.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.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.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: cf6ec0622af7a16c5cf32c02d41a29060b91ec79)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <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.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.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: 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.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.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.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: 15b5625a7f5fa1a4a74c61c0c46e3969d2c6adc2)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <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.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.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: 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.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.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.82.0
        (3.7.14) package.  The Visual C++ 2010 SP1 runtime for x86 and the .NET
        Framework 4.0 are required.
        <br />
        (sha1: 6f6cdfddb08f254b744e7088b4825db02bec73da)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <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.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.82.0 (3.7.14) package.  The Visual C++ 2010 SP1
        runtime for x86 and the .NET Framework 4.0 are required.
        <br />
        (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.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.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.82.0
        (3.7.14) package.  The Visual C++ 2010 SP1 runtime for x64 and the .NET
        Framework 4.0 are required.
        <br />



        (sha1: e1b79aa7763853a68068f43c9edb6382a2c67550)


































































































































































      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <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.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.82.0 (3.7.14) package.  The Visual C++ 2010 SP1
        runtime for x64 and the .NET Framework 4.0 are required.

        <br />
        (sha1: a91739243166b9ae27be244722acd480d1ce4537)
      </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.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.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.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: 43076280a7ee02b1574bb666d3a14c185d6fe84a)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <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.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.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: 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.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.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.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: 1e29c539c75e106ddbdd18c83563fc0b9df7c1bf)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <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.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.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: 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.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.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.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: 335da5c15d56b868f948dbf842ad97c94c5c148c)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <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.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.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: 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.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.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.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: 929f1d2a0eb9bb697c4e8725bedef1f4042c076b)
      </td>
    </tr>

    <tr>
      <td width="10">&nbsp;</td>
      <td width="30%" valign="top" align="right">
        <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.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.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: 4c12b0ad3aae3510bd573e49a6159f6a3405d312)
      </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.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.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.82.0 (3.7.14) package.  The .NET Compact
        Framework 3.5 is required.
        <br />
        (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.82.0">System.Data.SQLite.1.0.82.0.nupkg</a>
        <br />
        (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.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: 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.82.0">System.Data.SQLite.MSIL.1.0.82.0.nupkg</a>
        <br />
        (0.26 MiB)
      </td>
      <td width="5"></td>
      <td valign="top">
        This NuGet package contains the managed binaries for System.Data.SQLite
        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: 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.82.0">System.Data.SQLite.x86.1.0.82.0.nupkg</a>
        <br />
        (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.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: 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.82.0">System.Data.SQLite.x64.1.0.82.0.nupkg</a>
        <br />
        (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.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: 1d0a1646f469ea63e74c9ad0778f9911dbde4d30)
      </td>
    </tr>

    <tr>
      <td colspan="4">
        <b>Legacy Versions</b>
      </td>







|

|




|

>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>












|

|





|




|

|






|

|




|
|


|












|

|





|



|






|

|




|
|


|












|

|





|





|






|

|




|
|


|












|

|





|


>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






|

|




|
|
|

>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>












|

|




|
|


|






|

|




|


|












|

|




|
|


|






|

|




|


|












|

|




|
|


|






|

|




|


|












|

|




|
|


>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






|

|




|
|
>

|












|

|




|
|


|






|

|




|



|












|

|




|
|


|






|

|




|



|












|

|




|
|


|






|

|




|



|












|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




|
|
|

|






|

|




|
|


|












|

|




|


|












|

|




|
|



|






|

|




|







|






|

|




|
|
|
|

|






|

|




|
|
|
|

|







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
        <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>
        <br />
        (2.88 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.
        <br />
        (sha1: 16ab3bdee2fa755af897daa8bc2b4edca75bd6b0)
      </td>
    </tr>

    <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>
        <br />
        (6.10 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
        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>
        <br />
        (sha1: 1685f4bcd63ad8f3456978d2e788a27c2d5136ea)
      </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>
        <br />
        (6.09 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.
        The .NET Framework 3.5 SP1 is required.
        <br />
        (sha1: 82d48b5f9c032c81c85b85e227d4578f770e9803)
      </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>
        <br />
        (6.84 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
        SP1 runtime for x64 is included.  The .NET Framework 3.5 SP1 is
        required.
        <br />
        (sha1: d4a476cdd96a7d153b4502e74649bfb60b5bd11a)
      </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>
        <br />
        (6.83 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.
        The .NET Framework 3.5 SP1 is required.
        <br />
        (sha1: d0e17d8800a53f6bcedb965c2f8eec8f87f7894e)
      </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>
        <br />
        (10.43 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
        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)
      </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>
        <br />
        (10.42 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.
        The .NET Framework 4.0 is required.
        <br />
        (sha1: 344e0406dd463689768ed1055f07adc8c5f2cde7)
      </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>
        <br />
        (11.68 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
        SP1 runtime for x64 is included.  The .NET Framework 4.0 is required.
        <br />
        (sha1: 753bd303e82f9267c607d3729cb1cd80aef89ada)
      </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>

    <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)
      </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
        RTM 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 RTM 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
        RTM 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 RTM runtime for x64 is included.
        The .NET Framework 4.5 is required.
        <br />
        (sha1: 0e24f71a7f2bcdb74bbd7afd807dafeafc64a81e)
      </td>
    </tr>

    <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>
        <br />
        (1.68 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
        Framework 3.5 SP1 are required.
        <br />
        (sha1: 8f2f071cdbb5cf7b7035d4ed7f6a99c4253a7816)
      </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>
        <br />
        (1.67 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
        runtime for x86 and the .NET Framework 3.5 SP1 are required.
        <br />
        (sha1: 55edb20a73da43ada0b6eb89d9fb66fe6cf5e51b)
      </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>
        <br />
        (1.75 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
        Framework 3.5 SP1 are required.
        <br />
        (sha1: c67a430533cf7c7776f4cff86041ee1afc856e4b)
      </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>
        <br />
        (1.74 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
        runtime for x64 and the .NET Framework 3.5 SP1 are required.
        <br />
        (sha1: c32b05f6824071b62a99f7732fbfbcec0c2e4e87)
      </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>
        <br />
        (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 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
        Framework 4.0 are required.
        <br />
        (sha1: 8c673f05e5ca349425a4e46a1b0b13336f6056e7)
      </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>
        <br />
        (1.72 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
        runtime for x86 and the .NET Framework 4.0 are required.
        <br />
        (sha1: cf4ead8c3337d595ff3cc8d1583c458084094793)
      </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>
        <br />
        (1.75 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
        Framework 4.0 are required.
        <br />
        (sha1: 32440a943c56d291c9732195b066474d8bcaebca)
      </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>
        <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)
      </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 RTM 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 RTM
        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 RTM 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 RTM
        runtime for x64 and the .NET Framework 4.5 are required.
        <br />
        (sha1: a3970b48c78ecbf9fb92553d52f2af5cbfe01e25)
      </td>
    </tr>

    <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>
        <br />
        (1.89 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
        linked.  The .NET Framework 3.5 SP1 is required.
        <br />
        (sha1: 60ed2d6a3d980af41e147e08357c285c8a3a1e20)
      </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>
        <br />
        (1.89 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
        runtime for x86 is statically linked.  The .NET Framework 3.5 SP1 is
        required.
        <br />
        (sha1: 7b57f575238156098153763a0473ed4e4a787dda)
      </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>
        <br />
        (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++ 2008 SP1 runtime for x64 is statically
        linked.  The .NET Framework 3.5 SP1 is required.
        <br />
        (sha1: bfed5c0a206fa433d308bae303eca1d56883c04d)
      </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>
        <br />
        (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++ 2008 SP1
        runtime for x64 is statically linked.  The .NET Framework 3.5 SP1 is
        required.
        <br />
        (sha1: a8d9cd5b94609f060a5f994dad0efa525c1744f9)
      </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>
        <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 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
        linked.  The .NET Framework 4.0 is required.
        <br />
        (sha1: 9e829efcac6d05dee68f6d0a97a9342773dc9573)
      </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>
        <br />
        (1.94 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
        runtime for x86 is statically linked.  The .NET Framework 4.0 is
        required.
        <br />
        (sha1: 67c7f69a31250db04440330385926df91710bd61)
      </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>
        <br />
        (1.95 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
        linked.  The .NET Framework 4.0 is required.
        <br />
        (sha1: 09e43ce56de8e9db493f895d0440bf58c90867e8)
      </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>
        <br />
        (1.94 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 is statically linked.  The .NET Framework 4.0 is
        required.
        <br />
        (sha1: 9a439387fe8a836cc6acafa5b4510becc0846cbd)
      </td>
    </tr>

    <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 RTM 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 RTM
        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 RTM 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 RTM
        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>
        <br />
        (0.87 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
        Framework 3.5 is required.
        <br />
        (sha1: b12956304f4bb770459f00827c450397d8473040)
      </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>
        <br />
        (3.19 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
        version of the Visual C++ runtime corresponding to the .NET Framework
        used by the associated managed assembly is statically linked.
        <br />
        (sha1: b4d1c9498cf27cd7cfde55fe3ab745f66396e0ad)
      </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>
        <br />
        (0.33 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.
        <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)
      </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>
        <br />
        (1.59 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.
        <br />
        (sha1: c10145217ed979efe53f5931d2e9b3a49b6c65d5)
      </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>
        <br />
        (1.80 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.
        <br />
        (sha1: 2e2cd4a194f5c308d46f8f70fc50ae3779afee79)
      </td>
    </tr>

    <tr>
      <td colspan="4">
        <b>Legacy Versions</b>
      </td>
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>


    </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.

  </p>

  <p>
    The <b>framework</b> in templates (3), (4), (5), (6), (7), and (8) will be
    one of netFx20, netFx35, netFx40, netFx45.
  </p>








>
>















>







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
      <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>

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>





  <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.







>
>
>
>







1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
    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.
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
        </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/raw/Doc/SQLite.NET.chm?name=trunk">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>







|
|







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
        </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>
Changes to www/news.wiki.
1
2
3
4
5
6




























7
8
9
10
11
12
13
<title>News</title>

<b>Version History</b>

<p>
    <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>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>





|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
<title>News</title>

<b>Version History</b>

<p>
    <b>1.0.85.0 - March XX, 2013 <font color="red">(release scheduled)</font></b>
</p>
<ul>
    <li>Updated to [http://www.sqlite.org/src/info/trunk|SQLite 3.7.16].</li>
    <li>Skip checking loaded assemblies for types tagged with the SQLiteFunction attribute when the No_SQLiteFunctions environment variable is set. Pursuant to [e4c8121f7b].</li>
    <li>Add HexPassword connection string property to work around the inability to include a literal semicolon in a connection string property value. Pursuant to [1c456ae75f].</li>
    <li>Add static Execute method to the SQLiteCommand class.</li>
    <li>Support custom connection pool implementations by adding the ISQLiteConnectionPool interface, the static SQLiteConnection.ConnectionPool property, and the static CreateHandle method in addition to modifying the SQLiteConnectionPool class. Pursuant to [393d954be0].</li>
    <li>Add public constructor to the SQLiteDataAdapter class that allows passing the parseViaFramework parameter to the SQLiteConnection constructor.</li>
    <li>When built with the CHECK_STATE compile-time option, skip throwing exceptions from the SQLiteDataReader class when the object is being disposed.</li>
    <li>Support automatic value conversions for columns with a declared type of BIGUINT, INTEGER8, INTEGER16, INTEGER32, INTEGER64, SMALLUINT, TINYSINT, UNSIGNEDINTEGER, UNSIGNEDINTEGER8, UNSIGNEDINTEGER16, UNSIGNEDINTEGER32, UNSIGNEDINTEGER64, INT8, INT16, INT32, INT64, UINT, UINT8, UINT16, UINT32, UINT64, or ULONG.</li>
    <li>Add BindUInt32AsInt64 connection flag to force binding of UInt32 values as Int64 instead. Pursuant to [c010fa6584].</li>
    <li>Add BindAllAsText connection flag to force binding of all values as text.</li>
    <li>Remove AUTOINCREMENT from the column type name map.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>Avoid throwing overflow exceptions from the SQLite3.GetValue method for integral column types. Partial fix for [c010fa6584].&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>Use the legacy connection closing algorithm when built with the INTEROP_LEGACY_CLOSE compile-time option.</li>
    <li>Support using the directory containing the primary managed-only assembly as the basis for native library pre-loading.</li>
</ul>
<p>
    <b>1.0.84.0 - January 9, 2013</b>
</p>
<ul>
    <li>Updated to [http://www.sqlite.org/releaselog/3_7_15_2.html|SQLite 3.7.15.2].</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>
</p>
<ul>
    <li>Updated to [http://www.sqlite.org/releaselog/3_7_15_1.html|SQLite 3.7.15.1].</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>
Changes to www/source.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
<title>Source Code</title>

<p>
  Follow these steps to obtain the latest (i.e. unreleased) source code for the
  System.Data.SQLite project.  To obtain the latest officially released source
  code instead, refer to the [./downloads.wiki | downloads page].  Unless
  otherwise noted, all steps need to be done in the order specified.
</p>

<a name="assumptions"></a>
<h2>Assumptions &amp; Prerequisites</h2>

<p>
  The string &quot;<b>&lt;root&gt;</b>&quot; represents the directory where you
  would like a local working copy of source tree (a.k.a. the working check-out
  directory) for the System.Data.SQLite project to reside (this should be a
  completely empty directory).
</p>

<p>
  The string &quot;<b>&lt;repositories&gt;</b>&quot; represents the directory
  where you would like the local clone of the repository for the
  System.Data.SQLite project (and potentially other projects) to reside.
</p>

<a name="fossil"></a>
<h2>Obtain &amp; Install Fossil</h2>

<p>
  The [http://www.fossil-scm.org | Fossil] open-source
  [http://en.wikipedia.org/wiki/Distributed_revision_control | distributed version control]
  system is a computer program that must be installed on your machine before you use it.
  Fortunately, installing Fossil is very easy.  Fossil consists of a single
  executable file that you simply download and run.  For convenience, the Fossil






|






|
|
|
|




|
|



|







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
<title>Source Code</title>

<p>
  Follow these steps to obtain the latest (i.e. unreleased) source code for the
  System.Data.SQLite project.  To obtain the latest officially released source
  code instead, refer to the [./downloads.wiki | downloads page].  Unless
  otherwise noted, all steps need to be performed in the order specified.
</p>

<a name="assumptions"></a>
<h2>Assumptions &amp; Prerequisites</h2>

<p>
  The string &quot;<b>&lt;root&gt;</b>&quot; represents the directory where the
  local working copy of the source tree (a.k.a. the working check-out directory)
  for the System.Data.SQLite project is to reside.  This should be a completely
  empty directory.
</p>

<p>
  The string &quot;<b>&lt;repositories&gt;</b>&quot; represents the directory
  where the local clone of the repository for the System.Data.SQLite project
  (and potentially other projects) is to reside.
</p>

<a name="fossil"></a>
<h2>Obtain &amp; Install Fossil Itself</h2>

<p>
  The [http://www.fossil-scm.org | Fossil] open-source
  [http://en.wikipedia.org/wiki/Distributed_revision_control | distributed version control]
  system is a computer program that must be installed on your machine before you use it.
  Fortunately, installing Fossil is very easy.  Fossil consists of a single
  executable file that you simply download and run.  For convenience, the Fossil
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
    command similar to:&nbsp;<b>cd&nbsp;/D&nbsp;&lt;root&gt;</b>
  </li>

  <li>
    Enter the following command to create a complete clone (i.e. local copy) of
    the entire source code repository for the System.Data.SQLite project,
    including the entire check-in history:&nbsp;
    <b>fossil&nbsp;[http://www.fossil-scm.org/index.html/help/clone | clone]&nbsp;http://system.data.sqlite.org/&nbsp;&lt;repositories&gt;\sds.fossil</b>
  </li>

  <li>
    The repository itself uses an
    [http://www.fossil-scm.org/index.html/doc/trunk/www/fileformat.wiki | enduring file format]
    stored in a single
    [http://www.fossil-scm.org/index.html/doc/trunk/www/tech_overview.wiki | SQLite database file]
    with a particular schema.
  </li>

  <li>







|



|







51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
    command similar to:&nbsp;<b>cd&nbsp;/D&nbsp;&lt;root&gt;</b>
  </li>

  <li>
    Enter the following command to create a complete clone (i.e. local copy) of
    the entire source code repository for the System.Data.SQLite project,
    including the entire check-in history:&nbsp;
    <b>fossil&nbsp;[http://www.fossil-scm.org/index.html/help/clone | clone]&nbsp;http://system.data.sqlite.org/&nbsp;&lt;repositories&gt;/sds.fossil</b>
  </li>

  <li>
    Please note that the repository itself uses an
    [http://www.fossil-scm.org/index.html/doc/trunk/www/fileformat.wiki | enduring file format]
    stored in a single
    [http://www.fossil-scm.org/index.html/doc/trunk/www/tech_overview.wiki | SQLite database file]
    with a particular schema.
  </li>

  <li>
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
    Change the current directory to &quot;<b>&lt;root&gt;</b>&quot; using a
    command similar to:&nbsp;<b>cd&nbsp;/D&nbsp;&lt;root&gt;</b>
  </li>

  <li>
    Enter the following command to create a local working copy of all the files
    that are currently part of the System.Data.SQLite project:&nbsp;
    <b>fossil&nbsp;[http://www.fossil-scm.org/index.html/help/open | open]&nbsp;&lt;repositories&gt;\sds.fossil</b>
  </li>

  <li>
    The local source tree should now be ready for use as described in the
    [./build.wiki | build procedures] and/or [./test.wiki | test procedures].
  </li>

  <li>
    In the future, to update the local working copy with the latest changes from
    the official System.Data.SQLite repository (i.e. instead of having to
    re-clone the entire thing), enter the following command from the same
    directory where a working copy is located:&nbsp;
    <b>fossil&nbsp;[http://www.fossil-scm.org/index.html/help/update | update]</b>
  </li>
</ol>







|











|



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
    Change the current directory to &quot;<b>&lt;root&gt;</b>&quot; using a
    command similar to:&nbsp;<b>cd&nbsp;/D&nbsp;&lt;root&gt;</b>
  </li>

  <li>
    Enter the following command to create a local working copy of all the files
    that are currently part of the System.Data.SQLite project:&nbsp;
    <b>fossil&nbsp;[http://www.fossil-scm.org/index.html/help/open | open]&nbsp;&lt;repositories&gt;/sds.fossil</b>
  </li>

  <li>
    The local source tree should now be ready for use as described in the
    [./build.wiki | build procedures] and/or [./test.wiki | test procedures].
  </li>

  <li>
    In the future, to update the local working copy with the latest changes from
    the official System.Data.SQLite repository (i.e. instead of having to
    re-clone the entire thing), enter the following command from the same
    directory where the working copy is located:&nbsp;
    <b>fossil&nbsp;[http://www.fossil-scm.org/index.html/help/update | update]</b>
  </li>
</ol>