System.Data.SQLite

Check-in Differences
Login

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

Difference From 299d71992b1ebdc9 To 178b6d6379fc9615

2011-11-05
23:56
Update core SQLite to 3.7.9 release. check-in: dedde051c4 user: mistachkin tags: trunk
2011-10-29
21:16
Fix error checking by portions of the batch tools that create missing directories on an as-needed basis. check-in: 299d71992b user: mistachkin tags: trunk
2011-10-23
08:58
Update Eagle in externals to the official beta 19 release. check-in: d598ffd546 user: mistachkin tags: trunk
2011-07-07
09:40
Cleanup leaked opaque object handle in test 'basic-1.2'. check-in: 07b0709845 user: mistachkin tags: trunk
08:47
Make the necessary adjustments to the unit test suite and to the 'test' / 'testlinq' projects to allow all the tests contained within those projects to be run programmatically via the unit test suite. check-in: 178b6d6379 user: mistachkin tags: trunk
05:53
Modify fix for [e1b2e0f769] so that it passes all the legacy unit tests in the 'test' project. Also, skip deploying CE projects for non-CE build configurations to avoid VS PDB locking issue. check-in: def75f76da user: mistachkin tags: trunk

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.76.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.74.0, Culture=neutral,
                 PublicKeyToken=db937bc2d44ff139"/&gt;
    &lt;/DbProviderFactories&gt;
  &lt;/system.data&gt;
&lt;/configuration&gt;
</pre>
      </div>
      <p>
Changes to Doc/Extra/version.html.
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
          </td>
        </tr>
      </table>
    </div>
    <div id="mainSection">
    <div id="mainBody">
    <h1 class="heading">Version History</h1>
    <p><b>1.0.76.0 - October 4, 2011</b></p>
    <ul>
      <li>Prevent the domain unload event handler in SQLiteLog from being registered multiple times. Fix for <a href="http://system.data.sqlite.org/index.html/info/0d5b1ef362">[0d5b1ef362]</a>.</li>
      <li>Stop allowing non-default application domains to initialize the SQLiteLog class. Fix for <a href="http://system.data.sqlite.org/index.html/info/ac47dd230a">[ac47dd230a]</a>.</li>
    </ul>
    <p><b>1.0.75.0 - October 3, 2011</b></p>
    <ul>
      <li>Updated to SQLite 3.7.8 <a href="http://www.sqlite.org/src/info/3e0da808d2">[3e0da808d2]</a>.</li>
      <li>More enhancements to the build system.</li>
      <li>Add official <a href="http://www.nuget.org/">NuGet</a> packages for x86 and x64.</li>
      <li>Add Changes and LastInsertRowId properties to the connection class.</li>
      <li>Support more formats when converting data from/to the DateTime type.</li>
      <li>Make all the assembly versioning attributes consistent.</li>
      <li>Add unit testing infrastructure using <a href="http://eagle.to/">Eagle</a>.</li>
      <li>Integrate all legacy unit tests, including the &quot;testlinq&quot; project, into the new test suite.</li>
      <li>Add projects to build the interop assembly statically linked to the Visual C++ runtime. Fix for <a href="http://system.data.sqlite.org/index.html/info/53f0c5cbf6">[53f0c5cbf6]</a>.</li>
      <li>Add SQLITE_ENABLE_STAT2 compile-time option to the interop assembly.  Fix for <a href="http://system.data.sqlite.org/index.html/info/74807fbf27">[74807fbf27]</a>.</li>
      <li>Fix mutex issues exposed when running the test suite with the debug version of SQLite.</li>
      <li>Fix transaction enlistment when repeated attempts are made to enlist in the same transaction. Fix for <a href="http://system.data.sqlite.org/index.html/info/ccfa69fc32">[ccfa69fc32]</a>.</li>
      <li>Support the SQLITE_FCNTL_WIN32_AV_RETRY file control to mitigate the impact of file sharing violations caused by external processes.</li>
      <li>Refactor the logging interface to be thread-safe and self-initializing.</li>
      <li>Shutdown the SQLite native interface when the AppDomain is being unloaded. Fix for <a href="http://system.data.sqlite.org/index.html/info/b4a7ddc83f">[b4a7ddc83f]</a>.</li>
      <li>Support Skip operation for LINQ using OFFSET. Fix for <a href="http://system.data.sqlite.org/index.html/info/8b7d179c3c">[8b7d179c3c]</a>.</li>
      <li>Support EndsWith operation for LINQ using SUBSTR. Fix for <a href="http://system.data.sqlite.org/index.html/info/59edc1018b">[59edc1018b]</a>.</li>
      <li>Support all SQLite journal modes. Fix for <a href="http://system.data.sqlite.org/index.html/info/448d663d11">[448d663d11]</a>.</li>
      <li>Do not throw exceptions when disposing SQLiteDataReader. Fix for <a href="http://system.data.sqlite.org/index.html/info/e1b2e0f769">[e1b2e0f769]</a>.</li>
      <li>The REAL type should be mapped to System.Double. Fix for <a href="http://system.data.sqlite.org/index.html/info/2c630bffa7">[2c630bffa7]</a> and <a href="http://system.data.sqlite.org/index.html/info/b0a5990f48">[b0a5990f48]</a>.</li>
      <li>Minor optimization to GetParamValueBytes(). Fix for <a href="http://system.data.sqlite.org/index.html/info/201128cc88">[201128cc88]</a>.</li>
      <li>Support the ON UPDATE, ON DELETE, and MATCH clause information when generating schema metadata for foreign keys. Partial fix for <a href="http://system.data.sqlite.org/index.html/info/b226147b37">[b226147b37]</a>. VS designer changes are not yet tested.</li>
      <li>Fix incorrect resource name for SR.resx in the mixed-mode assembly.</li>
      <li>Reduce the number of String.Compare() calls in the hot path for SQLiteCommand.ExecuteReader().</li>
    </ul>
    <p><b>1.0.74.0 - July 4, 2011</b></p>
    <ul>
      <li>Updated to SQLite 3.7.7.1 <a href="http://www.sqlite.org/src/info/af0d91adf4">[af0d91adf4]</a>.</li>
      <li>Fix incorrect hard-coded .NET Framework version information SQLiteFactory_Linq.cs that was causing IServiceProvider.GetService to fail when running against the .NET Framework 3.5.</li>
      <li>Fix all XML documentation warnings.</li>
      <li>Restore support for the mixed-mode assembly (i.e. the one that can be registered in the Global Assembly Cache).</li>
      <li>Restore support for the Compact Framework.</li>
      <li>Remove unused &quot;using&quot; statements from the System.Data.SQLite and System.Data.SQLite.Linq projects.</li>
      <li>Remove hard-coded System.Data.SQLite.Linq version from SQLiteFactory_Linq.cs</li>
      <li>Modify the setup to support bundled packages (i.e. with the mixed-mode assembly) and standard packages (i.e. with the managed assembly separate from the native interop library).</li>
      <li>Disable the ability to register with the Global Assembly Cache in the standard setup package (i.e. it is available in the bundled setup only).</li>
      <li>Remove PATH modification from the setup.</li>
      <li>Modify the naming scheme for the source, setup, and binary packages to allow for the necessary variants.</li>
      <li>In the build automation, attempt to automatically detect if Visual Studio 2008 and/or 2010 are installed and support building binaries for both at once, when available.</li>
      <li>Add release automation to build the source, setup, and binary packages in all supported build variants.</li>
      <li>Add the testlinq project to the new build system and make it work properly with Visual Studio 2008 and 2010.</li>
    </ul>
    <p><b>1.0.73.0 - June 2, 2011</b></p>
    <ul>
      <li>Updated to SQLite 3.7.6.3 <a href="http://www.sqlite.org/src/info/ed1da510a2">[ed1da510a2]</a>.</li>
      <li>Minor optimization to GetBytes(). Fix for <a href="http://system.data.sqlite.org/index.html/info/8c1650482e">[8c1650482e]</a>.</li>
      <li>Update various assembly information settings.</li>
      <li>Correct System.Data.SQLite.Linq version and resource information. Fix for <a href="http://system.data.sqlite.org/index.html/info/6489c5a396">[6489c5a396]</a> and <a href="http://system.data.sqlite.org/index.html/info/133daf50d6">[133daf50d6]</a>.</li>
      <li>Moved log handler from SQLiteConnection object to SQLiteFactory object to prevent if from being prematurely GCed.</li>
      <li>We should block x64 installs on x86 and we should install native only if the setup package itself is native. Fix for <a href="http://system.data.sqlite.org/index.html/info/e058ce156e">[e058ce156e]</a>.</li>
    </ul>
    <p><b>1.0.72.0 - May 1, 2011</b></p>
    <ul>
      <li>Add the correct directory to the path. Fix for <a href="http://system.data.sqlite.org/index.html/info/50515a0c8e">[50515a0c8e]</a>.</li>
    </ul>
    <p><b>1.0.71.0 - April 27, 2011</b></p>
    <ul>
      <li>Updated to SQLite 3.7.6+ <a href="http://www.sqlite.org/src/info/1bd1484cd7">[1bd1484cd7]</a> to get additional Windows error logging.</li>
      <li>Updated setup to optionally add install directory to PATH if GAC option selected.</li>
    </ul>
    <p><b>1.0.69.0 - April 12, 2011</b></p>







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




















|

|

|



|







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
          </td>
        </tr>
      </table>
    </div>
    <div id="mainSection">
    <div id="mainBody">
    <h1 class="heading">Version History</h1>
































    <p><b>1.0.74.0 - July 4, 2011</b></p>
    <ul>
      <li>Updated to SQLite 3.7.7.1 <a href="http://www.sqlite.org/src/info/af0d91adf4">[af0d91adf4]</a>.</li>
      <li>Fix incorrect hard-coded .NET Framework version information SQLiteFactory_Linq.cs that was causing IServiceProvider.GetService to fail when running against the .NET Framework 3.5.</li>
      <li>Fix all XML documentation warnings.</li>
      <li>Restore support for the mixed-mode assembly (i.e. the one that can be registered in the Global Assembly Cache).</li>
      <li>Restore support for the Compact Framework.</li>
      <li>Remove unused &quot;using&quot; statements from the System.Data.SQLite and System.Data.SQLite.Linq projects.</li>
      <li>Remove hard-coded System.Data.SQLite.Linq version from SQLiteFactory_Linq.cs</li>
      <li>Modify the setup to support bundled packages (i.e. with the mixed-mode assembly) and standard packages (i.e. with the managed assembly separate from the native interop library).</li>
      <li>Disable the ability to register with the Global Assembly Cache in the standard setup package (i.e. it is available in the bundled setup only).</li>
      <li>Remove PATH modification from the setup.</li>
      <li>Modify the naming scheme for the source, setup, and binary packages to allow for the necessary variants.</li>
      <li>In the build automation, attempt to automatically detect if Visual Studio 2008 and/or 2010 are installed and support building binaries for both at once, when available.</li>
      <li>Add release automation to build the source, setup, and binary packages in all supported build variants.</li>
      <li>Add the testlinq project to the new build system and make it work properly with Visual Studio 2008 and 2010.</li>
    </ul>
    <p><b>1.0.73.0 - June 2, 2011</b></p>
    <ul>
      <li>Updated to SQLite 3.7.6.3 <a href="http://www.sqlite.org/src/info/ed1da510a2">[ed1da510a2]</a>.</li>
      <li>Minor optimization to GetBytes(). Fix for <a href="http://system.data.sqlite.org/src/info/8c1650482e">[8c1650482e]</a>.</li>
      <li>Update various assembly information settings.</li>
      <li>Correct System.Data.SQLite.Linq version and resource information. Fix for <a href="http://system.data.sqlite.org/src/info/6489c5a396">[6489c5a396]</a> and <a href="http://system.data.sqlite.org/src/info/133daf50d6">[133daf50d6]</a>.</li>
      <li>Moved log handler from SQLiteConnection object to SQLiteFactory object to prevent if from being prematurely GCed.</li>
      <li>We should block x64 installs on x86 and we should install native only if the setup package itself is native. Fix for <a href="http://system.data.sqlite.org/src/info/e058ce156e">[e058ce156e]</a>.</li>
    </ul>
    <p><b>1.0.72.0 - May 1, 2011</b></p>
    <ul>
      <li>Add the correct directory to the path. Fix for <a href="http://system.data.sqlite.org/src/info/50515a0c8e">[50515a0c8e]</a>.</li>
    </ul>
    <p><b>1.0.71.0 - April 27, 2011</b></p>
    <ul>
      <li>Updated to SQLite 3.7.6+ <a href="http://www.sqlite.org/src/info/1bd1484cd7">[1bd1484cd7]</a> to get additional Windows error logging.</li>
      <li>Updated setup to optionally add install directory to PATH if GAC option selected.</li>
    </ul>
    <p><b>1.0.69.0 - April 12, 2011</b></p>
Changes to Doc/Extra/welcome.html.
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
        in case you want to add it to the Global Assembly Cache (GAC). This is the only DLL required to be redistributed with 
        your SQLite.NET application(s).&nbsp; It 
        comes in&nbsp;3
        flavors: Win32, Itanium and x64 (AMD64).</p>
      <h1 class="heading">Distributing the Binaries (Compact Framework)</h1>
      <p><b>System.Data.SQLite.DLL </b>and <b>SQLite.Interop.XXX.DLL</b> must be 
        deployed on the Compact Framework.&nbsp; The XXX is the build number of the 
        System.Data.SQLite library (e.g. &quot;076&quot;).&nbsp; SQLite.Interop.XXX 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">
          Send comments on this topic.<!--[if gte IE 5]><tool:tip element="seeAlsoToolTip" avoidmouse="false" /><tool:tip element="languageFilterToolTip" avoidmouse="false" /><![endif]-->    </div>







|







138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
        in case you want to add it to the Global Assembly Cache (GAC). This is the only DLL required to be redistributed with 
        your SQLite.NET application(s).&nbsp; It 
        comes in&nbsp;3
        flavors: Win32, Itanium and x64 (AMD64).</p>
      <h1 class="heading">Distributing the Binaries (Compact Framework)</h1>
      <p><b>System.Data.SQLite.DLL </b>and <b>SQLite.Interop.XXX.DLL</b> must be 
        deployed on the Compact Framework.&nbsp; The XXX is the build number of the 
        System.Data.SQLite library (e.g. &quot;074&quot;).&nbsp; SQLite.Interop.XXX 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">
          Send comments on this topic.<!--[if gte IE 5]><tool:tip element="seeAlsoToolTip" avoidmouse="false" /><tool:tip element="languageFilterToolTip" avoidmouse="false" /><![endif]-->    </div>
Changes to Doc/SQLite.NET.chm.

cannot compute difference between binary files

Added Externals/Eagle/Tests/constraints.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
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
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
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
###############################################################################
#
# constraints.eagle --
#
# Extensible Adaptable Generalized Logic Engine (Eagle)
# Test Constraints File
#
# Copyright (c) 2007-2010 by Joe Mistachkin.  All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: $
#
###############################################################################

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

    addConstraint $::tcl_platform(platform)

    if {![isEagle]} then {
      #
      # BUGFIX: We do not want to skip any Mono bugs in Tcl.
      #         Also, fake the culture.
      #
      set constraints [list monoToDo monoBug monoCrash culture.en_US]

      #
      # NOTE: Add the necessary constraints for each version
      #       of Mono we know about.
      #
      foreach version [list 20 22 24 26 28 210 30] {
        addConstraint [appendArgs monoToDo $version]
        addConstraint [appendArgs monoBug $version]
        addConstraint [appendArgs monoCrash $version]
      }

      foreach constraint $constraints {
        addConstraint $constraint; # running in Tcl.
      }
    }

    tputs $channel [appendArgs $::tcl_platform(platform) \n]
  }

  proc checkForEagle { channel } {
    tputs $channel "---- checking for Eagle... "

    if {[isEagle]} then {
      #
      # NOTE: We are running inside Eagle.
      #
      addConstraint eagle

      #
      # NOTE: We do not want to skip bugs or crashing
      #       issues for Tcl since we are not running
      #       in Tcl.
      #
      addConstraint tclBug
      addConstraint tclCrash

      #
      # NOTE: Add the necessary constraints for each
      #       version of Tcl we know about.
      #
      foreach version [list 84 85 86] {
        addConstraint [appendArgs tclBug $version]
        addConstraint [appendArgs tclCrash $version]
      }

      tputs $channel yes\n
    } else {
      #
      # NOTE: We are running inside Tcl.
      #
      addConstraint tcl

      #
      # NOTE: Each Tcl bug and crash constraint is set
      #       based on the exact Tcl version (i.e. not
      #       greater than or equal to).
      #
      if {[info exists ::tcl_version]} then {
        #
        # NOTE: For each Tcl version we know about,
        #       check it against the currently running
        #       Tcl version.  If the two are not equal,
        #       add the test constraints that prevent
        #       skipping those tests that are buggy
        #       only for the particular version of Tcl.
        #
        foreach dotVersion [list 8.4 8.5 8.6] {
          if {$::tcl_version ne $dotVersion} then {
            set version [string map [list . ""] $dotVersion]

            addConstraint [appendArgs tclBug $version]
            addConstraint [appendArgs tclCrash $version]
          }
        }
      }

      #
      # NOTE: We do not want to skip bugs or crashing
      #       issues for Eagle since we are not running
      #       in Eagle.
      #
      addConstraint eagleBug
      addConstraint eagleCrash

      tputs $channel no\n
    }
  }

  proc checkForGaruda { channel } {
    tputs $channel "---- checking for Garuda... "

    if {[haveGaruda packageId]} then {
      #
      # NOTE: We are running with or via Garuda.
      #
      addConstraint garuda

      tputs $channel [appendArgs "yes (" $packageId ")\n"]
    } else {
      tputs $channel no\n
    }
  }

  proc checkForShell { channel } {
    tputs $channel "---- checking for shell... "

    set name [file rootname [file tail [info nameofexecutable]]]

    if {[isEagle]} then {
      if {$name eq "EagleShell"} then {
        #
        # NOTE: We are running in Eagle via the EagleShell.
        #
        addConstraint shell

        tputs $channel "yes (Eagle)\n"

        #
        # NOTE: We are done here, return now.
        #
        return
      }
    } else {
      if {[string match tclsh* $name]} then {
        #
        # NOTE: We are running in Tcl via tclsh.
        #
        addConstraint shell

        tputs $channel "yes (Tcl)\n"

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

    tputs $channel no\n
  }

  proc checkForDebug { channel } {
    tputs $channel "---- checking for debug... "

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

      tputs $channel yes\n
    } else {
      tputs $channel no\n
    }
  }

  proc checkForVersion { channel } {
    tputs $channel "---- checking for language version... "

    if {[info exists ::tcl_version]} then {
      #
      # TODO: Cleanup the semantics for adding test
      #       constraints here.
      #
      if {$::tcl_version eq "8.4"} then {
        #
        # NOTE: Baseline reported language and feature
        #       version.
        #
        addConstraint tcl84
        addConstraint tcl84OrHigher
        addConstraint tcl84Feature

        if {[isEagle]} then {
          #
          # NOTE: *EAGLE* We do want to include any
          #       tests that target "Tcl 8.5 or higher"
          #       features and/or "Tcl 8.6 or higher"
          #       features because they would not be in
          #       the test suite if we did not support
          #       that particular feature, regardless
          #       of the language version.
          #
          addConstraint tcl85Feature
          addConstraint tcl86Feature
        }
      } elseif {$::tcl_version eq "8.5"} then {
        #
        # NOTE: Baseline reported language and feature
        #       version.  Tcl 8.5 includes all the
        #       features from itself and Tcl 8.4.
        #
        addConstraint tcl85
        addConstraint tcl84OrHigher
        addConstraint tcl85OrHigher
        addConstraint tcl84Feature
        addConstraint tcl85Feature

        if {[isEagle]} then {
          #
          # NOTE: *EAGLE* We do want to include any
          #       tests that target "Tcl 8.5 or higher"
          #       features and/or "Tcl 8.6 or higher"
          #       features because they would not be in
          #       the test suite if we did not support
          #       that particular feature, regardless
          #       of the language version.
          #
          addConstraint tcl86Feature
        }
      } elseif {$::tcl_version eq "8.6"} then {
        #
        # NOTE: Baseline reported language and feature
        #       version.  Tcl 8.6 includes all the
        #       features from itself Tcl 8.4, and Tcl
        #       8.5.
        #
        addConstraint tcl86
        addConstraint tcl84OrHigher
        addConstraint tcl85OrHigher
        addConstraint tcl86OrHigher
        addConstraint tcl84Feature
        addConstraint tcl85Feature
        addConstraint tcl86Feature
      }

      tputs $channel [appendArgs $::tcl_version \n]
    } else {
      tputs $channel no\n
    }
  }

  proc checkForCommand { channel name } {
    tputs $channel [appendArgs "---- checking for command \"" $name \
        "\"... "]

    #
    # NOTE: Is the command available?
    #
    if {[llength [info commands $name]] > 0} then {
      #
      # NOTE: Yes, it appears that it is available.
      #
      addConstraint command.$name

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

    if {[file exists $name]} then {
      #
      # NOTE: Yes, it appears that it is available.
      #
      if {[string length $constraint] > 0} then {
        addConstraint file_$constraint
      } else {
        addConstraint file_[file tail $name]
      }

      tputs $channel yes\n
    } else {
      tputs $channel no\n
    }
  }

  proc checkForPathFile { channel name {constraint ""} } {
    tputs $channel [appendArgs "---- checking for file \"" $name \
        "\" along PATH... "]

    if {[file exists $name]} then {
      #
      # NOTE: Yes, it appears that it is available [in the exact location they
      #       specified].
      #
      if {[string length $constraint] > 0} then {
        addConstraint file_$constraint
      } else {
        addConstraint file_[file tail $name]
      }

      tputs $channel yes\n

      #
      # NOTE: We are done here, return now.
      #
      return
    } else {
      #
      # NOTE: Use the appropriate environment variable for the platform.
      #
      if {$::tcl_platform(platform) eq "windows"} then {
        set pathName PATH
      } else {
        #
        # HACK: For shared libraries, use the LD_LIBRARY_PATH.
        #
        if {[file extension $name] eq [info sharedlibextension]} then {
          set pathName LD_LIBRARY_PATH
        } else {
          set pathName PATH
        }
      }

      #
      # NOTE: Is the required environment variable available?
      #
      if {[info exists ::env($pathName)]} then {
        #
        # NOTE: Ok, grab it now.
        #
        set path $::env($pathName)

        #
        # NOTE: Use the appropriate path separator for the platform.
        #
        if {[info exists ::tcl_platform(pathSeparator)]} then {
          set separator $::tcl_platform(pathSeparator)
        } elseif {$::tcl_platform(platform) eq "windows"} then {
          set separator \;
        } else {
          set separator :
        }

        #
        # NOTE: Grab just the file name from the possibly fully qualified file
        #       name provided by the caller.
        #
        set tail [file tail $name]

        #
        # NOTE: Check each directory in the PATH for the file.
        #
        foreach directory [split $path $separator] {
          #
          # NOTE: Check for the file in this directory contained in the PATH.
          #       This strips the directory portion off the file name specified
          #       by the caller, if any, before joining that file name to the
          #       current directory of the PATH being searched.
          #
          if {[file exists [file join $directory $tail]]} then {
            #
            # NOTE: Yes, it appears that it is available in the PATH.
            #
            if {[string length $constraint] > 0} then {
              addConstraint file_$constraint
            } else {
              addConstraint file_[file tail $name]
            }

            tputs $channel yes\n

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

    tputs $channel no\n
  }

  proc checkForNativeCode { channel } {
    tputs $channel "---- checking for native code... "

    if {[isEagle]} then {
      if {[info exists ::eagle_platform(compileOptions)] && \
          [info exists ::tcl_platform(platform)] && \
          [lsearch -exact -nocase $::eagle_platform(compileOptions) \
          $::tcl_platform(platform)] != -1} then {
        #
        # NOTE: Yes, the binary matches the current platform,
        #       native code can be used.
        #
        addConstraint native

        tputs $channel yes\n
      } else {
        tputs $channel no\n
      }
    } else {
      #
      # NOTE: Tcl is always native code and can always execute native code.
      #
      addConstraint native

      #
      # HACK: Needed by test "benchmark-1.22".
      #
      addConstraint compile.NATIVE

      tputs $channel yes\n
    }
  }

  proc checkForTip127 { channel } {
    tputs $channel "---- checking for TIP #127... "

    #
    # NOTE: Is the interpreter TIP #127 ready?
    #
    if {[catch {lsearch -index 0 0 0}] == 0} then {
      addConstraint tip127

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

    #
    # NOTE: Is the interpreter TIP #194 ready?
    #
    catch {apply} error

    if {$error ne {invalid command name "apply"}} then {
      addConstraint tip194

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

    #
    # NOTE: Is the interpreter TIP #241 ready?
    #
    if {[catch {lsearch -nocase 0 0}] == 0} then {
      addConstraint tip241

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

    #
    # NOTE: Is the interpreter TIP #285 ready?
    #
    catch {interp cancel} error

    if {$error eq "eval canceled"} then {
      addConstraint tip285

      tputs $channel yes\n
    } else {
      tputs $channel no\n
    }
  }

  proc checkForTiming { channel threshold } {
    tputs $channel "---- checking for precision timing... "

    #
    # NOTE: Are we allowed to do precision timing tests?
    #
    if {![info exists ::no(timing)]} then {
      #
      # NOTE: Attempt to block for exactly one second.
      #
      set start [expr {[clock clicks -milliseconds] & 0x7fffffff}]
      after 1000; # wait for "exactly" one second.
      set stop [expr {[clock clicks -milliseconds] & 0x7fffffff}]

      #
      # NOTE: Calculate the difference between the actual and expected
      #       number of milliseconds.
      #
      set difference [expr {abs($stop - $start - 1000)}]

      #
      # NOTE: Are we within the threshold specified by the caller?
      #
      if {$difference >= 0 && $difference <= $threshold} then {
        addConstraint timing

        tputs $channel [appendArgs "yes (0 <= " $difference " <= " \
            $threshold " milliseconds)\n"]
      } else {
        tputs $channel [appendArgs "no (0 <= " $difference " > " \
            $threshold " milliseconds)\n"]
      }
    } else {
      tputs $channel no\n
    }
  }

  proc checkForPerformance { channel } {
    tputs $channel "---- checking for performance testing... "

    #
    # NOTE: Are we allowed to do performance testing?
    #
    if {![info exists ::no(performance)]} then {
      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?
    #
    if {[info exists ::tcl_interactive] && $::tcl_interactive} then {
      addConstraint interactive

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

    #
    # HACK: For now, do the exact same check as checkForInteractive; however,
    #       this is still useful as a separate constraint because it can be
    #       individually disabled in "prologue.eagle".
    #
    if {[info exists ::tcl_interactive] && $::tcl_interactive} then {
      addConstraint userInteraction

      tputs $channel yes\n
    } else {
      tputs $channel no\n
    }
  }

  proc checkForNetwork { channel host timeout } {
    tputs $channel [appendArgs \
        "---- checking for network connectivity to host \"" $host "\"... "]

    if {[isEagle]} then {
      #
      # BUGBUG: Tcl 8.4 does not like this expression (and Tcl tries to
      #         compile it even though it will only actually ever be
      #         evaluated in Eagle).
      #
      set expr {[llength [info commands uri]] > 0 && \
          [catch {uri ping $host $timeout} response] == 0 && \
          [lindex $response 0] in [list Success TimedOut] && \
          [string is integer -strict [lindex $response 1]] && \
          [lindex $response 1] <= $timeout}

      #
      # NOTE: Does it look like we are able to contact the network host?
      #
      if {[expr $expr]} then {
        #
        # NOTE: Yes, it appears that it is available.
        #
        addConstraint network_$host

        tputs $channel [appendArgs "yes (" $response ")\n"]
      } else {
        tputs $channel no\n
      }
    } else {
      #
      # HACK: Running in Tcl, just assume we have network access.
      #
      addConstraint network_$host

      tputs $channel yes\n
    }
  }

  if {[isEagle]} then {
    ###########################################################################
    ############################ BEGIN Eagle ONLY #############################
    ###########################################################################

    proc checkForSoftwareUpdateTrust { channel } {
      tputs $channel "---- checking for software update trust... "

      if {[llength [info commands uri]] > 0 && \
          [catch {uri softwareupdates} result] == 0 && \
          $result eq "software update certificate is trusted"} then {
        #
        # NOTE: Yes, it appears that we trust our software updates.
        #       Since this setting is off by default, the user (or
        #       a script evaluated by the user) must have manually
        #       turned it on.
        #
        addConstraint softwareUpdate

        tputs $channel "trusted\n"
      } else {
        tputs $channel "untrusted\n"
      }
    }

    proc checkForAdministrator { channel } {
      tputs $channel "---- checking for administrator... "

      if {[isAdministrator]} then {
        addConstraint administrator; # running as full admin.

        tputs $channel yes\n
      } else {
        tputs $channel no\n
      }
    }

    proc checkForHost { channel } {
      tputs $channel "---- checking for host... "

      if {[set code [catch {host isopen} result]] == 0 && $result} then {
        addConstraint hostIsOpen

        tputs $channel open\n
      } elseif {$code == 0} then {
        tputs $channel closed\n
      } else {
        tlog $result; tputs $channel error\n]
      }
    }

    proc checkForPrimaryThread { channel } {
      tputs $channel "---- checking for primary thread... "

      set threadId [object invoke Interpreter.GetActive ThreadId]

      if {[info tid] == $threadId} then {
        addConstraint primaryThread

        tputs $channel [appendArgs "yes (" $threadId ")\n"]
      } else {
        tputs $channel [appendArgs "no (" $threadId ")\n"]
      }
    }

    proc checkForRuntime { channel } {
      tputs $channel "---- checking for runtime... "

      #
      # NOTE: Are we running inside Mono (regardless of operating system)?
      #
      if {[isMono]} then {
        #
        # NOTE: Yes, it appears that we are running inside Mono.
        #
        addConstraint mono; # running on Mono.

        tputs $channel [appendArgs [expr {[info exists \
            ::eagle_platform(runtime)] ? \
            $::eagle_platform(runtime) : "Mono"}] \n]
      } else {
        #
        # NOTE: No, it appears that we are not running inside Mono.
        #
        addConstraint dotNet; # running on .NET.

        #
        # NOTE: We do not want to skip Mono bugs on .NET.
        #
        addConstraint monoToDo; # running on .NET.
        addConstraint monoBug; # running on .NET.
        addConstraint monoCrash; # running on .NET.

        tputs $channel [appendArgs [expr {[info exists \
            ::eagle_platform(runtime)] ? \
            $::eagle_platform(runtime) : "Microsoft.NET"}] \n]
      }
    }

    proc checkForImageRuntimeVersion { channel } {
      tputs $channel "---- checking for image runtime version... "

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

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

        #
        # NOTE: Keep track of the specific image runtime version for usage in
        #       test constraints.
        #
        addConstraint imageRuntime$version

        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 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 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 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 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
      }
    }

    proc checkForMachine { channel bits machine } {
      tputs $channel [appendArgs "---- checking for machine \"" $bits \
          "-bit " $machine "\"... "]

      #
      # NOTE: What are the machine architecture and the
      #       number of bits for this operating system?
      #
      if {[info exists ::tcl_platform(machine)] && \
          [info exists ::tcl_platform(osBits)]} then {
        #
        # NOTE: Does the machine and number of bits match
        #       what the caller specified?
        #
        if {$::tcl_platform(machine) eq $machine && \
            $::tcl_platform(osBits) eq $bits} then {
          #
          # NOTE: Yes, it matches.
          #
          addConstraint $machine.${bits}bit

          set result yes
        } else {
          set result no
        }

        tputs $channel [appendArgs $result ", " $::tcl_platform(osBits) -bit \
            " " $::tcl_platform(machine)\n]
      } else {
        tputs $channel "no, unknown\n"
      }
    }

    proc checkForGarudaDll { channel } {
      #
      # NOTE: Check for the Garuda DLL of the same platform (i.e. machine
      #       type) as the native Tcl shell.
      #
      return [checkForFile $channel [file join $::base_path bin \
          [machineToPlatform [getMachineForTclShell]] \
          [appendArgs $::eagle_platform(configuration) Dll] \
          [appendArgs Garuda [info sharedlibextension]]]]
    }

    proc checkForCulture { channel } {
      tputs $channel "---- checking for culture... "

      #
      # NOTE: Grab the current culture.
      #
      set culture [info culture]

      if {[string length $culture] > 0} then {
        #
        # NOTE: The culture information is present, use it and show it.
        #
        addConstraint culture.[string map [list - _] $culture]

        tputs $channel [appendArgs $culture \n]
      } else {
        tputs $channel [appendArgs unknown \n]
      }
    }

    proc checkForReferenceCountTracking { channel } {
      tputs $channel "---- checking for object reference count tracking... "

      if {[info exists ::eagle_platform(compileOptions)] && \
          ([lsearch -exact -nocase $::eagle_platform(compileOptions) \
              NOTIFY] != -1 || \
           [lsearch -exact -nocase $::eagle_platform(compileOptions) \
              NOTIFY_OBJECT] != -1)} then {
        #
        # NOTE: Yes, support for object reference count tracking is present.
        #
        addConstraint refCount

        tputs $channel yes\n
      } else {
        tputs $channel no\n
      }
    }

    proc checkForCompileOption { channel option } {
      tputs $channel [appendArgs "---- checking for compile option \"" \
          $option "\"... "]

      if {[info exists ::eagle_platform(compileOptions)] && \
          [lsearch -exact -nocase $::eagle_platform(compileOptions) \
              $option] != -1} then {
        #
        # NOTE: Yes, support for the compile option is present.
        #
        addConstraint compile.$option

        tputs $channel yes\n
      } else {
        tputs $channel no\n
      }
    }

    proc checkForRuntimeOption { channel option } {
      tputs $channel [appendArgs "---- checking for runtime option \"" \
          $option "\"... "]

      if {[info exists ::eagle_platform(runtimeOptions)] && \
          [lsearch -exact -nocase $::eagle_platform(runtimeOptions) \
              $option] != -1} then {
        #
        # NOTE: Yes, support for the runtime option is present.
        #
        addConstraint runtime.$option

        tputs $channel yes\n
      } else {
        tputs $channel no\n
      }
    }

    proc checkForDynamicLoading { channel } {
      tputs $channel "---- checking for dynamic loading... "

      #
      # NOTE: As far as we know, dynamic loading always works on Windows.
      #       On some Unix systems, dlopen does not work (e.g. because
      #       Mono is statically linked, etc).
      #
      if {$::tcl_platform(platform) eq "windows" || \
          ([llength [info commands library]] > 0 && \
           [catch {library test}] == 0)} then {
        #
        # NOTE: Yes, it appears that it is available.
        #
        addConstraint dynamic

        tputs $channel yes\n
      } else {
        tputs $channel no\n
      }
    }

    proc checkForWindowsForms { channel } {
      tputs $channel "---- checking for Windows Forms... "

      #
      # HACK: When running on Windows, we do not need to do any other
      #       special checks here; however, on Unix (and Mac OS X?),
      #       we should check for the DISPLAY environment variable as
      #       some basic indication that the X server is available.
      #       This appears to be very necessary on Mono because it
      #       crashes after repeated failed attempts to create a
      #       Windows Form when the X server is unavailable (e.g. on
      #       OpenBSD).
      #
      if {$::tcl_platform(platform) eq "windows" || \
          [info exists ::env(DISPLAY)]} then {
        #
        # NOTE: Is the Windows Forms assembly available?
        #
        if {[catch {object resolve System.Windows.Forms} assembly] == 0} then {
          #
          # NOTE: Yes, it appears that it is available.
          #
          addConstraint winForms

          tputs $channel yes\n

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

      tputs $channel no\n
    }

    proc checkForStaThread { channel } {
      tputs $channel "---- checking for STA thread... "

      if {[catch {object invoke System.Threading.Thread.CurrentThread \
              GetApartmentState} apartmentState] == 0 && \
          $apartmentState eq "STA"} then {
        #
        # NOTE: Yes, we are running in an STA thread.
        #
        addConstraint staThread

        tputs $channel yes\n
      } else {
        tputs $channel no\n
      }
    }

    proc checkForWindowsPresentationFoundation { channel } {
      tputs $channel "---- checking for Windows Presentation Foundation... "

      #
      # NOTE: Is the Windows Presentation Foundation available?
      #
      if {[catch {object resolve PresentationFramework} assembly] == 0} then {
        #
        # NOTE: Yes, it appears that it is available.
        #
        addConstraint wpf

        tputs $channel yes\n
      } else {
        tputs $channel no\n
      }
    }

    proc checkForDatabase { channel string } {
      tputs $channel "---- checking for database... "

      #
      # HACK: Disable database connectivity testing on Mono because
      #       it fails to timeout (unless special test suite hacks
      #       for Mono have been disabled by the user).
      #
      if {[info exists ::no(mono)] || ![isMono]} then {
        #
        # NOTE: Can we access the local database?
        #
        if {[catch {sql open $string} connection] == 0} then {
          #
          # NOTE: Yes, it appears that we can connect to the local database.
          #
          addConstraint sql

          #
          # NOTE: Cleanup the database connection we just opened.
          #
          sql close $connection

          tputs $channel yes\n
        } else {
          tputs $channel no\n
        }
      } else {
        tputs $channel "disabled\n"
      }
    }

    proc checkForAssembly { channel name } {
      tputs $channel [appendArgs "---- checking for assembly \"" $name \
          "\"... "]

      #
      # NOTE: Can the assembly be loaded?
      #
      if {[catch {object resolve $name} assembly] == 0} then {
        #
        # NOTE: Yes, it appears that it is available.
        #
        addConstraint $name

        tputs $channel yes\n
      } else {
        tputs $channel no\n
      }
    }

    proc checkForObjectMember { channel object member } {
      tputs $channel [appendArgs "---- checking for object member \"" \
          $object . $member "\"... "]

      if {[catch {object members -flags +NonPublic -pattern $member $object} \
          members] == 0 && [llength $members] > 0} then {
        #
        # NOTE: Yes, it appears that it is available.
        #
        addConstraint $object.[string trim $member *?]

        tputs $channel yes\n
      } else {
        tputs $channel no\n
      }
    }

    proc checkForTclInstalls { channel } {
      tputs $channel "---- checking for Tcl installs... "

      #
      # NOTE: Check for dynamically loadable Tcl libraries (for this
      #       architecture only).
      #
      if {[catch {tcl select -architecture} tcl] == 0} then {
        #
        # NOTE: Did we find one?  Attempt to grab the index
        #       of the version field from the list.
        #
        set index [lsearch -exact $tcl version]

        if {$index != -1} then {
          #
          # NOTE: The very next list index contains the value
          #       (i.e. like a Tcl 8.5+ dict).
          #
          set dotVersion [lindex $tcl [incr index]]

          #
          # NOTE: Do we know the version?
          #
          if {[string length $dotVersion] > 0 && \
              [regexp -- {^\d+\.\d+$} $dotVersion]} then {
            #
            # NOTE: Yes, some version of Tcl is available.
            #
            addConstraint tclLibrary

            #
            # NOTE: Is the version 8.x or higher?
            #
            if {$dotVersion >= 8.6} then {
              addConstraint tclLibrary86
            } elseif {$dotVersion >= 8.5} then {
              addConstraint tclLibrary85
            } elseif {$dotVersion >= 8.4} then {
              addConstraint tclLibrary84
            }

            tputs $channel [appendArgs $dotVersion \n]

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

      tputs $channel no\n
    }

    proc checkForTclReady { channel } {
      tputs $channel "---- checking for Tcl readiness... "

      if {[catch {tcl ready} result] == 0 && $result} then {
        #
        # NOTE: Yes, native Tcl is loaded and ready.
        #
        addConstraint tclReady

        tputs $channel yes\n
      } else {
        tputs $channel no\n
      }
    }

    proc checkForTclShell { channel } {
      #
      # HACK: We do not care about the machine type returned from this
      #       procedure, we only care if it returns "error" because that
      #       would indicate an error was caught during [exec] (i.e. the
      #       native Tcl shell could not be executed).
      #
      if {[catch {getMachineForTclShell} result] == 0 && \
          $result ne "error"} then {
        #
        # NOTE: Yes, a native Tcl shell appears to be available.
        #
        addConstraint tclShell

        tputs $channel "---- checking for Tcl shell... yes\n"
      } else {
        tputs $channel "---- checking for Tcl shell... no\n"
      }
    }

    proc checkForPowerShell { channel } {
      tputs $channel "---- checking for PowerShell... "

      #
      # NOTE: Can the PowerShell assembly be loaded?
      #
      if {[catch {object resolve System.Management.Automation} \
              assembly] == 0} then {
        #
        # NOTE: Yes, it appears that it is available.
        #
        addConstraint powerShell

        tputs $channel yes\n
      } else {
        tputs $channel no\n
      }
    }

    proc checkForWix { channel } {
      tputs $channel "---- checking for WiX... "

      #
      # NOTE: Platform must be Windows for this constraint to
      #       even be checked (i.e. we require the registry).
      #
      if {$::tcl_platform(platform) eq "windows"} then {
        #
        # NOTE: Indicate that we have not found it yet.
        #
        set directory ""

        #
        # NOTE: Have we not found the directory yet?
        #
        #       Yes, this is somewhat redundant because we just set
        #       the directory to an empty string (above); however,
        #       maintaining a uniform pattern is more important.
        #
        if {[string length $directory] == 0} then {
          #
          # NOTE: Check for the WIX environment variable.
          #
          if {[info exists ::env(WIX)]} then {
            set directory [file normalize [string trimright $::env(WIX)]]

            if {[string length $directory] > 0} then {
              #
              # NOTE: We need the directory containing the binaries.
              #
              set directory [file join $directory bin]

              #
              # NOTE: Does the directory actually exist?
              #
              if {[file isdirectory $directory]} then {
                #
                # NOTE: The file name of the primary WiX assembly.
                #
                set fileName [file join $directory wix.dll]

                #
                # NOTE: We do not know the file version yet.
                #
                set version ""

                #
                # NOTE: Attempt to query the version of the file.
                #
                if {[catch {file version $fileName} version] == 0 && \
                    [string length $version] > 0} then {
                  #
                  # NOTE: Indicate where we found the file.
                  #
                  set where environment
                } else {
                  #
                  # NOTE: The file does not exist or is not properly
                  #       versioned.
                  #
                  set directory ""
                }
              } else {
                #
                # NOTE: The directory does not exist.
                #
                set directory ""
              }
            }
          }
        }

        #
        # NOTE: Have we not found the directory yet?
        #
        if {[string length $directory] == 0} then {
          #
          # NOTE: Registry hive where WiX install information
          #       is stored.
          #
          set key {HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Installer XML}

          #
          # NOTE: The versions of WiX that we support.
          #
          set versions [list 3.5 3.0]

          #
          # NOTE: Check each version, stopping when one is found.
          #
          foreach version $versions {
            #
            # NOTE: Attempt to fetch the WiX install directory
            #       value from the registry, removing the
            #       trailing backslash, if any.
            #
            set directory [file normalize [string trimright [object invoke \
                Microsoft.Win32.Registry GetValue \
                [appendArgs $key \\ $version] InstallRoot \
                null] \\]]

            #
            # NOTE: Does the directory name look valid and
            #       does it actually exist?
            #
            if {[string length $directory] > 0} then {
              #
              # NOTE: Does the directory actually exist?
              #
              if {[file isdirectory $directory]} then {
                #
                # NOTE: The file name of the primary WiX assembly.
                #
                set fileName [file join $directory wix.dll]

                #
                # NOTE: We do not know the file version yet.
                #
                set version ""

                #
                # NOTE: Attempt to query the version of the file.
                #
                if {[catch {file version $fileName} version] == 0 && \
                    [string length $version] > 0} then {
                  #
                  # NOTE: Indicate where we found the file.
                  #
                  set where registry

                  #
                  # NOTE: We found it, bail out now.
                  #
                  break
                } else {
                  #
                  # NOTE: The file does not exist or is not properly
                  #       versioned.
                  #
                  set directory ""
                }
              } else {
                #
                # NOTE: The directory does not exist.
                #
                set directory ""
              }
            }
          }
        }

        #
        # NOTE: Did we find the directory?
        #
        if {[string length $directory] > 0 && \
            [file isdirectory $directory]} then {
          #
          # NOTE: Yes, it appears that it is available.
          #
          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 checkForManagedDebugger { channel } {
      tputs $channel "---- checking for managed debugger... "

      #
      # NOTE: Is the managed debugger attached?
      #
      if {[object invoke System.Diagnostics.Debugger IsAttached]} then {
        #
        # NOTE: Yes, it appears that it is attached.
        #
        addConstraint managedDebugger

        tputs $channel yes\n
      } else {
        tputs $channel no\n
      }
    }

    proc checkForScriptDebugger { channel } {
      tputs $channel "---- checking for script debugger... "

      #
      # NOTE: Is the script debugger available?
      #
      if {[catch {object invoke -flags +NonPublic Interpreter.GetActive \
              Debugger} debugger] == 0} then {
        #
        # NOTE: We do not own this, do not dispose it.
        #
        if {[string length $debugger] > 0} then {
          object flags $debugger +NoDispose
        }

        if {[regexp -- {^Debugger#\d+$} $debugger]} then {
          #
          # NOTE: Yes, it appears that it is available.
          #
          addConstraint scriptDebugger

          tputs $channel yes\n

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

      tputs $channel no\n
    }

    proc checkForScriptDebuggerInterpreter { channel } {
      tputs $channel "---- checking for script debugger interpreter... "

      #
      # NOTE: Is the script debugger interpreter available?
      #
      if {[catch {object invoke -flags +NonPublic Interpreter.GetActive \
              Debugger} debugger] == 0} then {
        #
        # NOTE: We do not own this, do not dispose it.
        #
        if {[string length $debugger] > 0} then {
          object flags $debugger +NoDispose
        }

        if {[regexp -- {^Debugger#\d+$} $debugger] && \
            [catch {object invoke $debugger Interpreter} interp] == 0} then {
          #
          # NOTE: We do not own this, do not dispose it.
          #
          if {[string length $interp] > 0} then {
            object flags $interp +NoDispose
          }

          if {[regexp -- {^Interpreter#\d+$} $interp]} then {
            #
            # NOTE: Yes, it appears that it is available.
            #
            addConstraint scriptDebuggerInterpreter

            tputs $channel yes\n

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

      tputs $channel no\n
    }

    ###########################################################################
    ############################# END Eagle ONLY ##############################
    ###########################################################################
  } else {
    ###########################################################################
    ############################# 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 \
        checkForVersion checkForCommand checkForFile checkForNativeCode \
        checkForTip127 checkForTip194 checkForTip241 checkForTip285 \
        checkForPerformance checkForTiming checkForInteractive \
        checkForUserInteraction checkForNetwork] false false

    ###########################################################################
    ############################## END Tcl ONLY ###############################
    ###########################################################################
  }

  #
  # NOTE: Provide the Eagle test constraints package to the interpreter.
  #
  package provide EagleTestConstraints \
    [expr {[isEagle] ? [info engine PatchLevel] : 1.0}]
}

Added Externals/Eagle/Tests/epilogue.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
###############################################################################
#
# epilogue.eagle --
#
# Extensible Adaptable Generalized Logic Engine (Eagle)
# Test Epilogue File
#
# Copyright (c) 2007-2010 by Joe Mistachkin.  All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: $
#
###############################################################################

if {![info exists no([file tail [info script]])]} then {
  if {[info level] > 0} then {
    error "cannot run, current level is not global"
  }

  if {[isEagle]} then {
    #
    # NOTE: Show the current state of the memory.
    #
    tputs $test_channel [appendArgs "---- ending memory: " \
        [formatListAsDict [debug memory]] \n]

    #
    # NOTE: Show the current state of the native stack.
    #
    catch {debug stack true} stack

    tputs $test_channel [appendArgs "---- ending stack: " \
        [formatListAsDict $stack] \n]

    unset stack
  }

  #
  # NOTE: Show when the tests actually ended (now).
  #
  tputs $test_channel [appendArgs "---- tests ended at " \
      [clock format [clock seconds]] \n]

  if {[isEagle]} then {
    tputs $test_channel \n; # NOTE: Blank line.

    if {$eagle_tests(passed) > 0} then {
      host result Ok [appendArgs "PASSED: " $eagle_tests(passed) \n]
      tlog [appendArgs "PASSED: " $eagle_tests(passed) \n]
    }

    if {$eagle_tests(failed) > 0} then {
      host result Error [appendArgs "FAILED: " $eagle_tests(failed) \n]
      tlog [appendArgs "FAILED: " $eagle_tests(failed) \n]

      if {[llength $eagle_tests(failedNames)] > 0} then {
        host result Error [appendArgs "FAILED: " $eagle_tests(failedNames) \n]
        tlog [appendArgs "FAILED: " $eagle_tests(failedNames) \n]
      }
    }

    if {$eagle_tests(skipped) > 0} then {
      host result Break [appendArgs "SKIPPED: " $eagle_tests(skipped) \n]
      tlog [appendArgs "SKIPPED: " $eagle_tests(skipped) \n]
    }

    if {$eagle_tests(total) > 0} then {
      host result Return [appendArgs "TOTAL: " $eagle_tests(total) \n]
      tlog [appendArgs "TOTAL: " $eagle_tests(total) \n]

      #
      # HACK: Temporarily modify the floating point precision so that the
      #       pass percentage does not end up with excessive detail.  In
      #       theory, we could use [string format] here; however, that
      #       would fail under Mono.
      #
      if {$tcl_precision != 4} then {
        set tcl_precision_save $tcl_precision
        set tcl_precision 4
      }

      if {$eagle_tests(skipped) > 0} then {
        set percent [getSkipPercentage]
        host result Break [appendArgs "SKIP PERCENTAGE: " $percent %\n]
        tlog [appendArgs "SKIP PERCENTAGE: " $percent %\n]
      }

      set percent [getPassPercentage]
      host result Return [appendArgs "PASS PERCENTAGE: " $percent %\n]
      tlog [appendArgs "PASS PERCENTAGE: " $percent% \n]

      #
      # NOTE: Restore the saved floating point precision.
      #
      if {[info exists tcl_precision_save]} then {
        set tcl_precision $tcl_precision_save
        unset tcl_precision_save
      }
    } else {
      #
      # NOTE: No tests.
      #
      set percent 0
    }

    #
    # NOTE: Has the test pass threshold been set?  If so, is it set to
    #       the default value?
    #
    if {![info exists test_threshold] || $test_threshold == 100} then {
      #
      # NOTE: The test pass threshold is set to the default value (100%).
      #       Check to make sure that all tests pass and then set the
      #       exit code to success; otherwise, we set it to failure.
      #
      set passedOrSkipped [expr {$eagle_tests(passed) + \
          $eagle_tests(skipped)}]

      if {$passedOrSkipped == $eagle_tests(total)} then {
        set exitCode Success

        host result Ok "OVERALL RESULT: SUCCESS\n"
        tlog "OVERALL RESULT: SUCCESS\n"
      } else {
        set exitCode Failure

        host result Error "OVERALL RESULT: FAILURE\n"
        tlog "OVERALL RESULT: FAILURE\n"
      }

      unset passedOrSkipped
    } else {
      #
      # NOTE: They specified a non-default test pass threshold.  Check to
      #       make sure that we meet or exceed the requirement and then
      #       set the exit code to success; otherwise, set it to failure.
      #
      if {$percent >= $test_threshold} then {
        set exitCode Success

        host result Ok [appendArgs "OVERALL RESULT: SUCCESS (" \
            $percent "% >= " $test_threshold %)\n]

        tlog [appendArgs "OVERALL RESULT: SUCCESS (" \
            $percent "% >= " $test_threshold %)\n]
      } else {
        set exitCode Failure

        host result Error [appendArgs \
            "OVERALL RESULT: FAILURE (" $percent "% < " $test_threshold %)\n]

        tlog [appendArgs \
            "OVERALL RESULT: FAILURE (" $percent "% < " $test_threshold %)\n]
      }
    }

    unset percent

    tputs $test_channel \n; # NOTE: Blank line.
  } else {
    tputs $test_channel \n; # NOTE: Blank line.

    if {$::tcltest::numTests(Passed) > 0} then {
      tputs $test_channel \
          [appendArgs "PASSED: " $::tcltest::numTests(Passed) \n]
    }

    if {$::tcltest::numTests(Failed) > 0} then {
      tputs $test_channel \
          [appendArgs "FAILED: " $::tcltest::numTests(Failed) \n]

      if {[llength $::tcltest::failFiles] > 0} then {
        tputs $test_channel \
            [appendArgs "FAILED: " $::tcltest::failFiles \n]
      }
    }

    if {$::tcltest::numTests(Skipped) > 0} then {
      tputs $test_channel \
          [appendArgs "SKIPPED: " $::tcltest::numTests(Skipped) \n]
    }

    if {$::tcltest::numTests(Total) > 0} then {
      tputs $test_channel \
          [appendArgs "TOTAL: " $::tcltest::numTests(Total) \n]

      if {$::tcltest::numTests(Skipped) > 0} then {
        set percent [getSkipPercentage]
        tputs $test_channel [appendArgs "SKIP PERCENTAGE: " \
            [format "%.4f" $percent] %\n]
      }

      set percent [getPassPercentage]
      tputs $test_channel [appendArgs "PASS PERCENTAGE: " \
          [format "%.4f" $percent] %\n]
    } else {
      #
      # NOTE: No tests.
      #
      set percent 0
    }

    #
    # NOTE: Has the test pass threshold been set?  If so, is it set to
    #       the default value?
    #
    if {![info exists test_threshold] || $test_threshold == 100} then {
      #
      # NOTE: The test pass threshold is set to the default value (100%).
      #       Check to make sure that all tests pass and then set the
      #       exit code to success; otherwise, we set it to failure.
      #
      set passedOrSkipped [expr {$::tcltest::numTests(Passed) + \
          $::tcltest::numTests(Skipped)}]

      if {$passedOrSkipped == $::tcltest::numTests(Total)} then {
        set exitCode 0; # Success.

        tputs $test_channel "OVERALL RESULT: SUCCESS\n"
      } else {
        set exitCode 1; # Failure.

        tputs $test_channel "OVERALL RESULT: FAILURE\n"
      }

      unset passedOrSkipped
    } else {
      #
      # NOTE: They specified a non-default test pass threshold.  Check to
      #       make sure that we meet or exceed the requirement and then
      #       set the exit code to success; otherwise, set it to failure.
      #
      if {$percent >= $test_threshold} then {
        set exitCode 0; # Success.

        tputs $test_channel [appendArgs "OVERALL RESULT: SUCCESS (" \
            $percent "% >= " $test_threshold %)\n]
      } else {
        set exitCode 1; # Failure.

        tputs $test_channel [appendArgs "OVERALL RESULT: FAILURE (" \
            $percent "% < " $test_threshold %)\n]
      }
    }

    unset percent

    tputs $test_channel \n; # NOTE: Blank line.
  }

  #
  # NOTE: Check for and process any custom test epilogue script that may
  #       be set in the environment.
  #
  sourceIfValid epilogue [getEnvironmentVariable testEpilogue]

  #
  # NOTE: Do we need to exit now?
  #
  if {[isExitOnComplete]} then {
    #
    # NOTE: Exit now.  In Eagle, this will not exit the entire process.
    #       Zero (0) will be the exit code if all the selected tests have
    #       succeeded or the test success threshold has been met or
    #       exceeded; otherwise, one (1) will be the exit code.
    #
    exit $exitCode
  } else {
    #
    # NOTE: For Eagle, even when not exiting, we still set the ExitCode
    #       property of the interpreter.
    #
    if {[isEagle]} then {
      object invoke -alias Interpreter.GetActive ExitCode $exitCode
    }

    unset exitCode
  }
}
Added Externals/Eagle/Tests/pkgIndex.eagle.










































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
###############################################################################
#
# pkgIndex.eagle --
#
# Extensible Adaptable Generalized Logic Engine (Eagle)
# Package Index File
#
# Copyright (c) 2007-2010 by Joe Mistachkin.  All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: $
#
###############################################################################

if {![package vsatisfies [package provide Tcl] 8.4]} {return}
if {![package vsatisfies [package provide Eagle] 1.0]} {return}

package ifneeded EagleTestConstraints 1.0 [list source [file join $dir \
    constraints.eagle]]
Added Externals/Eagle/Tests/pkgIndex.tcl.










































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
###############################################################################
#
# pkgIndex.tcl --
#
# Extensible Adaptable Generalized Logic Engine (Eagle)
# Package Index File
#
# Copyright (c) 2007-2010 by Joe Mistachkin.  All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: $
#
###############################################################################

if {![package vsatisfies [package provide Tcl] 8.4]} {return}
if {[string length [package provide Eagle]] > 0} then {return}

package ifneeded EagleTestConstraints 1.0 [list source [file join $dir \
    constraints.eagle]]
Added Externals/Eagle/Tests/prologue.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
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
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
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
###############################################################################
#
# prologue.eagle --
#
# Extensible Adaptable Generalized Logic Engine (Eagle)
# Test Prologue File
#
# Copyright (c) 2007-2010 by Joe Mistachkin.  All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: $
#
###############################################################################

if {![info exists no([file tail [info script]])]} then {
  if {[info level] > 0} then {
    error "cannot run, current level is not global"
  }

  #
  # NOTE: Set the location of the test suite, if necessary.
  #
  if {![info exists test_path]} then {
    set test_path [file normalize [file dirname [info script]]]
  }

  #
  # NOTE: Set the location of the base Eagle directory, if
  #       necessary.
  #
  if {![info exists base_path]} then {
    #
    # NOTE: Start out going up one level and check for a "lib"
    #       sub-directory.  If not found, go up another level
    #       because we will always be two levels down from the
    #       base directory when running inside the source tree.
    #
    set base_path [file normalize [file dirname $test_path]]

    #
    # HACK: We must verify that the "init.eagle" file can eventually
    #       be found under the "lib" directory since Visual Studio
    #       insists on creating a superfluous (and empty) "lib\Eagle1.0"
    #       sub-directory inside of the "Library" project directory
    #       simply due to the links contained in the project file that
    #       actually point to the "lib\Eagle1.0" sub-directory under the
    #       solution directory.
    #
    # WARNING: The Eagle package name and version are hard-coded here.
    #
    if {![file exists [file join $base_path lib]] || \
        ![file isdirectory [file join $base_path lib]] || \
        ![file exists [file join $base_path lib Eagle1.0]] || \
        ![file isdirectory [file join $base_path lib Eagle1.0]] || \
        ![file exists [file join $base_path lib Eagle1.0 init.eagle]] || \
        ![file isfile [file join $base_path lib Eagle1.0 init.eagle]]} then {
      #
      # NOTE: We do not bother to check if the "lib" sub-directory
      #       actually exists as a child of this one.  This is the
      #       previous (legacy) behavior (i.e. where we always went
      #       up two levels to the base directory).
      #
      set base_path [file dirname $base_path]
    }
  }

  #
  # NOTE: Set the executable file name for the process, if
  #       necessary.
  #
  if {![info exists bin_file]} then {
    set bin_file [info nameofexecutable]
  }

  #
  # NOTE: Set the location of the directory containing the
  #       executable file for the process, if necessary.
  #
  if {![info exists bin_path]} then {
    set bin_path [file normalize [file dirname $bin_file]]
  }

  #
  # NOTE: Set the location of the [non-script] library directory
  #       (i.e. the directory where the plugins are located), if
  #       necessary.
  #
  if {![info exists lib_path]} then {
    #
    # NOTE: This should go one directory up from the directory
    #       containing the executable file for the process (e.g.
    #       the shell) and then into the "lib" directory just
    #       beneath that.
    #
    set lib_path [file normalize [file join [file dirname $bin_path] lib]]
  }

  #
  # NOTE: Set the web host to test against, if necessary.
  #
  if {![info exists test_host]} then {
    set test_host eagle.to
  }

  #
  # NOTE: Set the port to use for server sockets, if necessary.
  #
  if {![info exists test_port]} then {
    set test_port 12346; # IANA, 12346-12752 Unassigned
  }

  #
  # NOTE: Set the network timeout, if necessary.
  #
  if {![info exists test_timeout]} then {
    set test_timeout 2000; # in milliseconds.
  }

  #
  # NOTE: Set the channel to use for test output, if necessary.
  #
  if {![info exists test_channel]} then {
    set test_channel stdout
  }

  #
  # NOTE: Set the primary package path, if necessary.
  #
  if {![info exists test_package_path]} then {
    set test_package_path [file join $base_path lib]
  }

  #
  # NOTE: Make sure our primary package path is part of the auto path.
  #
  if {[lsearch -exact $auto_path $test_package_path] == -1} then {
    lappend auto_path $test_package_path
  }

  #
  # NOTE: Make sure our test package path is part of the auto path.
  #
  if {[lsearch -exact $auto_path $test_path] == -1} then {
    lappend auto_path $test_path
  }

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

  #
  # NOTE: Check for and load the Eagle library package, if necessary.
  #
  if {[catch {package present EagleLibrary}]} then {
    package require EagleLibrary
  }

  #
  # NOTE: Check for and load the Eagle test package, if necessary.
  #
  if {[catch {package present EagleTest}]} then {
    package require EagleTest
  }

  #
  # NOTE: Check for and load the Eagle test constraints package, if
  #       necessary.
  #
  if {[catch {package present EagleTestConstraints}]} then {
    package require EagleTestConstraints
  }

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

  #
  # 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.
  set test_flags(-logFile) ""; # default to using standard log file naming.
  set test_flags(-threshold) ""; # default to requiring all tests to pass.
  set test_flags(-stopOnFailure) ""; # default to continue on failure.
  set test_flags(-exitOnComplete) ""; # default to not exit after complete.

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

    if {[info exists test_flags(-logFile)] && \
        [string length $test_flags(-logFile)] > 0} then {
      #
      # NOTE: Set the log file name to the one provided by the command line.
      #
      set test_log $test_flags(-logFile)
    }

    if {[info exists test_flags(-threshold)] && \
        [string is integer -strict $test_flags(-threshold)]} then {
      #
      # NOTE: Set the test pass threshold to the one provided by the command
      #       line.
      #
      set test_threshold $test_flags(-threshold)
    }

    if {[info exists test_flags(-stopOnFailure)] && \
        [string is boolean -strict $test_flags(-stopOnFailure)]} then {
      #
      # NOTE: Set the test stop-on-failure flag to the one provided by the
      #       command line.
      #
      set test_stop_on_failure $test_flags(-stopOnFailure)
    }

    if {[info exists test_flags(-exitOnComplete)] && \
        [string is boolean -strict $test_flags(-exitOnComplete)]} then {
      #
      # NOTE: Set the test exit-on-complete flag to the one provided by the
      #       command line.
      #
      set test_exit_on_complete $test_flags(-exitOnComplete)
    }
  }

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

  #
  # NOTE: Set the Tcl shell executable to use for those specialized
  #       tests that may require it, if necessary.
  #
  if {![info exists test_tclsh]} then {
    if {[isEagle] || ![string match tclsh* $bin_file]} then {
      set test_tclsh tclsh
    } else {
      set test_tclsh $bin_file
    }
  }

  #
  # NOTE: Has logging been disabled?
  #
  if {![info exists no(log)]} then {
    #
    # NOTE: Set the log to use for test output, if necessary.
    #
    if {![info exists test_log]} then {
      set test_log [file join [getTemporaryPath] [file tail [info \
          nameofexecutable]][getTestLogId].test.[pid].log]
    }
  }

  #
  # NOTE: Check for and process any custom test prologue script that may be set
  #       in the environment.  This must be done after the Eagle test package
  #       has been made available and after the log file has been setup.
  #
  sourceIfValid prologue [getEnvironmentVariable testPrologue]

  #
  # NOTE: Show the name of the executable and the command line arguments, if
  #       any.  This must be done after the log file has been setup; otherwise,
  #       this information will not be visible in the log file.
  #
  tputs $test_channel [appendArgs "---- testRunId: " \
      [getTestRunId] \n]

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

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

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

  if {[isEagle]} then {
    tputs $test_channel [appendArgs "---- original command line: " \
        [info cmdline] \n]

    tputs $test_channel [appendArgs "---- threadId: " \
        [info tid] \n]

    tputs $test_channel [appendArgs "---- processors: " \
        [info processors] \n]

    catch {object invoke Console.InputEncoding WebName} encoding

    tputs $test_channel [appendArgs "---- input encoding: " \
        $encoding \n]

    catch {object invoke Console.OutputEncoding WebName} encoding

    tputs $test_channel [appendArgs "---- output encoding: " \
        $encoding \n]

    tputs $test_channel [appendArgs "---- starting memory: " \
        [formatListAsDict [debug memory]] \n]

    catch {debug stack true} stack

    tputs $test_channel [appendArgs "---- starting stack: " \
        [formatListAsDict $stack] \n]

    unset stack
    catch {file drive} drive

    tputs $test_channel [appendArgs "---- system drive: " \
        [formatListAsDict $drive] \n]

    unset drive
  }

  tputs $test_channel [appendArgs "---- executable: \"" \
      $bin_file \"\n]

  tputs $test_channel [appendArgs "---- command line: " \
      [expr {[info exists argv] && [string length $argv] > 0 ? \
          $argv : "<none>"}] \n]

  tputs $test_channel [appendArgs "---- logging to: " \
      [expr {[info exists test_log] && [string length $test_log] > 0 ? \
          [appendArgs \" $test_log \"] : "<none>"}] \n]

  tputs $test_channel [appendArgs "---- pass threshold: " \
      [expr {[info exists test_threshold] && \
          [string is integer -strict $test_threshold] ? \
              [appendArgs $test_threshold %] : "<none>"}] \n]

  tputs $test_channel [appendArgs "---- stop on failure: " \
      [expr {[info exists test_stop_on_failure] && \
          [string is boolean -strict $test_stop_on_failure] ? \
              $test_stop_on_failure : "<none>"}] \n]

  tputs $test_channel [appendArgs "---- exit on complete: " \
      [expr {[info exists test_exit_on_complete] && \
          [string is boolean -strict $test_exit_on_complete] ? \
              $test_exit_on_complete : "<none>"}] \n]

  #
  # NOTE: Show the information about which tests and files are being run and/or
  #       skipped (COMPAT: Tcl).
  #
  if {[llength $test_flags(-file)] > 0} then {
    tputs $test_channel [appendArgs "---- running test files that match: " \
        $test_flags(-file) \n]
  }

  if {[llength $test_flags(-notFile)] > 0} then {
    tputs $test_channel [appendArgs "---- skipping test files that match: " \
        $test_flags(-notFile) \n]
  }

  if {[llength $test_flags(-match)] > 0} then {
    tputs $test_channel [appendArgs "---- running tests that match: " \
        $test_flags(-match) \n]
  }

  if {[llength $test_flags(-skip)] > 0} then {
    tputs $test_channel [appendArgs "---- skipping tests that match: " \
        $test_flags(-skip) \n]
  }

  tputs $test_channel [appendArgs "---- path: \"" \
      [expr {[info exists path] && [string length $path] > 0 ? \
          $path : "<none>"}] \"\n]

  tputs $test_channel [appendArgs "---- base path: \"" \
      $base_path \"\n]

  tputs $test_channel [appendArgs "---- binary path: \"" \
      $bin_path \"\n]

  tputs $test_channel [appendArgs "---- library path: \"" \
      $lib_path \"\n]

  tputs $test_channel [appendArgs "---- tests located in: \"" \
      $test_path \"\n]

  tputs $test_channel [appendArgs "---- tests running in: \"" \
      [pwd] \"\n]

  tputs $test_channel [appendArgs "---- temporary files stored in: \"" \
      [getTemporaryPath] \"\n]

  tputs $test_channel [appendArgs "---- native Tcl shell: \"" \
      $test_tclsh \"\n]

  #
  # NOTE: Initialize the Eagle test constraints.
  #
  if {[isEagle]} then {
    initializeTests

    #
    # NOTE: If the "no(mono)" variable is set (to anything) then any
    #       special test suite hacks for Mono will be disabled. This
    #       does not control or change any hacks for Mono that may
    #       be present in the library itself.
    #
    # if {![info exists no(mono)] && [isMono]} then {
    #   set no(mono) true
    # }

    #
    # NOTE: Has administrator detection support been disabled?  We do
    #       this check [nearly] first as it may [eventually] be used
    #       to help determine if other constraints should be skipped.
    #
    if {![info exists no(administrator)]} then {
      checkForAdministrator $test_channel
    }

    #
    # NOTE: Has host detection support been disabled?
    #
    if {![info exists no(host)]} then {
      checkForHost $test_channel
    }

    #
    # NOTE: Has primary thread detection support been disabled?  We do
    #       this check [nearly] first as it may [eventually] be used
    #       to help determine if other constraints should be skipped.
    #
    if {![info exists no(primaryThread)]} then {
      checkForPrimaryThread $test_channel
    }

    #
    # NOTE: Has runtime detection support been disabled?  We do this
    #       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?
    #
    if {![info exists no(machine)]} then {
      checkForMachine $test_channel 32 intel; # (i.e. x86)
      checkForMachine $test_channel 64 amd64; # (i.e. x64)
    }

    #
    # NOTE: Has culture detection support been disabled?
    #
    if {![info exists no(culture)]} then {
      checkForCulture $test_channel
    }

    #
    # NOTE: Has software update trust detection support been disabled?
    #
    if {![info exists no(softwareUpdate)]} then {
      checkForSoftwareUpdateTrust $test_channel
    }

    #
    # NOTE: Has database testing support been disabled?
    #
    if {![info exists no(sql)]} then {
      #
      # NOTE: Set the server name, if necessary.
      #
      if {![info exists server]} then {
        set server .
      }

      #
      # NOTE: Set the database name, if necessary.
      #
      if {![info exists database]} then {
        set database master
      }

      #
      # NOTE: Set the connection timeout, if necessary.
      #
      if {![info exists timeout]} then {
        set timeout [expr {$test_timeout / 1000}]; # milliseconds to seconds.
      }

      #
      # NOTE: Set the test user name, if necessary.
      #
      if {![info exists user]} then {
        set user [getEnvironmentVariable user]
      }

      #
      # NOTE: Set the test password, if necessary.
      #
      if {![info exists password]} then {
        set password [getEnvironmentVariable password]
      }

      #
      # NOTE: Set the database connection string, if necessary.
      #
      if {![info exists test_database]} then {
        #
        # NOTE: Mono does not have support for trusted connections;
        #       therefore, we must create a slightly different
        #       connection string.
        #
        set test_database [subst \
            {Data Source=${server};Initial Catalog=${database};Connect\
            Timeout=${timeout};[expr {[isMono] ? [subst \
            {User Id=${user};Password=${password};}] : {Integrated\
            Security=SSPI;}}]}]
      }

      #
      # NOTE: Can we access the local database?
      #
      checkForDatabase $test_channel $test_database
      unset password user timeout database server
    }

    #
    # NOTE: Has object handle reference count tracking support been disabled
    #       (at compile-time)?
    #
    if {![info exists no(refCount)]} then {
      #
      # NOTE: For tests "excel-*", "object-2.*", "object-7.1", "object-8.*",
      #       and "object-98.*".
      #
      checkForReferenceCountTracking $test_channel
    }

    #
    # NOTE: Has compile/runtime option testing support been disabled?
    #
    if {![info exists no(compileOptions)]} then {
      #
      # NOTE: Has callback queue support been enabled (at compile-time)?
      #
      if {![info exists no(compileCallbackQueue)]} then {
        #
        # NOTE: For test "commands-1.4".
        #
        checkForCompileOption $test_channel CALLBACK_QUEUE
      }

      #
      # NOTE: Has console support been enabled (at compile-time)?
      #
      if {![info exists no(compileConsole)]} then {
        #
        # NOTE: For test "host-1.2".
        #
        checkForCompileOption $test_channel CONSOLE
      }

      #
      # NOTE: Has database support been enabled (at compile-time)?
      #
      if {![info exists no(compileData)]} then {
        #
        # NOTE: For tests "sql-1.1" and "upvar-99.1".
        #
        checkForCompileOption $test_channel DATA
      }

      #
      # NOTE: Has script debugger support been enabled (at compile-time)?
      #
      if {![info exists no(compileDebugger)]} then {
        #
        # NOTE: For tests "debug-1.1", "debug-2.1", "debug-3.1" and
        #       "debug-4.1".
        #
        checkForCompileOption $test_channel DEBUGGER
      }

      #
      # NOTE: Has isolated interpreter support been enabled (at compile-time)?
      #
      if {![info exists no(compileIsolatedInterpreters)]} then {
        #
        # NOTE: For test "xaml-1.2".
        #
        checkForCompileOption $test_channel ISOLATED_INTERPRETERS
      }

      #
      # NOTE: Has isolated plugin support been enabled (at compile-time)?
      #
      if {![info exists no(compileIsolatedPlugins)]} then {
        #
        # NOTE: For test "load-1.1.1".
        #
        checkForCompileOption $test_channel ISOLATED_PLUGINS
      }

      #
      # NOTE: Has PowerShell approved-verbs support been enabled (at
      #       compile-time)?
      #
      if {![info exists no(compileApprovedVerbs)]} then {
        #
        # NOTE: For test "object-4.8".
        #
        checkForCompileOption $test_channel APPROVED_VERBS
      }

      #
      # NOTE: Has Mono support been enabled (at compile-time)?
      #
      if {![info exists no(compileMono)]} then {
        #
        # NOTE: For test "object-4.13".
        #
        checkForCompileOption $test_channel MONO
      }

      #
      # NOTE: Has Windows support been enabled (at compile-time)?
      #
      if {![info exists no(compileWindows)]} then {
        #
        # NOTE: For test "garuda-1.0".
        #
        checkForCompileOption $test_channel WINDOWS
      }

      #
      # NOTE: Has native code support been enabled (at compile-time)?
      #
      if {![info exists no(compileNative)]} then {
        #
        # NOTE: For tests "debug-3.2", "expr-3.2", and "host-1.1".
        #
        checkForCompileOption $test_channel NATIVE
      }

      #
      # NOTE: Has native package support been enabled (at compile-time)?
      #
      if {![info exists no(compileNativePackage)]} then {
        #
        # NOTE: For test "garuda-1.0".
        #
        checkForCompileOption $test_channel NATIVE_PACKAGE
      }

      #
      # NOTE: Has network support been enabled (at compile-time)?
      #
      if {![info exists no(compileNetwork)]} then {
        #
        # NOTE: For tests "commands-1.4", "socket-1.*", "socket-2.1", and
        #       "socket-3.1".
        #
        checkForCompileOption $test_channel NETWORK
      }

      #
      # NOTE: Has native Tcl support been enabled (at compile-time)?
      #
      if {![info exists no(compileTcl)]} then {
        #
        # NOTE: For tests "commands-1.1.*", "excel-2.2", "tclCancel-1.1",
        #       "tclEncoding-1.*", "tclErrorInfo-1.*", "tclLoad-1.*",
        #       "tclResetCancel-1.1", "tclResetCancel-2.1",
        #       "tclResetCancel-2.2", "tclResetCancel-3.1",
        #       "tclResetCancel-4.1", "tclSet-1.1", and "tclSubst-1.1".
        #
        checkForCompileOption $test_channel TCL
      }

      #
      # NOTE: Has xml support been enabled (at compile-time)?
      #
      if {![info exists no(compileXml)]} then {
        #
        # NOTE: For tests "commands-1.4", "object-7.3" and "xml-1.1.*".
        #
        checkForCompileOption $test_channel XML
      }

      #
      # NOTE: Has dedicated test support been enabled (at compile-time)?
      #
      if {![info exists no(compileTest)]} then {
        #
        # NOTE: For tests "basic-1.20", "basic-1.21", "function-1.1",
        #       "object-2.1", "object-3.1", "object-4.1", "object-7.1",
        #       "object-7.2", "object-7.4", "object-14.4", "object-14.5",
        #       "object-14.6", "remotingServer-1.*", and "debug-5.*".
        #
        checkForCompileOption $test_channel TEST
      }

      #
      # NOTE: Has threading support been enabled (at compile-time)?
      #
      if {![info exists no(compileThreading)]} then {
        #
        # NOTE: For tests "object-10.2" and "object-10.3".
        #
        checkForCompileOption $test_channel THREADING
      }

      #
      # NOTE: Has Tcl threading support been enabled (at compile-time)?
      #
      if {![info exists no(compileTclThreaded)]} then {
        #
        # NOTE: For tests "tclLoad-1.5" and "tclLoad-1.6".
        #
        checkForCompileOption $test_channel TCL_THREADED
      }

      #
      # NOTE: Has Tcl isolated interpreter thread support been enabled (at
      #       compile-time)?
      #
      if {![info exists no(compileTclThreads)]} then {
        #
        # NOTE: For tests "tclLoad-1.5" and "tclLoad-1.6".
        #
        checkForCompileOption $test_channel TCL_THREADS
      }
    }

    #
    # NOTE: Has dynamic loading testing support been disabled?
    #
    if {![info exists no(dynamic)]} then {
      #
      # NOTE: For tests "commands-1.1.*", "library-3.*", and "tcl*-*.*".
      #
      checkForDynamicLoading $test_channel
    }

    #
    # NOTE: Has Tcl testing support been disabled?
    #
    if {![info exists no(tcl)]} then {
      if {![info exists no(tclInstalls)]} then {
        #
        # NOTE: For tests "commands-1.1.*", "library-3.*", and "tcl*-*.*".
        #
        checkForTclInstalls $test_channel
      }

      if {![info exists no(tclReady)]} then {
        checkForTclReady $test_channel
      }

      if {![info exists no(tclShell)]} then {
        #
        # NOTE: For test "garuda-1.0".
        #
        checkForTclShell $test_channel
      }
    }

    #
    # NOTE: Has custom test method support been disabled?
    #
    if {![info exists no(test)]} then {
      #
      # NOTE: Has remoting testing support been disabled?
      #
      if {![info exists no(testRemoting)]} then {
        #
        # NOTE: For tests "remotingServer-1.*".
        #
        checkForObjectMember $test_channel Eagle._Tests.Default \
            *TestRemoting*
      }

      #
      # NOTE: Has asynchronous testing support been disabled?
      #
      if {![info exists no(testAsynchronous)]} then {
        #
        # NOTE: For tests "basic-1.20" and "basic-1.21".
        #
        checkForObjectMember $test_channel Eagle._Tests.Default \
            *TestEvaluateAsync*
      }

      #
      # NOTE: Has custom function testing support been disabled?
      #
      if {![info exists no(testFunction)]} then {
        #
        # NOTE: For test "function-1.1".
        #
        checkForObjectMember $test_channel Eagle._Tests.Default \
            *TestAddFunction*

        checkForObjectMember $test_channel Eagle._Tests.Default \
            *TestRemoveFunction*
      }

      #
      # NOTE: Has write-box testing support been disabled?
      #
      if {![info exists no(testWriteBox)]} then {
        #
        # NOTE: For tests "debug-5.*".
        #
        checkForObjectMember $test_channel Eagle._Tests.Default \
            *TestWriteBox*
      }

      #
      # NOTE: Has core marshaller testing support been disabled?
      #
      if {![info exists no(testMarshaller)]} then {
        #
        # NOTE: For test "object-2.1".
        #
        checkForObjectMember $test_channel Eagle._Tests.Default \
            *TestComplexMethod*

        #
        # NOTE: For test "object-2.3".
        #
        checkForObjectMember $test_channel Eagle._Components.Private.ArrayOps \
            *ToHexadecimalString*

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

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

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

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

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

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

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

        #
        # 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 \
            *TestNullableValueTypeMethod*

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

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

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

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

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

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

        #
        # NOTE: For tests "object-14.4" and "object-14.5".
        #
        checkForObjectMember $test_channel Eagle._Tests.Default \
            *StaticObjectProperty*

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

        #
        # NOTE: For test "basic-1.29".
        #
        checkForObjectMember $test_channel Eagle._Tests.Default \
            *TestExecuteStaticDelegates*

        #
        # NOTE: For tests "basic-1.30" and "basic-1.31".
        #
        checkForObjectMember $test_channel Eagle._Tests.Default \
            *TestExecuteDelegateCommands*

        #
        # NOTE: For test "object-7.2" and "object-7.4".
        #
        checkForObjectMember $test_channel Eagle._Tests.Default \
            *TestNullArray*

        checkForObjectMember $test_channel Eagle._Tests.Default \
            *TestOutArray*
      }
    }

    #
    # NOTE: Has Excel testing support been disabled?
    #
    if {![info exists no(excel)]} then {
      #
      # NOTE: For tests "excel-*.*".
      #
      checkForAssembly $test_channel Microsoft.Office.Interop.Excel
    }

    #
    # NOTE: Has speech testing support been disabled?
    #
    if {![info exists no(speech)]} then {
      #
      # NOTE: Set the audio volume, if necessary.
      #
      if {![info exists test_volume]} then {
        set test_volume 0; # in percent, 0 is silent.
      }

      #
      # NOTE: For test "object-4.5".
      #
      checkForAssembly $test_channel System.Speech
    }

    #
    # NOTE: Has WinForms testing support been disabled?
    #
    if {![info exists no(winForms)]} then {
      #
      # NOTE: For tests "object-13.1.*", "object-13.2.*", and
      #       "winForms-*.*".
      #
      checkForWindowsForms $test_channel
    }

    #
    # NOTE: Are we running in an STA thread?
    #
    if {![info exists no(staThread)]} then {
      #
      # NOTE: For test "xaml-1.*".
      #
      checkForStaThread $test_channel
    }

    #
    # NOTE: Has WPF testing support been disabled?
    #
    if {![info exists no(wpf)]} then {
      #
      # NOTE: For test "xaml-1.*".
      #
      checkForWindowsPresentationFoundation $test_channel
    }

    #
    # NOTE: Has PowerShell testing support been disabled?
    #
    if {![info exists no(powerShell)]} then {
      #
      # NOTE: For tests "object-4.7", "object-4.8", and "object-4.9".
      #
      checkForPowerShell $test_channel
    }

    #
    # NOTE: Has WiX testing support been disabled?
    #
    if {![info exists no(wix)]} then {
      #
      # NOTE: For test "object-4.10".
      #
      checkForWix $test_channel
    }

    #
    # 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
      #       "debug-4.1".
      #
      checkForScriptDebugger $test_channel
    }

    #
    # NOTE: Has script debugger interpreter testing support been
    #       disabled?
    #
    if {![info exists no(scriptDebuggerInterpreter)]} then {
      #
      # NOTE: For test "debug-2.1".
      #
      checkForScriptDebuggerInterpreter $test_channel
    }

    #
    # NOTE: Are we running under the Mono debugger?  If so, several
    #       tests will have to be disabled because they do not appear
    #       to work there.
    #
    if {![info exists no(monoDebugger)]} then {
      tputs $test_channel "---- checking for Mono debugger... "

      if {[haveConstraint mono] && [haveConstraint managedDebugger]} then {
        #
        # NOTE: Add a special test constraint to simplify the Mono debugger
        #       test constraint checking for the tests that need it.
        #
        addConstraint monoDebugger

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

    #
    # NOTE: Has Garuda testing support been disabled?
    #
    if {![info exists no(garudaDll)]} then {
      #
      # NOTE: For test "garuda-1.0".
      #
      checkForGarudaDll $test_channel
    }
  } else {
    #
    # HACK: Reset the test counts for tcltest.
    #
    set ::tcltest::numTests(Total) 0
    set ::tcltest::numTests(Skipped) 0
    set ::tcltest::numTests(Passed) 0
    set ::tcltest::numTests(Failed) 0

    #
    # HACK: Reset the list of failed files.
    #
    set ::tcltest::failFiles [list]
  }

  #
  # NOTE: For test "package-1.0".
  #
  if {![info exists no(pkgAll.tcl)]} then {
    checkForFile $test_channel [file join $base_path Package Tests all.tcl] \
        pkgAll.tcl
  }

  #
  # NOTE: For test "subst-1.*".
  #
  if {![info exists no(bad_subst.txt)]} then {
    checkForFile $test_channel [file join $test_path bad_subst.txt]
  }

  #
  # NOTE: For test "fileIO-1.*".
  #
  if {![info exists no(file.dat)]} then {
    checkForFile $test_channel [file join $test_path file.dat]
  }

  #
  # NOTE: For test "garbage-1.1".
  #
  if {![info exists no(garbage.txt)]} then {
    checkForFile $test_channel [file join $test_path garbage.txt]
  }

  #
  # NOTE: For test "xaml-1.*".
  #
  if {![info exists no(test.png)]} then {
    checkForFile $test_channel [file join $test_path test.png]
  }

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

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

  #
  # NOTE: For test "read.eagle".
  #
  if {![info exists no(read.eagle)]} then {
    checkForFile $test_channel [file join $test_path read.eagle]
  }

  #
  # NOTE: For test "read2.eagle".
  #
  if {![info exists no(read2.eagle)]} then {
    checkForFile $test_channel [file join $test_path read2.eagle]
  }

  #
  # NOTE: For test "read3.eagle".
  #
  if {![info exists no(read3.eagle)]} then {
    checkForFile $test_channel [file join $test_path read3.eagle]
  }

  #
  # NOTE: For test "read4.eagle".
  #
  if {![info exists no(read4.eagle)]} then {
    checkForFile $test_channel [file join $test_path read4.eagle]
  }

  #
  # NOTE: For test "source.eagle".
  #
  if {![info exists no(source.eagle)]} then {
    checkForFile $test_channel [file join $test_path source.eagle]
  }

  #
  # NOTE: For test "unbalanced_brace.eagle".
  #
  if {![info exists no(unbalanced_brace.eagle)]} then {
    checkForFile $test_channel [file join $test_path unbalanced_brace.eagle]
  }

  #
  # NOTE: For test "unbalanced_brace2.eagle".
  #
  if {![info exists no(unbalanced_brace2.eagle)]} then {
    checkForFile $test_channel [file join $test_path unbalanced_brace2.eagle]
  }

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

  #
  # NOTE: For test "load-1.1.*".
  #
  if {![info exists no(Plugin.dll)]} then {
    checkForFile $test_channel [file join $lib_path Plugin1.0 Plugin.dll]
  }

  #
  # NOTE: For test "object-6.1".
  #
  if {![info exists no(Sample.exe)]} then {
    checkForFile $test_channel [file join $bin_path Sample.exe]
  }

  #
  # NOTE: For test "object-4.8".
  #
  if {![info exists no(EagleCmdlets.dll)]} then {
    checkForFile $test_channel [file join $bin_path EagleCmdlets.dll]
  }

  #
  # NOTE: For test "object-4.10".
  #
  if {![info exists no(EagleExtensions.dll)]} then {
    checkForFile $test_channel [file join $bin_path EagleExtensions.dll]
  }

  #
  # NOTE: For test "object-4.10".
  #
  if {![info exists no(test.wxs)]} then {
    checkForFile $test_channel [file join $base_path Installer Tests test.wxs]
  }

  #
  # NOTE: For test "sql-1.2".
  #
  if {![info exists no(sqlite3.dll)]} then {
    checkForFile $test_channel [file join $bin_path sqlite3.dll]
  }

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

  if {![info exists no(test.sqlite3)]} then {
    checkForFile $test_channel [file join $test_path test.sqlite3]
  }

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

  if {![info exists no(version)]} then {
    checkForVersion $test_channel
  }

  if {![info exists no(eagle)]} then {
    checkForEagle $test_channel
  }

  if {![info exists no(garuda)]} then {
    checkForGaruda $test_channel
  }

  if {![info exists no(shell)]} then {
    checkForShell $test_channel
  }

  if {![info exists no(debug)]} then {
    checkForDebug $test_channel
  }

  #
  # NOTE: Has native code detection support been disabled?
  #
  if {![info exists no(native)]} then {
    checkForNativeCode $test_channel
  }

  #
  # NOTE: Check for various extra commands that may be present.
  #
  if {![info exists no(callbackCommand)]} then {
    checkForCommand $test_channel callback
  }

  if {![info exists no(libraryCommand)]} then {
    checkForCommand $test_channel library
  }

  if {![info exists no(socketCommand)]} then {
    checkForCommand $test_channel socket
  }

  if {![info exists no(sqlCommand)]} then {
    checkForCommand $test_channel sql
  }

  if {![info exists no(tclCommand)]} then {
    checkForCommand $test_channel tcl
  }

  if {![info exists no(xmlCommand)]} then {
    checkForCommand $test_channel xml
  }

  #
  # NOTE: Check for various features that were added through
  #       the TIP process.
  #
  if {![info exists no(tip127)]} then {
    checkForTip127 $test_channel
  }

  if {![info exists no(tip194)]} then {
    checkForTip194 $test_channel
  }

  if {![info exists no(tip241)]} then {
    checkForTip241 $test_channel
  }

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

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

  #
  # NOTE: Have precision timing tests been disabled?
  #
  if {![info exists no(timing)]} then {
    checkForTiming $test_channel 50; # 1/20th second.
  }

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

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

  #
  # NOTE: Check for network connectivity to our test host (i.e.
  #       the Eagle distribution site).
  #
  if {![info exists no(network)]} then {
    checkForNetwork $test_channel $test_host $test_timeout
  }

  #
  # NOTE: For Eagle, dump the platform information, including
  #       the compile options.
  #
  if {[isEagle]} then {
    #
    # NOTE: Figure out the approximate relative performance
    #       of this machine.
    #
    if {[haveConstraint performance]} then {
      tputs $test_channel [appendArgs \
          "---- checking for baseline BogoCops (commands-per-second)... "]

      if {![info exists test_base_cops]} then {
        #
        # NOTE: The expected performance numbers for all the
        #       performance tests will be calibrated based on
        #       this number (which is based on the measured
        #       performance of the actual machine that was
        #       used to determine those expected performance
        #       numbers).
        #
        set test_base_cops 36000.0
      }

      tputs $test_channel [appendArgs $test_base_cops \n]
      tputs $test_channel [appendArgs \
          "---- checking for current BogoCops (commands-per-second)... "]

      if {![info exists test_cops]} then {
        set test_cops [calculateBogoCops]
      }

      tputs $test_channel [appendArgs $test_cops \n]
    }

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

    set timeStamp [getPlatformInfo timeStamp ""]

    if {[string length $timeStamp] > 0} then {
      #########################################################################
      # MONO: Bug, see: https://bugzilla.novell.com/show_bug.cgi?id=479061
      #########################################################################

      if {[isMono]} then {
        #
        # HACK: We need something to go into the log file.
        #
        set timeStamp [lindex $timeStamp 0]
      } else {
        set timeStamp [clock format [clock scan $timeStamp] -iso]
      }
    } else {
      set timeStamp <none>
    }

    tputs $test_channel [appendArgs "---- build: " \
        [getPlatformInfo engine <none>] " " \
        [getPlatformInfo patchLevel <none>] " " \
        [getPlatformInfo tag <none>] " " \
        [getPlatformInfo text <none>] " " \
        [getPlatformInfo configuration <none>] " " \
        [getPlatformInfo suffix <none>] " " \
        $timeStamp \n]

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

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

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

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

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

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

    unset timeStamp
  }

  #
  # 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 ? \
      $test_file : "<none>"}] \n]

  #
  # NOTE: Show the active test constraints.
  #
  tputs $test_channel [appendArgs "---- constraints: " \
      [formatList [lsort [getConstraints]]] \n]

  #
  # NOTE: Show when the tests actually began (now).
  #
  tputs $test_channel [appendArgs "---- tests began at " \
      [clock format [clock seconds]] \n]
}
Changes to Externals/Eagle/bin/Eagle.dll.

cannot compute difference between binary files

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

cannot compute difference between binary files

Deleted Externals/Eagle/bin/EagleShell.exe.config.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?xml version="1.0" encoding="UTF-8" ?>
<!--
 *
 * EagleShell.exe.config -
 *
 * Copyright (c) 2007-2010 by Joe Mistachkin.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: $
 *
-->
<configuration>
  <startup useLegacyV2RuntimeActivationPolicy="true">
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
  </startup>

  <runtime>
    <!--
    <NetFx40_LegacySecurityPolicy enabled="true" />
    <generatePublisherEvidence enabled="false" />
    -->

    <!--
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Eagle"
                          publicKeyToken="29c6297630be05eb"
                          culture="neutral" />

        <bindingRedirect oldVersion="1.0.0.0-1.0.9999.65535"
                         newVersion="[info engine PatchLevel]" />
      </dependentAssembly>

      <dependentAssembly>
        <assemblyIdentity name="Eagle"
                          publicKeyToken="1e22ec67879739a2"
                          culture="neutral" />

        <bindingRedirect oldVersion="1.0.0.0-1.0.9999.65535"
                         newVersion="[info engine PatchLevel]" />
      </dependentAssembly>
    </assemblyBinding>
    -->
  </runtime>
</configuration>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






























































































Deleted Externals/Eagle/bin/EagleShell.exe.mda.config.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
<?xml version="1.0" encoding="UTF-8" ?>
<!--
 *
 * EagleShell.exe.mda.config -
 *
 * Copyright (c) 2007-2010 by Joe Mistachkin.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * 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" />
    <dllMainReturnsFalse />
    <exceptionSwallowedOnCallFromCom enable="true" />
    <failedQI />
    <fatalExecutionEngineError />
    <gcManagedToUnmanaged />
    <gcUnmanagedToManaged />
    <illegalPrepareConstrainedRegion />
    <invalidApartmentStateChange />
    <invalidCERCall />
    <invalidFunctionPointerInDelegate enable="true" />
    <invalidGCHandleCookie />
    <invalidIUnknown />
    <invalidMemberDeclaration />
    <invalidOverlappedToPinvoke />
    <invalidVariant />
    <jitCompilationStart>
      <methods>
        <match name="*" />
      </methods>
    </jitCompilationStart>
    <loaderLock />
    <loadFromContext />
    <marshalCleanupError enable="true" />
    <marshaling>
      <methodFilter>
        <match name="*" />
      </methodFilter>
      <fieldFilter>
        <match name="*" />
      </fieldFilter>
    </marshaling>
    <memberInfoCacheCreation />
    <moduloObjectHashcode modulus="1" />
    <nonComVisibleBaseClass />
    <notMarshalable />
    <openGenericCERCall />
    <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>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




































































































































































Changes to Externals/Eagle/lib/Eagle1.0/init.eagle.
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
    # 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:
    #

    #       <name1> <value1> <name2> <value2> ... <nameN> <valueN>
    #



    foreach {pairName pairValue} $dictionary {
      #
      # NOTE: Does this name match the one specified by the caller?
      #
      if {$pairName eq $name} then {
        #
        # NOTE: Return the value, optionally wrapped.
        #
        return [appendArgs $wrap $pairValue $wrap]

      }
    }

    #
    # NOTE: Return the default value.
    #
    return $default


  }

  proc getColumnValue { row column {default ""} {wrap ""} } {
    #
    # NOTE: Start with the default value.
    #
    set result $default







|
<

>
|

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







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
    # NOTE: This should work properly in both Tcl and Eagle.
    #
    eval lappend result $args
  }

  proc getDictionaryValue { dictionary name {default ""} {wrap ""} } {
    #
    # NOTE: Start with the default value.

    #
    set result $default

    #
    # NOTE: Locate the index of the named value we are interested in.
    #
    set index [lsearch -exact $dictionary $name]

    #
    # NOTE: Did we find the name in the row?
    #
    if {$index != -1} then {
      #
      # NOTE: The next element in the list will be the value.
      #

      incr index


      #

      # NOTE: Grab the value.
      #

      set result [appendArgs $wrap [lindex $dictionary $index] $wrap]
    }
  }

  proc getColumnValue { row column {default ""} {wrap ""} } {
    #
    # NOTE: Start with the default value.
    #
    set result $default
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
  }

  proc readFile { fileName } {
    #
    # NOTE: This should work properly in both Tcl and Eagle.
    #
    set file_id [open $fileName RDONLY]
    fconfigure $file_id -encoding binary -translation binary; # BINARY DATA
    set result [read $file_id]
    close $file_id
    return $result
  }

  proc readSharedFile { fileName } {
    #
    # NOTE: This should work properly in both Tcl and Eagle.
    #
    set command [list open $fileName RDONLY]

    #
    # HACK: Tcl appears to do this by default; however Eagle does not and
    #       will not.  Therefore, manually add the -share option to the
    #       command if running in Eagle.
    #
    if {[isEagle]} then {
      lappend command 0 file -share readWrite
    }

    #
    # NOTE: Open the file using the command constructed above, configure
    #       the channel for binary data, and output the data to it.
    #
    set file_id [eval $command]
    fconfigure $file_id -encoding binary -translation binary; # BINARY DATA
    set result [read $file_id]
    close $file_id
    return $result
  }

  proc writeFile { fileName data } {







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







210
211
212
213
214
215
216


























217
218
219
220
221
222
223
  }

  proc readFile { fileName } {
    #
    # NOTE: This should work properly in both Tcl and Eagle.
    #
    set file_id [open $fileName RDONLY]


























    fconfigure $file_id -encoding binary -translation binary; # BINARY DATA
    set result [read $file_id]
    close $file_id
    return $result
  }

  proc writeFile { fileName data } {
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
    if {[llength $options] > 0} then {eval lappend command $options}

    lappend command --

    #
    # HACK: Assume that Mono is somewhere along the PATH.
    #
    if {[isMono]} then {
      lappend command mono \
          [appendArgs \" [file nativename [info nameofexecutable]] \"]
    } else {
      lappend command [info nameofexecutable]
    }

    if {[llength $args] > 0} then {eval lappend command $args}

    return [uplevel 1 $command]
  }

  proc ldifference { list1 list2 } {
    set result [list]








|
|
<
<
|
<
<
|







529
530
531
532
533
534
535
536
537


538


539
540
541
542
543
544
545
546
    if {[llength $options] > 0} then {eval lappend command $options}

    lappend command --

    #
    # HACK: Assume that Mono is somewhere along the PATH.
    #
    if {[isMono]} then { lappend command mono }



    lappend command [info nameofexecutable]


    eval lappend command $args

    return [uplevel 1 $command]
  }

  proc ldifference { list1 list2 } {
    set result [list]

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

    foreach item $list {
      set result [uplevel 1 $script [list $result] [list $item]]
    }

    return $result
  }


































































  if {[isEagle]} then {
    ###########################################################################
    ############################ BEGIN Eagle ONLY #############################
    ###########################################################################

    proc isAdministrator {} {
      #
      # NOTE: Returns non-zero if the logged on user has full administrator
      #       rights on this machine.
      #
      return [expr {[info exists ::eagle_platform(administrator)] && \
          $::eagle_platform(administrator)}]
    }

    proc hasRuntimeOption { name } {
      #
      # NOTE: Returns non-zero if the specified runtime option is set.
      #
      return [object invoke Interpreter.GetActive HasRuntimeOption $name]
    }

    proc getPluginFlags { pattern } {
      foreach loaded [info loaded] {
        set plugin [lindex $loaded end]

        if {[regexp -- $pattern $plugin]} then {
          return [string map [list , " "] \
              [getDictionaryValue [info plugin $plugin] flags]]







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















<
<
<
<
<
<
<







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

    foreach item $list {
      set result [uplevel 1 $script [list $result] [list $item]]
    }

    return $result
  }

  proc testShim { args } {
    #
    # NOTE: Call the original (saved) [test] command, wrapping it in
    #       our standard test wrapper.
    #
    uplevel 1 [list runTest [concat ::savedTest $args]]
  }

  proc tsource { fileName {prologue true} {epilogue true} } {
    #
    # NOTE: At this point, we need to require the test package so that
    #       we can run the test prologue.  Besides, the contained test(s)
    #       will almost certainly require access to procedures defined in
    #       our test package.
    #
    package require EagleTest

    #
    # NOTE: Run the test prologue in the context of the caller (which
    #       must be global)?
    #
    if {$prologue} then {
      uplevel 1 runTestPrologue
    }

    #
    # NOTE: Save the original [test] command and setup our test shim in
    #       its place.
    #
    rename test ::savedTest
    interp alias {} test {} testShim

    #
    # NOTE: Source the specified test file in the context of the
    #       caller (which should be global).
    #
    set code [catch {uplevel 1 [list source $fileName]} result]
    set error [expr {$code == 0 ? false : true}]

    #
    # NOTE: Remove our test shim and restore the original (saved)
    #       [test] command.
    #
    interp alias {} test {}
    rename ::savedTest test

    #
    # NOTE: Run the test epilogue in the context of the caller (which
    #       must be global)?
    #
    if {$epilogue} then {
      uplevel 1 runTestEpilogue
    }

    #
    # NOTE: If the test raised an error, re-raise it now; otherwise,
    #       just return the result.
    #
    if {$error} then {
      error $result
    } else {
      return $result
    }
  }

  if {[isEagle]} then {
    ###########################################################################
    ############################ BEGIN Eagle ONLY #############################
    ###########################################################################

    proc isAdministrator {} {
      #
      # NOTE: Returns non-zero if the logged on user has full administrator
      #       rights on this machine.
      #
      return [expr {[info exists ::eagle_platform(administrator)] && \
          $::eagle_platform(administrator)}]
    }








    proc getPluginFlags { pattern } {
      foreach loaded [info loaded] {
        set plugin [lindex $loaded end]

        if {[regexp -- $pattern $plugin]} then {
          return [string map [list , " "] \
              [getDictionaryValue [info plugin $plugin] flags]]
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
      #
      # NOTE: This should work properly in Tcl only.
      #
      # NOTE: Forget any previous commands that were imported from this
      #       namespace into the global namespace?
      #
      if {$forget} then {
        namespace eval :: [list namespace forget [appendArgs $namespace ::*]]
      }

      #
      # NOTE: Process each command to be exported from the specified
      #       namespace and import it into the global namespace, if
      #       necessary.
      #
      foreach export $exports {
        #
        # NOTE: Force importing of our exported commands into the global
        #       namespace?  Otherwise, see if the command is already
        #       present in the global namespace before trying to import
        #       it.
        #
        if {$force || \
            [llength [info commands [appendArgs :: $export]]] == 0} then {
          #
          # NOTE: Export the specified command from the specified namespace.
          #
          namespace eval $namespace [list namespace export $export]

          #
          # NOTE: Import the specified command into the global namespace.
          #
          set namespaceExport [appendArgs $namespace :: $export]

          if {$force} then {
            namespace eval :: [list namespace import -force $namespaceExport]

          } else {
            namespace eval :: [list namespace import $namespaceExport]

          }
        }
      }
    }

    #
    # 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 filter map reduce \
        getPlatformInfo execShell] false false

    ###########################################################################
    ############################## END Tcl ONLY ###############################
    ###########################################################################
  }

  #
  # NOTE: Provide the Eagle library package to the interpreter.
  #
  package provide EagleLibrary \
    [expr {[isEagle] ? [info engine PatchLevel] : 1.0}]
}








|



|





|
|
|
|

|
<
<
<
<
|

<
<
<
<
<

|
>

|
>






|
|




|
|













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
      #
      # NOTE: This should work properly in Tcl only.
      #
      # NOTE: Forget any previous commands that were imported from this
      #       namespace into the global namespace?
      #
      if {$forget} then {
        namespace forget ${namespace}::*
      }

      #
      # NOTE: Process each of the commands to be exported from this
      #       namespace and import it into the global namespace, if
      #       necessary.
      #
      foreach export $exports {
        #
        # NOTE: Force importing of our exported commands into the
        #       global namespace?  Otherwise, see if the command is
        #       already present in the global namespace before trying
        #       to import it.
        #
        if {$force || [llength [info commands ::$export]] == 0} then {




          namespace export $export






          if {$force} then {
            namespace eval :: [list namespace import -force \
                ${namespace}::$export]
          } else {
            namespace eval :: [list namespace import \
                ${namespace}::$export]
          }
        }
      }
    }

    #
    # 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 filter map reduce tsource \
        getPlatformInfo testShim] false false

    ###########################################################################
    ############################## END Tcl ONLY ###############################
    ###########################################################################
  }

  #
  # NOTE: Provide the Eagle library package to the interpreter.
  #
  package provide EagleLibrary \
    [expr {[isEagle] ? [info engine PatchLevel] : 1.0}]
}

Changes to Externals/Eagle/lib/Eagle1.0/test.eagle.
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182

  proc sourceIfValid { type fileName } {
    if {[string length $fileName] > 0} then {
      if {[file exists $fileName]} then {
        tputs $::test_channel [appendArgs \
            "---- evaluating $type file: \"" $fileName \"\n]

        if {[catch {uplevel 1 [list source $fileName]} error]} then {
          tputs $::test_channel [appendArgs \
              "---- error during $type file: " $error \n]

          #
          # NOTE: The error has been logged, now re-throw it.
          #
          error $error $::errorInfo $::errorCode







|







168
169
170
171
172
173
174
175
176
177
178
179
180
181
182

  proc sourceIfValid { type fileName } {
    if {[string length $fileName] > 0} then {
      if {[file exists $fileName]} then {
        tputs $::test_channel [appendArgs \
            "---- evaluating $type file: \"" $fileName \"\n]

        if {[catch {uplevel 1 [list source $fileName]} error] != 0} then {
          tputs $::test_channel [appendArgs \
              "---- error during $type file: " $error \n]

          #
          # NOTE: The error has been logged, now re-throw it.
          #
          error $error $::errorInfo $::errorCode
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
    #       the caller.
    #
    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 -threshold]

    foreach {name value} $args {
      if {[lsearch -exact $options $name] != -1} then {
        set array($name) $value

        tputs $::test_channel [appendArgs \
            "---- overrode test option \"" $name "\" with value \"" $value \







|
<
|







196
197
198
199
200
201
202
203

204
205
206
207
208
209
210
211
    #       the caller.
    #
    upvar 1 $varName array

    #
    # TODO: Add more support for standard tcltest options here.
    #
    set options [list -configuration -suffix -file -notFile -match -skip \

        -constraints -logFile -threshold -stopOnFailure -exitOnComplete]

    foreach {name value} $args {
      if {[lsearch -exact $options $name] != -1} then {
        set array($name) $value

        tputs $::test_channel [appendArgs \
            "---- overrode test option \"" $name "\" with value \"" $value \
227
228
229
230
231
232
233
234

235
236
237
238
239
240
241
242
    set names [list]

    foreach name [list TEMP TMP] {
      #
      # NOTE: Make sure we handle all the reasonable "cases" of
      #       the environment variable names.
      #
      lappend names [string toupper $name] [string tolower $name] \

          [string totitle $name]
    }

    #
    # NOTE: Check if we can use any of the environment variables.
    #
    foreach name $names {
      set value [getEnvironmentVariable $name]







|
>
|







226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
    set names [list]

    foreach name [list TEMP TMP] {
      #
      # NOTE: Make sure we handle all the reasonable "cases" of
      #       the environment variable names.
      #
      lappend names [string toupper $name]
      lappend names [string tolower $name]
      lappend names [string totitle $name]
    }

    #
    # NOTE: Check if we can use any of the environment variables.
    #
    foreach name $names {
      set value [getEnvironmentVariable $name]
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
      # BUGBUG: Tcl 8.4 does not like this expression (and Tcl tries to
      #         compile it even though it will only actually ever be
      #         evaluated in Eagle).
      #
      set expr {random()}

      #
      # NOTE: Include the host name to make the result more unique in both

      #       time and space.  Also, hash the entire constructed string.
      #
      if {![isMono]} then {
        #
        # NOTE: When running on the .NET Framework, we can simply use the
        #       [string format] command.
        #
        return [hash normal sha256 [string format \
            "{0}{1:X8}{2:X8}{3:X16}{4:X16}{5:X16}" [info host] [pid] \
            [info tid] [clock now] [clock clicks] [expr $expr]]]
      } else {
        #
        # HACK: Mono does not currently support calling the String.Format
        #       overload that takes a variable number of arguments via
        #       reflection (Mono bug #636939).  Also, strip any leading
        #       minus signs for cleanliness.
        #
        return [hash normal sha256 [appendArgs [info host] [string trimleft \
            [pid] -] [string trimleft [info tid] -] [string trimleft \
            [clock now] -] [string trimleft [clock clicks] -] [string trimleft \
            [expr $expr] -]]]
      }
    } else {
      #
      # NOTE: Generate a random number using [expr] and then convert it
      #       to hexadecimal.
      #

      binary scan [binary format d* [expr {rand()}]] w* random

      #
      # NOTE: Convert the host name to a hexadecimal string and include
      #       it in the result in an attempt to make it more unique in
      #       both time and space.
      #
      binary scan [info host] c* host
      set host [eval [list format [string repeat %X [llength $host]]] $host]

      #
      # NOTE: Build the final result with the [format] command, converting
      #       all the pieces to hexadecimal (except the host, which is
      #       already hexadecimal).
      #
      set pid [pid]; set seconds [clock seconds]; set clicks [clock clicks]

      return [appendArgs $host [format [appendArgs % [getLengthModifier $pid] \
          X% [getLengthModifier $seconds] X% [getLengthModifier $clicks] X% \
          [getLengthModifier $random] X] $pid $seconds $clicks $random]]
    }
  }

  proc getTestLogId {} {
    return [expr {[info exists ::test_log_id] ? \
        [append result . $::test_log_id] : ""}]
  }

  proc getTestLog {} {
    return [expr {[info exists ::test_log] ? $::test_log : ""}]
  }

  proc testExec { commandName options args } {
    set command [list exec]

    if {[llength $options] > 0} then {eval lappend command $options}

    lappend command -- $commandName

    if {[llength $args] > 0} then {eval lappend command $args}

    tputs $::test_channel [appendArgs "---- running command: " $command \n]

    return [uplevel 1 $command]
  }

  proc testClrExec { commandName options args } {
    set command [list exec]

    if {[llength $options] > 0} then {eval lappend command $options}

    lappend command --

    #
    # HACK: Assume that Mono is somewhere along the PATH.
    #
    if {[isMono]} then {
      lappend command mono \
          [appendArgs \" [file nativename $commandName] \"]
    } else {
      lappend command $commandName
    }

    if {[llength $args] > 0} then {eval lappend command $args}

    tputs $::test_channel [appendArgs "---- running command: " $command \n]

    return [uplevel 1 $command]
  }

  proc execTestShell { options args } {







|
>
|


<
<
|
<
<
<
|


<
<
<
|

|
|
|
|


<
<
<
<
>


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

















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

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







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
      # BUGBUG: Tcl 8.4 does not like this expression (and Tcl tries to
      #         compile it even though it will only actually ever be
      #         evaluated in Eagle).
      #
      set expr {random()}

      #
      # HACK: Mono does not currently support calling the String.Format
      #       overload that takes a variable number of arguments via
      #       reflection (Mono bug #636939).
      #
      if {![isMono]} then {


        return [string format "{0:X16}{1:X16}{2:X16}" \



            [clock now] [clock clicks] [expr $expr]]
      } else {
        #



        # NOTE: Strip any leading minus signs for cleanliness.
        #
        return [appendArgs \
            [string trimleft [clock now] -] \
            [string trimleft [clock clicks] -] \
            [string trimleft [expr $expr] -]]
      }
    } else {




      set seconds [clock seconds]; set clicks [clock clicks]
      binary scan [binary format d* [expr {rand()}]] w* random
















      return [format [appendArgs % [getLengthModifier $seconds] X% \
          [getLengthModifier $clicks] X% [getLengthModifier $random] X] \
          $seconds $clicks $random]
    }
  }

  proc getTestLogId {} {
    return [expr {[info exists ::test_log_id] ? \
        [append result . $::test_log_id] : ""}]
  }

  proc getTestLog {} {
    return [expr {[info exists ::test_log] ? $::test_log : ""}]
  }

  proc testExec { commandName options args } {
    set command [list exec]

    if {[llength $options] > 0} then {eval lappend command $options}















    lappend command --








    lappend command $commandName


    eval lappend command $args

    tputs $::test_channel [appendArgs "---- running command: " $command \n]

    return [uplevel 1 $command]
  }

  proc execTestShell { options args } {
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
          #
          return [tputs $::test_channel [lindex $args 0]]
        }
        2 {
          #
          # NOTE: Either -nonewline or channelId has been specified.
          #
          if {[lindex $args 0] eq "-nonewline"} then {
            return [tputs $::test_channel [lindex $args end]]
          } else {
            set channel [lindex $args 0]
            set newLine \n
          }
        }
        3 {
          #
          # NOTE: Both -nonewline and channelId are specified, unless
          #       it's an error.  The -nonewline option is supposed to
          #       be argv[0].
          #
          if {[lindex $args 0] eq "-nonewline"} then {
            set channel [lindex $args 1]
            set newLine ""
          }
        }
      }

      if {[info exists channel]} then {
        if {$channel eq "stdout"} then {
          #
          # NOTE: Write output for stdout to the test channel.
          #
          return [tputs $::test_channel [appendArgs [lindex $args end] \
              $newLine]]
        }
      }







|












|







|







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
          #
          return [tputs $::test_channel [lindex $args 0]]
        }
        2 {
          #
          # NOTE: Either -nonewline or channelId has been specified.
          #
          if {[string equal [lindex $args 0] -nonewline]} then {
            return [tputs $::test_channel [lindex $args end]]
          } else {
            set channel [lindex $args 0]
            set newLine \n
          }
        }
        3 {
          #
          # NOTE: Both -nonewline and channelId are specified, unless
          #       it's an error.  The -nonewline option is supposed to
          #       be argv[0].
          #
          if {[string equal [lindex $args 0] -nonewline]} then {
            set channel [lindex $args 1]
            set newLine ""
          }
        }
      }

      if {[info exists channel]} then {
        if {[string equal $channel stdout]} then {
          #
          # NOTE: Write output for stdout to the test channel.
          #
          return [tputs $::test_channel [appendArgs [lindex $args end] \
              $newLine]]
        }
      }
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
        tputs $::test_channel [appendArgs "ERROR (runTest): " $result \n]
      }

      unhookPuts
    }
  }

  proc testShim { args } {
    #
    # NOTE: Call the original (saved) [test] command, wrapping it in
    #       our standard test wrapper.
    #
    uplevel 1 [list runTest [concat ::savedTest $args]]
  }

  proc tsource { fileName {prologue true} {epilogue true} } {
    #
    # NOTE: Run the test prologue in the context of the caller (which
    #       must be global)?
    #
    if {$prologue} then {
      uplevel 1 runTestPrologue
    }

    #
    # NOTE: Save the original [test] command and setup our test shim in
    #       its place.
    #
    rename ::test ::savedTest
    interp alias {} ::test {} testShim

    #
    # NOTE: Source the specified test file in the context of the caller
    #       (which should be global).
    #
    set code [catch {uplevel 1 [list source $fileName]} result]
    set error [expr {$code == 0 ? false : true}]

    #
    # NOTE: Remove our test shim and restore the original (saved) [test]
    #       command.
    #
    interp alias {} ::test {}
    rename ::savedTest ::test

    #
    # NOTE: Run the test epilogue in the context of the caller (which
    #       must be global)?
    #
    if {$epilogue} then {
      uplevel 1 runTestEpilogue
    }

    #
    # NOTE: If the test raised an error, re-raise it now; otherwise,
    #       just return the result.
    #
    if {$error} then {
      error $result
    } else {
      return $result
    }
  }

  proc recordTestStatistics { varName index } {
    #
    # NOTE: Record counts of all object types that we track.
    #
    upvar 1 $varName array

    set array(time,$index) [clock seconds]







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







529
530
531
532
533
534
535

























































536
537
538
539
540
541
542
        tputs $::test_channel [appendArgs "ERROR (runTest): " $result \n]
      }

      unhookPuts
    }
  }


























































  proc recordTestStatistics { varName index } {
    #
    # NOTE: Record counts of all object types that we track.
    #
    upvar 1 $varName array

    set array(time,$index) [clock seconds]
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
      #
      set array(connections,$index) 0
      set array(transactions,$index) 0
      set array(modules,$index) 0
      set array(delegates,$index) 0
      set array(tcl,$index) 0
      set array(tclinterps,$index) 0
      set array(tclthreads,$index) 0
      set array(tclcommands,$index) 0

      catch {set array(connections,$index) [llength [info connections]]}
      catch {set array(transactions,$index) [llength [info transactions]]}
      catch {set array(modules,$index) [llength [info modules]]}
      catch {set array(delegates,$index) [llength [info delegates]]}

      if {[llength [info commands tcl]] > 0} then {
        set array(tcl,$index) [tcl ready]
      }

      catch {set array(tclinterps,$index) [llength [tcl interps]]}
      catch {set array(tclthreads,$index) [llength [tcl threads]]}
      catch {set array(tclcommands,$index) [llength [tcl command list]]}
    }
  }

  proc reportTestStatistics { channel fileName statsVarName filesVarName } {
    set statistics [list afters variables commands procedures files \
        temporaryFiles channels aliases interpreters environment]

    if {[isEagle]} then {
      #
      # TODO: For now, tracking "leaked" assemblies is meaningless because
      #       the .NET Framework has no way to unload them without tearing
      #       down the entire application domain.
      #
      lappend statistics scopes objects callbacks types interfaces \
          namespaces processes connections transactions modules \
          delegates tcl tclinterps tclthreads tclcommands; # assemblies
    }

    #
    # NOTE: Show what leaked, if anything.
    #
    set count 0; upvar 1 $statsVarName array

    foreach statistic $statistics {
      if {$array($statistic,after) > $array($statistic,before)} then {
        incr count

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

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

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

    #
    # NOTE: Make sure this file name is recorded in the list of file names with
    #       leaking tests.
    #
    upvar 1 $filesVarName fileNames

    if {$count > 0 && \
        [lsearch -exact $fileNames [file tail $fileName]] == -1} then {
      lappend fileNames [file tail $fileName]
    }
  }

  proc formatList { list {default ""} {columns 1} } {
    set count 1
    set result ""

    foreach item $list {
      if {[incr count -1] == 0} then {
        set count $columns
        append result \n
      }

      append result \t

      if {[string length $item] > 0} then {
        append result $item
      } else {
        append result <noItem>
      }
    }

    return [expr {[string length $result] > 0 ? $result : $default}]
  }

  proc formatListAsDict { list {default ""} } {
    set result ""

    foreach {name value} $list {
      append result \n\t

      if {[string length $name] > 0} then {
        append result $name
      } else {
        append result <noName>
      }

      append result ": "

      if {[string length $value] > 0} then {
        append result $value
      } else {
        append result <noValue>
      }
    }

    return [expr {[string length $result] > 0 ? $result : $default}]
  }

  proc inverseLsearchGlob { noCase patterns element } {
    #
    # NOTE: Perform the inverse of [lsearch -glob], attempt
    #       to match an element against a list of patterns.
    #







<












<




|











|





|



<
<














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


















|


|




















|







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
      #
      set array(connections,$index) 0
      set array(transactions,$index) 0
      set array(modules,$index) 0
      set array(delegates,$index) 0
      set array(tcl,$index) 0
      set array(tclinterps,$index) 0

      set array(tclcommands,$index) 0

      catch {set array(connections,$index) [llength [info connections]]}
      catch {set array(transactions,$index) [llength [info transactions]]}
      catch {set array(modules,$index) [llength [info modules]]}
      catch {set array(delegates,$index) [llength [info delegates]]}

      if {[llength [info commands tcl]] > 0} then {
        set array(tcl,$index) [tcl ready]
      }

      catch {set array(tclinterps,$index) [llength [tcl interps]]}

      catch {set array(tclcommands,$index) [llength [tcl command list]]}
    }
  }

  proc reportTestStatistics { channel fileName varName } {
    set statistics [list afters variables commands procedures files \
        temporaryFiles channels aliases interpreters environment]

    if {[isEagle]} then {
      #
      # TODO: For now, tracking "leaked" assemblies is meaningless because
      #       the .NET Framework has no way to unload them without tearing
      #       down the entire application domain.
      #
      lappend statistics scopes objects callbacks types interfaces \
          namespaces processes connections transactions modules \
          delegates tcl tclinterps tclcommands; # assemblies
    }

    #
    # NOTE: Show what leaked, if anything.
    #
    upvar 1 $varName array

    foreach statistic $statistics {
      if {$array($statistic,after) > $array($statistic,before)} then {


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

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

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











  proc formatList { list {columns 1} } {
    set count 1
    set result ""

    foreach item $list {
      if {[incr count -1] == 0} then {
        set count $columns
        append result \n
      }

      append result \t

      if {[string length $item] > 0} then {
        append result $item
      } else {
        append result <noItem>
      }
    }

    return $result
  }

  proc formatListAsDict { list } {
    set result ""

    foreach {name value} $list {
      append result \n\t

      if {[string length $name] > 0} then {
        append result $name
      } else {
        append result <noName>
      }

      append result ": "

      if {[string length $value] > 0} then {
        append result $value
      } else {
        append result <noValue>
      }
    }

    return $result
  }

  proc inverseLsearchGlob { noCase patterns element } {
    #
    # NOTE: Perform the inverse of [lsearch -glob], attempt
    #       to match an element against a list of patterns.
    #
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
        lappend result $fileName
      }
    }

    return $result
  }

  proc formatDecimal { value {places 4} } {
    if {[isEagle]} then {
      #
      # HACK: This works; however, in order to do this kind of thing cleanly,
      #       we really need the Tcl [format] command.
      #
      set result [object invoke String Format [appendArgs "{0:0." \
          [string repeat # $places] "}"] [set object [object invoke \
          -create Double Parse $value]]]

      unset object; # dispose
    } else {
      #
      # NOTE: See, nice and clean when done in Tcl?
      #
      set result [format [appendArgs %. $places f] $value]
    }

    return $result
  }

  proc clearTestPercent { channel } {
    if {[isEagle]} then {
      host title ""
    }
  }

  proc reportTestPercent { channel percent } {
    set status [appendArgs "---- test suite running, about " $percent \
        "% complete..."]

    tputs $channel [appendArgs $status \n]

    if {[isEagle]} then {
      host title $status
    }
  }

  proc runAllTests { channel path fileNames skipFileNames } {
    #
    # NOTE: Show the exact arguments we received since they may not
    #       have been displayed by the caller (or anybody else).
    #
    tputs $channel [appendArgs "---- test run path: \"" $path \"\n]

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

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

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

    #
    # NOTE: So far, we have run no tests.
    #
    set count 0

    #
    # NOTE: So far, no files have had failing or leaking tests.
    #
    set failed [list]
    set leaked [list]

    #
    # NOTE: Process each file name we have been given by the caller...
    #
    set total [llength $fileNames]; set lastPercent -1

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

      if {$percent != $lastPercent} then {
        reportTestPercent $channel $percent
        set lastPercent $percent
      }

      #
      # NOTE: Skipping over any file name that matches a pattern in the
      #       list of file names to skip.
      #
      if {[inverseLsearchGlob false $skipFileNames \
          [file tail $fileName]] == -1} then {
        #







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





|

|


|














|


<




<
<

<
<
<
<
<
<
<
<
<
<
<







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

    return $result
  }







































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

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

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

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

    #
    # NOTE: So far, we have run no tests.
    #
    set count 0

    #
    # NOTE: So far, no files have had no files with failing tests.
    #
    set failed [list]


    #
    # NOTE: Process each file name we have been given by the caller...
    #


    foreach fileName $fileNames {











      #
      # NOTE: Skipping over any file name that matches a pattern in the
      #       list of file names to skip.
      #
      if {[inverseLsearchGlob false $skipFileNames \
          [file tail $fileName]] == -1} then {
        #
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
          #
          if {[catch {uplevel 1 [list source $fileName]} error]} then {
            #
            # NOTE: Most likely, this error was caused by malformed or
            #       incorrect code in-between the tests themselves.  We
            #       need to report this.
            #
            tputs $channel [appendArgs "==== \"" $fileName "\" ERROR \"" \
                $error \"\n]

            #
            # NOTE: Stop further processing after this loop iteration?
            #
            if {[isStopOnFailure]} then {
              #
              # NOTE: This will terminate the loop right after the test
              #       file cleanup code (i.e. at the bottom of the loop).
              #
              set stop true
            }
          }

          #
          # 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 {100.0 * ($count / double($total))}]]

          if {$percent != $lastPercent} then {
            reportTestPercent $channel $percent
            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)







|
|


















<
<
<
<
<
<
<
<
<
<
<







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
          #
          if {[catch {uplevel 1 [list source $fileName]} error]} then {
            #
            # NOTE: Most likely, this error was caused by malformed or
            #       incorrect code in-between the tests themselves.  We
            #       need to report this.
            #
            tputs $::test_channel [appendArgs "==== \"" $fileName \
                "\" ERROR \"" $error \"\n]

            #
            # NOTE: Stop further processing after this loop iteration?
            #
            if {[isStopOnFailure]} then {
              #
              # NOTE: This will terminate the loop right after the test
              #       file cleanup code (i.e. at the bottom of the loop).
              #
              set stop true
            }
          }

          #
          # 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)
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
            #
            recordTestStatistics leaks after

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

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

        if {$percent != $lastPercent} then {
          reportTestPercent $channel $percent
          set lastPercent $percent
        }

        #
        # NOTE: If the test file raised an error (i.e. to indicate a
        #       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
      }

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

      if {$percent != $lastPercent} then {
        reportTestPercent $channel $percent
        set lastPercent $percent
      }
    }

    #
    # NOTE: Reset the host title because we may have changed it in the for
    #       loop (above).
    #
    clearTestPercent $channel

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

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

    if {[llength $leaked] > 0} then {
      tputs $channel [appendArgs "---- files with leaking tests: " $leaked \n]
    }
  }

  proc configureTcltest { imports force } {
    if {[isEagle]} then {
      #
      # NOTE: Fake having the tcltest package.
      #
      package provide tcltest 2.2.10; # Tcl 8.4

      #
      # HACK: Compatibility shim(s) for use with various tests in the Tcl
      #       test suite.
      #
      interp alias {} testConstraint {} haveOrAddConstraint
      interp alias {} ::tcltest::testConstraint {} haveOrAddConstraint

      #
      # NOTE: This is needed by most tests in the Tcl test suite.
      #
      proc ::tcltest::cleanupTests { args } {}
    } else {
      #
      # NOTE: Load the tcltest package.
      #
      package require tcltest

      #







|

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










<
<
<
<
<
<

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


|


|
<
|
<
<




















|







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
            #
            recordTestStatistics leaks after

            #
            # NOTE: Determine if any resource leaks have occurred and
            #       output diagnostics as necessary if they have.
            #
            reportTestStatistics $channel $fileName leaks
          }

















        }

        #
        # NOTE: If the test file raised an error (i.e. to indicate a
        #       test failure with the stop-on-failure flag enabled),
        #       break out of the test loop now.
        #
        if {$stop} then {
          break
        }






      }
    }


















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

    #
    # NOTE: Show the files that had failing tests.
    #
    if {[llength $failed] > 0} then {
      tputs $::test_channel [appendArgs "---- files with failing tests: " \

          $failed \n]


    }
  }

  proc configureTcltest { imports force } {
    if {[isEagle]} then {
      #
      # NOTE: Fake having the tcltest package.
      #
      package provide tcltest 2.2.10; # Tcl 8.4

      #
      # HACK: Compatibility shim(s) for use with various tests in the Tcl
      #       test suite.
      #
      interp alias {} testConstraint {} haveOrAddConstraint
      interp alias {} ::tcltest::testConstraint {} haveOrAddConstraint

      #
      # NOTE: This is needed by most tests in the Tcl test suite.
      #
      proc ::tcltest::cleanupTests {} {}
    } else {
      #
      # NOTE: Load the tcltest package.
      #
      package require tcltest

      #
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235

        if {[info exists test_flags(-skip)]} then {
          set eagle_tests(skipNames) $test_flags(-skip); # skip these tests.
        } else {
          set eagle_tests(skipNames) [list]; # default to skipping no tests.
        }

        #
        # NOTE: What tests have been skipped, if any?
        #
        set eagle_tests(skippedNames) [list]

        #
        # NOTE: What tests have failed, if any?
        #
        set eagle_tests(failedNames) [list]

        #
        # NOTE: Initialize the list of active test constraints from the







<
<
<
<
<







991
992
993
994
995
996
997





998
999
1000
1001
1002
1003
1004

        if {[info exists test_flags(-skip)]} then {
          set eagle_tests(skipNames) $test_flags(-skip); # skip these tests.
        } else {
          set eagle_tests(skipNames) [list]; # default to skipping no tests.
        }






        #
        # NOTE: What tests have failed, if any?
        #
        set eagle_tests(failedNames) [list]

        #
        # NOTE: Initialize the list of active test constraints from the
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
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
1438
            {100.0 * ($::eagle_tests(skipped) / \
            double($::eagle_tests(total)))}]
      }

      return 0; # no tests were run, etc.
    }

    proc cleanupThread { thread {timeout 2000} } {
      if {[$thread IsAlive]} then {
        if {[catch {$thread Interrupt} error]} then {
          tputs $::test_channel [appendArgs \
              "---- failed to interrupt test thread \"" $thread "\": " $error \
              \n]
        } else {
          tputs $::test_channel [appendArgs "---- test thread \"" $thread \
              "\" interrupted\n"]
        }

        if {[$thread IsAlive]} then {
          if {[catch {$thread Join $timeout} error]} then {
            tputs $::test_channel [appendArgs \
                "---- failed to join test thread \"" $thread "\": " $error \n]
          } elseif {$error} then {
            tputs $::test_channel [appendArgs "---- joined test thread \"" \
                $thread \"\n]
          } else {
            tputs $::test_channel [appendArgs \
                "---- timeout joining test thread \"" $thread " (" $timeout \
                " milliseconds)\"\n"]
          }

          if {[$thread IsAlive]} then {
            if {[catch {$thread Abort} error]} then {
              tputs $::test_channel [appendArgs \
                  "---- failed to abort test thread \"" $thread "\": " $error \
                  \n]
            } else {
              tputs $::test_channel [appendArgs "---- test thread \"" $thread \
                  "\" aborted\n"]
            }

            if {[$thread IsAlive]} then {
              tputs $::test_channel [appendArgs "---- test thread \"" $thread \
                  "\" appears to be a zombie\n"]
            } else {
              return true; # aborted?
            }
          } else {
            return true; # joined?


          }
        } else {
          return true; # interrupted?
        }
      } else {
        return true; # already dead?
      }

      return false; # still alive (or error).
    }

    proc calculateBogoCops { {milliseconds 2000} } {
      #
      # NOTE: Save the current background error handler for later restoration
      #       and then reset the current background error handler to nothing.
      #
      set bgerror [interp bgerror {}]
      interp bgerror {} ""

      try {
        #
        # NOTE: Save the current [after] flags for later restoration and then
        #       reset them to process events immediately.
        #
        set flags [after flags]
        after flags =Immediate

        try {
          set code [catch {
            #
            # NOTE: Schedule the event to cancel the script we are about to
            #       evaluate, capturing the name so we can cancel it later, if
            #       necessary.
            #
            set event [after $milliseconds [list interp cancel]]

            #
            # HACK: There is the potential for a "race condition" here.  If the
            #       specified number of milliseconds elapses before (or after)
            #       entering the [catch] script block (below) then the resulting
            #       script cancellation error will not be caught and we will be
            #       unable to return the correct result to the caller.
            #
            set before [info cmdcount]
            catch {time {nop} -1}; # uses the [time] internal busy loop.
            set after [info cmdcount]

            #
            # HACK: Mono has a bug that results in excessive trailing zeros
            #       here (Mono bug #655780).
            #
            if {[isMono]} then {

              expr {double(($after - $before) / ($milliseconds / 1000.0))}
            } else {
              expr {($after - $before) / ($milliseconds / 1000.0)}
            }
          } result]

          #
          # NOTE: If we failed to calculate the number of commands-per-second
          #       due to some subtle race condition [as explained above], return
          #       an obviously invalid result instead.
          #
          if {$code == 0} then {
            return $result
          } else {
            return 0
          }
        } finally {
          if {[info exists event]} then {
            catch {after cancel $event}
          }

          after flags =$flags
        }
      } finally {
        interp bgerror {} $bgerror
      }
    }

    proc evalWithTimeout { script {milliseconds 2000} {resultVarName ""} } {
      #
      # NOTE: Save the current background error handler for later restoration
      #       and then reset the current background error handler to nothing.
      #
      set bgerror [interp bgerror {}]
      interp bgerror {} ""

      try {
        #
        # NOTE: Save the current [after] flags for later restoration and then
        #       reset them to process events immediately.
        #
        set flags [after flags]
        after flags =Immediate

        try {
          #
          # NOTE: Evaluate the specified script in the context of the caller,
          #       returning the result to the caller.
          #
          if {[string length $resultVarName] > 0} then {
            upvar 1 $resultVarName result
          }

          return [catch {
            #
            # NOTE: Schedule the event to cancel the script we are about to
            #       evaluate, capturing the name so we can cancel it later, if
            #       necessary.
            #
            set event [after $milliseconds [list interp cancel]]

            #
            # NOTE: Evaluate the script in the context of the caller.
            #
            uplevel 1 $script
          } result]
        } finally {
          if {[info exists event]} then {
            catch {after cancel $event}
          }

          after flags =$flags
        }
      } finally {
        interp bgerror {} $bgerror
      }
    }








|



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

|
|
|
|
|
<
<
<
|

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










<
<
<
<




<
<
<
<




<
<
<
<
<
<
|

<
<
<
<
<
<
<
|
|
|

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

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







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
            {100.0 * ($::eagle_tests(skipped) / \
            double($::eagle_tests(total)))}]
      }

      return 0; # no tests were run, etc.
    }

    proc cleanupThread { thread } {
      if {[$thread IsAlive]} then {
        if {[catch {$thread Interrupt} error]} then {
          tputs $::test_channel [appendArgs \
              "---- failed to interrupt test thread \"" \












              $thread "\": " $error \n]




        }

        if {[$thread IsAlive]} then {
          if {[catch {$thread Abort} error]} then {
            tputs $::test_channel [appendArgs \
                "---- failed to abort test thread \"" \
                $thread "\": " $error \n]



          }

          if {![$thread IsAlive]} then {
            tputs $::test_channel [appendArgs \
                "---- test thread \"" $thread "\" aborted\n"]

            return true; # aborted?
          }
        } else {

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


          return true; # interrupted?
        }
      } else {
        return true; # already dead?
      }

      return false; # still alive (or error).
    }

    proc calculateBogoCops { {milliseconds 2000} } {




      set bgerror [interp bgerror {}]
      interp bgerror {} ""

      try {




        set flags [after flags]
        after flags =Immediate

        try {






          set event [after $milliseconds [list interp cancel]]








          set before [info cmdcount]
          catch {time {nop} -1}; # internal busy loop.
          set after [info cmdcount]

          #
          # HACK: Mono has a bug that results in excessive trailing zeros
          #       here (Mono bug #655780).
          #
          if {[isMono]} then {
            return [expr \
                {double(($after - $before) / ($milliseconds / 1000.0))}]
          } else {
            return [expr {($after - $before) / ($milliseconds / 1000.0)}]
          }












        } finally {

          catch {after cancel $event}




















































          after flags =$flags
        }
      } finally {
        interp bgerror {} $bgerror
      }
    }

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
        }
        default {
          return unknown
        }
      }
    }

    proc getGarudaDll {} {
      #
      # NOTE: Get the Garuda DLL of the same platform (i.e. machine type)
      #       as the native Tcl shell.
      #
      if {[info exists ::base_path]} then {
        #
        # NOTE: If the test configuration is available, use it.  Failing that,
        #       use the build configuration of Eagle itself.
        #
        if {[info exists ::test_configuration]} then {
          #
          # NOTE: Use the test configuration.  The default value is "Release",
          #       as set by the test suite prologue; however, this may have
          #       been overridden.
          #
          set configuration $::test_configuration
        } elseif {[info exists ::eagle_platform(configuration)]} then {
          #
          # NOTE: Use the build configuration of Eagle itself.  This value will
          #       always be "Debug" or "Release".
          #
          set configuration $::eagle_platform(configuration)
        } else {
          #
          # NOTE: We are missing the configuration, return nothing.
          #
          return ""
        }

        #
        # NOTE: Build the full path and file name of the Garuda DLL, using
        #       the Eagle base path.  Currently, this will only work
        #       correctly if the test suite is being run from inside the
        #       source tree.
        #
        return [file join $::base_path bin \
            [machineToPlatform [getMachineForTclShell]] [appendArgs \
            $configuration Dll] [appendArgs Garuda [info sharedlibextension]]]
      } else {
        #
        # NOTE: We are missing the base path, return nothing.
        #
        return ""
      }
    }

    proc cleanupExcel {} {
      #
      # TODO: These may need to be changed in later Excel versions.
      #
      object undeclare -declarepattern Microsoft.Office.Interop.Excel*
      object unimport -importpattern Microsoft.Office.Interop.Excel
    }







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







1165
1166
1167
1168
1169
1170
1171















































1172
1173
1174
1175
1176
1177
1178
        }
        default {
          return unknown
        }
      }
    }
















































    proc cleanupExcel {} {
      #
      # TODO: These may need to be changed in later Excel versions.
      #
      object undeclare -declarepattern Microsoft.Office.Interop.Excel*
      object unimport -importpattern Microsoft.Office.Interop.Excel
    }
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
      object unimport -importpattern System.Windows.Forms.PropertyGridInternal
      object unimport -importpattern System.Windows.Forms.VisualStyles
    }

    #
    # NOTE: Setup the test path relative to the library path.
    #
    if {![interp issafe] && ![info exists ::test_path]} then {
      #
      # NOTE: Try the source release directory structure.
      #
      set ::test_path [file join [file normalize [file dirname [file dirname \
          [info library]]]] Library Tests]

      if {![file exists $::test_path] || \
          ![file isdirectory $::test_path]} then {
        #
        # NOTE: Try for the test package directory.
        #
        set ::test_path [file join [file normalize [file dirname \
            [file dirname [info script]]]] Test1.0]
      }

      if {![file exists $::test_path] || \
          ![file isdirectory $::test_path]} then {
        #
        # NOTE: This must be a binary release, no "Library" directory then.
        #       Also, binary releases have an upper-case "Tests" directory
        #       name that originates from the "update.bat" tool.  This must
        #       match the casing used in "update.bat".
        #
        set ::test_path [file join [file normalize [file dirname [file dirname \
            [info library]]]] Tests]
      }
    }

    #
    # NOTE: Fake having the tcltest package unless we are prevented.
    #
    if {![info exists ::no(configureTcltest)]} then {







|









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


|







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
      object unimport -importpattern System.Windows.Forms.PropertyGridInternal
      object unimport -importpattern System.Windows.Forms.VisualStyles
    }

    #
    # NOTE: Setup the test path relative to the library path.
    #
    if {![interp issafe] && ![info exists test_path]} then {
      #
      # NOTE: Try the source release directory structure.
      #
      set ::test_path [file join [file normalize [file dirname [file dirname \
          [info library]]]] Library Tests]

      if {![file exists $::test_path] || \
          ![file isdirectory $::test_path]} then {
        #









        # NOTE: Must be a binary release, no "Library" directory then.
        #       Also, binary releases have a lower-case "tests" directory
        #       name that originates from the "update.bat" tool.  Must
        #       match casing with "update.bat".
        #
        set ::test_path [file join [file normalize [file dirname [file dirname \
            [info library]]]] tests]
      }
    }

    #
    # NOTE: Fake having the tcltest package unless we are prevented.
    #
    if {![info exists ::no(configureTcltest)]} then {
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

      return 0; # no tests were run, etc.
    }

    #
    # NOTE: Setup the test path relative to the path of this file.
    #
    if {![info exists ::test_path]} then {
      #
      # NOTE: Try the source release directory structure.
      #
      set ::test_path [file join [file normalize [file dirname \
          [file dirname [file dirname [info script]]]]] Library Tests]

      if {![file exists $::test_path] || \
          ![file isdirectory $::test_path]} then {
        #
        # NOTE: Try for the test package directory.
        #
        set ::test_path [file join [file normalize [file dirname \
            [file dirname [info script]]]] Test1.0]
      }

      if {![file exists $::test_path] || \
          ![file isdirectory $::test_path]} then {
        #
        # NOTE: This must be a binary release, no "Library" directory then.
        #       Also, binary releases have an upper-case "Tests" directory
        #       name that originates from the "update.bat" tool.  This must
        #       match the casing used in "update.bat".
        #
        set ::test_path [file join [file normalize [file dirname \
            [file dirname [file dirname [info script]]]]] Tests]
      }
    }

    #
    # NOTE: Load and configure the tcltest package unless we are prevented.
    #
    if {![info exists ::no(configureTcltest)]} then {
      configureTcltest [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 \
        tputs formatDecimal formatList configureTcltest tsource testShim] \
        false false

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

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







|









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


|




















|
<













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

      return 0; # no tests were run, etc.
    }

    #
    # NOTE: Setup the test path relative to the path of this file.
    #
    if {![info exists test_path]} then {
      #
      # NOTE: Try the source release directory structure.
      #
      set ::test_path [file join [file normalize [file dirname \
          [file dirname [file dirname [info script]]]]] Library Tests]

      if {![file exists $::test_path] || \
          ![file isdirectory $::test_path]} then {
        #









        # NOTE: Must be a binary release, no "Library" directory then.
        #       Also, binary releases have a lower-case "tests" directory
        #       name that originates from the "update.bat" tool.  Must
        #       match casing with "update.bat".
        #
        set ::test_path [file join [file normalize [file dirname \
            [file dirname [file dirname [info script]]]]] tests]
      }
    }

    #
    # NOTE: Load and configure the tcltest package unless we are prevented.
    #
    if {![info exists ::no(configureTcltest)]} then {
      configureTcltest [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 \
        tputs formatList configureTcltest] false false


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

  #
  # NOTE: Provide the Eagle test package to the interpreter.
  #
  package provide EagleTest \
    [expr {[isEagle] ? [info engine PatchLevel] : 1.0}]
}

Deleted Externals/Eagle/lib/Eagle1.0/vendor.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
###############################################################################
#
# vendor.eagle --
#
# Extensible Adaptable Generalized Logic Engine (Eagle)
# Vendor Initialization File
#
# Copyright (c) 2007-2010 by Joe Mistachkin.  All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: $
#
###############################################################################

#
# STUB: This script file is a placeholder.  This file, when present, is always
#       evaluated when an interpreter is initialized.  Vendors distributing
#       Eagle can place custom application-specific, interpreter-specific
#       initialization and/or customizations in here.  Additionally, this file
#       may contain per-interpreter customizations required when porting to
#       new platforms, operating systems, etc.
#

#
# 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 {
  if {[isEagle]} then {
    #
    # NOTE: This script library helper procedure helps to establish the link
    #       between the System.Data.SQLite test package and Eagle.
    #
    proc addTestSuiteToAutoPath { channel quiet } {
      #
      # NOTE: Start with the directory containing this file.
      #
      set dir [file normalize [file dirname [info script]]]

      #
      # NOTE: Keep going until the directory name is empty OR is actually the
      #       root of the associated volume.
      #
      while {[string length $dir] > 0 && \
          [lsearch -exact -nocase -- [file volumes] $dir] == -1} {
        #
        # NOTE: Does this directory have the necessary sub-directory that
        #       contains a package index file?
        #
        if {[file exists [file join $dir Tests]] && \
            [file isdirectory [file join $dir Tests]] && \
            [file exists [file join $dir Tests pkgIndex.eagle]] && \
            [file isfile [file join $dir Tests pkgIndex.eagle]]} then {
          #
          # NOTE: Ok, show the directory we found.
          #
          set dir [file join $dir Tests]

          #
          # NOTE: We found the necessary directory to add to the auto-path;
          #       However, we cannot simply add it to the auto-path directly
          #       because the auto-path is dynamically constructed after this
          #       script is evaluated; therefore, set the Eagle library path
          #       environment variable and force the appropriate internal path
          #       list to be refreshed.
          #
          if {![info exists ::env(EAGLELIBPATH)] || \
              [lsearch -exact $::env(EAGLELIBPATH) $dir] == -1} then {
            #
            # NOTE: If we have NOT been instructed to be quiet, report now.
            #
            if {!$quiet} then {
              puts -nonewline $channel [appendArgs \
                  "Found vendor-specific test package directory \"" $dir \
                  "\", adding...\n"]
            }

            lappend ::env(EAGLELIBPATH) $dir
            object invoke Utility RefreshAutoPathList
          }

          #
          # NOTE: We are done, return success.
          #
          return true
        }

        #
        # NOTE: Keep going up the directory tree...
        #
        set dir [file dirname $dir]
      }

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

      #
      # NOTE: Directory not found, return failure.
      #
      return false
    }

    addTestSuiteToAutoPath stdout false
  }
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


































































































































































































































Deleted Externals/Eagle/lib/Test1.0/constraints.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
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
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
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
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
1694
###############################################################################
#
# constraints.eagle --
#
# Extensible Adaptable Generalized Logic Engine (Eagle)
# Test Constraints File
#
# Copyright (c) 2007-2010 by Joe Mistachkin.  All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: $
#
###############################################################################

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

    addConstraint $::tcl_platform(platform)

    if {![isEagle]} then {
      #
      # BUGFIX: We do not want to skip any Mono bugs in Tcl.
      #         Also, fake the culture.
      #
      set constraints [list monoToDo monoBug monoCrash culture.en_US]

      #
      # NOTE: Add the necessary constraints for each version
      #       of Mono we know about.
      #
      foreach version [list 20 22 24 26 28 210 30] {
        addConstraint [appendArgs monoToDo $version]
        addConstraint [appendArgs monoBug $version]
        addConstraint [appendArgs monoCrash $version]
      }

      foreach constraint $constraints {
        addConstraint $constraint; # running in Tcl.
      }
    }

    tputs $channel [appendArgs $::tcl_platform(platform) \n]
  }

  proc checkForEagle { channel } {
    tputs $channel "---- checking for Eagle... "

    if {[isEagle]} then {
      #
      # NOTE: We are running inside Eagle.
      #
      addConstraint eagle

      #
      # NOTE: We do not want to skip bugs or crashing
      #       issues for Tcl since we are not running
      #       in Tcl.
      #
      addConstraint tclBug
      addConstraint tclCrash

      #
      # NOTE: Add the necessary constraints for each
      #       version of Tcl we know about.
      #
      foreach version [list 84 85 86] {
        addConstraint [appendArgs tclBug $version]
        addConstraint [appendArgs tclCrash $version]
      }

      tputs $channel yes\n
    } else {
      #
      # NOTE: We are running inside Tcl.
      #
      addConstraint tcl

      #
      # NOTE: Each Tcl bug and crash constraint is set
      #       based on the exact Tcl version (i.e. not
      #       greater than or equal to).
      #
      if {[info exists ::tcl_version]} then {
        #
        # NOTE: For each Tcl version we know about,
        #       check it against the currently running
        #       Tcl version.  If the two are not equal,
        #       add the test constraints that prevent
        #       skipping those tests that are buggy
        #       only for the particular version of Tcl.
        #
        foreach dotVersion [list 8.4 8.5 8.6] {
          if {$::tcl_version ne $dotVersion} then {
            set version [string map [list . ""] $dotVersion]

            addConstraint [appendArgs tclBug $version]
            addConstraint [appendArgs tclCrash $version]
          }
        }
      }

      #
      # NOTE: We do not want to skip bugs or crashing
      #       issues for Eagle since we are not running
      #       in Eagle.
      #
      addConstraint eagleBug
      addConstraint eagleCrash

      #
      # HACK: Needed by tests "socket-*.*".
      #
      if {![info exists ::no(compileNetwork)]} then {
        addConstraint compile.NETWORK
      }

      tputs $channel no\n
    }
  }

  proc checkForSymbols { channel name {constraint ""} } {
    set fileName [file normalize [appendArgs [file rootname $name] .pdb]]

    tputs $channel [appendArgs "---- checking for symbols \"" $fileName \
        "\"... "]

    if {[file exists $fileName]} then {
      #
      # NOTE: The file appears to have associated symbols available.
      #
      if {[string length $constraint] > 0} then {
        addConstraint [appendArgs symbols_ $constraint]
      } else {
        addConstraint [appendArgs symbols_ [file tail $name]]
      }

      tputs $channel yes\n
    } else {
      tputs $channel no\n
    }
  }

  proc checkForLogFile { channel } {
    tputs $channel "---- checking for log file... "

    if {[info exists ::test_log] && \
        [string length $::test_log] > 0 && \
        [file exists $::test_log]} then {
      #
      # NOTE: The log file appears to be available.
      #
      addConstraint logFile

      tputs $channel yes\n
    } else {
      tputs $channel no\n
    }
  }

  proc checkForGaruda { channel } {
    tputs $channel "---- checking for Garuda... "

    if {[haveGaruda packageId]} then {
      #
      # NOTE: We are running with or via Garuda.
      #
      addConstraint garuda

      tputs $channel [appendArgs "yes (" $packageId ")\n"]
    } else {
      tputs $channel no\n
    }
  }

  proc checkForShell { channel } {
    tputs $channel "---- checking for shell... "

    set name [file rootname [file tail [info nameofexecutable]]]

    if {[isEagle]} then {
      if {$name eq "EagleShell"} then {
        #
        # NOTE: We are running in Eagle via the EagleShell.
        #
        addConstraint shell

        tputs $channel "yes (Eagle)\n"

        #
        # NOTE: We are done here, return now.
        #
        return
      }
    } else {
      if {[string match tclsh* $name]} then {
        #
        # NOTE: We are running in Tcl via tclsh.
        #
        addConstraint shell

        tputs $channel "yes (Tcl)\n"

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

    tputs $channel no\n
  }

  proc checkForDebug { channel } {
    tputs $channel "---- checking for debug... "

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

      tputs $channel yes\n
    } else {
      tputs $channel no\n
    }
  }

  proc checkForTk { channel } {
    tputs $channel "---- checking for Tk... "

    #
    # HACK: For now, disable testing Tk 8.4/8.5 when running in Eagle.
    #
    if {![isEagle] || [haveConstraint tclLibrary86]} then {
      addConstraint tk

      tputs $channel yes\n
    } else {
      tputs $channel no\n
    }
  }

  proc checkForVersion { channel } {
    tputs $channel "---- checking for language version... "

    if {[info exists ::tcl_version]} then {
      #
      # TODO: Cleanup the semantics for adding test
      #       constraints here.
      #
      if {$::tcl_version eq "8.4"} then {
        #
        # NOTE: Baseline reported language and feature
        #       version.
        #
        addConstraint tcl84
        addConstraint tcl84OrHigher
        addConstraint tcl84Feature

        if {[isEagle]} then {
          #
          # NOTE: *EAGLE* We do want to include any
          #       tests that target "Tcl 8.5 or higher"
          #       features and/or "Tcl 8.6 or higher"
          #       features because they would not be in
          #       the test suite if we did not support
          #       that particular feature, regardless
          #       of the language version.
          #
          addConstraint tcl85Feature
          addConstraint tcl86Feature
        }
      } elseif {$::tcl_version eq "8.5"} then {
        #
        # NOTE: Baseline reported language and feature
        #       version.  Tcl 8.5 includes all the
        #       features from itself and Tcl 8.4.
        #
        addConstraint tcl85
        addConstraint tcl84OrHigher
        addConstraint tcl85OrHigher
        addConstraint tcl84Feature
        addConstraint tcl85Feature

        if {[isEagle]} then {
          #
          # NOTE: *EAGLE* We do want to include any
          #       tests that target "Tcl 8.5 or higher"
          #       features and/or "Tcl 8.6 or higher"
          #       features because they would not be in
          #       the test suite if we did not support
          #       that particular feature, regardless
          #       of the language version.
          #
          addConstraint tcl86Feature
        }
      } elseif {$::tcl_version eq "8.6"} then {
        #
        # NOTE: Baseline reported language and feature
        #       version.  Tcl 8.6 includes all the
        #       features from itself Tcl 8.4, and Tcl
        #       8.5.
        #
        addConstraint tcl86
        addConstraint tcl84OrHigher
        addConstraint tcl85OrHigher
        addConstraint tcl86OrHigher
        addConstraint tcl84Feature
        addConstraint tcl85Feature
        addConstraint tcl86Feature
      }

      tputs $channel [appendArgs $::tcl_version \n]
    } else {
      tputs $channel no\n
    }
  }

  proc checkForCommand { channel name } {
    tputs $channel [appendArgs "---- checking for command \"" $name \
        "\"... "]

    #
    # NOTE: Is the command available?
    #
    if {[llength [info commands $name]] > 0} then {
      #
      # NOTE: Yes, it appears that it is available.
      #
      addConstraint [appendArgs command. $name]

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

    if {[file exists $name]} then {
      #
      # NOTE: Yes, it appears that it is available.
      #
      if {[string length $constraint] > 0} then {
        addConstraint [appendArgs file_ $constraint]
      } else {
        addConstraint [appendArgs file_ [file tail $name]]
      }

      tputs $channel yes\n
    } else {
      tputs $channel no\n
    }
  }

  proc checkForPathFile { channel name {constraint ""} } {
    tputs $channel [appendArgs "---- checking for file \"" $name \
        "\" along PATH... "]

    if {[file exists $name]} then {
      #
      # NOTE: Yes, it appears that it is available [in the exact location they
      #       specified].
      #
      if {[string length $constraint] > 0} then {
        addConstraint [appendArgs file_ $constraint]
      } else {
        addConstraint [appendArgs file_ [file tail $name]]
      }

      tputs $channel yes\n

      #
      # NOTE: We are done here, return now.
      #
      return
    } else {
      #
      # NOTE: Use the appropriate environment variable for the platform.
      #
      if {$::tcl_platform(platform) eq "windows"} then {
        set pathName PATH
      } else {
        #
        # HACK: For shared libraries, use the LD_LIBRARY_PATH.
        #
        if {[file extension $name] eq [info sharedlibextension]} then {
          set pathName LD_LIBRARY_PATH
        } else {
          set pathName PATH
        }
      }

      #
      # NOTE: Is the required environment variable available?
      #
      if {[info exists ::env($pathName)]} then {
        #
        # NOTE: Ok, grab it now.
        #
        set path $::env($pathName)

        #
        # NOTE: Use the appropriate path separator for the platform.
        #
        if {[info exists ::tcl_platform(pathSeparator)]} then {
          set separator $::tcl_platform(pathSeparator)
        } elseif {$::tcl_platform(platform) eq "windows"} then {
          set separator \;
        } else {
          set separator :
        }

        #
        # NOTE: Grab just the file name from the possibly fully qualified file
        #       name provided by the caller.
        #
        set tail [file tail $name]

        #
        # NOTE: Check each directory in the PATH for the file.
        #
        foreach directory [split $path $separator] {
          #
          # NOTE: Check for the file in this directory contained in the PATH.
          #       This strips the directory portion off the file name specified
          #       by the caller, if any, before joining that file name to the
          #       current directory of the PATH being searched.
          #
          if {[file exists [file join $directory $tail]]} then {
            #
            # NOTE: Yes, it appears that it is available in the PATH.
            #
            if {[string length $constraint] > 0} then {
              addConstraint [appendArgs file_ $constraint]
            } else {
              addConstraint [appendArgs file_ [file tail $name]]
            }

            tputs $channel yes\n

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

    tputs $channel no\n
  }

  proc checkForNativeCode { channel } {
    tputs $channel "---- checking for native code... "

    if {[isEagle]} then {
      if {[info exists ::eagle_platform(compileOptions)] && \
          [info exists ::tcl_platform(platform)] && \
          [lsearch -exact -nocase $::eagle_platform(compileOptions) \
          $::tcl_platform(platform)] != -1} then {
        #
        # NOTE: Yes, the binary matches the current platform,
        #       native code can be used.
        #
        addConstraint native

        tputs $channel yes\n
      } else {
        tputs $channel no\n
      }
    } else {
      #
      # NOTE: Tcl is always native code and can always execute native code.
      #
      addConstraint native

      #
      # HACK: Needed by test "benchmark-1.22".
      #
      if {![info exists ::no(compileNative)]} then {
        addConstraint compile.NATIVE
      }

      tputs $channel yes\n
    }
  }

  proc checkForTip127 { channel } {
    tputs $channel "---- checking for TIP #127... "

    #
    # NOTE: Is the interpreter TIP #127 ready?
    #
    if {[catch {lsearch -index 0 0 0}] == 0} then {
      addConstraint tip127

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

    #
    # NOTE: Is the interpreter TIP #194 ready?
    #
    catch {apply} error

    if {$error ne {invalid command name "apply"}} then {
      addConstraint tip194

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

    #
    # NOTE: Is the interpreter TIP #241 ready?
    #
    if {[catch {lsearch -nocase 0 0}] == 0} then {
      addConstraint tip241

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

    #
    # NOTE: Is the interpreter TIP #285 ready?
    #
    catch {interp cancel} error

    if {$error eq "eval canceled"} then {
      addConstraint tip285

      tputs $channel yes\n
    } else {
      tputs $channel no\n
    }
  }

  proc checkForTiming { channel threshold {tries 2} } {
    tputs $channel "---- checking for precision timing... "

    #
    # HACK: Sometimes the first try takes quite a bit longer than subsequent
    #       tries.  We attempt to bypass this problem by retrying a set number
    #       of times (which can be overridden by the caller) before giving up.
    #
    for {set try 0} {$try < $tries} {incr try} {
      #
      # NOTE: Attempt to block for exactly one second.
      #
      set start [expr {[clock clicks -milliseconds] & 0x7fffffff}]
      after 1000; # wait for "exactly" one second.
      set stop [expr {[clock clicks -milliseconds] & 0x7fffffff}]

      #
      # NOTE: Calculate the difference between the actual and expected
      #       number of milliseconds.
      #
      set difference [expr {abs($stop - $start - 1000)}]

      #
      # NOTE: Are we within the threshold specified by the caller?
      #
      if {$difference >= 0 && $difference <= $threshold} then {
        #
        # NOTE: We appear to be capable of fairly precise timing.
        #
        addConstraint timing

        tputs $channel [appendArgs "yes (0 <= " $difference " <= " \
            $threshold " milliseconds, tried " [expr {$try + 1}] \
            " " [expr {$try > 0 ? "times" : "time"}] ")\n"]

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

    tputs $channel [appendArgs "no (0 <= " $difference " > " \
        $threshold " milliseconds)\n"]
  }

  proc checkForPerformance { channel } {
    tputs $channel "---- checking for performance testing... "

    #
    # NOTE: Are we allowed to do performance testing?
    #
    if {![info exists ::no(performance)]} then {
      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?
    #
    if {[info exists ::tcl_interactive] && $::tcl_interactive} then {
      addConstraint interactive

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

    #
    # HACK: For now, do the exact same check as checkForInteractive; however,
    #       this is still useful as a separate constraint because it can be
    #       individually disabled in "prologue.eagle".
    #
    if {[info exists ::tcl_interactive] && $::tcl_interactive} then {
      addConstraint userInteraction

      tputs $channel yes\n
    } else {
      tputs $channel no\n
    }
  }

  proc checkForNetwork { channel host timeout } {
    tputs $channel [appendArgs \
        "---- checking for network connectivity to host \"" $host "\"... "]

    if {[isEagle]} then {
      #
      # BUGBUG: Tcl 8.4 does not like this expression (and Tcl tries to
      #         compile it even though it will only actually ever be
      #         evaluated in Eagle).
      #
      set expr {[llength [info commands uri]] > 0 && \
          [catch {uri ping $host $timeout} response] == 0 && \
          [lindex $response 0] in [list Success TimedOut] && \
          [string is integer -strict [lindex $response 1]] && \
          [lindex $response 1] <= $timeout}

      #
      # NOTE: Does it look like we are able to contact the network host?
      #
      if {[expr $expr]} then {
        #
        # NOTE: Yes, it appears that it is available.
        #
        addConstraint [appendArgs network_ $host]

        tputs $channel [appendArgs "yes (" $response ")\n"]
      } else {
        tputs $channel no\n
      }
    } else {
      #
      # HACK: Running in Tcl, just assume we have network access.
      #
      addConstraint [appendArgs network_ $host]

      tputs $channel yes\n
    }
  }

  proc checkForCompileOption { channel option } {
    tputs $channel [appendArgs "---- checking for compile option \"" \
        $option "\"... "]

    if {[isEagle]} then {
      if {[info exists ::eagle_platform(compileOptions)] && \
          [lsearch -exact -nocase $::eagle_platform(compileOptions) \
              $option] != -1} then {
        #
        # NOTE: Yes, support for the Eagle compile option is present.
        #
        addConstraint [appendArgs compile. $option]

        tputs $channel yes\n
      } else {
        tputs $channel no\n
      }
    } else {
      #
      # NOTE: We are running inside Tcl; however, we need to check for an
      #       Eagle compile option.  This can now be accomplished via the
      #       [eagle] command supplied by the Eagle Package for Tcl, if
      #       it is actually loaded and available.
      #
      if {[llength [info commands eagle]] > 0} then {
        set options [eagle [list expr {[info exists \
            ::eagle_platform(compileOptions)] ? \
            $::eagle_platform(compileOptions) : [list]}]]

        if {[lsearch -exact $options $option] != -1} then {
          #
          # NOTE: Yes, support for the Eagle compile option is present.
          #
          addConstraint [appendArgs compile. $option]

          tputs $channel yes\n

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

      tputs $channel no\n
    }
  }

  if {[isEagle]} then {
    ###########################################################################
    ############################ BEGIN Eagle ONLY #############################
    ###########################################################################

    proc checkForSoftwareUpdateTrust { channel } {
      tputs $channel "---- checking for software update trust... "

      if {[llength [info commands uri]] > 0 && \
          [catch {uri softwareupdates} result] == 0 && \
          $result eq "software update certificate is trusted"} then {
        #
        # NOTE: Yes, it appears that we trust our software updates.
        #       Since this setting is off by default, the user (or
        #       a script evaluated by the user) must have manually
        #       turned it on.
        #
        addConstraint softwareUpdate

        tputs $channel trusted\n
      } else {
        tputs $channel untrusted\n
      }
    }

    proc checkForAdministrator { channel } {
      tputs $channel "---- checking for administrator... "

      if {[isAdministrator]} then {
        addConstraint administrator; # running as full admin.

        tputs $channel yes\n
      } else {
        tputs $channel no\n
      }
    }

    proc checkForHost { channel } {
      tputs $channel "---- checking for host... "

      if {[set code [catch {host isopen} result]] == 0 && $result} then {
        addConstraint hostIsOpen

        tputs $channel open\n
      } elseif {$code == 0} then {
        tputs $channel closed\n
      } else {
        tlog $result; tputs $channel error\n]
      }
    }

    proc checkForPrimaryThread { channel } {
      tputs $channel "---- checking for primary thread... "

      set threadId [object invoke Interpreter.GetActive ThreadId]

      if {[info tid] == $threadId} then {
        addConstraint primaryThread

        tputs $channel [appendArgs "yes (" $threadId ")\n"]
      } else {
        tputs $channel [appendArgs "no (" $threadId ")\n"]
      }
    }

    proc checkForRuntime { channel } {
      tputs $channel "---- checking for runtime... "

      #
      # NOTE: Are we running inside Mono (regardless of operating system)?
      #
      if {[isMono]} then {
        #
        # NOTE: Yes, it appears that we are running inside Mono.
        #
        addConstraint mono; # running on Mono.

        tputs $channel [appendArgs [expr {[info exists \
            ::eagle_platform(runtime)] ? \
            $::eagle_platform(runtime) : "Mono"}] \n]
      } else {
        #
        # NOTE: No, it appears that we are not running inside Mono.
        #
        addConstraint dotNet; # running on .NET.

        #
        # NOTE: We do not want to skip Mono bugs on .NET.
        #
        addConstraint monoToDo; # running on .NET.
        addConstraint monoBug; # running on .NET.
        addConstraint monoCrash; # running on .NET.

        tputs $channel [appendArgs [expr {[info exists \
            ::eagle_platform(runtime)] ? \
            $::eagle_platform(runtime) : "Microsoft.NET"}] \n]
      }
    }

    proc checkForImageRuntimeVersion { channel } {
      tputs $channel "---- checking for image runtime version... "

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

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

        #
        # NOTE: Keep track of the specific image runtime version for usage in
        #       test constraints.
        #
        addConstraint [appendArgs imageRuntime $version]

        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 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 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
      }
    }

    proc checkForMachine { channel bits machine } {
      tputs $channel [appendArgs "---- checking for machine \"" $bits \
          "-bit " $machine "\"... "]

      #
      # NOTE: What are the machine architecture and the
      #       number of bits for this operating system?
      #
      if {[info exists ::tcl_platform(machine)] && \
          [info exists ::tcl_platform(osBits)]} then {
        #
        # NOTE: Does the machine and number of bits match
        #       what the caller specified?
        #
        if {$::tcl_platform(machine) eq $machine && \
            $::tcl_platform(osBits) eq $bits} then {
          #
          # NOTE: Yes, it matches.
          #
          addConstraint [appendArgs $machine . $bits bit]

          set result yes
        } else {
          set result no
        }

        tputs $channel [appendArgs $result ", " $::tcl_platform(osBits) -bit \
            " " $::tcl_platform(machine) \n]
      } else {
        tputs $channel "no, unknown\n"
      }
    }

    proc checkForGarudaDll { channel } {
      #
      # NOTE: Check for the Garuda DLL of the same platform (i.e. machine
      #       type) as the native Tcl shell.
      #
      return [checkForFile $channel [getGarudaDll]]
    }

    proc checkForCulture { channel } {
      tputs $channel "---- checking for culture... "

      #
      # NOTE: Grab the current culture.
      #
      set culture [info culture]

      if {[string length $culture] > 0} then {
        #
        # NOTE: The culture information is present, use it and show it.
        #
        addConstraint [appendArgs culture. [string map [list - _] $culture]]

        tputs $channel [appendArgs $culture \n]
      } else {
        tputs $channel [appendArgs unknown \n]
      }
    }

    proc checkForQuiet { channel } {
      tputs $channel "---- checking for quiet... "

      if {[object invoke Interpreter.GetActive Quiet]} then {
        #
        # NOTE: Yes, quiet mode is enabled.
        #
        addConstraint quiet

        tputs $channel yes\n
      } else {
        tputs $channel no\n
      }
    }

    proc checkForReferenceCountTracking { channel } {
      tputs $channel "---- checking for object reference count tracking... "

      if {[info exists ::eagle_platform(compileOptions)] && \
          ([lsearch -exact -nocase $::eagle_platform(compileOptions) \
              NOTIFY] != -1 || \
           [lsearch -exact -nocase $::eagle_platform(compileOptions) \
              NOTIFY_OBJECT] != -1)} then {
        #
        # NOTE: Yes, support for object reference count tracking is present.
        #
        addConstraint refCount

        tputs $channel yes\n
      } else {
        tputs $channel no\n
      }
    }

    proc checkForRuntimeOption { channel option } {
      tputs $channel [appendArgs "---- checking for runtime option \"" \
          $option "\"... "]

      if {[info exists ::eagle_platform(runtimeOptions)] && \
          [lsearch -exact -nocase $::eagle_platform(runtimeOptions) \
              $option] != -1} then {
        #
        # NOTE: Yes, support for the runtime option is present.
        #
        addConstraint [appendArgs runtime. $option]

        tputs $channel yes\n
      } else {
        tputs $channel no\n
      }
    }

    proc checkForDynamicLoading { channel } {
      tputs $channel "---- checking for dynamic loading... "

      #
      # NOTE: As far as we know, dynamic loading always works on Windows.
      #       On some Unix systems, dlopen does not work (e.g. because
      #       Mono is statically linked, etc).
      #
      if {$::tcl_platform(platform) eq "windows" || \
          ([llength [info commands library]] > 0 && \
           [catch {library test}] == 0)} then {
        #
        # NOTE: Yes, it appears that it is available.
        #
        addConstraint dynamic

        tputs $channel yes\n
      } else {
        tputs $channel no\n
      }
    }

    proc checkForWindowsForms { channel } {
      tputs $channel "---- checking for Windows Forms... "

      #
      # HACK: When running on Windows, we do not need to do any other
      #       special checks here; however, on Unix (and Mac OS X?),
      #       we should check for the DISPLAY environment variable as
      #       some basic indication that the X server is available.
      #       This appears to be very necessary on Mono because it
      #       crashes after repeated failed attempts to create a
      #       Windows Form when the X server is unavailable (e.g. on
      #       OpenBSD).
      #
      if {$::tcl_platform(platform) eq "windows" || \
          [info exists ::env(DISPLAY)]} then {
        #
        # NOTE: Is the Windows Forms assembly available?
        #
        if {[catch {object resolve System.Windows.Forms} assembly] == 0} then {
          #
          # NOTE: Yes, it appears that it is available.
          #
          addConstraint winForms

          tputs $channel yes\n

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

      tputs $channel no\n
    }

    proc checkForStaThread { channel } {
      tputs $channel "---- checking for STA thread... "

      if {[catch {object invoke System.Threading.Thread.CurrentThread \
              GetApartmentState} apartmentState] == 0 && \
          $apartmentState eq "STA"} then {
        #
        # NOTE: Yes, we are running in an STA thread.
        #
        addConstraint staThread

        tputs $channel yes\n
      } else {
        tputs $channel no\n
      }
    }

    proc checkForWindowsPresentationFoundation { channel } {
      tputs $channel "---- checking for Windows Presentation Foundation... "

      #
      # NOTE: Is the Windows Presentation Foundation available?
      #
      if {[catch {object resolve PresentationFramework} assembly] == 0} then {
        #
        # NOTE: Yes, it appears that it is available.
        #
        addConstraint wpf

        tputs $channel yes\n
      } else {
        tputs $channel no\n
      }
    }

    proc checkForDatabase { channel string } {
      tputs $channel "---- checking for database... "

      #
      # HACK: Disable database connectivity testing on Mono because
      #       it fails to timeout (unless special test suite hacks
      #       for Mono have been disabled by the user).
      #
      if {[info exists ::no(mono)] || ![isMono]} then {
        #
        # NOTE: Can we access the local database?
        #
        if {[catch {sql open $string} connection] == 0} then {
          #
          # NOTE: Yes, it appears that we can connect to the local database.
          #
          addConstraint sql

          #
          # NOTE: Cleanup the database connection we just opened.
          #
          sql close $connection

          tputs $channel yes\n
        } else {
          tputs $channel no\n
        }
      } else {
        tputs $channel disabled\n
      }
    }

    proc checkForAssembly { channel name } {
      tputs $channel [appendArgs "---- checking for assembly \"" $name \
          "\"... "]

      #
      # NOTE: Can the assembly be loaded?
      #
      if {[catch {object resolve $name} assembly] == 0} then {
        #
        # NOTE: Yes, it appears that it is available.
        #
        addConstraint $name

        tputs $channel yes\n
      } else {
        tputs $channel no\n
      }
    }

    proc checkForObjectMember { channel object member {constraint ""} } {
      tputs $channel [appendArgs "---- checking for object member \"" \
          $object . $member "\"... "]

      if {[catch {object members -flags +NonPublic -pattern $member $object} \
          members] == 0 && [llength $members] > 0} then {
        #
        # NOTE: Yes, it appears that it is available.
        #
        if {[string length $constraint] > 0} then {
          addConstraint [appendArgs member_ $constraint]
        } else {
          addConstraint [appendArgs $object. [string trim $member *?]]
        }

        tputs $channel yes\n
      } else {
        tputs $channel no\n
      }
    }

    proc checkForTclInstalls { channel } {
      tputs $channel "---- checking for Tcl installs... "

      #
      # NOTE: Check for dynamically loadable Tcl libraries (for this
      #       architecture only).
      #
      if {[catch {tcl select -architecture} tcl] == 0} then {
        #
        # NOTE: Did we find one?  Attempt to grab the index
        #       of the version field from the list.
        #
        set index [lsearch -exact $tcl version]

        if {$index != -1} then {
          #
          # NOTE: The very next list index contains the value
          #       (i.e. like a Tcl 8.5+ dict).
          #
          set dotVersion [lindex $tcl [incr index]]

          #
          # NOTE: Do we know the version?
          #
          if {[string length $dotVersion] > 0 && \
              [regexp -- {^\d+\.\d+$} $dotVersion]} then {
            #
            # NOTE: Yes, some version of Tcl is available.
            #
            addConstraint tclLibrary

            #
            # NOTE: Is the version 8.x or higher?
            #
            if {$dotVersion >= 8.6} then {
              addConstraint tclLibrary86
            } elseif {$dotVersion >= 8.5} then {
              addConstraint tclLibrary85
            } elseif {$dotVersion >= 8.4} then {
              addConstraint tclLibrary84
            }

            tputs $channel [appendArgs $dotVersion \n]

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

      tputs $channel no\n
    }

    proc checkForTclReady { channel } {
      tputs $channel "---- checking for Tcl readiness... "

      if {[catch {tcl ready} result] == 0 && $result} then {
        #
        # NOTE: Yes, native Tcl is loaded and ready.
        #
        addConstraint tclReady

        tputs $channel yes\n
      } else {
        tputs $channel no\n
      }
    }

    proc checkForTclShell { channel } {
      #
      # HACK: We do not care about the machine type returned from this
      #       procedure, we only care if it returns "error" because that
      #       would indicate an error was caught during [exec] (i.e. the
      #       native Tcl shell could not be executed).
      #
      if {[catch {getMachineForTclShell} result] == 0 && \
          $result ne "error"} then {
        #
        # NOTE: Yes, a native Tcl shell appears to be available.
        #
        addConstraint tclShell

        tputs $channel [appendArgs "---- checking for Tcl shell... yes (" \
            $result ")\n"]
      } else {
        tputs $channel "---- checking for Tcl shell... no\n"
      }
    }

    proc checkForPowerShell { channel } {
      tputs $channel "---- checking for PowerShell... "

      #
      # NOTE: Can the PowerShell assembly be loaded?
      #
      if {[catch {object resolve System.Management.Automation} \
              assembly] == 0} then {
        #
        # NOTE: Yes, it appears that it is available.
        #
        addConstraint powerShell

        tputs $channel yes\n
      } else {
        tputs $channel no\n
      }
    }

    proc checkForWix { channel } {
      tputs $channel "---- checking for WiX... "

      #
      # NOTE: Platform must be Windows for this constraint to
      #       even be checked (i.e. we require the registry).
      #
      if {$::tcl_platform(platform) eq "windows"} then {
        #
        # NOTE: Indicate that we have not found it yet.
        #
        set directory ""

        #
        # NOTE: Have we not found the directory yet?
        #
        #       Yes, this is somewhat redundant because we just set
        #       the directory to an empty string (above); however,
        #       maintaining a uniform pattern is more important.
        #
        if {[string length $directory] == 0} then {
          #
          # NOTE: Check for the WIX environment variable.
          #
          if {[info exists ::env(WIX)]} then {
            set directory [file normalize [string trimright $::env(WIX)]]

            if {[string length $directory] > 0} then {
              #
              # NOTE: We need the directory containing the binaries.
              #
              set directory [file join $directory bin]

              #
              # NOTE: Does the directory actually exist?
              #
              if {[file isdirectory $directory]} then {
                #
                # NOTE: The file name of the primary WiX assembly.
                #
                set fileName [file join $directory wix.dll]

                #
                # NOTE: We do not know the file version yet.
                #
                set version ""

                #
                # NOTE: Attempt to query the version of the file.
                #
                if {[catch {file version $fileName} version] == 0 && \
                    [string length $version] > 0} then {
                  #
                  # NOTE: Indicate where we found the file.
                  #
                  set where environment
                } else {
                  #
                  # NOTE: The file does not exist or is not properly
                  #       versioned.
                  #
                  set directory ""
                }
              } else {
                #
                # NOTE: The directory does not exist.
                #
                set directory ""
              }
            }
          }
        }

        #
        # NOTE: Have we not found the directory yet?
        #
        if {[string length $directory] == 0} then {
          #
          # NOTE: Registry hive where WiX install information
          #       is stored.
          #
          set key {HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Installer XML}

          #
          # NOTE: The versions of WiX that we support.
          #
          set versions [list 3.5 3.0]

          #
          # NOTE: Check each version, stopping when one is found.
          #
          foreach version $versions {
            #
            # NOTE: Attempt to fetch the WiX install directory
            #       value from the registry, removing the
            #       trailing backslash, if any.
            #
            set directory [file normalize [string trimright [object invoke \
                Microsoft.Win32.Registry GetValue \
                [appendArgs $key \\ $version] InstallRoot \
                null] \\]]

            #
            # NOTE: Does the directory name look valid and
            #       does it actually exist?
            #
            if {[string length $directory] > 0} then {
              #
              # NOTE: Does the directory actually exist?
              #
              if {[file isdirectory $directory]} then {
                #
                # NOTE: The file name of the primary WiX assembly.
                #
                set fileName [file join $directory wix.dll]

                #
                # NOTE: We do not know the file version yet.
                #
                set version ""

                #
                # NOTE: Attempt to query the version of the file.
                #
                if {[catch {file version $fileName} version] == 0 && \
                    [string length $version] > 0} then {
                  #
                  # NOTE: Indicate where we found the file.
                  #
                  set where registry

                  #
                  # NOTE: We found it, bail out now.
                  #
                  break
                } else {
                  #
                  # NOTE: The file does not exist or is not properly
                  #       versioned.
                  #
                  set directory ""
                }
              } else {
                #
                # NOTE: The directory does not exist.
                #
                set directory ""
              }
            }
          }
        }

        #
        # NOTE: Did we find the directory?
        #
        if {[string length $directory] > 0 && \
            [file isdirectory $directory]} then {
          #
          # NOTE: Yes, it appears that it is available.
          #
          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 checkForManagedDebugger { channel } {
      tputs $channel "---- checking for managed debugger... "

      #
      # NOTE: Is the managed debugger attached?
      #
      if {[object invoke System.Diagnostics.Debugger IsAttached]} then {
        #
        # NOTE: Yes, it appears that it is attached.
        #
        addConstraint managedDebugger

        tputs $channel yes\n
      } else {
        tputs $channel no\n
      }
    }

    proc checkForScriptDebugger { channel } {
      tputs $channel "---- checking for script debugger... "

      #
      # NOTE: Is the script debugger available?
      #
      if {[catch {object invoke -flags +NonPublic Interpreter.GetActive \
              Debugger} debugger] == 0} then {
        #
        # NOTE: We do not own this, do not dispose it.
        #
        if {[string length $debugger] > 0} then {
          object flags $debugger +NoDispose
        }

        if {[regexp -- {^Debugger#\d+$} $debugger]} then {
          #
          # NOTE: Yes, it appears that it is available.
          #
          addConstraint scriptDebugger

          tputs $channel yes\n

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

      tputs $channel no\n
    }

    proc checkForScriptDebuggerInterpreter { channel } {
      tputs $channel "---- checking for script debugger interpreter... "

      #
      # NOTE: Is the script debugger interpreter available?
      #
      if {[catch {object invoke -flags +NonPublic Interpreter.GetActive \
              Debugger} debugger] == 0} then {
        #
        # NOTE: We do not own this, do not dispose it.
        #
        if {[string length $debugger] > 0} then {
          object flags $debugger +NoDispose
        }

        if {[regexp -- {^Debugger#\d+$} $debugger] && \
            [catch {object invoke $debugger Interpreter} interp] == 0} then {
          #
          # NOTE: We do not own this, do not dispose it.
          #
          if {[string length $interp] > 0} then {
            object flags $interp +NoDispose
          }

          if {[regexp -- {^Interpreter#\d+$} $interp]} then {
            #
            # NOTE: Yes, it appears that it is available.
            #
            addConstraint scriptDebuggerInterpreter

            tputs $channel yes\n

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

      tputs $channel no\n
    }

    ###########################################################################
    ############################# END Eagle ONLY ##############################
    ###########################################################################
  } else {
    ###########################################################################
    ############################# 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 \
        checkForPerformance checkForTiming checkForInteractive checkForSymbols \
        checkForLogFile checkForNetwork checkForCompileOption \
        checkForUserInteraction] false false

    ###########################################################################
    ############################## END Tcl ONLY ###############################
    ###########################################################################
  }

  #
  # NOTE: Provide the Eagle test constraints package to the interpreter.
  #
  package provide EagleTestConstraints \
    [expr {[isEagle] ? [info engine PatchLevel] : 1.0}]
}

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































Deleted Externals/Eagle/lib/Test1.0/epilogue.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
###############################################################################
#
# epilogue.eagle --
#
# Extensible Adaptable Generalized Logic Engine (Eagle)
# Test Epilogue File
#
# Copyright (c) 2007-2010 by Joe Mistachkin.  All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: $
#
###############################################################################

if {![info exists no([file tail [info script]])]} then {
  if {[info level] > 0} then {
    error "cannot run, current level is not global"
  }

  if {[isEagle]} then {
    #
    # NOTE: Show the current state of the memory.
    #
    catch {debug memory} memory

    tputs $test_channel [appendArgs "---- ending memory: " \
        [formatListAsDict $memory] \n]

    unset memory

    #
    # NOTE: Show the current state of the native stack.
    #
    catch {debug stack true} stack

    tputs $test_channel [appendArgs "---- ending stack: " \
        [formatListAsDict $stack] \n]

    unset stack
  }

  #
  # NOTE: Show when the tests actually ended (now).
  #
  tputs $test_channel [appendArgs "---- tests ended at " \
      [clock format [clock seconds]] \n]

  if {[isEagle]} then {
    #
    # NOTE: Check for and display any duplicate test names that we found.  In
    #       theory, this checking may produce false positives if a test file
    #       (or the entire test suite) is run multiple times without resetting
    #       the test statistics and/or restarting Eagle; however, duplicate
    #       test names must be avoided and this is considered a good trade-off.
    #
    foreach {name count} $eagle_tests(counts) {
      if {$count > 1} then {
        tputs $test_channel [appendArgs \
            "==== test name \"" $name "\" DUPLICATED (" $count ")\n"]
      } elseif {$count <= 0} then {
        tputs $test_channel [appendArgs \
            "==== test name \"" $name "\" BAD COUNT (" $count ")\n"]
      }
    }

    unset -nocomplain name count

    tputs $test_channel \n; # NOTE: Blank line.

    if {$eagle_tests(passed) > 0} then {
      host result Ok [appendArgs "PASSED: " $eagle_tests(passed) \n]
      tlog [appendArgs "PASSED: " $eagle_tests(passed) \n]
    }

    if {$eagle_tests(failed) > 0} then {
      host result Error [appendArgs "FAILED: " $eagle_tests(failed) \n]
      tlog [appendArgs "FAILED: " $eagle_tests(failed) \n]

      if {[llength $eagle_tests(failedNames)] > 0} then {
        host result Error [appendArgs "FAILED: " $eagle_tests(failedNames) \n]
        tlog [appendArgs "FAILED: " $eagle_tests(failedNames) \n]
      }
    }

    if {$eagle_tests(skipped) > 0} then {
      host result Break [appendArgs "SKIPPED: " $eagle_tests(skipped) \n]
      tlog [appendArgs "SKIPPED: " $eagle_tests(skipped) \n]

      if {[llength $eagle_tests(skippedNames)] > 0} then {
        host result Break [appendArgs "SKIPPED: " $eagle_tests(skippedNames) \n]
        tlog [appendArgs "SKIPPED: " $eagle_tests(skippedNames) \n]
      }
    }

    if {$eagle_tests(total) > 0} then {
      host result Return [appendArgs "TOTAL: " $eagle_tests(total) \n]
      tlog [appendArgs "TOTAL: " $eagle_tests(total) \n]

      if {$eagle_tests(skipped) > 0} then {
        set percent [getSkipPercentage]
        host result Break [appendArgs "SKIP PERCENTAGE: " \
            [formatDecimal $percent] %\n]

        tlog [appendArgs "SKIP PERCENTAGE: " [formatDecimal $percent] %\n]
      }

      set percent [getPassPercentage]
      host result Return [appendArgs "PASS PERCENTAGE: " \
          [formatDecimal $percent] %\n]

      tlog [appendArgs "PASS PERCENTAGE: " [formatDecimal $percent] %\n]
    } else {
      #
      # NOTE: No tests.
      #
      set percent 0
    }

    #
    # NOTE: Has the test pass threshold been set?  If so, is it set to
    #       the default value?
    #
    if {![info exists test_threshold] || $test_threshold == 100} then {
      #
      # NOTE: The test pass threshold is set to the default value (100%).
      #       Check to make sure that all tests pass and then set the
      #       exit code to success; otherwise, we set it to failure.
      #
      set passedOrSkipped [expr {$eagle_tests(passed) + \
          $eagle_tests(skipped)}]

      if {$passedOrSkipped == $eagle_tests(total)} then {
        set exitCode Success

        host result Ok "OVERALL RESULT: SUCCESS\n"
        tlog "OVERALL RESULT: SUCCESS\n"
      } else {
        set exitCode Failure

        host result Error "OVERALL RESULT: FAILURE\n"
        tlog "OVERALL RESULT: FAILURE\n"
      }

      unset passedOrSkipped
    } else {
      #
      # NOTE: They specified a non-default test pass threshold.  Check to
      #       make sure that we meet or exceed the requirement and then
      #       set the exit code to success; otherwise, set it to failure.
      #
      if {$percent >= $test_threshold} then {
        set exitCode Success

        host result Ok [appendArgs "OVERALL RESULT: SUCCESS (" \
            $percent "% >= " $test_threshold %)\n]

        tlog [appendArgs "OVERALL RESULT: SUCCESS (" \
            $percent "% >= " $test_threshold %)\n]
      } else {
        set exitCode Failure

        host result Error [appendArgs \
            "OVERALL RESULT: FAILURE (" $percent "% < " $test_threshold %)\n]

        tlog [appendArgs \
            "OVERALL RESULT: FAILURE (" $percent "% < " $test_threshold %)\n]
      }
    }

    unset percent

    tputs $test_channel \n; # NOTE: Blank line.
  } else {
    tputs $test_channel \n; # NOTE: Blank line.

    if {$::tcltest::numTests(Passed) > 0} then {
      tputs $test_channel \
          [appendArgs "PASSED: " $::tcltest::numTests(Passed) \n]
    }

    if {$::tcltest::numTests(Failed) > 0} then {
      tputs $test_channel \
          [appendArgs "FAILED: " $::tcltest::numTests(Failed) \n]

      if {[llength $::tcltest::failFiles] > 0} then {
        tputs $test_channel \
            [appendArgs "FAILED: " $::tcltest::failFiles \n]
      }
    }

    if {$::tcltest::numTests(Skipped) > 0} then {
      tputs $test_channel \
          [appendArgs "SKIPPED: " $::tcltest::numTests(Skipped) \n]
    }

    if {$::tcltest::numTests(Total) > 0} then {
      tputs $test_channel \
          [appendArgs "TOTAL: " $::tcltest::numTests(Total) \n]

      if {$::tcltest::numTests(Skipped) > 0} then {
        set percent [getSkipPercentage]
        tputs $test_channel [appendArgs "SKIP PERCENTAGE: " \
            [formatDecimal $percent] %\n]
      }

      set percent [getPassPercentage]
      tputs $test_channel [appendArgs "PASS PERCENTAGE: " \
          [formatDecimal $percent] %\n]
    } else {
      #
      # NOTE: No tests.
      #
      set percent 0
    }

    #
    # NOTE: Has the test pass threshold been set?  If so, is it set to
    #       the default value?
    #
    if {![info exists test_threshold] || $test_threshold == 100} then {
      #
      # NOTE: The test pass threshold is set to the default value (100%).
      #       Check to make sure that all tests pass and then set the
      #       exit code to success; otherwise, we set it to failure.
      #
      set passedOrSkipped [expr {$::tcltest::numTests(Passed) + \
          $::tcltest::numTests(Skipped)}]

      if {$passedOrSkipped == $::tcltest::numTests(Total)} then {
        set exitCode 0; # Success.

        tputs $test_channel "OVERALL RESULT: SUCCESS\n"
      } else {
        set exitCode 1; # Failure.

        tputs $test_channel "OVERALL RESULT: FAILURE\n"
      }

      unset passedOrSkipped
    } else {
      #
      # NOTE: They specified a non-default test pass threshold.  Check to
      #       make sure that we meet or exceed the requirement and then
      #       set the exit code to success; otherwise, set it to failure.
      #
      if {$percent >= $test_threshold} then {
        set exitCode 0; # Success.

        tputs $test_channel [appendArgs "OVERALL RESULT: SUCCESS (" \
            $percent "% >= " $test_threshold %)\n]
      } else {
        set exitCode 1; # Failure.

        tputs $test_channel [appendArgs "OVERALL RESULT: FAILURE (" \
            $percent "% < " $test_threshold %)\n]
      }
    }

    unset percent

    tputs $test_channel \n; # NOTE: Blank line.

    #
    # NOTE: Call the Tcl test cleanup procedure now to give it a chance to do
    #       any custom cleanup that has been registered.
    #
    ::tcltest::cleanupTests
  }

  #
  # NOTE: Check for and process any custom test epilogue script that may
  #       be set in the environment.
  #
  sourceIfValid epilogue [getEnvironmentVariable testEpilogue]

  #
  # NOTE: Are we being prevented from evaluating the "post-test" script?
  #
  if {![info exists no(postTest)]} then {
    #
    # NOTE: Evaluate the specified post-test script now, if any.
    #
    if {[info exists test_flags(-postTest)] && \
        [string length $test_flags(-postTest)] > 0} then {
      #
      # TODO: Perhaps use [uplevel] here instead of [eval].  For now, it does
      #       not matter since we enforce this file being evaluated at the
      #       top-level.
      #
      eval $test_flags(-postTest)
    }
  }

  #
  # NOTE: Do we need to exit now?
  #
  if {[isExitOnComplete]} then {
    #
    # NOTE: Exit now.  In Eagle, this will not exit the entire process.
    #       Zero (0) will be the exit code if all the selected tests have
    #       succeeded or the test success threshold has been met or
    #       exceeded; otherwise, one (1) will be the exit code.
    #
    exit $exitCode
  } else {
    #
    # NOTE: For Eagle, even when not exiting, we still set the ExitCode
    #       property of the interpreter.
    #
    if {[isEagle]} then {
      object invoke -alias Interpreter.GetActive ExitCode $exitCode
    }

    unset exitCode
  }
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




























































































































































































































































































































































































































































































































































































































































Deleted Externals/Eagle/lib/Test1.0/pkgIndex.eagle.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
###############################################################################
#
# pkgIndex.eagle --
#
# Extensible Adaptable Generalized Logic Engine (Eagle)
# Package Index File
#
# Copyright (c) 2007-2010 by Joe Mistachkin.  All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: $
#
###############################################################################

if {![package vsatisfies [package provide Tcl] 8.4]} {return}
if {![package vsatisfies [package provide Eagle] 1.0]} {return}

package ifneeded EagleTestConstraints 1.0 [list source [file join $dir \
    constraints.eagle]]
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










































Deleted Externals/Eagle/lib/Test1.0/pkgIndex.tcl.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
###############################################################################
#
# pkgIndex.tcl --
#
# Extensible Adaptable Generalized Logic Engine (Eagle)
# Package Index File
#
# Copyright (c) 2007-2010 by Joe Mistachkin.  All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: $
#
###############################################################################

if {![package vsatisfies [package provide Tcl] 8.4]} {return}
if {[string length [package provide Eagle]] > 0} then {return}

package ifneeded EagleTestConstraints 1.0 [list source [file join $dir \
    constraints.eagle]]
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










































Deleted Externals/Eagle/lib/Test1.0/prologue.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
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
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
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
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
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
###############################################################################
#
# prologue.eagle --
#
# Extensible Adaptable Generalized Logic Engine (Eagle)
# Test Prologue File
#
# Copyright (c) 2007-2010 by Joe Mistachkin.  All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: $
#
###############################################################################

if {![info exists no([file tail [info script]])]} then {
  if {[info level] > 0} then {
    error "cannot run, current level is not global"
  }

  #
  # NOTE: Set the location of the test suite, if necessary.
  #
  if {![info exists test_path]} then {
    set test_path [file normalize [file dirname [info script]]]
  }

  #
  # NOTE: Set the location of the base Eagle directory, if
  #       necessary.
  #
  if {![info exists base_path]} then {
    #
    # NOTE: Start out going up one level and check for a "lib"
    #       sub-directory.  If not found, go up another level
    #       because we will always be two levels down from the
    #       base directory when running inside the source tree.
    #
    set base_path [file normalize [file dirname $test_path]]

    #
    # HACK: We must verify that the "init.eagle" file can eventually
    #       be found under the "lib" directory since Visual Studio
    #       insists on creating a superfluous (and empty) "lib\Eagle1.0"
    #       sub-directory inside of the "Library" project directory
    #       simply due to the links contained in the project file that
    #       actually point to the "lib\Eagle1.0" sub-directory under the
    #       solution directory.
    #
    # WARNING: The Eagle package name and version are hard-coded here.
    #
    set pkg_dir Eagle1.0; # TODO: Change me.

    if {![file exists [file join $base_path lib]] || \
        ![file isdirectory [file join $base_path lib]] || \
        ![file exists [file join $base_path lib $pkg_dir]] || \
        ![file isdirectory [file join $base_path lib $pkg_dir]] || \
        ![file exists [file join $base_path lib $pkg_dir init.eagle]] || \
        ![file isfile [file join $base_path lib $pkg_dir init.eagle]]} then {
      #
      # NOTE: We do not bother to check if the "lib" sub-directory actually
      #       exists as a child of this one.  This is the previous (legacy)
      #       behavior (i.e. where we always went up two levels to the base
      #       directory).
      #
      set base_path [file dirname $base_path]
    }

    unset pkg_dir
  }

  #
  # NOTE: Set the local root directory of the source checkout (i.e. of
  #       Eagle or whatever project the Eagle binaries are being used by).
  #
  if {![info exists root_path]} then {
    set pattern {^local-root:\s+(.*)\s+$}

    if {[catch {set exec [exec -- fossil info]}] || \
        [regexp -line -- $pattern $exec dummy directory] == 0} then {
      #
      # NOTE: We could not query local root directory of the source checkout
      #       from Fossil; therefore, attempt to make an educated guess.  This
      #       value will probably be wrong for any project(s) other than Eagle.
      #       In that case, this value should be overridden by that project to
      #       relfect the actual local root directory of the source checkout
      #       for that project.
      #
      set root_path $base_path
    } else {
      #
      # NOTE: We extracted the local root directory of the source checkout
      #       from Fossil.  Now, make sure it is fully normalized and has no
      #       trailing slashes.
      #
      set root_path [file normalize $directory]
    }

    unset -nocomplain directory dummy exec pattern
  }

  #
  # NOTE: Set the executable file name for the process, if
  #       necessary.
  #
  if {![info exists bin_file]} then {
    set bin_file [info nameofexecutable]
  }

  #
  # NOTE: Set the location of the directory containing the
  #       executable file for the process, if necessary.
  #
  if {![info exists bin_path]} then {
    set bin_path [file normalize [file dirname $bin_file]]
  }

  #
  # NOTE: Set the location of the [non-script] library directory
  #       (i.e. the directory where the plugins are located), if
  #       necessary.
  #
  if {![info exists lib_path]} then {
    #
    # NOTE: This should go one directory up from the directory
    #       containing the executable file for the process (e.g.
    #       the shell) and then into the "lib" directory just
    #       beneath that.
    #
    set lib_path [file normalize [file join [file dirname $bin_path] lib]]
  }

  #
  # NOTE: Set the web host to test against, if necessary.
  #
  if {![info exists test_host]} then {
    set test_host eagle.to
  }

  #
  # NOTE: Set the port to use for server sockets, if necessary.
  #
  if {![info exists test_port]} then {
    set test_port 12346; # IANA, 12346-12752 Unassigned
  }

  #
  # NOTE: Set the network timeout, if necessary.
  #
  if {![info exists test_timeout]} then {
    set test_timeout 2000; # in milliseconds.
  }

  #
  # NOTE: Set the channel to use for test output, if necessary.
  #
  if {![info exists test_channel]} then {
    set test_channel stdout
  }

  #
  # NOTE: Set the primary package path, if necessary.
  #
  if {![info exists test_package_path]} then {
    set test_package_path [file join $base_path lib]
  }

  #
  # NOTE: Make sure our primary package path is part of the auto path.
  #
  if {[lsearch -exact $auto_path $test_package_path] == -1} then {
    lappend auto_path $test_package_path
  }

  #
  # NOTE: Make sure our test package path is part of the auto path.
  #
  if {[lsearch -exact $auto_path $test_path] == -1} then {
    lappend auto_path $test_path
  }

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

  #
  # NOTE: Check for and load the Eagle library package, if necessary.
  #
  if {[catch {package present EagleLibrary}]} then {
    package require EagleLibrary
  }

  #
  # NOTE: Check for and load the Eagle test package, if necessary.
  #
  if {[catch {package present EagleTest}]} then {
    package require EagleTest
  }

  #
  # NOTE: Check for and load the Eagle test constraints package, if
  #       necessary.
  #
  if {[catch {package present EagleTestConstraints}]} then {
    package require EagleTestConstraints
  }

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

  #
  # 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.
  set test_flags(-logFile) ""; # default to using standard log file naming.
  set test_flags(-threshold) ""; # default to requiring all tests to pass.
  set test_flags(-stopOnFailure) ""; # default to continue on failure.
  set test_flags(-exitOnComplete) ""; # default to not exit after complete.
  set test_flags(-preTest) ""; # default to not evaluating anything.
  set test_flags(-postTest) ""; # default to not evaluating anything.

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

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

      unset name value
    }

    if {[info exists test_flags(-logFile)] && \
        [string length $test_flags(-logFile)] > 0} then {
      #
      # NOTE: Set the log file name to the one provided by the command line.
      #
      set test_log $test_flags(-logFile)
    }

    if {[info exists test_flags(-threshold)] && \
        [string is integer -strict $test_flags(-threshold)]} then {
      #
      # NOTE: Set the test pass threshold to the one provided by the command
      #       line.
      #
      set test_threshold $test_flags(-threshold)
    }

    if {[info exists test_flags(-stopOnFailure)] && \
        [string is boolean -strict $test_flags(-stopOnFailure)]} then {
      #
      # NOTE: Set the test stop-on-failure flag to the one provided by the
      #       command line.
      #
      set test_stop_on_failure $test_flags(-stopOnFailure)
    }

    if {[info exists test_flags(-exitOnComplete)] && \
        [string is boolean -strict $test_flags(-exitOnComplete)]} then {
      #
      # NOTE: Set the test exit-on-complete flag to the one provided by the
      #       command line.
      #
      set test_exit_on_complete $test_flags(-exitOnComplete)
    }
  }

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

  #
  # NOTE: Set the Tcl shell executable to use for those specialized
  #       tests that may require it, if necessary.
  #
  if {![info exists test_tclsh]} then {
    if {[isEagle] || ![string match tclsh* $bin_file]} then {
      set test_tclsh tclsh
    } else {
      set test_tclsh $bin_file
    }
  }

  #
  # NOTE: Has automatic log file naming been disabled?
  #
  if {![info exists no(logFileName)]} then {
    #
    # NOTE: Set the log to use for test output, if necessary.
    #
    if {![info exists test_log]} then {
      set test_log [file join [getTemporaryPath] [appendArgs [file tail [info \
          nameofexecutable]] [getTestLogId] .test. [pid] .log]]
    }
  }

  #
  # NOTE: Are we being prevented from evaluating the "pre-test" script?
  #
  if {![info exists no(preTest)]} then {
    #
    # NOTE: Evaluate the specified pre-test script now, if any.
    #
    if {[info exists test_flags(-preTest)] && \
        [string length $test_flags(-preTest)] > 0} then {
      #
      # TODO: Perhaps use [uplevel] here instead of [eval].  For now, it does
      #       not matter since we enforce this file being evaluated at the
      #       top-level.
      #
      eval $test_flags(-preTest)
    }
  }

  #
  # NOTE: Check for and process any custom test prologue script that may be set
  #       in the environment.  This must be done after the Eagle test package
  #       has been made available and after the log file has been setup.
  #
  sourceIfValid prologue [getEnvironmentVariable testPrologue]

  #
  # NOTE: Show the name of the executable and the command line arguments, if
  #       any.  This must be done after the log file has been setup; otherwise,
  #       this information will not be visible in the log file.
  #
  tputs $test_channel [appendArgs "---- testRunId: " \
      [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]

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

    if {[string length $publicKeyToken] == 0} then {
      #
      # NOTE: The Eagle core library is not strong name signed.  This is not an
      #       error, per se; however, it may cause some tests to fail and it
      #       should be reported to the user and noted in the test suite log
      #       file.
      #
      tputs $test_channel [appendArgs \
          "==== WARNING: running without any strong name signature...\n"]
    } else {
      #
      # BUGBUG: Tcl 8.4 does not like this expression because it contains the
      #         "ni" operator (and Tcl tries to compile it even though it will
      #         only actually ever be evaluated in Eagle).
      #
      set expr {$publicKeyToken ni "29c6297630be05eb 1e22ec67879739a2"}

      if {[expr $expr]} then {
        #
        # NOTE: The Eagle core library is strong name signed with a key that is
        #       not official.  This is also not an error, per se; however, it
        #       may cause some tests to fail and it should be reported to the
        #       user and noted in the test suite log file.
        #
        tputs $test_channel [appendArgs \
            "==== WARNING: running without official strong name signature: " \
            $publicKeyToken \n]
      }

      unset expr
    }

    unset publicKeyToken

    tputs $test_channel [appendArgs "---- original command line: " \
        [info cmdline] \n]

    tputs $test_channel [appendArgs "---- threadId: " \
        [info tid] \n]

    tputs $test_channel [appendArgs "---- processors: " \
        [info processors] \n]

    catch {object invoke Console.InputEncoding WebName} encoding

    tputs $test_channel [appendArgs "---- input encoding: " \
        $encoding \n]

    catch {object invoke Console.OutputEncoding WebName} encoding

    tputs $test_channel [appendArgs "---- output encoding: " \
        $encoding \n]

    unset encoding
    catch {debug memory} memory

    tputs $test_channel [appendArgs "---- starting memory: " \
        [formatListAsDict $memory] \n]

    unset memory
    catch {debug stack true} stack

    tputs $test_channel [appendArgs "---- starting stack: " \
        [formatListAsDict $stack] \n]

    unset stack
    catch {file drive} drive

    tputs $test_channel [appendArgs "---- system drive: " \
        [formatListAsDict $drive] \n]

    unset drive
  }

  tputs $test_channel [appendArgs "---- executable: \"" \
      $bin_file \"\n]

  tputs $test_channel [appendArgs "---- command line: " \
      [expr {[info exists argv] && [string length $argv] > 0 ? \
          $argv : "<none>"}] \n]

  tputs $test_channel [appendArgs "---- logging to: " \
      [expr {[info exists test_log] && [string length $test_log] > 0 ? \
          [appendArgs \" $test_log \"] : "<none>"}] \n]

  tputs $test_channel [appendArgs "---- pass threshold: " \
      [expr {[info exists test_threshold] && \
          [string is integer -strict $test_threshold] ? \
              [appendArgs $test_threshold %] : "<none>"}] \n]

  tputs $test_channel [appendArgs "---- stop on failure: " \
      [expr {[info exists test_stop_on_failure] && \
          [string is boolean -strict $test_stop_on_failure] ? \
              $test_stop_on_failure : "<none>"}] \n]

  tputs $test_channel [appendArgs "---- exit on complete: " \
      [expr {[info exists test_exit_on_complete] && \
          [string is boolean -strict $test_exit_on_complete] ? \
              $test_exit_on_complete : "<none>"}] \n]

  #
  # NOTE: Show the information about which tests and files are being run and/or
  #       skipped (COMPAT: Tcl).
  #
  if {[llength $test_flags(-file)] > 0} then {
    tputs $test_channel [appendArgs "---- running test files that match: " \
        $test_flags(-file) \n]
  }

  if {[llength $test_flags(-notFile)] > 0} then {
    tputs $test_channel [appendArgs "---- skipping test files that match: " \
        $test_flags(-notFile) \n]
  }

  if {[llength $test_flags(-match)] > 0} then {
    tputs $test_channel [appendArgs "---- running tests that match: " \
        $test_flags(-match) \n]
  }

  if {[llength $test_flags(-skip)] > 0} then {
    tputs $test_channel [appendArgs "---- skipping tests that match: " \
        $test_flags(-skip) \n]
  }

  tputs $test_channel [appendArgs "---- path: " \
      [expr {[info exists path] && [string length $path] > 0 ? \
          [appendArgs \" $path \"] : "<none>"}] \n]

  tputs $test_channel [appendArgs "---- base path: \"" \
      $base_path \"\n]

  tputs $test_channel [appendArgs "---- root path: \"" \
      $root_path \"\n]

  tputs $test_channel [appendArgs "---- binary path: \"" \
      $bin_path \"\n]

  tputs $test_channel [appendArgs "---- library path: \"" \
      $lib_path \"\n]

  tputs $test_channel [appendArgs "---- tests located in: \"" \
      $test_path \"\n]

  tputs $test_channel [appendArgs "---- tests running in: \"" \
      [pwd] \"\n]

  tputs $test_channel [appendArgs "---- temporary files stored in: \"" \
      [getTemporaryPath] \"\n]

  tputs $test_channel [appendArgs "---- native Tcl shell: \"" \
      $test_tclsh \"\n]

  tputs $test_channel [appendArgs "---- disabled options: " \
      [formatList [lsort [array names no]] <none>] \n]

  #
  # NOTE: Initialize the Eagle test constraints.
  #
  if {[isEagle]} then {
    initializeTests

    #
    # NOTE: If the "no(mono)" variable is set (to anything) then any
    #       special test suite hacks for Mono will be disabled. This
    #       does not control or change any hacks for Mono that may
    #       be present in the library itself.
    #
    # if {![info exists no(mono)] && [isMono]} then {
    #   set no(mono) true
    # }

    #
    # NOTE: Has administrator detection support been disabled?  We do
    #       this check [nearly] first as it may [eventually] be used
    #       to help determine if other constraints should be skipped.
    #
    if {![info exists no(administrator)]} then {
      checkForAdministrator $test_channel
    }

    #
    # NOTE: Has host detection support been disabled?
    #
    if {![info exists no(host)]} then {
      checkForHost $test_channel
    }

    #
    # NOTE: Has primary thread detection support been disabled?  We do
    #       this check [nearly] first as it may [eventually] be used
    #       to help determine if other constraints should be skipped.
    #
    if {![info exists no(primaryThread)]} then {
      checkForPrimaryThread $test_channel
    }

    #
    # NOTE: Has runtime detection support been disabled?  We do this
    #       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?
    #
    if {![info exists no(machine)]} then {
      checkForMachine $test_channel 32 intel; # (i.e. x86)
      checkForMachine $test_channel 64 amd64; # (i.e. x64)
    }

    #
    # NOTE: Has culture detection support been disabled?
    #
    if {![info exists no(culture)]} then {
      checkForCulture $test_channel
    }

    #
    # NOTE: Has software update trust detection support been disabled?
    #
    if {![info exists no(softwareUpdate)]} then {
      checkForSoftwareUpdateTrust $test_channel
    }

    #
    # NOTE: Has database testing support been disabled?
    #
    if {![info exists no(sql)]} then {
      #
      # NOTE: Set the server name, if necessary.
      #
      if {![info exists server]} then {
        set server .
      }

      #
      # NOTE: Set the database name, if necessary.
      #
      if {![info exists database]} then {
        set database master
      }

      #
      # NOTE: Set the connection timeout, if necessary.
      #
      if {![info exists timeout]} then {
        set timeout [expr {$test_timeout / 1000}]; # milliseconds to seconds.
      }

      #
      # NOTE: Set the test user name, if necessary.
      #
      if {![info exists user]} then {
        set user [getEnvironmentVariable user]
      }

      #
      # NOTE: Set the test password, if necessary.
      #
      if {![info exists password]} then {
        set password [getEnvironmentVariable password]
      }

      #
      # NOTE: Set the database connection string, if necessary.
      #
      if {![info exists test_database]} then {
        #
        # NOTE: Mono does not have support for trusted connections;
        #       therefore, we must create a slightly different
        #       connection string.
        #
        set test_database [subst \
            {Data Source=${server};Initial Catalog=${database};Connect\
            Timeout=${timeout};[expr {[isMono] ? [subst \
            {User Id=${user};Password=${password};}] : {Integrated\
            Security=SSPI;}}]}]
      }

      #
      # NOTE: Can we access the local database?
      #
      checkForDatabase $test_channel $test_database
      unset password user timeout database server
    }

    #
    # NOTE: Has symbol testing support been disabled?
    #
    if {![info exists no(assemblySymbols)]} then {
      checkForSymbols $test_channel [lindex [info assembly] end]
    }

    #
    # NOTE: Has quiet testing support been disabled?
    #
    if {![info exists no(quiet)]} then {
      #
      # NOTE: For tests "basic-1.36", "debug-1.3", "debug-1.4", "object-10.*",
      #       and "perf-2.2".
      #
      checkForQuiet $test_channel
    }

    #
    # NOTE: Has object handle reference count tracking support been disabled
    #       (at compile-time)?
    #
    if {![info exists no(refCount)]} then {
      #
      # NOTE: For tests "excel-*", "object-2.*", "object-7.1", "object-8.*",
      #       and "object-98.*".
      #
      checkForReferenceCountTracking $test_channel
    }

    #
    # NOTE: Has compile/runtime option testing support been disabled?
    #
    if {![info exists no(compileOptions)]} then {
      #
      # NOTE: Has callback queue support been enabled (at compile-time)?
      #
      if {![info exists no(compileCallbackQueue)]} then {
        #
        # NOTE: For test "commands-1.4".
        #
        checkForCompileOption $test_channel CALLBACK_QUEUE
      }

      #
      # NOTE: Has console support been enabled (at compile-time)?
      #
      if {![info exists no(compileConsole)]} then {
        #
        # NOTE: For test "host-1.2".
        #
        checkForCompileOption $test_channel CONSOLE
      }

      #
      # NOTE: Has database support been enabled (at compile-time)?
      #
      if {![info exists no(compileData)]} then {
        #
        # NOTE: For tests "sql-1.1" and "upvar-99.1".
        #
        checkForCompileOption $test_channel DATA
      }

      #
      # NOTE: Has script debugger support been enabled (at compile-time)?
      #
      if {![info exists no(compileDebugger)]} then {
        #
        # NOTE: For tests "debug-1.1", "debug-2.1", "debug-3.1" and
        #       "debug-4.1".
        #
        checkForCompileOption $test_channel DEBUGGER
      }

      #
      # NOTE: Has isolated interpreter support been enabled (at compile-time)?
      #
      if {![info exists no(compileIsolatedInterpreters)]} then {
        #
        # NOTE: For test "xaml-1.2".
        #
        checkForCompileOption $test_channel ISOLATED_INTERPRETERS
      }

      #
      # NOTE: Has isolated plugin support been enabled (at compile-time)?
      #
      if {![info exists no(compileIsolatedPlugins)]} then {
        #
        # NOTE: For test "load-1.1.1".
        #
        checkForCompileOption $test_channel ISOLATED_PLUGINS
      }

      #
      # NOTE: Has PowerShell approved-verbs support been enabled (at
      #       compile-time)?
      #
      if {![info exists no(compileApprovedVerbs)]} then {
        #
        # NOTE: For test "object-4.8".
        #
        checkForCompileOption $test_channel APPROVED_VERBS
      }

      #
      # NOTE: Has Mono support been enabled (at compile-time)?
      #
      if {![info exists no(compileMono)]} then {
        #
        # NOTE: For test "object-4.13".
        #
        checkForCompileOption $test_channel MONO
      }

      #
      # NOTE: Has Windows support been enabled (at compile-time)?
      #
      if {![info exists no(compileWindows)]} then {
        #
        # NOTE: For test "garuda-1.0".
        #
        checkForCompileOption $test_channel WINDOWS
      }

      #
      # NOTE: Has native code support been enabled (at compile-time)?
      #
      if {![info exists no(compileNative)]} then {
        #
        # NOTE: For tests "debug-3.2", "expr-3.2", and "host-1.1".
        #
        checkForCompileOption $test_channel NATIVE
      }

      #
      # NOTE: Has native package support been enabled (at compile-time)?
      #
      if {![info exists no(compileNativePackage)]} then {
        #
        # NOTE: For test "garuda-1.0".
        #
        checkForCompileOption $test_channel NATIVE_PACKAGE
      }

      #
      # NOTE: Has network support been enabled (at compile-time)?
      #
      if {![info exists no(compileNetwork)]} then {
        #
        # NOTE: For tests "commands-1.4", "socket-1.*", "socket-2.1", and
        #       "socket-3.1".
        #
        checkForCompileOption $test_channel NETWORK
      }

      #
      # NOTE: Has native Tcl support been enabled (at compile-time)?
      #
      if {![info exists no(compileTcl)]} then {
        #
        # NOTE: For tests "commands-1.1.*", "excel-2.2", "tclCancel-1.1",
        #       "tclEncoding-1.*", "tclErrorInfo-1.*", "tclLoad-1.*",
        #       "tclResetCancel-1.1", "tclResetCancel-2.1",
        #       "tclResetCancel-2.2", "tclResetCancel-3.1",
        #       "tclResetCancel-4.1", "tclSet-1.1", and "tclSubst-1.1".
        #
        checkForCompileOption $test_channel TCL
      }

      #
      # NOTE: Has xml support been enabled (at compile-time)?
      #
      if {![info exists no(compileXml)]} then {
        #
        # NOTE: For tests "commands-1.4", "object-7.3" and "xml-1.1.*".
        #
        checkForCompileOption $test_channel XML
      }

      #
      # NOTE: Has serialization support been enabled (at compile-time)?
      #
      if {![info exists no(compileSerialization)]} then {
        #
        # NOTE: For test "interp-1.10".
        #
        checkForCompileOption $test_channel SERIALIZATION
      }

      #
      # NOTE: Has dedicated test support been enabled (at compile-time)?
      #
      if {![info exists no(compileTest)]} then {
        #
        # NOTE: For tests "basic-1.20", "basic-1.21", "function-1.1",
        #       "object-2.1", "object-3.1", "object-4.1", "object-7.1",
        #       "object-7.2", "object-7.4", "object-14.4", "object-14.5",
        #       "object-14.6", "remotingServer-1.*", and "debug-5.*".
        #
        checkForCompileOption $test_channel TEST
      }

      #
      # NOTE: Has threading support been enabled (at compile-time)?
      #
      if {![info exists no(compileThreading)]} then {
        #
        # NOTE: For tests "object-10.2" and "object-10.3".
        #
        checkForCompileOption $test_channel THREADING
      }

      #
      # NOTE: Has Tcl threading support been enabled (at compile-time)?
      #
      if {![info exists no(compileTclThreaded)]} then {
        #
        # NOTE: For tests "tclLoad-1.5" and "tclLoad-1.6".
        #
        checkForCompileOption $test_channel TCL_THREADED
      }

      #
      # NOTE: Has Tcl isolated interpreter thread support been enabled (at
      #       compile-time)?
      #
      if {![info exists no(compileTclThreads)]} then {
        #
        # NOTE: For tests "tclLoad-1.5" and "tclLoad-1.6".
        #
        checkForCompileOption $test_channel TCL_THREADS
      }
    }

    #
    # NOTE: Has dynamic loading testing support been disabled?
    #
    if {![info exists no(dynamic)]} then {
      #
      # NOTE: For tests "commands-1.1.*", "library-3.*", and "tcl*-*.*".
      #
      checkForDynamicLoading $test_channel
    }

    #
    # NOTE: Has Tcl testing support been disabled?
    #
    if {![info exists no(tcl)]} then {
      if {![info exists no(tclInstalls)]} then {
        #
        # NOTE: For tests "commands-1.1.*", "library-3.*", and "tcl*-*.*".
        #
        checkForTclInstalls $test_channel
      }

      if {![info exists no(tclReady)]} then {
        checkForTclReady $test_channel
      }

      if {![info exists no(tclShell)]} then {
        #
        # NOTE: For test "garuda-1.0".
        #
        checkForTclShell $test_channel
      }
    }

    #
    # NOTE: Has custom test method support been disabled?
    #
    if {![info exists no(test)]} then {
      #
      # NOTE: Has remoting testing support been disabled?
      #
      if {![info exists no(testRemoting)]} then {
        #
        # NOTE: For tests "remotingServer-1.*".
        #
        checkForObjectMember $test_channel Eagle._Tests.Default \
            *TestRemoting*
      }

      #
      # NOTE: Has asynchronous testing support been disabled?
      #
      if {![info exists no(testAsynchronous)]} then {
        #
        # NOTE: For tests "basic-1.20" and "basic-1.21".
        #
        checkForObjectMember $test_channel Eagle._Tests.Default \
            *TestEvaluateAsync*
      }

      #
      # NOTE: Has custom function testing support been disabled?
      #
      if {![info exists no(testFunction)]} then {
        #
        # NOTE: For test "function-1.1".
        #
        checkForObjectMember $test_channel Eagle._Tests.Default \
            *TestAddFunction*

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

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

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

      #
      # NOTE: Has write-box testing support been disabled?
      #
      if {![info exists no(testWriteBox)]} then {
        #
        # NOTE: For tests "debug-5.*".
        #
        checkForObjectMember $test_channel Eagle._Tests.Default \
            *TestWriteBox*
      }

      #
      # NOTE: Has shell testing support been disabled?
      #
      if {![info exists no(testShell)]} then {
        #
        # NOTE: For test "debug-1.3".
        #
        checkForObjectMember $test_channel Eagle._Tests.Default \
            *TestShellMainCore*

        #
        # NOTE: For tests "basic-1.36" and "debug-1.3".
        #
        checkForObjectMember $test_channel Eagle._Tests.Default \
            *TestSetQuiet*
      }

      #
      # NOTE: Has IDisposable testing support been disabled?
      #
      if {![info exists no(testDisposable)]} then {
        #
        # NOTE: For test "object-2.8".
        #
        checkForObjectMember $test_channel Eagle._Tests.Default+Disposable \
            *ToString* Eagle._Tests.Default.Disposable.ToString
      }

      #
      # NOTE: Has core marshaller testing support been disabled?
      #
      if {![info exists no(testMarshaller)]} then {
        #
        # NOTE: For test "basic-1.29".
        #
        checkForObjectMember $test_channel Eagle._Tests.Default \
            *TestExecuteStaticDelegates*

        #
        # NOTE: For tests "basic-1.30" and "basic-1.31".
        #
        checkForObjectMember $test_channel Eagle._Tests.Default \
            *TestExecuteDelegateCommands*

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

        #
        # NOTE: For test "object-2.3".
        #
        checkForObjectMember $test_channel Eagle._Components.Private.ArrayOps \
            *ToHexadecimalString*

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

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

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

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

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

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

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

        #
        # 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 \
            *TestNullableValueTypeMethod*

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

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

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

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

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

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

        #
        # NOTE: For tests "object-7.2" and "object-7.4".
        #
        checkForObjectMember $test_channel Eagle._Tests.Default \
            *TestNullArray*

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

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

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

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

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

        #
        # NOTE: For tests "object-14.4" and "object-14.5".
        #
        checkForObjectMember $test_channel Eagle._Tests.Default \
            *StaticObjectProperty*

        #
        # NOTE: For test "object-14.6".
        #
        checkForObjectMember $test_channel Eagle._Tests.Default \
            *TypeProperty*
      }
    }

    #
    # NOTE: Has Excel testing support been disabled?
    #
    if {![info exists no(excel)]} then {
      #
      # NOTE: For tests "excel-*.*".
      #
      checkForAssembly $test_channel Microsoft.Office.Interop.Excel
    }

    #
    # NOTE: Has speech testing support been disabled?
    #
    if {![info exists no(speech)]} then {
      #
      # NOTE: Set the audio volume, if necessary.
      #
      if {![info exists test_volume]} then {
        set test_volume 0; # in percent, 0 is silent.
      }

      #
      # NOTE: For test "object-4.5".
      #
      checkForAssembly $test_channel System.Speech
    }

    #
    # NOTE: Has WinForms testing support been disabled?
    #
    if {![info exists no(winForms)]} then {
      #
      # NOTE: For tests "object-13.1.*", "object-13.2.*", and
      #       "winForms-*.*".
      #
      checkForWindowsForms $test_channel
    }

    #
    # NOTE: Are we running in an STA thread?
    #
    if {![info exists no(staThread)]} then {
      #
      # NOTE: For test "xaml-1.*".
      #
      checkForStaThread $test_channel
    }

    #
    # NOTE: Has WPF testing support been disabled?
    #
    if {![info exists no(wpf)]} then {
      #
      # NOTE: For test "xaml-1.*".
      #
      checkForWindowsPresentationFoundation $test_channel
    }

    #
    # NOTE: Has PowerShell testing support been disabled?
    #
    if {![info exists no(powerShell)]} then {
      #
      # NOTE: For tests "object-4.7", "object-4.8", and "object-4.9".
      #
      checkForPowerShell $test_channel
    }

    #
    # NOTE: Has WiX testing support been disabled?
    #
    if {![info exists no(wix)]} then {
      #
      # NOTE: For test "object-4.10".
      #
      checkForWix $test_channel
    }

    #
    # 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
      #       "debug-4.1".
      #
      checkForScriptDebugger $test_channel
    }

    #
    # NOTE: Has script debugger interpreter testing support been
    #       disabled?
    #
    if {![info exists no(scriptDebuggerInterpreter)]} then {
      #
      # NOTE: For test "debug-2.1".
      #
      checkForScriptDebuggerInterpreter $test_channel
    }

    #
    # NOTE: Are we running under the Mono debugger?  If so, several
    #       tests will have to be disabled because they do not appear
    #       to work there.
    #
    if {![info exists no(monoDebugger)]} then {
      tputs $test_channel "---- checking for Mono debugger... "

      if {[haveConstraint mono] && [haveConstraint managedDebugger]} then {
        #
        # NOTE: Add a special test constraint to simplify the Mono debugger
        #       test constraint checking for the tests that need it.
        #
        addConstraint monoDebugger

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

    #
    # NOTE: Has Garuda testing support been disabled?
    #
    if {![info exists no(garudaDll)]} then {
      #
      # NOTE: For test "garuda-1.0".
      #
      checkForGarudaDll $test_channel
    }
  } else {
    #
    # HACK: Reset the test counts for tcltest.
    #
    set ::tcltest::numTests(Total) 0
    set ::tcltest::numTests(Skipped) 0
    set ::tcltest::numTests(Passed) 0
    set ::tcltest::numTests(Failed) 0

    #
    # HACK: Reset the list of failed files.
    #
    set ::tcltest::failFiles [list]

    #
    # NOTE: Has compile/runtime option testing support been disabled?
    #
    if {![info exists no(compileOptions)]} then {
      #
      # NOTE: Has dedicated test support been enabled (at compile-time)?
      #
      if {![info exists no(compileTest)]} then {
        #
        # NOTE: For test "tclLoad-1.16.1".
        #
        checkForCompileOption $test_channel TEST
      }
    }
  }

  #
  # NOTE: For test "package-1.0".
  #
  if {![info exists no(pkgAll.tcl)]} then {
    checkForFile $test_channel [file join $base_path Package Tests all.tcl] \
        pkgAll.tcl
  }

  #
  # NOTE: For test "subst-1.*".
  #
  if {![info exists no(bad_subst.txt)]} then {
    checkForFile $test_channel [file join $test_path bad_subst.txt]
  }

  #
  # NOTE: For test "fileIO-1.*".
  #
  if {![info exists no(file.dat)]} then {
    checkForFile $test_channel [file join $test_path file.dat]
  }

  #
  # NOTE: For test "garbage-1.1".
  #
  if {![info exists no(garbage.txt)]} then {
    checkForFile $test_channel [file join $test_path garbage.txt]
  }

  #
  # NOTE: For test "xaml-1.*".
  #
  if {![info exists no(test.png)]} then {
    checkForFile $test_channel [file join $test_path test.png]
  }

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

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

  #
  # NOTE: For test "read.eagle".
  #
  if {![info exists no(read.eagle)]} then {
    checkForFile $test_channel [file join $test_path read.eagle]
  }

  #
  # NOTE: For test "read2.eagle".
  #
  if {![info exists no(read2.eagle)]} then {
    checkForFile $test_channel [file join $test_path read2.eagle]
  }

  #
  # NOTE: For test "read3.eagle".
  #
  if {![info exists no(read3.eagle)]} then {
    checkForFile $test_channel [file join $test_path read3.eagle]
  }

  #
  # NOTE: For test "read4.eagle".
  #
  if {![info exists no(read4.eagle)]} then {
    checkForFile $test_channel [file join $test_path read4.eagle]
  }

  #
  # NOTE: For test "source.eagle".
  #
  if {![info exists no(source.eagle)]} then {
    checkForFile $test_channel [file join $test_path source.eagle]
  }

  #
  # NOTE: For test "unbalanced_brace.eagle".
  #
  if {![info exists no(unbalanced_brace.eagle)]} then {
    checkForFile $test_channel [file join $test_path unbalanced_brace.eagle]
  }

  #
  # NOTE: For test "unbalanced_brace2.eagle".
  #
  if {![info exists no(unbalanced_brace2.eagle)]} then {
    checkForFile $test_channel [file join $test_path unbalanced_brace2.eagle]
  }

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

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

  #
  # NOTE: For test "load-1.1.*".
  #
  if {![info exists no(Plugin.dll)]} then {
    checkForFile $test_channel [file join $lib_path Plugin1.0 Plugin.dll]
  }

  #
  # NOTE: For test "object-6.1".
  #
  if {![info exists no(Sample.exe)]} then {
    checkForFile $test_channel [file join $bin_path Sample.exe]
  }

  #
  # NOTE: For test "object-4.8".
  #
  if {![info exists no(EagleCmdlets.dll)]} then {
    checkForFile $test_channel [file join $bin_path EagleCmdlets.dll]
  }

  #
  # NOTE: For test "object-4.10".
  #
  if {![info exists no(EagleExtensions.dll)]} then {
    checkForFile $test_channel [file join $bin_path EagleExtensions.dll]
  }

  #
  # NOTE: For test "object-4.10".
  #
  if {![info exists no(test.wxs)]} then {
    checkForFile $test_channel [file join $base_path Installer Tests test.wxs]
  }

  #
  # NOTE: For test "sql-1.2".
  #
  if {![info exists no(sqlite3.dll)]} then {
    checkForFile $test_channel [file join $bin_path sqlite3.dll]
  }

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

  if {![info exists no(test.sqlite3)]} then {
    checkForFile $test_channel [file join $test_path test.sqlite3]
  }

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

  if {![info exists no(version)]} then {
    checkForVersion $test_channel
  }

  if {![info exists no(eagle)]} then {
    checkForEagle $test_channel
  }

  if {![info exists no(noLogFile)]} then {
    checkForLogFile $test_channel
  }

  if {![info exists no(symbols)]} then {
    checkForSymbols $test_channel [info nameofexecutable]
  }

  if {![info exists no(garuda)]} then {
    checkForGaruda $test_channel
  }

  if {![info exists no(shell)]} then {
    checkForShell $test_channel
  }

  if {![info exists no(debug)]} then {
    checkForDebug $test_channel
  }

  #
  # NOTE: Has Tk testing support been disabled?
  #
  if {![info exists no(tk)]} then {
    checkForTk $test_channel
  }

  #
  # NOTE: Has native code detection support been disabled?
  #
  if {![info exists no(native)]} then {
    checkForNativeCode $test_channel
  }

  #
  # NOTE: Check for various extra commands that may be present.
  #
  if {![info exists no(callbackCommand)]} then {
    checkForCommand $test_channel callback
  }

  if {![info exists no(libraryCommand)]} then {
    checkForCommand $test_channel library
  }

  if {![info exists no(socketCommand)]} then {
    checkForCommand $test_channel socket
  }

  if {![info exists no(sqlCommand)]} then {
    checkForCommand $test_channel sql
  }

  if {![info exists no(tclCommand)]} then {
    checkForCommand $test_channel tcl
  }

  if {![info exists no(xmlCommand)]} then {
    checkForCommand $test_channel xml
  }

  #
  # NOTE: Check for various features that were added through
  #       the TIP process.
  #
  if {![info exists no(tip127)]} then {
    checkForTip127 $test_channel
  }

  if {![info exists no(tip194)]} then {
    checkForTip194 $test_channel
  }

  if {![info exists no(tip241)]} then {
    checkForTip241 $test_channel
  }

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

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

  #
  # NOTE: Have precision timing tests been disabled?
  #
  if {![info exists no(timing)]} then {
    checkForTiming $test_channel 50; # 1/20th second.
  }

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

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

  #
  # NOTE: Check for network connectivity to our test host (i.e.
  #       the Eagle distribution site).
  #
  if {![info exists no(network)]} then {
    checkForNetwork $test_channel $test_host $test_timeout
  }

  #
  # NOTE: For Eagle, dump the platform information, including
  #       the compile options.
  #
  if {[isEagle]} then {
    #
    # NOTE: Figure out the approximate relative performance
    #       of this machine.
    #
    if {[haveConstraint performance]} then {
      tputs $test_channel [appendArgs \
          "---- checking for baseline BogoCops (commands-per-second)... "]

      if {![info exists test_base_cops]} then {
        #
        # NOTE: The expected performance numbers for all the
        #       performance tests will be calibrated based on
        #       this number (which is based on the measured
        #       performance of the actual machine that was
        #       used to determine those expected performance
        #       numbers).
        #
        set test_base_cops 36000.0
      }

      tputs $test_channel [appendArgs $test_base_cops \n]
      tputs $test_channel [appendArgs \
          "---- checking for current BogoCops (commands-per-second)... "]

      if {![info exists test_cops]} then {
        set test_cops [calculateBogoCops]
      }

      tputs $test_channel [appendArgs $test_cops \n]

      set percent [expr {[calculateRelativePerformance iterations 1] * 100}]

      tputs $test_channel [appendArgs \
          "---- current BogoCops (commands-per-second) is " [formatDecimal \
          [expr {$percent > 100 ? $percent - 100 : $percent}] 2] "% " \
          [expr {$percent > 100 ? "faster than" : "as fast as"}] \
          " the baseline\n"]

      unset percent
    }

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

    set timeStamp [getPlatformInfo timeStamp ""]

    if {[string length $timeStamp] > 0} then {
      #########################################################################
      # MONO: Bug, see: https://bugzilla.novell.com/show_bug.cgi?id=479061
      #########################################################################

      if {[isMono]} then {
        #
        # HACK: We need something to go into the log file.
        #
        set timeStamp [lindex $timeStamp 0]
      } else {
        set timeStamp [clock format [clock scan $timeStamp] -iso -isotimezone]
      }
    } else {
      set timeStamp <none>
    }

    tputs $test_channel [appendArgs "---- build: " \
        [list [getPlatformInfo engine <none>]] " " \
        [list [getPlatformInfo patchLevel <none>]] " " \
        [list [getPlatformInfo tag <none>]] " " \
        [list [getPlatformInfo release <none>]] " " \
        [list [getPlatformInfo text <none>]] " " \
        [list [getPlatformInfo configuration <none>]] " " \
        [list [getPlatformInfo suffix <none>]] " " \
        [list $timeStamp] \n]

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

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

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

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

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

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

    unset timeStamp
  }

  #
  # 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 ? \
      $test_file : "<none>"}] \n]

  #
  # NOTE: Show the active test constraints.
  #
  tputs $test_channel [appendArgs "---- constraints: " \
      [formatList [lsort [getConstraints]]] \n]

  #
  # NOTE: Show when the tests actually began (now).
  #
  tputs $test_channel [appendArgs "---- tests began at " \
      [clock format [clock seconds]] \n]
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































Deleted Externals/HtmlHelp/HelpDocs.zip.

cannot compute difference between binary files

Deleted Externals/HtmlHelp/htmlhelp.exe.

cannot compute difference between binary files

Deleted Externals/HtmlHelp/htmlhelpj.exe.

cannot compute difference between binary files

Deleted Externals/NDoc3/NDoc3 Beta 4.msi.

cannot compute difference between binary files

Changes to Membership/Properties/AssemblyInfo.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
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following 
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SQLiteProvider")]


[assembly: AssemblyCompany("Fresnel Computing")]
[assembly: AssemblyProduct("SQLiteProvider")]
[assembly: AssemblyCopyright("Copyright © Fresnel Computing 2006")]

#if DEBUG
[assembly: AssemblyConfiguration("Debug")]
#else
[assembly: AssemblyConfiguration("Release")]
#endif

// Setting ComVisible to false makes the types in this assembly not visible 
// to COM components.  If you need to access a type in this assembly from 
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("08669110-651d-458d-8c01-0bf683bbe931")]

// Version information for an assembly consists of the following four values:
//
//      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.76.0")]
[assembly: AssemblyFileVersion("1.0.76.0")]








>
>



<
<
|
<
|
<


















|
|
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
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following 
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SQLiteProvider")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Fresnel Computing")]
[assembly: AssemblyProduct("SQLiteProvider")]
[assembly: AssemblyCopyright("Copyright © Fresnel Computing 2006")]


[assembly: AssemblyTrademark("")]

[assembly: AssemblyCulture("")]


// Setting ComVisible to false makes the types in this assembly not visible 
// to COM components.  If you need to access a type in this assembly from 
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("08669110-651d-458d-8c01-0bf683bbe931")]

// Version information for an assembly consists of the following four values:
//
//      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.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
Changes to Membership/SQLiteProvider.2008.csproj.
22
23
24
25
26
27
28

29
30
31
32
33
34
35
    <SQLiteNetDir>$(MSBuildProjectDirectory)\..</SQLiteNetDir>
    <NetFx20>true</NetFx20>
    <ConfigurationYear>2008</ConfigurationYear>
  </PropertyGroup>
  <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets" />
  <PropertyGroup Condition="'$(BinaryOutputPath)' != ''">
    <OutputPath>$(BinaryOutputPath)</OutputPath>

  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>







>







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
    <SQLiteNetDir>$(MSBuildProjectDirectory)\..</SQLiteNetDir>
    <NetFx20>true</NetFx20>
    <ConfigurationYear>2008</ConfigurationYear>
  </PropertyGroup>
  <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets" />
  <PropertyGroup Condition="'$(BinaryOutputPath)' != ''">
    <OutputPath>$(BinaryOutputPath)</OutputPath>
    <DocumentationFile>$(BinaryOutputPath)System.Data.SQLite.xml</DocumentationFile>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
Changes to Membership/SQLiteProvider.2010.csproj.
21
22
23
24
25
26
27

28
29
30
31
32
33
34
    <OldToolsVersion>3.5</OldToolsVersion>
    <SQLiteNetDir>$(MSBuildProjectDirectory)\..</SQLiteNetDir>
    <ConfigurationYear>2010</ConfigurationYear>
  </PropertyGroup>
  <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets" />
  <PropertyGroup Condition="'$(BinaryOutputPath)' != ''">
    <OutputPath>$(BinaryOutputPath)</OutputPath>

  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>







>







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
    <OldToolsVersion>3.5</OldToolsVersion>
    <SQLiteNetDir>$(MSBuildProjectDirectory)\..</SQLiteNetDir>
    <ConfigurationYear>2010</ConfigurationYear>
  </PropertyGroup>
  <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets" />
  <PropertyGroup Condition="'$(BinaryOutputPath)' != ''">
    <OutputPath>$(BinaryOutputPath)</OutputPath>
    <DocumentationFile>$(BinaryOutputPath)System.Data.SQLite.xml</DocumentationFile>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
Changes to SQLite.Designer/AssemblyInfo.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
using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.ConstrainedExecution;
using System.Resources;

// General Information about an assembly is controlled through the following 
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("System.Data.SQLite Designer")]
[assembly: AssemblyDescription("ADO.NET Data Provider for SQLite")]

[assembly: AssemblyCompany("http://system.data.sqlite.org/")]
[assembly: AssemblyProduct("System.Data.SQLite")]
[assembly: AssemblyCopyright("Public Domain")]

#if DEBUG
[assembly: AssemblyConfiguration("Debug")]
#else
[assembly: AssemblyConfiguration("Release")]
#endif

// Setting ComVisible to false makes the types in this assembly not visible 
// to COM componenets.  If you need to access a type in this assembly from 
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
[assembly: CLSCompliant(true)]
[assembly: ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[assembly: NeutralResourcesLanguage("en")]

// Version information for an assembly consists of the following four values:
//
//      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.76.0")]
[assembly: AssemblyFileVersion("1.0.76.0")]









|
|
>
|
|

<
<
|
<
|
<


















|
|
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
using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.ConstrainedExecution;
using System.Resources;

// General Information about an assembly is controlled through the following 
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SQLite.Designer")]
[assembly: AssemblyDescription("ADO.NET Data Designer for SQLite")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("http://system.data.sqlite.org")]
[assembly: AssemblyProduct("SQLite Designer")]
[assembly: AssemblyCopyright("Public Domain")]


[assembly: AssemblyTrademark("")]

[assembly: AssemblyCulture("")]


// Setting ComVisible to false makes the types in this assembly not visible 
// to COM componenets.  If you need to access a type in this assembly from 
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
[assembly: CLSCompliant(true)]
[assembly: ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[assembly: NeutralResourcesLanguage("en")]

// Version information for an assembly consists of the following four values:
//
//      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.38.1")]
[assembly: AssemblyFileVersion("1.0.38.1")]
Changes to SQLite.Designer/Design/ForeignKey.cs.
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
  [DefaultProperty("From")]
  internal class ForeignKey : IHaveConnection, ICloneable
  {
    internal Table _table;
    internal ForeignKeyFromItem _from;
    internal ForeignKeyToItem _to;
    internal string _name;
    internal string _onUpdate;
    internal string _onDelete;
    internal string _match;
    private bool _dirty;

    private ForeignKey(ForeignKey source)
    {
      _table = source._table;
      _from = new ForeignKeyFromItem(this, source._from.Column);
      _to = new ForeignKeyToItem(this, source._to.Catalog, source._to.Table, source._to.Column);
      _name = source._name;
      _onUpdate = source._onUpdate;
      _onDelete = source._onDelete;
      _match = source._match;
      _dirty = source._dirty;
    }

    internal void MakeDirty()
    {
      _dirty = true;
    }







<
<
<








<
<
<







283
284
285
286
287
288
289



290
291
292
293
294
295
296
297



298
299
300
301
302
303
304
  [DefaultProperty("From")]
  internal class ForeignKey : IHaveConnection, ICloneable
  {
    internal Table _table;
    internal ForeignKeyFromItem _from;
    internal ForeignKeyToItem _to;
    internal string _name;



    private bool _dirty;

    private ForeignKey(ForeignKey source)
    {
      _table = source._table;
      _from = new ForeignKeyFromItem(this, source._from.Column);
      _to = new ForeignKeyToItem(this, source._to.Catalog, source._to.Table, source._to.Column);
      _name = source._name;



      _dirty = source._dirty;
    }

    internal void MakeDirty()
    {
      _dirty = true;
    }
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
    {
      _table = table;
      if (row != null)
      {
        _from = new ForeignKeyFromItem(this, row["FKEY_FROM_COLUMN"].ToString());
        _to = new ForeignKeyToItem(this, row["FKEY_TO_CATALOG"].ToString(), row["FKEY_TO_TABLE"].ToString(), row["FKEY_TO_COLUMN"].ToString());
        _name = row["CONSTRAINT_NAME"].ToString();
        _onUpdate = row["FKEY_ON_UPDATE"].ToString();
        _onDelete = row["FKEY_ON_DELETE"].ToString();
        _match = row["FKEY_MATCH"].ToString();
      }
      else
      {
        _from = new ForeignKeyFromItem(this, "");
        _to = new ForeignKeyToItem(this, _table.Catalog, "", "");
      }
    }







<
<
<







318
319
320
321
322
323
324



325
326
327
328
329
330
331
    {
      _table = table;
      if (row != null)
      {
        _from = new ForeignKeyFromItem(this, row["FKEY_FROM_COLUMN"].ToString());
        _to = new ForeignKeyToItem(this, row["FKEY_TO_CATALOG"].ToString(), row["FKEY_TO_TABLE"].ToString(), row["FKEY_TO_COLUMN"].ToString());
        _name = row["CONSTRAINT_NAME"].ToString();



      }
      else
      {
        _from = new ForeignKeyFromItem(this, "");
        _to = new ForeignKeyToItem(this, _table.Catalog, "", "");
      }
    }
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
    [Category("To")]
    [Description("The table and column to which the specified from column is related.")]
    public ForeignKeyToItem To
    {
      get { return _to; }
    }

    [DisplayName("On Update")]
    [Category("Action")]
    [Description("The action to take when modifying the parent key values of an existing row.")]
    public string OnUpdate
    {
        get { return _onUpdate; }
    }

    [DisplayName("On Delete")]
    [Category("Action")]
    [Description("The action to take when deleting a row from the parent table.")]
    public string OnDelete
    {
        get { return _onDelete; }
    }

    [DisplayName("Match")]
    [Category("Match")]
    [Description("Used with composite foreign key definitions to modify the way NULL values that occur in child keys are handled.  Not currently supported.")]
    public string Match
    {
        get { return _match; }
    }

    #region ICloneable Members

    public object Clone()
    {
      return new ForeignKey(this);
    }

    #endregion
  }
}







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










387
388
389
390
391
392
393
























394
395
396
397
398
399
400
401
402
403
    [Category("To")]
    [Description("The table and column to which the specified from column is related.")]
    public ForeignKeyToItem To
    {
      get { return _to; }
    }

























    #region ICloneable Members

    public object Clone()
    {
      return new ForeignKey(this);
    }

    #endregion
  }
}
Changes to SQLite.Designer/Design/Table.cs.
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
      separator = "";
      foreach (ForeignKey key in keys)
      {
        builder.AppendFormat("{0}[{1}]", separator, key.To.Column);
        separator = ", ";
      }
      builder.Append(")");

      if (!String.IsNullOrEmpty(keys[0].Match))
          builder.AppendFormat(" MATCH {0}", keys[0].Match);

      if (!String.IsNullOrEmpty(keys[0].OnUpdate))
          builder.AppendFormat(" ON UPDATE {0}", keys[0].OnUpdate);

      if (!String.IsNullOrEmpty(keys[0].OnDelete))
          builder.AppendFormat(" ON DELETE {0}", keys[0].OnDelete);
    }

    [Browsable(false)]
    public override ViewTableBase DesignTable
    {
      get { return this; }
    }







<
<
<
<
<
<
<
<
<







514
515
516
517
518
519
520









521
522
523
524
525
526
527
      separator = "";
      foreach (ForeignKey key in keys)
      {
        builder.AppendFormat("{0}[{1}]", separator, key.To.Column);
        separator = ", ";
      }
      builder.Append(")");









    }

    [Browsable(false)]
    public override ViewTableBase DesignTable
    {
      get { return this; }
    }
Changes to SQLite.Interop/SQLite.Interop.2008.vcproj.
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
			/>
			<Tool
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="0"
				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_DEBUG_DEFINES)"
				MinimalRebuild="false"
				ExceptionHandling="0"
				BasicRuntimeChecks="0"
				RuntimeLibrary="3"
				UsePrecompiledHeader="0"
				WarningLevel="4"
				DebugInformationFormat="3"







|







49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
			/>
			<Tool
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="0"
				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_DEBUG_DEFINES)"
				MinimalRebuild="false"
				ExceptionHandling="0"
				BasicRuntimeChecks="0"
				RuntimeLibrary="3"
				UsePrecompiledHeader="0"
				WarningLevel="4"
				DebugInformationFormat="3"
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
			<Tool
				Name="VCMIDLTool"
				TargetEnvironment="3"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="0"
				PreprocessorDefinitions="WIN32;x64;_DEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_DEBUG_DEFINES)"
				MinimalRebuild="false"
				ExceptionHandling="0"
				BasicRuntimeChecks="0"
				RuntimeLibrary="3"
				UsePrecompiledHeader="0"
				WarningLevel="4"
				DebugInformationFormat="3"







|







146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
			<Tool
				Name="VCMIDLTool"
				TargetEnvironment="3"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="0"
				PreprocessorDefinitions="WIN32;x64;_DEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_DEBUG_DEFINES)"
				MinimalRebuild="false"
				ExceptionHandling="0"
				BasicRuntimeChecks="0"
				RuntimeLibrary="3"
				UsePrecompiledHeader="0"
				WarningLevel="4"
				DebugInformationFormat="3"
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
			/>
			<Tool
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="0"
				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_DEBUG_DEFINES)"
				MinimalRebuild="false"
				ExceptionHandling="0"
				BasicRuntimeChecks="0"
				RuntimeLibrary="3"
				UsePrecompiledHeader="0"
				WarningLevel="4"
				DebugInformationFormat="3"







|







242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
			/>
			<Tool
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="0"
				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_DEBUG_DEFINES)"
				MinimalRebuild="false"
				ExceptionHandling="0"
				BasicRuntimeChecks="0"
				RuntimeLibrary="3"
				UsePrecompiledHeader="0"
				WarningLevel="4"
				DebugInformationFormat="3"
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
			<Tool
				Name="VCMIDLTool"
				TargetEnvironment="3"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="0"
				PreprocessorDefinitions="WIN32;x64;_DEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_DEBUG_DEFINES)"
				MinimalRebuild="false"
				ExceptionHandling="0"
				BasicRuntimeChecks="0"
				RuntimeLibrary="3"
				UsePrecompiledHeader="0"
				WarningLevel="4"
				DebugInformationFormat="3"







|







333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
			<Tool
				Name="VCMIDLTool"
				TargetEnvironment="3"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="0"
				PreprocessorDefinitions="WIN32;x64;_DEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_DEBUG_DEFINES)"
				MinimalRebuild="false"
				ExceptionHandling="0"
				BasicRuntimeChecks="0"
				RuntimeLibrary="3"
				UsePrecompiledHeader="0"
				WarningLevel="4"
				DebugInformationFormat="3"
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="3"
				EnableIntrinsicFunctions="true"
				FavorSizeOrSpeed="1"
				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_RELEASE_DEFINES)"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="2"
				UsePrecompiledHeader="0"
				WarningLevel="4"
				DebugInformationFormat="3"
				CompileAs="0"







|







426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="3"
				EnableIntrinsicFunctions="true"
				FavorSizeOrSpeed="1"
				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES)"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="2"
				UsePrecompiledHeader="0"
				WarningLevel="4"
				DebugInformationFormat="3"
				CompileAs="0"
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
				TargetEnvironment="3"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="3"
				EnableIntrinsicFunctions="true"
				FavorSizeOrSpeed="1"
				PreprocessorDefinitions="WIN32;x64;NDEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_RELEASE_DEFINES)"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="2"
				UsePrecompiledHeader="0"
				WarningLevel="4"
				DebugInformationFormat="3"
				CompileAs="0"







|







525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
				TargetEnvironment="3"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="3"
				EnableIntrinsicFunctions="true"
				FavorSizeOrSpeed="1"
				PreprocessorDefinitions="WIN32;x64;NDEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES)"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="2"
				UsePrecompiledHeader="0"
				WarningLevel="4"
				DebugInformationFormat="3"
				CompileAs="0"
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="3"
				EnableIntrinsicFunctions="true"
				FavorSizeOrSpeed="1"
				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_RELEASE_DEFINES)"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="2"
				UsePrecompiledHeader="0"
				WarningLevel="4"
				DebugInformationFormat="3"
				CompileAs="0"







|







623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="3"
				EnableIntrinsicFunctions="true"
				FavorSizeOrSpeed="1"
				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES)"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="2"
				UsePrecompiledHeader="0"
				WarningLevel="4"
				DebugInformationFormat="3"
				CompileAs="0"
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
				TargetEnvironment="3"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="3"
				EnableIntrinsicFunctions="true"
				FavorSizeOrSpeed="1"
				PreprocessorDefinitions="WIN32;x64;NDEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_RELEASE_DEFINES)"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="2"
				UsePrecompiledHeader="0"
				WarningLevel="4"
				DebugInformationFormat="3"
				CompileAs="0"







|







716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
				TargetEnvironment="3"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="3"
				EnableIntrinsicFunctions="true"
				FavorSizeOrSpeed="1"
				PreprocessorDefinitions="WIN32;x64;NDEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES)"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="2"
				UsePrecompiledHeader="0"
				WarningLevel="4"
				DebugInformationFormat="3"
				CompileAs="0"
Changes to SQLite.Interop/SQLite.Interop.2010.vcxproj.
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
    <LinkDelaySign Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkDelaySign>
    <LinkDelaySign Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</LinkDelaySign>
    <LinkDelaySign Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</LinkDelaySign>
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_DEBUG_DEFINES);%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>false</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <WarningLevel>Level4</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
      <CompileAs>Default</CompileAs>
      <DisableSpecificWarnings>$(SQLITE_DISABLE_WARNINGS);%(DisableSpecificWarnings)</DisableSpecificWarnings>







|







120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
    <LinkDelaySign Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkDelaySign>
    <LinkDelaySign Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</LinkDelaySign>
    <LinkDelaySign Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</LinkDelaySign>
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_DEBUG_DEFINES);%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>false</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <WarningLevel>Level4</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
      <CompileAs>Default</CompileAs>
      <DisableSpecificWarnings>$(SQLITE_DISABLE_WARNINGS);%(DisableSpecificWarnings)</DisableSpecificWarnings>
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
    <PostBuildEvent>
      <Command>"$(FrameworkSDKDir)Bin\sn.exe" -Ra "$(TargetPath)" "$(INTEROP_KEY_FILE)"</Command>
    </PostBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <PreprocessorDefinitions>WIN32;x64;_DEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_DEBUG_DEFINES);%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>false</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <WarningLevel>Level4</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
      <CompileAs>Default</CompileAs>
      <DisableSpecificWarnings>$(SQLITE_DISABLE_WARNINGS);$(SQLITE_DISABLE_X64_WARNINGS);%(DisableSpecificWarnings)</DisableSpecificWarnings>







|







161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
    <PostBuildEvent>
      <Command>"$(FrameworkSDKDir)Bin\sn.exe" -Ra "$(TargetPath)" "$(INTEROP_KEY_FILE)"</Command>
    </PostBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <PreprocessorDefinitions>WIN32;x64;_DEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_DEBUG_DEFINES);%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>false</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <WarningLevel>Level4</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
      <CompileAs>Default</CompileAs>
      <DisableSpecificWarnings>$(SQLITE_DISABLE_WARNINGS);$(SQLITE_DISABLE_X64_WARNINGS);%(DisableSpecificWarnings)</DisableSpecificWarnings>
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
    <PostBuildEvent>
      <Command>"$(FrameworkSDKDir)Bin\sn.exe" -Ra "$(TargetPath)" "$(INTEROP_KEY_FILE)"</Command>
    </PostBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugNativeOnly|Win32'">
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_DEBUG_DEFINES);%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>false</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <WarningLevel>Level4</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
      <CompileAs>Default</CompileAs>
      <DisableSpecificWarnings>$(SQLITE_DISABLE_WARNINGS);%(DisableSpecificWarnings)</DisableSpecificWarnings>







|







202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
    <PostBuildEvent>
      <Command>"$(FrameworkSDKDir)Bin\sn.exe" -Ra "$(TargetPath)" "$(INTEROP_KEY_FILE)"</Command>
    </PostBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugNativeOnly|Win32'">
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_DEBUG_DEFINES);%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>false</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <WarningLevel>Level4</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
      <CompileAs>Default</CompileAs>
      <DisableSpecificWarnings>$(SQLITE_DISABLE_WARNINGS);%(DisableSpecificWarnings)</DisableSpecificWarnings>
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
    <PostBuildEvent>
      <Command>XCOPY "$(TargetPath)" "$(OutDir)..\..\Debug\bin\" /D /E /V /I /F /H /Y</Command>
    </PostBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugNativeOnly|x64'">
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <PreprocessorDefinitions>WIN32;x64;_DEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_DEBUG_DEFINES);%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>false</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <WarningLevel>Level4</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
      <CompileAs>Default</CompileAs>
      <DisableSpecificWarnings>$(SQLITE_DISABLE_WARNINGS);$(SQLITE_DISABLE_X64_WARNINGS);%(DisableSpecificWarnings)</DisableSpecificWarnings>







|







236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
    <PostBuildEvent>
      <Command>XCOPY "$(TargetPath)" "$(OutDir)..\..\Debug\bin\" /D /E /V /I /F /H /Y</Command>
    </PostBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugNativeOnly|x64'">
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <PreprocessorDefinitions>WIN32;x64;_DEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_DEBUG_DEFINES);%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>false</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <WarningLevel>Level4</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
      <CompileAs>Default</CompileAs>
      <DisableSpecificWarnings>$(SQLITE_DISABLE_WARNINGS);$(SQLITE_DISABLE_X64_WARNINGS);%(DisableSpecificWarnings)</DisableSpecificWarnings>
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
    </PostBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <ClCompile>
      <Optimization>Full</Optimization>
      <IntrinsicFunctions>true</IntrinsicFunctions>
      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_RELEASE_DEFINES);%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>false</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <StringPooling>true</StringPooling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <WarningLevel>Level4</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
      <CompileAs>Default</CompileAs>







|







272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
    </PostBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <ClCompile>
      <Optimization>Full</Optimization>
      <IntrinsicFunctions>true</IntrinsicFunctions>
      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>false</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <StringPooling>true</StringPooling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <WarningLevel>Level4</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
      <CompileAs>Default</CompileAs>
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
    </PostBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <ClCompile>
      <Optimization>Full</Optimization>
      <IntrinsicFunctions>true</IntrinsicFunctions>
      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
      <PreprocessorDefinitions>WIN32;x64;NDEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_RELEASE_DEFINES);%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>false</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <StringPooling>true</StringPooling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <WarningLevel>Level4</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
      <CompileAs>Default</CompileAs>







|







315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
    </PostBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <ClCompile>
      <Optimization>Full</Optimization>
      <IntrinsicFunctions>true</IntrinsicFunctions>
      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
      <PreprocessorDefinitions>WIN32;x64;NDEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>false</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <StringPooling>true</StringPooling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <WarningLevel>Level4</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
      <CompileAs>Default</CompileAs>
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
    </PostBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseNativeOnly|Win32'">
    <ClCompile>
      <Optimization>Full</Optimization>
      <IntrinsicFunctions>true</IntrinsicFunctions>
      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_RELEASE_DEFINES);%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>false</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <StringPooling>true</StringPooling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <WarningLevel>Level4</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
      <CompileAs>Default</CompileAs>







|







358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
    </PostBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseNativeOnly|Win32'">
    <ClCompile>
      <Optimization>Full</Optimization>
      <IntrinsicFunctions>true</IntrinsicFunctions>
      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>false</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <StringPooling>true</StringPooling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <WarningLevel>Level4</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
      <CompileAs>Default</CompileAs>
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
    </PostBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseNativeOnly|x64'">
    <ClCompile>
      <Optimization>Full</Optimization>
      <IntrinsicFunctions>true</IntrinsicFunctions>
      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
      <PreprocessorDefinitions>WIN32;x64;NDEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_RELEASE_DEFINES);%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>false</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <StringPooling>true</StringPooling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <WarningLevel>Level4</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
      <CompileAs>Default</CompileAs>







|







395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
    </PostBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseNativeOnly|x64'">
    <ClCompile>
      <Optimization>Full</Optimization>
      <IntrinsicFunctions>true</IntrinsicFunctions>
      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
      <PreprocessorDefinitions>WIN32;x64;NDEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>false</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <StringPooling>true</StringPooling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <WarningLevel>Level4</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
      <CompileAs>Default</CompileAs>
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
    <ClInclude Include="src\win\interop.h" />
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="src\win\SQLite.Interop.rc" />
  </ItemGroup>
  <ItemGroup>
    <EmbeddedResource Include="..\System.Data.SQLite\SR.resx">
      <LogicalName>System.Data.SQLite.%(Filename).resources</LogicalName>
      <SubType>Designer</SubType>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='DebugNativeOnly|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='DebugNativeOnly|x64'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseNativeOnly|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseNativeOnly|x64'">true</ExcludedFromBuild>
    </EmbeddedResource>
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>







|









456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
    <ClInclude Include="src\win\interop.h" />
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="src\win\SQLite.Interop.rc" />
  </ItemGroup>
  <ItemGroup>
    <EmbeddedResource Include="..\System.Data.SQLite\SR.resx">
      <LogicalName>$(IntDir)System.Data.SQLite.%(Filename).resources</LogicalName>
      <SubType>Designer</SubType>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='DebugNativeOnly|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='DebugNativeOnly|x64'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseNativeOnly|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseNativeOnly|x64'">true</ExcludedFromBuild>
    </EmbeddedResource>
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
Changes to SQLite.Interop/SQLite.Interop.CE.2008.vcproj.
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
				Name="VCMIDLTool"
				TargetEnvironment="1"
			/>
			<Tool
				Name="VCCLCompilerTool"
				ExecutionBucket="7"
				Optimization="0"
				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;DEBUG;_WINDOWS;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE;$(SQLITE_WINCE_DEFINES);$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_DEBUG_DEFINES)"
				MinimalRebuild="true"
				RuntimeLibrary="1"
				UsePrecompiledHeader="0"
				WarningLevel="3"
				DebugInformationFormat="3"
				CompileAs="1"
				DisableSpecificWarnings="$(SQLITE_DISABLE_WARNINGS)"







|







45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
				Name="VCMIDLTool"
				TargetEnvironment="1"
			/>
			<Tool
				Name="VCCLCompilerTool"
				ExecutionBucket="7"
				Optimization="0"
				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;DEBUG;_WINDOWS;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE;$(SQLITE_WINCE_DEFINES);$(SQLITE_COMMON_DEFINES);$(SQLITE_DEBUG_DEFINES)"
				MinimalRebuild="true"
				RuntimeLibrary="1"
				UsePrecompiledHeader="0"
				WarningLevel="3"
				DebugInformationFormat="3"
				CompileAs="1"
				DisableSpecificWarnings="$(SQLITE_DISABLE_WARNINGS)"
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
				TargetEnvironment="1"
			/>
			<Tool
				Name="VCCLCompilerTool"
				ExecutionBucket="7"
				Optimization="2"
				FavorSizeOrSpeed="2"
				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;_WINDOWS;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE;$(SQLITE_WINCE_DEFINES);$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_RELEASE_DEFINES)"
				RuntimeLibrary="0"
				UsePrecompiledHeader="0"
				WarningLevel="3"
				DebugInformationFormat="3"
				CompileAs="1"
				DisableSpecificWarnings="$(SQLITE_DISABLE_WARNINGS)"
			/>







|







142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
				TargetEnvironment="1"
			/>
			<Tool
				Name="VCCLCompilerTool"
				ExecutionBucket="7"
				Optimization="2"
				FavorSizeOrSpeed="2"
				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;_WINDOWS;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE;$(SQLITE_WINCE_DEFINES);$(SQLITE_COMMON_DEFINES)"
				RuntimeLibrary="0"
				UsePrecompiledHeader="0"
				WarningLevel="3"
				DebugInformationFormat="3"
				CompileAs="1"
				DisableSpecificWarnings="$(SQLITE_DISABLE_WARNINGS)"
			/>
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
			<Tool
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				ExecutionBucket="7"
				Optimization="0"
				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;DEBUG;_WINDOWS;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE;$(SQLITE_WINCE_DEFINES);$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_DEBUG_DEFINES)"
				MinimalRebuild="true"
				RuntimeLibrary="1"
				UsePrecompiledHeader="0"
				WarningLevel="3"
				DebugInformationFormat="3"
				CompileAs="1"
				DisableSpecificWarnings="$(SQLITE_DISABLE_WARNINGS)"







|







238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
			<Tool
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				ExecutionBucket="7"
				Optimization="0"
				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;DEBUG;_WINDOWS;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE;$(SQLITE_WINCE_DEFINES);$(SQLITE_COMMON_DEFINES);$(SQLITE_DEBUG_DEFINES)"
				MinimalRebuild="true"
				RuntimeLibrary="1"
				UsePrecompiledHeader="0"
				WarningLevel="3"
				DebugInformationFormat="3"
				CompileAs="1"
				DisableSpecificWarnings="$(SQLITE_DISABLE_WARNINGS)"
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
			<Tool
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				ExecutionBucket="7"
				Optimization="0"
				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;DEBUG;_WINDOWS;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE;$(SQLITE_WINCE_DEFINES);$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_DEBUG_DEFINES)"
				MinimalRebuild="true"
				RuntimeLibrary="1"
				UsePrecompiledHeader="0"
				WarningLevel="3"
				DebugInformationFormat="3"
				CompileAs="1"
				DisableSpecificWarnings="$(SQLITE_DISABLE_WARNINGS)"







|







331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
			<Tool
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				ExecutionBucket="7"
				Optimization="0"
				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;DEBUG;_WINDOWS;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE;$(SQLITE_WINCE_DEFINES);$(SQLITE_COMMON_DEFINES);$(SQLITE_DEBUG_DEFINES)"
				MinimalRebuild="true"
				RuntimeLibrary="1"
				UsePrecompiledHeader="0"
				WarningLevel="3"
				DebugInformationFormat="3"
				CompileAs="1"
				DisableSpecificWarnings="$(SQLITE_DISABLE_WARNINGS)"
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				ExecutionBucket="7"
				Optimization="2"
				FavorSizeOrSpeed="2"
				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;_WINDOWS;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE;$(SQLITE_WINCE_DEFINES);$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_RELEASE_DEFINES)"
				RuntimeLibrary="0"
				UsePrecompiledHeader="0"
				WarningLevel="3"
				DebugInformationFormat="3"
				CompileAs="1"
				DisableSpecificWarnings="$(SQLITE_DISABLE_WARNINGS)"
			/>







|







425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				ExecutionBucket="7"
				Optimization="2"
				FavorSizeOrSpeed="2"
				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;_WINDOWS;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE;$(SQLITE_WINCE_DEFINES);$(SQLITE_COMMON_DEFINES)"
				RuntimeLibrary="0"
				UsePrecompiledHeader="0"
				WarningLevel="3"
				DebugInformationFormat="3"
				CompileAs="1"
				DisableSpecificWarnings="$(SQLITE_DISABLE_WARNINGS)"
			/>
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				ExecutionBucket="7"
				Optimization="2"
				FavorSizeOrSpeed="2"
				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;_WINDOWS;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE;$(SQLITE_WINCE_DEFINES);$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_RELEASE_DEFINES)"
				RuntimeLibrary="0"
				UsePrecompiledHeader="0"
				WarningLevel="3"
				DebugInformationFormat="3"
				CompileAs="1"
				DisableSpecificWarnings="$(SQLITE_DISABLE_WARNINGS)"
			/>







|







520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				ExecutionBucket="7"
				Optimization="2"
				FavorSizeOrSpeed="2"
				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;_WINDOWS;_USRDLL;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE;$(SQLITE_WINCE_DEFINES);$(SQLITE_COMMON_DEFINES)"
				RuntimeLibrary="0"
				UsePrecompiledHeader="0"
				WarningLevel="3"
				DebugInformationFormat="3"
				CompileAs="1"
				DisableSpecificWarnings="$(SQLITE_DISABLE_WARNINGS)"
			/>
Deleted SQLite.Interop/SQLite.Interop.Static.2008.vcproj.
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
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
<?xml version="1.0" encoding="Windows-1252"?>
<!--
 *
 * SQLite.Interop.Static.2008.vcproj -
 *
 * Written by Joe Mistachkin.
 * Released to the public domain, use at your own risk!
 *
-->
<VisualStudioProject
	ProjectType="Visual C++"
	Version="9.00"
	Name="SQLite.Interop.Static.2008"
	ProjectGUID="{490CBC51-A3B2-4397-89F9-16E858DCB4F8}"
	RootNamespace="SQLite.Interop"
	Keyword="Win32Proj"
	TargetFrameworkVersion="131072"
	>
	<Platforms>
		<Platform
			Name="Win32"
		/>
		<Platform
			Name="x64"
		/>
	</Platforms>
	<ToolFiles>
	</ToolFiles>
	<Configurations>
		<Configuration
			Name="Debug|Win32"
			OutputDirectory="$(ProjectDir)..\bin\$(ConfigurationYear)\$(PlatformName)\$(ConfigurationName)Static"
			IntermediateDirectory="..\obj\$(ConfigurationYear)\$(PlatformName)\$(ConfigurationName)Static"
			ConfigurationType="2"
			InheritedPropertySheets=".\props\sqlite3.vsprops;.\props\SQLite.Interop.vsprops"
			CharacterSet="1"
			>
			<Tool
				Name="VCPreBuildEventTool"
			/>
			<Tool
				Name="VCCustomBuildTool"
			/>
			<Tool
				Name="VCXMLDataGeneratorTool"
			/>
			<Tool
				Name="VCWebServiceProxyGeneratorTool"
			/>
			<Tool
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="0"
				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_DEBUG_DEFINES)"
				MinimalRebuild="false"
				ExceptionHandling="0"
				BasicRuntimeChecks="0"
				RuntimeLibrary="1"
				UsePrecompiledHeader="0"
				WarningLevel="4"
				DebugInformationFormat="3"
				CompileAs="0"
				DisableSpecificWarnings="$(SQLITE_DISABLE_WARNINGS)"
			/>
			<Tool
				Name="VCManagedResourceCompilerTool"
			/>
			<Tool
				Name="VCResourceCompilerTool"
				PreprocessorDefinitions="_DEBUG;_UNICODE;UNICODE;&quot;INTEROP_RC_VERSION=$(INTEROP_RC_VERSION)&quot;"
			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLinkerTool"
				AdditionalOptions="$(INTEROP_ASSEMBLY_RESOURCES)"
				AdditionalDependencies="$(ProjectDir)..\bin\$(ConfigurationYear)\$(ConfigurationName)Module\bin\System.Data.SQLite.netmodule"
				OutputFile="$(OutDir)\$(INTEROP_MIXED_NAME).dll"
				Version="$(INTEROP_MANIFEST_VERSION)"
				LinkIncremental="1"
				GenerateDebugInformation="true"
				AssemblyDebug="1"
				ProgramDatabaseFile="$(TargetDir)$(INTEROP_MIXED_NAME).pdb"
				GenerateMapFile="true"
				MapExports="true"
				SubSystem="2"
				OptimizeReferences="2"
				EnableCOMDATFolding="2"
				LinkTimeCodeGeneration="1"
				ImportLibrary="$(TargetDir)$(INTEROP_MIXED_NAME).lib"
				TargetMachine="1"
				KeyFile="$(INTEROP_KEY_FILE)"
				DelaySign="true"
				CLRUnmanagedCodeCheck="true"
			/>
			<Tool
				Name="VCALinkTool"
			/>
			<Tool
				Name="VCManifestTool"
				VerboseOutput="true"
				AssemblyIdentity="$(ProjectName), processorArchitecture=x86, version=$(INTEROP_MANIFEST_VERSION), type=win32"
				UpdateFileHashes="true"
			/>
			<Tool
				Name="VCXDCMakeTool"
			/>
			<Tool
				Name="VCBscMakeTool"
				OutputFile="$(OutDir)/$(INTEROP_MIXED_NAME).bsc"
			/>
			<Tool
				Name="VCFxCopTool"
			/>
			<Tool
				Name="VCAppVerifierTool"
			/>
			<Tool
				Name="VCPostBuildEventTool"
				CommandLine="&quot;$(FrameworkSDKDir)Bin\sn.exe&quot; -Ra &quot;$(OutDir)\$(INTEROP_MIXED_NAME).dll&quot; &quot;$(INTEROP_KEY_FILE)&quot;"
			/>
		</Configuration>
		<Configuration
			Name="Debug|x64"
			OutputDirectory="$(ProjectDir)..\bin\$(ConfigurationYear)\$(PlatformName)\$(ConfigurationName)Static"
			IntermediateDirectory="..\obj\$(ConfigurationYear)\$(PlatformName)\$(ConfigurationName)Static"
			ConfigurationType="2"
			InheritedPropertySheets=".\props\sqlite3.vsprops;.\props\SQLite.Interop.vsprops"
			CharacterSet="1"
			>
			<Tool
				Name="VCPreBuildEventTool"
			/>
			<Tool
				Name="VCCustomBuildTool"
			/>
			<Tool
				Name="VCXMLDataGeneratorTool"
			/>
			<Tool
				Name="VCWebServiceProxyGeneratorTool"
			/>
			<Tool
				Name="VCMIDLTool"
				TargetEnvironment="3"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="0"
				PreprocessorDefinitions="WIN32;x64;_DEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_DEBUG_DEFINES)"
				MinimalRebuild="false"
				ExceptionHandling="0"
				BasicRuntimeChecks="0"
				RuntimeLibrary="1"
				UsePrecompiledHeader="0"
				WarningLevel="4"
				DebugInformationFormat="3"
				CompileAs="0"
				DisableSpecificWarnings="$(SQLITE_DISABLE_WARNINGS);$(SQLITE_DISABLE_X64_WARNINGS)"
			/>
			<Tool
				Name="VCManagedResourceCompilerTool"
			/>
			<Tool
				Name="VCResourceCompilerTool"
				PreprocessorDefinitions="_DEBUG;_UNICODE;UNICODE;&quot;INTEROP_RC_VERSION=$(INTEROP_RC_VERSION)&quot;"
			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLinkerTool"
				AdditionalOptions="$(INTEROP_ASSEMBLY_RESOURCES)"
				AdditionalDependencies="$(ProjectDir)..\bin\$(ConfigurationYear)\$(ConfigurationName)Module\bin\System.Data.SQLite.netmodule"
				OutputFile="$(OutDir)\$(INTEROP_MIXED_NAME).dll"
				Version="$(INTEROP_MANIFEST_VERSION)"
				LinkIncremental="1"
				GenerateDebugInformation="true"
				AssemblyDebug="1"
				ProgramDatabaseFile="$(TargetDir)$(INTEROP_MIXED_NAME).pdb"
				GenerateMapFile="true"
				MapExports="true"
				SubSystem="2"
				OptimizeReferences="2"
				EnableCOMDATFolding="2"
				LinkTimeCodeGeneration="1"
				ImportLibrary="$(TargetDir)$(INTEROP_MIXED_NAME).lib"
				TargetMachine="17"
				KeyFile="$(INTEROP_KEY_FILE)"
				DelaySign="true"
				CLRUnmanagedCodeCheck="true"
			/>
			<Tool
				Name="VCALinkTool"
			/>
			<Tool
				Name="VCManifestTool"
				VerboseOutput="true"
				AssemblyIdentity="$(ProjectName), processorArchitecture=x86, version=$(INTEROP_MANIFEST_VERSION), type=win32"
				UpdateFileHashes="true"
			/>
			<Tool
				Name="VCXDCMakeTool"
			/>
			<Tool
				Name="VCBscMakeTool"
				OutputFile="$(OutDir)/$(INTEROP_MIXED_NAME).bsc"
			/>
			<Tool
				Name="VCFxCopTool"
			/>
			<Tool
				Name="VCAppVerifierTool"
			/>
			<Tool
				Name="VCPostBuildEventTool"
				CommandLine="&quot;$(FrameworkSDKDir)Bin\sn.exe&quot; -Ra &quot;$(OutDir)\$(INTEROP_MIXED_NAME).dll&quot; &quot;$(INTEROP_KEY_FILE)&quot;"
			/>
		</Configuration>
		<Configuration
			Name="DebugNativeOnly|Win32"
			OutputDirectory="$(ProjectDir)..\bin\$(ConfigurationYear)\$(PlatformName)\$(ConfigurationName)Static"
			IntermediateDirectory="..\obj\$(ConfigurationYear)\$(PlatformName)\$(ConfigurationName)Static"
			ConfigurationType="2"
			InheritedPropertySheets=".\props\sqlite3.vsprops;.\props\SQLite.Interop.vsprops"
			CharacterSet="1"
			>
			<Tool
				Name="VCPreBuildEventTool"
			/>
			<Tool
				Name="VCCustomBuildTool"
			/>
			<Tool
				Name="VCXMLDataGeneratorTool"
			/>
			<Tool
				Name="VCWebServiceProxyGeneratorTool"
			/>
			<Tool
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="0"
				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_DEBUG_DEFINES)"
				MinimalRebuild="false"
				ExceptionHandling="0"
				BasicRuntimeChecks="0"
				RuntimeLibrary="1"
				UsePrecompiledHeader="0"
				WarningLevel="4"
				DebugInformationFormat="3"
				CompileAs="0"
				DisableSpecificWarnings="$(SQLITE_DISABLE_WARNINGS)"
			/>
			<Tool
				Name="VCManagedResourceCompilerTool"
			/>
			<Tool
				Name="VCResourceCompilerTool"
				PreprocessorDefinitions="_DEBUG;_UNICODE;UNICODE;&quot;INTEROP_RC_VERSION=$(INTEROP_RC_VERSION)&quot;"
			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLinkerTool"
				OutputFile="$(OutDir)\$(INTEROP_NATIVE_NAME).dll"
				Version="$(INTEROP_MANIFEST_VERSION)"
				LinkIncremental="1"
				GenerateDebugInformation="true"
				AssemblyDebug="1"
				ProgramDatabaseFile="$(TargetDir)$(INTEROP_NATIVE_NAME).pdb"
				GenerateMapFile="true"
				MapExports="true"
				SubSystem="2"
				OptimizeReferences="2"
				EnableCOMDATFolding="2"
				ImportLibrary="$(TargetDir)$(INTEROP_NATIVE_NAME).lib"
				TargetMachine="1"
			/>
			<Tool
				Name="VCALinkTool"
			/>
			<Tool
				Name="VCManifestTool"
				VerboseOutput="true"
				AssemblyIdentity="$(ProjectName), processorArchitecture=x86, version=$(INTEROP_MANIFEST_VERSION), type=win32"
				UpdateFileHashes="true"
			/>
			<Tool
				Name="VCXDCMakeTool"
			/>
			<Tool
				Name="VCBscMakeTool"
				OutputFile="$(OutDir)/$(INTEROP_NATIVE_NAME).bsc"
			/>
			<Tool
				Name="VCFxCopTool"
			/>
			<Tool
				Name="VCAppVerifierTool"
			/>
			<Tool
				Name="VCPostBuildEventTool"
				CommandLine="IF /I &quot;%PROCESSOR_ARCHITECTURE%&quot; == &quot;x86&quot; XCOPY &quot;$(TargetPath)&quot; &quot;$(OutDir)..\..\..\Debug\bin\&quot; /D /E /V /I /F /H /Y"
			/>
		</Configuration>
		<Configuration
			Name="DebugNativeOnly|x64"
			OutputDirectory="$(ProjectDir)..\bin\$(ConfigurationYear)\$(PlatformName)\$(ConfigurationName)Static"
			IntermediateDirectory="..\obj\$(ConfigurationYear)\$(PlatformName)\$(ConfigurationName)Static"
			ConfigurationType="2"
			InheritedPropertySheets=".\props\sqlite3.vsprops;.\props\SQLite.Interop.vsprops"
			CharacterSet="1"
			>
			<Tool
				Name="VCPreBuildEventTool"
			/>
			<Tool
				Name="VCCustomBuildTool"
			/>
			<Tool
				Name="VCXMLDataGeneratorTool"
			/>
			<Tool
				Name="VCWebServiceProxyGeneratorTool"
			/>
			<Tool
				Name="VCMIDLTool"
				TargetEnvironment="3"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="0"
				PreprocessorDefinitions="WIN32;x64;_DEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_DEBUG_DEFINES)"
				MinimalRebuild="false"
				ExceptionHandling="0"
				BasicRuntimeChecks="0"
				RuntimeLibrary="1"
				UsePrecompiledHeader="0"
				WarningLevel="4"
				DebugInformationFormat="3"
				CompileAs="0"
				DisableSpecificWarnings="$(SQLITE_DISABLE_WARNINGS);$(SQLITE_DISABLE_X64_WARNINGS)"
			/>
			<Tool
				Name="VCManagedResourceCompilerTool"
			/>
			<Tool
				Name="VCResourceCompilerTool"
				PreprocessorDefinitions="_DEBUG;_UNICODE;UNICODE;&quot;INTEROP_RC_VERSION=$(INTEROP_RC_VERSION)&quot;"
			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLinkerTool"
				OutputFile="$(OutDir)\$(INTEROP_NATIVE_NAME).dll"
				Version="$(INTEROP_MANIFEST_VERSION)"
				LinkIncremental="1"
				GenerateDebugInformation="true"
				AssemblyDebug="1"
				ProgramDatabaseFile="$(TargetDir)$(INTEROP_NATIVE_NAME).pdb"
				GenerateMapFile="true"
				MapExports="true"
				SubSystem="2"
				OptimizeReferences="2"
				EnableCOMDATFolding="2"
				ImportLibrary="$(TargetDir)$(INTEROP_NATIVE_NAME).lib"
				TargetMachine="17"
			/>
			<Tool
				Name="VCALinkTool"
			/>
			<Tool
				Name="VCManifestTool"
				VerboseOutput="true"
				AssemblyIdentity="$(ProjectName), processorArchitecture=x86, version=$(INTEROP_MANIFEST_VERSION), type=win32"
				UpdateFileHashes="true"
			/>
			<Tool
				Name="VCXDCMakeTool"
			/>
			<Tool
				Name="VCBscMakeTool"
				OutputFile="$(OutDir)/$(INTEROP_NATIVE_NAME).bsc"
			/>
			<Tool
				Name="VCFxCopTool"
			/>
			<Tool
				Name="VCAppVerifierTool"
			/>
			<Tool
				Name="VCPostBuildEventTool"
				CommandLine="IF /I &quot;%PROCESSOR_ARCHITECTURE%&quot; == &quot;AMD64&quot; XCOPY &quot;$(TargetPath)&quot; &quot;$(OutDir)..\..\..\Debug\bin\&quot; /D /E /V /I /F /H /Y"
			/>
		</Configuration>
		<Configuration
			Name="Release|Win32"
			OutputDirectory="$(ProjectDir)..\bin\$(ConfigurationYear)\$(PlatformName)\$(ConfigurationName)Static"
			IntermediateDirectory="..\obj\$(ConfigurationYear)\$(PlatformName)\$(ConfigurationName)Static"
			ConfigurationType="2"
			InheritedPropertySheets=".\props\sqlite3.vsprops;.\props\SQLite.Interop.vsprops"
			CharacterSet="1"
			WholeProgramOptimization="1"
			>
			<Tool
				Name="VCPreBuildEventTool"
			/>
			<Tool
				Name="VCCustomBuildTool"
			/>
			<Tool
				Name="VCXMLDataGeneratorTool"
			/>
			<Tool
				Name="VCWebServiceProxyGeneratorTool"
			/>
			<Tool
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="3"
				EnableIntrinsicFunctions="true"
				FavorSizeOrSpeed="1"
				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_RELEASE_DEFINES)"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="0"
				UsePrecompiledHeader="0"
				WarningLevel="4"
				DebugInformationFormat="3"
				CompileAs="0"
				DisableSpecificWarnings="$(SQLITE_DISABLE_WARNINGS)"
			/>
			<Tool
				Name="VCManagedResourceCompilerTool"
			/>
			<Tool
				Name="VCResourceCompilerTool"
				PreprocessorDefinitions="NDEBUG;_UNICODE;UNICODE;&quot;INTEROP_RC_VERSION=$(INTEROP_RC_VERSION)&quot;"
			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLinkerTool"
				AdditionalOptions="$(INTEROP_ASSEMBLY_RESOURCES)"
				AdditionalDependencies="$(ProjectDir)..\bin\$(ConfigurationYear)\$(ConfigurationName)Module\bin\System.Data.SQLite.netmodule"
				OutputFile="$(OutDir)\$(INTEROP_MIXED_NAME).dll"
				Version="$(INTEROP_MANIFEST_VERSION)"
				LinkIncremental="1"
				GenerateDebugInformation="true"
				ProgramDatabaseFile="$(TargetDir)$(INTEROP_MIXED_NAME).pdb"
				GenerateMapFile="true"
				MapExports="true"
				SubSystem="2"
				LargeAddressAware="0"
				OptimizeReferences="2"
				EnableCOMDATFolding="2"
				LinkTimeCodeGeneration="1"
				ImportLibrary="$(TargetDir)$(INTEROP_MIXED_NAME).lib"
				TargetMachine="1"
				KeyFile="$(INTEROP_KEY_FILE)"
				DelaySign="true"
				CLRUnmanagedCodeCheck="true"
			/>
			<Tool
				Name="VCALinkTool"
			/>
			<Tool
				Name="VCManifestTool"
				VerboseOutput="true"
				AssemblyIdentity="$(ProjectName), processorArchitecture=x86, version=$(INTEROP_MANIFEST_VERSION), type=win32"
				UpdateFileHashes="true"
			/>
			<Tool
				Name="VCXDCMakeTool"
			/>
			<Tool
				Name="VCBscMakeTool"
				OutputFile="$(OutDir)/$(INTEROP_MIXED_NAME).bsc"
			/>
			<Tool
				Name="VCFxCopTool"
			/>
			<Tool
				Name="VCAppVerifierTool"
			/>
			<Tool
				Name="VCPostBuildEventTool"
				CommandLine="&quot;$(FrameworkSDKDir)Bin\sn.exe&quot; -Ra &quot;$(OutDir)\$(INTEROP_MIXED_NAME).dll&quot; &quot;$(INTEROP_KEY_FILE)&quot;"
			/>
		</Configuration>
		<Configuration
			Name="Release|x64"
			OutputDirectory="$(ProjectDir)..\bin\$(ConfigurationYear)\$(PlatformName)\$(ConfigurationName)Static"
			IntermediateDirectory="..\obj\$(ConfigurationYear)\$(PlatformName)\$(ConfigurationName)Static"
			ConfigurationType="2"
			InheritedPropertySheets=".\props\sqlite3.vsprops;.\props\SQLite.Interop.vsprops"
			CharacterSet="1"
			WholeProgramOptimization="1"
			>
			<Tool
				Name="VCPreBuildEventTool"
			/>
			<Tool
				Name="VCCustomBuildTool"
			/>
			<Tool
				Name="VCXMLDataGeneratorTool"
			/>
			<Tool
				Name="VCWebServiceProxyGeneratorTool"
			/>
			<Tool
				Name="VCMIDLTool"
				TargetEnvironment="3"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="3"
				EnableIntrinsicFunctions="true"
				FavorSizeOrSpeed="1"
				PreprocessorDefinitions="WIN32;x64;NDEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_RELEASE_DEFINES)"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="0"
				UsePrecompiledHeader="0"
				WarningLevel="4"
				DebugInformationFormat="3"
				CompileAs="0"
				DisableSpecificWarnings="$(SQLITE_DISABLE_WARNINGS);$(SQLITE_DISABLE_X64_WARNINGS)"
			/>
			<Tool
				Name="VCManagedResourceCompilerTool"
			/>
			<Tool
				Name="VCResourceCompilerTool"
				PreprocessorDefinitions="NDEBUG;_UNICODE;UNICODE;&quot;INTEROP_RC_VERSION=$(INTEROP_RC_VERSION)&quot;"
			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLinkerTool"
				AdditionalOptions="$(INTEROP_ASSEMBLY_RESOURCES)"
				AdditionalDependencies="$(ProjectDir)..\bin\$(ConfigurationYear)\$(ConfigurationName)Module\bin\System.Data.SQLite.netmodule"
				OutputFile="$(OutDir)\$(INTEROP_MIXED_NAME).dll"
				Version="$(INTEROP_MANIFEST_VERSION)"
				LinkIncremental="1"
				GenerateDebugInformation="true"
				ProgramDatabaseFile="$(TargetDir)$(INTEROP_MIXED_NAME).pdb"
				GenerateMapFile="true"
				MapExports="true"
				SubSystem="2"
				LargeAddressAware="0"
				OptimizeReferences="2"
				EnableCOMDATFolding="2"
				LinkTimeCodeGeneration="1"
				ImportLibrary="$(TargetDir)$(INTEROP_MIXED_NAME).lib"
				TargetMachine="17"
				KeyFile="$(INTEROP_KEY_FILE)"
				DelaySign="true"
				CLRUnmanagedCodeCheck="true"
			/>
			<Tool
				Name="VCALinkTool"
			/>
			<Tool
				Name="VCManifestTool"
				VerboseOutput="true"
				AssemblyIdentity="$(ProjectName), processorArchitecture=x86, version=$(INTEROP_MANIFEST_VERSION), type=win32"
				UpdateFileHashes="true"
			/>
			<Tool
				Name="VCXDCMakeTool"
			/>
			<Tool
				Name="VCBscMakeTool"
				OutputFile="$(OutDir)/$(INTEROP_MIXED_NAME).bsc"
			/>
			<Tool
				Name="VCFxCopTool"
			/>
			<Tool
				Name="VCAppVerifierTool"
			/>
			<Tool
				Name="VCPostBuildEventTool"
				CommandLine="&quot;$(FrameworkSDKDir)Bin\sn.exe&quot; -Ra &quot;$(OutDir)\$(INTEROP_MIXED_NAME).dll&quot; &quot;$(INTEROP_KEY_FILE)&quot;"
			/>
		</Configuration>
		<Configuration
			Name="ReleaseNativeOnly|Win32"
			OutputDirectory="$(ProjectDir)..\bin\$(ConfigurationYear)\$(PlatformName)\$(ConfigurationName)Static"
			IntermediateDirectory="..\obj\$(ConfigurationYear)\$(PlatformName)\$(ConfigurationName)Static"
			ConfigurationType="2"
			InheritedPropertySheets=".\props\sqlite3.vsprops;.\props\SQLite.Interop.vsprops"
			CharacterSet="1"
			WholeProgramOptimization="1"
			>
			<Tool
				Name="VCPreBuildEventTool"
			/>
			<Tool
				Name="VCCustomBuildTool"
			/>
			<Tool
				Name="VCXMLDataGeneratorTool"
			/>
			<Tool
				Name="VCWebServiceProxyGeneratorTool"
			/>
			<Tool
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="3"
				EnableIntrinsicFunctions="true"
				FavorSizeOrSpeed="1"
				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_RELEASE_DEFINES)"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="0"
				UsePrecompiledHeader="0"
				WarningLevel="4"
				DebugInformationFormat="3"
				CompileAs="0"
				DisableSpecificWarnings="$(SQLITE_DISABLE_WARNINGS)"
			/>
			<Tool
				Name="VCManagedResourceCompilerTool"
			/>
			<Tool
				Name="VCResourceCompilerTool"
				PreprocessorDefinitions="NDEBUG;_UNICODE;UNICODE;&quot;INTEROP_RC_VERSION=$(INTEROP_RC_VERSION)&quot;"
			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLinkerTool"
				OutputFile="$(OutDir)\$(INTEROP_NATIVE_NAME).dll"
				Version="$(INTEROP_MANIFEST_VERSION)"
				LinkIncremental="1"
				GenerateDebugInformation="true"
				ProgramDatabaseFile="$(TargetDir)$(INTEROP_NATIVE_NAME).pdb"
				GenerateMapFile="true"
				MapExports="true"
				SubSystem="2"
				LargeAddressAware="0"
				OptimizeReferences="2"
				EnableCOMDATFolding="2"
				ImportLibrary="$(TargetDir)$(INTEROP_NATIVE_NAME).lib"
				TargetMachine="1"
			/>
			<Tool
				Name="VCALinkTool"
			/>
			<Tool
				Name="VCManifestTool"
				VerboseOutput="true"
				AssemblyIdentity="$(ProjectName), processorArchitecture=x86, version=$(INTEROP_MANIFEST_VERSION), type=win32"
				UpdateFileHashes="true"
			/>
			<Tool
				Name="VCXDCMakeTool"
			/>
			<Tool
				Name="VCBscMakeTool"
				OutputFile="$(OutDir)/$(INTEROP_NATIVE_NAME).bsc"
			/>
			<Tool
				Name="VCFxCopTool"
			/>
			<Tool
				Name="VCAppVerifierTool"
			/>
			<Tool
				Name="VCPostBuildEventTool"
				CommandLine="IF /I &quot;%PROCESSOR_ARCHITECTURE%&quot; == &quot;x86&quot; XCOPY &quot;$(TargetPath)&quot; &quot;$(OutDir)..\..\..\Release\bin\&quot; /D /E /V /I /F /H /Y"
			/>
		</Configuration>
		<Configuration
			Name="ReleaseNativeOnly|x64"
			OutputDirectory="$(ProjectDir)..\bin\$(ConfigurationYear)\$(PlatformName)\$(ConfigurationName)Static"
			IntermediateDirectory="..\obj\$(ConfigurationYear)\$(PlatformName)\$(ConfigurationName)Static"
			ConfigurationType="2"
			InheritedPropertySheets=".\props\sqlite3.vsprops;.\props\SQLite.Interop.vsprops"
			CharacterSet="1"
			WholeProgramOptimization="1"
			>
			<Tool
				Name="VCPreBuildEventTool"
			/>
			<Tool
				Name="VCCustomBuildTool"
			/>
			<Tool
				Name="VCXMLDataGeneratorTool"
			/>
			<Tool
				Name="VCWebServiceProxyGeneratorTool"
			/>
			<Tool
				Name="VCMIDLTool"
				TargetEnvironment="3"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="3"
				EnableIntrinsicFunctions="true"
				FavorSizeOrSpeed="1"
				PreprocessorDefinitions="WIN32;x64;NDEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_RELEASE_DEFINES)"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="0"
				UsePrecompiledHeader="0"
				WarningLevel="4"
				DebugInformationFormat="3"
				CompileAs="0"
				DisableSpecificWarnings="$(SQLITE_DISABLE_WARNINGS);$(SQLITE_DISABLE_X64_WARNINGS)"
			/>
			<Tool
				Name="VCManagedResourceCompilerTool"
			/>
			<Tool
				Name="VCResourceCompilerTool"
				PreprocessorDefinitions="NDEBUG;_UNICODE;UNICODE;&quot;INTEROP_RC_VERSION=$(INTEROP_RC_VERSION)&quot;"
			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLinkerTool"
				OutputFile="$(OutDir)\$(INTEROP_NATIVE_NAME).dll"
				Version="$(INTEROP_MANIFEST_VERSION)"
				LinkIncremental="1"
				GenerateDebugInformation="true"
				ProgramDatabaseFile="$(TargetDir)$(INTEROP_NATIVE_NAME).pdb"
				GenerateMapFile="true"
				MapExports="true"
				SubSystem="2"
				LargeAddressAware="0"
				OptimizeReferences="2"
				EnableCOMDATFolding="2"
				ImportLibrary="$(TargetDir)$(INTEROP_NATIVE_NAME).lib"
				TargetMachine="17"
			/>
			<Tool
				Name="VCALinkTool"
			/>
			<Tool
				Name="VCManifestTool"
				VerboseOutput="true"
				AssemblyIdentity="$(ProjectName), processorArchitecture=x86, version=$(INTEROP_MANIFEST_VERSION), type=win32"
				UpdateFileHashes="true"
			/>
			<Tool
				Name="VCXDCMakeTool"
			/>
			<Tool
				Name="VCBscMakeTool"
				OutputFile="$(OutDir)/$(INTEROP_NATIVE_NAME).bsc"
			/>
			<Tool
				Name="VCFxCopTool"
			/>
			<Tool
				Name="VCAppVerifierTool"
			/>
			<Tool
				Name="VCPostBuildEventTool"
				CommandLine="IF /I &quot;%PROCESSOR_ARCHITECTURE%&quot; == &quot;AMD64&quot; XCOPY &quot;$(TargetPath)&quot; &quot;$(OutDir)..\..\..\Release\bin\&quot; /D /E /V /I /F /H /Y"
			/>
		</Configuration>
	</Configurations>
	<References>
	</References>
	<Files>
		<Filter
			Name="Source Files"
			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
			>
			<File
				RelativePath=".\src\win\AssemblyInfo.cpp"
				>
				<FileConfiguration
					Name="Debug|Win32"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="Debug|x64"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="DebugNativeOnly|Win32"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="DebugNativeOnly|x64"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="Release|Win32"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="Release|x64"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="ReleaseNativeOnly|Win32"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="ReleaseNativeOnly|x64"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
			</File>
			<File
				RelativePath=".\src\win\crypt.c"
				>
				<FileConfiguration
					Name="Debug|Win32"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="Debug|x64"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="DebugNativeOnly|Win32"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="DebugNativeOnly|x64"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="Release|Win32"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="Release|x64"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="ReleaseNativeOnly|Win32"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="ReleaseNativeOnly|x64"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
			</File>
			<File
				RelativePath=".\src\contrib\extension-functions.c"
				>
				<FileConfiguration
					Name="Debug|Win32"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="Debug|x64"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="DebugNativeOnly|Win32"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="DebugNativeOnly|x64"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="Release|Win32"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="Release|x64"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="ReleaseNativeOnly|Win32"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="ReleaseNativeOnly|x64"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
			</File>
			<File
				RelativePath=".\src\win\interop.c"
				>
			</File>
			<File
				RelativePath=".\src\core\sqlite3.c"
				>
				<FileConfiguration
					Name="Debug|Win32"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="Debug|x64"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="DebugNativeOnly|Win32"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="DebugNativeOnly|x64"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="Release|Win32"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="Release|x64"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="ReleaseNativeOnly|Win32"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="ReleaseNativeOnly|x64"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
			</File>
		</Filter>
		<Filter
			Name="Header Files"
			Filter="h;hpp;hxx;hm;inl;inc;xsd"
			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
			>
			<File
				RelativePath=".\src\core\sqlite3.h"
				>
			</File>
			<File
				RelativePath=".\src\core\sqlite3ext.h"
				>
			</File>
			<File
				RelativePath=".\src\win\interop.h"
				>
			</File>
		</Filter>
		<Filter
			Name="Resource Files"
			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
			>
			<File
				RelativePath=".\src\win\SQLite.Interop.rc"
				>
			</File>
			<File
				RelativePath="..\System.Data.SQLite\SR.resx"
				>
				<FileConfiguration
					Name="Debug|Win32"
					>
					<Tool
						Name="VCManagedResourceCompilerTool"
						ResourceFileName="$(IntDir)\$(INTEROP_MIXED_NAME).$(InputName).resources"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="Debug|x64"
					>
					<Tool
						Name="VCManagedResourceCompilerTool"
						ResourceFileName="$(IntDir)\$(INTEROP_MIXED_NAME).$(InputName).resources"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="DebugNativeOnly|Win32"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCManagedResourceCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="DebugNativeOnly|x64"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCManagedResourceCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="Release|Win32"
					>
					<Tool
						Name="VCManagedResourceCompilerTool"
						ResourceFileName="$(IntDir)\$(INTEROP_MIXED_NAME).$(InputName).resources"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="Release|x64"
					>
					<Tool
						Name="VCManagedResourceCompilerTool"
						ResourceFileName="$(IntDir)\$(INTEROP_MIXED_NAME).$(InputName).resources"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="ReleaseNativeOnly|Win32"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCManagedResourceCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="ReleaseNativeOnly|x64"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCManagedResourceCompilerTool"
					/>
				</FileConfiguration>
			</File>
		</Filter>
		<Filter
			Name="Property Files"
			>
			<File
				RelativePath=".\props\SQLite.Interop.vsprops"
				>
			</File>
			<File
				RelativePath=".\props\sqlite3.vsprops"
				>
			</File>
		</Filter>
	</Files>
	<Globals>
	</Globals>
</VisualStudioProject>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































Deleted SQLite.Interop/SQLite.Interop.Static.2010.vcxproj.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
<?xml version="1.0" encoding="utf-8"?>
<!--
 *
 * SQLite.Interop.Static.2010.vcxproj -
 *
 * Written by Joe Mistachkin.
 * Released to the public domain, use at your own risk!
 *
-->
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="DebugNativeOnly|x64">
      <Configuration>DebugNativeOnly</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|Win32">
      <Configuration>Debug</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="DebugNativeOnly|Win32">
      <Configuration>DebugNativeOnly</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|x64">
      <Configuration>Debug</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="ReleaseNativeOnly|x64">
      <Configuration>ReleaseNativeOnly</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|Win32">
      <Configuration>Release</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="ReleaseNativeOnly|Win32">
      <Configuration>ReleaseNativeOnly</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|x64">
      <Configuration>Release</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
  </ItemGroup>
  <PropertyGroup Label="Globals">
    <ProjectName>SQLite.Interop.Static.2010</ProjectName>
    <ProjectGuid>{490CBC51-A3B2-4397-89F9-16E858DCB4F8}</ProjectGuid>
    <RootNamespace>SQLite.Interop</RootNamespace>
    <Keyword>Win32Proj</Keyword>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  <Import Project="props\sqlite3.props" />
  <Import Project="props\SQLite.Interop.props" />
  <PropertyGroup Condition="('$(Configuration)' == 'DebugNativeOnly' Or
                             '$(Configuration)' == 'ReleaseNativeOnly') And
                            (('$(Platform)' == 'Win32' And
                              '$(PROCESSOR_ARCHITECTURE)' != 'x86') Or
                             ('$(Platform)' == 'x64' And
                              '$(PROCESSOR_ARCHITECTURE)' != 'AMD64' And
                              '$(PROCESSOR_ARCHITEW6432)' != 'AMD64'))"
                 Label="PostBuildEvent">
    <PostBuildEventUseInBuild>false</PostBuildEventUseInBuild>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
    <TargetName>$(INTEROP_MIXED_NAME)</TargetName>
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <CharacterSet>Unicode</CharacterSet>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
    <TargetName>$(INTEROP_MIXED_NAME)</TargetName>
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <CharacterSet>Unicode</CharacterSet>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugNativeOnly|Win32'" Label="Configuration">
    <TargetName>$(INTEROP_NATIVE_NAME)</TargetName>
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <CharacterSet>Unicode</CharacterSet>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugNativeOnly|x64'" Label="Configuration">
    <TargetName>$(INTEROP_NATIVE_NAME)</TargetName>
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <CharacterSet>Unicode</CharacterSet>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    <TargetName>$(INTEROP_MIXED_NAME)</TargetName>
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <CharacterSet>Unicode</CharacterSet>
    <WholeProgramOptimization>true</WholeProgramOptimization>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
    <TargetName>$(INTEROP_MIXED_NAME)</TargetName>
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <CharacterSet>Unicode</CharacterSet>
    <WholeProgramOptimization>true</WholeProgramOptimization>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseNativeOnly|Win32'" Label="Configuration">
    <TargetName>$(INTEROP_NATIVE_NAME)</TargetName>
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <CharacterSet>Unicode</CharacterSet>
    <WholeProgramOptimization>true</WholeProgramOptimization>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseNativeOnly|x64'" Label="Configuration">
    <TargetName>$(INTEROP_NATIVE_NAME)</TargetName>
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <CharacterSet>Unicode</CharacterSet>
    <WholeProgramOptimization>true</WholeProgramOptimization>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
  <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  <PropertyGroup>
    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
    <OutDir>$(ProjectDir)..\bin\$(ConfigurationYear)\$(Platform)\$(Configuration)Static\</OutDir>
    <IntDir>..\obj\$(ConfigurationYear)\$(Platform)\$(Configuration)Static\</IntDir>
    <LinkIncremental>false</LinkIncremental>
    <LinkKeyFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(INTEROP_KEY_FILE)</LinkKeyFile>
    <LinkKeyFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(INTEROP_KEY_FILE)</LinkKeyFile>
    <LinkKeyFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(INTEROP_KEY_FILE)</LinkKeyFile>
    <LinkKeyFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(INTEROP_KEY_FILE)</LinkKeyFile>
    <LinkDelaySign Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkDelaySign>
    <LinkDelaySign Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkDelaySign>
    <LinkDelaySign Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</LinkDelaySign>
    <LinkDelaySign Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</LinkDelaySign>
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_DEBUG_DEFINES);%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>false</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
      <WarningLevel>Level4</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
      <CompileAs>Default</CompileAs>
      <DisableSpecificWarnings>$(SQLITE_DISABLE_WARNINGS);%(DisableSpecificWarnings)</DisableSpecificWarnings>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>_DEBUG;_UNICODE;UNICODE;INTEROP_RC_VERSION=$(INTEROP_RC_VERSION);%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </ResourceCompile>
    <Link>
      <AdditionalOptions>$(INTEROP_ASSEMBLY_RESOURCES) %(AdditionalOptions)</AdditionalOptions>
      <AdditionalDependencies>$(ProjectDir)..\bin\$(ConfigurationYear)\$(Configuration)Module\bin\System.Data.SQLite.netmodule;%(AdditionalDependencies)</AdditionalDependencies>
      <Version>$(INTEROP_MANIFEST_VERSION)</Version>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <AssemblyDebug>true</AssemblyDebug>
      <GenerateMapFile>true</GenerateMapFile>
      <MapExports>true</MapExports>
      <SubSystem>Windows</SubSystem>
      <OptimizeReferences>true</OptimizeReferences>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
      <TargetMachine>MachineX86</TargetMachine>
      <CLRUnmanagedCodeCheck>true</CLRUnmanagedCodeCheck>
      <KeyFile>$(INTEROP_KEY_FILE)</KeyFile>
      <DelaySign>true</DelaySign>
    </Link>
    <Manifest>
      <VerboseOutput>true</VerboseOutput>
      <AssemblyIdentity>$(ProjectName), processorArchitecture=x86, version=$(INTEROP_MANIFEST_VERSION), type=win32</AssemblyIdentity>
      <UpdateFileHashes>true</UpdateFileHashes>
    </Manifest>
    <PostBuildEvent>
      <Command>"$(FrameworkSDKDir)Bin\sn.exe" -Ra "$(TargetPath)" "$(INTEROP_KEY_FILE)"</Command>
    </PostBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <PreprocessorDefinitions>WIN32;x64;_DEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_DEBUG_DEFINES);%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>false</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
      <WarningLevel>Level4</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
      <CompileAs>Default</CompileAs>
      <DisableSpecificWarnings>$(SQLITE_DISABLE_WARNINGS);$(SQLITE_DISABLE_X64_WARNINGS);%(DisableSpecificWarnings)</DisableSpecificWarnings>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>_DEBUG;_UNICODE;UNICODE;INTEROP_RC_VERSION=$(INTEROP_RC_VERSION);%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </ResourceCompile>
    <Link>
      <AdditionalOptions>$(INTEROP_ASSEMBLY_RESOURCES) %(AdditionalOptions)</AdditionalOptions>
      <AdditionalDependencies>$(ProjectDir)..\bin\$(ConfigurationYear)\$(Configuration)Module\bin\System.Data.SQLite.netmodule;%(AdditionalDependencies)</AdditionalDependencies>
      <Version>$(INTEROP_MANIFEST_VERSION)</Version>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <AssemblyDebug>true</AssemblyDebug>
      <GenerateMapFile>true</GenerateMapFile>
      <MapExports>true</MapExports>
      <SubSystem>Windows</SubSystem>
      <OptimizeReferences>true</OptimizeReferences>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
      <TargetMachine>MachineX64</TargetMachine>
      <CLRUnmanagedCodeCheck>true</CLRUnmanagedCodeCheck>
      <KeyFile>$(INTEROP_KEY_FILE)</KeyFile>
      <DelaySign>true</DelaySign>
    </Link>
    <Manifest>
      <VerboseOutput>true</VerboseOutput>
      <AssemblyIdentity>$(ProjectName), processorArchitecture=amd64, version=$(INTEROP_MANIFEST_VERSION), type=win32</AssemblyIdentity>
      <UpdateFileHashes>true</UpdateFileHashes>
    </Manifest>
    <PostBuildEvent>
      <Command>"$(FrameworkSDKDir)Bin\sn.exe" -Ra "$(TargetPath)" "$(INTEROP_KEY_FILE)"</Command>
    </PostBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugNativeOnly|Win32'">
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_DEBUG_DEFINES);%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>false</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
      <WarningLevel>Level4</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
      <CompileAs>Default</CompileAs>
      <DisableSpecificWarnings>$(SQLITE_DISABLE_WARNINGS);%(DisableSpecificWarnings)</DisableSpecificWarnings>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>_DEBUG;_UNICODE;UNICODE;INTEROP_RC_VERSION=$(INTEROP_RC_VERSION);%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </ResourceCompile>
    <Link>
      <Version>$(INTEROP_MANIFEST_VERSION)</Version>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <GenerateMapFile>true</GenerateMapFile>
      <MapExports>true</MapExports>
      <SubSystem>Windows</SubSystem>
      <OptimizeReferences>true</OptimizeReferences>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <TargetMachine>MachineX86</TargetMachine>
    </Link>
    <Manifest>
      <VerboseOutput>true</VerboseOutput>
      <AssemblyIdentity>$(ProjectName), processorArchitecture=x86, version=$(INTEROP_MANIFEST_VERSION), type=win32</AssemblyIdentity>
      <UpdateFileHashes>true</UpdateFileHashes>
    </Manifest>
    <PostBuildEvent>
      <Command>XCOPY "$(TargetPath)" "$(OutDir)..\..\Debug\bin\" /D /E /V /I /F /H /Y</Command>
    </PostBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugNativeOnly|x64'">
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <PreprocessorDefinitions>WIN32;x64;_DEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_DEBUG_DEFINES);%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>false</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
      <WarningLevel>Level4</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
      <CompileAs>Default</CompileAs>
      <DisableSpecificWarnings>$(SQLITE_DISABLE_WARNINGS);$(SQLITE_DISABLE_X64_WARNINGS);%(DisableSpecificWarnings)</DisableSpecificWarnings>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>_DEBUG;_UNICODE;UNICODE;INTEROP_RC_VERSION=$(INTEROP_RC_VERSION);%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </ResourceCompile>
    <Link>
      <Version>$(INTEROP_MANIFEST_VERSION)</Version>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <GenerateMapFile>true</GenerateMapFile>
      <MapExports>true</MapExports>
      <SubSystem>Windows</SubSystem>
      <OptimizeReferences>true</OptimizeReferences>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <TargetMachine>MachineX64</TargetMachine>
    </Link>
    <Manifest>
      <VerboseOutput>true</VerboseOutput>
      <AssemblyIdentity>$(ProjectName), processorArchitecture=amd64, version=$(INTEROP_MANIFEST_VERSION), type=win32</AssemblyIdentity>
      <UpdateFileHashes>true</UpdateFileHashes>
    </Manifest>
    <PostBuildEvent>
      <Command>XCOPY "$(TargetPath)" "$(OutDir)..\..\Debug\bin\" /D /E /V /I /F /H /Y</Command>
    </PostBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <ClCompile>
      <Optimization>Full</Optimization>
      <IntrinsicFunctions>true</IntrinsicFunctions>
      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_RELEASE_DEFINES);%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>false</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <StringPooling>true</StringPooling>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <WarningLevel>Level4</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
      <CompileAs>Default</CompileAs>
      <DisableSpecificWarnings>$(SQLITE_DISABLE_WARNINGS);%(DisableSpecificWarnings)</DisableSpecificWarnings>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>NDEBUG;_UNICODE;UNICODE;INTEROP_RC_VERSION=$(INTEROP_RC_VERSION);%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </ResourceCompile>
    <Link>
      <AdditionalOptions>$(INTEROP_ASSEMBLY_RESOURCES) %(AdditionalOptions)</AdditionalOptions>
      <AdditionalDependencies>$(ProjectDir)..\bin\$(ConfigurationYear)\$(Configuration)Module\bin\System.Data.SQLite.netmodule;%(AdditionalDependencies)</AdditionalDependencies>
      <Version>$(INTEROP_MANIFEST_VERSION)</Version>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <GenerateMapFile>true</GenerateMapFile>
      <MapExports>true</MapExports>
      <SubSystem>Windows</SubSystem>
      <OptimizeReferences>true</OptimizeReferences>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
      <TargetMachine>MachineX86</TargetMachine>
      <CLRUnmanagedCodeCheck>true</CLRUnmanagedCodeCheck>
      <KeyFile>$(INTEROP_KEY_FILE)</KeyFile>
      <DelaySign>true</DelaySign>
    </Link>
    <Manifest>
      <VerboseOutput>true</VerboseOutput>
      <AssemblyIdentity>$(ProjectName), processorArchitecture=x86, version=$(INTEROP_MANIFEST_VERSION), type=win32</AssemblyIdentity>
      <UpdateFileHashes>true</UpdateFileHashes>
    </Manifest>
    <PostBuildEvent>
      <Command>"$(FrameworkSDKDir)Bin\sn.exe" -Ra "$(TargetPath)" "$(INTEROP_KEY_FILE)"</Command>
    </PostBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <ClCompile>
      <Optimization>Full</Optimization>
      <IntrinsicFunctions>true</IntrinsicFunctions>
      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
      <PreprocessorDefinitions>WIN32;x64;NDEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_RELEASE_DEFINES);%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>false</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <StringPooling>true</StringPooling>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <WarningLevel>Level4</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
      <CompileAs>Default</CompileAs>
      <DisableSpecificWarnings>$(SQLITE_DISABLE_WARNINGS);$(SQLITE_DISABLE_X64_WARNINGS);%(DisableSpecificWarnings)</DisableSpecificWarnings>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>NDEBUG;_UNICODE;UNICODE;INTEROP_RC_VERSION=$(INTEROP_RC_VERSION);%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </ResourceCompile>
    <Link>
      <AdditionalOptions>$(INTEROP_ASSEMBLY_RESOURCES) %(AdditionalOptions)</AdditionalOptions>
      <AdditionalDependencies>$(ProjectDir)..\bin\$(ConfigurationYear)\$(Configuration)Module\bin\System.Data.SQLite.netmodule;%(AdditionalDependencies)</AdditionalDependencies>
      <Version>$(INTEROP_MANIFEST_VERSION)</Version>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <GenerateMapFile>true</GenerateMapFile>
      <MapExports>true</MapExports>
      <SubSystem>Windows</SubSystem>
      <OptimizeReferences>true</OptimizeReferences>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
      <TargetMachine>MachineX64</TargetMachine>
      <CLRUnmanagedCodeCheck>true</CLRUnmanagedCodeCheck>
      <KeyFile>$(INTEROP_KEY_FILE)</KeyFile>
      <DelaySign>true</DelaySign>
    </Link>
    <Manifest>
      <VerboseOutput>true</VerboseOutput>
      <AssemblyIdentity>$(ProjectName), processorArchitecture=amd64, version=$(INTEROP_MANIFEST_VERSION), type=win32</AssemblyIdentity>
      <UpdateFileHashes>true</UpdateFileHashes>
    </Manifest>
    <PostBuildEvent>
      <Command>"$(FrameworkSDKDir)Bin\sn.exe" -Ra "$(TargetPath)" "$(INTEROP_KEY_FILE)"</Command>
    </PostBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseNativeOnly|Win32'">
    <ClCompile>
      <Optimization>Full</Optimization>
      <IntrinsicFunctions>true</IntrinsicFunctions>
      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_RELEASE_DEFINES);%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>false</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <StringPooling>true</StringPooling>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <WarningLevel>Level4</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
      <CompileAs>Default</CompileAs>
      <DisableSpecificWarnings>$(SQLITE_DISABLE_WARNINGS);%(DisableSpecificWarnings)</DisableSpecificWarnings>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>NDEBUG;_UNICODE;UNICODE;INTEROP_RC_VERSION=$(INTEROP_RC_VERSION);%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </ResourceCompile>
    <Link>
      <Version>$(INTEROP_MANIFEST_VERSION)</Version>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <GenerateMapFile>true</GenerateMapFile>
      <MapExports>true</MapExports>
      <SubSystem>Windows</SubSystem>
      <OptimizeReferences>true</OptimizeReferences>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <TargetMachine>MachineX86</TargetMachine>
    </Link>
    <Manifest>
      <VerboseOutput>true</VerboseOutput>
      <AssemblyIdentity>$(ProjectName), processorArchitecture=x86, version=$(INTEROP_MANIFEST_VERSION), type=win32</AssemblyIdentity>
      <UpdateFileHashes>true</UpdateFileHashes>
    </Manifest>
    <PostBuildEvent>
      <Command>XCOPY "$(TargetPath)" "$(OutDir)..\..\Release\bin\" /D /E /V /I /F /H /Y</Command>
    </PostBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseNativeOnly|x64'">
    <ClCompile>
      <Optimization>Full</Optimization>
      <IntrinsicFunctions>true</IntrinsicFunctions>
      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
      <PreprocessorDefinitions>WIN32;x64;NDEBUG;_WINDOWS;_USRDLL;$(SQLITE_COMMON_DEFINES);$(SQLITE_EXTRA_DEFINES);$(SQLITE_RELEASE_DEFINES);%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>false</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <StringPooling>true</StringPooling>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <WarningLevel>Level4</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
      <CompileAs>Default</CompileAs>
      <DisableSpecificWarnings>$(SQLITE_DISABLE_WARNINGS);$(SQLITE_DISABLE_X64_WARNINGS);%(DisableSpecificWarnings)</DisableSpecificWarnings>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>NDEBUG;_UNICODE;UNICODE;INTEROP_RC_VERSION=$(INTEROP_RC_VERSION);%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </ResourceCompile>
    <Link>
      <Version>$(INTEROP_MANIFEST_VERSION)</Version>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <GenerateMapFile>true</GenerateMapFile>
      <MapExports>true</MapExports>
      <SubSystem>Windows</SubSystem>
      <OptimizeReferences>true</OptimizeReferences>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <TargetMachine>MachineX64</TargetMachine>
    </Link>
    <Manifest>
      <VerboseOutput>true</VerboseOutput>
      <AssemblyIdentity>$(ProjectName), processorArchitecture=amd64, version=$(INTEROP_MANIFEST_VERSION), type=win32</AssemblyIdentity>
      <UpdateFileHashes>true</UpdateFileHashes>
    </Manifest>
    <PostBuildEvent>
      <Command>XCOPY "$(TargetPath)" "$(OutDir)..\..\Release\bin\" /D /E /V /I /F /H /Y</Command>
    </PostBuildEvent>
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="src\win\AssemblyInfo.cpp">
      <ExcludedFromBuild>true</ExcludedFromBuild>
    </ClCompile>
    <ClCompile Include="src\win\crypt.c">
      <ExcludedFromBuild>true</ExcludedFromBuild>
    </ClCompile>
    <ClCompile Include="src\contrib\extension-functions.c">
      <ExcludedFromBuild>true</ExcludedFromBuild>
    </ClCompile>
    <ClCompile Include="src\win\interop.c" />
    <ClCompile Include="src\core\sqlite3.c">
      <ExcludedFromBuild>true</ExcludedFromBuild>
    </ClCompile>
  </ItemGroup>
  <ItemGroup>
    <None Include="props\SQLite.Interop.props" />
    <None Include="props\sqlite3.props" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="src\core\sqlite3.h" />
    <ClInclude Include="src\core\sqlite3ext.h" />
    <ClInclude Include="src\win\interop.h" />
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="src\win\SQLite.Interop.rc" />
  </ItemGroup>
  <ItemGroup>
    <EmbeddedResource Include="..\System.Data.SQLite\SR.resx">
      <LogicalName>System.Data.SQLite.%(Filename).resources</LogicalName>
      <SubType>Designer</SubType>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='DebugNativeOnly|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='DebugNativeOnly|x64'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseNativeOnly|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseNativeOnly|x64'">true</ExcludedFromBuild>
    </EmbeddedResource>
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































Deleted SQLite.Interop/SQLite.Interop.Static.2010.vcxproj.filters.
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
<?xml version="1.0" encoding="utf-8"?>
<!--
 *
 * SQLite.Interop.Static.2010.vcxproj.filters -
 *
 * Written by Joe Mistachkin.
 * Released to the public domain, use at your own risk!
 *
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <Filter Include="Source Files">
      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
    </Filter>
    <Filter Include="Header Files">
      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
    </Filter>
    <Filter Include="Resource Files">
      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
    </Filter>
    <Filter Include="Property Files">
      <UniqueIdentifier>{d69d5c95-1d03-4325-ad06-fce223ab4e42}</UniqueIdentifier>
    </Filter>
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="src\win\AssemblyInfo.cpp">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="src\win\crypt.c">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="src\contrib\extension-functions.c">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="src\win\interop.c">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="src\core\sqlite3.c">
      <Filter>Source Files</Filter>
    </ClCompile>
  </ItemGroup>
  <ItemGroup>
    <None Include="props\sqlite3.props">
      <Filter>Property Files</Filter>
    </None>
    <None Include="props\SQLite.Interop.props">
      <Filter>Property Files</Filter>
    </None>
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="src\core\sqlite3.h">
      <Filter>Header Files</Filter>
    </ClInclude>
    <ClInclude Include="src\core\sqlite3ext.h">
      <Filter>Header Files</Filter>
    </ClInclude>
    <ClInclude Include="src\win\interop.h">
      <Filter>Header Files</Filter>
    </ClInclude>
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="src\win\SQLite.Interop.rc">
      <Filter>Resource Files</Filter>
    </ResourceCompile>
    <EmbeddedResource Include="..\System.Data.SQLite\SR.resx">
      <Filter>Resource Files</Filter>
    </EmbeddedResource>
  </ItemGroup>
</Project>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
















































































































































Changes to SQLite.Interop/props/SQLite.Interop.props.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="utf-8"?>
<!--
 *
 * SQLite.Interop.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>076</INTEROP_BUILD_NUMBER>
    <INTEROP_MANIFEST_VERSION>1.0.76.0</INTEROP_MANIFEST_VERSION>
    <INTEROP_RC_VERSION>1,0,76,0</INTEROP_RC_VERSION>
    <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>
  <PropertyGroup>
    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>












|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="utf-8"?>
<!--
 *
 * SQLite.Interop.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>074</INTEROP_BUILD_NUMBER>
    <INTEROP_MANIFEST_VERSION>1.0.74.0</INTEROP_MANIFEST_VERSION>
    <INTEROP_RC_VERSION>1,0,74,0</INTEROP_RC_VERSION>
    <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>
  <PropertyGroup>
    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
Changes to SQLite.Interop/props/SQLite.Interop.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
	<UserMacro
		Name="ConfigurationYear"
		Value="2008"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_BUILD_NUMBER"
		Value="076"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_MANIFEST_VERSION"
		Value="1.0.76.0"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_RC_VERSION"
		Value="1,0,76,0"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_ASSEMBLY_RESOURCES"
		Value="/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"
		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
	<UserMacro
		Name="ConfigurationYear"
		Value="2008"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_BUILD_NUMBER"
		Value="074"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_MANIFEST_VERSION"
		Value="1.0.74.0"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_RC_VERSION"
		Value="1,0,74,0"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="INTEROP_ASSEMBLY_RESOURCES"
		Value="/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"
		PerformEnvironmentSet="true"
	/>
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
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
<?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.8</SQLITE_MANIFEST_VERSION>
    <SQLITE_RC_VERSION>3,7,8</SQLITE_RC_VERSION>
    <SQLITE_COMMON_DEFINES>SQLITE_THREADSAFE=1;SQLITE_ENABLE_COLUMN_METADATA=1;SQLITE_ENABLE_STAT2=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_DEBUG_DEFINES>
    <SQLITE_RELEASE_DEFINES>SQLITE_WIN32_MALLOC=1</SQLITE_RELEASE_DEFINES>
    <SQLITE_DISABLE_WARNINGS>4018;4055;4057;4090;4100;4127;4132;4146;4152;4210;4244;4245;4389;4701;4706;4996</SQLITE_DISABLE_WARNINGS>
    <SQLITE_DISABLE_X64_WARNINGS>4267;4306</SQLITE_DISABLE_X64_WARNINGS>
  </PropertyGroup>
  <PropertyGroup>
    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
  </PropertyGroup>
  <ItemGroup>
    <BuildMacro Include="SQLITE_MANIFEST_VERSION">
      <Value>$(SQLITE_MANIFEST_VERSION)</Value>
      <EnvironmentVariable>true</EnvironmentVariable>
    </BuildMacro>
    <BuildMacro Include="SQLITE_RC_VERSION">
      <Value>$(SQLITE_RC_VERSION)</Value>
      <EnvironmentVariable>true</EnvironmentVariable>
    </BuildMacro>
    <BuildMacro Include="SQLITE_COMMON_DEFINES">
      <Value>$(SQLITE_COMMON_DEFINES)</Value>
      <EnvironmentVariable>true</EnvironmentVariable>
    </BuildMacro>
    <BuildMacro Include="SQLITE_EXTRA_DEFINES">
      <Value>$(SQLITE_EXTRA_DEFINES)</Value>
      <EnvironmentVariable>true</EnvironmentVariable>
    </BuildMacro>
    <BuildMacro Include="SQLITE_WINCE_DEFINES">
      <Value>$(SQLITE_WINCE_DEFINES)</Value>
      <EnvironmentVariable>true</EnvironmentVariable>
    </BuildMacro>
    <BuildMacro Include="SQLITE_DEBUG_DEFINES">
      <Value>$(SQLITE_DEBUG_DEFINES)</Value>
      <EnvironmentVariable>true</EnvironmentVariable>
    </BuildMacro>
    <BuildMacro Include="SQLITE_RELEASE_DEFINES">
      <Value>$(SQLITE_RELEASE_DEFINES)</Value>
      <EnvironmentVariable>true</EnvironmentVariable>
    </BuildMacro>
    <BuildMacro Include="SQLITE_DISABLE_WARNINGS">
      <Value>$(SQLITE_DISABLE_WARNINGS)</Value>
      <EnvironmentVariable>true</EnvironmentVariable>
    </BuildMacro>
    <BuildMacro Include="SQLITE_DISABLE_X64_WARNINGS">
      <Value>$(SQLITE_DISABLE_X64_WARNINGS)</Value>
      <EnvironmentVariable>true</EnvironmentVariable>
    </BuildMacro>
  </ItemGroup>
</Project>











|
|
|
<
|
|
<



















<
<
<
<






<
<
<
<












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
<?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.7.1</SQLITE_MANIFEST_VERSION>
    <SQLITE_RC_VERSION>3,7,7,1</SQLITE_RC_VERSION>
    <SQLITE_COMMON_DEFINES>NDEBUG;SQLITE_THREADSAFE=1;SQLITE_HAS_CODEC=1;SQLITE_ENABLE_COLUMN_METADATA=1;SQLITE_ENABLE_FTS3=1;SQLITE_ENABLE_LOAD_EXTENSION=1;SQLITE_ENABLE_RTREE=1;SQLITE_SOUNDEX=1</SQLITE_COMMON_DEFINES>

    <SQLITE_WINCE_DEFINES>SQLITE_OMIT_WAL</SQLITE_WINCE_DEFINES>
    <SQLITE_DEBUG_DEFINES></SQLITE_DEBUG_DEFINES>

    <SQLITE_DISABLE_WARNINGS>4018;4055;4057;4090;4100;4127;4132;4146;4152;4210;4244;4245;4389;4701;4706;4996</SQLITE_DISABLE_WARNINGS>
    <SQLITE_DISABLE_X64_WARNINGS>4267;4306</SQLITE_DISABLE_X64_WARNINGS>
  </PropertyGroup>
  <PropertyGroup>
    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
  </PropertyGroup>
  <ItemGroup>
    <BuildMacro Include="SQLITE_MANIFEST_VERSION">
      <Value>$(SQLITE_MANIFEST_VERSION)</Value>
      <EnvironmentVariable>true</EnvironmentVariable>
    </BuildMacro>
    <BuildMacro Include="SQLITE_RC_VERSION">
      <Value>$(SQLITE_RC_VERSION)</Value>
      <EnvironmentVariable>true</EnvironmentVariable>
    </BuildMacro>
    <BuildMacro Include="SQLITE_COMMON_DEFINES">
      <Value>$(SQLITE_COMMON_DEFINES)</Value>
      <EnvironmentVariable>true</EnvironmentVariable>
    </BuildMacro>




    <BuildMacro Include="SQLITE_WINCE_DEFINES">
      <Value>$(SQLITE_WINCE_DEFINES)</Value>
      <EnvironmentVariable>true</EnvironmentVariable>
    </BuildMacro>
    <BuildMacro Include="SQLITE_DEBUG_DEFINES">
      <Value>$(SQLITE_DEBUG_DEFINES)</Value>




      <EnvironmentVariable>true</EnvironmentVariable>
    </BuildMacro>
    <BuildMacro Include="SQLITE_DISABLE_WARNINGS">
      <Value>$(SQLITE_DISABLE_WARNINGS)</Value>
      <EnvironmentVariable>true</EnvironmentVariable>
    </BuildMacro>
    <BuildMacro Include="SQLITE_DISABLE_X64_WARNINGS">
      <Value>$(SQLITE_DISABLE_X64_WARNINGS)</Value>
      <EnvironmentVariable>true</EnvironmentVariable>
    </BuildMacro>
  </ItemGroup>
</Project>
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
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
<VisualStudioPropertySheet
	ProjectType="Visual C++"
	Version="8.00"
	Name="sqlite3"
	>
	<UserMacro
		Name="SQLITE_MANIFEST_VERSION"
		Value="3.7.8"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="SQLITE_RC_VERSION"
		Value="3,7,8"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="SQLITE_COMMON_DEFINES"
		Value="SQLITE_THREADSAFE=1;SQLITE_ENABLE_COLUMN_METADATA=1;SQLITE_ENABLE_STAT2=1;SQLITE_ENABLE_FTS3=1;SQLITE_ENABLE_LOAD_EXTENSION=1;SQLITE_ENABLE_RTREE=1;SQLITE_SOUNDEX=1"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="SQLITE_EXTRA_DEFINES"
		Value="SQLITE_HAS_CODEC=1"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="SQLITE_WINCE_DEFINES"
		Value="SQLITE_OMIT_WAL=1"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="SQLITE_DEBUG_DEFINES"
		Value="SQLITE_DEBUG=1;SQLITE_MEMDEBUG=1"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="SQLITE_RELEASE_DEFINES"
		Value="SQLITE_WIN32_MALLOC=1"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="SQLITE_DISABLE_WARNINGS"
		Value="4018;4055;4057;4090;4100;4127;4132;4146;4152;4210;4244;4245;4389;4701;4706;4996"
		PerformEnvironmentSet="true"
	/>







|




|




|
<
<
<
<
<




|




<
<
<
<
<
|







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
<VisualStudioPropertySheet
	ProjectType="Visual C++"
	Version="8.00"
	Name="sqlite3"
	>
	<UserMacro
		Name="SQLITE_MANIFEST_VERSION"
		Value="3.7.7.1"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="SQLITE_RC_VERSION"
		Value="3,7,7,1"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="SQLITE_COMMON_DEFINES"
		Value="NDEBUG;SQLITE_THREADSAFE=1;SQLITE_HAS_CODEC=1;SQLITE_ENABLE_COLUMN_METADATA=1;SQLITE_ENABLE_FTS3=1;SQLITE_ENABLE_LOAD_EXTENSION=1;SQLITE_ENABLE_RTREE=1;SQLITE_SOUNDEX=1"





		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="SQLITE_WINCE_DEFINES"
		Value="SQLITE_OMIT_WAL"
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="SQLITE_DEBUG_DEFINES"





		Value=""
		PerformEnvironmentSet="true"
	/>
	<UserMacro
		Name="SQLITE_DISABLE_WARNINGS"
		Value="4018;4055;4057;4090;4100;4127;4132;4146;4152;4210;4244;4245;4389;4701;4706;4996"
		PerformEnvironmentSet="true"
	/>
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.8.  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.7.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
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
#endif

/*
** Exactly one of the following macros must be defined in order to
** specify which memory allocation subsystem to use.
**
**     SQLITE_SYSTEM_MALLOC          // Use normal system malloc()
**     SQLITE_WIN32_MALLOC           // Use Win32 native heap API
**     SQLITE_MEMDEBUG               // Debugging version of system malloc()
**
** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the
** assert() macro is enabled, each call into the Win32 native heap subsystem
** will cause HeapValidate to be called.  If heap validation should fail, an
** assertion will be triggered.
**
** (Historical note:  There used to be several other options, but we've
** pared it down to just these two.)
**
** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
** the default.
*/
#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_WIN32_MALLOC)+defined(SQLITE_MEMDEBUG)>1
# error "At most one of the following compile-time configuration options\
 is allows: SQLITE_SYSTEM_MALLOC, SQLITE_WIN32_MALLOC, SQLITE_MEMDEBUG"
#endif
#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_WIN32_MALLOC)+defined(SQLITE_MEMDEBUG)==0
# define SQLITE_SYSTEM_MALLOC 1
#endif

/*
** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the
** sizes of memory allocations below this value where possible.
*/







<


<
<
<
<
<






|

|

|







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

/*
** Exactly one of the following macros must be defined in order to
** specify which memory allocation subsystem to use.
**
**     SQLITE_SYSTEM_MALLOC          // Use normal system malloc()

**     SQLITE_MEMDEBUG               // Debugging version of system malloc()
**





** (Historical note:  There used to be several other options, but we've
** pared it down to just these two.)
**
** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
** the default.
*/
#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)>1
# error "At most one of the following compile-time configuration options\
 is allows: SQLITE_SYSTEM_MALLOC, SQLITE_MEMDEBUG"
#endif
#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)==0
# define SQLITE_SYSTEM_MALLOC 1
#endif

/*
** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the
** sizes of memory allocations below this value where possible.
*/
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
** 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.8"
#define SQLITE_VERSION_NUMBER 3007008
#define SQLITE_SOURCE_ID      "2011-09-19 14:49:19 3e0da808d2f5b4d12046e05980ca04578f581177"

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







|
|
|







646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
** 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.7.1"
#define SQLITE_VERSION_NUMBER 3007007
#define SQLITE_SOURCE_ID      "2011-06-28 17:39:05 af0d91adf497f5f36ec3813f04235a6e195a605f"

/*
** 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
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
** when the database connection has [PRAGMA synchronous] set to OFF.)^
** Some specialized VFSes need this signal in order to operate correctly
** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most 
** VFSes do not need this signal and should silently ignore this opcode.
** Applications should not call [sqlite3_file_control()] with this
** opcode as doing so may disrupt the operation of the specialized VFSes
** that do require it.  
**
** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
** retry counts and intervals for certain disk I/O operations for the
** windows [VFS] in order to work to provide robustness against
** anti-virus programs.  By default, the windows VFS will retry file read,
** file write, and file delete opertions up to 10 times, with a delay
** of 25 milliseconds before the first retry and with the delay increasing
** by an additional 25 milliseconds with each subsequent retry.  This
** opcode allows those to values (10 retries and 25 milliseconds of delay)
** to be adjusted.  The values are changed for all database connections
** within the same process.  The argument is a pointer to an array of two
** integers where the first integer i the new retry count and the second
** integer is the delay.  If either integer is negative, then the setting
** is not changed but instead the prior value of that setting is written
** into the array entry, allowing the current retry settings to be
** interrogated.  The zDbName parameter is ignored.
**
** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the
** persistent [WAL | Write AHead Log] setting.  By default, the auxiliary
** write ahead log and shared memory files used for transaction control
** are automatically deleted when the latest connection to the database
** closes.  Setting persistent WAL mode causes those files to persist after
** close.  Persisting the files is useful when other processes that do not
** have write permission on the directory containing the database file want
** to read the database file, as the WAL and shared memory files must exist
** in order for the database to be readable.  The fourth parameter to
** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
** That integer is 0 to disable persistent WAL mode or 1 to enable persistent
** WAL mode.  If the integer is -1, then it is overwritten with the current
** WAL persistence setting.
** 
*/
#define SQLITE_FCNTL_LOCKSTATE        1
#define SQLITE_GET_LOCKPROXYFILE      2
#define SQLITE_SET_LOCKPROXYFILE      3
#define SQLITE_LAST_ERRNO             4
#define SQLITE_FCNTL_SIZE_HINT        5
#define SQLITE_FCNTL_CHUNK_SIZE       6
#define SQLITE_FCNTL_FILE_POINTER     7
#define SQLITE_FCNTL_SYNC_OMITTED     8
#define SQLITE_FCNTL_WIN32_AV_RETRY   9
#define SQLITE_FCNTL_PERSIST_WAL     10

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







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









|
<







1280
1281
1282
1283
1284
1285
1286































1287
1288
1289
1290
1291
1292
1293
1294
1295
1296

1297
1298
1299
1300
1301
1302
1303
** when the database connection has [PRAGMA synchronous] set to OFF.)^
** Some specialized VFSes need this signal in order to operate correctly
** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most 
** VFSes do not need this signal and should silently ignore this opcode.
** Applications should not call [sqlite3_file_control()] with this
** opcode as doing so may disrupt the operation of the specialized VFSes
** that do require it.  































*/
#define SQLITE_FCNTL_LOCKSTATE        1
#define SQLITE_GET_LOCKPROXYFILE      2
#define SQLITE_SET_LOCKPROXYFILE      3
#define SQLITE_LAST_ERRNO             4
#define SQLITE_FCNTL_SIZE_HINT        5
#define SQLITE_FCNTL_CHUNK_SIZE       6
#define SQLITE_FCNTL_FILE_POINTER     7
#define SQLITE_FCNTL_SYNC_OMITTED     8



/*
** CAPI3REF: Mutex Handle
**
** The mutex module within SQLite defines [sqlite3_mutex] to be an
** abstract type for a mutex object.  The SQLite core never looks
** at the internal representation of an [sqlite3_mutex].  It only
1755
1756
1757
1758
1759
1760
1761
1762
1763



1764
1765



1766
1767
1768
1769
1770
1771
1772
** and that this object is only useful to a tiny minority of applications
** with specialized memory allocation requirements.  This object is
** also used during testing of SQLite in order to specify an alternative
** memory allocator that simulates memory out-of-memory conditions in
** order to verify that SQLite recovers gracefully from such
** conditions.
**
** The xMalloc, xRealloc, and xFree methods must work like the
** malloc(), realloc() and free() functions from the standard C library.



** ^SQLite guarantees that the second argument to
** xRealloc is always a value returned by a prior call to xRoundup.



**
** xSize should return the allocated size of a memory allocation
** previously obtained from xMalloc or xRealloc.  The allocated size
** is always at least as big as the requested size but may be larger.
**
** The xRoundup method returns what would be the allocated size of
** a memory allocation given a particular requested size.  Most memory







|
|
>
>
>
|

>
>
>







1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
** and that this object is only useful to a tiny minority of applications
** with specialized memory allocation requirements.  This object is
** also used during testing of SQLite in order to specify an alternative
** memory allocator that simulates memory out-of-memory conditions in
** order to verify that SQLite recovers gracefully from such
** conditions.
**
** The xMalloc and xFree methods must work like the
** malloc() and free() functions from the standard C library.
** The xRealloc method must work like realloc() from the standard C library
** with the exception that if the second argument to xRealloc is zero,
** xRealloc must be a no-op - it must not perform any allocation or
** deallocation.  ^SQLite guarantees that the second argument to
** xRealloc is always a value returned by a prior call to xRoundup.
** And so in cases where xRoundup always returns a positive number,
** xRealloc can perform exactly as the standard library realloc() and
** still be in compliance with this specification.
**
** xSize should return the allocated size of a memory allocation
** previously obtained from xMalloc or xRealloc.  The allocated size
** is always at least as big as the requested size but may be larger.
**
** The xRoundup method returns what would be the allocated size of
** a memory allocation given a particular requested size.  Most memory
8174
8175
8176
8177
8178
8179
8180
8181
8182
8183
8184
8185
8186
8187
8188
**
** This header defines the interface to the virtual database engine
** or VDBE.  The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database.
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
/* #include <stdio.h> */

/*
** A single VDBE is an opaque structure named "Vdbe".  Only routines
** in the source file sqliteVdbe.c are allowed to see the insides
** of this structure.
*/
typedef struct Vdbe Vdbe;







<







8142
8143
8144
8145
8146
8147
8148

8149
8150
8151
8152
8153
8154
8155
**
** This header defines the interface to the virtual database engine
** or VDBE.  The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database.
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_


/*
** A single VDBE is an opaque structure named "Vdbe".  Only routines
** in the source file sqliteVdbe.c are allowed to see the insides
** of this structure.
*/
typedef struct Vdbe Vdbe;
8218
8219
8220
8221
8222
8223
8224
8225
8226
8227
8228
8229
8230
8231
8232
    VdbeFunc *pVdbeFunc;   /* Used when p4type is P4_VDBEFUNC */
    CollSeq *pColl;        /* Used when p4type is P4_COLLSEQ */
    Mem *pMem;             /* Used when p4type is P4_MEM */
    VTable *pVtab;         /* Used when p4type is P4_VTAB */
    KeyInfo *pKeyInfo;     /* Used when p4type is P4_KEYINFO */
    int *ai;               /* Used when p4type is P4_INTARRAY */
    SubProgram *pProgram;  /* Used when p4type is P4_SUBPROGRAM */
    int (*xAdvance)(BtCursor *, int *);
  } p4;
#ifdef SQLITE_DEBUG
  char *zComment;          /* Comment to improve readability */
#endif
#ifdef VDBE_PROFILE
  int cnt;                 /* Number of times this instruction was executed */
  u64 cycles;              /* Total time spent executing this instruction */







<







8185
8186
8187
8188
8189
8190
8191

8192
8193
8194
8195
8196
8197
8198
    VdbeFunc *pVdbeFunc;   /* Used when p4type is P4_VDBEFUNC */
    CollSeq *pColl;        /* Used when p4type is P4_COLLSEQ */
    Mem *pMem;             /* Used when p4type is P4_MEM */
    VTable *pVtab;         /* Used when p4type is P4_VTAB */
    KeyInfo *pKeyInfo;     /* Used when p4type is P4_KEYINFO */
    int *ai;               /* Used when p4type is P4_INTARRAY */
    SubProgram *pProgram;  /* Used when p4type is P4_SUBPROGRAM */

  } p4;
#ifdef SQLITE_DEBUG
  char *zComment;          /* Comment to improve readability */
#endif
#ifdef VDBE_PROFILE
  int cnt;                 /* Number of times this instruction was executed */
  u64 cycles;              /* Total time spent executing this instruction */
8274
8275
8276
8277
8278
8279
8280
8281
8282
8283
8284
8285
8286
8287
8288
#define P4_VTAB     (-10) /* P4 is a pointer to an sqlite3_vtab structure */
#define P4_MPRINTF  (-11) /* P4 is a string obtained from sqlite3_mprintf() */
#define P4_REAL     (-12) /* P4 is a 64-bit floating point value */
#define P4_INT64    (-13) /* P4 is a 64-bit signed integer */
#define P4_INT32    (-14) /* P4 is a 32-bit signed integer */
#define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */
#define P4_SUBPROGRAM  (-18) /* P4 is a pointer to a SubProgram structure */
#define P4_ADVANCE  (-19) /* P4 is a pointer to BtreeNext() or BtreePrev() */

/* When adding a P4 argument using P4_KEYINFO, a copy of the KeyInfo structure
** is made.  That copy is freed when the Vdbe is finalized.  But if the
** argument is P4_KEYINFO_HANDOFF, the passed in pointer is used.  It still
** gets freed when the Vdbe is finalized so it still should be obtained
** from a single sqliteMalloc().  But no copy is made and the calling
** function should *not* try to free the KeyInfo.







<







8240
8241
8242
8243
8244
8245
8246

8247
8248
8249
8250
8251
8252
8253
#define P4_VTAB     (-10) /* P4 is a pointer to an sqlite3_vtab structure */
#define P4_MPRINTF  (-11) /* P4 is a string obtained from sqlite3_mprintf() */
#define P4_REAL     (-12) /* P4 is a 64-bit floating point value */
#define P4_INT64    (-13) /* P4 is a 64-bit signed integer */
#define P4_INT32    (-14) /* P4 is a 32-bit signed integer */
#define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */
#define P4_SUBPROGRAM  (-18) /* P4 is a pointer to a SubProgram structure */


/* When adding a P4 argument using P4_KEYINFO, a copy of the KeyInfo structure
** is made.  That copy is freed when the Vdbe is finalized.  But if the
** argument is P4_KEYINFO_HANDOFF, the passed in pointer is used.  It still
** gets freed when the Vdbe is finalized so it still should be obtained
** from a single sqliteMalloc().  But no copy is made and the calling
** function should *not* try to free the KeyInfo.
8372
8373
8374
8375
8376
8377
8378
8379
8380
8381
8382
8383
8384
8385
8386
8387
8388
8389
8390
8391
8392
8393
8394
8395
8396
8397
8398
8399
8400
8401
8402
8403
8404
8405
8406
8407
8408
8409
8410
8411
8412
8413
8414
8415
8416
8417
8418
8419
8420
8421
8422
8423
8424
8425
8426
8427
8428
8429
8430
8431
8432
8433
8434
8435
8436
8437
8438
8439
8440
8441
8442
8443
8444
8445
8446
8447
8448
8449
8450
8451
8452
8453
8454
8455
8456
8457
8458
8459
8460
8461
8462
8463
8464
8465
8466
8467
8468
8469
8470
8471
8472
8473
8474
8475
8476
8477




8478
8479
8480
8481
8482
8483
8484
8485
8486
8487
8488
8489
8490
8491
8492
8493
8494
8495
8496
8497
8498
8499
8500
8501
8502
8503
8504
8505
8506
8507

8508
8509
8510
8511
8512
8513
8514
8515
8516
8517
8518
8519
8520
8521
8522
8523
8524
8525
8526
8527
8528
8529
8530
8531
8532
8533
8534
8535
8536
8537
8538
8539
8540
#define OP_Permutation                         23
#define OP_Compare                             24
#define OP_Jump                                25
#define OP_And                                 69   /* same as TK_AND      */
#define OP_Or                                  68   /* same as TK_OR       */
#define OP_Not                                 19   /* same as TK_NOT      */
#define OP_BitNot                              93   /* same as TK_BITNOT   */
#define OP_Once                                26
#define OP_If                                  27
#define OP_IfNot                               28
#define OP_IsNull                              73   /* same as TK_ISNULL   */
#define OP_NotNull                             74   /* same as TK_NOTNULL  */
#define OP_Column                              29
#define OP_Affinity                            30
#define OP_MakeRecord                          31
#define OP_Count                               32
#define OP_Savepoint                           33
#define OP_AutoCommit                          34
#define OP_Transaction                         35
#define OP_ReadCookie                          36
#define OP_SetCookie                           37
#define OP_VerifyCookie                        38
#define OP_OpenRead                            39
#define OP_OpenWrite                           40
#define OP_OpenAutoindex                       41
#define OP_OpenEphemeral                       42
#define OP_SorterOpen                          43
#define OP_OpenPseudo                          44
#define OP_Close                               45
#define OP_SeekLt                              46
#define OP_SeekLe                              47
#define OP_SeekGe                              48
#define OP_SeekGt                              49
#define OP_Seek                                50
#define OP_NotFound                            51
#define OP_Found                               52
#define OP_IsUnique                            53
#define OP_NotExists                           54
#define OP_Sequence                            55
#define OP_NewRowid                            56
#define OP_Insert                              57
#define OP_InsertInt                           58
#define OP_Delete                              59
#define OP_ResetCount                          60
#define OP_SorterCompare                       61
#define OP_SorterData                          62
#define OP_RowKey                              63
#define OP_RowData                             64
#define OP_Rowid                               65
#define OP_NullRow                             66
#define OP_Last                                67
#define OP_SorterSort                          70
#define OP_Sort                                71
#define OP_Rewind                              72
#define OP_SorterNext                          81
#define OP_Prev                                92
#define OP_Next                                95
#define OP_SorterInsert                        96
#define OP_IdxInsert                           97
#define OP_IdxDelete                           98
#define OP_IdxRowid                            99
#define OP_IdxLT                              100
#define OP_IdxGE                              101
#define OP_Destroy                            102
#define OP_Clear                              103
#define OP_CreateIndex                        104
#define OP_CreateTable                        105
#define OP_ParseSchema                        106
#define OP_LoadAnalysis                       107
#define OP_DropTable                          108
#define OP_DropIndex                          109
#define OP_DropTrigger                        110
#define OP_IntegrityCk                        111
#define OP_RowSetAdd                          112
#define OP_RowSetRead                         113
#define OP_RowSetTest                         114
#define OP_Program                            115
#define OP_Param                              116
#define OP_FkCounter                          117
#define OP_FkIfZero                           118
#define OP_MemMax                             119
#define OP_IfPos                              120
#define OP_IfNeg                              121
#define OP_IfZero                             122
#define OP_AggStep                            123
#define OP_AggFinal                           124
#define OP_Checkpoint                         125
#define OP_JournalMode                        126
#define OP_Vacuum                             127
#define OP_IncrVacuum                         128
#define OP_Expire                             129
#define OP_TableLock                          131
#define OP_VBegin                             132
#define OP_VCreate                            133
#define OP_VDestroy                           134
#define OP_VOpen                              135
#define OP_VFilter                            136
#define OP_VColumn                            137
#define OP_VNext                              138
#define OP_VRename                            139
#define OP_VUpdate                            140
#define OP_Pagecount                          146
#define OP_MaxPgcnt                           147
#define OP_Trace                              148
#define OP_Noop                               149
#define OP_Explain                            150






/* Properties such as "out2" or "jump" that are specified in
** comments following the "case" for each opcode in the vdbe.c
** are encoded into bitvectors as follows:
*/
#define OPFLG_JUMP            0x0001  /* jump:  P2 holds jmp target */
#define OPFLG_OUT2_PRERELEASE 0x0002  /* out2-prerelease: */
#define OPFLG_IN1             0x0004  /* in1:   P1 is an input */
#define OPFLG_IN2             0x0008  /* in2:   P2 is an input */
#define OPFLG_IN3             0x0010  /* in3:   P3 is an input */
#define OPFLG_OUT2            0x0020  /* out2:  P2 is an output */
#define OPFLG_OUT3            0x0040  /* out3:  P3 is an output */
#define OPFLG_INITIALIZER {\
/*   0 */ 0x00, 0x01, 0x05, 0x04, 0x04, 0x10, 0x00, 0x02,\
/*   8 */ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x24, 0x24,\
/*  16 */ 0x00, 0x00, 0x00, 0x24, 0x04, 0x05, 0x04, 0x00,\
/*  24 */ 0x00, 0x01, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00,\
/*  32 */ 0x02, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,\
/*  40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11,\
/*  48 */ 0x11, 0x11, 0x08, 0x11, 0x11, 0x11, 0x11, 0x02,\
/*  56 */ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
/*  64 */ 0x00, 0x02, 0x00, 0x01, 0x4c, 0x4c, 0x01, 0x01,\
/*  72 */ 0x01, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15, 0x15,\
/*  80 */ 0x15, 0x01, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,\
/*  88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x01, 0x24, 0x02, 0x01,\
/*  96 */ 0x08, 0x08, 0x00, 0x02, 0x01, 0x01, 0x02, 0x00,\
/* 104 */ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
/* 112 */ 0x0c, 0x45, 0x15, 0x01, 0x02, 0x00, 0x01, 0x08,\
/* 120 */ 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00,\

/* 128 */ 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,\
/* 136 */ 0x01, 0x00, 0x01, 0x00, 0x00, 0x04, 0x04, 0x04,\
/* 144 */ 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00,}

/************** End of opcodes.h *********************************************/
/************** Continuing where we left off in vdbe.h ***********************/

/*
** Prototypes for the VDBE interface.  See comments on the implementation
** for a description of what each of these routines does.
*/
SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(sqlite3*);
SQLITE_PRIVATE int sqlite3VdbeAddOp0(Vdbe*,int);
SQLITE_PRIVATE int sqlite3VdbeAddOp1(Vdbe*,int,int);
SQLITE_PRIVATE int sqlite3VdbeAddOp2(Vdbe*,int,int,int);
SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int);
SQLITE_PRIVATE int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int);
SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp);
SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1);
SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2);
SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3);
SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u8 P5);
SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr);
SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe*, int addr);
SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int);
SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeDeleteObject(sqlite3*,Vdbe*);







<
|
|


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

















|
|
|
|
|
|
|

|
<
|
|
|
>
|
|
|

















|
|
|


|







8337
8338
8339
8340
8341
8342
8343

8344
8345
8346
8347
8348
8349
8350
8351
8352
8353
8354
8355
8356
8357
8358
8359
8360
8361

8362
8363
8364
8365
8366
8367
8368
8369
8370
8371
8372
8373
8374
8375
8376
8377
8378


8379
8380
8381
8382
8383

8384
8385

8386
8387

8388
8389
8390
8391
8392
8393
8394
8395
8396
8397
8398
8399
8400
8401
8402
8403
8404
8405
8406
8407
8408
8409
8410
8411
8412
8413
8414
8415
8416
8417
8418
8419
8420
8421
8422
8423
8424
8425
8426
8427
8428
8429
8430
8431
8432
8433
8434
8435
8436
8437
8438
8439
8440
8441
8442
8443
8444
8445
8446
8447
8448
8449
8450
8451
8452
8453
8454
8455
8456
8457
8458
8459
8460
8461
8462
8463
8464
8465

8466
8467
8468
8469
8470
8471
8472
8473
8474
8475
8476
8477
8478
8479
8480
8481
8482
8483
8484
8485
8486
8487
8488
8489
8490
8491
8492
8493
8494
8495
8496
8497
8498
8499
8500
8501
8502
#define OP_Permutation                         23
#define OP_Compare                             24
#define OP_Jump                                25
#define OP_And                                 69   /* same as TK_AND      */
#define OP_Or                                  68   /* same as TK_OR       */
#define OP_Not                                 19   /* same as TK_NOT      */
#define OP_BitNot                              93   /* same as TK_BITNOT   */

#define OP_If                                  26
#define OP_IfNot                               27
#define OP_IsNull                              73   /* same as TK_ISNULL   */
#define OP_NotNull                             74   /* same as TK_NOTNULL  */
#define OP_Column                              28
#define OP_Affinity                            29
#define OP_MakeRecord                          30
#define OP_Count                               31
#define OP_Savepoint                           32
#define OP_AutoCommit                          33
#define OP_Transaction                         34
#define OP_ReadCookie                          35
#define OP_SetCookie                           36
#define OP_VerifyCookie                        37
#define OP_OpenRead                            38
#define OP_OpenWrite                           39
#define OP_OpenAutoindex                       40
#define OP_OpenEphemeral                       41

#define OP_OpenPseudo                          42
#define OP_Close                               43
#define OP_SeekLt                              44
#define OP_SeekLe                              45
#define OP_SeekGe                              46
#define OP_SeekGt                              47
#define OP_Seek                                48
#define OP_NotFound                            49
#define OP_Found                               50
#define OP_IsUnique                            51
#define OP_NotExists                           52
#define OP_Sequence                            53
#define OP_NewRowid                            54
#define OP_Insert                              55
#define OP_InsertInt                           56
#define OP_Delete                              57
#define OP_ResetCount                          58


#define OP_RowKey                              59
#define OP_RowData                             60
#define OP_Rowid                               61
#define OP_NullRow                             62
#define OP_Last                                63

#define OP_Sort                                64
#define OP_Rewind                              65

#define OP_Prev                                66
#define OP_Next                                67

#define OP_IdxInsert                           70
#define OP_IdxDelete                           71
#define OP_IdxRowid                            72
#define OP_IdxLT                               81
#define OP_IdxGE                               92
#define OP_Destroy                             95
#define OP_Clear                               96
#define OP_CreateIndex                         97
#define OP_CreateTable                         98
#define OP_ParseSchema                         99
#define OP_LoadAnalysis                       100
#define OP_DropTable                          101
#define OP_DropIndex                          102
#define OP_DropTrigger                        103
#define OP_IntegrityCk                        104
#define OP_RowSetAdd                          105
#define OP_RowSetRead                         106
#define OP_RowSetTest                         107
#define OP_Program                            108
#define OP_Param                              109
#define OP_FkCounter                          110
#define OP_FkIfZero                           111
#define OP_MemMax                             112
#define OP_IfPos                              113
#define OP_IfNeg                              114
#define OP_IfZero                             115
#define OP_AggStep                            116
#define OP_AggFinal                           117
#define OP_Checkpoint                         118
#define OP_JournalMode                        119
#define OP_Vacuum                             120
#define OP_IncrVacuum                         121
#define OP_Expire                             122
#define OP_TableLock                          123
#define OP_VBegin                             124
#define OP_VCreate                            125
#define OP_VDestroy                           126
#define OP_VOpen                              127
#define OP_VFilter                            128
#define OP_VColumn                            129
#define OP_VNext                              131
#define OP_VRename                            132
#define OP_VUpdate                            133
#define OP_Pagecount                          134
#define OP_MaxPgcnt                           135
#define OP_Trace                              136
#define OP_Noop                               137
#define OP_Explain                            138

/* The following opcode values are never used */
#define OP_NotUsed_139                        139
#define OP_NotUsed_140                        140


/* Properties such as "out2" or "jump" that are specified in
** comments following the "case" for each opcode in the vdbe.c
** are encoded into bitvectors as follows:
*/
#define OPFLG_JUMP            0x0001  /* jump:  P2 holds jmp target */
#define OPFLG_OUT2_PRERELEASE 0x0002  /* out2-prerelease: */
#define OPFLG_IN1             0x0004  /* in1:   P1 is an input */
#define OPFLG_IN2             0x0008  /* in2:   P2 is an input */
#define OPFLG_IN3             0x0010  /* in3:   P3 is an input */
#define OPFLG_OUT2            0x0020  /* out2:  P2 is an output */
#define OPFLG_OUT3            0x0040  /* out3:  P3 is an output */
#define OPFLG_INITIALIZER {\
/*   0 */ 0x00, 0x01, 0x05, 0x04, 0x04, 0x10, 0x00, 0x02,\
/*   8 */ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x24, 0x24,\
/*  16 */ 0x00, 0x00, 0x00, 0x24, 0x04, 0x05, 0x04, 0x00,\
/*  24 */ 0x00, 0x01, 0x05, 0x05, 0x00, 0x00, 0x00, 0x02,\
/*  32 */ 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00,\
/*  40 */ 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11,\
/*  48 */ 0x08, 0x11, 0x11, 0x11, 0x11, 0x02, 0x02, 0x00,\
/*  56 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01,\
/*  64 */ 0x01, 0x01, 0x01, 0x01, 0x4c, 0x4c, 0x08, 0x00,\
/*  72 */ 0x02, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15, 0x15,\
/*  80 */ 0x15, 0x01, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,\
/*  88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x01, 0x24, 0x02, 0x02,\

/*  96 */ 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,\
/* 104 */ 0x00, 0x0c, 0x45, 0x15, 0x01, 0x02, 0x00, 0x01,\
/* 112 */ 0x08, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x02,\
/* 120 */ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
/* 128 */ 0x01, 0x00, 0x02, 0x01, 0x00, 0x00, 0x02, 0x02,\
/* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04,\
/* 144 */ 0x04, 0x04,}

/************** End of opcodes.h *********************************************/
/************** Continuing where we left off in vdbe.h ***********************/

/*
** Prototypes for the VDBE interface.  See comments on the implementation
** for a description of what each of these routines does.
*/
SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(sqlite3*);
SQLITE_PRIVATE int sqlite3VdbeAddOp0(Vdbe*,int);
SQLITE_PRIVATE int sqlite3VdbeAddOp1(Vdbe*,int,int);
SQLITE_PRIVATE int sqlite3VdbeAddOp2(Vdbe*,int,int,int);
SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int);
SQLITE_PRIVATE int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int);
SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp);
SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1);
SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2);
SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, int addr, int P3);
SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u8 P5);
SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr);
SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N);
SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int);
SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeDeleteObject(sqlite3*,Vdbe*);
8558
8559
8560
8561
8562
8563
8564
8565

8566
8567
8568
8569
8570
8571
8572
8573
8574
SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*);
SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetValue(Vdbe*, int, u8);
SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe*, int);
#ifndef SQLITE_OMIT_TRACE
SQLITE_PRIVATE   char *sqlite3VdbeExpandSql(Vdbe*, const char*);
#endif

SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);

SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **);

#ifndef SQLITE_OMIT_TRIGGER
SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
#endif


#ifndef NDEBUG







|
>

<







8520
8521
8522
8523
8524
8525
8526
8527
8528
8529

8530
8531
8532
8533
8534
8535
8536
SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*);
SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetValue(Vdbe*, int, u8);
SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe*, int);
#ifndef SQLITE_OMIT_TRACE
SQLITE_PRIVATE   char *sqlite3VdbeExpandSql(Vdbe*, const char*);
#endif

SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,char*,int);
SQLITE_PRIVATE void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord*);
SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);


#ifndef SQLITE_OMIT_TRIGGER
SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
#endif


#ifndef NDEBUG
9594
9595
9596
9597
9598
9599
9600
9601
9602
9603
9604
9605
9606
9607
9608
#define SQLITE_ColumnCache    0x02        /* Disable the column cache */
#define SQLITE_IndexSort      0x04        /* Disable indexes for sorting */
#define SQLITE_IndexSearch    0x08        /* Disable indexes for searching */
#define SQLITE_IndexCover     0x10        /* Disable index covering table */
#define SQLITE_GroupByOrder   0x20        /* Disable GROUPBY cover of ORDERBY */
#define SQLITE_FactorOutConst 0x40        /* Disable factoring out constants */
#define SQLITE_IdxRealAsInt   0x80        /* Store REAL as INT in indices */
#define SQLITE_DistinctOpt    0x80        /* DISTINCT using indexes */
#define SQLITE_OptMask        0xff        /* Mask of all disablable opts */

/*
** Possible values for the sqlite.magic field.
** The numbers are obtained at random and have no special meaning, other
** than being distinct from one another.
*/







<







9556
9557
9558
9559
9560
9561
9562

9563
9564
9565
9566
9567
9568
9569
#define SQLITE_ColumnCache    0x02        /* Disable the column cache */
#define SQLITE_IndexSort      0x04        /* Disable indexes for sorting */
#define SQLITE_IndexSearch    0x08        /* Disable indexes for searching */
#define SQLITE_IndexCover     0x10        /* Disable index covering table */
#define SQLITE_GroupByOrder   0x20        /* Disable GROUPBY cover of ORDERBY */
#define SQLITE_FactorOutConst 0x40        /* Disable factoring out constants */
#define SQLITE_IdxRealAsInt   0x80        /* Store REAL as INT in indices */

#define SQLITE_OptMask        0xff        /* Mask of all disablable opts */

/*
** Possible values for the sqlite.magic field.
** The numbers are obtained at random and have no special meaning, other
** than being distinct from one another.
*/
10174
10175
10176
10177
10178
10179
10180
10181
10182
10183
10184
10185
10186
10187
10188
*/
struct AggInfo {
  u8 directMode;          /* Direct rendering mode means take data directly
                          ** from source tables rather than from accumulators */
  u8 useSortingIdx;       /* In direct mode, reference the sorting index rather
                          ** than the source table */
  int sortingIdx;         /* Cursor number of the sorting index */
  int sortingIdxPTab;     /* Cursor number of pseudo-table */
  ExprList *pGroupBy;     /* The group by clause */
  int nSortingColumn;     /* Number of columns in the sorting index */
  struct AggInfo_col {    /* For each column used in source tables */
    Table *pTab;             /* Source table */
    int iTable;              /* Cursor number of the source table */
    int iColumn;             /* Column number within the source table */
    int iSorterColumn;       /* Column number in the sorting index */







<







10135
10136
10137
10138
10139
10140
10141

10142
10143
10144
10145
10146
10147
10148
*/
struct AggInfo {
  u8 directMode;          /* Direct rendering mode means take data directly
                          ** from source tables rather than from accumulators */
  u8 useSortingIdx;       /* In direct mode, reference the sorting index rather
                          ** than the source table */
  int sortingIdx;         /* Cursor number of the sorting index */

  ExprList *pGroupBy;     /* The group by clause */
  int nSortingColumn;     /* Number of columns in the sorting index */
  struct AggInfo_col {    /* For each column used in source tables */
    Table *pTab;             /* Source table */
    int iTable;              /* Cursor number of the source table */
    int iColumn;             /* Column number within the source table */
    int iSorterColumn;       /* Column number in the sorting index */
10484
10485
10486
10487
10488
10489
10490
10491
10492
10493
10494
10495
10496
10497
10498
10499
10500
10501
10502
  i16 nAlloc;      /* Number of entries allocated in a[] below */
  struct SrcList_item {
    char *zDatabase;  /* Name of database holding this table */
    char *zName;      /* Name of the table */
    char *zAlias;     /* The "B" part of a "A AS B" phrase.  zName is the "A" */
    Table *pTab;      /* An SQL table corresponding to zName */
    Select *pSelect;  /* A SELECT statement used in place of a table name */
    int addrFillSub;  /* Address of subroutine to manifest a subquery */
    int regReturn;    /* Register holding return address of addrFillSub */
    u8 jointype;      /* Type of join between this able and the previous */
    u8 notIndexed;    /* True if there is a NOT INDEXED clause */
    u8 isCorrelated;  /* True if sub-query is correlated */
#ifndef SQLITE_OMIT_EXPLAIN
    u8 iSelectId;     /* If pSelect!=0, the id of the sub-select in EQP */
#endif
    int iCursor;      /* The VDBE cursor number used to access this table */
    Expr *pOn;        /* The ON clause of a join */
    IdList *pUsing;   /* The USING clause of a join */
    Bitmask colUsed;  /* Bit N (1<<N) set if column N of pTab is used */







|
<


<







10444
10445
10446
10447
10448
10449
10450
10451

10452
10453

10454
10455
10456
10457
10458
10459
10460
  i16 nAlloc;      /* Number of entries allocated in a[] below */
  struct SrcList_item {
    char *zDatabase;  /* Name of database holding this table */
    char *zName;      /* Name of the table */
    char *zAlias;     /* The "B" part of a "A AS B" phrase.  zName is the "A" */
    Table *pTab;      /* An SQL table corresponding to zName */
    Select *pSelect;  /* A SELECT statement used in place of a table name */
    u8 isPopulated;   /* Temporary table associated with SELECT is populated */

    u8 jointype;      /* Type of join between this able and the previous */
    u8 notIndexed;    /* True if there is a NOT INDEXED clause */

#ifndef SQLITE_OMIT_EXPLAIN
    u8 iSelectId;     /* If pSelect!=0, the id of the sub-select in EQP */
#endif
    int iCursor;      /* The VDBE cursor number used to access this table */
    Expr *pOn;        /* The ON clause of a join */
    IdList *pUsing;   /* The USING clause of a join */
    Bitmask colUsed;  /* Bit N (1<<N) set if column N of pTab is used */
10608
10609
10610
10611
10612
10613
10614
10615
10616
10617
10618
10619
10620
10621
10622
10623
10624
10625
10626
10627
10628
10629
10630
10631
10632
10633
10634
10635
10636
** into the second half to give some continuity.
*/
struct WhereInfo {
  Parse *pParse;       /* Parsing and code generating context */
  u16 wctrlFlags;      /* Flags originally passed to sqlite3WhereBegin() */
  u8 okOnePass;        /* Ok to use one-pass algorithm for UPDATE or DELETE */
  u8 untestedTerms;    /* Not all WHERE terms resolved by outer loop */
  u8 eDistinct;
  SrcList *pTabList;             /* List of tables in the join */
  int iTop;                      /* The very beginning of the WHERE loop */
  int iContinue;                 /* Jump here to continue with next record */
  int iBreak;                    /* Jump here to break out of the loop */
  int nLevel;                    /* Number of nested loop */
  struct WhereClause *pWC;       /* Decomposition of the WHERE clause */
  double savedNQueryLoop;        /* pParse->nQueryLoop outside the WHERE loop */
  double nRowOut;                /* Estimated number of output rows */
  WhereLevel a[1];               /* Information about each nest loop in WHERE */
};

#define WHERE_DISTINCT_UNIQUE 1
#define WHERE_DISTINCT_ORDERED 2

/*
** A NameContext defines a context in which to resolve table and column
** names.  The context consists of a list of tables (the pSrcList) field and
** a list of named expression (pEList).  The named expression list may
** be NULL.  The pSrc corresponds to the FROM clause of a SELECT or
** to the table being operated on by INSERT, UPDATE, or DELETE.  The
** pEList corresponds to the result set of a SELECT and is NULL for







<











<
<
<







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
** into the second half to give some continuity.
*/
struct WhereInfo {
  Parse *pParse;       /* Parsing and code generating context */
  u16 wctrlFlags;      /* Flags originally passed to sqlite3WhereBegin() */
  u8 okOnePass;        /* Ok to use one-pass algorithm for UPDATE or DELETE */
  u8 untestedTerms;    /* Not all WHERE terms resolved by outer loop */

  SrcList *pTabList;             /* List of tables in the join */
  int iTop;                      /* The very beginning of the WHERE loop */
  int iContinue;                 /* Jump here to continue with next record */
  int iBreak;                    /* Jump here to break out of the loop */
  int nLevel;                    /* Number of nested loop */
  struct WhereClause *pWC;       /* Decomposition of the WHERE clause */
  double savedNQueryLoop;        /* pParse->nQueryLoop outside the WHERE loop */
  double nRowOut;                /* Estimated number of output rows */
  WhereLevel a[1];               /* Information about each nest loop in WHERE */
};




/*
** A NameContext defines a context in which to resolve table and column
** names.  The context consists of a list of tables (the pSrcList) field and
** a list of named expression (pEList).  The named expression list may
** be NULL.  The pSrc corresponds to the FROM clause of a SELECT or
** to the table being operated on by INSERT, UPDATE, or DELETE.  The
** pEList corresponds to the result set of a SELECT and is NULL for
10708
10709
10710
10711
10712
10713
10714
10715
10716
10717
10718
10719
10720
10721
10722
*/
#define SF_Distinct        0x0001  /* Output should be DISTINCT */
#define SF_Resolved        0x0002  /* Identifiers have been resolved */
#define SF_Aggregate       0x0004  /* Contains aggregate functions */
#define SF_UsesEphemeral   0x0008  /* Uses the OpenEphemeral opcode */
#define SF_Expanded        0x0010  /* sqlite3SelectExpand() called on this */
#define SF_HasTypeInfo     0x0020  /* FROM subqueries have Table metadata */
#define SF_UseSorter       0x0040  /* Sort using a sorter */


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







<







10662
10663
10664
10665
10666
10667
10668

10669
10670
10671
10672
10673
10674
10675
*/
#define SF_Distinct        0x0001  /* Output should be DISTINCT */
#define SF_Resolved        0x0002  /* Identifiers have been resolved */
#define SF_Aggregate       0x0004  /* Contains aggregate functions */
#define SF_UsesEphemeral   0x0008  /* Uses the OpenEphemeral opcode */
#define SF_Expanded        0x0010  /* sqlite3SelectExpand() called on this */
#define SF_HasTypeInfo     0x0020  /* FROM subqueries have Table metadata */



/*
** 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 */
11385
11386
11387
11388
11389
11390
11391
11392
11393
11394
11395
11396
11397
11398
11399
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
SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**,ExprList*,u16);
SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*);
SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCachePush(Parse*);







|







11338
11339
11340
11341
11342
11343
11344
11345
11346
11347
11348
11349
11350
11351
11352
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
SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u16);
SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*);
SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCachePush(Parse*);
12035
12036
12037
12038
12039
12040
12041
12042
12043
12044
12045
12046
12047
12048
12049
*/
SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
   SQLITE_DEFAULT_MEMSTATUS,  /* bMemstat */
   1,                         /* bCoreMutex */
   SQLITE_THREADSAFE==1,      /* bFullMutex */
   SQLITE_USE_URI,            /* bOpenUri */
   0x7ffffffe,                /* mxStrlen */
   128,                       /* szLookaside */
   500,                       /* nLookaside */
   {0,0,0,0,0,0,0,0},         /* m */
   {0,0,0,0,0,0,0,0,0},       /* mutex */
   {0,0,0,0,0,0,0,0,0,0,0},   /* pcache */
   (void*)0,                  /* pHeap */
   0,                         /* nHeap */
   0, 0,                      /* mnHeap, mxHeap */







|







11988
11989
11990
11991
11992
11993
11994
11995
11996
11997
11998
11999
12000
12001
12002
*/
SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
   SQLITE_DEFAULT_MEMSTATUS,  /* bMemstat */
   1,                         /* bCoreMutex */
   SQLITE_THREADSAFE==1,      /* bFullMutex */
   SQLITE_USE_URI,            /* bOpenUri */
   0x7ffffffe,                /* mxStrlen */
   100,                       /* szLookaside */
   500,                       /* nLookaside */
   {0,0,0,0,0,0,0,0},         /* m */
   {0,0,0,0,0,0,0,0,0},       /* mutex */
   {0,0,0,0,0,0,0,0,0,0,0},   /* pcache */
   (void*)0,                  /* pHeap */
   0,                         /* nHeap */
   0, 0,                      /* mnHeap, mxHeap */
12258
12259
12260
12261
12262
12263
12264
12265
12266
12267
12268
12269
12270
12271
12272
12273
12274
#endif
#ifdef SQLITE_INT64_TYPE
  "INT64_TYPE",
#endif
#ifdef SQLITE_LOCK_TRACE
  "LOCK_TRACE",
#endif
#ifdef SQLITE_MAX_SCHEMA_RETRY
  "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
#endif
#ifdef SQLITE_MEMDEBUG
  "MEMDEBUG",
#endif
#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
  "MIXED_ENDIAN_64BIT_FLOAT",
#endif
#ifdef SQLITE_NO_SYNC







<
<
<







12211
12212
12213
12214
12215
12216
12217



12218
12219
12220
12221
12222
12223
12224
#endif
#ifdef SQLITE_INT64_TYPE
  "INT64_TYPE",
#endif
#ifdef SQLITE_LOCK_TRACE
  "LOCK_TRACE",
#endif



#ifdef SQLITE_MEMDEBUG
  "MEMDEBUG",
#endif
#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
  "MIXED_ENDIAN_64BIT_FLOAT",
#endif
#ifdef SQLITE_NO_SYNC
12374
12375
12376
12377
12378
12379
12380
12381
12382
12383
12384
12385
12386
12387
12388
12389
12390
#endif
#ifdef SQLITE_OMIT_LOOKASIDE
  "OMIT_LOOKASIDE",
#endif
#ifdef SQLITE_OMIT_MEMORYDB
  "OMIT_MEMORYDB",
#endif
#ifdef SQLITE_OMIT_MERGE_SORT
  "OMIT_MERGE_SORT",
#endif
#ifdef SQLITE_OMIT_OR_OPTIMIZATION
  "OMIT_OR_OPTIMIZATION",
#endif
#ifdef SQLITE_OMIT_PAGER_PRAGMAS
  "OMIT_PAGER_PRAGMAS",
#endif
#ifdef SQLITE_OMIT_PRAGMA







<
<
<







12324
12325
12326
12327
12328
12329
12330



12331
12332
12333
12334
12335
12336
12337
#endif
#ifdef SQLITE_OMIT_LOOKASIDE
  "OMIT_LOOKASIDE",
#endif
#ifdef SQLITE_OMIT_MEMORYDB
  "OMIT_MEMORYDB",
#endif



#ifdef SQLITE_OMIT_OR_OPTIMIZATION
  "OMIT_OR_OPTIMIZATION",
#endif
#ifdef SQLITE_OMIT_PAGER_PRAGMAS
  "OMIT_PAGER_PRAGMAS",
#endif
#ifdef SQLITE_OMIT_PRAGMA
12443
12444
12445
12446
12447
12448
12449
12450
12451
12452
12453
12454
12455
12456
12457
12458
12459
#endif
#ifdef SQLITE_OMIT_WSD
  "OMIT_WSD",
#endif
#ifdef SQLITE_OMIT_XFER_OPT
  "OMIT_XFER_OPT",
#endif
#ifdef SQLITE_PAGECACHE_BLOCKALLOC
  "PAGECACHE_BLOCKALLOC",
#endif
#ifdef SQLITE_PERFORMANCE_TRACE
  "PERFORMANCE_TRACE",
#endif
#ifdef SQLITE_PROXY_DEBUG
  "PROXY_DEBUG",
#endif
#ifdef SQLITE_SECURE_DELETE







<
<
<







12390
12391
12392
12393
12394
12395
12396



12397
12398
12399
12400
12401
12402
12403
#endif
#ifdef SQLITE_OMIT_WSD
  "OMIT_WSD",
#endif
#ifdef SQLITE_OMIT_XFER_OPT
  "OMIT_XFER_OPT",
#endif



#ifdef SQLITE_PERFORMANCE_TRACE
  "PERFORMANCE_TRACE",
#endif
#ifdef SQLITE_PROXY_DEBUG
  "PROXY_DEBUG",
#endif
#ifdef SQLITE_SECURE_DELETE
12566
12567
12568
12569
12570
12571
12572
12573
12574
12575
12576
12577
12578
12579
12580
12581
12582
typedef struct VdbeOp Op;

/*
** Boolean values
*/
typedef unsigned char Bool;

/* Opaque type used by code in vdbesort.c */
typedef struct VdbeSorter VdbeSorter;

/*
** A cursor is a pointer into a single BTree within a database file.
** The cursor can seek to a BTree entry with a particular key, or
** loop over all entries of the Btree.  You can also insert new BTree
** entries or retrieve the key or data from the entry that the cursor
** is currently pointing to.
** 







<
<
<







12510
12511
12512
12513
12514
12515
12516



12517
12518
12519
12520
12521
12522
12523
typedef struct VdbeOp Op;

/*
** Boolean values
*/
typedef unsigned char Bool;




/*
** A cursor is a pointer into a single BTree within a database file.
** The cursor can seek to a BTree entry with a particular key, or
** loop over all entries of the Btree.  You can also insert new BTree
** entries or retrieve the key or data from the entry that the cursor
** is currently pointing to.
** 
12595
12596
12597
12598
12599
12600
12601
12602
12603
12604
12605
12606
12607
12608
12609
12610
12611
12612
12613
12614
12615
  Bool atFirst;         /* True if pointing to first entry */
  Bool useRandomRowid;  /* Generate new record numbers semi-randomly */
  Bool nullRow;         /* True if pointing to a row with no data */
  Bool deferredMoveto;  /* A call to sqlite3BtreeMoveto() is needed */
  Bool isTable;         /* True if a table requiring integer keys */
  Bool isIndex;         /* True if an index containing keys only - no data */
  Bool isOrdered;       /* True if the underlying table is BTREE_UNORDERED */
  Bool isSorter;        /* True if a new-style sorter */
  sqlite3_vtab_cursor *pVtabCursor;  /* The cursor for a virtual table */
  const sqlite3_module *pModule;     /* Module for cursor pVtabCursor */
  i64 seqCount;         /* Sequence counter */
  i64 movetoTarget;     /* Argument to the deferred sqlite3BtreeMoveto() */
  i64 lastRowid;        /* Last rowid from a Next or NextIdx operation */
  VdbeSorter *pSorter;  /* Sorter object for OP_SorterOpen cursors */

  /* Result of last sqlite3BtreeMoveto() done by an OP_NotExists or 
  ** OP_IsUnique opcode on this cursor. */
  int seekResult;

  /* Cached information about the header for the data record that the
  ** cursor is currently pointing to.  Only valid if cacheStatus matches







<





<







12536
12537
12538
12539
12540
12541
12542

12543
12544
12545
12546
12547

12548
12549
12550
12551
12552
12553
12554
  Bool atFirst;         /* True if pointing to first entry */
  Bool useRandomRowid;  /* Generate new record numbers semi-randomly */
  Bool nullRow;         /* True if pointing to a row with no data */
  Bool deferredMoveto;  /* A call to sqlite3BtreeMoveto() is needed */
  Bool isTable;         /* True if a table requiring integer keys */
  Bool isIndex;         /* True if an index containing keys only - no data */
  Bool isOrdered;       /* True if the underlying table is BTREE_UNORDERED */

  sqlite3_vtab_cursor *pVtabCursor;  /* The cursor for a virtual table */
  const sqlite3_module *pModule;     /* Module for cursor pVtabCursor */
  i64 seqCount;         /* Sequence counter */
  i64 movetoTarget;     /* Argument to the deferred sqlite3BtreeMoveto() */
  i64 lastRowid;        /* Last rowid from a Next or NextIdx operation */


  /* Result of last sqlite3BtreeMoveto() done by an OP_NotExists or 
  ** OP_IsUnique opcode on this cursor. */
  int seekResult;

  /* Cached information about the header for the data record that the
  ** cursor is currently pointing to.  Only valid if cacheStatus matches
12921
12922
12923
12924
12925
12926
12927
12928
12929
12930
12931
12932
12933
12934
12935
12936
12937
12938
12939
12940
12941
12942
12943
12944
12945
12946
12947
12948
12949
12950
12951
12952
12953
12954
12955
12956
12957
12958
12959
12960
12961
12962
12963
SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem*);
SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*);
SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p);
SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p);
#define MemReleaseExt(X)  \
  if((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame)) \
    sqlite3VdbeMemReleaseExternal(X);
SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
SQLITE_PRIVATE const char *sqlite3OpcodeName(int);
SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int);
SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*);
SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *);
SQLITE_PRIVATE void sqlite3VdbeMemStoreType(Mem *pMem);

#ifdef SQLITE_OMIT_MERGE_SORT
# define sqlite3VdbeSorterInit(Y,Z)      SQLITE_OK
# define sqlite3VdbeSorterWrite(X,Y,Z)   SQLITE_OK
# define sqlite3VdbeSorterClose(Y,Z)
# define sqlite3VdbeSorterRowkey(Y,Z)    SQLITE_OK
# define sqlite3VdbeSorterRewind(X,Y,Z)  SQLITE_OK
# define sqlite3VdbeSorterNext(X,Y,Z)    SQLITE_OK
# define sqlite3VdbeSorterCompare(X,Y,Z) SQLITE_OK
#else
SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *);
SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(VdbeCursor *, Mem *);
SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, VdbeCursor *, int *);
SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *, VdbeCursor *, int *);
SQLITE_PRIVATE int sqlite3VdbeSorterWrite(sqlite3 *, VdbeCursor *, Mem *);
SQLITE_PRIVATE int sqlite3VdbeSorterCompare(VdbeCursor *, Mem *, int *);
#endif

#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
SQLITE_PRIVATE   void sqlite3VdbeEnter(Vdbe*);
SQLITE_PRIVATE   void sqlite3VdbeLeave(Vdbe*);
#else
# define sqlite3VdbeEnter(X)
# define sqlite3VdbeLeave(X)
#endif







<
<
<








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







12860
12861
12862
12863
12864
12865
12866



12867
12868
12869
12870
12871
12872
12873
12874


















12875
12876
12877
12878
12879
12880
12881
SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem*);
SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*);
SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p);
SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p);



SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
SQLITE_PRIVATE const char *sqlite3OpcodeName(int);
SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int);
SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*);
SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *);
SQLITE_PRIVATE void sqlite3VdbeMemStoreType(Mem *pMem);



















#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
SQLITE_PRIVATE   void sqlite3VdbeEnter(Vdbe*);
SQLITE_PRIVATE   void sqlite3VdbeLeave(Vdbe*);
#else
# define sqlite3VdbeEnter(X)
# define sqlite3VdbeLeave(X)
#endif
13243
13244
13245
13246
13247
13248
13249
13250
13251
13252
13253
13254
13255
13256
13257
13258
**
**      Jean Meeus
**      Astronomical Algorithms, 2nd Edition, 1998
**      ISBM 0-943396-61-1
**      Willmann-Bell, Inc
**      Richmond, Virginia (USA)
*/
/* #include <stdlib.h> */
/* #include <assert.h> */
#include <time.h>

#ifndef SQLITE_OMIT_DATETIME_FUNCS


/*
** A structure for holding a single date and time.







<
<







13161
13162
13163
13164
13165
13166
13167


13168
13169
13170
13171
13172
13173
13174
**
**      Jean Meeus
**      Astronomical Algorithms, 2nd Edition, 1998
**      ISBM 0-943396-61-1
**      Willmann-Bell, Inc
**      Richmond, Virginia (USA)
*/


#include <time.h>

#ifndef SQLITE_OMIT_DATETIME_FUNCS


/*
** A structure for holding a single date and time.
13626
13627
13628
13629
13630
13631
13632
13633
13634
13635
13636
13637
13638
13639
13640
13641
13642
** routine will always fail.
*/
static int osLocaltime(time_t *t, struct tm *pTm){
  int rc;
#if (!defined(HAVE_LOCALTIME_R) || !HAVE_LOCALTIME_R) \
      && (!defined(HAVE_LOCALTIME_S) || !HAVE_LOCALTIME_S)
  struct tm *pX;
#if SQLITE_THREADSAFE>0
  sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
  sqlite3_mutex_enter(mutex);
  pX = localtime(t);
#ifndef SQLITE_OMIT_BUILTIN_TEST
  if( sqlite3GlobalConfig.bLocaltimeFault ) pX = 0;
#endif
  if( pX ) *pTm = *pX;
  sqlite3_mutex_leave(mutex);







<

<







13542
13543
13544
13545
13546
13547
13548

13549

13550
13551
13552
13553
13554
13555
13556
** routine will always fail.
*/
static int osLocaltime(time_t *t, struct tm *pTm){
  int rc;
#if (!defined(HAVE_LOCALTIME_R) || !HAVE_LOCALTIME_R) \
      && (!defined(HAVE_LOCALTIME_S) || !HAVE_LOCALTIME_S)
  struct tm *pX;

  sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);

  sqlite3_mutex_enter(mutex);
  pX = localtime(t);
#ifndef SQLITE_OMIT_BUILTIN_TEST
  if( sqlite3GlobalConfig.bLocaltimeFault ) pX = 0;
#endif
  if( pX ) *pTm = *pX;
  sqlite3_mutex_leave(mutex);
14462
14463
14464
14465
14466
14467
14468
14469
14470
14471
14472
14473
14474
14475
14476
){
  int rc;
  DO_OS_MALLOC_TEST(0);
  /* 0x87f3f is a mask of SQLITE_OPEN_ flags that are valid to be passed
  ** down into the VFS layer.  Some SQLITE_OPEN_ flags (for example,
  ** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before
  ** reaching the VFS. */
  rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f7f, pFlagsOut);
  assert( rc==SQLITE_OK || pFile->pMethods==0 );
  return rc;
}
SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
  return pVfs->xDelete(pVfs, zPath, dirSync);
}
SQLITE_PRIVATE int sqlite3OsAccess(







|







14376
14377
14378
14379
14380
14381
14382
14383
14384
14385
14386
14387
14388
14389
14390
){
  int rc;
  DO_OS_MALLOC_TEST(0);
  /* 0x87f3f is a mask of SQLITE_OPEN_ flags that are valid to be passed
  ** down into the VFS layer.  Some SQLITE_OPEN_ flags (for example,
  ** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before
  ** reaching the VFS. */
  rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f3f, pFlagsOut);
  assert( rc==SQLITE_OK || pFile->pMethods==0 );
  return rc;
}
SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
  return pVfs->xDelete(pVfs, zPath, dirSync);
}
SQLITE_PRIVATE int sqlite3OsAccess(
14534
14535
14536
14537
14538
14539
14540
14541
14542
14543
14544
14545
14546
14547
14548
  const char *zFile, 
  sqlite3_file **ppFile, 
  int flags,
  int *pOutFlags
){
  int rc = SQLITE_NOMEM;
  sqlite3_file *pFile;
  pFile = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile);
  if( pFile ){
    rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags);
    if( rc!=SQLITE_OK ){
      sqlite3_free(pFile);
    }else{
      *ppFile = pFile;
    }







|







14448
14449
14450
14451
14452
14453
14454
14455
14456
14457
14458
14459
14460
14461
14462
  const char *zFile, 
  sqlite3_file **ppFile, 
  int flags,
  int *pOutFlags
){
  int rc = SQLITE_NOMEM;
  sqlite3_file *pFile;
  pFile = (sqlite3_file *)sqlite3Malloc(pVfs->szOsFile);
  if( pFile ){
    rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags);
    if( rc!=SQLITE_OK ){
      sqlite3_free(pFile);
    }else{
      *ppFile = pFile;
    }
14998
14999
15000
15001
15002
15003
15004
15005
15006
15007
15008
15009
15010
15011
15012
#ifdef __GLIBC__
  extern int backtrace(void**,int);
  extern void backtrace_symbols_fd(void*const*,int,int);
#else
# define backtrace(A,B) 1
# define backtrace_symbols_fd(A,B,C)
#endif
/* #include <stdio.h> */

/*
** Each memory allocation looks like this:
**
**  ------------------------------------------------------------------------
**  | Title |  backtrace pointers |  MemBlockHdr |  allocation |  EndGuard |
**  ------------------------------------------------------------------------







<







14912
14913
14914
14915
14916
14917
14918

14919
14920
14921
14922
14923
14924
14925
#ifdef __GLIBC__
  extern int backtrace(void**,int);
  extern void backtrace_symbols_fd(void*const*,int,int);
#else
# define backtrace(A,B) 1
# define backtrace_symbols_fd(A,B,C)
#endif


/*
** Each memory allocation looks like this:
**
**  ------------------------------------------------------------------------
**  | Title |  backtrace pointers |  MemBlockHdr |  allocation |  EndGuard |
**  ------------------------------------------------------------------------
15924
15925
15926
15927
15928
15929
15930
15931
15932
15933
15934
15935
15936
15937
15938

/*
** Free an outstanding memory allocation.
**
** This function assumes that the necessary mutexes, if any, are
** already held by the caller. Hence "Unsafe".
*/
static void memsys3FreeUnsafe(void *pOld){
  Mem3Block *p = (Mem3Block*)pOld;
  int i;
  u32 size, x;
  assert( sqlite3_mutex_held(mem3.mutex) );
  assert( p>mem3.aPool && p<&mem3.aPool[mem3.nPool] );
  i = p - mem3.aPool;
  assert( (mem3.aPool[i-1].u.hdr.size4x&1)==1 );







|







15837
15838
15839
15840
15841
15842
15843
15844
15845
15846
15847
15848
15849
15850
15851

/*
** Free an outstanding memory allocation.
**
** This function assumes that the necessary mutexes, if any, are
** already held by the caller. Hence "Unsafe".
*/
void memsys3FreeUnsafe(void *pOld){
  Mem3Block *p = (Mem3Block*)pOld;
  int i;
  u32 size, x;
  assert( sqlite3_mutex_held(mem3.mutex) );
  assert( p>mem3.aPool && p<&mem3.aPool[mem3.nPool] );
  i = p - mem3.aPool;
  assert( (mem3.aPool[i-1].u.hdr.size4x&1)==1 );
15999
16000
16001
16002
16003
16004
16005
16006
16007
16008
16009
16010
16011
16012
16013
16014
16015
16016
16017
16018
16019
16020
16021
16022
16023
  memsys3Leave();
  return (void*)p; 
}

/*
** Free memory.
*/
static void memsys3Free(void *pPrior){
  assert( pPrior );
  memsys3Enter();
  memsys3FreeUnsafe(pPrior);
  memsys3Leave();
}

/*
** Change the size of an existing memory allocation
*/
static void *memsys3Realloc(void *pPrior, int nBytes){
  int nOld;
  void *p;
  if( pPrior==0 ){
    return sqlite3_malloc(nBytes);
  }
  if( nBytes<=0 ){
    sqlite3_free(pPrior);







|









|







15912
15913
15914
15915
15916
15917
15918
15919
15920
15921
15922
15923
15924
15925
15926
15927
15928
15929
15930
15931
15932
15933
15934
15935
15936
  memsys3Leave();
  return (void*)p; 
}

/*
** Free memory.
*/
void memsys3Free(void *pPrior){
  assert( pPrior );
  memsys3Enter();
  memsys3FreeUnsafe(pPrior);
  memsys3Leave();
}

/*
** Change the size of an existing memory allocation
*/
void *memsys3Realloc(void *pPrior, int nBytes){
  int nOld;
  void *p;
  if( pPrior==0 ){
    return sqlite3_malloc(nBytes);
  }
  if( nBytes<=0 ){
    sqlite3_free(pPrior);
18102
18103
18104
18105
18106
18107
18108
18109
18110
18111
18112
18113
18114
18115
18116
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** Memory allocation functions used throughout sqlite.
*/
/* #include <stdarg.h> */

/*
** Attempt to release up to n bytes of non-essential memory currently
** held by SQLite. An example of non-essential memory is memory used to
** cache database pages that are not currently in use.
*/
SQLITE_API int sqlite3_release_memory(int n){







<







18015
18016
18017
18018
18019
18020
18021

18022
18023
18024
18025
18026
18027
18028
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** Memory allocation functions used throughout sqlite.
*/


/*
** Attempt to release up to n bytes of non-essential memory currently
** held by SQLite. An example of non-essential memory is memory used to
** cache database pages that are not currently in use.
*/
SQLITE_API int sqlite3_release_memory(int n){
20080
20081
20082
20083
20084
20085
20086
20087
20088
20089
20090
20091
20092
20093
20094
**
**
** BOM or Byte Order Mark:
**     0xff 0xfe   little-endian utf-16 follows
**     0xfe 0xff   big-endian utf-16 follows
**
*/
/* #include <assert.h> */

#ifndef SQLITE_AMALGAMATION
/*
** The following constant value is used by the SQLITE_BIGENDIAN and
** SQLITE_LITTLEENDIAN macros.
*/
SQLITE_PRIVATE const int sqlite3one = 1;







<







19992
19993
19994
19995
19996
19997
19998

19999
20000
20001
20002
20003
20004
20005
**
**
** BOM or Byte Order Mark:
**     0xff 0xfe   little-endian utf-16 follows
**     0xfe 0xff   big-endian utf-16 follows
**
*/


#ifndef SQLITE_AMALGAMATION
/*
** The following constant value is used by the SQLITE_BIGENDIAN and
** SQLITE_LITTLEENDIAN macros.
*/
SQLITE_PRIVATE const int sqlite3one = 1;
20623
20624
20625
20626
20627
20628
20629
20630
20631
20632
20633
20634
20635
20636
20637
*************************************************************************
** Utility functions used throughout sqlite.
**
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
*/
/* #include <stdarg.h> */
#ifdef SQLITE_HAVE_ISNAN
# include <math.h>
#endif

/*
** Routine needed to support the testcase() macro.
*/







<







20534
20535
20536
20537
20538
20539
20540

20541
20542
20543
20544
20545
20546
20547
*************************************************************************
** Utility functions used throughout sqlite.
**
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
*/

#ifdef SQLITE_HAVE_ISNAN
# include <math.h>
#endif

/*
** Routine needed to support the testcase() macro.
*/
21756
21757
21758
21759
21760
21761
21762
21763
21764
21765
21766
21767
21768
21769
21770
21771
21772
21773
21774
21775
21776
21777
21778
21779
21780
21781
21782
21783
21784
21785
21786
21787
21788
21789
21790
21791
  if( x>=0 ) return x;
  if( x==(int)0x80000000 ) return 0x7fffffff;
  return -x;
}

#ifdef SQLITE_ENABLE_8_3_NAMES
/*
** If SQLITE_ENABLE_8_3_NAMES is set at compile-time and if the database
** filename in zBaseFilename is a URI with the "8_3_names=1" parameter and
** if filename in z[] has a suffix (a.k.a. "extension") that is longer than
** three characters, then shorten the suffix on z[] to be the last three
** characters of the original suffix.
**
** If SQLITE_ENABLE_8_3_NAMES is set to 2 at compile-time, then always
** do the suffix shortening regardless of URI parameter.
**
** Examples:
**
**     test.db-journal    =>   test.nal
**     test.db-wal        =>   test.wal
**     test.db-shm        =>   test.shm
*/
SQLITE_PRIVATE void sqlite3FileSuffix3(const char *zBaseFilename, char *z){
#if SQLITE_ENABLE_8_3_NAMES<2
  const char *zOk;
  zOk = sqlite3_uri_parameter(zBaseFilename, "8_3_names");
  if( zOk && sqlite3GetBoolean(zOk) )
#endif
  {
    int i, sz;
    sz = sqlite3Strlen30(z);
    for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
    if( z[i]=='.' && ALWAYS(sz>i+4) ) memcpy(&z[i+1], &z[sz-3], 4);
  }
}
#endif







|





<
<
<







<


|
<
<







21666
21667
21668
21669
21670
21671
21672
21673
21674
21675
21676
21677
21678



21679
21680
21681
21682
21683
21684
21685

21686
21687
21688


21689
21690
21691
21692
21693
21694
21695
  if( x>=0 ) return x;
  if( x==(int)0x80000000 ) return 0x7fffffff;
  return -x;
}

#ifdef SQLITE_ENABLE_8_3_NAMES
/*
** If SQLITE_ENABLE_8_3_NAME is set at compile-time and if the database
** filename in zBaseFilename is a URI with the "8_3_names=1" parameter and
** if filename in z[] has a suffix (a.k.a. "extension") that is longer than
** three characters, then shorten the suffix on z[] to be the last three
** characters of the original suffix.
**



** Examples:
**
**     test.db-journal    =>   test.nal
**     test.db-wal        =>   test.wal
**     test.db-shm        =>   test.shm
*/
SQLITE_PRIVATE void sqlite3FileSuffix3(const char *zBaseFilename, char *z){

  const char *zOk;
  zOk = sqlite3_uri_parameter(zBaseFilename, "8_3_names");
  if( zOk && sqlite3GetBoolean(zOk) ){


    int i, sz;
    sz = sqlite3Strlen30(z);
    for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
    if( z[i]=='.' && ALWAYS(sz>i+4) ) memcpy(&z[i+1], &z[sz-3], 4);
  }
}
#endif
21802
21803
21804
21805
21806
21807
21808
21809
21810
21811
21812
21813
21814
21815
21816
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This is the implementation of generic hash-tables
** used in SQLite.
*/
/* #include <assert.h> */

/* Turn bulk memory into a hash table object by initializing the
** fields of the Hash structure.
**
** "pNew" is a pointer to the hash table that is to be initialized.
*/
SQLITE_PRIVATE void sqlite3HashInit(Hash *pNew){







<







21706
21707
21708
21709
21710
21711
21712

21713
21714
21715
21716
21717
21718
21719
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This is the implementation of generic hash-tables
** used in SQLite.
*/


/* Turn bulk memory into a hash table object by initializing the
** fields of the Hash structure.
**
** "pNew" is a pointer to the hash table that is to be initialized.
*/
SQLITE_PRIVATE void sqlite3HashInit(Hash *pNew){
22097
22098
22099
22100
22101
22102
22103
22104
22105
22106
22107
22108
22109
22110
22111
22112
22113
22114
22115
22116
22117
22118
22119
22120
22121
22122
22123
22124
22125
22126
22127
22128
22129
22130
22131
22132
22133
22134
22135
22136
22137
22138
22139
22140
22141
22142
22143
22144
22145
22146
22147
22148
22149
22150
22151
22152
22153
22154
22155
22156
22157
22158
22159
22160
22161
22162
22163
22164
22165
22166
22167
22168
22169
22170
22171
22172
22173
22174
22175
22176
22177
22178
22179
22180
22181
22182
22183
22184
22185
22186
22187
22188
22189
22190
22191
22192
22193
22194
22195
22196
22197
22198
22199
22200
22201
22202
22203
22204
22205
22206
22207
22208
22209
22210
22211
22212
22213
22214
22215
22216
22217
22218
22219
22220
22221
22222
22223
22224
22225
22226
22227
22228
22229
22230
22231
22232
22233
22234
22235
     /*  19 */ "Not",
     /*  20 */ "AddImm",
     /*  21 */ "MustBeInt",
     /*  22 */ "RealAffinity",
     /*  23 */ "Permutation",
     /*  24 */ "Compare",
     /*  25 */ "Jump",
     /*  26 */ "Once",
     /*  27 */ "If",
     /*  28 */ "IfNot",
     /*  29 */ "Column",
     /*  30 */ "Affinity",
     /*  31 */ "MakeRecord",
     /*  32 */ "Count",
     /*  33 */ "Savepoint",
     /*  34 */ "AutoCommit",
     /*  35 */ "Transaction",
     /*  36 */ "ReadCookie",
     /*  37 */ "SetCookie",
     /*  38 */ "VerifyCookie",
     /*  39 */ "OpenRead",
     /*  40 */ "OpenWrite",
     /*  41 */ "OpenAutoindex",
     /*  42 */ "OpenEphemeral",
     /*  43 */ "SorterOpen",
     /*  44 */ "OpenPseudo",
     /*  45 */ "Close",
     /*  46 */ "SeekLt",
     /*  47 */ "SeekLe",
     /*  48 */ "SeekGe",
     /*  49 */ "SeekGt",
     /*  50 */ "Seek",
     /*  51 */ "NotFound",
     /*  52 */ "Found",
     /*  53 */ "IsUnique",
     /*  54 */ "NotExists",
     /*  55 */ "Sequence",
     /*  56 */ "NewRowid",
     /*  57 */ "Insert",
     /*  58 */ "InsertInt",
     /*  59 */ "Delete",
     /*  60 */ "ResetCount",
     /*  61 */ "SorterCompare",
     /*  62 */ "SorterData",
     /*  63 */ "RowKey",
     /*  64 */ "RowData",
     /*  65 */ "Rowid",
     /*  66 */ "NullRow",
     /*  67 */ "Last",
     /*  68 */ "Or",
     /*  69 */ "And",
     /*  70 */ "SorterSort",
     /*  71 */ "Sort",
     /*  72 */ "Rewind",
     /*  73 */ "IsNull",
     /*  74 */ "NotNull",
     /*  75 */ "Ne",
     /*  76 */ "Eq",
     /*  77 */ "Gt",
     /*  78 */ "Le",
     /*  79 */ "Lt",
     /*  80 */ "Ge",
     /*  81 */ "SorterNext",
     /*  82 */ "BitAnd",
     /*  83 */ "BitOr",
     /*  84 */ "ShiftLeft",
     /*  85 */ "ShiftRight",
     /*  86 */ "Add",
     /*  87 */ "Subtract",
     /*  88 */ "Multiply",
     /*  89 */ "Divide",
     /*  90 */ "Remainder",
     /*  91 */ "Concat",
     /*  92 */ "Prev",
     /*  93 */ "BitNot",
     /*  94 */ "String8",
     /*  95 */ "Next",
     /*  96 */ "SorterInsert",
     /*  97 */ "IdxInsert",
     /*  98 */ "IdxDelete",
     /*  99 */ "IdxRowid",
     /* 100 */ "IdxLT",
     /* 101 */ "IdxGE",
     /* 102 */ "Destroy",
     /* 103 */ "Clear",
     /* 104 */ "CreateIndex",
     /* 105 */ "CreateTable",
     /* 106 */ "ParseSchema",
     /* 107 */ "LoadAnalysis",
     /* 108 */ "DropTable",
     /* 109 */ "DropIndex",
     /* 110 */ "DropTrigger",
     /* 111 */ "IntegrityCk",
     /* 112 */ "RowSetAdd",
     /* 113 */ "RowSetRead",
     /* 114 */ "RowSetTest",
     /* 115 */ "Program",
     /* 116 */ "Param",
     /* 117 */ "FkCounter",
     /* 118 */ "FkIfZero",
     /* 119 */ "MemMax",
     /* 120 */ "IfPos",
     /* 121 */ "IfNeg",
     /* 122 */ "IfZero",
     /* 123 */ "AggStep",
     /* 124 */ "AggFinal",
     /* 125 */ "Checkpoint",
     /* 126 */ "JournalMode",
     /* 127 */ "Vacuum",
     /* 128 */ "IncrVacuum",
     /* 129 */ "Expire",
     /* 130 */ "Real",
     /* 131 */ "TableLock",
     /* 132 */ "VBegin",
     /* 133 */ "VCreate",
     /* 134 */ "VDestroy",
     /* 135 */ "VOpen",
     /* 136 */ "VFilter",
     /* 137 */ "VColumn",
     /* 138 */ "VNext",
     /* 139 */ "VRename",
     /* 140 */ "VUpdate",
     /* 141 */ "ToText",
     /* 142 */ "ToBlob",
     /* 143 */ "ToNumeric",
     /* 144 */ "ToInt",
     /* 145 */ "ToReal",
     /* 146 */ "Pagecount",
     /* 147 */ "MaxPgcnt",
     /* 148 */ "Trace",
     /* 149 */ "Noop",
     /* 150 */ "Explain",
  };
  return azName[i];
}
#endif

/************** End of opcodes.c *********************************************/
/************** Begin file os_os2.c ******************************************/







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|


|
|
|








|










|


|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|





<
<
<
<
<







22000
22001
22002
22003
22004
22005
22006
22007
22008
22009
22010
22011
22012
22013
22014
22015
22016
22017
22018
22019
22020
22021
22022
22023
22024
22025
22026
22027
22028
22029
22030
22031
22032
22033
22034
22035
22036
22037
22038
22039
22040
22041
22042
22043
22044
22045
22046
22047
22048
22049
22050
22051
22052
22053
22054
22055
22056
22057
22058
22059
22060
22061
22062
22063
22064
22065
22066
22067
22068
22069
22070
22071
22072
22073
22074
22075
22076
22077
22078
22079
22080
22081
22082
22083
22084
22085
22086
22087
22088
22089
22090
22091
22092
22093
22094
22095
22096
22097
22098
22099
22100
22101
22102
22103
22104
22105
22106
22107
22108
22109
22110
22111
22112
22113
22114
22115
22116
22117
22118
22119
22120
22121
22122
22123
22124
22125
22126





22127
22128
22129
22130
22131
22132
22133
     /*  19 */ "Not",
     /*  20 */ "AddImm",
     /*  21 */ "MustBeInt",
     /*  22 */ "RealAffinity",
     /*  23 */ "Permutation",
     /*  24 */ "Compare",
     /*  25 */ "Jump",
     /*  26 */ "If",
     /*  27 */ "IfNot",
     /*  28 */ "Column",
     /*  29 */ "Affinity",
     /*  30 */ "MakeRecord",
     /*  31 */ "Count",
     /*  32 */ "Savepoint",
     /*  33 */ "AutoCommit",
     /*  34 */ "Transaction",
     /*  35 */ "ReadCookie",
     /*  36 */ "SetCookie",
     /*  37 */ "VerifyCookie",
     /*  38 */ "OpenRead",
     /*  39 */ "OpenWrite",
     /*  40 */ "OpenAutoindex",
     /*  41 */ "OpenEphemeral",
     /*  42 */ "OpenPseudo",
     /*  43 */ "Close",
     /*  44 */ "SeekLt",
     /*  45 */ "SeekLe",
     /*  46 */ "SeekGe",
     /*  47 */ "SeekGt",
     /*  48 */ "Seek",
     /*  49 */ "NotFound",
     /*  50 */ "Found",
     /*  51 */ "IsUnique",
     /*  52 */ "NotExists",
     /*  53 */ "Sequence",
     /*  54 */ "NewRowid",
     /*  55 */ "Insert",
     /*  56 */ "InsertInt",
     /*  57 */ "Delete",
     /*  58 */ "ResetCount",
     /*  59 */ "RowKey",
     /*  60 */ "RowData",
     /*  61 */ "Rowid",
     /*  62 */ "NullRow",
     /*  63 */ "Last",
     /*  64 */ "Sort",
     /*  65 */ "Rewind",
     /*  66 */ "Prev",
     /*  67 */ "Next",
     /*  68 */ "Or",
     /*  69 */ "And",
     /*  70 */ "IdxInsert",
     /*  71 */ "IdxDelete",
     /*  72 */ "IdxRowid",
     /*  73 */ "IsNull",
     /*  74 */ "NotNull",
     /*  75 */ "Ne",
     /*  76 */ "Eq",
     /*  77 */ "Gt",
     /*  78 */ "Le",
     /*  79 */ "Lt",
     /*  80 */ "Ge",
     /*  81 */ "IdxLT",
     /*  82 */ "BitAnd",
     /*  83 */ "BitOr",
     /*  84 */ "ShiftLeft",
     /*  85 */ "ShiftRight",
     /*  86 */ "Add",
     /*  87 */ "Subtract",
     /*  88 */ "Multiply",
     /*  89 */ "Divide",
     /*  90 */ "Remainder",
     /*  91 */ "Concat",
     /*  92 */ "IdxGE",
     /*  93 */ "BitNot",
     /*  94 */ "String8",
     /*  95 */ "Destroy",
     /*  96 */ "Clear",
     /*  97 */ "CreateIndex",
     /*  98 */ "CreateTable",
     /*  99 */ "ParseSchema",
     /* 100 */ "LoadAnalysis",
     /* 101 */ "DropTable",
     /* 102 */ "DropIndex",
     /* 103 */ "DropTrigger",
     /* 104 */ "IntegrityCk",
     /* 105 */ "RowSetAdd",
     /* 106 */ "RowSetRead",
     /* 107 */ "RowSetTest",
     /* 108 */ "Program",
     /* 109 */ "Param",
     /* 110 */ "FkCounter",
     /* 111 */ "FkIfZero",
     /* 112 */ "MemMax",
     /* 113 */ "IfPos",
     /* 114 */ "IfNeg",
     /* 115 */ "IfZero",
     /* 116 */ "AggStep",
     /* 117 */ "AggFinal",
     /* 118 */ "Checkpoint",
     /* 119 */ "JournalMode",
     /* 120 */ "Vacuum",
     /* 121 */ "IncrVacuum",
     /* 122 */ "Expire",
     /* 123 */ "TableLock",
     /* 124 */ "VBegin",
     /* 125 */ "VCreate",
     /* 126 */ "VDestroy",
     /* 127 */ "VOpen",
     /* 128 */ "VFilter",
     /* 129 */ "VColumn",
     /* 130 */ "Real",
     /* 131 */ "VNext",
     /* 132 */ "VRename",
     /* 133 */ "VUpdate",
     /* 134 */ "Pagecount",
     /* 135 */ "MaxPgcnt",
     /* 136 */ "Trace",
     /* 137 */ "Noop",
     /* 138 */ "Explain",
     /* 139 */ "NotUsed_139",
     /* 140 */ "NotUsed_140",
     /* 141 */ "ToText",
     /* 142 */ "ToBlob",
     /* 143 */ "ToNumeric",
     /* 144 */ "ToInt",
     /* 145 */ "ToReal",





  };
  return azName[i];
}
#endif

/************** End of opcodes.c *********************************************/
/************** Begin file os_os2.c ******************************************/
22316
22317
22318
22319
22320
22321
22322
22323
22324
22325
22326
22327
22328
22329
22330
22331
22332
22333
22334
22335
22336
22337
** macro to SQLITE_DEBUG and some older makefiles have not yet made the
** switch.  The following code should catch this problem at compile-time.
*/
#ifdef MEMORY_DEBUG
# error "The MEMORY_DEBUG macro is obsolete.  Use SQLITE_DEBUG instead."
#endif

#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
# ifndef SQLITE_DEBUG_OS_TRACE
#   define SQLITE_DEBUG_OS_TRACE 0
# endif
  int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
# define OSTRACE(X)          if( sqlite3OSTrace ) sqlite3DebugPrintf X
#else
# define OSTRACE(X)
#endif

/*
** Macros for performance tracing.  Normally turned off.  Only works
** on i486 hardware.
*/
#ifdef SQLITE_PERFORMANCE_TRACE







<
|
<
<
|
|

|







22214
22215
22216
22217
22218
22219
22220

22221


22222
22223
22224
22225
22226
22227
22228
22229
22230
22231
22232
** macro to SQLITE_DEBUG and some older makefiles have not yet made the
** switch.  The following code should catch this problem at compile-time.
*/
#ifdef MEMORY_DEBUG
# error "The MEMORY_DEBUG macro is obsolete.  Use SQLITE_DEBUG instead."
#endif


#ifdef SQLITE_DEBUG


SQLITE_PRIVATE int sqlite3OSTrace = 0;
#define OSTRACE(X)          if( sqlite3OSTrace ) sqlite3DebugPrintf X
#else
#define OSTRACE(X)
#endif

/*
** Macros for performance tracing.  Normally turned off.  Only works
** on i486 hardware.
*/
#ifdef SQLITE_PERFORMANCE_TRACE
24480
24481
24482
24483
24484
24485
24486
24487
24488
24489
24490
24491
24492
24493
24494
/*
** standard include files.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
/* #include <time.h> */
#include <sys/time.h>
#include <errno.h>
#ifndef SQLITE_OMIT_WAL
#include <sys/mman.h>
#endif

#if SQLITE_ENABLE_LOCKING_STYLE







<







24375
24376
24377
24378
24379
24380
24381

24382
24383
24384
24385
24386
24387
24388
/*
** standard include files.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#include <sys/time.h>
#include <errno.h>
#ifndef SQLITE_OMIT_WAL
#include <sys/mman.h>
#endif

#if SQLITE_ENABLE_LOCKING_STYLE
24516
24517
24518
24519
24520
24521
24522
24523
24524
24525
24526
24527
24528
24529
24530
#define SQLITE_FSFLAGS_IS_MSDOS     0x1

/*
** If we are to be thread-safe, include the pthreads header and define
** the SQLITE_UNIX_THREADS macro.
*/
#if SQLITE_THREADSAFE
/* # include <pthread.h> */
# define SQLITE_UNIX_THREADS 1
#endif

/*
** Default permissions when creating a new file
*/
#ifndef SQLITE_DEFAULT_FILE_PERMISSIONS







<







24410
24411
24412
24413
24414
24415
24416

24417
24418
24419
24420
24421
24422
24423
#define SQLITE_FSFLAGS_IS_MSDOS     0x1

/*
** If we are to be thread-safe, include the pthreads header and define
** the SQLITE_UNIX_THREADS macro.
*/
#if SQLITE_THREADSAFE

# define SQLITE_UNIX_THREADS 1
#endif

/*
** Default permissions when creating a new file
*/
#ifndef SQLITE_DEFAULT_FILE_PERMISSIONS
24572
24573
24574
24575
24576
24577
24578

24579
24580
24581
24582
24583
24584
24585
** VFS implementations.
*/
typedef struct unixFile unixFile;
struct unixFile {
  sqlite3_io_methods const *pMethod;  /* Always the first entry */
  unixInodeInfo *pInode;              /* Info about locks on this inode */
  int h;                              /* The file descriptor */

  unsigned char eFileLock;            /* The type of lock held on this fd */
  unsigned char ctrlFlags;            /* Behavioral bits.  UNIXFILE_* flags */
  int lastErrno;                      /* The unix errno from last I/O error */
  void *lockingContext;               /* Locking style specific state */
  UnixUnusedFd *pUnused;              /* Pre-allocated UnixUnusedFd */
  const char *zPath;                  /* Name of the file */
  unixShm *pShm;                      /* Shared memory segment information */







>







24465
24466
24467
24468
24469
24470
24471
24472
24473
24474
24475
24476
24477
24478
24479
** VFS implementations.
*/
typedef struct unixFile unixFile;
struct unixFile {
  sqlite3_io_methods const *pMethod;  /* Always the first entry */
  unixInodeInfo *pInode;              /* Info about locks on this inode */
  int h;                              /* The file descriptor */
  int dirfd;                          /* File descriptor for the directory */
  unsigned char eFileLock;            /* The type of lock held on this fd */
  unsigned char ctrlFlags;            /* Behavioral bits.  UNIXFILE_* flags */
  int lastErrno;                      /* The unix errno from last I/O error */
  void *lockingContext;               /* Locking style specific state */
  UnixUnusedFd *pUnused;              /* Pre-allocated UnixUnusedFd */
  const char *zPath;                  /* Name of the file */
  unixShm *pShm;                      /* Shared memory segment information */
24613
24614
24615
24616
24617
24618
24619
24620
24621
24622
24623
24624
24625
24626
24627
24628
24629
24630
24631
24632
24633
24634
  char aPadding[32];
#endif
};

/*
** Allowed values for the unixFile.ctrlFlags bitmask:
*/
#define UNIXFILE_EXCL        0x01     /* Connections from one process only */
#define UNIXFILE_RDONLY      0x02     /* Connection is read only */
#define UNIXFILE_PERSIST_WAL 0x04     /* Persistent WAL mode */
#ifndef SQLITE_DISABLE_DIRSYNC
# define UNIXFILE_DIRSYNC    0x08     /* Directory sync needed */
#else
# define UNIXFILE_DIRSYNC    0x00
#endif

/*
** Include code that is common to all os_*.c files
*/
/************** Include os_common.h in the middle of os_unix.c ***************/
/************** Begin file os_common.h ***************************************/
/*







|
|
<
<
<
<
<
<







24507
24508
24509
24510
24511
24512
24513
24514
24515






24516
24517
24518
24519
24520
24521
24522
  char aPadding[32];
#endif
};

/*
** Allowed values for the unixFile.ctrlFlags bitmask:
*/
#define UNIXFILE_EXCL   0x01     /* Connections from one process only */
#define UNIXFILE_RDONLY 0x02     /* Connection is read only */







/*
** Include code that is common to all os_*.c files
*/
/************** Include os_common.h in the middle of os_unix.c ***************/
/************** Begin file os_common.h ***************************************/
/*
24658
24659
24660
24661
24662
24663
24664
24665
24666
24667
24668
24669
24670
24671
24672
24673
24674
24675
24676
24677
24678
24679
** macro to SQLITE_DEBUG and some older makefiles have not yet made the
** switch.  The following code should catch this problem at compile-time.
*/
#ifdef MEMORY_DEBUG
# error "The MEMORY_DEBUG macro is obsolete.  Use SQLITE_DEBUG instead."
#endif

#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
# ifndef SQLITE_DEBUG_OS_TRACE
#   define SQLITE_DEBUG_OS_TRACE 0
# endif
  int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
# define OSTRACE(X)          if( sqlite3OSTrace ) sqlite3DebugPrintf X
#else
# define OSTRACE(X)
#endif

/*
** Macros for performance tracing.  Normally turned off.  Only works
** on i486 hardware.
*/
#ifdef SQLITE_PERFORMANCE_TRACE







<
|
<
<
|
|

|







24546
24547
24548
24549
24550
24551
24552

24553


24554
24555
24556
24557
24558
24559
24560
24561
24562
24563
24564
** macro to SQLITE_DEBUG and some older makefiles have not yet made the
** switch.  The following code should catch this problem at compile-time.
*/
#ifdef MEMORY_DEBUG
# error "The MEMORY_DEBUG macro is obsolete.  Use SQLITE_DEBUG instead."
#endif


#ifdef SQLITE_DEBUG


SQLITE_PRIVATE int sqlite3OSTrace = 0;
#define OSTRACE(X)          if( sqlite3OSTrace ) sqlite3DebugPrintf X
#else
#define OSTRACE(X)
#endif

/*
** Macros for performance tracing.  Normally turned off.  Only works
** on i486 hardware.
*/
#ifdef SQLITE_PERFORMANCE_TRACE
24874
24875
24876
24877
24878
24879
24880
24881
24882
24883
24884
24885
24886
24887
24888
24889
24890
** The safest way to deal with the problem is to always use this wrapper
** which always has the same well-defined interface.
*/
static int posixOpen(const char *zFile, int flags, int mode){
  return open(zFile, flags, mode);
}

/* Forward reference */
static int openDirectory(const char*, int*);

/*
** Many system calls are accessed through pointer-to-functions so that
** they may be overridden at runtime to facilitate fault injection during
** testing and sandboxing.  The following array holds the names and pointers
** to all overrideable system calls.
*/
static struct unix_syscall {







<
<
<







24759
24760
24761
24762
24763
24764
24765



24766
24767
24768
24769
24770
24771
24772
** The safest way to deal with the problem is to always use this wrapper
** which always has the same well-defined interface.
*/
static int posixOpen(const char *zFile, int flags, int mode){
  return open(zFile, flags, mode);
}




/*
** Many system calls are accessed through pointer-to-functions so that
** they may be overridden at runtime to facilitate fault injection during
** testing and sandboxing.  The following array holds the names and pointers
** to all overrideable system calls.
*/
static struct unix_syscall {
24973
24974
24975
24976
24977
24978
24979
24980
24981
24982
24983
24984
24985
24986
24987
24988
24989
24990
24991
24992
#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
  { "fallocate",    (sqlite3_syscall_ptr)posix_fallocate,  0 },
#else
  { "fallocate",    (sqlite3_syscall_ptr)0,                0 },
#endif
#define osFallocate ((int(*)(int,off_t,off_t))aSyscall[15].pCurrent)

  { "unlink",       (sqlite3_syscall_ptr)unlink,           0 },
#define osUnlink    ((int(*)(const char*))aSyscall[16].pCurrent)

  { "openDirectory",    (sqlite3_syscall_ptr)openDirectory,      0 },
#define osOpenDirectory ((int(*)(const char*,int*))aSyscall[17].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.







<
<
<
<
<
<







24855
24856
24857
24858
24859
24860
24861






24862
24863
24864
24865
24866
24867
24868
#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
  { "fallocate",    (sqlite3_syscall_ptr)posix_fallocate,  0 },
#else
  { "fallocate",    (sqlite3_syscall_ptr)0,                0 },
#endif
#define osFallocate ((int(*)(int,off_t,off_t))aSyscall[15].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.
25263
25264
25265
25266
25267
25268
25269
25270
25271
25272
25273
25274
25275
25276
25277
25278
25279
  case EIO:
  case EBADF:
  case EINVAL:
  case ENOTCONN:
  case ENODEV:
  case ENXIO:
  case ENOENT:
#ifdef ESTALE                     /* ESTALE is not defined on Interix systems */
  case ESTALE:
#endif
  case ENOSYS:
    /* these should force the client to close the file and reconnect */
    
  default: 
    return sqliteIOErr;
  }
}







<

<







25139
25140
25141
25142
25143
25144
25145

25146

25147
25148
25149
25150
25151
25152
25153
  case EIO:
  case EBADF:
  case EINVAL:
  case ENOTCONN:
  case ENODEV:
  case ENXIO:
  case ENOENT:

  case ESTALE:

  case ENOSYS:
    /* these should force the client to close the file and reconnect */
    
  default: 
    return sqliteIOErr;
  }
}
26335
26336
26337
26338
26339
26340
26341




26342
26343
26344
26345
26346
26347
26348
26349
26350
26351
26352
26353
26354
26355
26356
**
** It is *not* necessary to hold the mutex when this routine is called,
** even on VxWorks.  A mutex will be acquired on VxWorks by the
** vxworksReleaseFileId() routine.
*/
static int closeUnixFile(sqlite3_file *id){
  unixFile *pFile = (unixFile*)id;




  if( pFile->h>=0 ){
    robust_close(pFile, pFile->h, __LINE__);
    pFile->h = -1;
  }
#if OS_VXWORKS
  if( pFile->pId ){
    if( pFile->isDelete ){
      osUnlink(pFile->pId->zCanonicalName);
    }
    vxworksReleaseFileId(pFile->pId);
    pFile->pId = 0;
  }
#endif
  OSTRACE(("CLOSE   %-3d\n", pFile->h));
  OpenCounter(-1);







>
>
>
>







|







26209
26210
26211
26212
26213
26214
26215
26216
26217
26218
26219
26220
26221
26222
26223
26224
26225
26226
26227
26228
26229
26230
26231
26232
26233
26234
**
** It is *not* necessary to hold the mutex when this routine is called,
** even on VxWorks.  A mutex will be acquired on VxWorks by the
** vxworksReleaseFileId() routine.
*/
static int closeUnixFile(sqlite3_file *id){
  unixFile *pFile = (unixFile*)id;
  if( pFile->dirfd>=0 ){
    robust_close(pFile, pFile->dirfd, __LINE__);
    pFile->dirfd=-1;
  }
  if( pFile->h>=0 ){
    robust_close(pFile, pFile->h, __LINE__);
    pFile->h = -1;
  }
#if OS_VXWORKS
  if( pFile->pId ){
    if( pFile->isDelete ){
      unlink(pFile->pId->zCanonicalName);
    }
    vxworksReleaseFileId(pFile->pId);
    pFile->pId = 0;
  }
#endif
  OSTRACE(("CLOSE   %-3d\n", pFile->h));
  OpenCounter(-1);
26591
26592
26593
26594
26595
26596
26597
26598
26599
26600
26601
26602
26603
26604
26605
  if( eFileLock==SHARED_LOCK ){
    pFile->eFileLock = SHARED_LOCK;
    return SQLITE_OK;
  }
  
  /* To fully unlock the database, delete the lock file */
  assert( eFileLock==NO_LOCK );
  if( osUnlink(zLockFile) ){
    int rc = 0;
    int tErrno = errno;
    if( ENOENT != tErrno ){
      rc = SQLITE_IOERR_UNLOCK;
    }
    if( IS_LOCK_ERROR(rc) ){
      pFile->lastErrno = tErrno;







|







26469
26470
26471
26472
26473
26474
26475
26476
26477
26478
26479
26480
26481
26482
26483
  if( eFileLock==SHARED_LOCK ){
    pFile->eFileLock = SHARED_LOCK;
    return SQLITE_OK;
  }
  
  /* To fully unlock the database, delete the lock file */
  assert( eFileLock==NO_LOCK );
  if( unlink(zLockFile) ){
    int rc = 0;
    int tErrno = errno;
    if( ENOENT != tErrno ){
      rc = SQLITE_IOERR_UNLOCK;
    }
    if( IS_LOCK_ERROR(rc) ){
      pFile->lastErrno = tErrno;
27097
27098
27099
27100
27101
27102
27103
27104
27105
27106
27107
27108
27109
27110
27111
27112
27113
27114
27115
27116
** to a non-zero value otherwise *pResOut is set to zero.  The return value
** is set to SQLITE_OK unless an I/O error occurs during lock checking.
*/
static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
  int rc = SQLITE_OK;
  int reserved = 0;
  unixFile *pFile = (unixFile*)id;
  afpLockingContext *context;
  
  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
  
  assert( pFile );
  context = (afpLockingContext *) pFile->lockingContext;
  if( context->reserved ){
    *pResOut = 1;
    return SQLITE_OK;
  }
  unixEnterMutex(); /* Because pFile->pInode is shared across threads */
  
  /* Check if a thread in this process holds such a lock */







<




|







26975
26976
26977
26978
26979
26980
26981

26982
26983
26984
26985
26986
26987
26988
26989
26990
26991
26992
26993
** to a non-zero value otherwise *pResOut is set to zero.  The return value
** is set to SQLITE_OK unless an I/O error occurs during lock checking.
*/
static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
  int rc = SQLITE_OK;
  int reserved = 0;
  unixFile *pFile = (unixFile*)id;

  
  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
  
  assert( pFile );
  afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
  if( context->reserved ){
    *pResOut = 1;
    return SQLITE_OK;
  }
  unixEnterMutex(); /* Because pFile->pInode is shared across threads */
  
  /* Check if a thread in this process holds such a lock */
27242
27243
27244
27245
27246
27247
27248
27249
27250
27251
27252
27253
27254
27255
27256
    }
  }
  
  /* If control gets to this point, then actually go ahead and make
  ** operating system calls for the specified lock.
  */
  if( eFileLock==SHARED_LOCK ){
    int lrc1, lrc2, lrc1Errno = 0;
    long lk, mask;
    
    assert( pInode->nShared==0 );
    assert( pInode->eFileLock==0 );
        
    mask = (sizeof(long)==8) ? LARGEST_INT64 : 0x7fffffff;
    /* Now get the read-lock SHARED_LOCK */







|







27119
27120
27121
27122
27123
27124
27125
27126
27127
27128
27129
27130
27131
27132
27133
    }
  }
  
  /* If control gets to this point, then actually go ahead and make
  ** operating system calls for the specified lock.
  */
  if( eFileLock==SHARED_LOCK ){
    int lrc1, lrc2, lrc1Errno;
    long lk, mask;
    
    assert( pInode->nShared==0 );
    assert( pInode->eFileLock==0 );
        
    mask = (sizeof(long)==8) ? LARGEST_INT64 : 0x7fffffff;
    /* Now get the read-lock SHARED_LOCK */
27616
27617
27618
27619
27620
27621
27622
27623
27624
27625
27626
27627
27628
27629
27630
27631
27632
27633
27634
27635
27636
27637
27638
27639
27640
27641
27642
#endif
  TIMER_START;
#if defined(USE_PREAD)
  do{ got = osPwrite(id->h, pBuf, cnt, offset); }while( got<0 && errno==EINTR );
#elif defined(USE_PREAD64)
  do{ got = osPwrite64(id->h, pBuf, cnt, offset);}while( got<0 && errno==EINTR);
#else
  do{
    newOffset = lseek(id->h, offset, SEEK_SET);
    SimulateIOError( newOffset-- );
    if( newOffset!=offset ){
      if( newOffset == -1 ){
        ((unixFile*)id)->lastErrno = errno;
      }else{
        ((unixFile*)id)->lastErrno = 0;			
      }
      return -1;
    }
    got = osWrite(id->h, pBuf, cnt);
  }while( got<0 && errno==EINTR );
#endif
  TIMER_END;
  if( got<0 ){
    ((unixFile*)id)->lastErrno = errno;
  }

  OSTRACE(("WRITE   %-3d %5d %7lld %llu\n", id->h, got, offset, TIMER_ELAPSED));







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







27493
27494
27495
27496
27497
27498
27499

27500
27501
27502
27503
27504
27505
27506
27507
27508
27509
27510

27511
27512
27513
27514
27515
27516
27517
#endif
  TIMER_START;
#if defined(USE_PREAD)
  do{ got = osPwrite(id->h, pBuf, cnt, offset); }while( got<0 && errno==EINTR );
#elif defined(USE_PREAD64)
  do{ got = osPwrite64(id->h, pBuf, cnt, offset);}while( got<0 && errno==EINTR);
#else

  newOffset = lseek(id->h, offset, SEEK_SET);
  SimulateIOError( newOffset-- );
  if( newOffset!=offset ){
    if( newOffset == -1 ){
      ((unixFile*)id)->lastErrno = errno;
    }else{
      ((unixFile*)id)->lastErrno = 0;			
    }
    return -1;
  }
  do{ got = osWrite(id->h, pBuf, cnt); }while( got<0 && errno==EINTR );

#endif
  TIMER_END;
  if( got<0 ){
    ((unixFile*)id)->lastErrno = errno;
  }

  OSTRACE(("WRITE   %-3d %5d %7lld %llu\n", id->h, got, offset, TIMER_ELAPSED));
27718
27719
27720
27721
27722
27723
27724
27725
27726
27727
27728
27729
27730
27731
27732
27733
27734
27735
27736
*/
SQLITE_API int sqlite3_sync_count = 0;
SQLITE_API int sqlite3_fullsync_count = 0;
#endif

/*
** We do not trust systems to provide a working fdatasync().  Some do.
** Others do no.  To be safe, we will stick with the (slightly slower)
** fsync(). If you know that your system does support fdatasync() correctly,
** then simply compile with -Dfdatasync=fdatasync
*/
#if !defined(fdatasync)
# define fdatasync fsync
#endif

/*
** Define HAVE_FULLFSYNC to 0 or 1 depending on whether or not
** the F_FULLFSYNC macro is defined.  F_FULLFSYNC is currently
** only available on Mac OS X.  But that could change.







|
|


|







27593
27594
27595
27596
27597
27598
27599
27600
27601
27602
27603
27604
27605
27606
27607
27608
27609
27610
27611
*/
SQLITE_API int sqlite3_sync_count = 0;
SQLITE_API int sqlite3_fullsync_count = 0;
#endif

/*
** We do not trust systems to provide a working fdatasync().  Some do.
** Others do no.  To be safe, we will stick with the (slower) fsync().
** If you know that your system does support fdatasync() correctly,
** then simply compile with -Dfdatasync=fdatasync
*/
#if !defined(fdatasync) && !defined(__linux__)
# define fdatasync fsync
#endif

/*
** Define HAVE_FULLFSYNC to 0 or 1 depending on whether or not
** the F_FULLFSYNC macro is defined.  F_FULLFSYNC is currently
** only available on Mac OS X.  But that could change.
27830
27831
27832
27833
27834
27835
27836
27837
27838
27839
27840
27841
27842
27843
27844
27845
27846
27847
27848
27849
27850
27851
27852
27853
27854
27855
27856
27857
27858
27859
27860
27861
27862
27863
27864
27865
27866
27867
27868
27869
27870
27871
27872
27873
27874
27875
27876
27877
27878
27879
27880
27881
27882
27883
27884
27885
27886
27887

  if( OS_VXWORKS && rc!= -1 ){
    rc = 0;
  }
  return rc;
}

/*
** Open a file descriptor to the directory containing file zFilename.
** If successful, *pFd is set to the opened file descriptor and
** SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM
** or SQLITE_CANTOPEN is returned and *pFd is set to an undefined
** value.
**
** The directory file descriptor is used for only one thing - to
** fsync() a directory to make sure file creation and deletion events
** are flushed to disk.  Such fsyncs are not needed on newer
** journaling filesystems, but are required on older filesystems.
**
** This routine can be overridden using the xSetSysCall interface.
** The ability to override this routine was added in support of the
** chromium sandbox.  Opening a directory is a security risk (we are
** told) so making it overrideable allows the chromium sandbox to
** replace this routine with a harmless no-op.  To make this routine
** a no-op, replace it with a stub that returns SQLITE_OK but leaves
** *pFd set to a negative number.
**
** If SQLITE_OK is returned, the caller is responsible for closing
** the file descriptor *pFd using close().
*/
static int openDirectory(const char *zFilename, int *pFd){
  int ii;
  int fd = -1;
  char zDirname[MAX_PATHNAME+1];

  sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename);
  for(ii=(int)strlen(zDirname); ii>1 && zDirname[ii]!='/'; ii--);
  if( ii>0 ){
    zDirname[ii] = '\0';
    fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0);
    if( fd>=0 ){
#ifdef FD_CLOEXEC
      osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
#endif
      OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname));
    }
  }
  *pFd = fd;
  return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname));
}

/*
** Make sure all writes to a particular file are committed to disk.
**
** If dataOnly==0 then both the file itself and its metadata (file
** size, access time, etc) are synced.  If dataOnly!=0 then only the
** file data is synced.
**







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







27705
27706
27707
27708
27709
27710
27711












































27712
27713
27714
27715
27716
27717
27718

  if( OS_VXWORKS && rc!= -1 ){
    rc = 0;
  }
  return rc;
}













































/*
** Make sure all writes to a particular file are committed to disk.
**
** If dataOnly==0 then both the file itself and its metadata (file
** size, access time, etc) are synced.  If dataOnly!=0 then only the
** file data is synced.
**
27914
27915
27916
27917
27918
27919
27920
27921
27922
27923
27924
27925
27926
27927
27928
27929

27930

27931

27932






27933
27934
27935
27936



27937
27938
27939
27940
27941
27942
27943
27944
  OSTRACE(("SYNC    %-3d\n", pFile->h));
  rc = full_fsync(pFile->h, isFullsync, isDataOnly);
  SimulateIOError( rc=1 );
  if( rc ){
    pFile->lastErrno = errno;
    return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath);
  }

  /* Also fsync the directory containing the file if the DIRSYNC flag
  ** is set.  This is a one-time occurrance.  Many systems (examples: AIX)
  ** are unable to fsync a directory, so ignore errors on the fsync.
  */
  if( pFile->ctrlFlags & UNIXFILE_DIRSYNC ){
    int dirfd;
    OSTRACE(("DIRSYNC %s (have_fullfsync=%d fullsync=%d)\n", pFile->zPath,
            HAVE_FULLFSYNC, isFullsync));

    rc = osOpenDirectory(pFile->zPath, &dirfd);

    if( rc==SQLITE_OK && dirfd>=0 ){

      full_fsync(dirfd, 0, 0);






      robust_close(pFile, dirfd, __LINE__);
    }else if( rc==SQLITE_CANTOPEN ){
      rc = SQLITE_OK;
    }



    pFile->ctrlFlags &= ~UNIXFILE_DIRSYNC;
  }
  return rc;
}

/*
** Truncate an open file to a specified size
*/







<
<
<
<
<
|
<
|

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

>
>
>
|







27745
27746
27747
27748
27749
27750
27751





27752

27753
27754
27755
27756
27757
27758
27759
27760
27761
27762
27763
27764
27765
27766
27767

27768
27769
27770
27771
27772
27773
27774
27775
27776
27777
27778
27779
27780
  OSTRACE(("SYNC    %-3d\n", pFile->h));
  rc = full_fsync(pFile->h, isFullsync, isDataOnly);
  SimulateIOError( rc=1 );
  if( rc ){
    pFile->lastErrno = errno;
    return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath);
  }





  if( pFile->dirfd>=0 ){

    OSTRACE(("DIRSYNC %-3d (have_fullfsync=%d fullsync=%d)\n", pFile->dirfd,
            HAVE_FULLFSYNC, isFullsync));
#ifndef SQLITE_DISABLE_DIRSYNC
    /* The directory sync is only attempted if full_fsync is
    ** turned off or unavailable.  If a full_fsync occurred above,
    ** then the directory sync is superfluous.
    */
    if( (!HAVE_FULLFSYNC || !isFullsync) && full_fsync(pFile->dirfd,0,0) ){
       /*
       ** We have received multiple reports of fsync() returning
       ** errors when applied to directories on certain file systems.
       ** A failed directory sync is not a big deal.  So it seems
       ** better to ignore the error.  Ticket #1657
       */
       /* pFile->lastErrno = errno; */

       /* return SQLITE_IOERR; */
    }
#endif
    /* Only need to sync once, so close the  directory when we are done */
    robust_close(pFile, pFile->dirfd, __LINE__);
    pFile->dirfd = -1;
  }
  return rc;
}

/*
** Truncate an open file to a specified size
*/
28012
28013
28014
28015
28016
28017
28018
28019

28020

28021
28022
28023
28024
28025
28026
28027
28028
28029
28030
28031
** proxying locking division.
*/
static int proxyFileControl(sqlite3_file*,int,void*);
#endif

/* 
** This function is called to handle the SQLITE_FCNTL_SIZE_HINT 
** file-control operation.  Enlarge the database to nBytes in size

** (rounded up to the next chunk-size).  If the database is already

** nBytes or larger, this routine is a no-op.
*/
static int fcntlSizeHint(unixFile *pFile, i64 nByte){
  if( pFile->szChunk>0 ){
    i64 nSize;                    /* Required file size */
    struct stat buf;              /* Used to hold return values of fstat() */
   
    if( osFstat(pFile->h, &buf) ) return SQLITE_IOERR_FSTAT;

    nSize = ((nByte+pFile->szChunk-1) / pFile->szChunk) * pFile->szChunk;
    if( nSize>(i64)buf.st_size ){







|
>
|
>
|


|







27848
27849
27850
27851
27852
27853
27854
27855
27856
27857
27858
27859
27860
27861
27862
27863
27864
27865
27866
27867
27868
27869
** proxying locking division.
*/
static int proxyFileControl(sqlite3_file*,int,void*);
#endif

/* 
** This function is called to handle the SQLITE_FCNTL_SIZE_HINT 
** file-control operation.
**
** If the user has configured a chunk-size for this file, it could be
** that the file needs to be extended at this point. Otherwise, the
** SQLITE_FCNTL_SIZE_HINT operation is a no-op for Unix.
*/
static int fcntlSizeHint(unixFile *pFile, i64 nByte){
  if( pFile->szChunk ){
    i64 nSize;                    /* Required file size */
    struct stat buf;              /* Used to hold return values of fstat() */
   
    if( osFstat(pFile->h, &buf) ) return SQLITE_IOERR_FSTAT;

    nSize = ((nByte+pFile->szChunk-1) / pFile->szChunk) * pFile->szChunk;
    if( nSize>(i64)buf.st_size ){
28066
28067
28068
28069
28070
28071
28072
28073
28074
28075
28076
28077
28078
28079
28080
28081
28082
28083
28084
28085
28086
28087
28088
28089
28090
28091
28092
28093
28094
28095
28096
28097
28098
28099
28100
28101
28102
28103
28104
28105
28106
28107
28108
28109
28110
  return SQLITE_OK;
}

/*
** Information and control of an open file handle.
*/
static int unixFileControl(sqlite3_file *id, int op, void *pArg){
  unixFile *pFile = (unixFile*)id;
  switch( op ){
    case SQLITE_FCNTL_LOCKSTATE: {
      *(int*)pArg = pFile->eFileLock;
      return SQLITE_OK;
    }
    case SQLITE_LAST_ERRNO: {
      *(int*)pArg = pFile->lastErrno;
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_CHUNK_SIZE: {
      pFile->szChunk = *(int *)pArg;
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_SIZE_HINT: {
      int rc;
      SimulateIOErrorBenign(1);
      rc = fcntlSizeHint(pFile, *(i64 *)pArg);
      SimulateIOErrorBenign(0);
      return rc;
    }
    case SQLITE_FCNTL_PERSIST_WAL: {
      int bPersist = *(int*)pArg;
      if( bPersist<0 ){
        *(int*)pArg = (pFile->ctrlFlags & UNIXFILE_PERSIST_WAL)!=0;
      }else if( bPersist==0 ){
        pFile->ctrlFlags &= ~UNIXFILE_PERSIST_WAL;
      }else{
        pFile->ctrlFlags |= UNIXFILE_PERSIST_WAL;
      }
      return SQLITE_OK;
    }
#ifndef NDEBUG
    /* The pager calls this method to signal that it has done
    ** a rollback and that the database is therefore unchanged and
    ** it hence it is OK for the transaction change counter to be
    ** unchanged.
    */







<


|



|



|



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







27904
27905
27906
27907
27908
27909
27910

27911
27912
27913
27914
27915
27916
27917
27918
27919
27920
27921
27922
27923
27924


27925













27926
27927
27928
27929
27930
27931
27932
  return SQLITE_OK;
}

/*
** Information and control of an open file handle.
*/
static int unixFileControl(sqlite3_file *id, int op, void *pArg){

  switch( op ){
    case SQLITE_FCNTL_LOCKSTATE: {
      *(int*)pArg = ((unixFile*)id)->eFileLock;
      return SQLITE_OK;
    }
    case SQLITE_LAST_ERRNO: {
      *(int*)pArg = ((unixFile*)id)->lastErrno;
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_CHUNK_SIZE: {
      ((unixFile*)id)->szChunk = *(int *)pArg;
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_SIZE_HINT: {


      return fcntlSizeHint((unixFile *)id, *(i64 *)pArg);













    }
#ifndef NDEBUG
    /* The pager calls this method to signal that it has done
    ** a rollback and that the database is therefore unchanged and
    ** it hence it is OK for the transaction change counter to be
    ** unchanged.
    */
28212
28213
28214
28215
28216
28217
28218
28219
28220
28221



28222
28223
28224
28225
28226
28227
28228
** All other fields are read/write.  The unixShm.pFile->mutex must be held
** while accessing any read/write fields.
*/
struct unixShm {
  unixShmNode *pShmNode;     /* The underlying unixShmNode object */
  unixShm *pNext;            /* Next unixShm with the same unixShmNode */
  u8 hasMutex;               /* True if holding the unixShmNode mutex */
  u8 id;                     /* Id of this connection within its unixShmNode */
  u16 sharedMask;            /* Mask of shared locks held */
  u16 exclMask;              /* Mask of exclusive locks held */



};

/*
** Constants used for locking
*/
#define UNIX_SHM_BASE   ((22+SQLITE_SHM_NLOCK)*4)         /* first lock byte */
#define UNIX_SHM_DMS    (UNIX_SHM_BASE+SQLITE_SHM_NLOCK)  /* deadman switch */







<


>
>
>







28034
28035
28036
28037
28038
28039
28040

28041
28042
28043
28044
28045
28046
28047
28048
28049
28050
28051
28052
** All other fields are read/write.  The unixShm.pFile->mutex must be held
** while accessing any read/write fields.
*/
struct unixShm {
  unixShmNode *pShmNode;     /* The underlying unixShmNode object */
  unixShm *pNext;            /* Next unixShm with the same unixShmNode */
  u8 hasMutex;               /* True if holding the unixShmNode mutex */

  u16 sharedMask;            /* Mask of shared locks held */
  u16 exclMask;              /* Mask of exclusive locks held */
#ifdef SQLITE_DEBUG
  u8 id;                     /* Id of this connection within its unixShmNode */
#endif
};

/*
** Constants used for locking
*/
#define UNIX_SHM_BASE   ((22+SQLITE_SHM_NLOCK)*4)         /* first lock byte */
#define UNIX_SHM_DMS    (UNIX_SHM_BASE+SQLITE_SHM_NLOCK)  /* deadman switch */
28310
28311
28312
28313
28314
28315
28316
28317
28318
28319
28320
28321
28322
28323
28324
*/
static void unixShmPurge(unixFile *pFd){
  unixShmNode *p = pFd->pInode->pShmNode;
  assert( unixMutexHeld() );
  if( p && p->nRef==0 ){
    int i;
    assert( p->pInode==pFd->pInode );
    sqlite3_mutex_free(p->mutex);
    for(i=0; i<p->nRegion; i++){
      if( p->h>=0 ){
        munmap(p->apRegion[i], p->szRegion);
      }else{
        sqlite3_free(p->apRegion[i]);
      }
    }







|







28134
28135
28136
28137
28138
28139
28140
28141
28142
28143
28144
28145
28146
28147
28148
*/
static void unixShmPurge(unixFile *pFd){
  unixShmNode *p = pFd->pInode->pShmNode;
  assert( unixMutexHeld() );
  if( p && p->nRef==0 ){
    int i;
    assert( p->pInode==pFd->pInode );
    if( p->mutex ) sqlite3_mutex_free(p->mutex);
    for(i=0; i<p->nRegion; i++){
      if( p->h>=0 ){
        munmap(p->apRegion[i], p->szRegion);
      }else{
        sqlite3_free(p->apRegion[i]);
      }
    }
28779
28780
28781
28782
28783
28784
28785
28786
28787
28788
28789
28790
28791
28792
28793

  /* If pShmNode->nRef has reached 0, then close the underlying
  ** shared-memory file, too */
  unixEnterMutex();
  assert( pShmNode->nRef>0 );
  pShmNode->nRef--;
  if( pShmNode->nRef==0 ){
    if( deleteFlag && pShmNode->h>=0 ) osUnlink(pShmNode->zFilename);
    unixShmPurge(pDbFd);
  }
  unixLeaveMutex();

  return SQLITE_OK;
}








|







28603
28604
28605
28606
28607
28608
28609
28610
28611
28612
28613
28614
28615
28616
28617

  /* If pShmNode->nRef has reached 0, then close the underlying
  ** shared-memory file, too */
  unixEnterMutex();
  assert( pShmNode->nRef>0 );
  pShmNode->nRef--;
  if( pShmNode->nRef==0 ){
    if( deleteFlag && pShmNode->h>=0 ) unlink(pShmNode->zFilename);
    unixShmPurge(pDbFd);
  }
  unixLeaveMutex();

  return SQLITE_OK;
}

29092
29093
29094
29095
29096
29097
29098
29099
29100
29101
29102
29103
29104
29105
29106

/*
** Initialize the contents of the unixFile structure pointed to by pId.
*/
static int fillInUnixFile(
  sqlite3_vfs *pVfs,      /* Pointer to vfs object */
  int h,                  /* Open file descriptor of file being opened */
  int syncDir,            /* True to sync directory on first sync */
  sqlite3_file *pId,      /* Write to the unixFile structure here */
  const char *zFilename,  /* Name of the file being opened */
  int noLock,             /* Omit locking if true */
  int isDelete,           /* Delete on close if true */
  int isReadOnly          /* True if the file is opened read-only */
){
  const sqlite3_io_methods *pLockingStyle;







|







28916
28917
28918
28919
28920
28921
28922
28923
28924
28925
28926
28927
28928
28929
28930

/*
** Initialize the contents of the unixFile structure pointed to by pId.
*/
static int fillInUnixFile(
  sqlite3_vfs *pVfs,      /* Pointer to vfs object */
  int h,                  /* Open file descriptor of file being opened */
  int dirfd,              /* Directory file descriptor */
  sqlite3_file *pId,      /* Write to the unixFile structure here */
  const char *zFilename,  /* Name of the file being opened */
  int noLock,             /* Omit locking if true */
  int isDelete,           /* Delete on close if true */
  int isReadOnly          /* True if the file is opened read-only */
){
  const sqlite3_io_methods *pLockingStyle;
29123
29124
29125
29126
29127
29128
29129

29130
29131
29132
29133
29134
29135
29136
29137
29138
29139
29140
29141
29142
29143
29144
29145
29146
29147
29148
    || pVfs->pAppData==(void*)&autolockIoFinder );
#else
  assert( zFilename==0 || zFilename[0]=='/' );
#endif

  OSTRACE(("OPEN    %-3d %s\n", h, zFilename));
  pNew->h = h;

  pNew->zPath = zFilename;
  if( memcmp(pVfs->zName,"unix-excl",10)==0 ){
    pNew->ctrlFlags = UNIXFILE_EXCL;
  }else{
    pNew->ctrlFlags = 0;
  }
  if( isReadOnly ){
    pNew->ctrlFlags |= UNIXFILE_RDONLY;
  }
  if( syncDir ){
    pNew->ctrlFlags |= UNIXFILE_DIRSYNC;
  }

#if OS_VXWORKS
  pNew->pId = vxworksFindFileId(zFilename);
  if( pNew->pId==0 ){
    noLock = 1;
    rc = SQLITE_NOMEM;
  }







>









<
<
<







28947
28948
28949
28950
28951
28952
28953
28954
28955
28956
28957
28958
28959
28960
28961
28962
28963



28964
28965
28966
28967
28968
28969
28970
    || pVfs->pAppData==(void*)&autolockIoFinder );
#else
  assert( zFilename==0 || zFilename[0]=='/' );
#endif

  OSTRACE(("OPEN    %-3d %s\n", h, zFilename));
  pNew->h = h;
  pNew->dirfd = dirfd;
  pNew->zPath = zFilename;
  if( memcmp(pVfs->zName,"unix-excl",10)==0 ){
    pNew->ctrlFlags = UNIXFILE_EXCL;
  }else{
    pNew->ctrlFlags = 0;
  }
  if( isReadOnly ){
    pNew->ctrlFlags |= UNIXFILE_RDONLY;
  }




#if OS_VXWORKS
  pNew->pId = vxworksFindFileId(zFilename);
  if( pNew->pId==0 ){
    noLock = 1;
    rc = SQLITE_NOMEM;
  }
29261
29262
29263
29264
29265
29266
29267
29268
29269
29270
29271
29272
29273

29274
29275
29276
29277
29278
29279
29280































29281
29282
29283
29284
29285
29286
29287
#endif
  
  pNew->lastErrno = 0;
#if OS_VXWORKS
  if( rc!=SQLITE_OK ){
    if( h>=0 ) robust_close(pNew, h, __LINE__);
    h = -1;
    osUnlink(zFilename);
    isDelete = 0;
  }
  pNew->isDelete = isDelete;
#endif
  if( rc!=SQLITE_OK ){

    if( h>=0 ) robust_close(pNew, h, __LINE__);
  }else{
    pNew->pMethod = pLockingStyle;
    OpenCounter(+1);
  }
  return rc;
}
































/*
** Return the name of a directory in which to put temporary files.
** If no suitable temporary file directory can be found, return NULL.
*/
static const char *unixTempFileDir(void){
  static const char *azDirs[] = {







|





>







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







29083
29084
29085
29086
29087
29088
29089
29090
29091
29092
29093
29094
29095
29096
29097
29098
29099
29100
29101
29102
29103
29104
29105
29106
29107
29108
29109
29110
29111
29112
29113
29114
29115
29116
29117
29118
29119
29120
29121
29122
29123
29124
29125
29126
29127
29128
29129
29130
29131
29132
29133
29134
29135
29136
29137
29138
29139
29140
29141
#endif
  
  pNew->lastErrno = 0;
#if OS_VXWORKS
  if( rc!=SQLITE_OK ){
    if( h>=0 ) robust_close(pNew, h, __LINE__);
    h = -1;
    unlink(zFilename);
    isDelete = 0;
  }
  pNew->isDelete = isDelete;
#endif
  if( rc!=SQLITE_OK ){
    if( dirfd>=0 ) robust_close(pNew, dirfd, __LINE__);
    if( h>=0 ) robust_close(pNew, h, __LINE__);
  }else{
    pNew->pMethod = pLockingStyle;
    OpenCounter(+1);
  }
  return rc;
}

/*
** Open a file descriptor to the directory containing file zFilename.
** If successful, *pFd is set to the opened file descriptor and
** SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM
** or SQLITE_CANTOPEN is returned and *pFd is set to an undefined
** value.
**
** If SQLITE_OK is returned, the caller is responsible for closing
** the file descriptor *pFd using close().
*/
static int openDirectory(const char *zFilename, int *pFd){
  int ii;
  int fd = -1;
  char zDirname[MAX_PATHNAME+1];

  sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename);
  for(ii=(int)strlen(zDirname); ii>1 && zDirname[ii]!='/'; ii--);
  if( ii>0 ){
    zDirname[ii] = '\0';
    fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0);
    if( fd>=0 ){
#ifdef FD_CLOEXEC
      osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
#endif
      OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname));
    }
  }
  *pFd = fd;
  return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname));
}

/*
** Return the name of a directory in which to put temporary files.
** If no suitable temporary file directory can be found, return NULL.
*/
static const char *unixTempFileDir(void){
  static const char *azDirs[] = {
29389
29390
29391
29392
29393
29394
29395
29396
29397
29398
29399
29400
29401
29402
29403
  ** almost certain that an open() call on the same path will also fail.
  ** For this reason, if an error occurs in the stat() call here, it is
  ** ignored and -1 is returned. The caller will try to open a new file
  ** descriptor on the same path, fail, and return an error to SQLite.
  **
  ** Even if a subsequent open() call does succeed, the consequences of
  ** not searching for a resusable file descriptor are not dire.  */
  if( 0==osStat(zPath, &sStat) ){
    unixInodeInfo *pInode;

    unixEnterMutex();
    pInode = inodeList;
    while( pInode && (pInode->fileId.dev!=sStat.st_dev
                     || pInode->fileId.ino!=sStat.st_ino) ){
       pInode = pInode->pNext;







|







29243
29244
29245
29246
29247
29248
29249
29250
29251
29252
29253
29254
29255
29256
29257
  ** almost certain that an open() call on the same path will also fail.
  ** For this reason, if an error occurs in the stat() call here, it is
  ** ignored and -1 is returned. The caller will try to open a new file
  ** descriptor on the same path, fail, and return an error to SQLite.
  **
  ** Even if a subsequent open() call does succeed, the consequences of
  ** not searching for a resusable file descriptor are not dire.  */
  if( 0==stat(zPath, &sStat) ){
    unixInodeInfo *pInode;

    unixEnterMutex();
    pInode = inodeList;
    while( pInode && (pInode->fileId.dev!=sStat.st_dev
                     || pInode->fileId.ino!=sStat.st_ino) ){
       pInode = pInode->pNext;
29465
29466
29467
29468
29469
29470
29471
29472
29473
29474
29475
29476
29477
29478
29479
    */
    nDb = sqlite3Strlen30(zPath) - 1; 
    while( nDb>0 && zPath[nDb]!='-' ) nDb--;
    if( nDb==0 ) return SQLITE_OK;
    memcpy(zDb, zPath, nDb);
    zDb[nDb] = '\0';

    if( 0==osStat(zDb, &sStat) ){
      *pMode = sStat.st_mode & 0777;
    }else{
      rc = SQLITE_IOERR_FSTAT;
    }
  }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){
    *pMode = 0600;
  }







|







29319
29320
29321
29322
29323
29324
29325
29326
29327
29328
29329
29330
29331
29332
29333
    */
    nDb = sqlite3Strlen30(zPath) - 1; 
    while( nDb>0 && zPath[nDb]!='-' ) nDb--;
    if( nDb==0 ) return SQLITE_OK;
    memcpy(zDb, zPath, nDb);
    zDb[nDb] = '\0';

    if( 0==stat(zDb, &sStat) ){
      *pMode = sStat.st_mode & 0777;
    }else{
      rc = SQLITE_IOERR_FSTAT;
    }
  }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){
    *pMode = 0600;
  }
29507
29508
29509
29510
29511
29512
29513

29514
29515
29516
29517
29518
29519
29520
29521
29522
29523
29524
29525
29526
29527
29528
29529
29530
29531
29532
29533
29534
29535
29536
29537
29538
29539
29540
29541
29542
  const char *zPath,           /* Pathname of file to be opened */
  sqlite3_file *pFile,         /* The file descriptor to be filled in */
  int flags,                   /* Input flags to control the opening */
  int *pOutFlags               /* Output flags returned to SQLite core */
){
  unixFile *p = (unixFile *)pFile;
  int fd = -1;                   /* File descriptor returned by open() */

  int openFlags = 0;             /* Flags to pass to open() */
  int eType = flags&0xFFFFFF00;  /* Type of file to open */
  int noLock;                    /* True to omit locking primitives */
  int rc = SQLITE_OK;            /* Function Return Code */

  int isExclusive  = (flags & SQLITE_OPEN_EXCLUSIVE);
  int isDelete     = (flags & SQLITE_OPEN_DELETEONCLOSE);
  int isCreate     = (flags & SQLITE_OPEN_CREATE);
  int isReadonly   = (flags & SQLITE_OPEN_READONLY);
  int isReadWrite  = (flags & SQLITE_OPEN_READWRITE);
#if SQLITE_ENABLE_LOCKING_STYLE
  int isAutoProxy  = (flags & SQLITE_OPEN_AUTOPROXY);
#endif
#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
  struct statfs fsInfo;
#endif

  /* If creating a master or main-file journal, this function will open
  ** a file-descriptor on the directory too. The first time unixSync()
  ** is called the directory file descriptor will be fsync()ed and close()d.
  */
  int syncDir = (isCreate && (
        eType==SQLITE_OPEN_MASTER_JOURNAL 
     || eType==SQLITE_OPEN_MAIN_JOURNAL 
     || eType==SQLITE_OPEN_WAL
  ));

  /* If argument zPath is a NULL pointer, this function is required to open
  ** a temporary file. Use this buffer to store the file name in.







>













<
<
<





|







29361
29362
29363
29364
29365
29366
29367
29368
29369
29370
29371
29372
29373
29374
29375
29376
29377
29378
29379
29380
29381



29382
29383
29384
29385
29386
29387
29388
29389
29390
29391
29392
29393
29394
  const char *zPath,           /* Pathname of file to be opened */
  sqlite3_file *pFile,         /* The file descriptor to be filled in */
  int flags,                   /* Input flags to control the opening */
  int *pOutFlags               /* Output flags returned to SQLite core */
){
  unixFile *p = (unixFile *)pFile;
  int fd = -1;                   /* File descriptor returned by open() */
  int dirfd = -1;                /* Directory file descriptor */
  int openFlags = 0;             /* Flags to pass to open() */
  int eType = flags&0xFFFFFF00;  /* Type of file to open */
  int noLock;                    /* True to omit locking primitives */
  int rc = SQLITE_OK;            /* Function Return Code */

  int isExclusive  = (flags & SQLITE_OPEN_EXCLUSIVE);
  int isDelete     = (flags & SQLITE_OPEN_DELETEONCLOSE);
  int isCreate     = (flags & SQLITE_OPEN_CREATE);
  int isReadonly   = (flags & SQLITE_OPEN_READONLY);
  int isReadWrite  = (flags & SQLITE_OPEN_READWRITE);
#if SQLITE_ENABLE_LOCKING_STYLE
  int isAutoProxy  = (flags & SQLITE_OPEN_AUTOPROXY);
#endif




  /* If creating a master or main-file journal, this function will open
  ** a file-descriptor on the directory too. The first time unixSync()
  ** is called the directory file descriptor will be fsync()ed and close()d.
  */
  int isOpenDirectory = (isCreate && (
        eType==SQLITE_OPEN_MASTER_JOURNAL 
     || eType==SQLITE_OPEN_MAIN_JOURNAL 
     || eType==SQLITE_OPEN_WAL
  ));

  /* If argument zPath is a NULL pointer, this function is required to open
  ** a temporary file. Use this buffer to store the file name in.
29582
29583
29584
29585
29586
29587
29588
29589
29590
29591
29592
29593
29594
29595
29596
      if( !pUnused ){
        return SQLITE_NOMEM;
      }
    }
    p->pUnused = pUnused;
  }else if( !zName ){
    /* If zName is NULL, the upper layer is requesting a temp file. */
    assert(isDelete && !syncDir);
    rc = unixGetTempname(MAX_PATHNAME+1, zTmpname);
    if( rc!=SQLITE_OK ){
      return rc;
    }
    zName = zTmpname;
  }








|







29434
29435
29436
29437
29438
29439
29440
29441
29442
29443
29444
29445
29446
29447
29448
      if( !pUnused ){
        return SQLITE_NOMEM;
      }
    }
    p->pUnused = pUnused;
  }else if( !zName ){
    /* If zName is NULL, the upper layer is requesting a temp file. */
    assert(isDelete && !isOpenDirectory);
    rc = unixGetTempname(MAX_PATHNAME+1, zTmpname);
    if( rc!=SQLITE_OK ){
      return rc;
    }
    zName = zTmpname;
  }

29638
29639
29640
29641
29642
29643
29644
29645
29646
29647
29648
29649
29650
29651
29652













29653
29654
29655
29656
29657
29658
29659
29660
29661

29662
29663

29664
29665
29666
29667
29668
29669
29670
    p->pUnused->flags = flags;
  }

  if( isDelete ){
#if OS_VXWORKS
    zPath = zName;
#else
    osUnlink(zName);
#endif
  }
#if SQLITE_ENABLE_LOCKING_STYLE
  else{
    p->openFlags = openFlags;
  }
#endif














#ifdef FD_CLOEXEC
  osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
#endif

  noLock = eType!=SQLITE_OPEN_MAIN_DB;

  
#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE

  if( fstatfs(fd, &fsInfo) == -1 ){
    ((unixFile*)pFile)->lastErrno = errno;

    robust_close(p, fd, __LINE__);
    return SQLITE_IOERR_ACCESS;
  }
  if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) {
    ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS;
  }
#endif







|







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









>


>







29490
29491
29492
29493
29494
29495
29496
29497
29498
29499
29500
29501
29502
29503
29504
29505
29506
29507
29508
29509
29510
29511
29512
29513
29514
29515
29516
29517
29518
29519
29520
29521
29522
29523
29524
29525
29526
29527
29528
29529
29530
29531
29532
29533
29534
29535
29536
29537
    p->pUnused->flags = flags;
  }

  if( isDelete ){
#if OS_VXWORKS
    zPath = zName;
#else
    unlink(zName);
#endif
  }
#if SQLITE_ENABLE_LOCKING_STYLE
  else{
    p->openFlags = openFlags;
  }
#endif

  if( isOpenDirectory ){
    rc = openDirectory(zPath, &dirfd);
    if( rc!=SQLITE_OK ){
      /* It is safe to close fd at this point, because it is guaranteed not
      ** to be open on a database file. If it were open on a database file,
      ** it would not be safe to close as this would release any locks held
      ** on the file by this process.  */
      assert( eType!=SQLITE_OPEN_MAIN_DB );
      robust_close(p, fd, __LINE__);
      goto open_finished;
    }
  }

#ifdef FD_CLOEXEC
  osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
#endif

  noLock = eType!=SQLITE_OPEN_MAIN_DB;

  
#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
  struct statfs fsInfo;
  if( fstatfs(fd, &fsInfo) == -1 ){
    ((unixFile*)pFile)->lastErrno = errno;
    if( dirfd>=0 ) robust_close(p, dirfd, __LINE__);
    robust_close(p, fd, __LINE__);
    return SQLITE_IOERR_ACCESS;
  }
  if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) {
    ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS;
  }
#endif
29678
29679
29680
29681
29682
29683
29684

29685
29686
29687
29688
29689
29690
29691
29692
29693



29694
29695
29696
29697
29698
29699
29700
29701
29702
29703
29704
29705
29706
29707
29708
29709
29710
29711
29712
29713
29714
29715
29716
29717
29718
29719
29720
29721
29722
29723
29724
29725
29726
    int useProxy = 0;

    /* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy, 0 means 
    ** never use proxy, NULL means use proxy for non-local files only.  */
    if( envforce!=NULL ){
      useProxy = atoi(envforce)>0;
    }else{

      if( statfs(zPath, &fsInfo) == -1 ){
        /* In theory, the close(fd) call is sub-optimal. If the file opened
        ** with fd is a database file, and there are other connections open
        ** on that file that are currently holding advisory locks on it,
        ** then the call to close() will cancel those locks. In practice,
        ** we're assuming that statfs() doesn't fail very often. At least
        ** not while other file descriptors opened by the same process on
        ** the same file are working.  */
        p->lastErrno = errno;



        robust_close(p, fd, __LINE__);
        rc = SQLITE_IOERR_ACCESS;
        goto open_finished;
      }
      useProxy = !(fsInfo.f_flags&MNT_LOCAL);
    }
    if( useProxy ){
      rc = fillInUnixFile(pVfs, fd, syncDir, pFile, zPath, noLock,
                          isDelete, isReadonly);
      if( rc==SQLITE_OK ){
        rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:");
        if( rc!=SQLITE_OK ){
          /* Use unixClose to clean up the resources added in fillInUnixFile 
          ** and clear all the structure's references.  Specifically, 
          ** pFile->pMethods will be NULL so sqlite3OsClose will be a no-op 
          */
          unixClose(pFile);
          return rc;
        }
      }
      goto open_finished;
    }
  }
#endif
  
  rc = fillInUnixFile(pVfs, fd, syncDir, pFile, zPath, noLock,
                      isDelete, isReadonly);
open_finished:
  if( rc!=SQLITE_OK ){
    sqlite3_free(p->pUnused);
  }
  return rc;
}







>









>
>
>







|

















|







29545
29546
29547
29548
29549
29550
29551
29552
29553
29554
29555
29556
29557
29558
29559
29560
29561
29562
29563
29564
29565
29566
29567
29568
29569
29570
29571
29572
29573
29574
29575
29576
29577
29578
29579
29580
29581
29582
29583
29584
29585
29586
29587
29588
29589
29590
29591
29592
29593
29594
29595
29596
29597
    int useProxy = 0;

    /* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy, 0 means 
    ** never use proxy, NULL means use proxy for non-local files only.  */
    if( envforce!=NULL ){
      useProxy = atoi(envforce)>0;
    }else{
      struct statfs fsInfo;
      if( statfs(zPath, &fsInfo) == -1 ){
        /* In theory, the close(fd) call is sub-optimal. If the file opened
        ** with fd is a database file, and there are other connections open
        ** on that file that are currently holding advisory locks on it,
        ** then the call to close() will cancel those locks. In practice,
        ** we're assuming that statfs() doesn't fail very often. At least
        ** not while other file descriptors opened by the same process on
        ** the same file are working.  */
        p->lastErrno = errno;
        if( dirfd>=0 ){
          robust_close(p, dirfd, __LINE__);
        }
        robust_close(p, fd, __LINE__);
        rc = SQLITE_IOERR_ACCESS;
        goto open_finished;
      }
      useProxy = !(fsInfo.f_flags&MNT_LOCAL);
    }
    if( useProxy ){
      rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock,
                          isDelete, isReadonly);
      if( rc==SQLITE_OK ){
        rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:");
        if( rc!=SQLITE_OK ){
          /* Use unixClose to clean up the resources added in fillInUnixFile 
          ** and clear all the structure's references.  Specifically, 
          ** pFile->pMethods will be NULL so sqlite3OsClose will be a no-op 
          */
          unixClose(pFile);
          return rc;
        }
      }
      goto open_finished;
    }
  }
#endif
  
  rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock,
                      isDelete, isReadonly);
open_finished:
  if( rc!=SQLITE_OK ){
    sqlite3_free(p->pUnused);
  }
  return rc;
}
29734
29735
29736
29737
29738
29739
29740
29741
29742
29743
29744
29745
29746
29747
29748
29749
29750
29751
29752
29753
29754
29755
29756
29757
29758
29759
29760
29761
29762
29763
29764
29765
29766
  sqlite3_vfs *NotUsed,     /* VFS containing this as the xDelete method */
  const char *zPath,        /* Name of file to be deleted */
  int dirSync               /* If true, fsync() directory after deleting file */
){
  int rc = SQLITE_OK;
  UNUSED_PARAMETER(NotUsed);
  SimulateIOError(return SQLITE_IOERR_DELETE);
  if( osUnlink(zPath)==(-1) && errno!=ENOENT ){
    return unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
  }
#ifndef SQLITE_DISABLE_DIRSYNC
  if( dirSync ){
    int fd;
    rc = osOpenDirectory(zPath, &fd);
    if( rc==SQLITE_OK ){
#if OS_VXWORKS
      if( fsync(fd)==-1 )
#else
      if( fsync(fd) )
#endif
      {
        rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath);
      }
      robust_close(0, fd, __LINE__);
    }else if( rc==SQLITE_CANTOPEN ){
      rc = SQLITE_OK;
    }
  }
#endif
  return rc;
}

/*







|





|










<
<







29605
29606
29607
29608
29609
29610
29611
29612
29613
29614
29615
29616
29617
29618
29619
29620
29621
29622
29623
29624
29625
29626
29627
29628


29629
29630
29631
29632
29633
29634
29635
  sqlite3_vfs *NotUsed,     /* VFS containing this as the xDelete method */
  const char *zPath,        /* Name of file to be deleted */
  int dirSync               /* If true, fsync() directory after deleting file */
){
  int rc = SQLITE_OK;
  UNUSED_PARAMETER(NotUsed);
  SimulateIOError(return SQLITE_IOERR_DELETE);
  if( unlink(zPath)==(-1) && errno!=ENOENT ){
    return unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
  }
#ifndef SQLITE_DISABLE_DIRSYNC
  if( dirSync ){
    int fd;
    rc = openDirectory(zPath, &fd);
    if( rc==SQLITE_OK ){
#if OS_VXWORKS
      if( fsync(fd)==-1 )
#else
      if( fsync(fd) )
#endif
      {
        rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath);
      }
      robust_close(0, fd, __LINE__);


    }
  }
#endif
  return rc;
}

/*
29795
29796
29797
29798
29799
29800
29801
29802
29803
29804
29805
29806
29807
29808
29809

    default:
      assert(!"Invalid flags argument");
  }
  *pResOut = (osAccess(zPath, amode)==0);
  if( flags==SQLITE_ACCESS_EXISTS && *pResOut ){
    struct stat buf;
    if( 0==osStat(zPath, &buf) && buf.st_size==0 ){
      *pResOut = 0;
    }
  }
  return SQLITE_OK;
}









|







29664
29665
29666
29667
29668
29669
29670
29671
29672
29673
29674
29675
29676
29677
29678

    default:
      assert(!"Invalid flags argument");
  }
  *pResOut = (osAccess(zPath, amode)==0);
  if( flags==SQLITE_ACCESS_EXISTS && *pResOut ){
    struct stat buf;
    if( 0==stat(zPath, &buf) && buf.st_size==0 ){
      *pResOut = 0;
    }
  }
  return SQLITE_OK;
}


30314
30315
30316
30317
30318
30319
30320

30321
30322
30323
30324
30325
30326
30327
*/
static int proxyCreateUnixFile(
    const char *path,        /* path for the new unixFile */
    unixFile **ppFile,       /* unixFile created and returned by ref */
    int islockfile           /* if non zero missing dirs will be created */
) {
  int fd = -1;

  unixFile *pNew;
  int rc = SQLITE_OK;
  int openFlags = O_RDWR | O_CREAT;
  sqlite3_vfs dummyVfs;
  int terrno = 0;
  UnixUnusedFd *pUnused = NULL;








>







30183
30184
30185
30186
30187
30188
30189
30190
30191
30192
30193
30194
30195
30196
30197
*/
static int proxyCreateUnixFile(
    const char *path,        /* path for the new unixFile */
    unixFile **ppFile,       /* unixFile created and returned by ref */
    int islockfile           /* if non zero missing dirs will be created */
) {
  int fd = -1;
  int dirfd = -1;
  unixFile *pNew;
  int rc = SQLITE_OK;
  int openFlags = O_RDWR | O_CREAT;
  sqlite3_vfs dummyVfs;
  int terrno = 0;
  UnixUnusedFd *pUnused = NULL;

30378
30379
30380
30381
30382
30383
30384
30385
30386
30387
30388
30389
30390
30391
30392
  memset(&dummyVfs, 0, sizeof(dummyVfs));
  dummyVfs.pAppData = (void*)&autolockIoFinder;
  dummyVfs.zName = "dummy";
  pUnused->fd = fd;
  pUnused->flags = openFlags;
  pNew->pUnused = pUnused;
  
  rc = fillInUnixFile(&dummyVfs, fd, 0, (sqlite3_file*)pNew, path, 0, 0, 0);
  if( rc==SQLITE_OK ){
    *ppFile = pNew;
    return SQLITE_OK;
  }
end_create_proxy:    
  robust_close(pNew, fd, __LINE__);
  sqlite3_free(pNew);







|







30248
30249
30250
30251
30252
30253
30254
30255
30256
30257
30258
30259
30260
30261
30262
  memset(&dummyVfs, 0, sizeof(dummyVfs));
  dummyVfs.pAppData = (void*)&autolockIoFinder;
  dummyVfs.zName = "dummy";
  pUnused->fd = fd;
  pUnused->flags = openFlags;
  pNew->pUnused = pUnused;
  
  rc = fillInUnixFile(&dummyVfs, fd, dirfd, (sqlite3_file*)pNew, path, 0, 0, 0);
  if( rc==SQLITE_OK ){
    *ppFile = pNew;
    return SQLITE_OK;
  }
end_create_proxy:    
  robust_close(pNew, fd, __LINE__);
  sqlite3_free(pNew);
30418
30419
30420
30421
30422
30423
30424
30425
30426
30427
30428
30429
30430
30431
30432
30433
      int err = errno;
      if( pError ){
        *pError = err;
      }
      return SQLITE_IOERR;
    }
  }
#else
  UNUSED_PARAMETER(pError);
#endif
#ifdef SQLITE_TEST
  /* simulate multiple hosts by creating unique hostid file paths */
  if( sqlite3_hostid_num != 0){
    pHostID[0] = (char)(pHostID[0] + (char)(sqlite3_hostid_num & 0xFF));
  }
#endif







<
<







30288
30289
30290
30291
30292
30293
30294


30295
30296
30297
30298
30299
30300
30301
      int err = errno;
      if( pError ){
        *pError = err;
      }
      return SQLITE_IOERR;
    }
  }


#endif
#ifdef SQLITE_TEST
  /* simulate multiple hosts by creating unique hostid file paths */
  if( sqlite3_hostid_num != 0){
    pHostID[0] = (char)(pHostID[0] + (char)(sqlite3_hostid_num & 0xFF));
  }
#endif
30494
30495
30496
30497
30498
30499
30500
30501
30502
30503
30504
30505
30506
30507
30508
30509
30510
30511
30512
30513
30514
30515
30516
30517
30518
30519
30520
30521
30522
30523
30524
30525
30526
  robust_close(pFile, conchFile->h, __LINE__);
  conchFile->h = fd;
  conchFile->openFlags = O_RDWR | O_CREAT;

end_breaklock:
  if( rc ){
    if( fd>=0 ){
      osUnlink(tPath);
      robust_close(pFile, fd, __LINE__);
    }
    fprintf(stderr, "failed to break stale lock on %s, %s\n", cPath, errmsg);
  }
  return rc;
}

/* Take the requested lock on the conch file and break a stale lock if the 
** host id matches.
*/
static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){
  proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; 
  unixFile *conchFile = pCtx->conchFile;
  int rc = SQLITE_OK;
  int nTries = 0;
  struct timespec conchModTime;
  
  memset(&conchModTime, 0, sizeof(conchModTime));
  do {
    rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
    nTries ++;
    if( rc==SQLITE_BUSY ){
      /* If the lock failed (busy):
       * 1st try: get the mod time of the conch, wait 0.5s and try again. 
       * 2nd try: fail if the mod time changed or host id is different, wait 







|

















<







30362
30363
30364
30365
30366
30367
30368
30369
30370
30371
30372
30373
30374
30375
30376
30377
30378
30379
30380
30381
30382
30383
30384
30385
30386

30387
30388
30389
30390
30391
30392
30393
  robust_close(pFile, conchFile->h, __LINE__);
  conchFile->h = fd;
  conchFile->openFlags = O_RDWR | O_CREAT;

end_breaklock:
  if( rc ){
    if( fd>=0 ){
      unlink(tPath);
      robust_close(pFile, fd, __LINE__);
    }
    fprintf(stderr, "failed to break stale lock on %s, %s\n", cPath, errmsg);
  }
  return rc;
}

/* Take the requested lock on the conch file and break a stale lock if the 
** host id matches.
*/
static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){
  proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; 
  unixFile *conchFile = pCtx->conchFile;
  int rc = SQLITE_OK;
  int nTries = 0;
  struct timespec conchModTime;
  

  do {
    rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
    nTries ++;
    if( rc==SQLITE_BUSY ){
      /* If the lock failed (busy):
       * 1st try: get the mod time of the conch, wait 0.5s and try again. 
       * 2nd try: fail if the mod time changed or host id is different, wait 
30744
30745
30746
30747
30748
30749
30750
30751
30752
30753
30754
30755
30756
30757
30758
30759
30760
30761
30762
30763
        }
      }
      conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, SHARED_LOCK);
      
    end_takeconch:
      OSTRACE(("TRANSPROXY: CLOSE  %d\n", pFile->h));
      if( rc==SQLITE_OK && pFile->openFlags ){
        int fd;
        if( pFile->h>=0 ){
          robust_close(pFile, pFile->h, __LINE__);
        }
        pFile->h = -1;
        fd = robust_open(pCtx->dbPath, pFile->openFlags,
                      SQLITE_DEFAULT_FILE_PERMISSIONS);
        OSTRACE(("TRANSPROXY: OPEN  %d\n", fd));
        if( fd>=0 ){
          pFile->h = fd;
        }else{
          rc=SQLITE_CANTOPEN_BKPT; /* SQLITE_BUSY? proxyTakeConch called
           during locking */







<




|







30611
30612
30613
30614
30615
30616
30617

30618
30619
30620
30621
30622
30623
30624
30625
30626
30627
30628
30629
        }
      }
      conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, SHARED_LOCK);
      
    end_takeconch:
      OSTRACE(("TRANSPROXY: CLOSE  %d\n", pFile->h));
      if( rc==SQLITE_OK && pFile->openFlags ){

        if( pFile->h>=0 ){
          robust_close(pFile, pFile->h, __LINE__);
        }
        pFile->h = -1;
        int fd = robust_open(pCtx->dbPath, pFile->openFlags,
                      SQLITE_DEFAULT_FILE_PERMISSIONS);
        OSTRACE(("TRANSPROXY: OPEN  %d\n", fd));
        if( fd>=0 ){
          pFile->h = fd;
        }else{
          rc=SQLITE_CANTOPEN_BKPT; /* SQLITE_BUSY? proxyTakeConch called
           during locking */
31319
31320
31321
31322
31323
31324
31325
31326
31327
31328
31329
31330
31331
31332
31333
    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)==18 );

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







|







31185
31186
31187
31188
31189
31190
31191
31192
31193
31194
31195
31196
31197
31198
31199
    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)==16 );

  /* 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; 
}
31435
31436
31437
31438
31439
31440
31441
31442
31443
31444
31445
31446
31447
31448
31449
31450
31451
31452
31453
31454
31455
31456
** macro to SQLITE_DEBUG and some older makefiles have not yet made the
** switch.  The following code should catch this problem at compile-time.
*/
#ifdef MEMORY_DEBUG
# error "The MEMORY_DEBUG macro is obsolete.  Use SQLITE_DEBUG instead."
#endif

#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
# ifndef SQLITE_DEBUG_OS_TRACE
#   define SQLITE_DEBUG_OS_TRACE 0
# endif
  int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
# define OSTRACE(X)          if( sqlite3OSTrace ) sqlite3DebugPrintf X
#else
# define OSTRACE(X)
#endif

/*
** Macros for performance tracing.  Normally turned off.  Only works
** on i486 hardware.
*/
#ifdef SQLITE_PERFORMANCE_TRACE







<
|
<
<
|
|

|







31301
31302
31303
31304
31305
31306
31307

31308


31309
31310
31311
31312
31313
31314
31315
31316
31317
31318
31319
** macro to SQLITE_DEBUG and some older makefiles have not yet made the
** switch.  The following code should catch this problem at compile-time.
*/
#ifdef MEMORY_DEBUG
# error "The MEMORY_DEBUG macro is obsolete.  Use SQLITE_DEBUG instead."
#endif


#ifdef SQLITE_DEBUG


SQLITE_PRIVATE int sqlite3OSTrace = 0;
#define OSTRACE(X)          if( sqlite3OSTrace ) sqlite3DebugPrintf X
#else
#define OSTRACE(X)
#endif

/*
** Macros for performance tracing.  Normally turned off.  Only works
** on i486 hardware.
*/
#ifdef SQLITE_PERFORMANCE_TRACE
31654
31655
31656
31657
31658
31659
31660
31661
31662
31663
31664
31665
31666
31667
31668
31669
31670
31671
31672
31673
31674
31675
31676
31677
31678
31679
31680
31681
31682
31683
31684
31685
31686
31687
31688
31689
31690
31691
31692
31693
31694
31695
31696
31697
31698
31699
31700
31701
31702
31703
31704
31705
31706
31707
31708
31709
31710
31711
31712
31713
31714
31715
31716
31717
31718
31719
31720
31721
31722
31723
31724
31725
31726
31727
31728
31729
31730
31731
31732
31733
31734
31735
31736
31737
31738
31739
31740
31741
31742
31743
31744
31745
31746
31747
31748
31749
31750
31751
31752
31753
31754
** portability layer.
*/
typedef struct winFile winFile;
struct winFile {
  const sqlite3_io_methods *pMethod; /*** Must be first ***/
  sqlite3_vfs *pVfs;      /* The VFS used to open this file */
  HANDLE h;               /* Handle for accessing the file */
  u8 locktype;            /* Type of lock currently held on this file */
  short sharedLockByte;   /* Randomly chosen byte used as a shared lock */
  u8 bPersistWal;         /* True to persist WAL files */
  DWORD lastErrno;        /* The Windows errno from the last I/O error */
  DWORD sectorSize;       /* Sector size of the device file is on */
  winShm *pShm;           /* Instance of shared memory on this file */
  const char *zPath;      /* Full pathname of this file */
  int szChunk;            /* Chunk size configured by FCNTL_CHUNK_SIZE */
#if SQLITE_OS_WINCE
  WCHAR *zDeleteOnClose;  /* Name of file to delete when closing */
  HANDLE hMutex;          /* Mutex used to control access to shared lock */  
  HANDLE hShared;         /* Shared memory segment used for locking */
  winceLock local;        /* Locks obtained by this instance of winFile */
  winceLock *shared;      /* Global shared lock memory for the file  */
#endif
};

/*
 * If compiled with SQLITE_WIN32_MALLOC on Windows, we will use the
 * various Win32 API heap functions instead of our own.
 */
#ifdef SQLITE_WIN32_MALLOC
/*
 * The initial size of the Win32-specific heap.  This value may be zero.
 */
#ifndef SQLITE_WIN32_HEAP_INIT_SIZE
#  define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_DEFAULT_CACHE_SIZE) * \
                                       (SQLITE_DEFAULT_PAGE_SIZE) + 4194304)
#endif

/*
 * The maximum size of the Win32-specific heap.  This value may be zero.
 */
#ifndef SQLITE_WIN32_HEAP_MAX_SIZE
#  define SQLITE_WIN32_HEAP_MAX_SIZE  (0)
#endif

/*
 * The extra flags to use in calls to the Win32 heap APIs.  This value may be
 * zero for the default behavior.
 */
#ifndef SQLITE_WIN32_HEAP_FLAGS
#  define SQLITE_WIN32_HEAP_FLAGS     (0)
#endif

/*
** The winMemData structure stores information required by the Win32-specific
** sqlite3_mem_methods implementation.
*/
typedef struct winMemData winMemData;
struct winMemData {
#ifndef NDEBUG
  u32 magic;    /* Magic number to detect structure corruption. */
#endif
  HANDLE hHeap; /* The handle to our heap. */
  BOOL bOwned;  /* Do we own the heap (i.e. destroy it on shutdown)? */
};

#ifndef NDEBUG
#define WINMEM_MAGIC     0x42b2830b
#endif

static struct winMemData win_mem_data = {
#ifndef NDEBUG
  WINMEM_MAGIC,
#endif
  NULL, FALSE
};

#ifndef NDEBUG
#define winMemAssertMagic() assert( win_mem_data.magic==WINMEM_MAGIC )
#else
#define winMemAssertMagic()
#endif

#define winMemGetHeap() win_mem_data.hHeap

static void *winMemMalloc(int nBytes);
static void winMemFree(void *pPrior);
static void *winMemRealloc(void *pPrior, int nBytes);
static int winMemSize(void *p);
static int winMemRoundup(int n);
static int winMemInit(void *pAppData);
static void winMemShutdown(void *pAppData);

SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetWin32(void);
#endif /* SQLITE_WIN32_MALLOC */

/*
** Forward prototypes.
*/
static int getSectorSize(
    sqlite3_vfs *pVfs,
    const char *zRelative     /* UTF-8 file name */







|

<














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







31517
31518
31519
31520
31521
31522
31523
31524
31525

31526
31527
31528
31529
31530
31531
31532
31533
31534
31535
31536
31537
31538
31539






































































31540
31541
31542
31543
31544
31545
31546
** portability layer.
*/
typedef struct winFile winFile;
struct winFile {
  const sqlite3_io_methods *pMethod; /*** Must be first ***/
  sqlite3_vfs *pVfs;      /* The VFS used to open this file */
  HANDLE h;               /* Handle for accessing the file */
  unsigned char locktype; /* Type of lock currently held on this file */
  short sharedLockByte;   /* Randomly chosen byte used as a shared lock */

  DWORD lastErrno;        /* The Windows errno from the last I/O error */
  DWORD sectorSize;       /* Sector size of the device file is on */
  winShm *pShm;           /* Instance of shared memory on this file */
  const char *zPath;      /* Full pathname of this file */
  int szChunk;            /* Chunk size configured by FCNTL_CHUNK_SIZE */
#if SQLITE_OS_WINCE
  WCHAR *zDeleteOnClose;  /* Name of file to delete when closing */
  HANDLE hMutex;          /* Mutex used to control access to shared lock */  
  HANDLE hShared;         /* Shared memory segment used for locking */
  winceLock local;        /* Locks obtained by this instance of winFile */
  winceLock *shared;      /* Global shared lock memory for the file  */
#endif
};








































































/*
** Forward prototypes.
*/
static int getSectorSize(
    sqlite3_vfs *pVfs,
    const char *zRelative     /* UTF-8 file name */
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
31893
31894
31895
31896
31897
31898
31899
31900
31901
31902
31903
31904
31905
31906
31907
31908
31909
31910
31911
31912
31913
31914
31915
31916
31917
31918
31919
31920
31921
31922
31923
31924
31925
31926
31927
31928
31929
31930
31931
31932
31933
31934
31935
31936
31937
31938
31939
31940
31941
31942
31943
31944
31945
31946
31947
31948
31949
31950
31951
31952
31953
31954
31955
31956
31957
31958
31959
31960
31961
31962
31963
31964
31965
31966
31967
31968
31969
31970
31971
31972
31973
31974
31975
31976
31977
31978
31979
31980
31981
31982
31983
31984
31985
31986
31987
31988
      GetVersionEx(&sInfo);
      sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
    }
    return sqlite3_os_type==2;
  }
#endif /* SQLITE_OS_WINCE */

#ifdef SQLITE_WIN32_MALLOC
/*
** Allocate nBytes of memory.
*/
static void *winMemMalloc(int nBytes){
  HANDLE hHeap;
  void *p;

  winMemAssertMagic();
  hHeap = winMemGetHeap();
  assert( hHeap!=0 );
  assert( hHeap!=INVALID_HANDLE_VALUE );
#ifdef SQLITE_WIN32_MALLOC_VALIDATE
  assert ( HeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
#endif
  assert( nBytes>=0 );
  p = HeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
  if( !p ){
    sqlite3_log(SQLITE_NOMEM, "failed to HeapAlloc %u bytes (%d), heap=%p",
        nBytes, GetLastError(), (void*)hHeap);
  }
  return p;
}

/*
** Free memory.
*/
static void winMemFree(void *pPrior){
  HANDLE hHeap;

  winMemAssertMagic();
  hHeap = winMemGetHeap();
  assert( hHeap!=0 );
  assert( hHeap!=INVALID_HANDLE_VALUE );
#ifdef SQLITE_WIN32_MALLOC_VALIDATE
  assert ( HeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
#endif
  if( !pPrior ) return; /* Passing NULL to HeapFree is undefined. */
  if( !HeapFree(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ){
    sqlite3_log(SQLITE_NOMEM, "failed to HeapFree block %p (%d), heap=%p",
        pPrior, GetLastError(), (void*)hHeap);
  }
}

/*
** Change the size of an existing memory allocation
*/
static void *winMemRealloc(void *pPrior, int nBytes){
  HANDLE hHeap;
  void *p;

  winMemAssertMagic();
  hHeap = winMemGetHeap();
  assert( hHeap!=0 );
  assert( hHeap!=INVALID_HANDLE_VALUE );
#ifdef SQLITE_WIN32_MALLOC_VALIDATE
  assert ( HeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
#endif
  assert( nBytes>=0 );
  if( !pPrior ){
    p = HeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
  }else{
    p = HeapReAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior, (SIZE_T)nBytes);
  }
  if( !p ){
    sqlite3_log(SQLITE_NOMEM, "failed to %s %u bytes (%d), heap=%p",
        pPrior ? "HeapReAlloc" : "HeapAlloc", nBytes, GetLastError(),
        (void*)hHeap);
  }
  return p;
}

/*
** Return the size of an outstanding allocation, in bytes.
*/
static int winMemSize(void *p){
  HANDLE hHeap;
  SIZE_T n;

  winMemAssertMagic();
  hHeap = winMemGetHeap();
  assert( hHeap!=0 );
  assert( hHeap!=INVALID_HANDLE_VALUE );
#ifdef SQLITE_WIN32_MALLOC_VALIDATE
  assert ( HeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
#endif
  if( !p ) return 0;
  n = HeapSize(hHeap, SQLITE_WIN32_HEAP_FLAGS, p);
  if( n==(SIZE_T)-1 ){
    sqlite3_log(SQLITE_NOMEM, "failed to HeapSize block %p (%d), heap=%p",
        p, GetLastError(), (void*)hHeap);
    return 0;
  }
  return (int)n;
}

/*
** Round up a request size to the next valid allocation size.
*/
static int winMemRoundup(int n){
  return n;
}

/*
** Initialize this module.
*/
static int winMemInit(void *pAppData){
  winMemData *pWinMemData = (winMemData *)pAppData;

  if( !pWinMemData ) return SQLITE_ERROR;
  assert( pWinMemData->magic==WINMEM_MAGIC );
  if( !pWinMemData->hHeap ){
    pWinMemData->hHeap = HeapCreate(SQLITE_WIN32_HEAP_FLAGS,
                                    SQLITE_WIN32_HEAP_INIT_SIZE,
                                    SQLITE_WIN32_HEAP_MAX_SIZE);
    if( !pWinMemData->hHeap ){
      sqlite3_log(SQLITE_NOMEM,
          "failed to HeapCreate (%d), flags=%u, initSize=%u, maxSize=%u",
          GetLastError(), SQLITE_WIN32_HEAP_FLAGS, SQLITE_WIN32_HEAP_INIT_SIZE,
          SQLITE_WIN32_HEAP_MAX_SIZE);
      return SQLITE_NOMEM;
    }
    pWinMemData->bOwned = TRUE;
  }
  assert( pWinMemData->hHeap!=0 );
  assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
#ifdef SQLITE_WIN32_MALLOC_VALIDATE
  assert( HeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
#endif
  return SQLITE_OK;
}

/*
** Deinitialize this module.
*/
static void winMemShutdown(void *pAppData){
  winMemData *pWinMemData = (winMemData *)pAppData;

  if( !pWinMemData ) return;
  if( pWinMemData->hHeap ){
    assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
#ifdef SQLITE_WIN32_MALLOC_VALIDATE
    assert( HeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
#endif
    if( pWinMemData->bOwned ){
      if( !HeapDestroy(pWinMemData->hHeap) ){
        sqlite3_log(SQLITE_NOMEM, "failed to HeapDestroy (%d), heap=%p",
            GetLastError(), (void*)pWinMemData->hHeap);
      }
      pWinMemData->bOwned = FALSE;
    }
    pWinMemData->hHeap = NULL;
  }
}

/*
** Populate the low-level memory allocation function pointers in
** sqlite3GlobalConfig.m with pointers to the routines in this file. The
** arguments specify the block of memory to manage.
**
** This routine is only called by sqlite3_config(), and therefore
** is not required to be threadsafe (it is not).
*/
SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetWin32(void){
  static const sqlite3_mem_methods winMemMethods = {
    winMemMalloc,
    winMemFree,
    winMemRealloc,
    winMemSize,
    winMemRoundup,
    winMemInit,
    winMemShutdown,
    &win_mem_data
  };
  return &winMemMethods;
}

SQLITE_PRIVATE void sqlite3MemSetDefault(void){
  sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetWin32());
}
#endif /* SQLITE_WIN32_MALLOC */

/*
** Convert a UTF-8 string to microsoft unicode (UTF-16?). 
**
** Space to hold the returned string is obtained from malloc.
*/
static WCHAR *utf8ToUnicode(const char *zFilename){
  int nChar;







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







31585
31586
31587
31588
31589
31590
31591






















































































































































































31592
31593
31594
31595
31596
31597
31598
      GetVersionEx(&sInfo);
      sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
    }
    return sqlite3_os_type==2;
  }
#endif /* SQLITE_OS_WINCE */























































































































































































/*
** Convert a UTF-8 string to microsoft unicode (UTF-16?). 
**
** Space to hold the returned string is obtained from malloc.
*/
static WCHAR *utf8ToUnicode(const char *zFilename){
  int nChar;
32207
32208
32209
32210
32211
32212
32213
32214
32215
32216
32217
32218
32219
32220
32221
32222
32223
32224
32225
32226
32227
32228
32229
32230
32231
32232
32233
32234
32235
32236
32237
32238
32239
32240
32241
32242
32243
32244
32245
32246
32247
32248
32249
32250
32251
32252
32253
32254
32255
32256
32257
32258
32259
32260
32261
32262
32263
32264
32265
32266
32267
32268
32269
32270
32271
32272
32273
32274
32275
32276
32277
      "os_win.c:%d: (%d) %s(%s) - %s",
      iLine, iErrno, zFunc, zPath, zMsg
  );

  return errcode;
}

/*
** The number of times that a ReadFile(), WriteFile(), and DeleteFile()
** will be retried following a locking error - probably caused by 
** antivirus software.  Also the initial delay before the first retry.
** The delay increases linearly with each retry.
*/
#ifndef SQLITE_WIN32_IOERR_RETRY
# define SQLITE_WIN32_IOERR_RETRY 10
#endif
#ifndef SQLITE_WIN32_IOERR_RETRY_DELAY
# define SQLITE_WIN32_IOERR_RETRY_DELAY 25
#endif
static int win32IoerrRetry = SQLITE_WIN32_IOERR_RETRY;
static int win32IoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY;

/*
** If a ReadFile() or WriteFile() error occurs, invoke this routine
** to see if it should be retried.  Return TRUE to retry.  Return FALSE
** to give up with an error.
*/
static int retryIoerr(int *pnRetry){
  DWORD e;
  if( *pnRetry>=win32IoerrRetry ){
    return 0;
  }
  e = GetLastError();
  if( e==ERROR_ACCESS_DENIED ||
      e==ERROR_LOCK_VIOLATION ||
      e==ERROR_SHARING_VIOLATION ){
    Sleep(win32IoerrRetryDelay*(1+*pnRetry));
    ++*pnRetry;
    return 1;
  }
  return 0;
}

/*
** Log a I/O error retry episode.
*/
static void logIoerr(int nRetry){
  if( nRetry ){
    sqlite3_log(SQLITE_IOERR, 
      "delayed %dms for lock/sharing conflict",
      win32IoerrRetryDelay*nRetry*(nRetry+1)/2
    );
  }
}

#if SQLITE_OS_WINCE
/*************************************************************************
** This section contains code for WinCE only.
*/
/*
** WindowsCE 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;
  sqlite3_int64 t64;
  t64 = *t;







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








<







31817
31818
31819
31820
31821
31822
31823
















































31824
31825
31826
31827
31828
31829
31830
31831

31832
31833
31834
31835
31836
31837
31838
      "os_win.c:%d: (%d) %s(%s) - %s",
      iLine, iErrno, zFunc, zPath, zMsg
  );

  return errcode;
}

















































#if SQLITE_OS_WINCE
/*************************************************************************
** This section contains code for WinCE only.
*/
/*
** WindowsCE does not have a localtime() function.  So create a
** substitute.
*/

struct tm *__cdecl localtime(const time_t *t)
{
  static struct tm y;
  FILETIME uTm, lTm;
  SYSTEMTIME pTm;
  sqlite3_int64 t64;
  t64 = *t;
32673
32674
32675
32676
32677
32678
32679
32680
32681
32682
32683
32684
32685
32686
32687
32688
32689
32690
32691
32692
32693
32694
32695
32696
32697
32698
32699
32700
32701
  sqlite3_file *id,          /* File to read from */
  void *pBuf,                /* Write content into this buffer */
  int amt,                   /* Number of bytes to read */
  sqlite3_int64 offset       /* Begin reading at this offset */
){
  winFile *pFile = (winFile*)id;  /* file handle */
  DWORD nRead;                    /* Number of bytes actually read from file */
  int nRetry = 0;                 /* Number of retrys */

  assert( id!=0 );
  SimulateIOError(return SQLITE_IOERR_READ);
  OSTRACE(("READ %d lock=%d\n", pFile->h, pFile->locktype));

  if( seekWinFile(pFile, offset) ){
    return SQLITE_FULL;
  }
  while( !ReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
    if( retryIoerr(&nRetry) ) continue;
    pFile->lastErrno = GetLastError();
    return winLogError(SQLITE_IOERR_READ, "winRead", pFile->zPath);
  }
  logIoerr(nRetry);
  if( nRead<(DWORD)amt ){
    /* Unread parts of the buffer must be zero-filled */
    memset(&((char*)pBuf)[nRead], 0, amt-nRead);
    return SQLITE_IOERR_SHORT_READ;
  }

  return SQLITE_OK;







<








|
<



<







32234
32235
32236
32237
32238
32239
32240

32241
32242
32243
32244
32245
32246
32247
32248
32249

32250
32251
32252

32253
32254
32255
32256
32257
32258
32259
  sqlite3_file *id,          /* File to read from */
  void *pBuf,                /* Write content into this buffer */
  int amt,                   /* Number of bytes to read */
  sqlite3_int64 offset       /* Begin reading at this offset */
){
  winFile *pFile = (winFile*)id;  /* file handle */
  DWORD nRead;                    /* Number of bytes actually read from file */


  assert( id!=0 );
  SimulateIOError(return SQLITE_IOERR_READ);
  OSTRACE(("READ %d lock=%d\n", pFile->h, pFile->locktype));

  if( seekWinFile(pFile, offset) ){
    return SQLITE_FULL;
  }
  if( !ReadFile(pFile->h, pBuf, amt, &nRead, 0) ){

    pFile->lastErrno = GetLastError();
    return winLogError(SQLITE_IOERR_READ, "winRead", pFile->zPath);
  }

  if( nRead<(DWORD)amt ){
    /* Unread parts of the buffer must be zero-filled */
    memset(&((char*)pBuf)[nRead], 0, amt-nRead);
    return SQLITE_IOERR_SHORT_READ;
  }

  return SQLITE_OK;
32709
32710
32711
32712
32713
32714
32715
32716
32717
32718
32719
32720
32721
32722
32723
32724
32725
32726
32727
32728
32729
32730
32731
32732
32733
32734
32735
32736
32737
32738
32739
32740
32741
32742
32743
32744
32745
32746
32747
32748
32749
32750
32751
32752
32753
32754
32755
32756
32757
32758
32759
32760
  sqlite3_file *id,               /* File to write into */
  const void *pBuf,               /* The bytes to be written */
  int amt,                        /* Number of bytes to write */
  sqlite3_int64 offset            /* Offset into the file to begin writing at */
){
  int rc;                         /* True if error has occured, else false */
  winFile *pFile = (winFile*)id;  /* File handle */
  int nRetry = 0;                 /* Number of retries */

  assert( amt>0 );
  assert( pFile );
  SimulateIOError(return SQLITE_IOERR_WRITE);
  SimulateDiskfullError(return SQLITE_FULL);

  OSTRACE(("WRITE %d lock=%d\n", pFile->h, pFile->locktype));

  rc = seekWinFile(pFile, offset);
  if( rc==0 ){
    u8 *aRem = (u8 *)pBuf;        /* Data yet to be written */
    int nRem = amt;               /* Number of bytes yet to be written */
    DWORD nWrite;                 /* Bytes written by each WriteFile() call */

    while( nRem>0 ){
      if( !WriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){
        if( retryIoerr(&nRetry) ) continue;
        break;
      }
      if( nWrite<=0 ) break;
      aRem += nWrite;
      nRem -= nWrite;
    }
    if( nRem>0 ){
      pFile->lastErrno = GetLastError();
      rc = 1;
    }
  }

  if( rc ){
    if(   ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL )
       || ( pFile->lastErrno==ERROR_DISK_FULL )){
      return SQLITE_FULL;
    }
    return winLogError(SQLITE_IOERR_WRITE, "winWrite", pFile->zPath);
  }else{
    logIoerr(nRetry);
  }
  return SQLITE_OK;
}

/*
** Truncate an open file to a specified size
*/







<














<
|
<
<
<
<















<
<







32267
32268
32269
32270
32271
32272
32273

32274
32275
32276
32277
32278
32279
32280
32281
32282
32283
32284
32285
32286
32287

32288




32289
32290
32291
32292
32293
32294
32295
32296
32297
32298
32299
32300
32301
32302
32303


32304
32305
32306
32307
32308
32309
32310
  sqlite3_file *id,               /* File to write into */
  const void *pBuf,               /* The bytes to be written */
  int amt,                        /* Number of bytes to write */
  sqlite3_int64 offset            /* Offset into the file to begin writing at */
){
  int rc;                         /* True if error has occured, else false */
  winFile *pFile = (winFile*)id;  /* File handle */


  assert( amt>0 );
  assert( pFile );
  SimulateIOError(return SQLITE_IOERR_WRITE);
  SimulateDiskfullError(return SQLITE_FULL);

  OSTRACE(("WRITE %d lock=%d\n", pFile->h, pFile->locktype));

  rc = seekWinFile(pFile, offset);
  if( rc==0 ){
    u8 *aRem = (u8 *)pBuf;        /* Data yet to be written */
    int nRem = amt;               /* Number of bytes yet to be written */
    DWORD nWrite;                 /* Bytes written by each WriteFile() call */


    while( nRem>0 && WriteFile(pFile->h, aRem, nRem, &nWrite, 0) && nWrite>0 ){




      aRem += nWrite;
      nRem -= nWrite;
    }
    if( nRem>0 ){
      pFile->lastErrno = GetLastError();
      rc = 1;
    }
  }

  if( rc ){
    if(   ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL )
       || ( pFile->lastErrno==ERROR_DISK_FULL )){
      return SQLITE_FULL;
    }
    return winLogError(SQLITE_IOERR_WRITE, "winWrite", pFile->zPath);


  }
  return SQLITE_OK;
}

/*
** Truncate an open file to a specified size
*/
32768
32769
32770
32771
32772
32773
32774
32775
32776
32777
32778
32779
32780
32781
32782
  SimulateIOError(return SQLITE_IOERR_TRUNCATE);

  /* If the user has configured a chunk-size for this file, truncate the
  ** file so that it consists of an integer number of chunks (i.e. the
  ** actual file size after the operation may be larger than the requested
  ** size).
  */
  if( pFile->szChunk>0 ){
    nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
  }

  /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
  if( seekWinFile(pFile, nByte) ){
    rc = winLogError(SQLITE_IOERR_TRUNCATE, "winTruncate1", pFile->zPath);
  }else if( 0==SetEndOfFile(pFile->h) ){







|







32318
32319
32320
32321
32322
32323
32324
32325
32326
32327
32328
32329
32330
32331
32332
  SimulateIOError(return SQLITE_IOERR_TRUNCATE);

  /* If the user has configured a chunk-size for this file, truncate the
  ** file so that it consists of an integer number of chunks (i.e. the
  ** actual file size after the operation may be larger than the requested
  ** size).
  */
  if( pFile->szChunk ){
    nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
  }

  /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
  if( seekWinFile(pFile, nByte) ){
    rc = winLogError(SQLITE_IOERR_TRUNCATE, "winTruncate1", pFile->zPath);
  }else if( 0==SetEndOfFile(pFile->h) ){
32797
32798
32799
32800
32801
32802
32803
32804
32805
32806
32807
32808
32809
32810
32811
32812
32813
32814
32815
32816

32817
32818
32819
32820
32821
32822
32823
SQLITE_API int sqlite3_fullsync_count = 0;
#endif

/*
** Make sure all writes to a particular file are committed to disk.
*/
static int winSync(sqlite3_file *id, int flags){
#ifndef SQLITE_NO_SYNC
  /*
  ** Used only when SQLITE_NO_SYNC is not defined.
   */
  BOOL rc;
#endif
#if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || \
    (defined(SQLITE_TEST) && defined(SQLITE_DEBUG))
  /*
  ** Used when SQLITE_NO_SYNC is not defined and by the assert() and/or
  ** OSTRACE() macros.
   */
  winFile *pFile = (winFile*)id;

#else
  UNUSED_PARAMETER(id);
#endif

  assert( pFile );
  /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */
  assert((flags&0x0F)==SQLITE_SYNC_NORMAL







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

>







32347
32348
32349
32350
32351
32352
32353






32354





32355
32356
32357
32358
32359
32360
32361
32362
32363
SQLITE_API int sqlite3_fullsync_count = 0;
#endif

/*
** Make sure all writes to a particular file are committed to disk.
*/
static int winSync(sqlite3_file *id, int flags){






#if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || defined(SQLITE_DEBUG)





  winFile *pFile = (winFile*)id;
  BOOL rc;
#else
  UNUSED_PARAMETER(id);
#endif

  assert( pFile );
  /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */
  assert((flags&0x0F)==SQLITE_SYNC_NORMAL
33150
33151
33152
33153
33154
33155
33156
33157
33158
33159
33160
33161
33162
33163
33164
33165
33166
33167
33168
33169
33170
33171
33172
33173
33174
33175
33176
33177
33178
33179
33180
33181
33182
33183
33184
33185
33186
33187
33188
33189
33190
33191
33192
33193
33194
33195
33196
33197
33198
33199
33200
33201
33202
33203
33204
33205
33206
33207
33208
33209
33210
33211
33212
33213
33214
33215
33216
33217
  return rc;
}

/*
** Control and query of the open file handle.
*/
static int winFileControl(sqlite3_file *id, int op, void *pArg){
  winFile *pFile = (winFile*)id;
  switch( op ){
    case SQLITE_FCNTL_LOCKSTATE: {
      *(int*)pArg = pFile->locktype;
      return SQLITE_OK;
    }
    case SQLITE_LAST_ERRNO: {
      *(int*)pArg = (int)pFile->lastErrno;
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_CHUNK_SIZE: {
      pFile->szChunk = *(int *)pArg;
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_SIZE_HINT: {
      if( pFile->szChunk>0 ){
        sqlite3_int64 oldSz;
        int rc = winFileSize(id, &oldSz);
        if( rc==SQLITE_OK ){
          sqlite3_int64 newSz = *(sqlite3_int64*)pArg;
          if( newSz>oldSz ){
            SimulateIOErrorBenign(1);
            rc = winTruncate(id, newSz);
            SimulateIOErrorBenign(0);
          }
        }
        return rc;
      }
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_PERSIST_WAL: {
      int bPersist = *(int*)pArg;
      if( bPersist<0 ){
        *(int*)pArg = pFile->bPersistWal;
      }else{
        pFile->bPersistWal = bPersist!=0;
      }
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_SYNC_OMITTED: {
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_WIN32_AV_RETRY: {
      int *a = (int*)pArg;
      if( a[0]>0 ){
        win32IoerrRetry = a[0];
      }else{
        a[0] = win32IoerrRetry;
      }
      if( a[1]>0 ){
        win32IoerrRetryDelay = a[1];
      }else{
        a[1] = win32IoerrRetryDelay;
      }
      return SQLITE_OK;
    }
  }
  return SQLITE_NOTFOUND;
}

/*







<


|



|



|



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


<
<
<
<
<
<
<
<
<

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







32690
32691
32692
32693
32694
32695
32696

32697
32698
32699
32700
32701
32702
32703
32704
32705
32706
32707
32708
32709
32710

32711




32712
32713
32714




32715
32716









32717














32718
32719
32720
32721
32722
32723
32724
  return rc;
}

/*
** Control and query of the open file handle.
*/
static int winFileControl(sqlite3_file *id, int op, void *pArg){

  switch( op ){
    case SQLITE_FCNTL_LOCKSTATE: {
      *(int*)pArg = ((winFile*)id)->locktype;
      return SQLITE_OK;
    }
    case SQLITE_LAST_ERRNO: {
      *(int*)pArg = (int)((winFile*)id)->lastErrno;
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_CHUNK_SIZE: {
      ((winFile*)id)->szChunk = *(int *)pArg;
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_SIZE_HINT: {

      sqlite3_int64 sz = *(sqlite3_int64*)pArg;




      SimulateIOErrorBenign(1);
      winTruncate(id, sz);
      SimulateIOErrorBenign(0);




      return SQLITE_OK;
    }









    case SQLITE_FCNTL_SYNC_OMITTED: {














      return SQLITE_OK;
    }
  }
  return SQLITE_NOTFOUND;
}

/*
34014
34015
34016
34017
34018
34019
34020
34021
34022
34023
34024
34025
34026
34027
34028
  DWORD dwFlagsAndAttributes = 0;
#if SQLITE_OS_WINCE
  int isTemp = 0;
#endif
  winFile *pFile = (winFile*)id;
  void *zConverted;              /* Filename in OS encoding */
  const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */
  int cnt = 0;

  /* If argument zPath is a NULL pointer, this function is required to open
  ** a temporary file. Use this buffer to store the file name in.
  */
  char zTmpname[MAX_PATH+1];     /* Buffer used to create temp filename */

  int rc = SQLITE_OK;            /* Function Return Code */







<







33521
33522
33523
33524
33525
33526
33527

33528
33529
33530
33531
33532
33533
33534
  DWORD dwFlagsAndAttributes = 0;
#if SQLITE_OS_WINCE
  int isTemp = 0;
#endif
  winFile *pFile = (winFile*)id;
  void *zConverted;              /* Filename in OS encoding */
  const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */


  /* If argument zPath is a NULL pointer, this function is required to open
  ** a temporary file. Use this buffer to store the file name in.
  */
  char zTmpname[MAX_PATH+1];     /* Buffer used to create temp filename */

  int rc = SQLITE_OK;            /* Function Return Code */
34134
34135
34136
34137
34138
34139
34140
34141
34142
34143

34144
34145
34146
34147

34148
34149
34150
34151
34152
34153
34154
34155
34156

34157
34158
34159
34160

34161
34162
34163
34164
34165
34166
34167
34168
34169
34170
34171
34172
  /* Reports from the internet are that performance is always
  ** better if FILE_FLAG_RANDOM_ACCESS is used.  Ticket #2699. */
#if SQLITE_OS_WINCE
  dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
#endif

  if( isNT() ){
    while( (h = CreateFileW((WCHAR*)zConverted,
                            dwDesiredAccess,
                            dwShareMode, NULL,

                            dwCreationDisposition,
                            dwFlagsAndAttributes,
                            NULL))==INVALID_HANDLE_VALUE &&
                            retryIoerr(&cnt) ){}

/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 
** Since the ASCII version of these Windows API do not exist for WINCE,
** it's important to not reference them for WINCE builds.
*/
#if SQLITE_OS_WINCE==0
  }else{
    while( (h = CreateFileA((char*)zConverted,
                            dwDesiredAccess,
                            dwShareMode, NULL,

                            dwCreationDisposition,
                            dwFlagsAndAttributes,
                            NULL))==INVALID_HANDLE_VALUE &&
                            retryIoerr(&cnt) ){}

#endif
  }

  logIoerr(cnt);

  OSTRACE(("OPEN %d %s 0x%lx %s\n", 
           h, zName, dwDesiredAccess, 
           h==INVALID_HANDLE_VALUE ? "failed" : "ok"));

  if( h==INVALID_HANDLE_VALUE ){
    pFile->lastErrno = GetLastError();
    winLogError(SQLITE_CANTOPEN, "winOpen", zUtf8Name);







|
|
|
>
|
|
|
<
>






|
|
|
>
|
|
|
<
>



<
<







33640
33641
33642
33643
33644
33645
33646
33647
33648
33649
33650
33651
33652
33653

33654
33655
33656
33657
33658
33659
33660
33661
33662
33663
33664
33665
33666
33667

33668
33669
33670
33671


33672
33673
33674
33675
33676
33677
33678
  /* Reports from the internet are that performance is always
  ** better if FILE_FLAG_RANDOM_ACCESS is used.  Ticket #2699. */
#if SQLITE_OS_WINCE
  dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
#endif

  if( isNT() ){
    h = CreateFileW((WCHAR*)zConverted,
       dwDesiredAccess,
       dwShareMode,
       NULL,
       dwCreationDisposition,
       dwFlagsAndAttributes,
       NULL

    );
/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 
** Since the ASCII version of these Windows API do not exist for WINCE,
** it's important to not reference them for WINCE builds.
*/
#if SQLITE_OS_WINCE==0
  }else{
    h = CreateFileA((char*)zConverted,
       dwDesiredAccess,
       dwShareMode,
       NULL,
       dwCreationDisposition,
       dwFlagsAndAttributes,
       NULL

    );
#endif
  }



  OSTRACE(("OPEN %d %s 0x%lx %s\n", 
           h, zName, dwDesiredAccess, 
           h==INVALID_HANDLE_VALUE ? "failed" : "ok"));

  if( h==INVALID_HANDLE_VALUE ){
    pFile->lastErrno = GetLastError();
    winLogError(SQLITE_CANTOPEN, "winOpen", zUtf8Name);
34224
34225
34226
34227
34228
34229
34230

34231
34232
34233
34234
34235
34236
34237

34238
34239
34240
34241
34242
34243
34244
34245
34246
34247
34248
34249

34250

34251


34252
34253
34254
34255
34256
34257
34258
34259

34260

34261


34262
34263
34264
34265
34266
34267
34268
34269
34270



34271


34272
34273
34274
34275
34276
34277
34278
** will open a journal file shortly after it is created in order to do
** whatever it does.  While this other process is holding the
** file open, we will be unable to delete it.  To work around this
** problem, we delay 100 milliseconds and try to delete again.  Up
** to MX_DELETION_ATTEMPTs deletion attempts are run before giving
** up and returning an error.
*/

static int winDelete(
  sqlite3_vfs *pVfs,          /* Not used on win32 */
  const char *zFilename,      /* Name of file to delete */
  int syncDir                 /* Not used on win32 */
){
  int cnt = 0;
  int rc;

  void *zConverted;
  UNUSED_PARAMETER(pVfs);
  UNUSED_PARAMETER(syncDir);

  SimulateIOError(return SQLITE_IOERR_DELETE);
  zConverted = convertUtf8Filename(zFilename);
  if( zConverted==0 ){
    return SQLITE_NOMEM;
  }
  if( isNT() ){
    rc = 1;
    while( GetFileAttributesW(zConverted)!=INVALID_FILE_ATTRIBUTES &&

           (rc = DeleteFileW(zConverted))==0 && retryIoerr(&cnt) ){}

    rc = rc ? SQLITE_OK : SQLITE_ERROR;


/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 
** Since the ASCII version of these Windows API do not exist for WINCE,
** it's important to not reference them for WINCE builds.
*/
#if SQLITE_OS_WINCE==0
  }else{
    rc = 1;
    while( GetFileAttributesA(zConverted)!=INVALID_FILE_ATTRIBUTES &&

           (rc = DeleteFileA(zConverted))==0 && retryIoerr(&cnt) ){}

    rc = rc ? SQLITE_OK : SQLITE_ERROR;


#endif
  }
  if( rc ){
    rc = winLogError(SQLITE_IOERR_DELETE, "winDelete", zFilename);
  }else{
    logIoerr(cnt);
  }
  free(zConverted);
  OSTRACE(("DELETE \"%s\" %s\n", zFilename, (rc ? "failed" : "ok" )));



  return rc;


}

/*
** Check the existance and status of a file.
*/
static int winAccess(
  sqlite3_vfs *pVfs,         /* Not used on win32 */







>






|
>










<
<
>
|
>
|
>
>






<
<
>
|
>
|
>
>


<
<
<
<
<

|
>
>
>
|
>
>







33730
33731
33732
33733
33734
33735
33736
33737
33738
33739
33740
33741
33742
33743
33744
33745
33746
33747
33748
33749
33750
33751
33752
33753
33754
33755


33756
33757
33758
33759
33760
33761
33762
33763
33764
33765
33766
33767


33768
33769
33770
33771
33772
33773
33774
33775





33776
33777
33778
33779
33780
33781
33782
33783
33784
33785
33786
33787
33788
33789
33790
** will open a journal file shortly after it is created in order to do
** whatever it does.  While this other process is holding the
** file open, we will be unable to delete it.  To work around this
** problem, we delay 100 milliseconds and try to delete again.  Up
** to MX_DELETION_ATTEMPTs deletion attempts are run before giving
** up and returning an error.
*/
#define MX_DELETION_ATTEMPTS 5
static int winDelete(
  sqlite3_vfs *pVfs,          /* Not used on win32 */
  const char *zFilename,      /* Name of file to delete */
  int syncDir                 /* Not used on win32 */
){
  int cnt = 0;
  DWORD rc;
  DWORD error = 0;
  void *zConverted;
  UNUSED_PARAMETER(pVfs);
  UNUSED_PARAMETER(syncDir);

  SimulateIOError(return SQLITE_IOERR_DELETE);
  zConverted = convertUtf8Filename(zFilename);
  if( zConverted==0 ){
    return SQLITE_NOMEM;
  }
  if( isNT() ){


    do{
      DeleteFileW(zConverted);
    }while(   (   ((rc = GetFileAttributesW(zConverted)) != INVALID_FILE_ATTRIBUTES)
               || ((error = GetLastError()) == ERROR_ACCESS_DENIED))
           && (++cnt < MX_DELETION_ATTEMPTS)
           && (Sleep(100), 1) );
/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 
** Since the ASCII version of these Windows API do not exist for WINCE,
** it's important to not reference them for WINCE builds.
*/
#if SQLITE_OS_WINCE==0
  }else{


    do{
      DeleteFileA(zConverted);
    }while(   (   ((rc = GetFileAttributesA(zConverted)) != INVALID_FILE_ATTRIBUTES)
               || ((error = GetLastError()) == ERROR_ACCESS_DENIED))
           && (++cnt < MX_DELETION_ATTEMPTS)
           && (Sleep(100), 1) );
#endif
  }





  free(zConverted);
  OSTRACE(("DELETE \"%s\" %s\n", zFilename,
       ( (rc==INVALID_FILE_ATTRIBUTES) && (error==ERROR_FILE_NOT_FOUND)) ?
         "ok" : "failed" ));
 
  return (   (rc == INVALID_FILE_ATTRIBUTES) 
          && (error == ERROR_FILE_NOT_FOUND)) ? SQLITE_OK :
                 winLogError(SQLITE_IOERR_DELETE, "winDelete", zFilename);
}

/*
** Check the existance and status of a file.
*/
static int winAccess(
  sqlite3_vfs *pVfs,         /* Not used on win32 */
34287
34288
34289
34290
34291
34292
34293
34294
34295
34296
34297
34298
34299
34300
34301
34302
34303
34304
34305
34306
34307
34308
34309
34310
34311
34312
34313
34314
34315
34316
34317
34318
34319

  SimulateIOError( return SQLITE_IOERR_ACCESS; );
  zConverted = convertUtf8Filename(zFilename);
  if( zConverted==0 ){
    return SQLITE_NOMEM;
  }
  if( isNT() ){
    int cnt = 0;
    WIN32_FILE_ATTRIBUTE_DATA sAttrData;
    memset(&sAttrData, 0, sizeof(sAttrData));
    while( !(rc = GetFileAttributesExW((WCHAR*)zConverted,
                             GetFileExInfoStandard, 
                             &sAttrData)) && retryIoerr(&cnt) ){}
    if( rc ){
      /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
      ** as if it does not exist.
      */
      if(    flags==SQLITE_ACCESS_EXISTS
          && sAttrData.nFileSizeHigh==0 
          && sAttrData.nFileSizeLow==0 ){
        attr = INVALID_FILE_ATTRIBUTES;
      }else{
        attr = sAttrData.dwFileAttributes;
      }
    }else{
      logIoerr(cnt);
      if( GetLastError()!=ERROR_FILE_NOT_FOUND ){
        winLogError(SQLITE_IOERR_ACCESS, "winAccess", zFilename);
        free(zConverted);
        return SQLITE_IOERR_ACCESS;
      }else{
        attr = INVALID_FILE_ATTRIBUTES;
      }







<


|

|
<











<







33799
33800
33801
33802
33803
33804
33805

33806
33807
33808
33809
33810

33811
33812
33813
33814
33815
33816
33817
33818
33819
33820
33821

33822
33823
33824
33825
33826
33827
33828

  SimulateIOError( return SQLITE_IOERR_ACCESS; );
  zConverted = convertUtf8Filename(zFilename);
  if( zConverted==0 ){
    return SQLITE_NOMEM;
  }
  if( isNT() ){

    WIN32_FILE_ATTRIBUTE_DATA sAttrData;
    memset(&sAttrData, 0, sizeof(sAttrData));
    if( GetFileAttributesExW((WCHAR*)zConverted,
                             GetFileExInfoStandard, 
                             &sAttrData) ){

      /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
      ** as if it does not exist.
      */
      if(    flags==SQLITE_ACCESS_EXISTS
          && sAttrData.nFileSizeHigh==0 
          && sAttrData.nFileSizeLow==0 ){
        attr = INVALID_FILE_ATTRIBUTES;
      }else{
        attr = sAttrData.dwFileAttributes;
      }
    }else{

      if( GetLastError()!=ERROR_FILE_NOT_FOUND ){
        winLogError(SQLITE_IOERR_ACCESS, "winAccess", zFilename);
        free(zConverted);
        return SQLITE_IOERR_ACCESS;
      }else{
        attr = INVALID_FILE_ATTRIBUTES;
      }
34330
34331
34332
34333
34334
34335
34336
34337
34338
34339
34340
34341
34342
34343
34344
34345
  free(zConverted);
  switch( flags ){
    case SQLITE_ACCESS_READ:
    case SQLITE_ACCESS_EXISTS:
      rc = attr!=INVALID_FILE_ATTRIBUTES;
      break;
    case SQLITE_ACCESS_READWRITE:
      rc = attr!=INVALID_FILE_ATTRIBUTES &&
             (attr & FILE_ATTRIBUTE_READONLY)==0;
      break;
    default:
      assert(!"Invalid flags argument");
  }
  *pResOut = rc;
  return SQLITE_OK;
}







<
|







33839
33840
33841
33842
33843
33844
33845

33846
33847
33848
33849
33850
33851
33852
33853
  free(zConverted);
  switch( flags ){
    case SQLITE_ACCESS_READ:
    case SQLITE_ACCESS_EXISTS:
      rc = attr!=INVALID_FILE_ATTRIBUTES;
      break;
    case SQLITE_ACCESS_READWRITE:

      rc = (attr & FILE_ATTRIBUTE_READONLY)==0;
      break;
    default:
      assert(!"Invalid flags argument");
  }
  *pResOut = rc;
  return SQLITE_OK;
}
35787
35788
35789
35790
35791
35792
35793
35794
35795
35796
35797
35798
35799
35800
35801
35802
35803


typedef struct PCache1 PCache1;
typedef struct PgHdr1 PgHdr1;
typedef struct PgFreeslot PgFreeslot;
typedef struct PGroup PGroup;

typedef struct PGroupBlock PGroupBlock;
typedef struct PGroupBlockList PGroupBlockList;

/* Each page cache (or PCache) belongs to a PGroup.  A PGroup is a set 
** of one or more PCaches that are able to recycle each others unpinned
** pages when they are under memory pressure.  A PGroup is an instance of
** the following object.
**
** This page cache implementation works in one of two modes:
**







<
<
<







35295
35296
35297
35298
35299
35300
35301



35302
35303
35304
35305
35306
35307
35308


typedef struct PCache1 PCache1;
typedef struct PgHdr1 PgHdr1;
typedef struct PgFreeslot PgFreeslot;
typedef struct PGroup PGroup;




/* Each page cache (or PCache) belongs to a PGroup.  A PGroup is a set 
** of one or more PCaches that are able to recycle each others unpinned
** pages when they are under memory pressure.  A PGroup is an instance of
** the following object.
**
** This page cache implementation works in one of two modes:
**
35819
35820
35821
35822
35823
35824
35825
35826
35827
35828
35829
35830
35831
35832
35833
35834
35835
35836
35837
35838
35839
35840
35841
35842
35843
35844
35845
35846
35847
35848
35849
35850
35851
35852
35853
35854
35855
35856
35857
35858
35859
35860
35861
35862
35863
35864
35865
35866
35867
35868
35869
35870
35871
35872
35873
35874
35875
35876
35877
35878
35879
35880
35881
35882
35883
35884
35885
35886
35887
35888
35889
35890
35891
struct PGroup {
  sqlite3_mutex *mutex;          /* MUTEX_STATIC_LRU or NULL */
  int nMaxPage;                  /* Sum of nMax for purgeable caches */
  int nMinPage;                  /* Sum of nMin for purgeable caches */
  int mxPinned;                  /* nMaxpage + 10 - nMinPage */
  int nCurrentPage;              /* Number of purgeable pages allocated */
  PgHdr1 *pLruHead, *pLruTail;   /* LRU list of unpinned pages */
#ifdef SQLITE_PAGECACHE_BLOCKALLOC
  int isBusy;                    /* Do not run ReleaseMemory() if true */
  PGroupBlockList *pBlockList;   /* List of block-lists for this group */
#endif
};

/*
** If SQLITE_PAGECACHE_BLOCKALLOC is defined when the library is built,
** each PGroup structure has a linked list of the the following starting
** at PGroup.pBlockList. There is one entry for each distinct page-size 
** currently used by members of the PGroup (i.e. 1024 bytes, 4096 bytes
** etc.). Variable PGroupBlockList.nByte is set to the actual allocation
** size requested by each pcache, which is the database page-size plus
** the various header structures used by the pcache, pager and btree layers.
** Usually around (pgsz+200) bytes.
**
** This size (pgsz+200) bytes is not allocated efficiently by some
** implementations of malloc. In particular, some implementations are only
** able to allocate blocks of memory chunks of 2^N bytes, where N is some
** integer value. Since the page-size is a power of 2, this means we
** end up wasting (pgsz-200) bytes in each allocation.
**
** If SQLITE_PAGECACHE_BLOCKALLOC is defined, the (pgsz+200) byte blocks
** are not allocated directly. Instead, blocks of roughly M*(pgsz+200) bytes 
** are requested from malloc allocator. After a block is returned,
** sqlite3MallocSize() is used to determine how many (pgsz+200) byte
** allocations can fit in the space returned by malloc(). This value may
** be more than M.
**
** The blocks are stored in a doubly-linked list. Variable PGroupBlock.nEntry
** contains the number of allocations that will fit in the aData[] space.
** nEntry is limited to the number of bits in bitmask mUsed. If a slot
** within aData is in use, the corresponding bit in mUsed is set. Thus
** when (mUsed+1==(1 << nEntry)) the block is completely full.
**
** Each time a slot within a block is freed, the block is moved to the start
** of the linked-list. And if a block becomes completely full, then it is
** moved to the end of the list. As a result, when searching for a free
** slot, only the first block in the list need be examined. If it is full,
** then it is guaranteed that all blocks are full.
*/
struct PGroupBlockList {
  int nByte;                     /* Size of each allocation in bytes */
  PGroupBlock *pFirst;           /* First PGroupBlock in list */
  PGroupBlock *pLast;            /* Last PGroupBlock in list */
  PGroupBlockList *pNext;        /* Next block-list attached to group */
};

struct PGroupBlock {
  Bitmask mUsed;                 /* Mask of used slots */
  int nEntry;                    /* Maximum number of allocations in aData[] */
  u8 *aData;                     /* Pointer to data block */
  PGroupBlock *pNext;            /* Next PGroupBlock in list */
  PGroupBlock *pPrev;            /* Previous PGroupBlock in list */
  PGroupBlockList *pList;        /* Owner list */
};

/* Minimum value for PGroupBlock.nEntry */
#define PAGECACHE_BLOCKALLOC_MINENTRY 15

/* Each page cache is an instance of the following object.  Every
** open database file (including each in-memory database and each
** temporary or transient database) has a single page cache which
** is an instance of this object.
**
** Pointers to structures of this type are cast and returned as 







<
<
<
<

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







35324
35325
35326
35327
35328
35329
35330




35331






















































35332
35333
35334
35335
35336
35337
35338
struct PGroup {
  sqlite3_mutex *mutex;          /* MUTEX_STATIC_LRU or NULL */
  int nMaxPage;                  /* Sum of nMax for purgeable caches */
  int nMinPage;                  /* Sum of nMin for purgeable caches */
  int mxPinned;                  /* nMaxpage + 10 - nMinPage */
  int nCurrentPage;              /* Number of purgeable pages allocated */
  PgHdr1 *pLruHead, *pLruTail;   /* LRU list of unpinned pages */




};























































/* Each page cache is an instance of the following object.  Every
** open database file (including each in-memory database and each
** temporary or transient database) has a single page cache which
** is an instance of this object.
**
** Pointers to structures of this type are cast and returned as 
35981
35982
35983
35984
35985
35986
35987
35988
35989
35990
35991
35992
35993
35994
35995
35996
35997
35998
35999
36000
36001
36002
36003
36004
36005
** a pointer to a block of szPage bytes of data and the return value is
** a pointer to the associated PgHdr1 structure.
**
**   assert( PGHDR1_TO_PAGE(PAGE_TO_PGHDR1(pCache, X))==X );
*/
#define PGHDR1_TO_PAGE(p)    (void*)(((char*)p) - p->pCache->szPage)
#define PAGE_TO_PGHDR1(c, p) (PgHdr1*)(((char*)p) + c->szPage)

/*
** Blocks used by the SQLITE_PAGECACHE_BLOCKALLOC blocks to store/retrieve 
** a PGroupBlock pointer based on a pointer to a page buffer. 
*/
#define PAGE_SET_BLOCKPTR(pCache, pPg, pBlock) \
  ( *(PGroupBlock **)&(((u8*)pPg)[sizeof(PgHdr1) + pCache->szPage]) = pBlock )

#define PAGE_GET_BLOCKPTR(pCache, pPg) \
  ( *(PGroupBlock **)&(((u8*)pPg)[sizeof(PgHdr1) + pCache->szPage]) )


/*
** Macros to enter and leave the PCache LRU mutex.
*/
#define pcache1EnterMutex(X) sqlite3_mutex_enter((X)->mutex)
#define pcache1LeaveMutex(X) sqlite3_mutex_leave((X)->mutex)








<
<
<
<
<
<
<
<
<
<
<







35428
35429
35430
35431
35432
35433
35434











35435
35436
35437
35438
35439
35440
35441
** a pointer to a block of szPage bytes of data and the return value is
** a pointer to the associated PgHdr1 structure.
**
**   assert( PGHDR1_TO_PAGE(PAGE_TO_PGHDR1(pCache, X))==X );
*/
#define PGHDR1_TO_PAGE(p)    (void*)(((char*)p) - p->pCache->szPage)
#define PAGE_TO_PGHDR1(c, p) (PgHdr1*)(((char*)p) + c->szPage)












/*
** Macros to enter and leave the PCache LRU mutex.
*/
#define pcache1EnterMutex(X) sqlite3_mutex_enter((X)->mutex)
#define pcache1LeaveMutex(X) sqlite3_mutex_leave((X)->mutex)

36118
36119
36120
36121
36122
36123
36124
36125
36126
36127
36128
36129
36130
36131
36132
36133
36134
36135
36136
36137
36138
36139
36140
36141
36142
36143
36144
36145
36146
36147
36148
36149
36150
36151
36152
36153
36154
36155
36156
36157
36158
36159
36160
36161
36162
36163
36164
36165
36166
36167
36168
36169
36170
36171
36172
36173
36174
36175
36176
36177
36178
36179
36180
36181
36182
36183
36184
36185
36186
36187
36188
36189
36190
36191
36192
36193
36194
36195
36196
36197
36198
36199
36200
36201
36202
36203
36204
36205
36206
36207
36208
36209
36210
36211
36212
36213
36214
36215
36216
36217
36218
36219
36220
36221
36222
36223
36224
36225
36226
36227
36228
36229
36230
36231
36232
36233
36234
36235
36236
36237
36238
36239
36240
36241
36242
36243
36244
36245
36246
36247
36248
36249
36250
36251
36252
36253
36254
36255
36256
36257
36258
36259
36260
36261
36262
36263
36264
36265
36266
36267
36268
36269
36270
36271
36272
36273
36274
36275
36276
36277
36278
36279
36280
36281
36282
36283
36284
36285
36286
36287
36288
36289
36290
36291
36292
36293
36294
36295
36296
36297
36298
36299
36300
36301
36302
36303
36304
36305
36306
36307
36308
36309
36310
36311
36312
36313
36314
36315
36316
36317
36318
36319
36320
36321
36322
36323
36324
36325
36326
36327
36328
36329
36330
36331
36332

36333
36334
36335
36336
36337
36338
36339
    iSize = sqlite3MallocSize(p);
    sqlite3MemdebugSetType(p, MEMTYPE_PCACHE);
    return iSize;
  }
}
#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */

#ifdef SQLITE_PAGECACHE_BLOCKALLOC
/*
** The block pBlock belongs to list pList but is not currently linked in.
** Insert it into the start of the list.
*/
static void addBlockToList(PGroupBlockList *pList, PGroupBlock *pBlock){
  pBlock->pPrev = 0;
  pBlock->pNext = pList->pFirst;
  pList->pFirst = pBlock;
  if( pBlock->pNext ){
    pBlock->pNext->pPrev = pBlock;
  }else{
    assert( pList->pLast==0 );
    pList->pLast = pBlock;
  }
}

/*
** If there are no blocks in the list headed by pList, remove pList
** from the pGroup->pBlockList list and free it with sqlite3_free().
*/
static void freeListIfEmpty(PGroup *pGroup, PGroupBlockList *pList){
  assert( sqlite3_mutex_held(pGroup->mutex) );
  if( pList->pFirst==0 ){
    PGroupBlockList **pp;
    for(pp=&pGroup->pBlockList; *pp!=pList; pp=&(*pp)->pNext);
    *pp = (*pp)->pNext;
    sqlite3_free(pList);
  }
}
#endif /* SQLITE_PAGECACHE_BLOCKALLOC */

/*
** Allocate a new page object initially associated with cache pCache.
*/
static PgHdr1 *pcache1AllocPage(PCache1 *pCache){
  int nByte = sizeof(PgHdr1) + pCache->szPage;
  void *pPg = 0;
  PgHdr1 *p;

#ifdef SQLITE_PAGECACHE_BLOCKALLOC
  PGroup *pGroup = pCache->pGroup;
  PGroupBlockList *pList;
  PGroupBlock *pBlock;
  int i;

  nByte += sizeof(PGroupBlockList *);
  nByte = ROUND8(nByte);

  for(pList=pGroup->pBlockList; pList; pList=pList->pNext){
    if( pList->nByte==nByte ) break;
  }
  if( pList==0 ){
    PGroupBlockList *pNew;
    assert( pGroup->isBusy==0 );
    assert( sqlite3_mutex_held(pGroup->mutex) );
    pGroup->isBusy = 1;  /* Disable sqlite3PcacheReleaseMemory() */
    pNew = (PGroupBlockList *)sqlite3MallocZero(sizeof(PGroupBlockList));
    pGroup->isBusy = 0;  /* Reenable sqlite3PcacheReleaseMemory() */
    if( pNew==0 ){
      /* malloc() failure. Return early. */
      return 0;
    }
#ifdef SQLITE_DEBUG
    for(pList=pGroup->pBlockList; pList; pList=pList->pNext){
      assert( pList->nByte!=nByte );
    }
#endif
    pNew->nByte = nByte;
    pNew->pNext = pGroup->pBlockList;
    pGroup->pBlockList = pNew;
    pList = pNew;
  }

  pBlock = pList->pFirst;
  if( pBlock==0 || pBlock->mUsed==(((Bitmask)1<<pBlock->nEntry)-1) ){
    int sz;

    /* Allocate a new block. Try to allocate enough space for the PGroupBlock
    ** structure and MINENTRY allocations of nByte bytes each. If the 
    ** allocator returns more memory than requested, then more than MINENTRY 
    ** allocations may fit in it. */
    assert( sqlite3_mutex_held(pGroup->mutex) );
    pcache1LeaveMutex(pCache->pGroup);
    sz = sizeof(PGroupBlock) + PAGECACHE_BLOCKALLOC_MINENTRY * nByte;
    pBlock = (PGroupBlock *)sqlite3Malloc(sz);
    pcache1EnterMutex(pCache->pGroup);

    if( !pBlock ){
      freeListIfEmpty(pGroup, pList);
      return 0;
    }
    pBlock->nEntry = (sqlite3MallocSize(pBlock) - sizeof(PGroupBlock)) / nByte;
    if( pBlock->nEntry>=BMS ){
      pBlock->nEntry = BMS-1;
    }
    pBlock->pList = pList;
    pBlock->mUsed = 0;
    pBlock->aData = (u8 *)&pBlock[1];
    addBlockToList(pList, pBlock);

    sz = sqlite3MallocSize(pBlock);
    sqlite3_mutex_enter(pcache1.mutex);
    sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
    sqlite3_mutex_leave(pcache1.mutex);
  }

  for(i=0; pPg==0 && ALWAYS(i<pBlock->nEntry); i++){
    if( 0==(pBlock->mUsed & ((Bitmask)1<<i)) ){
      pBlock->mUsed |= ((Bitmask)1<<i);
      pPg = (void *)&pBlock->aData[pList->nByte * i];
    }
  }
  assert( pPg );
  PAGE_SET_BLOCKPTR(pCache, pPg, pBlock);

  /* If the block is now full, shift it to the end of the list */
  if( pBlock->mUsed==(((Bitmask)1<<pBlock->nEntry)-1) && pList->pLast!=pBlock ){
    assert( pList->pFirst==pBlock );
    assert( pBlock->pPrev==0 );
    assert( pList->pLast->pNext==0 );
    pList->pFirst = pBlock->pNext;
    pList->pFirst->pPrev = 0;
    pBlock->pPrev = pList->pLast;
    pBlock->pNext = 0;
    pList->pLast->pNext = pBlock;
    pList->pLast = pBlock;
  }
  p = PAGE_TO_PGHDR1(pCache, pPg);
  if( pCache->bPurgeable ){
    pCache->pGroup->nCurrentPage++;
  }
#else
  /* The group mutex must be released before pcache1Alloc() is called. This
  ** is because it may call sqlite3_release_memory(), which assumes that 
  ** this mutex is not held. */
  assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
  pcache1LeaveMutex(pCache->pGroup);
  pPg = pcache1Alloc(nByte);
  pcache1EnterMutex(pCache->pGroup);
  if( pPg ){
    p = PAGE_TO_PGHDR1(pCache, pPg);
    if( pCache->bPurgeable ){
      pCache->pGroup->nCurrentPage++;
    }
  }else{
    p = 0;
  }
#endif
  return p;
}

/*
** Free a page object allocated by pcache1AllocPage().
**
** The pointer is allowed to be NULL, which is prudent.  But it turns out
** that the current implementation happens to never call this routine
** with a NULL pointer, so we mark the NULL test with ALWAYS().
*/
static void pcache1FreePage(PgHdr1 *p){
  if( ALWAYS(p) ){
    PCache1 *pCache = p->pCache;
    void *pPg = PGHDR1_TO_PAGE(p);

#ifdef SQLITE_PAGECACHE_BLOCKALLOC
    PGroupBlock *pBlock = PAGE_GET_BLOCKPTR(pCache, pPg);
    PGroupBlockList *pList = pBlock->pList;
    int i = ((u8 *)pPg - pBlock->aData) / pList->nByte;

    assert( pPg==(void *)&pBlock->aData[i*pList->nByte] );
    assert( pBlock->mUsed & ((Bitmask)1<<i) );
    pBlock->mUsed &= ~((Bitmask)1<<i);

    /* Remove the block from the list. If it is completely empty, free it.
    ** Or if it is not completely empty, re-insert it at the start of the
    ** list. */
    if( pList->pFirst==pBlock ){
      pList->pFirst = pBlock->pNext;
      if( pList->pFirst ) pList->pFirst->pPrev = 0;
    }else{
      pBlock->pPrev->pNext = pBlock->pNext;
    }
    if( pList->pLast==pBlock ){
      pList->pLast = pBlock->pPrev;
      if( pList->pLast ) pList->pLast->pNext = 0;
    }else{
      pBlock->pNext->pPrev = pBlock->pPrev;
    }

    if( pBlock->mUsed==0 ){
      PGroup *pGroup = p->pCache->pGroup;

      int sz = sqlite3MallocSize(pBlock);
      sqlite3_mutex_enter(pcache1.mutex);
      sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -sz);
      sqlite3_mutex_leave(pcache1.mutex);
      freeListIfEmpty(pGroup, pList);
      sqlite3_free(pBlock);
    }else{
      addBlockToList(pList, pBlock);
    }
#else
    assert( sqlite3_mutex_held(p->pCache->pGroup->mutex) );
    pcache1Free(pPg);
#endif
    if( pCache->bPurgeable ){
      pCache->pGroup->nCurrentPage--;
    }

  }
}

/*
** Malloc function used by SQLite to obtain space from the buffer configured
** using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no such buffer
** exists, this function falls back to sqlite3Malloc().







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





|

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








<













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



>







35554
35555
35556
35557
35558
35559
35560
































35561
35562
35563
35564
35565
35566
35567





































































































35568
35569
35570
35571
35572
35573
35574
35575

35576
35577
35578
35579
35580
35581
35582
35583
35584
35585
35586
35587
35588











































35589
35590
35591
35592
35593
35594
35595
35596
35597
35598
35599
    iSize = sqlite3MallocSize(p);
    sqlite3MemdebugSetType(p, MEMTYPE_PCACHE);
    return iSize;
  }
}
#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */

































/*
** Allocate a new page object initially associated with cache pCache.
*/
static PgHdr1 *pcache1AllocPage(PCache1 *pCache){
  int nByte = sizeof(PgHdr1) + pCache->szPage;
  void *pPg = pcache1Alloc(nByte);
  PgHdr1 *p;





































































































  if( pPg ){
    p = PAGE_TO_PGHDR1(pCache, pPg);
    if( pCache->bPurgeable ){
      pCache->pGroup->nCurrentPage++;
    }
  }else{
    p = 0;
  }

  return p;
}

/*
** Free a page object allocated by pcache1AllocPage().
**
** The pointer is allowed to be NULL, which is prudent.  But it turns out
** that the current implementation happens to never call this routine
** with a NULL pointer, so we mark the NULL test with ALWAYS().
*/
static void pcache1FreePage(PgHdr1 *p){
  if( ALWAYS(p) ){
    PCache1 *pCache = p->pCache;











































    if( pCache->bPurgeable ){
      pCache->pGroup->nCurrentPage--;
    }
    pcache1Free(PGHDR1_TO_PAGE(p));
  }
}

/*
** Malloc function used by SQLite to obtain space from the buffer configured
** using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no such buffer
** exists, this function falls back to sqlite3Malloc().
36763
36764
36765
36766
36767
36768
36769

36770

36771
36772
36773
36774
36775
36776
36777
  }

  /* Step 5. If a usable page buffer has still not been found, 
  ** attempt to allocate a new one. 
  */
  if( !pPage ){
    if( createFlag==1 ) sqlite3BeginBenignMalloc();

    pPage = pcache1AllocPage(pCache);

    if( createFlag==1 ) sqlite3EndBenignMalloc();
  }

  if( pPage ){
    unsigned int h = iKey % pCache->nHash;
    pCache->nPage++;
    pPage->iKey = iKey;







>

>







36023
36024
36025
36026
36027
36028
36029
36030
36031
36032
36033
36034
36035
36036
36037
36038
36039
  }

  /* Step 5. If a usable page buffer has still not been found, 
  ** attempt to allocate a new one. 
  */
  if( !pPage ){
    if( createFlag==1 ) sqlite3BeginBenignMalloc();
    pcache1LeaveMutex(pGroup);
    pPage = pcache1AllocPage(pCache);
    pcache1EnterMutex(pGroup);
    if( createFlag==1 ) sqlite3EndBenignMalloc();
  }

  if( pPage ){
    unsigned int h = iKey % pCache->nHash;
    pCache->nPage++;
    pPage->iKey = iKey;
36933
36934
36935
36936
36937
36938
36939
36940
36941
36942
36943
36944
36945
36946
36947
36948
36949
**
** nReq is the number of bytes of memory required. Once this much has
** been released, the function returns. The return value is the total number 
** of bytes of memory released.
*/
SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){
  int nFree = 0;
#ifdef SQLITE_PAGECACHE_BLOCKALLOC
  if( pcache1.grp.isBusy ) return 0;
#endif
  assert( sqlite3_mutex_notheld(pcache1.grp.mutex) );
  assert( sqlite3_mutex_notheld(pcache1.mutex) );
  if( pcache1.pStart==0 ){
    PgHdr1 *p;
    pcache1EnterMutex(&pcache1.grp);
    while( (nReq<0 || nFree<nReq) && ((p=pcache1.grp.pLruTail)!=0) ){
      nFree += pcache1MemSize(PGHDR1_TO_PAGE(p));







<
<
<







36195
36196
36197
36198
36199
36200
36201



36202
36203
36204
36205
36206
36207
36208
**
** nReq is the number of bytes of memory required. Once this much has
** been released, the function returns. The return value is the total number 
** of bytes of memory released.
*/
SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){
  int nFree = 0;



  assert( sqlite3_mutex_notheld(pcache1.grp.mutex) );
  assert( sqlite3_mutex_notheld(pcache1.mutex) );
  if( pcache1.pStart==0 ){
    PgHdr1 *p;
    pcache1EnterMutex(&pcache1.grp);
    while( (nReq<0 || nFree<nReq) && ((p=pcache1.grp.pLruTail)!=0) ){
      nFree += pcache1MemSize(PGHDR1_TO_PAGE(p));
41267
41268
41269
41270
41271
41272
41273
41274
41275
41276
41277
41278
41279
41280
41281
** is made to roll it back. If an error occurs during the rollback 
** a hot journal may be left in the filesystem but no error is returned
** to the caller.
*/
SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){
  u8 *pTmp = (u8 *)pPager->pTmpSpace;

  assert( assert_pager_state(pPager) );
  disable_simulated_io_errors();
  sqlite3BeginBenignMalloc();
  /* pPager->errCode = 0; */
  pPager->exclusiveMode = 0;
#ifndef SQLITE_OMIT_WAL
  sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, pPager->pageSize, pTmp);
  pPager->pWal = 0;







<







40526
40527
40528
40529
40530
40531
40532

40533
40534
40535
40536
40537
40538
40539
** is made to roll it back. If an error occurs during the rollback 
** a hot journal may be left in the filesystem but no error is returned
** to the caller.
*/
SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){
  u8 *pTmp = (u8 *)pPager->pTmpSpace;


  disable_simulated_io_errors();
  sqlite3BeginBenignMalloc();
  /* pPager->errCode = 0; */
  pPager->exclusiveMode = 0;
#ifndef SQLITE_OMIT_WAL
  sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, pPager->pageSize, pTmp);
  pPager->pWal = 0;
46165
46166
46167
46168
46169
46170
46171
46172
46173
46174
46175
46176
46177
46178
46179
46180
46181
46182
46183
46184
46185
46186
46187
    ** the database. In this case checkpoint the database and unlink both
    ** the wal and wal-index files.
    **
    ** The EXCLUSIVE lock is not released before returning.
    */
    rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE);
    if( rc==SQLITE_OK ){
      int bPersistWal = -1;
      if( pWal->exclusiveMode==WAL_NORMAL_MODE ){
        pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
      }
      rc = sqlite3WalCheckpoint(
          pWal, SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0
      );
      sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_PERSIST_WAL, &bPersistWal);
      if( rc==SQLITE_OK && bPersistWal!=1 ){
        isDelete = 1;
      }
    }

    walIndexClose(pWal, isDelete);
    sqlite3OsClose(pWal->pWalFd);
    if( isDelete ){







<






<
|







45423
45424
45425
45426
45427
45428
45429

45430
45431
45432
45433
45434
45435

45436
45437
45438
45439
45440
45441
45442
45443
    ** the database. In this case checkpoint the database and unlink both
    ** the wal and wal-index files.
    **
    ** The EXCLUSIVE lock is not released before returning.
    */
    rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE);
    if( rc==SQLITE_OK ){

      if( pWal->exclusiveMode==WAL_NORMAL_MODE ){
        pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
      }
      rc = sqlite3WalCheckpoint(
          pWal, SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0
      );

      if( rc==SQLITE_OK ){
        isDelete = 1;
      }
    }

    walIndexClose(pWal, isDelete);
    sqlite3OsClose(pWal->pWalFd);
    if( isDelete ){
48907
48908
48909
48910
48911
48912
48913
48914
48915
48916
48917
48918
48919
48920
48921
48922
48923
48924
48925
48926
48927
48928
48929
48930
48931
48932
48933
48934
48935
  i64 nKey,           /* Integer key for tables.  Size of pKey for indices */
  int bias,           /* Bias search to the high end */
  int *pRes           /* Write search results here */
){
  int rc;                    /* Status code */
  UnpackedRecord *pIdxKey;   /* Unpacked index key */
  char aSpace[150];          /* Temp space for pIdxKey - to avoid a malloc */
  char *pFree = 0;

  if( pKey ){
    assert( nKey==(i64)(int)nKey );
    pIdxKey = sqlite3VdbeAllocUnpackedRecord(
        pCur->pKeyInfo, aSpace, sizeof(aSpace), &pFree
    );
    if( pIdxKey==0 ) return SQLITE_NOMEM;
    sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey);
  }else{
    pIdxKey = 0;
  }
  rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes);
  if( pFree ){
    sqlite3DbFree(pCur->pKeyInfo->db, pFree);
  }
  return rc;
}

/*
** Restore the cursor to the position it was in (or as close to as possible)
** when saveCursorPosition() was called. Note that this call deletes the 







<



|
|
<

<




|
|







48163
48164
48165
48166
48167
48168
48169

48170
48171
48172
48173
48174

48175

48176
48177
48178
48179
48180
48181
48182
48183
48184
48185
48186
48187
48188
  i64 nKey,           /* Integer key for tables.  Size of pKey for indices */
  int bias,           /* Bias search to the high end */
  int *pRes           /* Write search results here */
){
  int rc;                    /* Status code */
  UnpackedRecord *pIdxKey;   /* Unpacked index key */
  char aSpace[150];          /* Temp space for pIdxKey - to avoid a malloc */


  if( pKey ){
    assert( nKey==(i64)(int)nKey );
    pIdxKey = sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey,
                                      aSpace, sizeof(aSpace));

    if( pIdxKey==0 ) return SQLITE_NOMEM;

  }else{
    pIdxKey = 0;
  }
  rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes);
  if( pKey ){
    sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
  }
  return rc;
}

/*
** Restore the cursor to the position it was in (or as close to as possible)
** when saveCursorPosition() was called. Note that this call deletes the 
50997
50998
50999
51000
51001
51002
51003
51004
51005
51006
51007
51008
51009

51010
51011
51012
51013
51014
51015
51016
    nCell = pPage->nCell;

    for(i=0; i<nCell; i++){
      u8 *pCell = findCell(pPage, i);
      if( eType==PTRMAP_OVERFLOW1 ){
        CellInfo info;
        btreeParseCellPtr(pPage, pCell, &info);
        if( info.iOverflow
         && pCell+info.iOverflow+3<=pPage->aData+pPage->maskPage
         && iFrom==get4byte(&pCell[info.iOverflow])
        ){
          put4byte(&pCell[info.iOverflow], iTo);
          break;

        }
      }else{
        if( get4byte(pCell)==iFrom ){
          put4byte(pCell, iTo);
          break;
        }
      }







|
<
|
<
|
|
>







50250
50251
50252
50253
50254
50255
50256
50257

50258

50259
50260
50261
50262
50263
50264
50265
50266
50267
50268
    nCell = pPage->nCell;

    for(i=0; i<nCell; i++){
      u8 *pCell = findCell(pPage, i);
      if( eType==PTRMAP_OVERFLOW1 ){
        CellInfo info;
        btreeParseCellPtr(pPage, pCell, &info);
        if( info.iOverflow ){

          if( iFrom==get4byte(&pCell[info.iOverflow]) ){

            put4byte(&pCell[info.iOverflow], iTo);
            break;
          }
        }
      }else{
        if( get4byte(pCell)==iFrom ){
          put4byte(pCell, iTo);
          break;
        }
      }
51723
51724
51725
51726
51727
51728
51729
51730
51731
51732
51733
51734
51735
51736
51737
51738
  assert( wrFlag==0 || p->inTrans==TRANS_WRITE );
  assert( pBt->pPage1 && pBt->pPage1->aData );

  if( NEVER(wrFlag && pBt->readOnly) ){
    return SQLITE_READONLY;
  }
  if( iTable==1 && btreePagecount(pBt)==0 ){
    assert( wrFlag==0 );
    iTable = 0;
  }

  /* Now that no other errors can occur, finish filling in the BtCursor
  ** variables and link the cursor into the BtShared list.  */
  pCur->pgnoRoot = (Pgno)iTable;
  pCur->iPage = -1;
  pCur->pKeyInfo = pKeyInfo;







|
<







50975
50976
50977
50978
50979
50980
50981
50982

50983
50984
50985
50986
50987
50988
50989
  assert( wrFlag==0 || p->inTrans==TRANS_WRITE );
  assert( pBt->pPage1 && pBt->pPage1->aData );

  if( NEVER(wrFlag && pBt->readOnly) ){
    return SQLITE_READONLY;
  }
  if( iTable==1 && btreePagecount(pBt)==0 ){
    return SQLITE_EMPTY;

  }

  /* Now that no other errors can occur, finish filling in the BtCursor
  ** variables and link the cursor into the BtShared list.  */
  pCur->pgnoRoot = (Pgno)iTable;
  pCur->iPage = -1;
  pCur->pKeyInfo = pKeyInfo;
52478
52479
52480
52481
52482
52483
52484
52485
52486
52487
52488
52489
52490
52491
52492
52493
52494

  if( pCur->iPage>=0 ){
    int i;
    for(i=1; i<=pCur->iPage; i++){
      releasePage(pCur->apPage[i]);
    }
    pCur->iPage = 0;
  }else if( pCur->pgnoRoot==0 ){
    pCur->eState = CURSOR_INVALID;
    return SQLITE_OK;
  }else{
    rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0]);
    if( rc!=SQLITE_OK ){
      pCur->eState = CURSOR_INVALID;
      return rc;
    }
    pCur->iPage = 0;







<
<
<







51729
51730
51731
51732
51733
51734
51735



51736
51737
51738
51739
51740
51741
51742

  if( pCur->iPage>=0 ){
    int i;
    for(i=1; i<=pCur->iPage; i++){
      releasePage(pCur->apPage[i]);
    }
    pCur->iPage = 0;



  }else{
    rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0]);
    if( rc!=SQLITE_OK ){
      pCur->eState = CURSOR_INVALID;
      return rc;
    }
    pCur->iPage = 0;
52590
52591
52592
52593
52594
52595
52596
52597
52598
52599
52600
52601
52602
52603
52604
  int rc;

  assert( cursorHoldsMutex(pCur) );
  assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
  rc = moveToRoot(pCur);
  if( rc==SQLITE_OK ){
    if( pCur->eState==CURSOR_INVALID ){
      assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
      *pRes = 1;
    }else{
      assert( pCur->apPage[pCur->iPage]->nCell>0 );
      *pRes = 0;
      rc = moveToLeftmost(pCur);
    }
  }







|







51838
51839
51840
51841
51842
51843
51844
51845
51846
51847
51848
51849
51850
51851
51852
  int rc;

  assert( cursorHoldsMutex(pCur) );
  assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
  rc = moveToRoot(pCur);
  if( rc==SQLITE_OK ){
    if( pCur->eState==CURSOR_INVALID ){
      assert( pCur->apPage[pCur->iPage]->nCell==0 );
      *pRes = 1;
    }else{
      assert( pCur->apPage[pCur->iPage]->nCell>0 );
      *pRes = 0;
      rc = moveToLeftmost(pCur);
    }
  }
52629
52630
52631
52632
52633
52634
52635
52636
52637
52638
52639
52640
52641
52642
52643
#endif
    return SQLITE_OK;
  }

  rc = moveToRoot(pCur);
  if( rc==SQLITE_OK ){
    if( CURSOR_INVALID==pCur->eState ){
      assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
      *pRes = 1;
    }else{
      assert( pCur->eState==CURSOR_VALID );
      *pRes = 0;
      rc = moveToRightmost(pCur);
      pCur->atLast = rc==SQLITE_OK ?1:0;
    }







|







51877
51878
51879
51880
51881
51882
51883
51884
51885
51886
51887
51888
51889
51890
51891
#endif
    return SQLITE_OK;
  }

  rc = moveToRoot(pCur);
  if( rc==SQLITE_OK ){
    if( CURSOR_INVALID==pCur->eState ){
      assert( pCur->apPage[pCur->iPage]->nCell==0 );
      *pRes = 1;
    }else{
      assert( pCur->eState==CURSOR_VALID );
      *pRes = 0;
      rc = moveToRightmost(pCur);
      pCur->atLast = rc==SQLITE_OK ?1:0;
    }
52702
52703
52704
52705
52706
52707
52708
52709
52710
52711
52712
52713
52714
52715
52716
52717
52718
52719
52720
52721
    }
  }

  rc = moveToRoot(pCur);
  if( rc ){
    return rc;
  }
  assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage] );
  assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->isInit );
  assert( pCur->eState==CURSOR_INVALID || pCur->apPage[pCur->iPage]->nCell>0 );
  if( pCur->eState==CURSOR_INVALID ){
    *pRes = -1;
    assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
    return SQLITE_OK;
  }
  assert( pCur->apPage[0]->intKey || pIdxKey );
  for(;;){
    int lwr, upr, idx;
    Pgno chldPg;
    MemPage *pPage = pCur->apPage[pCur->iPage];







|
|
|


|







51950
51951
51952
51953
51954
51955
51956
51957
51958
51959
51960
51961
51962
51963
51964
51965
51966
51967
51968
51969
    }
  }

  rc = moveToRoot(pCur);
  if( rc ){
    return rc;
  }
  assert( pCur->apPage[pCur->iPage] );
  assert( pCur->apPage[pCur->iPage]->isInit );
  assert( pCur->apPage[pCur->iPage]->nCell>0 || pCur->eState==CURSOR_INVALID );
  if( pCur->eState==CURSOR_INVALID ){
    *pRes = -1;
    assert( pCur->apPage[pCur->iPage]->nCell==0 );
    return SQLITE_OK;
  }
  assert( pCur->apPage[0]->intKey || pIdxKey );
  for(;;){
    int lwr, upr, idx;
    Pgno chldPg;
    MemPage *pPage = pCur->apPage[pCur->iPage];
53434
53435
53436
53437
53438
53439
53440
53441
53442
53443
53444
53445
53446
53447
53448
53449
53450
  u32 ovflPageSize;

  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  btreeParseCellPtr(pPage, pCell, &info);
  if( info.iOverflow==0 ){
    return SQLITE_OK;  /* No overflow pages. Return without doing anything */
  }
  if( pCell+info.iOverflow+3 > pPage->aData+pPage->maskPage ){
    return SQLITE_CORRUPT;  /* Cell extends past end of page */
  }
  ovflPgno = get4byte(&pCell[info.iOverflow]);
  assert( pBt->usableSize > 4 );
  ovflPageSize = pBt->usableSize - 4;
  nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize;
  assert( ovflPgno==0 || nOvfl>0 );
  while( nOvfl-- ){
    Pgno iNext = 0;







<
<
<







52682
52683
52684
52685
52686
52687
52688



52689
52690
52691
52692
52693
52694
52695
  u32 ovflPageSize;

  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  btreeParseCellPtr(pPage, pCell, &info);
  if( info.iOverflow==0 ){
    return SQLITE_OK;  /* No overflow pages. Return without doing anything */
  }



  ovflPgno = get4byte(&pCell[info.iOverflow]);
  assert( pBt->usableSize > 4 );
  ovflPageSize = pBt->usableSize - 4;
  nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize;
  assert( ovflPgno==0 || nOvfl>0 );
  while( nOvfl-- ){
    Pgno iNext = 0;
55620
55621
55622
55623
55624
55625
55626
55627
55628
55629
55630
55631
55632
55633
55634
55635
55636
55637
55638
** SQLITE_OK is returned if the operation is successfully executed. 
** Otherwise, if an error is encountered (i.e. an IO error or database
** corruption) an SQLite error code is returned.
*/
SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
  i64 nEntry = 0;                      /* Value to return in *pnEntry */
  int rc;                              /* Return code */

  if( pCur->pgnoRoot==0 ){
    *pnEntry = 0;
    return SQLITE_OK;
  }
  rc = moveToRoot(pCur);

  /* Unless an error occurs, the following loop runs one iteration for each
  ** page in the B-Tree structure (not including overflow pages). 
  */
  while( rc==SQLITE_OK ){
    int iIdx;                          /* Index of child node in parent */







<
<
<
<
<







54865
54866
54867
54868
54869
54870
54871





54872
54873
54874
54875
54876
54877
54878
** SQLITE_OK is returned if the operation is successfully executed. 
** Otherwise, if an error is encountered (i.e. an IO error or database
** corruption) an SQLite error code is returned.
*/
SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
  i64 nEntry = 0;                      /* Value to return in *pnEntry */
  int rc;                              /* Return code */





  rc = moveToRoot(pCur);

  /* Unless an error occurs, the following loop runs one iteration for each
  ** page in the B-Tree structure (not including overflow pages). 
  */
  while( rc==SQLITE_OK ){
    int iIdx;                          /* Index of child node in parent */
56409
56410
56411
56412
56413
56414
56415

56416
56417
56418
56419
56420
56421
56422
** "write version" (single byte at byte offset 19) fields in the database
** header to iVersion.
*/
SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
  BtShared *pBt = pBtree->pBt;
  int rc;                         /* Return code */
 

  assert( iVersion==1 || iVersion==2 );

  /* If setting the version fields to 1, do not automatically open the
  ** WAL connection, even if the version fields are currently set to 2.
  */
  pBt->doNotUseWAL = (u8)(iVersion==1);








>







55649
55650
55651
55652
55653
55654
55655
55656
55657
55658
55659
55660
55661
55662
55663
** "write version" (single byte at byte offset 19) fields in the database
** header to iVersion.
*/
SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
  BtShared *pBt = pBtree->pBt;
  int rc;                         /* Return code */
 
  assert( pBtree->inTrans==TRANS_NONE );
  assert( iVersion==1 || iVersion==2 );

  /* If setting the version fields to 1, do not automatically open the
  ** WAL connection, even if the version fields are currently set to 2.
  */
  pBt->doNotUseWAL = (u8)(iVersion==1);

56847
56848
56849
56850
56851
56852
56853
56854
56855


56856
56857
56858
56859
56860
56861
56862
56863
56864
56865
56866
56867
56868
56869
56870
56871
56872
56873
56874
56875
56876
56877
56878
56879
56880
56881
56882
56883
56884
56885
56886
56887
56888
56889
56890
56891
56892
56893
56894
56895
56896
56897
56898
56899
56900
56901
56902
56903
56904
56905
56906
56907
56908
56909
56910
56911
56912
56913
56914
56915
56916
56917
56918
56919
56920
56921
56922
56923
56924
56925
56926
56927
56928
56929
56930
56931
56932
56933
56934
56935
56936
56937
56938
56939
56940
56941
56942
56943
56944
56945
56946
56947
56948
56949
56950
56951
56952
56953
56954
56955
56956
56957
56958
56959
56960
    }
  
    /* Update the schema version field in the destination database. This
    ** is to make sure that the schema-version really does change in
    ** the case where the source and destination databases have the
    ** same schema version.
    */
    if( rc==SQLITE_DONE ){
      rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1);


      if( rc==SQLITE_OK ){
        if( p->pDestDb ){
          sqlite3ResetInternalSchema(p->pDestDb, -1);
        }
        if( destMode==PAGER_JOURNALMODE_WAL ){
          rc = sqlite3BtreeSetVersion(p->pDest, 2);
        }
      }
      if( rc==SQLITE_OK ){
        int nDestTruncate;
        /* Set nDestTruncate to the final number of pages in the destination
        ** database. The complication here is that the destination page
        ** size may be different to the source page size. 
        **
        ** If the source page size is smaller than the destination page size, 
        ** round up. In this case the call to sqlite3OsTruncate() below will
        ** fix the size of the file. However it is important to call
        ** sqlite3PagerTruncateImage() here so that any pages in the 
        ** destination file that lie beyond the nDestTruncate page mark are
        ** journalled by PagerCommitPhaseOne() before they are destroyed
        ** by the file truncation.
        */
        assert( pgszSrc==sqlite3BtreeGetPageSize(p->pSrc) );
        assert( pgszDest==sqlite3BtreeGetPageSize(p->pDest) );
        if( pgszSrc<pgszDest ){
          int ratio = pgszDest/pgszSrc;
          nDestTruncate = (nSrcPage+ratio-1)/ratio;
          if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){
            nDestTruncate--;
          }
        }else{
          nDestTruncate = nSrcPage * (pgszSrc/pgszDest);
        }
        sqlite3PagerTruncateImage(pDestPager, nDestTruncate);

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

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

          /* This call ensures that all data required to recreate the original
          ** database has been stored in the journal for pDestPager and the
          ** journal synced to disk. So at this point we may safely modify
          ** the database file in any way, knowing that if a power failure
          ** occurs, the original database will be reconstructed from the 
          ** journal file.  */
          rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1);

          /* Write the extra pages and truncate the database file as required */
          iEnd = MIN(PENDING_BYTE + pgszDest, iSize);
          for(
            iOff=PENDING_BYTE+pgszSrc; 
            rc==SQLITE_OK && iOff<iEnd; 
            iOff+=pgszSrc
          ){
            PgHdr *pSrcPg = 0;
            const Pgno iSrcPg = (Pgno)((iOff/pgszSrc)+1);
            rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg);
            if( rc==SQLITE_OK ){
              u8 *zData = sqlite3PagerGetData(pSrcPg);
              rc = sqlite3OsWrite(pFile, zData, pgszSrc, iOff);
            }
            sqlite3PagerUnref(pSrcPg);
          }
          if( rc==SQLITE_OK ){
            rc = backupTruncateFile(pFile, iSize);
          }

          /* Sync the database file to disk. */
          if( rc==SQLITE_OK ){
            rc = sqlite3PagerSync(pDestPager);
          }
        }else{
          rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0);
        }
    
        /* Finish committing the transaction to the destination database. */
        if( SQLITE_OK==rc
         && SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(p->pDest, 0))
        ){
          rc = SQLITE_DONE;
        }
      }
    }
  
    /* If bCloseTrans is true, then this function opened a read transaction
    ** on the source database. Close the read transaction here. There is
    ** no need to check the return values of the btree methods here, as
    ** "committing" a read-only transaction cannot fail.







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

|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|

|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

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







56088
56089
56090
56091
56092
56093
56094
56095
56096
56097
56098
56099
56100
56101
56102


56103



56104
56105
56106
56107
56108
56109
56110
56111
56112
56113
56114
56115
56116
56117
56118
56119
56120
56121
56122
56123
56124
56125
56126
56127
56128
56129
56130
56131
56132
56133
56134
56135
56136
56137
56138
56139
56140
56141
56142
56143
56144
56145
56146
56147
56148
56149
56150
56151
56152
56153
56154
56155
56156
56157
56158
56159
56160
56161
56162
56163
56164
56165
56166
56167
56168
56169
56170
56171
56172
56173
56174
56175
56176
56177
56178
56179
56180
56181
56182
56183
56184
56185
56186
56187
56188
56189
56190

56191
56192
56193
56194
56195
56196
56197
    }
  
    /* Update the schema version field in the destination database. This
    ** is to make sure that the schema-version really does change in
    ** the case where the source and destination databases have the
    ** same schema version.
    */
    if( rc==SQLITE_DONE 
     && (rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1))==SQLITE_OK
    ){
      int nDestTruncate;
  
      if( p->pDestDb ){
        sqlite3ResetInternalSchema(p->pDestDb, -1);
      }






      /* Set nDestTruncate to the final number of pages in the destination
      ** database. The complication here is that the destination page
      ** size may be different to the source page size. 
      **
      ** If the source page size is smaller than the destination page size, 
      ** round up. In this case the call to sqlite3OsTruncate() below will
      ** fix the size of the file. However it is important to call
      ** sqlite3PagerTruncateImage() here so that any pages in the 
      ** destination file that lie beyond the nDestTruncate page mark are
      ** journalled by PagerCommitPhaseOne() before they are destroyed
      ** by the file truncation.
      */
      assert( pgszSrc==sqlite3BtreeGetPageSize(p->pSrc) );
      assert( pgszDest==sqlite3BtreeGetPageSize(p->pDest) );
      if( pgszSrc<pgszDest ){
        int ratio = pgszDest/pgszSrc;
        nDestTruncate = (nSrcPage+ratio-1)/ratio;
        if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){
          nDestTruncate--;
        }
      }else{
        nDestTruncate = nSrcPage * (pgszSrc/pgszDest);
      }
      sqlite3PagerTruncateImage(pDestPager, nDestTruncate);

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

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

        /* This call ensures that all data required to recreate the original
        ** database has been stored in the journal for pDestPager and the
        ** journal synced to disk. So at this point we may safely modify
        ** the database file in any way, knowing that if a power failure
        ** occurs, the original database will be reconstructed from the 
        ** journal file.  */
        rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1);

        /* Write the extra pages and truncate the database file as required. */
        iEnd = MIN(PENDING_BYTE + pgszDest, iSize);
        for(
          iOff=PENDING_BYTE+pgszSrc; 
          rc==SQLITE_OK && iOff<iEnd; 
          iOff+=pgszSrc
        ){
          PgHdr *pSrcPg = 0;
          const Pgno iSrcPg = (Pgno)((iOff/pgszSrc)+1);
          rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg);
          if( rc==SQLITE_OK ){
            u8 *zData = sqlite3PagerGetData(pSrcPg);
            rc = sqlite3OsWrite(pFile, zData, pgszSrc, iOff);
          }
          sqlite3PagerUnref(pSrcPg);
        }
        if( rc==SQLITE_OK ){
          rc = backupTruncateFile(pFile, iSize);
        }

        /* Sync the database file to disk. */
        if( rc==SQLITE_OK ){
          rc = sqlite3PagerSync(pDestPager);
        }
      }else{
        rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0);
      }
  
      /* Finish committing the transaction to the destination database. */
      if( SQLITE_OK==rc
       && SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(p->pDest, 0))
      ){
        rc = SQLITE_DONE;

      }
    }
  
    /* If bCloseTrans is true, then this function opened a read transaction
    ** on the source database. Close the read transaction here. There is
    ** no need to check the return values of the btree methods here, as
    ** "committing" a read-only transaction cannot fail.
57414
57415
57416
57417
57418
57419
57420





57421
57422
57423
57424
57425
57426
57427
57428
57429
57430
57431
57432

57433
57434
57435
57436
57437
57438
57439
57440
57441
57442
57443
57444
57445
57446
57447
57448
57449
/*
** If the memory cell contains a string value that must be freed by
** invoking an external callback, free it now. Calling this function
** does not free any Mem.zMalloc buffer.
*/
SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p){
  assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) );





  if( p->flags&MEM_Agg ){
    sqlite3VdbeMemFinalize(p, p->u.pDef);
    assert( (p->flags & MEM_Agg)==0 );
    sqlite3VdbeMemRelease(p);
  }else if( p->flags&MEM_Dyn && p->xDel ){
    assert( (p->flags&MEM_RowSet)==0 );
    p->xDel((void *)p->z);
    p->xDel = 0;
  }else if( p->flags&MEM_RowSet ){
    sqlite3RowSetClear(p->u.pRowSet);
  }else if( p->flags&MEM_Frame ){
    sqlite3VdbeMemSetNull(p);

  }
}

/*
** Release any memory held by the Mem. This may leave the Mem in an
** inconsistent state, for example with (Mem.z==0) and
** (Mem.type==SQLITE_TEXT).
*/
SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p){
  MemReleaseExt(p);
  sqlite3DbFree(p->db, p->zMalloc);
  p->z = 0;
  p->zMalloc = 0;
  p->xDel = 0;
}

/*







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









|







56651
56652
56653
56654
56655
56656
56657
56658
56659
56660
56661
56662
56663
56664
56665
56666
56667
56668
56669
56670
56671
56672
56673
56674
56675
56676
56677
56678
56679
56680
56681
56682
56683
56684
56685
56686
56687
56688
56689
56690
56691
56692
/*
** If the memory cell contains a string value that must be freed by
** invoking an external callback, free it now. Calling this function
** does not free any Mem.zMalloc buffer.
*/
SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p){
  assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) );
  testcase( p->flags & MEM_Agg );
  testcase( p->flags & MEM_Dyn );
  testcase( p->flags & MEM_RowSet );
  testcase( p->flags & MEM_Frame );
  if( p->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame) ){
    if( p->flags&MEM_Agg ){
      sqlite3VdbeMemFinalize(p, p->u.pDef);
      assert( (p->flags & MEM_Agg)==0 );
      sqlite3VdbeMemRelease(p);
    }else if( p->flags&MEM_Dyn && p->xDel ){
      assert( (p->flags&MEM_RowSet)==0 );
      p->xDel((void *)p->z);
      p->xDel = 0;
    }else if( p->flags&MEM_RowSet ){
      sqlite3RowSetClear(p->u.pRowSet);
    }else if( p->flags&MEM_Frame ){
      sqlite3VdbeMemSetNull(p);
    }
  }
}

/*
** Release any memory held by the Mem. This may leave the Mem in an
** inconsistent state, for example with (Mem.z==0) and
** (Mem.type==SQLITE_TEXT).
*/
SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p){
  sqlite3VdbeMemReleaseExternal(p);
  sqlite3DbFree(p->db, p->zMalloc);
  p->z = 0;
  p->zMalloc = 0;
  p->xDel = 0;
}

/*
57757
57758
57759
57760
57761
57762
57763
57764
57765
57766
57767
57768
57769
57770
57771
57772
57773
57774
57775
57776
57777
57778
57779
57780
57781
57782
57783
57784
57785
57786
57787
57788
57789
** Make an shallow copy of pFrom into pTo.  Prior contents of
** pTo are freed.  The pFrom->z field is not duplicated.  If
** pFrom->z is used, then pTo->z points to the same thing as pFrom->z
** and flags gets srcType (either MEM_Ephem or MEM_Static).
*/
SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
  assert( (pFrom->flags & MEM_RowSet)==0 );
  MemReleaseExt(pTo);
  memcpy(pTo, pFrom, MEMCELLSIZE);
  pTo->xDel = 0;
  if( (pFrom->flags&MEM_Static)==0 ){
    pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Ephem);
    assert( srcType==MEM_Ephem || srcType==MEM_Static );
    pTo->flags |= srcType;
  }
}

/*
** Make a full copy of pFrom into pTo.  Prior contents of pTo are
** freed before the copy is made.
*/
SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
  int rc = SQLITE_OK;

  assert( (pFrom->flags & MEM_RowSet)==0 );
  MemReleaseExt(pTo);
  memcpy(pTo, pFrom, MEMCELLSIZE);
  pTo->flags &= ~MEM_Dyn;

  if( pTo->flags&(MEM_Str|MEM_Blob) ){
    if( 0==(pFrom->flags&MEM_Static) ){
      pTo->flags |= MEM_Ephem;
      rc = sqlite3VdbeMemMakeWriteable(pTo);







|

















|







57000
57001
57002
57003
57004
57005
57006
57007
57008
57009
57010
57011
57012
57013
57014
57015
57016
57017
57018
57019
57020
57021
57022
57023
57024
57025
57026
57027
57028
57029
57030
57031
57032
** Make an shallow copy of pFrom into pTo.  Prior contents of
** pTo are freed.  The pFrom->z field is not duplicated.  If
** pFrom->z is used, then pTo->z points to the same thing as pFrom->z
** and flags gets srcType (either MEM_Ephem or MEM_Static).
*/
SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
  assert( (pFrom->flags & MEM_RowSet)==0 );
  sqlite3VdbeMemReleaseExternal(pTo);
  memcpy(pTo, pFrom, MEMCELLSIZE);
  pTo->xDel = 0;
  if( (pFrom->flags&MEM_Static)==0 ){
    pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Ephem);
    assert( srcType==MEM_Ephem || srcType==MEM_Static );
    pTo->flags |= srcType;
  }
}

/*
** Make a full copy of pFrom into pTo.  Prior contents of pTo are
** freed before the copy is made.
*/
SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
  int rc = SQLITE_OK;

  assert( (pFrom->flags & MEM_RowSet)==0 );
  sqlite3VdbeMemReleaseExternal(pTo);
  memcpy(pTo, pFrom, MEMCELLSIZE);
  pTo->flags &= ~MEM_Dyn;

  if( pTo->flags&(MEM_Str|MEM_Blob) ){
    if( 0==(pFrom->flags&MEM_Static) ){
      pTo->flags |= MEM_Ephem;
      rc = sqlite3VdbeMemMakeWriteable(pTo);
58730
58731
58732
58733
58734
58735
58736
58737
58738
58739
58740
58741
58742
58743
58744
58745
58746
58747
58748
58749
    }else if( opcode==OP_VFilter ){
      int n;
      assert( p->nOp - i >= 3 );
      assert( pOp[-1].opcode==OP_Integer );
      n = pOp[-1].p1;
      if( n>nMaxArgs ) nMaxArgs = n;
#endif
    }else if( opcode==OP_Next || opcode==OP_SorterNext ){
      pOp->p4.xAdvance = sqlite3BtreeNext;
      pOp->p4type = P4_ADVANCE;
    }else if( opcode==OP_Prev ){
      pOp->p4.xAdvance = sqlite3BtreePrevious;
      pOp->p4type = P4_ADVANCE;
    }

    if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){
      assert( -1-pOp->p2<p->nLabel );
      pOp->p2 = aLabel[-1-pOp->p2];
    }
  }







<
<
<
<
<
<







57973
57974
57975
57976
57977
57978
57979






57980
57981
57982
57983
57984
57985
57986
    }else if( opcode==OP_VFilter ){
      int n;
      assert( p->nOp - i >= 3 );
      assert( pOp[-1].opcode==OP_Integer );
      n = pOp[-1].p1;
      if( n>nMaxArgs ) nMaxArgs = n;
#endif






    }

    if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){
      assert( -1-pOp->p2<p->nLabel );
      pOp->p2 = aLabel[-1-pOp->p2];
    }
  }
58827
58828
58829
58830
58831
58832
58833
58834
58835

58836
58837
58838
58839
58840
58841
58842
58843
58844
58845
58846

58847
58848
58849
58850
58851
58852
58853
58854
58855
58856

58857
58858
58859
58860
58861
58862
58863
58864

/*
** Change the value of the P1 operand for a specific instruction.
** This routine is useful when a large program is loaded from a
** static array using sqlite3VdbeAddOpList but we want to make a
** few minor changes to the program.
*/
SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe *p, u32 addr, int val){
  assert( p!=0 );

  if( ((u32)p->nOp)>addr ){
    p->aOp[addr].p1 = val;
  }
}

/*
** Change the value of the P2 operand for a specific instruction.
** This routine is useful for setting a jump destination.
*/
SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe *p, u32 addr, int val){
  assert( p!=0 );

  if( ((u32)p->nOp)>addr ){
    p->aOp[addr].p2 = val;
  }
}

/*
** Change the value of the P3 operand for a specific instruction.
*/
SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){
  assert( p!=0 );

  if( ((u32)p->nOp)>addr ){
    p->aOp[addr].p3 = val;
  }
}

/*
** Change the value of the P5 operand for the most recently
** added operation.







|

>
|








|

>
|







|

>
|







58064
58065
58066
58067
58068
58069
58070
58071
58072
58073
58074
58075
58076
58077
58078
58079
58080
58081
58082
58083
58084
58085
58086
58087
58088
58089
58090
58091
58092
58093
58094
58095
58096
58097
58098
58099
58100
58101
58102
58103
58104

/*
** Change the value of the P1 operand for a specific instruction.
** This routine is useful when a large program is loaded from a
** static array using sqlite3VdbeAddOpList but we want to make a
** few minor changes to the program.
*/
SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe *p, int addr, int val){
  assert( p!=0 );
  assert( addr>=0 );
  if( p->nOp>addr ){
    p->aOp[addr].p1 = val;
  }
}

/*
** Change the value of the P2 operand for a specific instruction.
** This routine is useful for setting a jump destination.
*/
SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe *p, int addr, int val){
  assert( p!=0 );
  assert( addr>=0 );
  if( p->nOp>addr ){
    p->aOp[addr].p2 = val;
  }
}

/*
** Change the value of the P3 operand for a specific instruction.
*/
SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, int addr, int val){
  assert( p!=0 );
  assert( addr>=0 );
  if( p->nOp>addr ){
    p->aOp[addr].p3 = val;
  }
}

/*
** Change the value of the P5 operand for the most recently
** added operation.
58967
58968
58969
58970
58971
58972
58973
58974
58975
58976
58977
58978
58979

58980
58981
58982


58983
58984
58985
58986
58987
58988
58989
*/
SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *pVdbe, SubProgram *p){
  p->pNext = pVdbe->pProgram;
  pVdbe->pProgram = p;
}

/*
** Change the opcode at addr into OP_Noop
*/
SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
  if( p->aOp ){
    VdbeOp *pOp = &p->aOp[addr];
    sqlite3 *db = p->db;

    freeP4(db, pOp->p4type, pOp->p4.p);
    memset(pOp, 0, sizeof(pOp[0]));
    pOp->opcode = OP_Noop;


  }
}

/*
** Change the value of the P4 operand for a specific instruction.
** This routine is useful when a large program is loaded from a
** static array using sqlite3VdbeAddOpList but we want to make a







|

|



>
|
|
|
>
>







58207
58208
58209
58210
58211
58212
58213
58214
58215
58216
58217
58218
58219
58220
58221
58222
58223
58224
58225
58226
58227
58228
58229
58230
58231
58232
*/
SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *pVdbe, SubProgram *p){
  p->pNext = pVdbe->pProgram;
  pVdbe->pProgram = p;
}

/*
** Change N opcodes starting at addr to No-ops.
*/
SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe *p, int addr, int N){
  if( p->aOp ){
    VdbeOp *pOp = &p->aOp[addr];
    sqlite3 *db = p->db;
    while( N-- ){
      freeP4(db, pOp->p4type, pOp->p4.p);
      memset(pOp, 0, sizeof(pOp[0]));
      pOp->opcode = OP_Noop;
      pOp++;
    }
  }
}

/*
** Change the value of the P4 operand for a specific instruction.
** This routine is useful when a large program is loaded from a
** static array using sqlite3VdbeAddOpList but we want to make a
59131
59132
59133
59134
59135
59136
59137
59138
59139
59140
59141
59142
59143
59144
59145
** having to double-check to make sure that the result is non-negative. But
** if SQLITE_OMIT_TRACE is defined, the OP_Trace is omitted and we do need to
** check the value of p->nOp-1 before continuing.
*/
SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
  /* C89 specifies that the constant "dummy" will be initialized to all
  ** zeros, which is correct.  MSVC generates a warning, nevertheless. */
  static VdbeOp dummy;  /* Ignore the MSVC warning about no initializer */
  assert( p->magic==VDBE_MAGIC_INIT );
  if( addr<0 ){
#ifdef SQLITE_OMIT_TRACE
    if( p->nOp==0 ) return (VdbeOp*)&dummy;
#endif
    addr = p->nOp - 1;
  }







|







58374
58375
58376
58377
58378
58379
58380
58381
58382
58383
58384
58385
58386
58387
58388
** having to double-check to make sure that the result is non-negative. But
** if SQLITE_OMIT_TRACE is defined, the OP_Trace is omitted and we do need to
** check the value of p->nOp-1 before continuing.
*/
SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
  /* C89 specifies that the constant "dummy" will be initialized to all
  ** zeros, which is correct.  MSVC generates a warning, nevertheless. */
  static const VdbeOp dummy;  /* Ignore the MSVC warning about no initializer */
  assert( p->magic==VDBE_MAGIC_INIT );
  if( addr<0 ){
#ifdef SQLITE_OMIT_TRACE
    if( p->nOp==0 ) return (VdbeOp*)&dummy;
#endif
    addr = p->nOp - 1;
  }
59239
59240
59241
59242
59243
59244
59245
59246
59247
59248
59249
59250
59251
59252
59253
59254
59255
59256
      sqlite3_snprintf(nTemp, zTemp, "intarray");
      break;
    }
    case P4_SUBPROGRAM: {
      sqlite3_snprintf(nTemp, zTemp, "program");
      break;
    }
    case P4_ADVANCE: {
      zTemp[0] = 0;
      break;
    }
    default: {
      zP4 = pOp->p4.z;
      if( zP4==0 ){
        zP4 = zTemp;
        zTemp[0] = 0;
      }
    }







<
<
<
<







58482
58483
58484
58485
58486
58487
58488




58489
58490
58491
58492
58493
58494
58495
      sqlite3_snprintf(nTemp, zTemp, "intarray");
      break;
    }
    case P4_SUBPROGRAM: {
      sqlite3_snprintf(nTemp, zTemp, "program");
      break;
    }




    default: {
      zP4 = pOp->p4.z;
      if( zP4==0 ){
        zP4 = zTemp;
        zTemp[0] = 0;
      }
    }
59866
59867
59868
59869
59870
59871
59872
59873
59874
59875
59876
59877
59878
59879
59880
** Close a VDBE cursor and release all the resources that cursor 
** happens to hold.
*/
SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
  if( pCx==0 ){
    return;
  }
  sqlite3VdbeSorterClose(p->db, pCx);
  if( pCx->pBt ){
    sqlite3BtreeClose(pCx->pBt);
    /* The pCx->pCursor will be close automatically, if it exists, by
    ** the call above. */
  }else if( pCx->pCursor ){
    sqlite3BtreeCloseCursor(pCx->pCursor);
  }







<







59105
59106
59107
59108
59109
59110
59111

59112
59113
59114
59115
59116
59117
59118
** Close a VDBE cursor and release all the resources that cursor 
** happens to hold.
*/
SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
  if( pCx==0 ){
    return;
  }

  if( pCx->pBt ){
    sqlite3BtreeClose(pCx->pBt);
    /* The pCx->pCursor will be close automatically, if it exists, by
    ** the call above. */
  }else if( pCx->pCursor ){
    sqlite3BtreeCloseCursor(pCx->pCursor);
  }
61123
61124
61125
61126
61127
61128
61129
61130

61131

61132
61133
61134
61135
61136
61137
61138
61139
61140
61141
61142
61143

61144
61145
61146


61147
61148
61149
61150

61151
61152


61153



61154

61155
61156
61157
61158
61159


61160
61161
61162
61163
61164

61165
61166
61167
61168
61169
61170
61171
61172
61173
61174
61175
61176
61177
61178
61179
61180
61181
61182
61183
61184
61185
61186
61187
61188
61189
61190
61191
61192
61193
61194
61195
61196
61197
61198
61199
61200
61201
61202
61203
61204
61205
61206
61207
61208
61209
61210
61211
61212

























61213
61214
61215
61216
61217
61218
61219
        pMem->flags = MEM_Blob | MEM_Ephem;
      }
      return len;
    }
  }
  return 0;
}


/*

** This routine is used to allocate sufficient space for an UnpackedRecord
** structure large enough to be used with sqlite3VdbeRecordUnpack() if
** the first argument is a pointer to KeyInfo structure pKeyInfo.
**
** The space is either allocated using sqlite3DbMallocRaw() or from within
** the unaligned buffer passed via the second and third arguments (presumably
** stack space). If the former, then *ppFree is set to a pointer that should
** be eventually freed by the caller using sqlite3DbFree(). Or, if the 
** allocation comes from the pSpace/szSpace buffer, *ppFree is set to NULL
** before returning.
**
** If an OOM error occurs, NULL is returned.

*/
SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(
  KeyInfo *pKeyInfo,              /* Description of the record */


  char *pSpace,                   /* Unaligned space available */
  int szSpace,                    /* Size of pSpace[] in bytes */
  char **ppFree                   /* OUT: Caller should free this pointer */
){

  UnpackedRecord *p;              /* Unpacked record to return */
  int nOff;                       /* Increment pSpace by nOff to align it */


  int nByte;                      /* Number of bytes required for *p */





  /* We want to shift the pointer pSpace up such that it is 8-byte aligned.
  ** Thus, we need to calculate a value, nOff, between 0 and 7, to shift 
  ** it by.  If pSpace is already 8-byte aligned, nOff should be zero.
  */
  nOff = (8 - (SQLITE_PTR_TO_INT(pSpace) & 7)) & 7;


  nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nField+1);
  if( nByte>szSpace+nOff ){
    p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte);
    *ppFree = (char *)p;
    if( !p ) return 0;

  }else{
    p = (UnpackedRecord*)&pSpace[nOff];
    *ppFree = 0;
  }

  p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))];
  p->pKeyInfo = pKeyInfo;
  p->nField = pKeyInfo->nField + 1;
  return p;
}

/*
** Given the nKey-byte encoding of a record in pKey[], populate the 
** UnpackedRecord structure indicated by the fourth argument with the
** contents of the decoded record.
*/ 
SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(
  KeyInfo *pKeyInfo,     /* Information about the record format */
  int nKey,              /* Size of the binary record */
  const void *pKey,      /* The binary record */
  UnpackedRecord *p      /* Populate this structure before returning. */
){
  const unsigned char *aKey = (const unsigned char *)pKey;
  int d; 
  u32 idx;                        /* Offset in aKey[] to read from */
  u16 u;                          /* Unsigned loop counter */
  u32 szHdr;
  Mem *pMem = p->aMem;

  p->flags = 0;
  assert( EIGHT_BYTE_ALIGNMENT(pMem) );
  idx = getVarint32(aKey, szHdr);
  d = szHdr;
  u = 0;
  while( idx<szHdr && u<p->nField && d<=nKey ){
    u32 serial_type;

    idx += getVarint32(&aKey[idx], serial_type);
    pMem->enc = pKeyInfo->enc;
    pMem->db = pKeyInfo->db;
    /* pMem->flags = 0; // sqlite3VdbeSerialGet() will set this for us */
    pMem->zMalloc = 0;
    d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem);
    pMem++;
    u++;
  }
  assert( u<=pKeyInfo->nField + 1 );
  p->nField = u;

























}

/*
** This function compares the two table rows or index records
** specified by {nKey1, pKey1} and pPKey2.  It returns a negative, zero
** or positive integer if key1 is less than, equal to or 
** greater than key2.  The {nKey1, pKey1} key must be a blob








>

>
|
<
|

|
<
|
|
|
<

|
>
|
|
|
>
>
|
|
<

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




>
>

|
|
<
|
>

|
|

<
<


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


















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







60361
60362
60363
60364
60365
60366
60367
60368
60369
60370
60371
60372

60373
60374
60375

60376
60377
60378

60379
60380
60381
60382
60383
60384
60385
60386
60387
60388

60389
60390
60391
60392
60393
60394
60395
60396
60397
60398
60399
60400
60401
60402
60403
60404
60405
60406
60407
60408
60409
60410

60411
60412
60413
60414
60415
60416


60417
60418


60419



















60420
60421
60422
60423
60424
60425
60426
60427
60428
60429
60430
60431
60432
60433
60434
60435
60436
60437
60438
60439
60440
60441
60442
60443
60444
60445
60446
60447
60448
60449
60450
60451
60452
60453
60454
60455
60456
60457
60458
60459
60460
60461
60462
60463
60464
60465
60466
60467
60468
60469
        pMem->flags = MEM_Blob | MEM_Ephem;
      }
      return len;
    }
  }
  return 0;
}


/*
** Given the nKey-byte encoding of a record in pKey[], parse the
** record into a UnpackedRecord structure.  Return a pointer to

** that structure.
**
** The calling function might provide szSpace bytes of memory

** space at pSpace.  This space can be used to hold the returned
** VDbeParsedRecord structure if it is large enough.  If it is
** not big enough, space is obtained from sqlite3_malloc().

**
** The returned structure should be closed by a call to
** sqlite3VdbeDeleteUnpackedRecord().
*/ 
SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(
  KeyInfo *pKeyInfo,     /* Information about the record format */
  int nKey,              /* Size of the binary record */
  const void *pKey,      /* The binary record */
  char *pSpace,          /* Unaligned space available to hold the object */
  int szSpace            /* Size of pSpace[] in bytes */

){
  const unsigned char *aKey = (const unsigned char *)pKey;
  UnpackedRecord *p;  /* The unpacked record that we will return */
  int nByte;          /* Memory space needed to hold p, in bytes */
  int d;
  u32 idx;
  u16 u;              /* Unsigned loop counter */
  u32 szHdr;
  Mem *pMem;
  int nOff;           /* Increase pSpace by this much to 8-byte align it */
  
  /*
  ** We want to shift the pointer pSpace up such that it is 8-byte aligned.
  ** Thus, we need to calculate a value, nOff, between 0 and 7, to shift 
  ** it by.  If pSpace is already 8-byte aligned, nOff should be zero.
  */
  nOff = (8 - (SQLITE_PTR_TO_INT(pSpace) & 7)) & 7;
  pSpace += nOff;
  szSpace -= nOff;
  nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nField+1);
  if( nByte>szSpace ){
    p = sqlite3DbMallocRaw(pKeyInfo->db, nByte);

    if( p==0 ) return 0;
    p->flags = UNPACKED_NEED_FREE | UNPACKED_NEED_DESTROY;
  }else{
    p = (UnpackedRecord*)pSpace;
    p->flags = UNPACKED_NEED_DESTROY;
  }


  p->pKeyInfo = pKeyInfo;
  p->nField = pKeyInfo->nField + 1;


  p->aMem = pMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))];



















  assert( EIGHT_BYTE_ALIGNMENT(pMem) );
  idx = getVarint32(aKey, szHdr);
  d = szHdr;
  u = 0;
  while( idx<szHdr && u<p->nField && d<=nKey ){
    u32 serial_type;

    idx += getVarint32(&aKey[idx], serial_type);
    pMem->enc = pKeyInfo->enc;
    pMem->db = pKeyInfo->db;
    /* pMem->flags = 0; // sqlite3VdbeSerialGet() will set this for us */
    pMem->zMalloc = 0;
    d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem);
    pMem++;
    u++;
  }
  assert( u<=pKeyInfo->nField + 1 );
  p->nField = u;
  return (void*)p;
}

/*
** This routine destroys a UnpackedRecord object.
*/
SQLITE_PRIVATE void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){
#ifdef SQLITE_DEBUG
  int i;
  Mem *pMem;

  assert( p!=0 );
  assert( p->flags & UNPACKED_NEED_DESTROY );
  for(i=0, pMem=p->aMem; i<p->nField; i++, pMem++){
    /* The unpacked record is always constructed by the
    ** sqlite3VdbeUnpackRecord() function above, which makes all
    ** strings and blobs static.  And none of the elements are
    ** ever transformed, so there is never anything to delete.
    */
    if( NEVER(pMem->zMalloc) ) sqlite3VdbeMemRelease(pMem);
  }
#endif
  if( p->flags & UNPACKED_NEED_FREE ){
    sqlite3DbFree(p->pKeyInfo->db, p);
  }
}

/*
** This function compares the two table rows or index records
** specified by {nKey1, pKey1} and pPKey2.  It returns a negative, zero
** or positive integer if key1 is less than, equal to or 
** greater than key2.  The {nKey1, pKey1} key must be a blob
62024
62025
62026
62027
62028
62029
62030
62031
62032
62033
62034
62035
62036
62037
62038
  }
  db = v->db;
  sqlite3_mutex_enter(db->mutex);
  while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
         && cnt++ < SQLITE_MAX_SCHEMA_RETRY
         && (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){
    sqlite3_reset(pStmt);
    assert( v->expired==0 );
  }
  if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
    /* This case occurs after failing to recompile an sql statement. 
    ** The error message from the SQL compiler has already been loaded 
    ** into the database handle. This block copies the error message 
    ** from the database handle into the statement and sets the statement
    ** program counter to 0 to ensure that when the statement is 







|







61274
61275
61276
61277
61278
61279
61280
61281
61282
61283
61284
61285
61286
61287
61288
  }
  db = v->db;
  sqlite3_mutex_enter(db->mutex);
  while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
         && cnt++ < SQLITE_MAX_SCHEMA_RETRY
         && (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){
    sqlite3_reset(pStmt);
    v->expired = 0;
  }
  if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
    /* This case occurs after failing to recompile an sql statement. 
    ** The error message from the SQL compiler has already been loaded 
    ** into the database handle. This block copies the error message 
    ** from the database handle into the statement and sets the statement
    ** program counter to 0 to ensure that when the statement is 
63155
63156
63157
63158
63159
63160
63161
63162
63163
63164
63165
63166
63167
63168
63169
63170
63171
63172
63173
63174
63175

/*
** Call sqlite3VdbeMemExpandBlob() on the supplied value (type Mem*)
** P if required.
*/
#define ExpandBlob(P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(P):0)

/* Return true if the cursor was opened using the OP_OpenSorter opcode. */
#ifdef SQLITE_OMIT_MERGE_SORT
# define isSorter(x) 0
#else
# define isSorter(x) ((x)->pSorter!=0)
#endif

/*
** Argument pMem points at a register that will be passed to a
** user-defined function or returned to the user as the result of a query.
** This routine sets the pMem->type variable used by the sqlite3_value_*() 
** routines.
*/
SQLITE_PRIVATE void sqlite3VdbeMemStoreType(Mem *pMem){







<
<
<
<
<
<
<







62405
62406
62407
62408
62409
62410
62411







62412
62413
62414
62415
62416
62417
62418

/*
** Call sqlite3VdbeMemExpandBlob() on the supplied value (type Mem*)
** P if required.
*/
#define ExpandBlob(P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(P):0)








/*
** Argument pMem points at a register that will be passed to a
** user-defined function or returned to the user as the result of a query.
** This routine sets the pMem->type variable used by the sqlite3_value_*() 
** routines.
*/
SQLITE_PRIVATE void sqlite3VdbeMemStoreType(Mem *pMem){
63756
63757
63758
63759
63760
63761
63762
63763
63764
63765
63766
63767
63768
63769
63770
      Mem sMem;          /* For storing the record being decoded */
      u8 *zIdx;          /* Index into header */
      u8 *zEndHdr;       /* Pointer to first byte after the header */
      u32 offset;        /* Offset into the data */
      u32 szField;       /* Number of bytes in the content of a field */
      int szHdr;         /* Size of the header size field at start of record */
      int avail;         /* Number of bytes of available data */
      u32 t;             /* A type code from the record header */
      Mem *pReg;         /* PseudoTable input register */
    } am;
    struct OP_Affinity_stack_vars {
      const char *zAffinity;   /* The affinity to be applied */
      char cAff;               /* A single character of affinity */
    } an;
    struct OP_MakeRecord_stack_vars {







<







62999
63000
63001
63002
63003
63004
63005

63006
63007
63008
63009
63010
63011
63012
      Mem sMem;          /* For storing the record being decoded */
      u8 *zIdx;          /* Index into header */
      u8 *zEndHdr;       /* Pointer to first byte after the header */
      u32 offset;        /* Offset into the data */
      u32 szField;       /* Number of bytes in the content of a field */
      int szHdr;         /* Size of the header size field at start of record */
      int avail;         /* Number of bytes of available data */

      Mem *pReg;         /* PseudoTable input register */
    } am;
    struct OP_Affinity_stack_vars {
      const char *zAffinity;   /* The affinity to be applied */
      char cAff;               /* A single character of affinity */
    } an;
    struct OP_MakeRecord_stack_vars {
63828
63829
63830
63831
63832
63833
63834
63835
63836
63837
63838
63839
63840
63841
63842
63843
63844
63845
63846
63847
63848
63849
63850
63851
63852
63853
63854
63855
63856
63857
63858
63859
63860
63861
63862
63863
63864
63865
63866
63867
63868
63869
63870
63871
63872
63873
63874
63875
63876
63877
63878
63879
63880
63881
63882
63883
63884
63885
63886
63887
63888
63889
63890
63891
63892
63893
63894
63895
63896
63897
63898
63899
63900
63901
63902
63903
63904
63905
63906
63907
63908
63909
63910
63911
63912
63913
63914
63915
63916
63917
63918
63919
63920
63921
63922
63923
63924
63925
63926
63927
63928
63929
63930
63931
63932

63933
63934
63935
63936
63937
63938
63939
63940
63941
63942
63943
63944
63945
63946
63947
63948
63949
63950
63951
63952
63953
63954
63955
63956
63957
63958
63959
63960
63961
63962
63963
63964
63965
63966
63967
63968
63969
63970
63971
63972
63973
63974
63975
63976
63977
63978
63979
63980
63981
63982
63983
63984
63985
63986
63987
63988
63989
63990
63991
63992
63993
63994
63995
63996
63997
63998
63999
64000
64001
64002
64003
64004
64005
64006
64007
64008
64009
64010
64011
64012
64013
64014
64015
64016
64017
64018
64019
64020
64021
64022
64023
64024
64025
64026
64027
64028
64029
64030
64031
64032
64033
64034
64035
64036
64037
64038
64039
64040
64041
64042
64043
64044
64045
64046
64047
64048
64049
64050
64051
64052
64053
64054
64055
64056
64057
64058
64059
64060
64061
64062
64063
64064
64065
64066
64067
64068
64069
64070
64071
64072
64073
64074
64075
64076
64077
64078
64079
64080
64081
64082
64083
64084
64085
64086
64087
64088
64089
64090
64091
64092
64093
      Btree *pX;
      VdbeCursor *pCur;
      Db *pDb;
    } aw;
    struct OP_OpenEphemeral_stack_vars {
      VdbeCursor *pCx;
    } ax;
    struct OP_SorterOpen_stack_vars {
      VdbeCursor *pCx;
    } ay;
    struct OP_OpenPseudo_stack_vars {
      VdbeCursor *pCx;
    } az;
    struct OP_SeekGt_stack_vars {
      int res;
      int oc;
      VdbeCursor *pC;
      UnpackedRecord r;
      int nField;
      i64 iKey;      /* The rowid we are to seek to */
    } ba;
    struct OP_Seek_stack_vars {
      VdbeCursor *pC;
    } bb;
    struct OP_Found_stack_vars {
      int alreadyExists;
      VdbeCursor *pC;
      int res;
      char *pFree;
      UnpackedRecord *pIdxKey;
      UnpackedRecord r;
      char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7];
    } bc;
    struct OP_IsUnique_stack_vars {
      u16 ii;
      VdbeCursor *pCx;
      BtCursor *pCrsr;
      u16 nField;
      Mem *aMx;
      UnpackedRecord r;                  /* B-Tree index search key */
      i64 R;                             /* Rowid stored in register P3 */
    } bd;
    struct OP_NotExists_stack_vars {
      VdbeCursor *pC;
      BtCursor *pCrsr;
      int res;
      u64 iKey;
    } be;
    struct OP_NewRowid_stack_vars {
      i64 v;                 /* The new rowid */
      VdbeCursor *pC;        /* Cursor of table to get the new rowid */
      int res;               /* Result of an sqlite3BtreeLast() */
      int cnt;               /* Counter to limit the number of searches */
      Mem *pMem;             /* Register holding largest rowid for AUTOINCREMENT */
      VdbeFrame *pFrame;     /* Root frame of VDBE */
    } bf;
    struct OP_InsertInt_stack_vars {
      Mem *pData;       /* MEM cell holding data for the record to be inserted */
      Mem *pKey;        /* MEM cell holding key  for the record */
      i64 iKey;         /* The integer ROWID or key for the record to be inserted */
      VdbeCursor *pC;   /* Cursor to table into which insert is written */
      int nZero;        /* Number of zero-bytes to append */
      int seekResult;   /* Result of prior seek or 0 if no USESEEKRESULT flag */
      const char *zDb;  /* database name - used by the update hook */
      const char *zTbl; /* Table name - used by the opdate hook */
      int op;           /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
    } bg;
    struct OP_Delete_stack_vars {
      i64 iKey;
      VdbeCursor *pC;
    } bh;
    struct OP_SorterCompare_stack_vars {
      VdbeCursor *pC;
      int res;
    } bi;
    struct OP_SorterData_stack_vars {
      VdbeCursor *pC;
    } bj;
    struct OP_RowData_stack_vars {
      VdbeCursor *pC;
      BtCursor *pCrsr;
      u32 n;
      i64 n64;
    } bk;
    struct OP_Rowid_stack_vars {
      VdbeCursor *pC;
      i64 v;
      sqlite3_vtab *pVtab;
      const sqlite3_module *pModule;
    } bl;
    struct OP_NullRow_stack_vars {
      VdbeCursor *pC;
    } bm;
    struct OP_Last_stack_vars {
      VdbeCursor *pC;
      BtCursor *pCrsr;
      int res;
    } bn;
    struct OP_Rewind_stack_vars {
      VdbeCursor *pC;
      BtCursor *pCrsr;
      int res;
    } bo;
    struct OP_Next_stack_vars {
      VdbeCursor *pC;

      int res;
    } bp;
    struct OP_IdxInsert_stack_vars {
      VdbeCursor *pC;
      BtCursor *pCrsr;
      int nKey;
      const char *zKey;
    } bq;
    struct OP_IdxDelete_stack_vars {
      VdbeCursor *pC;
      BtCursor *pCrsr;
      int res;
      UnpackedRecord r;
    } br;
    struct OP_IdxRowid_stack_vars {
      BtCursor *pCrsr;
      VdbeCursor *pC;
      i64 rowid;
    } bs;
    struct OP_IdxGE_stack_vars {
      VdbeCursor *pC;
      int res;
      UnpackedRecord r;
    } bt;
    struct OP_Destroy_stack_vars {
      int iMoved;
      int iCnt;
      Vdbe *pVdbe;
      int iDb;
    } bu;
    struct OP_Clear_stack_vars {
      int nChange;
    } bv;
    struct OP_CreateTable_stack_vars {
      int pgno;
      int flags;
      Db *pDb;
    } bw;
    struct OP_ParseSchema_stack_vars {
      int iDb;
      const char *zMaster;
      char *zSql;
      InitData initData;
    } bx;
    struct OP_IntegrityCk_stack_vars {
      int nRoot;      /* Number of tables to check.  (Number of root pages.) */
      int *aRoot;     /* Array of rootpage numbers for tables to be checked */
      int j;          /* Loop counter */
      int nErr;       /* Number of errors reported */
      char *z;        /* Text of the error report */
      Mem *pnErr;     /* Register keeping track of errors remaining */
    } by;
    struct OP_RowSetRead_stack_vars {
      i64 val;
    } bz;
    struct OP_RowSetTest_stack_vars {
      int iSet;
      int exists;
    } ca;
    struct OP_Program_stack_vars {
      int nMem;               /* Number of memory registers for sub-program */
      int nByte;              /* Bytes of runtime space required for sub-program */
      Mem *pRt;               /* Register to allocate runtime space */
      Mem *pMem;              /* Used to iterate through memory cells */
      Mem *pEnd;              /* Last memory cell in new array */
      VdbeFrame *pFrame;      /* New vdbe frame to execute in */
      SubProgram *pProgram;   /* Sub-program to execute */
      void *t;                /* Token identifying trigger */
    } cb;
    struct OP_Param_stack_vars {
      VdbeFrame *pFrame;
      Mem *pIn;
    } cc;
    struct OP_MemMax_stack_vars {
      Mem *pIn1;
      VdbeFrame *pFrame;
    } cd;
    struct OP_AggStep_stack_vars {
      int n;
      int i;
      Mem *pMem;
      Mem *pRec;
      sqlite3_context ctx;
      sqlite3_value **apVal;
    } ce;
    struct OP_AggFinal_stack_vars {
      Mem *pMem;
    } cf;
    struct OP_Checkpoint_stack_vars {
      int i;                          /* Loop counter */
      int aRes[3];                    /* Results */
      Mem *pMem;                      /* Write results here */
    } cg;
    struct OP_JournalMode_stack_vars {
      Btree *pBt;                     /* Btree to change journal mode of */
      Pager *pPager;                  /* Pager associated with pBt */
      int eNew;                       /* New journal mode */
      int eOld;                       /* The old journal mode */
      const char *zFilename;          /* Name of database file for pPager */
    } ch;
    struct OP_IncrVacuum_stack_vars {
      Btree *pBt;
    } ci;
    struct OP_VBegin_stack_vars {
      VTable *pVTab;
    } cj;
    struct OP_VOpen_stack_vars {
      VdbeCursor *pCur;
      sqlite3_vtab_cursor *pVtabCursor;
      sqlite3_vtab *pVtab;
      sqlite3_module *pModule;
    } ck;
    struct OP_VFilter_stack_vars {
      int nArg;
      int iQuery;
      const sqlite3_module *pModule;
      Mem *pQuery;
      Mem *pArgc;
      sqlite3_vtab_cursor *pVtabCursor;
      sqlite3_vtab *pVtab;
      VdbeCursor *pCur;
      int res;
      int i;
      Mem **apArg;
    } cl;
    struct OP_VColumn_stack_vars {
      sqlite3_vtab *pVtab;
      const sqlite3_module *pModule;
      Mem *pDest;
      sqlite3_context sContext;
    } cm;
    struct OP_VNext_stack_vars {
      sqlite3_vtab *pVtab;
      const sqlite3_module *pModule;
      int res;
      VdbeCursor *pCur;
    } cn;
    struct OP_VRename_stack_vars {
      sqlite3_vtab *pVtab;
      Mem *pName;
    } co;
    struct OP_VUpdate_stack_vars {
      sqlite3_vtab *pVtab;
      sqlite3_module *pModule;
      int nArg;
      int i;
      sqlite_int64 rowid;
      Mem **apArg;
      Mem *pX;
    } cp;
    struct OP_Trace_stack_vars {
      char *zTrace;
      char *z;
    } cq;
  } u;
  /* End automatically generated code
  ********************************************************************/

  assert( p->magic==VDBE_MAGIC_RUN );  /* sqlite3_step() verifies this */
  sqlite3VdbeEnter(p);
  if( p->rc==SQLITE_NOMEM ){







<
<
<


|







|


|




<



|








|





|







|










|



|
<
<
<
<
<
<
<





|





|


|




|




|


>

|





|





|




|




|





|


|




|





|







|


|



|









|



|



|







|


|




|






|


|


|





|












|





|





|



|








|



|







63070
63071
63072
63073
63074
63075
63076



63077
63078
63079
63080
63081
63082
63083
63084
63085
63086
63087
63088
63089
63090
63091
63092
63093
63094

63095
63096
63097
63098
63099
63100
63101
63102
63103
63104
63105
63106
63107
63108
63109
63110
63111
63112
63113
63114
63115
63116
63117
63118
63119
63120
63121
63122
63123
63124
63125
63126
63127
63128
63129
63130
63131
63132
63133
63134
63135
63136







63137
63138
63139
63140
63141
63142
63143
63144
63145
63146
63147
63148
63149
63150
63151
63152
63153
63154
63155
63156
63157
63158
63159
63160
63161
63162
63163
63164
63165
63166
63167
63168
63169
63170
63171
63172
63173
63174
63175
63176
63177
63178
63179
63180
63181
63182
63183
63184
63185
63186
63187
63188
63189
63190
63191
63192
63193
63194
63195
63196
63197
63198
63199
63200
63201
63202
63203
63204
63205
63206
63207
63208
63209
63210
63211
63212
63213
63214
63215
63216
63217
63218
63219
63220
63221
63222
63223
63224
63225
63226
63227
63228
63229
63230
63231
63232
63233
63234
63235
63236
63237
63238
63239
63240
63241
63242
63243
63244
63245
63246
63247
63248
63249
63250
63251
63252
63253
63254
63255
63256
63257
63258
63259
63260
63261
63262
63263
63264
63265
63266
63267
63268
63269
63270
63271
63272
63273
63274
63275
63276
63277
63278
63279
63280
63281
63282
63283
63284
63285
63286
63287
63288
63289
63290
63291
63292
63293
63294
63295
63296
63297
63298
63299
63300
63301
63302
63303
63304
63305
63306
63307
63308
63309
63310
63311
63312
63313
63314
63315
63316
63317
63318
63319
63320
63321
63322
63323
63324
63325
      Btree *pX;
      VdbeCursor *pCur;
      Db *pDb;
    } aw;
    struct OP_OpenEphemeral_stack_vars {
      VdbeCursor *pCx;
    } ax;



    struct OP_OpenPseudo_stack_vars {
      VdbeCursor *pCx;
    } ay;
    struct OP_SeekGt_stack_vars {
      int res;
      int oc;
      VdbeCursor *pC;
      UnpackedRecord r;
      int nField;
      i64 iKey;      /* The rowid we are to seek to */
    } az;
    struct OP_Seek_stack_vars {
      VdbeCursor *pC;
    } ba;
    struct OP_Found_stack_vars {
      int alreadyExists;
      VdbeCursor *pC;
      int res;

      UnpackedRecord *pIdxKey;
      UnpackedRecord r;
      char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7];
    } bb;
    struct OP_IsUnique_stack_vars {
      u16 ii;
      VdbeCursor *pCx;
      BtCursor *pCrsr;
      u16 nField;
      Mem *aMx;
      UnpackedRecord r;                  /* B-Tree index search key */
      i64 R;                             /* Rowid stored in register P3 */
    } bc;
    struct OP_NotExists_stack_vars {
      VdbeCursor *pC;
      BtCursor *pCrsr;
      int res;
      u64 iKey;
    } bd;
    struct OP_NewRowid_stack_vars {
      i64 v;                 /* The new rowid */
      VdbeCursor *pC;        /* Cursor of table to get the new rowid */
      int res;               /* Result of an sqlite3BtreeLast() */
      int cnt;               /* Counter to limit the number of searches */
      Mem *pMem;             /* Register holding largest rowid for AUTOINCREMENT */
      VdbeFrame *pFrame;     /* Root frame of VDBE */
    } be;
    struct OP_InsertInt_stack_vars {
      Mem *pData;       /* MEM cell holding data for the record to be inserted */
      Mem *pKey;        /* MEM cell holding key  for the record */
      i64 iKey;         /* The integer ROWID or key for the record to be inserted */
      VdbeCursor *pC;   /* Cursor to table into which insert is written */
      int nZero;        /* Number of zero-bytes to append */
      int seekResult;   /* Result of prior seek or 0 if no USESEEKRESULT flag */
      const char *zDb;  /* database name - used by the update hook */
      const char *zTbl; /* Table name - used by the opdate hook */
      int op;           /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
    } bf;
    struct OP_Delete_stack_vars {
      i64 iKey;
      VdbeCursor *pC;
    } bg;







    struct OP_RowData_stack_vars {
      VdbeCursor *pC;
      BtCursor *pCrsr;
      u32 n;
      i64 n64;
    } bh;
    struct OP_Rowid_stack_vars {
      VdbeCursor *pC;
      i64 v;
      sqlite3_vtab *pVtab;
      const sqlite3_module *pModule;
    } bi;
    struct OP_NullRow_stack_vars {
      VdbeCursor *pC;
    } bj;
    struct OP_Last_stack_vars {
      VdbeCursor *pC;
      BtCursor *pCrsr;
      int res;
    } bk;
    struct OP_Rewind_stack_vars {
      VdbeCursor *pC;
      BtCursor *pCrsr;
      int res;
    } bl;
    struct OP_Next_stack_vars {
      VdbeCursor *pC;
      BtCursor *pCrsr;
      int res;
    } bm;
    struct OP_IdxInsert_stack_vars {
      VdbeCursor *pC;
      BtCursor *pCrsr;
      int nKey;
      const char *zKey;
    } bn;
    struct OP_IdxDelete_stack_vars {
      VdbeCursor *pC;
      BtCursor *pCrsr;
      int res;
      UnpackedRecord r;
    } bo;
    struct OP_IdxRowid_stack_vars {
      BtCursor *pCrsr;
      VdbeCursor *pC;
      i64 rowid;
    } bp;
    struct OP_IdxGE_stack_vars {
      VdbeCursor *pC;
      int res;
      UnpackedRecord r;
    } bq;
    struct OP_Destroy_stack_vars {
      int iMoved;
      int iCnt;
      Vdbe *pVdbe;
      int iDb;
    } br;
    struct OP_Clear_stack_vars {
      int nChange;
    } bs;
    struct OP_CreateTable_stack_vars {
      int pgno;
      int flags;
      Db *pDb;
    } bt;
    struct OP_ParseSchema_stack_vars {
      int iDb;
      const char *zMaster;
      char *zSql;
      InitData initData;
    } bu;
    struct OP_IntegrityCk_stack_vars {
      int nRoot;      /* Number of tables to check.  (Number of root pages.) */
      int *aRoot;     /* Array of rootpage numbers for tables to be checked */
      int j;          /* Loop counter */
      int nErr;       /* Number of errors reported */
      char *z;        /* Text of the error report */
      Mem *pnErr;     /* Register keeping track of errors remaining */
    } bv;
    struct OP_RowSetRead_stack_vars {
      i64 val;
    } bw;
    struct OP_RowSetTest_stack_vars {
      int iSet;
      int exists;
    } bx;
    struct OP_Program_stack_vars {
      int nMem;               /* Number of memory registers for sub-program */
      int nByte;              /* Bytes of runtime space required for sub-program */
      Mem *pRt;               /* Register to allocate runtime space */
      Mem *pMem;              /* Used to iterate through memory cells */
      Mem *pEnd;              /* Last memory cell in new array */
      VdbeFrame *pFrame;      /* New vdbe frame to execute in */
      SubProgram *pProgram;   /* Sub-program to execute */
      void *t;                /* Token identifying trigger */
    } by;
    struct OP_Param_stack_vars {
      VdbeFrame *pFrame;
      Mem *pIn;
    } bz;
    struct OP_MemMax_stack_vars {
      Mem *pIn1;
      VdbeFrame *pFrame;
    } ca;
    struct OP_AggStep_stack_vars {
      int n;
      int i;
      Mem *pMem;
      Mem *pRec;
      sqlite3_context ctx;
      sqlite3_value **apVal;
    } cb;
    struct OP_AggFinal_stack_vars {
      Mem *pMem;
    } cc;
    struct OP_Checkpoint_stack_vars {
      int i;                          /* Loop counter */
      int aRes[3];                    /* Results */
      Mem *pMem;                      /* Write results here */
    } cd;
    struct OP_JournalMode_stack_vars {
      Btree *pBt;                     /* Btree to change journal mode of */
      Pager *pPager;                  /* Pager associated with pBt */
      int eNew;                       /* New journal mode */
      int eOld;                       /* The old journal mode */
      const char *zFilename;          /* Name of database file for pPager */
    } ce;
    struct OP_IncrVacuum_stack_vars {
      Btree *pBt;
    } cf;
    struct OP_VBegin_stack_vars {
      VTable *pVTab;
    } cg;
    struct OP_VOpen_stack_vars {
      VdbeCursor *pCur;
      sqlite3_vtab_cursor *pVtabCursor;
      sqlite3_vtab *pVtab;
      sqlite3_module *pModule;
    } ch;
    struct OP_VFilter_stack_vars {
      int nArg;
      int iQuery;
      const sqlite3_module *pModule;
      Mem *pQuery;
      Mem *pArgc;
      sqlite3_vtab_cursor *pVtabCursor;
      sqlite3_vtab *pVtab;
      VdbeCursor *pCur;
      int res;
      int i;
      Mem **apArg;
    } ci;
    struct OP_VColumn_stack_vars {
      sqlite3_vtab *pVtab;
      const sqlite3_module *pModule;
      Mem *pDest;
      sqlite3_context sContext;
    } cj;
    struct OP_VNext_stack_vars {
      sqlite3_vtab *pVtab;
      const sqlite3_module *pModule;
      int res;
      VdbeCursor *pCur;
    } ck;
    struct OP_VRename_stack_vars {
      sqlite3_vtab *pVtab;
      Mem *pName;
    } cl;
    struct OP_VUpdate_stack_vars {
      sqlite3_vtab *pVtab;
      sqlite3_module *pModule;
      int nArg;
      int i;
      sqlite_int64 rowid;
      Mem **apArg;
      Mem *pX;
    } cm;
    struct OP_Trace_stack_vars {
      char *zTrace;
      char *z;
    } cn;
  } u;
  /* End automatically generated code
  ********************************************************************/

  assert( p->magic==VDBE_MAGIC_RUN );  /* sqlite3_step() verifies this */
  sqlite3VdbeEnter(p);
  if( p->rc==SQLITE_NOMEM ){
64179
64180
64181
64182
64183
64184
64185
64186
64187
64188
64189
64190
64191
64192
64193
    */
    assert( pOp->opflags==sqlite3OpcodeProperty[pOp->opcode] );
    if( pOp->opflags & OPFLG_OUT2_PRERELEASE ){
      assert( pOp->p2>0 );
      assert( pOp->p2<=p->nMem );
      pOut = &aMem[pOp->p2];
      memAboutToChange(p, pOut);
      MemReleaseExt(pOut);
      pOut->flags = MEM_Int;
    }

    /* Sanity checking on other operands */
#ifdef SQLITE_DEBUG
    if( (pOp->opflags & OPFLG_IN1)!=0 ){
      assert( pOp->p1>0 );







|







63411
63412
63413
63414
63415
63416
63417
63418
63419
63420
63421
63422
63423
63424
63425
    */
    assert( pOp->opflags==sqlite3OpcodeProperty[pOp->opcode] );
    if( pOp->opflags & OPFLG_OUT2_PRERELEASE ){
      assert( pOp->p2>0 );
      assert( pOp->p2<=p->nMem );
      pOut = &aMem[pOp->p2];
      memAboutToChange(p, pOut);
      sqlite3VdbeMemReleaseExternal(pOut);
      pOut->flags = MEM_Int;
    }

    /* Sanity checking on other operands */
#ifdef SQLITE_DEBUG
    if( (pOp->opflags & OPFLG_IN1)!=0 ){
      assert( pOp->p1>0 );
64546
64547
64548
64549
64550
64551
64552
64553
64554
64555
64556
64557
64558
64559
64560
64561
64562
64563
64564
    assert( pOut<=&aMem[p->nMem] );
    assert( pIn1<=&aMem[p->nMem] );
    assert( memIsValid(pIn1) );
    memAboutToChange(p, pOut);
    u.ac.zMalloc = pOut->zMalloc;
    pOut->zMalloc = 0;
    sqlite3VdbeMemMove(pOut, pIn1);
#ifdef SQLITE_DEBUG
    if( pOut->pScopyFrom>=&aMem[u.ac.p1] && pOut->pScopyFrom<&aMem[u.ac.p1+pOp->p3] ){
      pOut->pScopyFrom += u.ac.p1 - pOp->p2;
    }
#endif
    pIn1->zMalloc = u.ac.zMalloc;
    REGISTER_TRACE(u.ac.p2++, pOut);
    pIn1++;
    pOut++;
  }
  break;
}







<
<
<
<
<







63778
63779
63780
63781
63782
63783
63784





63785
63786
63787
63788
63789
63790
63791
    assert( pOut<=&aMem[p->nMem] );
    assert( pIn1<=&aMem[p->nMem] );
    assert( memIsValid(pIn1) );
    memAboutToChange(p, pOut);
    u.ac.zMalloc = pOut->zMalloc;
    pOut->zMalloc = 0;
    sqlite3VdbeMemMove(pOut, pIn1);





    pIn1->zMalloc = u.ac.zMalloc;
    REGISTER_TRACE(u.ac.p2++, pOut);
    pIn1++;
    pOut++;
  }
  break;
}
65549
65550
65551
65552
65553
65554
65555
65556
65557
65558
65559
65560
65561
65562
65563
65564
65565
65566
65567
65568
65569
65570
65571
65572
65573
65574
65575
65576
65577
65578
65579
65580
65581
65582
65583
65584
65585
65586
65587
65588
65589
65590
65591
65592
65593
65594
65595
65596
65597
65598
65599
65600
65601
65602
65603
65604
65605
65606
65607
65608
65609
    sqlite3VdbeMemSetNull(pOut);
  }else{
    sqlite3VdbeMemSetInt64(pOut, ~sqlite3VdbeIntValue(pIn1));
  }
  break;
}

/* Opcode: Once P1 P2 * * *
**
** Jump to P2 if the value in register P1 is a not null or zero.  If
** the value is NULL or zero, fall through and change the P1 register
** to an integer 1.
**
** When P1 is not used otherwise in a program, this opcode falls through
** once and jumps on all subsequent invocations.  It is the equivalent
** of "OP_If P1 P2", followed by "OP_Integer 1 P1".
*/
/* Opcode: If P1 P2 P3 * *
**
** Jump to P2 if the value in register P1 is true.  The value
** is considered true if it is numeric and non-zero.  If the value
** in P1 is NULL then take the jump if P3 is true.
*/
/* Opcode: IfNot P1 P2 P3 * *
**
** Jump to P2 if the value in register P1 is False.  The value
** is considered true if it has a numeric value of zero.  If the value
** in P1 is NULL then take the jump if P3 is true.
*/
case OP_Once:               /* jump, in1 */
case OP_If:                 /* jump, in1 */
case OP_IfNot: {            /* jump, in1 */
#if 0  /* local variables moved into u.al */
  int c;
#endif /* local variables moved into u.al */
  pIn1 = &aMem[pOp->p1];
  if( pIn1->flags & MEM_Null ){
    u.al.c = pOp->p3;
  }else{
#ifdef SQLITE_OMIT_FLOATING_POINT
    u.al.c = sqlite3VdbeIntValue(pIn1)!=0;
#else
    u.al.c = sqlite3VdbeRealValue(pIn1)!=0.0;
#endif
    if( pOp->opcode==OP_IfNot ) u.al.c = !u.al.c;
  }
  if( u.al.c ){
    pc = pOp->p2-1;
  }else if( pOp->opcode==OP_Once ){
    assert( (pIn1->flags & (MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))==0 );
    memAboutToChange(p, pIn1);
    pIn1->flags = MEM_Int;
    pIn1->u.i = 1;
    REGISTER_TRACE(pOp->p1, pIn1);
  }
  break;
}

/* Opcode: IsNull P1 P2 * * *
**
** Jump to P2 if the value in register P1 is NULL.







<
<
<
<
<
<
<
<
<
<












<


















<
<
<
<
<
<







64776
64777
64778
64779
64780
64781
64782










64783
64784
64785
64786
64787
64788
64789
64790
64791
64792
64793
64794

64795
64796
64797
64798
64799
64800
64801
64802
64803
64804
64805
64806
64807
64808
64809
64810
64811
64812






64813
64814
64815
64816
64817
64818
64819
    sqlite3VdbeMemSetNull(pOut);
  }else{
    sqlite3VdbeMemSetInt64(pOut, ~sqlite3VdbeIntValue(pIn1));
  }
  break;
}











/* Opcode: If P1 P2 P3 * *
**
** Jump to P2 if the value in register P1 is true.  The value
** is considered true if it is numeric and non-zero.  If the value
** in P1 is NULL then take the jump if P3 is true.
*/
/* Opcode: IfNot P1 P2 P3 * *
**
** Jump to P2 if the value in register P1 is False.  The value
** is considered true if it has a numeric value of zero.  If the value
** in P1 is NULL then take the jump if P3 is true.
*/

case OP_If:                 /* jump, in1 */
case OP_IfNot: {            /* jump, in1 */
#if 0  /* local variables moved into u.al */
  int c;
#endif /* local variables moved into u.al */
  pIn1 = &aMem[pOp->p1];
  if( pIn1->flags & MEM_Null ){
    u.al.c = pOp->p3;
  }else{
#ifdef SQLITE_OMIT_FLOATING_POINT
    u.al.c = sqlite3VdbeIntValue(pIn1)!=0;
#else
    u.al.c = sqlite3VdbeRealValue(pIn1)!=0.0;
#endif
    if( pOp->opcode==OP_IfNot ) u.al.c = !u.al.c;
  }
  if( u.al.c ){
    pc = pOp->p2-1;






  }
  break;
}

/* Opcode: IsNull P1 P2 * * *
**
** Jump to P2 if the value in register P1 is NULL.
65666
65667
65668
65669
65670
65671
65672
65673
65674
65675
65676
65677
65678
65679
65680
65681
65682
65683
65684
65685

65686
65687
65688
65689
65690
65691
65692
  Mem sMem;          /* For storing the record being decoded */
  u8 *zIdx;          /* Index into header */
  u8 *zEndHdr;       /* Pointer to first byte after the header */
  u32 offset;        /* Offset into the data */
  u32 szField;       /* Number of bytes in the content of a field */
  int szHdr;         /* Size of the header size field at start of record */
  int avail;         /* Number of bytes of available data */
  u32 t;             /* A type code from the record header */
  Mem *pReg;         /* PseudoTable input register */
#endif /* local variables moved into u.am */


  u.am.p1 = pOp->p1;
  u.am.p2 = pOp->p2;
  u.am.pC = 0;
  memset(&u.am.sMem, 0, sizeof(u.am.sMem));
  assert( u.am.p1<p->nCursor );
  assert( pOp->p3>0 && pOp->p3<=p->nMem );
  u.am.pDest = &aMem[pOp->p3];
  memAboutToChange(p, u.am.pDest);

  u.am.zRec = 0;

  /* This block sets the variable u.am.payloadSize to be the total number of
  ** bytes in the record.
  **
  ** u.am.zRec is set to be the complete text of the record if it is available.
  ** The complete record text is always available for pseudo-tables







<












>







64876
64877
64878
64879
64880
64881
64882

64883
64884
64885
64886
64887
64888
64889
64890
64891
64892
64893
64894
64895
64896
64897
64898
64899
64900
64901
64902
  Mem sMem;          /* For storing the record being decoded */
  u8 *zIdx;          /* Index into header */
  u8 *zEndHdr;       /* Pointer to first byte after the header */
  u32 offset;        /* Offset into the data */
  u32 szField;       /* Number of bytes in the content of a field */
  int szHdr;         /* Size of the header size field at start of record */
  int avail;         /* Number of bytes of available data */

  Mem *pReg;         /* PseudoTable input register */
#endif /* local variables moved into u.am */


  u.am.p1 = pOp->p1;
  u.am.p2 = pOp->p2;
  u.am.pC = 0;
  memset(&u.am.sMem, 0, sizeof(u.am.sMem));
  assert( u.am.p1<p->nCursor );
  assert( pOp->p3>0 && pOp->p3<=p->nMem );
  u.am.pDest = &aMem[pOp->p3];
  memAboutToChange(p, u.am.pDest);
  MemSetTypeFlag(u.am.pDest, MEM_Null);
  u.am.zRec = 0;

  /* This block sets the variable u.am.payloadSize to be the total number of
  ** bytes in the record.
  **
  ** u.am.zRec is set to be the complete text of the record if it is available.
  ** The complete record text is always available for pseudo-tables
65722
65723
65724
65725
65726
65727
65728
65729
65730
65731
65732
65733
65734
65735
65736
65737
65738
65739
65740
65741
65742
65743
65744
65745
65746
65747
65748
65749
65750
65751
65752
      assert( (u.am.payloadSize64 & SQLITE_MAX_U32)==(u64)u.am.payloadSize64 );
      u.am.payloadSize = (u32)u.am.payloadSize64;
    }else{
      assert( sqlite3BtreeCursorIsValid(u.am.pCrsr) );
      rc = sqlite3BtreeDataSize(u.am.pCrsr, &u.am.payloadSize);
      assert( rc==SQLITE_OK );   /* DataSize() cannot fail */
    }
  }else if( ALWAYS(u.am.pC->pseudoTableReg>0) ){
    u.am.pReg = &aMem[u.am.pC->pseudoTableReg];
    assert( u.am.pReg->flags & MEM_Blob );
    assert( memIsValid(u.am.pReg) );
    u.am.payloadSize = u.am.pReg->n;
    u.am.zRec = u.am.pReg->z;
    u.am.pC->cacheStatus = (pOp->p5&OPFLAG_CLEARCACHE) ? CACHE_STALE : p->cacheCtr;
    assert( u.am.payloadSize==0 || u.am.zRec!=0 );
  }else{
    /* Consider the row to be NULL */
    u.am.payloadSize = 0;
  }

  /* If u.am.payloadSize is 0, then just store a NULL.  This can happen because of
  ** nullRow or because of a corrupt database. */
  if( u.am.payloadSize==0 ){
    MemSetTypeFlag(u.am.pDest, MEM_Null);
    goto op_column_out;
  }
  assert( db->aLimit[SQLITE_LIMIT_LENGTH]>=0 );
  if( u.am.payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
    goto too_big;
  }








|












|
<

|







64932
64933
64934
64935
64936
64937
64938
64939
64940
64941
64942
64943
64944
64945
64946
64947
64948
64949
64950
64951
64952

64953
64954
64955
64956
64957
64958
64959
64960
64961
      assert( (u.am.payloadSize64 & SQLITE_MAX_U32)==(u64)u.am.payloadSize64 );
      u.am.payloadSize = (u32)u.am.payloadSize64;
    }else{
      assert( sqlite3BtreeCursorIsValid(u.am.pCrsr) );
      rc = sqlite3BtreeDataSize(u.am.pCrsr, &u.am.payloadSize);
      assert( rc==SQLITE_OK );   /* DataSize() cannot fail */
    }
  }else if( u.am.pC->pseudoTableReg>0 ){
    u.am.pReg = &aMem[u.am.pC->pseudoTableReg];
    assert( u.am.pReg->flags & MEM_Blob );
    assert( memIsValid(u.am.pReg) );
    u.am.payloadSize = u.am.pReg->n;
    u.am.zRec = u.am.pReg->z;
    u.am.pC->cacheStatus = (pOp->p5&OPFLAG_CLEARCACHE) ? CACHE_STALE : p->cacheCtr;
    assert( u.am.payloadSize==0 || u.am.zRec!=0 );
  }else{
    /* Consider the row to be NULL */
    u.am.payloadSize = 0;
  }

  /* If u.am.payloadSize is 0, then just store a NULL */

  if( u.am.payloadSize==0 ){
    assert( u.am.pDest->flags&MEM_Null );
    goto op_column_out;
  }
  assert( db->aLimit[SQLITE_LIMIT_LENGTH]>=0 );
  if( u.am.payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
    goto too_big;
  }

65845
65846
65847
65848
65849
65850
65851
65852
65853
65854
65855
65856
65857
65858
65859
65860
65861
65862
65863
65864
65865
65866
    ** arrays.  u.am.aType[u.am.i] will contain the type integer for the u.am.i-th
    ** column and u.am.aOffset[u.am.i] will contain the u.am.offset from the beginning
    ** of the record to the start of the data for the u.am.i-th column
    */
    for(u.am.i=0; u.am.i<u.am.nField; u.am.i++){
      if( u.am.zIdx<u.am.zEndHdr ){
        u.am.aOffset[u.am.i] = u.am.offset;
        if( u.am.zIdx[0]<0x80 ){
          u.am.t = u.am.zIdx[0];
          u.am.zIdx++;
        }else{
          u.am.zIdx += sqlite3GetVarint32(u.am.zIdx, &u.am.t);
        }
        u.am.aType[u.am.i] = u.am.t;
        u.am.szField = sqlite3VdbeSerialTypeLen(u.am.t);
        u.am.offset += u.am.szField;
        if( u.am.offset<u.am.szField ){  /* True if u.am.offset overflows */
          u.am.zIdx = &u.am.zEndHdr[1];  /* Forces SQLITE_CORRUPT return below */
          break;
        }
      }else{
        /* If u.am.i is less that u.am.nField, then there are less fields in this







<
<
<
<
<
<
|
|







65054
65055
65056
65057
65058
65059
65060






65061
65062
65063
65064
65065
65066
65067
65068
65069
    ** arrays.  u.am.aType[u.am.i] will contain the type integer for the u.am.i-th
    ** column and u.am.aOffset[u.am.i] will contain the u.am.offset from the beginning
    ** of the record to the start of the data for the u.am.i-th column
    */
    for(u.am.i=0; u.am.i<u.am.nField; u.am.i++){
      if( u.am.zIdx<u.am.zEndHdr ){
        u.am.aOffset[u.am.i] = u.am.offset;






        u.am.zIdx += getVarint32(u.am.zIdx, u.am.aType[u.am.i]);
        u.am.szField = sqlite3VdbeSerialTypeLen(u.am.aType[u.am.i]);
        u.am.offset += u.am.szField;
        if( u.am.offset<u.am.szField ){  /* True if u.am.offset overflows */
          u.am.zIdx = &u.am.zEndHdr[1];  /* Forces SQLITE_CORRUPT return below */
          break;
        }
      }else{
        /* If u.am.i is less that u.am.nField, then there are less fields in this
65893
65894
65895
65896
65897
65898
65899
65900
65901
65902
65903
65904
65905
65906
65907
65908
65909
65910
65911
65912
65913
65914
65915
65916
65917
65918
65919
65920
65921
65922
65923
65924
  ** then there are not enough fields in the record to satisfy the
  ** request.  In this case, set the value NULL or to P4 if P4 is
  ** a pointer to a Mem object.
  */
  if( u.am.aOffset[u.am.p2] ){
    assert( rc==SQLITE_OK );
    if( u.am.zRec ){
      MemReleaseExt(u.am.pDest);
      sqlite3VdbeSerialGet((u8 *)&u.am.zRec[u.am.aOffset[u.am.p2]], u.am.aType[u.am.p2], u.am.pDest);
    }else{
      u.am.len = sqlite3VdbeSerialTypeLen(u.am.aType[u.am.p2]);
      sqlite3VdbeMemMove(&u.am.sMem, u.am.pDest);
      rc = sqlite3VdbeMemFromBtree(u.am.pCrsr, u.am.aOffset[u.am.p2], u.am.len, u.am.pC->isIndex, &u.am.sMem);
      if( rc!=SQLITE_OK ){
        goto op_column_out;
      }
      u.am.zData = u.am.sMem.z;
      sqlite3VdbeSerialGet((u8*)u.am.zData, u.am.aType[u.am.p2], u.am.pDest);
    }
    u.am.pDest->enc = encoding;
  }else{
    if( pOp->p4type==P4_MEM ){
      sqlite3VdbeMemShallowCopy(u.am.pDest, pOp->p4.pMem, MEM_Static);
    }else{
      MemSetTypeFlag(u.am.pDest, MEM_Null);
    }
  }

  /* If we dynamically allocated space to hold the data (in the
  ** sqlite3VdbeMemFromBtree() call above) then transfer control of that
  ** dynamically allocated space over to the u.am.pDest structure.
  ** This prevents a memory copy.







|
















|







65096
65097
65098
65099
65100
65101
65102
65103
65104
65105
65106
65107
65108
65109
65110
65111
65112
65113
65114
65115
65116
65117
65118
65119
65120
65121
65122
65123
65124
65125
65126
65127
  ** then there are not enough fields in the record to satisfy the
  ** request.  In this case, set the value NULL or to P4 if P4 is
  ** a pointer to a Mem object.
  */
  if( u.am.aOffset[u.am.p2] ){
    assert( rc==SQLITE_OK );
    if( u.am.zRec ){
      sqlite3VdbeMemReleaseExternal(u.am.pDest);
      sqlite3VdbeSerialGet((u8 *)&u.am.zRec[u.am.aOffset[u.am.p2]], u.am.aType[u.am.p2], u.am.pDest);
    }else{
      u.am.len = sqlite3VdbeSerialTypeLen(u.am.aType[u.am.p2]);
      sqlite3VdbeMemMove(&u.am.sMem, u.am.pDest);
      rc = sqlite3VdbeMemFromBtree(u.am.pCrsr, u.am.aOffset[u.am.p2], u.am.len, u.am.pC->isIndex, &u.am.sMem);
      if( rc!=SQLITE_OK ){
        goto op_column_out;
      }
      u.am.zData = u.am.sMem.z;
      sqlite3VdbeSerialGet((u8*)u.am.zData, u.am.aType[u.am.p2], u.am.pDest);
    }
    u.am.pDest->enc = encoding;
  }else{
    if( pOp->p4type==P4_MEM ){
      sqlite3VdbeMemShallowCopy(u.am.pDest, pOp->p4.pMem, MEM_Static);
    }else{
      assert( u.am.pDest->flags&MEM_Null );
    }
  }

  /* If we dynamically allocated space to hold the data (in the
  ** sqlite3VdbeMemFromBtree() call above) then transfer control of that
  ** dynamically allocated space over to the u.am.pDest structure.
  ** This prevents a memory copy.
66112
66113
66114
66115
66116
66117
66118
66119
66120
66121
66122
66123
66124
66125
66126
case OP_Count: {         /* out2-prerelease */
#if 0  /* local variables moved into u.ap */
  i64 nEntry;
  BtCursor *pCrsr;
#endif /* local variables moved into u.ap */

  u.ap.pCrsr = p->apCsr[pOp->p1]->pCursor;
  if( ALWAYS(u.ap.pCrsr) ){
    rc = sqlite3BtreeCount(u.ap.pCrsr, &u.ap.nEntry);
  }else{
    u.ap.nEntry = 0;
  }
  pOut->u.i = u.ap.nEntry;
  break;
}







|







65315
65316
65317
65318
65319
65320
65321
65322
65323
65324
65325
65326
65327
65328
65329
case OP_Count: {         /* out2-prerelease */
#if 0  /* local variables moved into u.ap */
  i64 nEntry;
  BtCursor *pCrsr;
#endif /* local variables moved into u.ap */

  u.ap.pCrsr = p->apCsr[pOp->p1]->pCursor;
  if( u.ap.pCrsr ){
    rc = sqlite3BtreeCount(u.ap.pCrsr, &u.ap.nEntry);
  }else{
    u.ap.nEntry = 0;
  }
  pOut->u.i = u.ap.nEntry;
  break;
}
66688
66689
66690
66691
66692
66693
66694
66695
66696


66697




66698
66699
66700
66701
66702
66703
66704
66705
66706
66707
66708
66709
66710
66711
66712
66713
66714
66715
66716
66717
66718
66719
66720
66721
66722
66723
66724
66725
66726
66727
66728
66729
66730
66731
66732
66733
66734
66735
66736
  u.aw.pCur = allocateCursor(p, pOp->p1, u.aw.nField, u.aw.iDb, 1);
  if( u.aw.pCur==0 ) goto no_mem;
  u.aw.pCur->nullRow = 1;
  u.aw.pCur->isOrdered = 1;
  rc = sqlite3BtreeCursor(u.aw.pX, u.aw.p2, u.aw.wrFlag, u.aw.pKeyInfo, u.aw.pCur->pCursor);
  u.aw.pCur->pKeyInfo = u.aw.pKeyInfo;

  /* Since it performs no memory allocation or IO, the only value that
  ** sqlite3BtreeCursor() may return is SQLITE_OK. */


  assert( rc==SQLITE_OK );





  /* Set the VdbeCursor.isTable and isIndex variables. Previous versions of
  ** SQLite used to check if the root-page flags were sane at this point
  ** and report database corruption if they were not, but this check has
  ** since moved into the btree layer.  */
  u.aw.pCur->isTable = pOp->p4type!=P4_KEYINFO;
  u.aw.pCur->isIndex = !u.aw.pCur->isTable;
  break;
}

/* Opcode: OpenEphemeral P1 P2 * P4 P5
**
** Open a new cursor P1 to a transient table.
** The cursor is always opened read/write even if 
** the main database is read-only.  The ephemeral
** table is deleted automatically when the cursor is closed.
**
** P2 is the number of columns in the ephemeral table.
** The cursor points to a BTree table if P4==0 and to a BTree index
** if P4 is not 0.  If P4 is not NULL, it points to a KeyInfo structure
** that defines the format of keys in the index.
**
** This opcode was once called OpenTemp.  But that created
** confusion because the term "temp table", might refer either
** to a TEMP table at the SQL level, or to a table opened by
** this opcode.  Then this opcode was call OpenVirtual.  But
** that created confusion with the whole virtual-table idea.
**
** The P5 parameter can be a mask of the BTREE_* flags defined
** in btree.h.  These flags control aspects of the operation of
** the btree.  The BTREE_OMIT_JOURNAL and BTREE_SINGLE flags are
** added automatically.
*/
/* Opcode: OpenAutoindex P1 P2 * P4 *
**
** This opcode works the same as OP_OpenEphemeral.  It has a
** different name to distinguish its use.  Tables created using
** by this opcode will be used for automatically created transient
** indices in joins.







|
|
>
>
|
>
>
>
>










|
















<
<
<
<
<







65891
65892
65893
65894
65895
65896
65897
65898
65899
65900
65901
65902
65903
65904
65905
65906
65907
65908
65909
65910
65911
65912
65913
65914
65915
65916
65917
65918
65919
65920
65921
65922
65923
65924
65925
65926
65927
65928
65929
65930
65931
65932
65933





65934
65935
65936
65937
65938
65939
65940
  u.aw.pCur = allocateCursor(p, pOp->p1, u.aw.nField, u.aw.iDb, 1);
  if( u.aw.pCur==0 ) goto no_mem;
  u.aw.pCur->nullRow = 1;
  u.aw.pCur->isOrdered = 1;
  rc = sqlite3BtreeCursor(u.aw.pX, u.aw.p2, u.aw.wrFlag, u.aw.pKeyInfo, u.aw.pCur->pCursor);
  u.aw.pCur->pKeyInfo = u.aw.pKeyInfo;

  /* Since it performs no memory allocation or IO, the only values that
  ** sqlite3BtreeCursor() may return are SQLITE_EMPTY and SQLITE_OK.
  ** SQLITE_EMPTY is only returned when attempting to open the table
  ** rooted at page 1 of a zero-byte database.  */
  assert( rc==SQLITE_EMPTY || rc==SQLITE_OK );
  if( rc==SQLITE_EMPTY ){
    u.aw.pCur->pCursor = 0;
    rc = SQLITE_OK;
  }

  /* Set the VdbeCursor.isTable and isIndex variables. Previous versions of
  ** SQLite used to check if the root-page flags were sane at this point
  ** and report database corruption if they were not, but this check has
  ** since moved into the btree layer.  */
  u.aw.pCur->isTable = pOp->p4type!=P4_KEYINFO;
  u.aw.pCur->isIndex = !u.aw.pCur->isTable;
  break;
}

/* Opcode: OpenEphemeral P1 P2 * P4 *
**
** Open a new cursor P1 to a transient table.
** The cursor is always opened read/write even if 
** the main database is read-only.  The ephemeral
** table is deleted automatically when the cursor is closed.
**
** P2 is the number of columns in the ephemeral table.
** The cursor points to a BTree table if P4==0 and to a BTree index
** if P4 is not 0.  If P4 is not NULL, it points to a KeyInfo structure
** that defines the format of keys in the index.
**
** This opcode was once called OpenTemp.  But that created
** confusion because the term "temp table", might refer either
** to a TEMP table at the SQL level, or to a table opened by
** this opcode.  Then this opcode was call OpenVirtual.  But
** that created confusion with the whole virtual-table idea.





*/
/* Opcode: OpenAutoindex P1 P2 * P4 *
**
** This opcode works the same as OP_OpenEphemeral.  It has a
** different name to distinguish its use.  Tables created using
** by this opcode will be used for automatically created transient
** indices in joins.
66761
66762
66763
66764
66765
66766
66767
66768
66769
66770
66771
66772
66773
66774
66775
66776
66777
66778
66779
66780
66781
66782
66783
66784
66785
66786
66787
66788
66789
66790
66791
66792
66793
66794
66795
66796
66797
66798
66799
66800
66801
66802
66803
66804
66805
66806
66807
66808
66809
66810
66811
66812
66813
66814
66815
66816
66817
66818
66819
66820
66821
66822
66823
66824
66825
66826
66827
66828
66829
66830
66831
66832
66833
66834
66835
66836
66837
66838
66839
66840
66841
66842
66843
66844
    ** sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before
    ** opening it. If a transient table is required, just use the
    ** automatically created table with root-page 1 (an BLOB_INTKEY table).
    */
    if( pOp->p4.pKeyInfo ){
      int pgno;
      assert( pOp->p4type==P4_KEYINFO );
      rc = sqlite3BtreeCreateTable(u.ax.pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5);
      if( rc==SQLITE_OK ){
        assert( pgno==MASTER_ROOT+1 );
        rc = sqlite3BtreeCursor(u.ax.pCx->pBt, pgno, 1,
                                (KeyInfo*)pOp->p4.z, u.ax.pCx->pCursor);
        u.ax.pCx->pKeyInfo = pOp->p4.pKeyInfo;
        u.ax.pCx->pKeyInfo->enc = ENC(p->db);
      }
      u.ax.pCx->isTable = 0;
    }else{
      rc = sqlite3BtreeCursor(u.ax.pCx->pBt, MASTER_ROOT, 1, 0, u.ax.pCx->pCursor);
      u.ax.pCx->isTable = 1;
    }
  }
  u.ax.pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
  u.ax.pCx->isIndex = !u.ax.pCx->isTable;
  break;
}

/* Opcode: OpenSorter P1 P2 * P4 *
**
** This opcode works like OP_OpenEphemeral except that it opens
** a transient index that is specifically designed to sort large
** tables using an external merge-sort algorithm.
*/
case OP_SorterOpen: {
#if 0  /* local variables moved into u.ay */
  VdbeCursor *pCx;
#endif /* local variables moved into u.ay */
#ifndef SQLITE_OMIT_MERGE_SORT
  u.ay.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
  if( u.ay.pCx==0 ) goto no_mem;
  u.ay.pCx->pKeyInfo = pOp->p4.pKeyInfo;
  u.ay.pCx->pKeyInfo->enc = ENC(p->db);
  u.ay.pCx->isSorter = 1;
  rc = sqlite3VdbeSorterInit(db, u.ay.pCx);
#else
  pOp->opcode = OP_OpenEphemeral;
  pc--;
#endif
  break;
}

/* Opcode: OpenPseudo P1 P2 P3 * *
**
** Open a new cursor that points to a fake table that contains a single
** row of data.  The content of that one row in the content of memory
** register P2.  In other words, cursor P1 becomes an alias for the 
** MEM_Blob content contained in register P2.
**
** A pseudo-table created by this opcode is used to hold a single
** row output from the sorter so that the row can be decomposed into
** individual columns using the OP_Column opcode.  The OP_Column opcode
** is the only cursor opcode that works with a pseudo-table.
**
** P3 is the number of fields in the records that will be stored by
** the pseudo-table.
*/
case OP_OpenPseudo: {
#if 0  /* local variables moved into u.az */
  VdbeCursor *pCx;
#endif /* local variables moved into u.az */

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

/* Opcode: Close P1 * * * *
**
** Close a cursor previously opened as P1.  If P1 is not
** currently open, this instruction is a no-op.







|















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



















|

|


|
|
|
|
|
|







65965
65966
65967
65968
65969
65970
65971
65972
65973
65974
65975
65976
65977
65978
65979
65980
65981
65982
65983
65984
65985
65986
65987
























65988
65989
65990
65991
65992
65993
65994
65995
65996
65997
65998
65999
66000
66001
66002
66003
66004
66005
66006
66007
66008
66009
66010
66011
66012
66013
66014
66015
66016
66017
66018
66019
66020
66021
66022
66023
66024
    ** sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before
    ** opening it. If a transient table is required, just use the
    ** automatically created table with root-page 1 (an BLOB_INTKEY table).
    */
    if( pOp->p4.pKeyInfo ){
      int pgno;
      assert( pOp->p4type==P4_KEYINFO );
      rc = sqlite3BtreeCreateTable(u.ax.pCx->pBt, &pgno, BTREE_BLOBKEY);
      if( rc==SQLITE_OK ){
        assert( pgno==MASTER_ROOT+1 );
        rc = sqlite3BtreeCursor(u.ax.pCx->pBt, pgno, 1,
                                (KeyInfo*)pOp->p4.z, u.ax.pCx->pCursor);
        u.ax.pCx->pKeyInfo = pOp->p4.pKeyInfo;
        u.ax.pCx->pKeyInfo->enc = ENC(p->db);
      }
      u.ax.pCx->isTable = 0;
    }else{
      rc = sqlite3BtreeCursor(u.ax.pCx->pBt, MASTER_ROOT, 1, 0, u.ax.pCx->pCursor);
      u.ax.pCx->isTable = 1;
    }
  }
  u.ax.pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
  u.ax.pCx->isIndex = !u.ax.pCx->isTable;
























  break;
}

/* Opcode: OpenPseudo P1 P2 P3 * *
**
** Open a new cursor that points to a fake table that contains a single
** row of data.  The content of that one row in the content of memory
** register P2.  In other words, cursor P1 becomes an alias for the 
** MEM_Blob content contained in register P2.
**
** A pseudo-table created by this opcode is used to hold a single
** row output from the sorter so that the row can be decomposed into
** individual columns using the OP_Column opcode.  The OP_Column opcode
** is the only cursor opcode that works with a pseudo-table.
**
** P3 is the number of fields in the records that will be stored by
** the pseudo-table.
*/
case OP_OpenPseudo: {
#if 0  /* local variables moved into u.ay */
  VdbeCursor *pCx;
#endif /* local variables moved into u.ay */

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

/* Opcode: Close P1 * * * *
**
** Close a cursor previously opened as P1.  If P1 is not
** currently open, this instruction is a no-op.
66902
66903
66904
66905
66906
66907
66908
66909
66910
66911
66912
66913
66914
66915
66916
66917
66918
66919
66920
66921
66922
66923
66924
66925
66926
66927
66928
66929
66930
66931
66932
66933
66934
66935
66936
66937
66938
66939
66940
66941
66942
66943
66944
66945
66946
66947
66948
66949
66950
66951
66952
66953
66954
66955
66956
66957
66958
66959
66960
66961
66962
66963
66964
66965
66966
66967
66968
66969
66970
66971
66972
66973
66974
66975
66976
66977
66978
66979
66980
66981
66982
66983
66984
66985
66986
66987
66988
66989
66990
66991
66992
66993
66994
66995
66996
66997
66998
66999
67000
67001
67002
67003
67004
67005
67006
67007
67008
67009
67010
67011
67012
67013
67014
67015
67016
67017
67018
67019
67020
67021
67022
67023
67024
67025
67026
67027
67028
67029
67030
67031
67032
67033
67034
67035
67036
67037
67038
67039
67040
67041
67042
67043
67044
67045
67046
67047
67048
67049
67050
67051
67052
67053
**
** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLt
*/
case OP_SeekLt:         /* jump, in3 */
case OP_SeekLe:         /* jump, in3 */
case OP_SeekGe:         /* jump, in3 */
case OP_SeekGt: {       /* jump, in3 */
#if 0  /* local variables moved into u.ba */
  int res;
  int oc;
  VdbeCursor *pC;
  UnpackedRecord r;
  int nField;
  i64 iKey;      /* The rowid we are to seek to */
#endif /* local variables moved into u.ba */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( pOp->p2!=0 );
  u.ba.pC = p->apCsr[pOp->p1];
  assert( u.ba.pC!=0 );
  assert( u.ba.pC->pseudoTableReg==0 );
  assert( OP_SeekLe == OP_SeekLt+1 );
  assert( OP_SeekGe == OP_SeekLt+2 );
  assert( OP_SeekGt == OP_SeekLt+3 );
  assert( u.ba.pC->isOrdered );
  if( ALWAYS(u.ba.pC->pCursor!=0) ){
    u.ba.oc = pOp->opcode;
    u.ba.pC->nullRow = 0;
    if( u.ba.pC->isTable ){
      /* The input value in P3 might be of any type: integer, real, string,
      ** blob, or NULL.  But it needs to be an integer before we can do
      ** the seek, so covert it. */
      pIn3 = &aMem[pOp->p3];
      applyNumericAffinity(pIn3);
      u.ba.iKey = sqlite3VdbeIntValue(pIn3);
      u.ba.pC->rowidIsValid = 0;

      /* If the P3 value could not be converted into an integer without
      ** loss of information, then special processing is required... */
      if( (pIn3->flags & MEM_Int)==0 ){
        if( (pIn3->flags & MEM_Real)==0 ){
          /* If the P3 value cannot be converted into any kind of a number,
          ** then the seek is not possible, so jump to P2 */
          pc = pOp->p2 - 1;
          break;
        }
        /* If we reach this point, then the P3 value must be a floating
        ** point number. */
        assert( (pIn3->flags & MEM_Real)!=0 );

        if( u.ba.iKey==SMALLEST_INT64 && (pIn3->r<(double)u.ba.iKey || pIn3->r>0) ){
          /* The P3 value is too large in magnitude to be expressed as an
          ** integer. */
          u.ba.res = 1;
          if( pIn3->r<0 ){
            if( u.ba.oc>=OP_SeekGe ){  assert( u.ba.oc==OP_SeekGe || u.ba.oc==OP_SeekGt );
              rc = sqlite3BtreeFirst(u.ba.pC->pCursor, &u.ba.res);
              if( rc!=SQLITE_OK ) goto abort_due_to_error;
            }
          }else{
            if( u.ba.oc<=OP_SeekLe ){  assert( u.ba.oc==OP_SeekLt || u.ba.oc==OP_SeekLe );
              rc = sqlite3BtreeLast(u.ba.pC->pCursor, &u.ba.res);
              if( rc!=SQLITE_OK ) goto abort_due_to_error;
            }
          }
          if( u.ba.res ){
            pc = pOp->p2 - 1;
          }
          break;
        }else if( u.ba.oc==OP_SeekLt || u.ba.oc==OP_SeekGe ){
          /* Use the ceiling() function to convert real->int */
          if( pIn3->r > (double)u.ba.iKey ) u.ba.iKey++;
        }else{
          /* Use the floor() function to convert real->int */
          assert( u.ba.oc==OP_SeekLe || u.ba.oc==OP_SeekGt );
          if( pIn3->r < (double)u.ba.iKey ) u.ba.iKey--;
        }
      }
      rc = sqlite3BtreeMovetoUnpacked(u.ba.pC->pCursor, 0, (u64)u.ba.iKey, 0, &u.ba.res);
      if( rc!=SQLITE_OK ){
        goto abort_due_to_error;
      }
      if( u.ba.res==0 ){
        u.ba.pC->rowidIsValid = 1;
        u.ba.pC->lastRowid = u.ba.iKey;
      }
    }else{
      u.ba.nField = pOp->p4.i;
      assert( pOp->p4type==P4_INT32 );
      assert( u.ba.nField>0 );
      u.ba.r.pKeyInfo = u.ba.pC->pKeyInfo;
      u.ba.r.nField = (u16)u.ba.nField;

      /* The next line of code computes as follows, only faster:
      **   if( u.ba.oc==OP_SeekGt || u.ba.oc==OP_SeekLe ){
      **     u.ba.r.flags = UNPACKED_INCRKEY;
      **   }else{
      **     u.ba.r.flags = 0;
      **   }
      */
      u.ba.r.flags = (u16)(UNPACKED_INCRKEY * (1 & (u.ba.oc - OP_SeekLt)));
      assert( u.ba.oc!=OP_SeekGt || u.ba.r.flags==UNPACKED_INCRKEY );
      assert( u.ba.oc!=OP_SeekLe || u.ba.r.flags==UNPACKED_INCRKEY );
      assert( u.ba.oc!=OP_SeekGe || u.ba.r.flags==0 );
      assert( u.ba.oc!=OP_SeekLt || u.ba.r.flags==0 );

      u.ba.r.aMem = &aMem[pOp->p3];
#ifdef SQLITE_DEBUG
      { int i; for(i=0; i<u.ba.r.nField; i++) assert( memIsValid(&u.ba.r.aMem[i]) ); }
#endif
      ExpandBlob(u.ba.r.aMem);
      rc = sqlite3BtreeMovetoUnpacked(u.ba.pC->pCursor, &u.ba.r, 0, 0, &u.ba.res);
      if( rc!=SQLITE_OK ){
        goto abort_due_to_error;
      }
      u.ba.pC->rowidIsValid = 0;
    }
    u.ba.pC->deferredMoveto = 0;
    u.ba.pC->cacheStatus = CACHE_STALE;
#ifdef SQLITE_TEST
    sqlite3_search_count++;
#endif
    if( u.ba.oc>=OP_SeekGe ){  assert( u.ba.oc==OP_SeekGe || u.ba.oc==OP_SeekGt );
      if( u.ba.res<0 || (u.ba.res==0 && u.ba.oc==OP_SeekGt) ){
        rc = sqlite3BtreeNext(u.ba.pC->pCursor, &u.ba.res);
        if( rc!=SQLITE_OK ) goto abort_due_to_error;
        u.ba.pC->rowidIsValid = 0;
      }else{
        u.ba.res = 0;
      }
    }else{
      assert( u.ba.oc==OP_SeekLt || u.ba.oc==OP_SeekLe );
      if( u.ba.res>0 || (u.ba.res==0 && u.ba.oc==OP_SeekLt) ){
        rc = sqlite3BtreePrevious(u.ba.pC->pCursor, &u.ba.res);
        if( rc!=SQLITE_OK ) goto abort_due_to_error;
        u.ba.pC->rowidIsValid = 0;
      }else{
        /* u.ba.res might be negative because the table is empty.  Check to
        ** see if this is the case.
        */
        u.ba.res = sqlite3BtreeEof(u.ba.pC->pCursor);
      }
    }
    assert( pOp->p2>0 );
    if( u.ba.res ){
      pc = pOp->p2 - 1;
    }
  }else{
    /* This happens when attempting to open the sqlite3_master table
    ** for read access returns SQLITE_EMPTY. In this case always
    ** take the jump (since there are no records in the table).
    */







|






|



|
|
|



|
|
|
|
|





|
|














|


|

|
|



|
|



|



|

|


|
|


|



|
|
|


|

|
|
|


|
|

|


|
|
|
|
|

|

|

|
|



|

|
|



|
|
|

|

|


|
|
|

|

|


|



|







66082
66083
66084
66085
66086
66087
66088
66089
66090
66091
66092
66093
66094
66095
66096
66097
66098
66099
66100
66101
66102
66103
66104
66105
66106
66107
66108
66109
66110
66111
66112
66113
66114
66115
66116
66117
66118
66119
66120
66121
66122
66123
66124
66125
66126
66127
66128
66129
66130
66131
66132
66133
66134
66135
66136
66137
66138
66139
66140
66141
66142
66143
66144
66145
66146
66147
66148
66149
66150
66151
66152
66153
66154
66155
66156
66157
66158
66159
66160
66161
66162
66163
66164
66165
66166
66167
66168
66169
66170
66171
66172
66173
66174
66175
66176
66177
66178
66179
66180
66181
66182
66183
66184
66185
66186
66187
66188
66189
66190
66191
66192
66193
66194
66195
66196
66197
66198
66199
66200
66201
66202
66203
66204
66205
66206
66207
66208
66209
66210
66211
66212
66213
66214
66215
66216
66217
66218
66219
66220
66221
66222
66223
66224
66225
66226
66227
66228
66229
66230
66231
66232
66233
**
** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLt
*/
case OP_SeekLt:         /* jump, in3 */
case OP_SeekLe:         /* jump, in3 */
case OP_SeekGe:         /* jump, in3 */
case OP_SeekGt: {       /* jump, in3 */
#if 0  /* local variables moved into u.az */
  int res;
  int oc;
  VdbeCursor *pC;
  UnpackedRecord r;
  int nField;
  i64 iKey;      /* The rowid we are to seek to */
#endif /* local variables moved into u.az */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( pOp->p2!=0 );
  u.az.pC = p->apCsr[pOp->p1];
  assert( u.az.pC!=0 );
  assert( u.az.pC->pseudoTableReg==0 );
  assert( OP_SeekLe == OP_SeekLt+1 );
  assert( OP_SeekGe == OP_SeekLt+2 );
  assert( OP_SeekGt == OP_SeekLt+3 );
  assert( u.az.pC->isOrdered );
  if( u.az.pC->pCursor!=0 ){
    u.az.oc = pOp->opcode;
    u.az.pC->nullRow = 0;
    if( u.az.pC->isTable ){
      /* The input value in P3 might be of any type: integer, real, string,
      ** blob, or NULL.  But it needs to be an integer before we can do
      ** the seek, so covert it. */
      pIn3 = &aMem[pOp->p3];
      applyNumericAffinity(pIn3);
      u.az.iKey = sqlite3VdbeIntValue(pIn3);
      u.az.pC->rowidIsValid = 0;

      /* If the P3 value could not be converted into an integer without
      ** loss of information, then special processing is required... */
      if( (pIn3->flags & MEM_Int)==0 ){
        if( (pIn3->flags & MEM_Real)==0 ){
          /* If the P3 value cannot be converted into any kind of a number,
          ** then the seek is not possible, so jump to P2 */
          pc = pOp->p2 - 1;
          break;
        }
        /* If we reach this point, then the P3 value must be a floating
        ** point number. */
        assert( (pIn3->flags & MEM_Real)!=0 );

        if( u.az.iKey==SMALLEST_INT64 && (pIn3->r<(double)u.az.iKey || pIn3->r>0) ){
          /* The P3 value is too large in magnitude to be expressed as an
          ** integer. */
          u.az.res = 1;
          if( pIn3->r<0 ){
            if( u.az.oc>=OP_SeekGe ){  assert( u.az.oc==OP_SeekGe || u.az.oc==OP_SeekGt );
              rc = sqlite3BtreeFirst(u.az.pC->pCursor, &u.az.res);
              if( rc!=SQLITE_OK ) goto abort_due_to_error;
            }
          }else{
            if( u.az.oc<=OP_SeekLe ){  assert( u.az.oc==OP_SeekLt || u.az.oc==OP_SeekLe );
              rc = sqlite3BtreeLast(u.az.pC->pCursor, &u.az.res);
              if( rc!=SQLITE_OK ) goto abort_due_to_error;
            }
          }
          if( u.az.res ){
            pc = pOp->p2 - 1;
          }
          break;
        }else if( u.az.oc==OP_SeekLt || u.az.oc==OP_SeekGe ){
          /* Use the ceiling() function to convert real->int */
          if( pIn3->r > (double)u.az.iKey ) u.az.iKey++;
        }else{
          /* Use the floor() function to convert real->int */
          assert( u.az.oc==OP_SeekLe || u.az.oc==OP_SeekGt );
          if( pIn3->r < (double)u.az.iKey ) u.az.iKey--;
        }
      }
      rc = sqlite3BtreeMovetoUnpacked(u.az.pC->pCursor, 0, (u64)u.az.iKey, 0, &u.az.res);
      if( rc!=SQLITE_OK ){
        goto abort_due_to_error;
      }
      if( u.az.res==0 ){
        u.az.pC->rowidIsValid = 1;
        u.az.pC->lastRowid = u.az.iKey;
      }
    }else{
      u.az.nField = pOp->p4.i;
      assert( pOp->p4type==P4_INT32 );
      assert( u.az.nField>0 );
      u.az.r.pKeyInfo = u.az.pC->pKeyInfo;
      u.az.r.nField = (u16)u.az.nField;

      /* The next line of code computes as follows, only faster:
      **   if( u.az.oc==OP_SeekGt || u.az.oc==OP_SeekLe ){
      **     u.az.r.flags = UNPACKED_INCRKEY;
      **   }else{
      **     u.az.r.flags = 0;
      **   }
      */
      u.az.r.flags = (u16)(UNPACKED_INCRKEY * (1 & (u.az.oc - OP_SeekLt)));
      assert( u.az.oc!=OP_SeekGt || u.az.r.flags==UNPACKED_INCRKEY );
      assert( u.az.oc!=OP_SeekLe || u.az.r.flags==UNPACKED_INCRKEY );
      assert( u.az.oc!=OP_SeekGe || u.az.r.flags==0 );
      assert( u.az.oc!=OP_SeekLt || u.az.r.flags==0 );

      u.az.r.aMem = &aMem[pOp->p3];
#ifdef SQLITE_DEBUG
      { int i; for(i=0; i<u.az.r.nField; i++) assert( memIsValid(&u.az.r.aMem[i]) ); }
#endif
      ExpandBlob(u.az.r.aMem);
      rc = sqlite3BtreeMovetoUnpacked(u.az.pC->pCursor, &u.az.r, 0, 0, &u.az.res);
      if( rc!=SQLITE_OK ){
        goto abort_due_to_error;
      }
      u.az.pC->rowidIsValid = 0;
    }
    u.az.pC->deferredMoveto = 0;
    u.az.pC->cacheStatus = CACHE_STALE;
#ifdef SQLITE_TEST
    sqlite3_search_count++;
#endif
    if( u.az.oc>=OP_SeekGe ){  assert( u.az.oc==OP_SeekGe || u.az.oc==OP_SeekGt );
      if( u.az.res<0 || (u.az.res==0 && u.az.oc==OP_SeekGt) ){
        rc = sqlite3BtreeNext(u.az.pC->pCursor, &u.az.res);
        if( rc!=SQLITE_OK ) goto abort_due_to_error;
        u.az.pC->rowidIsValid = 0;
      }else{
        u.az.res = 0;
      }
    }else{
      assert( u.az.oc==OP_SeekLt || u.az.oc==OP_SeekLe );
      if( u.az.res>0 || (u.az.res==0 && u.az.oc==OP_SeekLt) ){
        rc = sqlite3BtreePrevious(u.az.pC->pCursor, &u.az.res);
        if( rc!=SQLITE_OK ) goto abort_due_to_error;
        u.az.pC->rowidIsValid = 0;
      }else{
        /* u.az.res might be negative because the table is empty.  Check to
        ** see if this is the case.
        */
        u.az.res = sqlite3BtreeEof(u.az.pC->pCursor);
      }
    }
    assert( pOp->p2>0 );
    if( u.az.res ){
      pc = pOp->p2 - 1;
    }
  }else{
    /* This happens when attempting to open the sqlite3_master table
    ** for read access returns SQLITE_EMPTY. In this case always
    ** take the jump (since there are no records in the table).
    */
67062
67063
67064
67065
67066
67067
67068
67069
67070
67071
67072
67073
67074
67075
67076
67077
67078
67079
67080
67081
67082
67083
67084
67085
67086
67087
67088
67089
** for P1 to move so that it points to the rowid given by P2.
**
** This is actually a deferred seek.  Nothing actually happens until
** the cursor is used to read a record.  That way, if no reads
** occur, no unnecessary I/O happens.
*/
case OP_Seek: {    /* in2 */
#if 0  /* local variables moved into u.bb */
  VdbeCursor *pC;
#endif /* local variables moved into u.bb */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bb.pC = p->apCsr[pOp->p1];
  assert( u.bb.pC!=0 );
  if( ALWAYS(u.bb.pC->pCursor!=0) ){
    assert( u.bb.pC->isTable );
    u.bb.pC->nullRow = 0;
    pIn2 = &aMem[pOp->p2];
    u.bb.pC->movetoTarget = sqlite3VdbeIntValue(pIn2);
    u.bb.pC->rowidIsValid = 0;
    u.bb.pC->deferredMoveto = 1;
  }
  break;
}
  

/* Opcode: Found P1 P2 P3 P4 *
**







|

|


|
|
|
|
|

|
|
|







66242
66243
66244
66245
66246
66247
66248
66249
66250
66251
66252
66253
66254
66255
66256
66257
66258
66259
66260
66261
66262
66263
66264
66265
66266
66267
66268
66269
** for P1 to move so that it points to the rowid given by P2.
**
** This is actually a deferred seek.  Nothing actually happens until
** the cursor is used to read a record.  That way, if no reads
** occur, no unnecessary I/O happens.
*/
case OP_Seek: {    /* in2 */
#if 0  /* local variables moved into u.ba */
  VdbeCursor *pC;
#endif /* local variables moved into u.ba */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.ba.pC = p->apCsr[pOp->p1];
  assert( u.ba.pC!=0 );
  if( ALWAYS(u.ba.pC->pCursor!=0) ){
    assert( u.ba.pC->isTable );
    u.ba.pC->nullRow = 0;
    pIn2 = &aMem[pOp->p2];
    u.ba.pC->movetoTarget = sqlite3VdbeIntValue(pIn2);
    u.ba.pC->rowidIsValid = 0;
    u.ba.pC->deferredMoveto = 1;
  }
  break;
}
  

/* Opcode: Found P1 P2 P3 P4 *
**
67107
67108
67109
67110
67111
67112
67113
67114
67115
67116
67117
67118
67119
67120
67121
67122
67123
67124
67125
67126
67127
67128
67129
67130
67131
67132
67133
67134
67135
67136
67137
67138
67139
67140
67141
67142
67143
67144
67145
67146
67147
67148
67149
67150
67151
67152
67153




67154
67155
67156
67157
67158
67159
67160
67161
67162
67163
67164
67165
67166
67167
67168
67169
67170
67171
67172
67173
67174
67175
67176
67177
** falls through to the next instruction and P1 is left pointing at the
** matching entry.
**
** See also: Found, NotExists, IsUnique
*/
case OP_NotFound:       /* jump, in3 */
case OP_Found: {        /* jump, in3 */
#if 0  /* local variables moved into u.bc */
  int alreadyExists;
  VdbeCursor *pC;
  int res;
  char *pFree;
  UnpackedRecord *pIdxKey;
  UnpackedRecord r;
  char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7];
#endif /* local variables moved into u.bc */

#ifdef SQLITE_TEST
  sqlite3_found_count++;
#endif

  u.bc.alreadyExists = 0;
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( pOp->p4type==P4_INT32 );
  u.bc.pC = p->apCsr[pOp->p1];
  assert( u.bc.pC!=0 );
  pIn3 = &aMem[pOp->p3];
  if( ALWAYS(u.bc.pC->pCursor!=0) ){

    assert( u.bc.pC->isTable==0 );
    if( pOp->p4.i>0 ){
      u.bc.r.pKeyInfo = u.bc.pC->pKeyInfo;
      u.bc.r.nField = (u16)pOp->p4.i;
      u.bc.r.aMem = pIn3;
#ifdef SQLITE_DEBUG
      { int i; for(i=0; i<u.bc.r.nField; i++) assert( memIsValid(&u.bc.r.aMem[i]) ); }
#endif
      u.bc.r.flags = UNPACKED_PREFIX_MATCH;
      u.bc.pIdxKey = &u.bc.r;
    }else{
      u.bc.pIdxKey = sqlite3VdbeAllocUnpackedRecord(
          u.bc.pC->pKeyInfo, u.bc.aTempRec, sizeof(u.bc.aTempRec), &u.bc.pFree
      );
      if( u.bc.pIdxKey==0 ) goto no_mem;
      assert( pIn3->flags & MEM_Blob );
      assert( (pIn3->flags & MEM_Zero)==0 );  /* zeroblobs already expanded */
      sqlite3VdbeRecordUnpack(u.bc.pC->pKeyInfo, pIn3->n, pIn3->z, u.bc.pIdxKey);




      u.bc.pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
    }
    rc = sqlite3BtreeMovetoUnpacked(u.bc.pC->pCursor, u.bc.pIdxKey, 0, 0, &u.bc.res);
    if( pOp->p4.i==0 ){
      sqlite3DbFree(db, u.bc.pFree);
    }
    if( rc!=SQLITE_OK ){
      break;
    }
    u.bc.alreadyExists = (u.bc.res==0);
    u.bc.pC->deferredMoveto = 0;
    u.bc.pC->cacheStatus = CACHE_STALE;
  }
  if( pOp->opcode==OP_Found ){
    if( u.bc.alreadyExists ) pc = pOp->p2 - 1;
  }else{
    if( !u.bc.alreadyExists ) pc = pOp->p2 - 1;
  }
  break;
}

/* Opcode: IsUnique P1 P2 P3 P4 *
**
** Cursor P1 is open on an index b-tree - that is to say, a btree which







|



<



|





|


|
|

|

|

|
|
|

|

|
|

<
<
<
<


|
>
>
>
>
|

|

|




|
|
|


|

|







66287
66288
66289
66290
66291
66292
66293
66294
66295
66296
66297

66298
66299
66300
66301
66302
66303
66304
66305
66306
66307
66308
66309
66310
66311
66312
66313
66314
66315
66316
66317
66318
66319
66320
66321
66322
66323
66324
66325




66326
66327
66328
66329
66330
66331
66332
66333
66334
66335
66336
66337
66338
66339
66340
66341
66342
66343
66344
66345
66346
66347
66348
66349
66350
66351
66352
66353
66354
66355
66356
** falls through to the next instruction and P1 is left pointing at the
** matching entry.
**
** See also: Found, NotExists, IsUnique
*/
case OP_NotFound:       /* jump, in3 */
case OP_Found: {        /* jump, in3 */
#if 0  /* local variables moved into u.bb */
  int alreadyExists;
  VdbeCursor *pC;
  int res;

  UnpackedRecord *pIdxKey;
  UnpackedRecord r;
  char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7];
#endif /* local variables moved into u.bb */

#ifdef SQLITE_TEST
  sqlite3_found_count++;
#endif

  u.bb.alreadyExists = 0;
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( pOp->p4type==P4_INT32 );
  u.bb.pC = p->apCsr[pOp->p1];
  assert( u.bb.pC!=0 );
  pIn3 = &aMem[pOp->p3];
  if( ALWAYS(u.bb.pC->pCursor!=0) ){

    assert( u.bb.pC->isTable==0 );
    if( pOp->p4.i>0 ){
      u.bb.r.pKeyInfo = u.bb.pC->pKeyInfo;
      u.bb.r.nField = (u16)pOp->p4.i;
      u.bb.r.aMem = pIn3;
#ifdef SQLITE_DEBUG
      { int i; for(i=0; i<u.bb.r.nField; i++) assert( memIsValid(&u.bb.r.aMem[i]) ); }
#endif
      u.bb.r.flags = UNPACKED_PREFIX_MATCH;
      u.bb.pIdxKey = &u.bb.r;
    }else{




      assert( pIn3->flags & MEM_Blob );
      assert( (pIn3->flags & MEM_Zero)==0 );  /* zeroblobs already expanded */
      u.bb.pIdxKey = sqlite3VdbeRecordUnpack(u.bb.pC->pKeyInfo, pIn3->n, pIn3->z,
                                        u.bb.aTempRec, sizeof(u.bb.aTempRec));
      if( u.bb.pIdxKey==0 ){
        goto no_mem;
      }
      u.bb.pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
    }
    rc = sqlite3BtreeMovetoUnpacked(u.bb.pC->pCursor, u.bb.pIdxKey, 0, 0, &u.bb.res);
    if( pOp->p4.i==0 ){
      sqlite3VdbeDeleteUnpackedRecord(u.bb.pIdxKey);
    }
    if( rc!=SQLITE_OK ){
      break;
    }
    u.bb.alreadyExists = (u.bb.res==0);
    u.bb.pC->deferredMoveto = 0;
    u.bb.pC->cacheStatus = CACHE_STALE;
  }
  if( pOp->opcode==OP_Found ){
    if( u.bb.alreadyExists ) pc = pOp->p2 - 1;
  }else{
    if( !u.bb.alreadyExists ) pc = pOp->p2 - 1;
  }
  break;
}

/* Opcode: IsUnique P1 P2 P3 P4 *
**
** Cursor P1 is open on an index b-tree - that is to say, a btree which
67195
67196
67197
67198
67199
67200
67201
67202
67203
67204
67205
67206
67207
67208
67209
67210
67211
67212
67213
67214
67215
67216
67217
67218
67219
67220
67221
67222
67223
67224
67225
67226
67227
67228
67229
67230
67231
67232
67233
67234
67235
67236
67237
67238
67239
67240
67241
67242
67243
67244
67245
67246
67247
67248
67249
67250
67251
67252
67253
67254
67255
67256
67257
67258
67259
67260
67261
67262
67263
67264
67265
67266
67267
67268
67269
67270
67271
67272
67273
67274
67275
67276
67277
67278
67279
67280
67281
67282
67283
67284
67285
67286
67287
67288
67289
67290
67291
67292
67293
67294
67295
67296
67297
67298
67299
67300
67301
67302
67303
67304
67305
67306
67307
67308
67309
67310
67311
67312
67313
67314
67315
67316
67317
67318
67319
67320
67321
** to instruction P2. Otherwise, the rowid of the conflicting index
** entry is copied to register P3 and control falls through to the next
** instruction.
**
** See also: NotFound, NotExists, Found
*/
case OP_IsUnique: {        /* jump, in3 */
#if 0  /* local variables moved into u.bd */
  u16 ii;
  VdbeCursor *pCx;
  BtCursor *pCrsr;
  u16 nField;
  Mem *aMx;
  UnpackedRecord r;                  /* B-Tree index search key */
  i64 R;                             /* Rowid stored in register P3 */
#endif /* local variables moved into u.bd */

  pIn3 = &aMem[pOp->p3];
  u.bd.aMx = &aMem[pOp->p4.i];
  /* Assert that the values of parameters P1 and P4 are in range. */
  assert( pOp->p4type==P4_INT32 );
  assert( pOp->p4.i>0 && pOp->p4.i<=p->nMem );
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );

  /* Find the index cursor. */
  u.bd.pCx = p->apCsr[pOp->p1];
  assert( u.bd.pCx->deferredMoveto==0 );
  u.bd.pCx->seekResult = 0;
  u.bd.pCx->cacheStatus = CACHE_STALE;
  u.bd.pCrsr = u.bd.pCx->pCursor;

  /* If any of the values are NULL, take the jump. */
  u.bd.nField = u.bd.pCx->pKeyInfo->nField;
  for(u.bd.ii=0; u.bd.ii<u.bd.nField; u.bd.ii++){
    if( u.bd.aMx[u.bd.ii].flags & MEM_Null ){
      pc = pOp->p2 - 1;
      u.bd.pCrsr = 0;
      break;
    }
  }
  assert( (u.bd.aMx[u.bd.nField].flags & MEM_Null)==0 );

  if( u.bd.pCrsr!=0 ){
    /* Populate the index search key. */
    u.bd.r.pKeyInfo = u.bd.pCx->pKeyInfo;
    u.bd.r.nField = u.bd.nField + 1;
    u.bd.r.flags = UNPACKED_PREFIX_SEARCH;
    u.bd.r.aMem = u.bd.aMx;
#ifdef SQLITE_DEBUG
    { int i; for(i=0; i<u.bd.r.nField; i++) assert( memIsValid(&u.bd.r.aMem[i]) ); }
#endif

    /* Extract the value of u.bd.R from register P3. */
    sqlite3VdbeMemIntegerify(pIn3);
    u.bd.R = pIn3->u.i;

    /* Search the B-Tree index. If no conflicting record is found, jump
    ** to P2. Otherwise, copy the rowid of the conflicting record to
    ** register P3 and fall through to the next instruction.  */
    rc = sqlite3BtreeMovetoUnpacked(u.bd.pCrsr, &u.bd.r, 0, 0, &u.bd.pCx->seekResult);
    if( (u.bd.r.flags & UNPACKED_PREFIX_SEARCH) || u.bd.r.rowid==u.bd.R ){
      pc = pOp->p2 - 1;
    }else{
      pIn3->u.i = u.bd.r.rowid;
    }
  }
  break;
}

/* Opcode: NotExists P1 P2 P3 * *
**
** Use the content of register P3 as an integer key.  If a record 
** with that key does not exist in table of P1, then jump to P2. 
** If the record does exist, then fall through.  The cursor is left 
** pointing to the record if it exists.
**
** The difference between this operation and NotFound is that this
** operation assumes the key is an integer and that P1 is a table whereas
** NotFound assumes key is a blob constructed from MakeRecord and
** P1 is an index.
**
** See also: Found, NotFound, IsUnique
*/
case OP_NotExists: {        /* jump, in3 */
#if 0  /* local variables moved into u.be */
  VdbeCursor *pC;
  BtCursor *pCrsr;
  int res;
  u64 iKey;
#endif /* local variables moved into u.be */

  pIn3 = &aMem[pOp->p3];
  assert( pIn3->flags & MEM_Int );
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.be.pC = p->apCsr[pOp->p1];
  assert( u.be.pC!=0 );
  assert( u.be.pC->isTable );
  assert( u.be.pC->pseudoTableReg==0 );
  u.be.pCrsr = u.be.pC->pCursor;
  if( ALWAYS(u.be.pCrsr!=0) ){
    u.be.res = 0;
    u.be.iKey = pIn3->u.i;
    rc = sqlite3BtreeMovetoUnpacked(u.be.pCrsr, 0, u.be.iKey, 0, &u.be.res);
    u.be.pC->lastRowid = pIn3->u.i;
    u.be.pC->rowidIsValid = u.be.res==0 ?1:0;
    u.be.pC->nullRow = 0;
    u.be.pC->cacheStatus = CACHE_STALE;
    u.be.pC->deferredMoveto = 0;
    if( u.be.res!=0 ){
      pc = pOp->p2 - 1;
      assert( u.be.pC->rowidIsValid==0 );
    }
    u.be.pC->seekResult = u.be.res;
  }else{
    /* This happens when an attempt to open a read cursor on the
    ** sqlite_master table returns SQLITE_EMPTY.
    */
    pc = pOp->p2 - 1;
    assert( u.be.pC->rowidIsValid==0 );
    u.be.pC->seekResult = 0;
  }
  break;
}

/* Opcode: Sequence P1 P2 * * *
**
** Find the next available sequence number for cursor P1.







|







|


|






|
|
|
|
|


|
|
|

|



|

|

|
|
|
|

|


|

|




|
|


|




















|




|




|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|

|





|
|







66374
66375
66376
66377
66378
66379
66380
66381
66382
66383
66384
66385
66386
66387
66388
66389
66390
66391
66392
66393
66394
66395
66396
66397
66398
66399
66400
66401
66402
66403
66404
66405
66406
66407
66408
66409
66410
66411
66412
66413
66414
66415
66416
66417
66418
66419
66420
66421
66422
66423
66424
66425
66426
66427
66428
66429
66430
66431
66432
66433
66434
66435
66436
66437
66438
66439
66440
66441
66442
66443
66444
66445
66446
66447
66448
66449
66450
66451
66452
66453
66454
66455
66456
66457
66458
66459
66460
66461
66462
66463
66464
66465
66466
66467
66468
66469
66470
66471
66472
66473
66474
66475
66476
66477
66478
66479
66480
66481
66482
66483
66484
66485
66486
66487
66488
66489
66490
66491
66492
66493
66494
66495
66496
66497
66498
66499
66500
** to instruction P2. Otherwise, the rowid of the conflicting index
** entry is copied to register P3 and control falls through to the next
** instruction.
**
** See also: NotFound, NotExists, Found
*/
case OP_IsUnique: {        /* jump, in3 */
#if 0  /* local variables moved into u.bc */
  u16 ii;
  VdbeCursor *pCx;
  BtCursor *pCrsr;
  u16 nField;
  Mem *aMx;
  UnpackedRecord r;                  /* B-Tree index search key */
  i64 R;                             /* Rowid stored in register P3 */
#endif /* local variables moved into u.bc */

  pIn3 = &aMem[pOp->p3];
  u.bc.aMx = &aMem[pOp->p4.i];
  /* Assert that the values of parameters P1 and P4 are in range. */
  assert( pOp->p4type==P4_INT32 );
  assert( pOp->p4.i>0 && pOp->p4.i<=p->nMem );
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );

  /* Find the index cursor. */
  u.bc.pCx = p->apCsr[pOp->p1];
  assert( u.bc.pCx->deferredMoveto==0 );
  u.bc.pCx->seekResult = 0;
  u.bc.pCx->cacheStatus = CACHE_STALE;
  u.bc.pCrsr = u.bc.pCx->pCursor;

  /* If any of the values are NULL, take the jump. */
  u.bc.nField = u.bc.pCx->pKeyInfo->nField;
  for(u.bc.ii=0; u.bc.ii<u.bc.nField; u.bc.ii++){
    if( u.bc.aMx[u.bc.ii].flags & MEM_Null ){
      pc = pOp->p2 - 1;
      u.bc.pCrsr = 0;
      break;
    }
  }
  assert( (u.bc.aMx[u.bc.nField].flags & MEM_Null)==0 );

  if( u.bc.pCrsr!=0 ){
    /* Populate the index search key. */
    u.bc.r.pKeyInfo = u.bc.pCx->pKeyInfo;
    u.bc.r.nField = u.bc.nField + 1;
    u.bc.r.flags = UNPACKED_PREFIX_SEARCH;
    u.bc.r.aMem = u.bc.aMx;
#ifdef SQLITE_DEBUG
    { int i; for(i=0; i<u.bc.r.nField; i++) assert( memIsValid(&u.bc.r.aMem[i]) ); }
#endif

    /* Extract the value of u.bc.R from register P3. */
    sqlite3VdbeMemIntegerify(pIn3);
    u.bc.R = pIn3->u.i;

    /* Search the B-Tree index. If no conflicting record is found, jump
    ** to P2. Otherwise, copy the rowid of the conflicting record to
    ** register P3 and fall through to the next instruction.  */
    rc = sqlite3BtreeMovetoUnpacked(u.bc.pCrsr, &u.bc.r, 0, 0, &u.bc.pCx->seekResult);
    if( (u.bc.r.flags & UNPACKED_PREFIX_SEARCH) || u.bc.r.rowid==u.bc.R ){
      pc = pOp->p2 - 1;
    }else{
      pIn3->u.i = u.bc.r.rowid;
    }
  }
  break;
}

/* Opcode: NotExists P1 P2 P3 * *
**
** Use the content of register P3 as an integer key.  If a record 
** with that key does not exist in table of P1, then jump to P2. 
** If the record does exist, then fall through.  The cursor is left 
** pointing to the record if it exists.
**
** The difference between this operation and NotFound is that this
** operation assumes the key is an integer and that P1 is a table whereas
** NotFound assumes key is a blob constructed from MakeRecord and
** P1 is an index.
**
** See also: Found, NotFound, IsUnique
*/
case OP_NotExists: {        /* jump, in3 */
#if 0  /* local variables moved into u.bd */
  VdbeCursor *pC;
  BtCursor *pCrsr;
  int res;
  u64 iKey;
#endif /* local variables moved into u.bd */

  pIn3 = &aMem[pOp->p3];
  assert( pIn3->flags & MEM_Int );
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bd.pC = p->apCsr[pOp->p1];
  assert( u.bd.pC!=0 );
  assert( u.bd.pC->isTable );
  assert( u.bd.pC->pseudoTableReg==0 );
  u.bd.pCrsr = u.bd.pC->pCursor;
  if( u.bd.pCrsr!=0 ){
    u.bd.res = 0;
    u.bd.iKey = pIn3->u.i;
    rc = sqlite3BtreeMovetoUnpacked(u.bd.pCrsr, 0, u.bd.iKey, 0, &u.bd.res);
    u.bd.pC->lastRowid = pIn3->u.i;
    u.bd.pC->rowidIsValid = u.bd.res==0 ?1:0;
    u.bd.pC->nullRow = 0;
    u.bd.pC->cacheStatus = CACHE_STALE;
    u.bd.pC->deferredMoveto = 0;
    if( u.bd.res!=0 ){
      pc = pOp->p2 - 1;
      assert( u.bd.pC->rowidIsValid==0 );
    }
    u.bd.pC->seekResult = u.bd.res;
  }else{
    /* This happens when an attempt to open a read cursor on the
    ** sqlite_master table returns SQLITE_EMPTY.
    */
    pc = pOp->p2 - 1;
    assert( u.bd.pC->rowidIsValid==0 );
    u.bd.pC->seekResult = 0;
  }
  break;
}

/* Opcode: Sequence P1 P2 * * *
**
** Find the next available sequence number for cursor P1.
67342
67343
67344
67345
67346
67347
67348
67349
67350
67351
67352
67353
67354
67355
67356
67357
67358
67359
67360
67361
67362
67363
67364
67365
67366
67367
67368
67369
67370
67371
67372
67373
67374
67375
67376
67377
67378
67379
67380
67381
67382
67383
67384
67385
67386
67387
67388
67389
67390
67391
67392
67393
67394
67395
67396
67397
67398
67399
67400
67401
67402
67403
67404
67405
67406
67407
67408
67409
67410
67411
67412
67413
67414
67415
67416
67417
67418
67419
67420
67421
67422
67423
67424
67425
67426
67427
67428
67429
67430
67431
67432
67433
67434
67435
67436
67437
67438
67439
67440
67441
67442
67443
67444
67445
67446
67447
67448
67449
67450
67451
67452
67453
67454
67455
67456
67457
67458
67459
67460
67461
67462
67463
67464
67465
67466
67467
67468
67469
67470
67471
67472
67473
67474
67475
67476
67477
67478
67479
67480
67481
67482
67483
67484
67485
67486
67487
67488
** the largest previously generated record number. No new record numbers are
** allowed to be less than this value. When this value reaches its maximum, 
** an SQLITE_FULL error is generated. The P3 register is updated with the '
** generated record number. This P3 mechanism is used to help implement the
** AUTOINCREMENT feature.
*/
case OP_NewRowid: {           /* out2-prerelease */
#if 0  /* local variables moved into u.bf */
  i64 v;                 /* The new rowid */
  VdbeCursor *pC;        /* Cursor of table to get the new rowid */
  int res;               /* Result of an sqlite3BtreeLast() */
  int cnt;               /* Counter to limit the number of searches */
  Mem *pMem;             /* Register holding largest rowid for AUTOINCREMENT */
  VdbeFrame *pFrame;     /* Root frame of VDBE */
#endif /* local variables moved into u.bf */

  u.bf.v = 0;
  u.bf.res = 0;
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bf.pC = p->apCsr[pOp->p1];
  assert( u.bf.pC!=0 );
  if( NEVER(u.bf.pC->pCursor==0) ){
    /* The zero initialization above is all that is needed */
  }else{
    /* The next rowid or record number (different terms for the same
    ** thing) is obtained in a two-step algorithm.
    **
    ** First we attempt to find the largest existing rowid and add one
    ** to that.  But if the largest existing rowid is already the maximum
    ** positive integer, we have to fall through to the second
    ** probabilistic algorithm
    **
    ** The second algorithm is to select a rowid at random and see if
    ** it already exists in the table.  If it does not exist, we have
    ** succeeded.  If the random rowid does exist, we select a new one
    ** and try again, up to 100 times.
    */
    assert( u.bf.pC->isTable );

#ifdef SQLITE_32BIT_ROWID
#   define MAX_ROWID 0x7fffffff
#else
    /* Some compilers complain about constants of the form 0x7fffffffffffffff.
    ** Others complain about 0x7ffffffffffffffffLL.  The following macro seems
    ** to provide the constant while making all compilers happy.
    */
#   define MAX_ROWID  (i64)( (((u64)0x7fffffff)<<32) | (u64)0xffffffff )
#endif

    if( !u.bf.pC->useRandomRowid ){
      u.bf.v = sqlite3BtreeGetCachedRowid(u.bf.pC->pCursor);
      if( u.bf.v==0 ){
        rc = sqlite3BtreeLast(u.bf.pC->pCursor, &u.bf.res);
        if( rc!=SQLITE_OK ){
          goto abort_due_to_error;
        }
        if( u.bf.res ){
          u.bf.v = 1;   /* IMP: R-61914-48074 */
        }else{
          assert( sqlite3BtreeCursorIsValid(u.bf.pC->pCursor) );
          rc = sqlite3BtreeKeySize(u.bf.pC->pCursor, &u.bf.v);
          assert( rc==SQLITE_OK );   /* Cannot fail following BtreeLast() */
          if( u.bf.v==MAX_ROWID ){
            u.bf.pC->useRandomRowid = 1;
          }else{
            u.bf.v++;   /* IMP: R-29538-34987 */
          }
        }
      }

#ifndef SQLITE_OMIT_AUTOINCREMENT
      if( pOp->p3 ){
        /* Assert that P3 is a valid memory cell. */
        assert( pOp->p3>0 );
        if( p->pFrame ){
          for(u.bf.pFrame=p->pFrame; u.bf.pFrame->pParent; u.bf.pFrame=u.bf.pFrame->pParent);
          /* Assert that P3 is a valid memory cell. */
          assert( pOp->p3<=u.bf.pFrame->nMem );
          u.bf.pMem = &u.bf.pFrame->aMem[pOp->p3];
        }else{
          /* Assert that P3 is a valid memory cell. */
          assert( pOp->p3<=p->nMem );
          u.bf.pMem = &aMem[pOp->p3];
          memAboutToChange(p, u.bf.pMem);
        }
        assert( memIsValid(u.bf.pMem) );

        REGISTER_TRACE(pOp->p3, u.bf.pMem);
        sqlite3VdbeMemIntegerify(u.bf.pMem);
        assert( (u.bf.pMem->flags & MEM_Int)!=0 );  /* mem(P3) holds an integer */
        if( u.bf.pMem->u.i==MAX_ROWID || u.bf.pC->useRandomRowid ){
          rc = SQLITE_FULL;   /* IMP: R-12275-61338 */
          goto abort_due_to_error;
        }
        if( u.bf.v<u.bf.pMem->u.i+1 ){
          u.bf.v = u.bf.pMem->u.i + 1;
        }
        u.bf.pMem->u.i = u.bf.v;
      }
#endif

      sqlite3BtreeSetCachedRowid(u.bf.pC->pCursor, u.bf.v<MAX_ROWID ? u.bf.v+1 : 0);
    }
    if( u.bf.pC->useRandomRowid ){
      /* IMPLEMENTATION-OF: R-07677-41881 If the largest ROWID is equal to the
      ** largest possible integer (9223372036854775807) then the database
      ** engine starts picking positive candidate ROWIDs at random until
      ** it finds one that is not previously used. */
      assert( pOp->p3==0 );  /* We cannot be in random rowid mode if this is
                             ** an AUTOINCREMENT table. */
      /* on the first attempt, simply do one more than previous */
      u.bf.v = lastRowid;
      u.bf.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
      u.bf.v++; /* ensure non-zero */
      u.bf.cnt = 0;
      while(   ((rc = sqlite3BtreeMovetoUnpacked(u.bf.pC->pCursor, 0, (u64)u.bf.v,
                                                 0, &u.bf.res))==SQLITE_OK)
            && (u.bf.res==0)
            && (++u.bf.cnt<100)){
        /* collision - try another random rowid */
        sqlite3_randomness(sizeof(u.bf.v), &u.bf.v);
        if( u.bf.cnt<5 ){
          /* try "small" random rowids for the initial attempts */
          u.bf.v &= 0xffffff;
        }else{
          u.bf.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
        }
        u.bf.v++; /* ensure non-zero */
      }
      if( rc==SQLITE_OK && u.bf.res==0 ){
        rc = SQLITE_FULL;   /* IMP: R-38219-53002 */
        goto abort_due_to_error;
      }
      assert( u.bf.v>0 );  /* EV: R-40812-03570 */
    }
    u.bf.pC->rowidIsValid = 0;
    u.bf.pC->deferredMoveto = 0;
    u.bf.pC->cacheStatus = CACHE_STALE;
  }
  pOut->u.i = u.bf.v;
  break;
}

/* Opcode: Insert P1 P2 P3 P4 P5
**
** Write an entry into the table of cursor P1.  A new entry is
** created if it doesn't already exist or the data for an existing







|






|

|
|

|
|
|















|











|
|
|
|



|
|

|
|

|
|

|









|

|
|



|
|

|

|
|
|
|



|
|

|



|

|







|
|
|
|
|
|
|
|

|
|

|

|

|

|



|

|
|
|

|







66521
66522
66523
66524
66525
66526
66527
66528
66529
66530
66531
66532
66533
66534
66535
66536
66537
66538
66539
66540
66541
66542
66543
66544
66545
66546
66547
66548
66549
66550
66551
66552
66553
66554
66555
66556
66557
66558
66559
66560
66561
66562
66563
66564
66565
66566
66567
66568
66569
66570
66571
66572
66573
66574
66575
66576
66577
66578
66579
66580
66581
66582
66583
66584
66585
66586
66587
66588
66589
66590
66591
66592
66593
66594
66595
66596
66597
66598
66599
66600
66601
66602
66603
66604
66605
66606
66607
66608
66609
66610
66611
66612
66613
66614
66615
66616
66617
66618
66619
66620
66621
66622
66623
66624
66625
66626
66627
66628
66629
66630
66631
66632
66633
66634
66635
66636
66637
66638
66639
66640
66641
66642
66643
66644
66645
66646
66647
66648
66649
66650
66651
66652
66653
66654
66655
66656
66657
66658
66659
66660
66661
66662
66663
66664
66665
66666
66667
** the largest previously generated record number. No new record numbers are
** allowed to be less than this value. When this value reaches its maximum, 
** an SQLITE_FULL error is generated. The P3 register is updated with the '
** generated record number. This P3 mechanism is used to help implement the
** AUTOINCREMENT feature.
*/
case OP_NewRowid: {           /* out2-prerelease */
#if 0  /* local variables moved into u.be */
  i64 v;                 /* The new rowid */
  VdbeCursor *pC;        /* Cursor of table to get the new rowid */
  int res;               /* Result of an sqlite3BtreeLast() */
  int cnt;               /* Counter to limit the number of searches */
  Mem *pMem;             /* Register holding largest rowid for AUTOINCREMENT */
  VdbeFrame *pFrame;     /* Root frame of VDBE */
#endif /* local variables moved into u.be */

  u.be.v = 0;
  u.be.res = 0;
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.be.pC = p->apCsr[pOp->p1];
  assert( u.be.pC!=0 );
  if( NEVER(u.be.pC->pCursor==0) ){
    /* The zero initialization above is all that is needed */
  }else{
    /* The next rowid or record number (different terms for the same
    ** thing) is obtained in a two-step algorithm.
    **
    ** First we attempt to find the largest existing rowid and add one
    ** to that.  But if the largest existing rowid is already the maximum
    ** positive integer, we have to fall through to the second
    ** probabilistic algorithm
    **
    ** The second algorithm is to select a rowid at random and see if
    ** it already exists in the table.  If it does not exist, we have
    ** succeeded.  If the random rowid does exist, we select a new one
    ** and try again, up to 100 times.
    */
    assert( u.be.pC->isTable );

#ifdef SQLITE_32BIT_ROWID
#   define MAX_ROWID 0x7fffffff
#else
    /* Some compilers complain about constants of the form 0x7fffffffffffffff.
    ** Others complain about 0x7ffffffffffffffffLL.  The following macro seems
    ** to provide the constant while making all compilers happy.
    */
#   define MAX_ROWID  (i64)( (((u64)0x7fffffff)<<32) | (u64)0xffffffff )
#endif

    if( !u.be.pC->useRandomRowid ){
      u.be.v = sqlite3BtreeGetCachedRowid(u.be.pC->pCursor);
      if( u.be.v==0 ){
        rc = sqlite3BtreeLast(u.be.pC->pCursor, &u.be.res);
        if( rc!=SQLITE_OK ){
          goto abort_due_to_error;
        }
        if( u.be.res ){
          u.be.v = 1;   /* IMP: R-61914-48074 */
        }else{
          assert( sqlite3BtreeCursorIsValid(u.be.pC->pCursor) );
          rc = sqlite3BtreeKeySize(u.be.pC->pCursor, &u.be.v);
          assert( rc==SQLITE_OK );   /* Cannot fail following BtreeLast() */
          if( u.be.v==MAX_ROWID ){
            u.be.pC->useRandomRowid = 1;
          }else{
            u.be.v++;   /* IMP: R-29538-34987 */
          }
        }
      }

#ifndef SQLITE_OMIT_AUTOINCREMENT
      if( pOp->p3 ){
        /* Assert that P3 is a valid memory cell. */
        assert( pOp->p3>0 );
        if( p->pFrame ){
          for(u.be.pFrame=p->pFrame; u.be.pFrame->pParent; u.be.pFrame=u.be.pFrame->pParent);
          /* Assert that P3 is a valid memory cell. */
          assert( pOp->p3<=u.be.pFrame->nMem );
          u.be.pMem = &u.be.pFrame->aMem[pOp->p3];
        }else{
          /* Assert that P3 is a valid memory cell. */
          assert( pOp->p3<=p->nMem );
          u.be.pMem = &aMem[pOp->p3];
          memAboutToChange(p, u.be.pMem);
        }
        assert( memIsValid(u.be.pMem) );

        REGISTER_TRACE(pOp->p3, u.be.pMem);
        sqlite3VdbeMemIntegerify(u.be.pMem);
        assert( (u.be.pMem->flags & MEM_Int)!=0 );  /* mem(P3) holds an integer */
        if( u.be.pMem->u.i==MAX_ROWID || u.be.pC->useRandomRowid ){
          rc = SQLITE_FULL;   /* IMP: R-12275-61338 */
          goto abort_due_to_error;
        }
        if( u.be.v<u.be.pMem->u.i+1 ){
          u.be.v = u.be.pMem->u.i + 1;
        }
        u.be.pMem->u.i = u.be.v;
      }
#endif

      sqlite3BtreeSetCachedRowid(u.be.pC->pCursor, u.be.v<MAX_ROWID ? u.be.v+1 : 0);
    }
    if( u.be.pC->useRandomRowid ){
      /* IMPLEMENTATION-OF: R-07677-41881 If the largest ROWID is equal to the
      ** largest possible integer (9223372036854775807) then the database
      ** engine starts picking positive candidate ROWIDs at random until
      ** it finds one that is not previously used. */
      assert( pOp->p3==0 );  /* We cannot be in random rowid mode if this is
                             ** an AUTOINCREMENT table. */
      /* on the first attempt, simply do one more than previous */
      u.be.v = lastRowid;
      u.be.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
      u.be.v++; /* ensure non-zero */
      u.be.cnt = 0;
      while(   ((rc = sqlite3BtreeMovetoUnpacked(u.be.pC->pCursor, 0, (u64)u.be.v,
                                                 0, &u.be.res))==SQLITE_OK)
            && (u.be.res==0)
            && (++u.be.cnt<100)){
        /* collision - try another random rowid */
        sqlite3_randomness(sizeof(u.be.v), &u.be.v);
        if( u.be.cnt<5 ){
          /* try "small" random rowids for the initial attempts */
          u.be.v &= 0xffffff;
        }else{
          u.be.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
        }
        u.be.v++; /* ensure non-zero */
      }
      if( rc==SQLITE_OK && u.be.res==0 ){
        rc = SQLITE_FULL;   /* IMP: R-38219-53002 */
        goto abort_due_to_error;
      }
      assert( u.be.v>0 );  /* EV: R-40812-03570 */
    }
    u.be.pC->rowidIsValid = 0;
    u.be.pC->deferredMoveto = 0;
    u.be.pC->cacheStatus = CACHE_STALE;
  }
  pOut->u.i = u.be.v;
  break;
}

/* Opcode: Insert P1 P2 P3 P4 P5
**
** Write an entry into the table of cursor P1.  A new entry is
** created if it doesn't already exist or the data for an existing
67524
67525
67526
67527
67528
67529
67530
67531
67532
67533
67534
67535
67536
67537
67538
67539
67540
67541
67542
67543
67544
67545
67546
67547
67548
67549
67550
67551
67552
67553
67554
67555
67556
67557
67558
67559
67560
67561
67562
67563
67564
67565
67566
67567
67568
67569
67570
67571
67572
67573
67574
67575
67576
67577
67578
67579
67580
67581
67582
67583
67584
67585
67586
67587
67588
67589
67590
67591
67592
67593
67594
67595
67596
67597
67598
67599
67600
67601
/* Opcode: InsertInt P1 P2 P3 P4 P5
**
** This works exactly like OP_Insert except that the key is the
** integer value P3, not the value of the integer stored in register P3.
*/
case OP_Insert: 
case OP_InsertInt: {
#if 0  /* local variables moved into u.bg */
  Mem *pData;       /* MEM cell holding data for the record to be inserted */
  Mem *pKey;        /* MEM cell holding key  for the record */
  i64 iKey;         /* The integer ROWID or key for the record to be inserted */
  VdbeCursor *pC;   /* Cursor to table into which insert is written */
  int nZero;        /* Number of zero-bytes to append */
  int seekResult;   /* Result of prior seek or 0 if no USESEEKRESULT flag */
  const char *zDb;  /* database name - used by the update hook */
  const char *zTbl; /* Table name - used by the opdate hook */
  int op;           /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
#endif /* local variables moved into u.bg */

  u.bg.pData = &aMem[pOp->p2];
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( memIsValid(u.bg.pData) );
  u.bg.pC = p->apCsr[pOp->p1];
  assert( u.bg.pC!=0 );
  assert( u.bg.pC->pCursor!=0 );
  assert( u.bg.pC->pseudoTableReg==0 );
  assert( u.bg.pC->isTable );
  REGISTER_TRACE(pOp->p2, u.bg.pData);

  if( pOp->opcode==OP_Insert ){
    u.bg.pKey = &aMem[pOp->p3];
    assert( u.bg.pKey->flags & MEM_Int );
    assert( memIsValid(u.bg.pKey) );
    REGISTER_TRACE(pOp->p3, u.bg.pKey);
    u.bg.iKey = u.bg.pKey->u.i;
  }else{
    assert( pOp->opcode==OP_InsertInt );
    u.bg.iKey = pOp->p3;
  }

  if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
  if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = u.bg.iKey;
  if( u.bg.pData->flags & MEM_Null ){
    u.bg.pData->z = 0;
    u.bg.pData->n = 0;
  }else{
    assert( u.bg.pData->flags & (MEM_Blob|MEM_Str) );
  }
  u.bg.seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bg.pC->seekResult : 0);
  if( u.bg.pData->flags & MEM_Zero ){
    u.bg.nZero = u.bg.pData->u.nZero;
  }else{
    u.bg.nZero = 0;
  }
  sqlite3BtreeSetCachedRowid(u.bg.pC->pCursor, 0);
  rc = sqlite3BtreeInsert(u.bg.pC->pCursor, 0, u.bg.iKey,
                          u.bg.pData->z, u.bg.pData->n, u.bg.nZero,
                          pOp->p5 & OPFLAG_APPEND, u.bg.seekResult
  );
  u.bg.pC->rowidIsValid = 0;
  u.bg.pC->deferredMoveto = 0;
  u.bg.pC->cacheStatus = CACHE_STALE;

  /* Invoke the update-hook if required. */
  if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
    u.bg.zDb = db->aDb[u.bg.pC->iDb].zName;
    u.bg.zTbl = pOp->p4.z;
    u.bg.op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
    assert( u.bg.pC->isTable );
    db->xUpdateCallback(db->pUpdateArg, u.bg.op, u.bg.zDb, u.bg.zTbl, u.bg.iKey);
    assert( u.bg.pC->iDb>=0 );
  }
  break;
}

/* Opcode: Delete P1 P2 * P4 *
**
** Delete the record at which the P1 cursor is currently pointing.







|









|

|

|
|
|
|
|
|
|


|
|
|
|
|


|



|
|
|
|

|

|
|
|

|

|
|
|
|

|
|
|



|
|
|
|
|
|







66703
66704
66705
66706
66707
66708
66709
66710
66711
66712
66713
66714
66715
66716
66717
66718
66719
66720
66721
66722
66723
66724
66725
66726
66727
66728
66729
66730
66731
66732
66733
66734
66735
66736
66737
66738
66739
66740
66741
66742
66743
66744
66745
66746
66747
66748
66749
66750
66751
66752
66753
66754
66755
66756
66757
66758
66759
66760
66761
66762
66763
66764
66765
66766
66767
66768
66769
66770
66771
66772
66773
66774
66775
66776
66777
66778
66779
66780
/* Opcode: InsertInt P1 P2 P3 P4 P5
**
** This works exactly like OP_Insert except that the key is the
** integer value P3, not the value of the integer stored in register P3.
*/
case OP_Insert: 
case OP_InsertInt: {
#if 0  /* local variables moved into u.bf */
  Mem *pData;       /* MEM cell holding data for the record to be inserted */
  Mem *pKey;        /* MEM cell holding key  for the record */
  i64 iKey;         /* The integer ROWID or key for the record to be inserted */
  VdbeCursor *pC;   /* Cursor to table into which insert is written */
  int nZero;        /* Number of zero-bytes to append */
  int seekResult;   /* Result of prior seek or 0 if no USESEEKRESULT flag */
  const char *zDb;  /* database name - used by the update hook */
  const char *zTbl; /* Table name - used by the opdate hook */
  int op;           /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
#endif /* local variables moved into u.bf */

  u.bf.pData = &aMem[pOp->p2];
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( memIsValid(u.bf.pData) );
  u.bf.pC = p->apCsr[pOp->p1];
  assert( u.bf.pC!=0 );
  assert( u.bf.pC->pCursor!=0 );
  assert( u.bf.pC->pseudoTableReg==0 );
  assert( u.bf.pC->isTable );
  REGISTER_TRACE(pOp->p2, u.bf.pData);

  if( pOp->opcode==OP_Insert ){
    u.bf.pKey = &aMem[pOp->p3];
    assert( u.bf.pKey->flags & MEM_Int );
    assert( memIsValid(u.bf.pKey) );
    REGISTER_TRACE(pOp->p3, u.bf.pKey);
    u.bf.iKey = u.bf.pKey->u.i;
  }else{
    assert( pOp->opcode==OP_InsertInt );
    u.bf.iKey = pOp->p3;
  }

  if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
  if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = u.bf.iKey;
  if( u.bf.pData->flags & MEM_Null ){
    u.bf.pData->z = 0;
    u.bf.pData->n = 0;
  }else{
    assert( u.bf.pData->flags & (MEM_Blob|MEM_Str) );
  }
  u.bf.seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bf.pC->seekResult : 0);
  if( u.bf.pData->flags & MEM_Zero ){
    u.bf.nZero = u.bf.pData->u.nZero;
  }else{
    u.bf.nZero = 0;
  }
  sqlite3BtreeSetCachedRowid(u.bf.pC->pCursor, 0);
  rc = sqlite3BtreeInsert(u.bf.pC->pCursor, 0, u.bf.iKey,
                          u.bf.pData->z, u.bf.pData->n, u.bf.nZero,
                          pOp->p5 & OPFLAG_APPEND, u.bf.seekResult
  );
  u.bf.pC->rowidIsValid = 0;
  u.bf.pC->deferredMoveto = 0;
  u.bf.pC->cacheStatus = CACHE_STALE;

  /* Invoke the update-hook if required. */
  if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
    u.bf.zDb = db->aDb[u.bf.pC->iDb].zName;
    u.bf.zTbl = pOp->p4.z;
    u.bf.op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
    assert( u.bf.pC->isTable );
    db->xUpdateCallback(db->pUpdateArg, u.bf.op, u.bf.zDb, u.bf.zTbl, u.bf.iKey);
    assert( u.bf.pC->iDb>=0 );
  }
  break;
}

/* Opcode: Delete P1 P2 * P4 *
**
** Delete the record at which the P1 cursor is currently pointing.
67613
67614
67615
67616
67617
67618
67619
67620
67621
67622
67623
67624
67625
67626
67627
67628
67629
67630
67631
67632
67633
67634
67635
67636
67637
67638
67639
67640
67641
67642
67643
67644
67645
67646
67647
67648
67649
67650
67651
67652
67653
67654
67655
67656
67657
67658
67659
67660
67661
67662
67663
67664
67665
67666
67667
67668
67669
67670
67671
67672
67673
67674
67675
67676
67677
67678
67679
67680
67681
67682
67683
67684
67685
67686
67687
67688
67689
67690
67691
67692
67693
67694
67695
67696
67697
67698
67699
67700
67701
67702
67703
67704
67705
67706
67707
67708
67709
67710
67711
67712
67713
67714
67715
67716
67717
67718
67719
67720
67721
67722
67723
67724
**
** If P4 is not NULL, then it is the name of the table that P1 is
** pointing to.  The update hook will be invoked, if it exists.
** If P4 is not NULL then the P1 cursor must have been positioned
** using OP_NotFound prior to invoking this opcode.
*/
case OP_Delete: {
#if 0  /* local variables moved into u.bh */
  i64 iKey;
  VdbeCursor *pC;
#endif /* local variables moved into u.bh */

  u.bh.iKey = 0;
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bh.pC = p->apCsr[pOp->p1];
  assert( u.bh.pC!=0 );
  assert( u.bh.pC->pCursor!=0 );  /* Only valid for real tables, no pseudotables */

  /* If the update-hook will be invoked, set u.bh.iKey to the rowid of the
  ** row being deleted.
  */
  if( db->xUpdateCallback && pOp->p4.z ){
    assert( u.bh.pC->isTable );
    assert( u.bh.pC->rowidIsValid );  /* lastRowid set by previous OP_NotFound */
    u.bh.iKey = u.bh.pC->lastRowid;
  }

  /* The OP_Delete opcode always follows an OP_NotExists or OP_Last or
  ** OP_Column on the same table without any intervening operations that
  ** might move or invalidate the cursor.  Hence cursor u.bh.pC is always pointing
  ** to the row to be deleted and the sqlite3VdbeCursorMoveto() operation
  ** below is always a no-op and cannot fail.  We will run it anyhow, though,
  ** to guard against future changes to the code generator.
  **/
  assert( u.bh.pC->deferredMoveto==0 );
  rc = sqlite3VdbeCursorMoveto(u.bh.pC);
  if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;

  sqlite3BtreeSetCachedRowid(u.bh.pC->pCursor, 0);
  rc = sqlite3BtreeDelete(u.bh.pC->pCursor);
  u.bh.pC->cacheStatus = CACHE_STALE;

  /* Invoke the update-hook if required. */
  if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
    const char *zDb = db->aDb[u.bh.pC->iDb].zName;
    const char *zTbl = pOp->p4.z;
    db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, u.bh.iKey);
    assert( u.bh.pC->iDb>=0 );
  }
  if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
  break;
}
/* Opcode: ResetCount * * * * *
**
** The value of the change counter is copied to the database handle
** change counter (returned by subsequent calls to sqlite3_changes()).
** Then the VMs internal change counter resets to 0.
** This is used by trigger programs.
*/
case OP_ResetCount: {
  sqlite3VdbeSetChanges(db, p->nChange);
  p->nChange = 0;
  break;
}

/* Opcode: SorterCompare P1 P2 P3
**
** P1 is a sorter cursor. This instruction compares the record blob in 
** register P3 with the entry that the sorter cursor currently points to.
** If, excluding the rowid fields at the end, the two records are a match,
** fall through to the next instruction. Otherwise, jump to instruction P2.
*/
case OP_SorterCompare: {
#if 0  /* local variables moved into u.bi */
  VdbeCursor *pC;
  int res;
#endif /* local variables moved into u.bi */

  u.bi.pC = p->apCsr[pOp->p1];
  assert( isSorter(u.bi.pC) );
  pIn3 = &aMem[pOp->p3];
  rc = sqlite3VdbeSorterCompare(u.bi.pC, pIn3, &u.bi.res);
  if( u.bi.res ){
    pc = pOp->p2-1;
  }
  break;
};

/* Opcode: SorterData P1 P2 * * *
**
** Write into register P2 the current sorter data for sorter cursor P1.
*/
case OP_SorterData: {
#if 0  /* local variables moved into u.bj */
  VdbeCursor *pC;
#endif /* local variables moved into u.bj */
#ifndef SQLITE_OMIT_MERGE_SORT
  pOut = &aMem[pOp->p2];
  u.bj.pC = p->apCsr[pOp->p1];
  assert( u.bj.pC->isSorter );
  rc = sqlite3VdbeSorterRowkey(u.bj.pC, pOut);
#else
  pOp->opcode = OP_RowKey;
  pc--;
#endif
  break;
}

/* Opcode: RowData P1 P2 * * *
**
** Write into register P2 the complete row data for cursor P1.
** There is no interpretation of the data.  







|


|

|

|
|
|

|



|
|
|




|




|
|


|
|
|



|

|
|














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







66792
66793
66794
66795
66796
66797
66798
66799
66800
66801
66802
66803
66804
66805
66806
66807
66808
66809
66810
66811
66812
66813
66814
66815
66816
66817
66818
66819
66820
66821
66822
66823
66824
66825
66826
66827
66828
66829
66830
66831
66832
66833
66834
66835
66836
66837
66838
66839
66840
66841
66842
66843
66844
66845
66846
66847
66848
66849
66850
66851
66852
66853











































66854
66855
66856
66857
66858
66859
66860
**
** If P4 is not NULL, then it is the name of the table that P1 is
** pointing to.  The update hook will be invoked, if it exists.
** If P4 is not NULL then the P1 cursor must have been positioned
** using OP_NotFound prior to invoking this opcode.
*/
case OP_Delete: {
#if 0  /* local variables moved into u.bg */
  i64 iKey;
  VdbeCursor *pC;
#endif /* local variables moved into u.bg */

  u.bg.iKey = 0;
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bg.pC = p->apCsr[pOp->p1];
  assert( u.bg.pC!=0 );
  assert( u.bg.pC->pCursor!=0 );  /* Only valid for real tables, no pseudotables */

  /* If the update-hook will be invoked, set u.bg.iKey to the rowid of the
  ** row being deleted.
  */
  if( db->xUpdateCallback && pOp->p4.z ){
    assert( u.bg.pC->isTable );
    assert( u.bg.pC->rowidIsValid );  /* lastRowid set by previous OP_NotFound */
    u.bg.iKey = u.bg.pC->lastRowid;
  }

  /* The OP_Delete opcode always follows an OP_NotExists or OP_Last or
  ** OP_Column on the same table without any intervening operations that
  ** might move or invalidate the cursor.  Hence cursor u.bg.pC is always pointing
  ** to the row to be deleted and the sqlite3VdbeCursorMoveto() operation
  ** below is always a no-op and cannot fail.  We will run it anyhow, though,
  ** to guard against future changes to the code generator.
  **/
  assert( u.bg.pC->deferredMoveto==0 );
  rc = sqlite3VdbeCursorMoveto(u.bg.pC);
  if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;

  sqlite3BtreeSetCachedRowid(u.bg.pC->pCursor, 0);
  rc = sqlite3BtreeDelete(u.bg.pC->pCursor);
  u.bg.pC->cacheStatus = CACHE_STALE;

  /* Invoke the update-hook if required. */
  if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
    const char *zDb = db->aDb[u.bg.pC->iDb].zName;
    const char *zTbl = pOp->p4.z;
    db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, u.bg.iKey);
    assert( u.bg.pC->iDb>=0 );
  }
  if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
  break;
}
/* Opcode: ResetCount * * * * *
**
** The value of the change counter is copied to the database handle
** change counter (returned by subsequent calls to sqlite3_changes()).
** Then the VMs internal change counter resets to 0.
** This is used by trigger programs.
*/
case OP_ResetCount: {
  sqlite3VdbeSetChanges(db, p->nChange);
  p->nChange = 0;











































  break;
}

/* Opcode: RowData P1 P2 * * *
**
** Write into register P2 the complete row data for cursor P1.
** There is no interpretation of the data.  
67736
67737
67738
67739
67740
67741
67742
67743
67744
67745
67746
67747
67748
67749
67750
67751
67752
67753
67754
67755
67756
67757
67758
67759
67760
67761
67762
67763
67764
67765
67766
67767
67768
67769
67770
67771
67772
67773
67774
67775
67776
67777
67778
67779
67780
67781
67782
67783
67784
67785
67786
67787
67788
67789
67790
67791
67792
67793
67794
67795
67796
67797
67798
67799
67800
67801
67802
67803
67804
67805
67806
67807
67808
67809
67810
67811
67812
67813
67814
67815
67816
67817
67818
67819
67820
67821
67822
67823
67824
67825
67826
67827
67828
67829
67830
67831
67832
67833
67834
67835
67836
67837
67838
67839
67840
67841
67842
67843
67844
67845
67846
67847
67848
67849
67850
67851
67852
67853
67854
67855
67856
67857
67858
67859
67860
67861
67862
67863
67864
67865
67866
67867
67868
67869
67870
67871
67872
67873
67874
67875
67876
67877
67878
67879
67880
67881
67882
67883
67884
67885
67886
67887
67888
67889
67890
67891
67892
67893
67894
67895
67896
67897
67898
67899
67900
67901
67902
67903
67904
67905
67906
67907
67908
67909
67910
67911
67912
67913
67914
67915
67916
67917
67918
67919
67920
67921
67922
67923
67924
67925
67926
67927
67928
67929
67930
67931
67932
67933
67934
67935
67936
67937
67938
67939
67940
67941
67942
67943
67944
67945
67946
67947
67948
67949
67950
67951
67952
67953
67954
67955
67956
67957
67958
67959
67960
67961
67962
67963
67964
67965
67966
67967
67968
67969
67970
67971
67972
67973
67974
67975
67976
67977
67978
67979
67980
67981
67982
67983
67984
67985
67986
67987
67988
67989
67990
67991
67992
67993
67994
67995
67996
67997
67998
67999
68000
68001
68002
68003
68004
68005
68006
68007
68008
68009
68010
68011
68012
68013
68014
68015

68016
68017
68018
68019
68020
68021
68022
68023
68024
68025
68026
68027
68028
68029
68030

68031
68032
68033
68034
68035
68036
68037
68038
68039
68040
68041
68042
68043
68044
68045
68046
68047
68048
68049
68050
68051
68052
68053
68054
68055
68056
68057
68058
68059
68060
68061
68062
68063
68064
68065
68066
68067
68068
68069
68070
68071
68072
68073
68074
68075
68076
68077
68078
68079
68080
68081
68082
68083
68084
68085
68086
68087
68088
68089
68090
68091
68092
68093
68094
68095
68096
68097
68098
68099
68100
68101
68102
68103
68104
68105
68106
68107
68108
68109
68110
68111
68112
68113
68114
68115
68116
68117
68118
68119
68120
68121
68122
68123
68124
68125
68126
68127
68128
68129
68130
68131
68132
68133
68134
68135
68136
68137
68138
68139
68140
68141
68142
68143
68144
68145
68146
68147
68148
68149
68150
68151
68152
68153
68154
68155
68156
68157
68158
68159
68160
68161
68162
68163
68164
68165
68166
68167
68168
68169
68170
68171
68172
68173
68174
68175
68176
68177
** it is found in the database file.
**
** If the P1 cursor must be pointing to a valid row (not a NULL row)
** of a real table, not a pseudo-table.
*/
case OP_RowKey:
case OP_RowData: {
#if 0  /* local variables moved into u.bk */
  VdbeCursor *pC;
  BtCursor *pCrsr;
  u32 n;
  i64 n64;
#endif /* local variables moved into u.bk */

  pOut = &aMem[pOp->p2];
  memAboutToChange(p, pOut);

  /* Note that RowKey and RowData are really exactly the same instruction */
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bk.pC = p->apCsr[pOp->p1];
  assert( u.bk.pC->isSorter==0 );
  assert( u.bk.pC->isTable || pOp->opcode!=OP_RowData );
  assert( u.bk.pC->isIndex || pOp->opcode==OP_RowData );
  assert( u.bk.pC!=0 );
  assert( u.bk.pC->nullRow==0 );
  assert( u.bk.pC->pseudoTableReg==0 );
  assert( !u.bk.pC->isSorter );
  assert( u.bk.pC->pCursor!=0 );
  u.bk.pCrsr = u.bk.pC->pCursor;
  assert( sqlite3BtreeCursorIsValid(u.bk.pCrsr) );

  /* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists or
  ** OP_Rewind/Op_Next with no intervening instructions that might invalidate
  ** the cursor.  Hence the following sqlite3VdbeCursorMoveto() call is always
  ** a no-op and can never fail.  But we leave it in place as a safety.
  */
  assert( u.bk.pC->deferredMoveto==0 );
  rc = sqlite3VdbeCursorMoveto(u.bk.pC);
  if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;

  if( u.bk.pC->isIndex ){
    assert( !u.bk.pC->isTable );
    rc = sqlite3BtreeKeySize(u.bk.pCrsr, &u.bk.n64);
    assert( rc==SQLITE_OK );    /* True because of CursorMoveto() call above */
    if( u.bk.n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){
      goto too_big;
    }
    u.bk.n = (u32)u.bk.n64;
  }else{
    rc = sqlite3BtreeDataSize(u.bk.pCrsr, &u.bk.n);
    assert( rc==SQLITE_OK );    /* DataSize() cannot fail */
    if( u.bk.n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
      goto too_big;
    }
  }
  if( sqlite3VdbeMemGrow(pOut, u.bk.n, 0) ){
    goto no_mem;
  }
  pOut->n = u.bk.n;
  MemSetTypeFlag(pOut, MEM_Blob);
  if( u.bk.pC->isIndex ){
    rc = sqlite3BtreeKey(u.bk.pCrsr, 0, u.bk.n, pOut->z);
  }else{
    rc = sqlite3BtreeData(u.bk.pCrsr, 0, u.bk.n, pOut->z);
  }
  pOut->enc = SQLITE_UTF8;  /* In case the blob is ever cast to text */
  UPDATE_MAX_BLOBSIZE(pOut);
  break;
}

/* Opcode: Rowid P1 P2 * * *
**
** Store in register P2 an integer which is the key of the table entry that
** P1 is currently point to.
**
** P1 can be either an ordinary table or a virtual table.  There used to
** be a separate OP_VRowid opcode for use with virtual tables, but this
** one opcode now works for both table types.
*/
case OP_Rowid: {                 /* out2-prerelease */
#if 0  /* local variables moved into u.bl */
  VdbeCursor *pC;
  i64 v;
  sqlite3_vtab *pVtab;
  const sqlite3_module *pModule;
#endif /* local variables moved into u.bl */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bl.pC = p->apCsr[pOp->p1];
  assert( u.bl.pC!=0 );
  assert( u.bl.pC->pseudoTableReg==0 );
  if( u.bl.pC->nullRow ){
    pOut->flags = MEM_Null;
    break;
  }else if( u.bl.pC->deferredMoveto ){
    u.bl.v = u.bl.pC->movetoTarget;
#ifndef SQLITE_OMIT_VIRTUALTABLE
  }else if( u.bl.pC->pVtabCursor ){
    u.bl.pVtab = u.bl.pC->pVtabCursor->pVtab;
    u.bl.pModule = u.bl.pVtab->pModule;
    assert( u.bl.pModule->xRowid );
    rc = u.bl.pModule->xRowid(u.bl.pC->pVtabCursor, &u.bl.v);
    importVtabErrMsg(p, u.bl.pVtab);
#endif /* SQLITE_OMIT_VIRTUALTABLE */
  }else{
    assert( u.bl.pC->pCursor!=0 );
    rc = sqlite3VdbeCursorMoveto(u.bl.pC);
    if( rc ) goto abort_due_to_error;
    if( u.bl.pC->rowidIsValid ){
      u.bl.v = u.bl.pC->lastRowid;
    }else{
      rc = sqlite3BtreeKeySize(u.bl.pC->pCursor, &u.bl.v);
      assert( rc==SQLITE_OK );  /* Always so because of CursorMoveto() above */
    }
  }
  pOut->u.i = u.bl.v;
  break;
}

/* Opcode: NullRow P1 * * * *
**
** Move the cursor P1 to a null row.  Any OP_Column operations
** that occur while the cursor is on the null row will always
** write a NULL.
*/
case OP_NullRow: {
#if 0  /* local variables moved into u.bm */
  VdbeCursor *pC;
#endif /* local variables moved into u.bm */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bm.pC = p->apCsr[pOp->p1];
  assert( u.bm.pC!=0 );
  u.bm.pC->nullRow = 1;
  u.bm.pC->rowidIsValid = 0;
  assert( u.bm.pC->pCursor || u.bm.pC->pVtabCursor );
  if( u.bm.pC->pCursor ){
    sqlite3BtreeClearCursor(u.bm.pC->pCursor);
  }
  break;
}

/* Opcode: Last P1 P2 * * *
**
** The next use of the Rowid or Column or Next instruction for P1 
** will refer to the last entry in the database table or index.
** If the table or index is empty and P2>0, then jump immediately to P2.
** If P2 is 0 or if the table or index is not empty, fall through
** to the following instruction.
*/
case OP_Last: {        /* jump */
#if 0  /* local variables moved into u.bn */
  VdbeCursor *pC;
  BtCursor *pCrsr;
  int res;
#endif /* local variables moved into u.bn */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bn.pC = p->apCsr[pOp->p1];
  assert( u.bn.pC!=0 );
  u.bn.pCrsr = u.bn.pC->pCursor;
  if( NEVER(u.bn.pCrsr==0) ){
    u.bn.res = 1;
  }else{
    rc = sqlite3BtreeLast(u.bn.pCrsr, &u.bn.res);
  }
  u.bn.pC->nullRow = (u8)u.bn.res;
  u.bn.pC->deferredMoveto = 0;
  u.bn.pC->rowidIsValid = 0;
  u.bn.pC->cacheStatus = CACHE_STALE;
  if( pOp->p2>0 && u.bn.res ){
    pc = pOp->p2 - 1;
  }
  break;
}


/* Opcode: Sort P1 P2 * * *
**
** This opcode does exactly the same thing as OP_Rewind except that
** it increments an undocumented global variable used for testing.
**
** Sorting is accomplished by writing records into a sorting index,
** then rewinding that index and playing it back from beginning to
** end.  We use the OP_Sort opcode instead of OP_Rewind to do the
** rewinding so that the global variable will be incremented and
** regression tests can determine whether or not the optimizer is
** correctly optimizing out sorts.
*/
case OP_SorterSort:    /* jump */
#ifdef SQLITE_OMIT_MERGE_SORT
  pOp->opcode = OP_Sort;
#endif
case OP_Sort: {        /* jump */
#ifdef SQLITE_TEST
  sqlite3_sort_count++;
  sqlite3_search_count--;
#endif
  p->aCounter[SQLITE_STMTSTATUS_SORT-1]++;
  /* Fall through into OP_Rewind */
}
/* Opcode: Rewind P1 P2 * * *
**
** The next use of the Rowid or Column or Next instruction for P1 
** will refer to the first entry in the database table or index.
** If the table or index is empty and P2>0, then jump immediately to P2.
** If P2 is 0 or if the table or index is not empty, fall through
** to the following instruction.
*/
case OP_Rewind: {        /* jump */
#if 0  /* local variables moved into u.bo */
  VdbeCursor *pC;
  BtCursor *pCrsr;
  int res;
#endif /* local variables moved into u.bo */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bo.pC = p->apCsr[pOp->p1];
  assert( u.bo.pC!=0 );
  assert( u.bo.pC->isSorter==(pOp->opcode==OP_SorterSort) );
  u.bo.res = 1;
  if( isSorter(u.bo.pC) ){
    rc = sqlite3VdbeSorterRewind(db, u.bo.pC, &u.bo.res);
  }else{
    u.bo.pCrsr = u.bo.pC->pCursor;
    assert( u.bo.pCrsr );
    rc = sqlite3BtreeFirst(u.bo.pCrsr, &u.bo.res);
    u.bo.pC->atFirst = u.bo.res==0 ?1:0;
    u.bo.pC->deferredMoveto = 0;
    u.bo.pC->cacheStatus = CACHE_STALE;
    u.bo.pC->rowidIsValid = 0;
  }
  u.bo.pC->nullRow = (u8)u.bo.res;
  assert( pOp->p2>0 && pOp->p2<p->nOp );
  if( u.bo.res ){
    pc = pOp->p2 - 1;
  }
  break;
}

/* Opcode: Next P1 P2 * P4 P5
**
** Advance cursor P1 so that it points to the next key/data pair in its
** table or index.  If there are no more key/value pairs then fall through
** to the following instruction.  But if the cursor advance was successful,
** jump immediately to P2.
**
** The P1 cursor must be for a real table, not a pseudo-table.
**
** P4 is always of type P4_ADVANCE. The function pointer points to
** sqlite3BtreeNext().
**
** If P5 is positive and the jump is taken, then event counter
** number P5-1 in the prepared statement is incremented.
**
** See also: Prev
*/
/* Opcode: Prev P1 P2 * * P5
**
** Back up cursor P1 so that it points to the previous key/data pair in its
** table or index.  If there is no previous key/value pairs then fall through
** to the following instruction.  But if the cursor backup was successful,
** jump immediately to P2.
**
** The P1 cursor must be for a real table, not a pseudo-table.
**
** P4 is always of type P4_ADVANCE. The function pointer points to
** sqlite3BtreePrevious().
**
** If P5 is positive and the jump is taken, then event counter
** number P5-1 in the prepared statement is incremented.
*/
case OP_SorterNext:    /* jump */
#ifdef SQLITE_OMIT_MERGE_SORT
  pOp->opcode = OP_Next;
#endif
case OP_Prev:          /* jump */
case OP_Next: {        /* jump */
#if 0  /* local variables moved into u.bp */
  VdbeCursor *pC;

  int res;
#endif /* local variables moved into u.bp */

  CHECK_FOR_INTERRUPT;
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( pOp->p5<=ArraySize(p->aCounter) );
  u.bp.pC = p->apCsr[pOp->p1];
  if( u.bp.pC==0 ){
    break;  /* See ticket #2273 */
  }
  assert( u.bp.pC->isSorter==(pOp->opcode==OP_SorterNext) );
  if( isSorter(u.bp.pC) ){
    assert( pOp->opcode==OP_SorterNext );
    rc = sqlite3VdbeSorterNext(db, u.bp.pC, &u.bp.res);
  }else{

    u.bp.res = 1;
    assert( u.bp.pC->deferredMoveto==0 );
    assert( u.bp.pC->pCursor );
    assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
    assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
    rc = pOp->p4.xAdvance(u.bp.pC->pCursor, &u.bp.res);
  }
  u.bp.pC->nullRow = (u8)u.bp.res;
  u.bp.pC->cacheStatus = CACHE_STALE;
  if( u.bp.res==0 ){
    pc = pOp->p2 - 1;
    if( pOp->p5 ) p->aCounter[pOp->p5-1]++;
#ifdef SQLITE_TEST
    sqlite3_search_count++;
#endif
  }
  u.bp.pC->rowidIsValid = 0;
  break;
}

/* Opcode: IdxInsert P1 P2 P3 * P5
**
** Register P2 holds an SQL index key made using the
** MakeRecord instructions.  This opcode writes that key
** into the index P1.  Data for the entry is nil.
**
** P3 is a flag that provides a hint to the b-tree layer that this
** insert is likely to be an append.
**
** This instruction only works for indices.  The equivalent instruction
** for tables is OP_Insert.
*/
case OP_SorterInsert:       /* in2 */
#ifdef SQLITE_OMIT_MERGE_SORT
  pOp->opcode = OP_IdxInsert;
#endif
case OP_IdxInsert: {        /* in2 */
#if 0  /* local variables moved into u.bq */
  VdbeCursor *pC;
  BtCursor *pCrsr;
  int nKey;
  const char *zKey;
#endif /* local variables moved into u.bq */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bq.pC = p->apCsr[pOp->p1];
  assert( u.bq.pC!=0 );
  assert( u.bq.pC->isSorter==(pOp->opcode==OP_SorterInsert) );
  pIn2 = &aMem[pOp->p2];
  assert( pIn2->flags & MEM_Blob );
  u.bq.pCrsr = u.bq.pC->pCursor;
  if( ALWAYS(u.bq.pCrsr!=0) ){
    assert( u.bq.pC->isTable==0 );
    rc = ExpandBlob(pIn2);
    if( rc==SQLITE_OK ){
      if( isSorter(u.bq.pC) ){
        rc = sqlite3VdbeSorterWrite(db, u.bq.pC, pIn2);
      }else{
        u.bq.nKey = pIn2->n;
        u.bq.zKey = pIn2->z;
        rc = sqlite3BtreeInsert(u.bq.pCrsr, u.bq.zKey, u.bq.nKey, "", 0, 0, pOp->p3,
            ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bq.pC->seekResult : 0)
            );
        assert( u.bq.pC->deferredMoveto==0 );
        u.bq.pC->cacheStatus = CACHE_STALE;
      }
    }
  }
  break;
}

/* Opcode: IdxDelete P1 P2 P3 * *
**
** The content of P3 registers starting at register P2 form
** an unpacked index key. This opcode removes that entry from the 
** index opened by cursor P1.
*/
case OP_IdxDelete: {
#if 0  /* local variables moved into u.br */
  VdbeCursor *pC;
  BtCursor *pCrsr;
  int res;
  UnpackedRecord r;
#endif /* local variables moved into u.br */

  assert( pOp->p3>0 );
  assert( pOp->p2>0 && pOp->p2+pOp->p3<=p->nMem+1 );
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.br.pC = p->apCsr[pOp->p1];
  assert( u.br.pC!=0 );
  u.br.pCrsr = u.br.pC->pCursor;
  if( ALWAYS(u.br.pCrsr!=0) ){
    u.br.r.pKeyInfo = u.br.pC->pKeyInfo;
    u.br.r.nField = (u16)pOp->p3;
    u.br.r.flags = 0;
    u.br.r.aMem = &aMem[pOp->p2];
#ifdef SQLITE_DEBUG
    { int i; for(i=0; i<u.br.r.nField; i++) assert( memIsValid(&u.br.r.aMem[i]) ); }
#endif
    rc = sqlite3BtreeMovetoUnpacked(u.br.pCrsr, &u.br.r, 0, 0, &u.br.res);
    if( rc==SQLITE_OK && u.br.res==0 ){
      rc = sqlite3BtreeDelete(u.br.pCrsr);
    }
    assert( u.br.pC->deferredMoveto==0 );
    u.br.pC->cacheStatus = CACHE_STALE;
  }
  break;
}

/* Opcode: IdxRowid P1 P2 * * *
**
** Write into register P2 an integer which is the last entry in the record at
** the end of the index key pointed to by cursor P1.  This integer should be
** the rowid of the table entry to which this index entry points.
**
** See also: Rowid, MakeRecord.
*/
case OP_IdxRowid: {              /* out2-prerelease */
#if 0  /* local variables moved into u.bs */
  BtCursor *pCrsr;
  VdbeCursor *pC;
  i64 rowid;
#endif /* local variables moved into u.bs */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bs.pC = p->apCsr[pOp->p1];
  assert( u.bs.pC!=0 );
  u.bs.pCrsr = u.bs.pC->pCursor;
  pOut->flags = MEM_Null;
  if( ALWAYS(u.bs.pCrsr!=0) ){
    rc = sqlite3VdbeCursorMoveto(u.bs.pC);
    if( NEVER(rc) ) goto abort_due_to_error;
    assert( u.bs.pC->deferredMoveto==0 );
    assert( u.bs.pC->isTable==0 );
    if( !u.bs.pC->nullRow ){
      rc = sqlite3VdbeIdxRowid(db, u.bs.pCrsr, &u.bs.rowid);
      if( rc!=SQLITE_OK ){
        goto abort_due_to_error;
      }
      pOut->u.i = u.bs.rowid;
      pOut->flags = MEM_Int;
    }
  }
  break;
}

/* Opcode: IdxGE P1 P2 P3 P4 P5







|




|






|
<
|
|
|
|
|
<
|
|
|






|
|


|
|
|

|


|

|

|



|


|

|
|

|
















|




|


|
|
|
|


|
|

|
|
|
|
|
|


|
|

|
|

|



|










|

|


|
|
|
|
<
|
|













|



|


|
|
|
|
|

|

|
|
|
|
|


















<
<
<
<

















|



|


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

|

|





|








<
<
<














<
<
<



<
<
<
<


|

>

|




|
|


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






|















<
<
<
<

|




|


|
|
<


|
|
|


<
<
<
|
|
|
|
|
|
|
<












|




|




|
|
|
|
|
|
|
|

|

|
|
|

|
|













|



|


|
|
|

|
|

|
|
|
|



|







66872
66873
66874
66875
66876
66877
66878
66879
66880
66881
66882
66883
66884
66885
66886
66887
66888
66889
66890
66891

66892
66893
66894
66895
66896

66897
66898
66899
66900
66901
66902
66903
66904
66905
66906
66907
66908
66909
66910
66911
66912
66913
66914
66915
66916
66917
66918
66919
66920
66921
66922
66923
66924
66925
66926
66927
66928
66929
66930
66931
66932
66933
66934
66935
66936
66937
66938
66939
66940
66941
66942
66943
66944
66945
66946
66947
66948
66949
66950
66951
66952
66953
66954
66955
66956
66957
66958
66959
66960
66961
66962
66963
66964
66965
66966
66967
66968
66969
66970
66971
66972
66973
66974
66975
66976
66977
66978
66979
66980
66981
66982
66983
66984
66985
66986
66987
66988
66989
66990
66991
66992
66993
66994
66995
66996
66997
66998
66999
67000
67001
67002
67003
67004

67005
67006
67007
67008
67009
67010
67011
67012
67013
67014
67015
67016
67017
67018
67019
67020
67021
67022
67023
67024
67025
67026
67027
67028
67029
67030
67031
67032
67033
67034
67035
67036
67037
67038
67039
67040
67041
67042
67043
67044
67045
67046
67047
67048
67049
67050
67051
67052
67053
67054
67055
67056
67057




67058
67059
67060
67061
67062
67063
67064
67065
67066
67067
67068
67069
67070
67071
67072
67073
67074
67075
67076
67077
67078
67079
67080
67081
67082
67083

67084



67085

67086
67087
67088
67089
67090
67091
67092
67093
67094
67095
67096
67097
67098
67099
67100
67101
67102
67103
67104
67105
67106
67107
67108



67109
67110
67111
67112
67113
67114
67115
67116
67117
67118
67119
67120
67121
67122



67123
67124
67125




67126
67127
67128
67129
67130
67131
67132
67133
67134
67135
67136
67137
67138
67139
67140
67141
67142
67143

67144
67145
67146
67147

67148
67149


67150
67151
67152
67153
67154
67155
67156
67157
67158
67159
67160
67161
67162
67163
67164
67165
67166
67167
67168
67169
67170
67171
67172
67173
67174




67175
67176
67177
67178
67179
67180
67181
67182
67183
67184
67185

67186
67187
67188
67189
67190
67191
67192



67193
67194
67195
67196
67197
67198
67199

67200
67201
67202
67203
67204
67205
67206
67207
67208
67209
67210
67211
67212
67213
67214
67215
67216
67217
67218
67219
67220
67221
67222
67223
67224
67225
67226
67227
67228
67229
67230
67231
67232
67233
67234
67235
67236
67237
67238
67239
67240
67241
67242
67243
67244
67245
67246
67247
67248
67249
67250
67251
67252
67253
67254
67255
67256
67257
67258
67259
67260
67261
67262
67263
67264
67265
67266
67267
67268
67269
67270
67271
67272
67273
67274
67275
67276
67277
67278
67279
67280
** it is found in the database file.
**
** If the P1 cursor must be pointing to a valid row (not a NULL row)
** of a real table, not a pseudo-table.
*/
case OP_RowKey:
case OP_RowData: {
#if 0  /* local variables moved into u.bh */
  VdbeCursor *pC;
  BtCursor *pCrsr;
  u32 n;
  i64 n64;
#endif /* local variables moved into u.bh */

  pOut = &aMem[pOp->p2];
  memAboutToChange(p, pOut);

  /* Note that RowKey and RowData are really exactly the same instruction */
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bh.pC = p->apCsr[pOp->p1];

  assert( u.bh.pC->isTable || pOp->opcode==OP_RowKey );
  assert( u.bh.pC->isIndex || pOp->opcode==OP_RowData );
  assert( u.bh.pC!=0 );
  assert( u.bh.pC->nullRow==0 );
  assert( u.bh.pC->pseudoTableReg==0 );

  assert( u.bh.pC->pCursor!=0 );
  u.bh.pCrsr = u.bh.pC->pCursor;
  assert( sqlite3BtreeCursorIsValid(u.bh.pCrsr) );

  /* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists or
  ** OP_Rewind/Op_Next with no intervening instructions that might invalidate
  ** the cursor.  Hence the following sqlite3VdbeCursorMoveto() call is always
  ** a no-op and can never fail.  But we leave it in place as a safety.
  */
  assert( u.bh.pC->deferredMoveto==0 );
  rc = sqlite3VdbeCursorMoveto(u.bh.pC);
  if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;

  if( u.bh.pC->isIndex ){
    assert( !u.bh.pC->isTable );
    rc = sqlite3BtreeKeySize(u.bh.pCrsr, &u.bh.n64);
    assert( rc==SQLITE_OK );    /* True because of CursorMoveto() call above */
    if( u.bh.n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){
      goto too_big;
    }
    u.bh.n = (u32)u.bh.n64;
  }else{
    rc = sqlite3BtreeDataSize(u.bh.pCrsr, &u.bh.n);
    assert( rc==SQLITE_OK );    /* DataSize() cannot fail */
    if( u.bh.n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
      goto too_big;
    }
  }
  if( sqlite3VdbeMemGrow(pOut, u.bh.n, 0) ){
    goto no_mem;
  }
  pOut->n = u.bh.n;
  MemSetTypeFlag(pOut, MEM_Blob);
  if( u.bh.pC->isIndex ){
    rc = sqlite3BtreeKey(u.bh.pCrsr, 0, u.bh.n, pOut->z);
  }else{
    rc = sqlite3BtreeData(u.bh.pCrsr, 0, u.bh.n, pOut->z);
  }
  pOut->enc = SQLITE_UTF8;  /* In case the blob is ever cast to text */
  UPDATE_MAX_BLOBSIZE(pOut);
  break;
}

/* Opcode: Rowid P1 P2 * * *
**
** Store in register P2 an integer which is the key of the table entry that
** P1 is currently point to.
**
** P1 can be either an ordinary table or a virtual table.  There used to
** be a separate OP_VRowid opcode for use with virtual tables, but this
** one opcode now works for both table types.
*/
case OP_Rowid: {                 /* out2-prerelease */
#if 0  /* local variables moved into u.bi */
  VdbeCursor *pC;
  i64 v;
  sqlite3_vtab *pVtab;
  const sqlite3_module *pModule;
#endif /* local variables moved into u.bi */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bi.pC = p->apCsr[pOp->p1];
  assert( u.bi.pC!=0 );
  assert( u.bi.pC->pseudoTableReg==0 );
  if( u.bi.pC->nullRow ){
    pOut->flags = MEM_Null;
    break;
  }else if( u.bi.pC->deferredMoveto ){
    u.bi.v = u.bi.pC->movetoTarget;
#ifndef SQLITE_OMIT_VIRTUALTABLE
  }else if( u.bi.pC->pVtabCursor ){
    u.bi.pVtab = u.bi.pC->pVtabCursor->pVtab;
    u.bi.pModule = u.bi.pVtab->pModule;
    assert( u.bi.pModule->xRowid );
    rc = u.bi.pModule->xRowid(u.bi.pC->pVtabCursor, &u.bi.v);
    importVtabErrMsg(p, u.bi.pVtab);
#endif /* SQLITE_OMIT_VIRTUALTABLE */
  }else{
    assert( u.bi.pC->pCursor!=0 );
    rc = sqlite3VdbeCursorMoveto(u.bi.pC);
    if( rc ) goto abort_due_to_error;
    if( u.bi.pC->rowidIsValid ){
      u.bi.v = u.bi.pC->lastRowid;
    }else{
      rc = sqlite3BtreeKeySize(u.bi.pC->pCursor, &u.bi.v);
      assert( rc==SQLITE_OK );  /* Always so because of CursorMoveto() above */
    }
  }
  pOut->u.i = u.bi.v;
  break;
}

/* Opcode: NullRow P1 * * * *
**
** Move the cursor P1 to a null row.  Any OP_Column operations
** that occur while the cursor is on the null row will always
** write a NULL.
*/
case OP_NullRow: {
#if 0  /* local variables moved into u.bj */
  VdbeCursor *pC;
#endif /* local variables moved into u.bj */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bj.pC = p->apCsr[pOp->p1];
  assert( u.bj.pC!=0 );
  u.bj.pC->nullRow = 1;
  u.bj.pC->rowidIsValid = 0;

  if( u.bj.pC->pCursor ){
    sqlite3BtreeClearCursor(u.bj.pC->pCursor);
  }
  break;
}

/* Opcode: Last P1 P2 * * *
**
** The next use of the Rowid or Column or Next instruction for P1 
** will refer to the last entry in the database table or index.
** If the table or index is empty and P2>0, then jump immediately to P2.
** If P2 is 0 or if the table or index is not empty, fall through
** to the following instruction.
*/
case OP_Last: {        /* jump */
#if 0  /* local variables moved into u.bk */
  VdbeCursor *pC;
  BtCursor *pCrsr;
  int res;
#endif /* local variables moved into u.bk */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bk.pC = p->apCsr[pOp->p1];
  assert( u.bk.pC!=0 );
  u.bk.pCrsr = u.bk.pC->pCursor;
  if( u.bk.pCrsr==0 ){
    u.bk.res = 1;
  }else{
    rc = sqlite3BtreeLast(u.bk.pCrsr, &u.bk.res);
  }
  u.bk.pC->nullRow = (u8)u.bk.res;
  u.bk.pC->deferredMoveto = 0;
  u.bk.pC->rowidIsValid = 0;
  u.bk.pC->cacheStatus = CACHE_STALE;
  if( pOp->p2>0 && u.bk.res ){
    pc = pOp->p2 - 1;
  }
  break;
}


/* Opcode: Sort P1 P2 * * *
**
** This opcode does exactly the same thing as OP_Rewind except that
** it increments an undocumented global variable used for testing.
**
** Sorting is accomplished by writing records into a sorting index,
** then rewinding that index and playing it back from beginning to
** end.  We use the OP_Sort opcode instead of OP_Rewind to do the
** rewinding so that the global variable will be incremented and
** regression tests can determine whether or not the optimizer is
** correctly optimizing out sorts.
*/




case OP_Sort: {        /* jump */
#ifdef SQLITE_TEST
  sqlite3_sort_count++;
  sqlite3_search_count--;
#endif
  p->aCounter[SQLITE_STMTSTATUS_SORT-1]++;
  /* Fall through into OP_Rewind */
}
/* Opcode: Rewind P1 P2 * * *
**
** The next use of the Rowid or Column or Next instruction for P1 
** will refer to the first entry in the database table or index.
** If the table or index is empty and P2>0, then jump immediately to P2.
** If P2 is 0 or if the table or index is not empty, fall through
** to the following instruction.
*/
case OP_Rewind: {        /* jump */
#if 0  /* local variables moved into u.bl */
  VdbeCursor *pC;
  BtCursor *pCrsr;
  int res;
#endif /* local variables moved into u.bl */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bl.pC = p->apCsr[pOp->p1];
  assert( u.bl.pC!=0 );

  u.bl.res = 1;



  if( (u.bl.pCrsr = u.bl.pC->pCursor)!=0 ){

    rc = sqlite3BtreeFirst(u.bl.pCrsr, &u.bl.res);
    u.bl.pC->atFirst = u.bl.res==0 ?1:0;
    u.bl.pC->deferredMoveto = 0;
    u.bl.pC->cacheStatus = CACHE_STALE;
    u.bl.pC->rowidIsValid = 0;
  }
  u.bl.pC->nullRow = (u8)u.bl.res;
  assert( pOp->p2>0 && pOp->p2<p->nOp );
  if( u.bl.res ){
    pc = pOp->p2 - 1;
  }
  break;
}

/* Opcode: Next P1 P2 * * P5
**
** Advance cursor P1 so that it points to the next key/data pair in its
** table or index.  If there are no more key/value pairs then fall through
** to the following instruction.  But if the cursor advance was successful,
** jump immediately to P2.
**
** The P1 cursor must be for a real table, not a pseudo-table.
**



** If P5 is positive and the jump is taken, then event counter
** number P5-1 in the prepared statement is incremented.
**
** See also: Prev
*/
/* Opcode: Prev P1 P2 * * P5
**
** Back up cursor P1 so that it points to the previous key/data pair in its
** table or index.  If there is no previous key/value pairs then fall through
** to the following instruction.  But if the cursor backup was successful,
** jump immediately to P2.
**
** The P1 cursor must be for a real table, not a pseudo-table.
**



** If P5 is positive and the jump is taken, then event counter
** number P5-1 in the prepared statement is incremented.
*/




case OP_Prev:          /* jump */
case OP_Next: {        /* jump */
#if 0  /* local variables moved into u.bm */
  VdbeCursor *pC;
  BtCursor *pCrsr;
  int res;
#endif /* local variables moved into u.bm */

  CHECK_FOR_INTERRUPT;
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( pOp->p5<=ArraySize(p->aCounter) );
  u.bm.pC = p->apCsr[pOp->p1];
  if( u.bm.pC==0 ){
    break;  /* See ticket #2273 */
  }
  u.bm.pCrsr = u.bm.pC->pCursor;
  if( u.bm.pCrsr==0 ){
    u.bm.pC->nullRow = 1;

    break;
  }
  u.bm.res = 1;
  assert( u.bm.pC->deferredMoveto==0 );

  rc = pOp->opcode==OP_Next ? sqlite3BtreeNext(u.bm.pCrsr, &u.bm.res) :
                              sqlite3BtreePrevious(u.bm.pCrsr, &u.bm.res);


  u.bm.pC->nullRow = (u8)u.bm.res;
  u.bm.pC->cacheStatus = CACHE_STALE;
  if( u.bm.res==0 ){
    pc = pOp->p2 - 1;
    if( pOp->p5 ) p->aCounter[pOp->p5-1]++;
#ifdef SQLITE_TEST
    sqlite3_search_count++;
#endif
  }
  u.bm.pC->rowidIsValid = 0;
  break;
}

/* Opcode: IdxInsert P1 P2 P3 * P5
**
** Register P2 holds an SQL index key made using the
** MakeRecord instructions.  This opcode writes that key
** into the index P1.  Data for the entry is nil.
**
** P3 is a flag that provides a hint to the b-tree layer that this
** insert is likely to be an append.
**
** This instruction only works for indices.  The equivalent instruction
** for tables is OP_Insert.
*/




case OP_IdxInsert: {        /* in2 */
#if 0  /* local variables moved into u.bn */
  VdbeCursor *pC;
  BtCursor *pCrsr;
  int nKey;
  const char *zKey;
#endif /* local variables moved into u.bn */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bn.pC = p->apCsr[pOp->p1];
  assert( u.bn.pC!=0 );

  pIn2 = &aMem[pOp->p2];
  assert( pIn2->flags & MEM_Blob );
  u.bn.pCrsr = u.bn.pC->pCursor;
  if( ALWAYS(u.bn.pCrsr!=0) ){
    assert( u.bn.pC->isTable==0 );
    rc = ExpandBlob(pIn2);
    if( rc==SQLITE_OK ){



      u.bn.nKey = pIn2->n;
      u.bn.zKey = pIn2->z;
      rc = sqlite3BtreeInsert(u.bn.pCrsr, u.bn.zKey, u.bn.nKey, "", 0, 0, pOp->p3,
          ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bn.pC->seekResult : 0)
      );
      assert( u.bn.pC->deferredMoveto==0 );
      u.bn.pC->cacheStatus = CACHE_STALE;

    }
  }
  break;
}

/* Opcode: IdxDelete P1 P2 P3 * *
**
** The content of P3 registers starting at register P2 form
** an unpacked index key. This opcode removes that entry from the 
** index opened by cursor P1.
*/
case OP_IdxDelete: {
#if 0  /* local variables moved into u.bo */
  VdbeCursor *pC;
  BtCursor *pCrsr;
  int res;
  UnpackedRecord r;
#endif /* local variables moved into u.bo */

  assert( pOp->p3>0 );
  assert( pOp->p2>0 && pOp->p2+pOp->p3<=p->nMem+1 );
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bo.pC = p->apCsr[pOp->p1];
  assert( u.bo.pC!=0 );
  u.bo.pCrsr = u.bo.pC->pCursor;
  if( ALWAYS(u.bo.pCrsr!=0) ){
    u.bo.r.pKeyInfo = u.bo.pC->pKeyInfo;
    u.bo.r.nField = (u16)pOp->p3;
    u.bo.r.flags = 0;
    u.bo.r.aMem = &aMem[pOp->p2];
#ifdef SQLITE_DEBUG
    { int i; for(i=0; i<u.bo.r.nField; i++) assert( memIsValid(&u.bo.r.aMem[i]) ); }
#endif
    rc = sqlite3BtreeMovetoUnpacked(u.bo.pCrsr, &u.bo.r, 0, 0, &u.bo.res);
    if( rc==SQLITE_OK && u.bo.res==0 ){
      rc = sqlite3BtreeDelete(u.bo.pCrsr);
    }
    assert( u.bo.pC->deferredMoveto==0 );
    u.bo.pC->cacheStatus = CACHE_STALE;
  }
  break;
}

/* Opcode: IdxRowid P1 P2 * * *
**
** Write into register P2 an integer which is the last entry in the record at
** the end of the index key pointed to by cursor P1.  This integer should be
** the rowid of the table entry to which this index entry points.
**
** See also: Rowid, MakeRecord.
*/
case OP_IdxRowid: {              /* out2-prerelease */
#if 0  /* local variables moved into u.bp */
  BtCursor *pCrsr;
  VdbeCursor *pC;
  i64 rowid;
#endif /* local variables moved into u.bp */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bp.pC = p->apCsr[pOp->p1];
  assert( u.bp.pC!=0 );
  u.bp.pCrsr = u.bp.pC->pCursor;
  pOut->flags = MEM_Null;
  if( ALWAYS(u.bp.pCrsr!=0) ){
    rc = sqlite3VdbeCursorMoveto(u.bp.pC);
    if( NEVER(rc) ) goto abort_due_to_error;
    assert( u.bp.pC->deferredMoveto==0 );
    assert( u.bp.pC->isTable==0 );
    if( !u.bp.pC->nullRow ){
      rc = sqlite3VdbeIdxRowid(db, u.bp.pCrsr, &u.bp.rowid);
      if( rc!=SQLITE_OK ){
        goto abort_due_to_error;
      }
      pOut->u.i = u.bp.rowid;
      pOut->flags = MEM_Int;
    }
  }
  break;
}

/* Opcode: IdxGE P1 P2 P3 P4 P5
68198
68199
68200
68201
68202
68203
68204
68205
68206
68207
68208
68209
68210
68211
68212
68213
68214
68215
68216
68217
68218
68219
68220
68221
68222
68223
68224
68225
68226
68227
68228
68229
68230
68231
68232
68233
68234
68235
68236
68237
68238
68239
68240
68241
68242
68243
68244
** Otherwise fall through to the next instruction.
**
** If P5 is non-zero then the key value is increased by an epsilon prior 
** to the comparison.  This makes the opcode work like IdxLE.
*/
case OP_IdxLT:          /* jump */
case OP_IdxGE: {        /* jump */
#if 0  /* local variables moved into u.bt */
  VdbeCursor *pC;
  int res;
  UnpackedRecord r;
#endif /* local variables moved into u.bt */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bt.pC = p->apCsr[pOp->p1];
  assert( u.bt.pC!=0 );
  assert( u.bt.pC->isOrdered );
  if( ALWAYS(u.bt.pC->pCursor!=0) ){
    assert( u.bt.pC->deferredMoveto==0 );
    assert( pOp->p5==0 || pOp->p5==1 );
    assert( pOp->p4type==P4_INT32 );
    u.bt.r.pKeyInfo = u.bt.pC->pKeyInfo;
    u.bt.r.nField = (u16)pOp->p4.i;
    if( pOp->p5 ){
      u.bt.r.flags = UNPACKED_INCRKEY | UNPACKED_IGNORE_ROWID;
    }else{
      u.bt.r.flags = UNPACKED_IGNORE_ROWID;
    }
    u.bt.r.aMem = &aMem[pOp->p3];
#ifdef SQLITE_DEBUG
    { int i; for(i=0; i<u.bt.r.nField; i++) assert( memIsValid(&u.bt.r.aMem[i]) ); }
#endif
    rc = sqlite3VdbeIdxKeyCompare(u.bt.pC, &u.bt.r, &u.bt.res);
    if( pOp->opcode==OP_IdxLT ){
      u.bt.res = -u.bt.res;
    }else{
      assert( pOp->opcode==OP_IdxGE );
      u.bt.res++;
    }
    if( u.bt.res>0 ){
      pc = pOp->p2 - 1 ;
    }
  }
  break;
}

/* Opcode: Destroy P1 P2 P3 * *







|



|


|
|
|
|
|


|
|

|

|

|

|

|

|


|

|







67301
67302
67303
67304
67305
67306
67307
67308
67309
67310
67311
67312
67313
67314
67315
67316
67317
67318
67319
67320
67321
67322
67323
67324
67325
67326
67327
67328
67329
67330
67331
67332
67333
67334
67335
67336
67337
67338
67339
67340
67341
67342
67343
67344
67345
67346
67347
** Otherwise fall through to the next instruction.
**
** If P5 is non-zero then the key value is increased by an epsilon prior 
** to the comparison.  This makes the opcode work like IdxLE.
*/
case OP_IdxLT:          /* jump */
case OP_IdxGE: {        /* jump */
#if 0  /* local variables moved into u.bq */
  VdbeCursor *pC;
  int res;
  UnpackedRecord r;
#endif /* local variables moved into u.bq */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bq.pC = p->apCsr[pOp->p1];
  assert( u.bq.pC!=0 );
  assert( u.bq.pC->isOrdered );
  if( ALWAYS(u.bq.pC->pCursor!=0) ){
    assert( u.bq.pC->deferredMoveto==0 );
    assert( pOp->p5==0 || pOp->p5==1 );
    assert( pOp->p4type==P4_INT32 );
    u.bq.r.pKeyInfo = u.bq.pC->pKeyInfo;
    u.bq.r.nField = (u16)pOp->p4.i;
    if( pOp->p5 ){
      u.bq.r.flags = UNPACKED_INCRKEY | UNPACKED_IGNORE_ROWID;
    }else{
      u.bq.r.flags = UNPACKED_IGNORE_ROWID;
    }
    u.bq.r.aMem = &aMem[pOp->p3];
#ifdef SQLITE_DEBUG
    { int i; for(i=0; i<u.bq.r.nField; i++) assert( memIsValid(&u.bq.r.aMem[i]) ); }
#endif
    rc = sqlite3VdbeIdxKeyCompare(u.bq.pC, &u.bq.r, &u.bq.res);
    if( pOp->opcode==OP_IdxLT ){
      u.bq.res = -u.bq.res;
    }else{
      assert( pOp->opcode==OP_IdxGE );
      u.bq.res++;
    }
    if( u.bq.res>0 ){
      pc = pOp->p2 - 1 ;
    }
  }
  break;
}

/* Opcode: Destroy P1 P2 P3 * *
68258
68259
68260
68261
68262
68263
68264
68265
68266
68267
68268
68269
68270
68271
68272
68273
68274
68275
68276
68277
68278
68279
68280
68281
68282
68283
68284
68285
68286
68287
68288
68289
68290
68291
68292
68293
68294
68295
68296
68297
68298
68299
68300
68301
68302
68303
68304
** movement was required (because the table being dropped was already 
** the last one in the database) then a zero is stored in register P2.
** If AUTOVACUUM is disabled then a zero is stored in register P2.
**
** See also: Clear
*/
case OP_Destroy: {     /* out2-prerelease */
#if 0  /* local variables moved into u.bu */
  int iMoved;
  int iCnt;
  Vdbe *pVdbe;
  int iDb;
#endif /* local variables moved into u.bu */
#ifndef SQLITE_OMIT_VIRTUALTABLE
  u.bu.iCnt = 0;
  for(u.bu.pVdbe=db->pVdbe; u.bu.pVdbe; u.bu.pVdbe = u.bu.pVdbe->pNext){
    if( u.bu.pVdbe->magic==VDBE_MAGIC_RUN && u.bu.pVdbe->inVtabMethod<2 && u.bu.pVdbe->pc>=0 ){
      u.bu.iCnt++;
    }
  }
#else
  u.bu.iCnt = db->activeVdbeCnt;
#endif
  pOut->flags = MEM_Null;
  if( u.bu.iCnt>1 ){
    rc = SQLITE_LOCKED;
    p->errorAction = OE_Abort;
  }else{
    u.bu.iDb = pOp->p3;
    assert( u.bu.iCnt==1 );
    assert( (p->btreeMask & (((yDbMask)1)<<u.bu.iDb))!=0 );
    rc = sqlite3BtreeDropTable(db->aDb[u.bu.iDb].pBt, pOp->p1, &u.bu.iMoved);
    pOut->flags = MEM_Int;
    pOut->u.i = u.bu.iMoved;
#ifndef SQLITE_OMIT_AUTOVACUUM
    if( rc==SQLITE_OK && u.bu.iMoved!=0 ){
      sqlite3RootPageMoved(db, u.bu.iDb, u.bu.iMoved, pOp->p1);
      /* All OP_Destroy operations occur on the same btree */
      assert( resetSchemaOnFault==0 || resetSchemaOnFault==u.bu.iDb+1 );
      resetSchemaOnFault = u.bu.iDb+1;
    }
#endif
  }
  break;
}

/* Opcode: Clear P1 P2 P3







|




|

|
|
|
|



|


|



|
|
|
|

|

|
|

|
|







67361
67362
67363
67364
67365
67366
67367
67368
67369
67370
67371
67372
67373
67374
67375
67376
67377
67378
67379
67380
67381
67382
67383
67384
67385
67386
67387
67388
67389
67390
67391
67392
67393
67394
67395
67396
67397
67398
67399
67400
67401
67402
67403
67404
67405
67406
67407
** movement was required (because the table being dropped was already 
** the last one in the database) then a zero is stored in register P2.
** If AUTOVACUUM is disabled then a zero is stored in register P2.
**
** See also: Clear
*/
case OP_Destroy: {     /* out2-prerelease */
#if 0  /* local variables moved into u.br */
  int iMoved;
  int iCnt;
  Vdbe *pVdbe;
  int iDb;
#endif /* local variables moved into u.br */
#ifndef SQLITE_OMIT_VIRTUALTABLE
  u.br.iCnt = 0;
  for(u.br.pVdbe=db->pVdbe; u.br.pVdbe; u.br.pVdbe = u.br.pVdbe->pNext){
    if( u.br.pVdbe->magic==VDBE_MAGIC_RUN && u.br.pVdbe->inVtabMethod<2 && u.br.pVdbe->pc>=0 ){
      u.br.iCnt++;
    }
  }
#else
  u.br.iCnt = db->activeVdbeCnt;
#endif
  pOut->flags = MEM_Null;
  if( u.br.iCnt>1 ){
    rc = SQLITE_LOCKED;
    p->errorAction = OE_Abort;
  }else{
    u.br.iDb = pOp->p3;
    assert( u.br.iCnt==1 );
    assert( (p->btreeMask & (((yDbMask)1)<<u.br.iDb))!=0 );
    rc = sqlite3BtreeDropTable(db->aDb[u.br.iDb].pBt, pOp->p1, &u.br.iMoved);
    pOut->flags = MEM_Int;
    pOut->u.i = u.br.iMoved;
#ifndef SQLITE_OMIT_AUTOVACUUM
    if( rc==SQLITE_OK && u.br.iMoved!=0 ){
      sqlite3RootPageMoved(db, u.br.iDb, u.br.iMoved, pOp->p1);
      /* All OP_Destroy operations occur on the same btree */
      assert( resetSchemaOnFault==0 || resetSchemaOnFault==u.br.iDb+1 );
      resetSchemaOnFault = u.br.iDb+1;
    }
#endif
  }
  break;
}

/* Opcode: Clear P1 P2 P3
68316
68317
68318
68319
68320
68321
68322
68323
68324
68325
68326
68327
68328
68329
68330
68331
68332
68333
68334
68335
68336
68337
68338
68339
68340
68341
68342
68343
68344
** count is incremented by the number of rows in the table being cleared. 
** If P3 is greater than zero, then the value stored in register P3 is
** also incremented by the number of rows in the table being cleared.
**
** See also: Destroy
*/
case OP_Clear: {
#if 0  /* local variables moved into u.bv */
  int nChange;
#endif /* local variables moved into u.bv */

  u.bv.nChange = 0;
  assert( (p->btreeMask & (((yDbMask)1)<<pOp->p2))!=0 );
  rc = sqlite3BtreeClearTable(
      db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &u.bv.nChange : 0)
  );
  if( pOp->p3 ){
    p->nChange += u.bv.nChange;
    if( pOp->p3>0 ){
      assert( memIsValid(&aMem[pOp->p3]) );
      memAboutToChange(p, &aMem[pOp->p3]);
      aMem[pOp->p3].u.i += u.bv.nChange;
    }
  }
  break;
}

/* Opcode: CreateTable P1 P2 * * *
**







|

|

|


|


|



|







67419
67420
67421
67422
67423
67424
67425
67426
67427
67428
67429
67430
67431
67432
67433
67434
67435
67436
67437
67438
67439
67440
67441
67442
67443
67444
67445
67446
67447
** count is incremented by the number of rows in the table being cleared. 
** If P3 is greater than zero, then the value stored in register P3 is
** also incremented by the number of rows in the table being cleared.
**
** See also: Destroy
*/
case OP_Clear: {
#if 0  /* local variables moved into u.bs */
  int nChange;
#endif /* local variables moved into u.bs */

  u.bs.nChange = 0;
  assert( (p->btreeMask & (((yDbMask)1)<<pOp->p2))!=0 );
  rc = sqlite3BtreeClearTable(
      db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &u.bs.nChange : 0)
  );
  if( pOp->p3 ){
    p->nChange += u.bs.nChange;
    if( pOp->p3>0 ){
      assert( memIsValid(&aMem[pOp->p3]) );
      memAboutToChange(p, &aMem[pOp->p3]);
      aMem[pOp->p3].u.i += u.bs.nChange;
    }
  }
  break;
}

/* Opcode: CreateTable P1 P2 * * *
**
68360
68361
68362
68363
68364
68365
68366
68367
68368
68369
68370
68371
68372
68373
68374
68375
68376
68377
68378
68379
68380
68381
68382
68383
68384
68385
68386
68387
68388
68389
68390
68391
68392
68393
68394
68395
68396
68397
68398
68399
68400
68401
68402
68403
68404
68405
68406
68407
68408
68409
68410
68411
68412
68413
68414
68415
68416
68417
68418
68419
68420
68421
68422
68423
68424
68425
68426
68427
68428
68429
68430
68431
68432
68433
68434
68435
68436
68437
68438
68439
68440
68441
68442
** P1>1.  Write the root page number of the new table into
** register P2.
**
** See documentation on OP_CreateTable for additional information.
*/
case OP_CreateIndex:            /* out2-prerelease */
case OP_CreateTable: {          /* out2-prerelease */
#if 0  /* local variables moved into u.bw */
  int pgno;
  int flags;
  Db *pDb;
#endif /* local variables moved into u.bw */

  u.bw.pgno = 0;
  assert( pOp->p1>=0 && pOp->p1<db->nDb );
  assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
  u.bw.pDb = &db->aDb[pOp->p1];
  assert( u.bw.pDb->pBt!=0 );
  if( pOp->opcode==OP_CreateTable ){
    /* u.bw.flags = BTREE_INTKEY; */
    u.bw.flags = BTREE_INTKEY;
  }else{
    u.bw.flags = BTREE_BLOBKEY;
  }
  rc = sqlite3BtreeCreateTable(u.bw.pDb->pBt, &u.bw.pgno, u.bw.flags);
  pOut->u.i = u.bw.pgno;
  break;
}

/* Opcode: ParseSchema P1 * * P4 *
**
** Read and parse all entries from the SQLITE_MASTER table of database P1
** that match the WHERE clause P4. 
**
** This opcode invokes the parser to create a new virtual machine,
** then runs the new virtual machine.  It is thus a re-entrant opcode.
*/
case OP_ParseSchema: {
#if 0  /* local variables moved into u.bx */
  int iDb;
  const char *zMaster;
  char *zSql;
  InitData initData;
#endif /* local variables moved into u.bx */

  /* Any prepared statement that invokes this opcode will hold mutexes
  ** on every btree.  This is a prerequisite for invoking
  ** sqlite3InitCallback().
  */
#ifdef SQLITE_DEBUG
  for(u.bx.iDb=0; u.bx.iDb<db->nDb; u.bx.iDb++){
    assert( u.bx.iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[u.bx.iDb].pBt) );
  }
#endif

  u.bx.iDb = pOp->p1;
  assert( u.bx.iDb>=0 && u.bx.iDb<db->nDb );
  assert( DbHasProperty(db, u.bx.iDb, DB_SchemaLoaded) );
  /* Used to be a conditional */ {
    u.bx.zMaster = SCHEMA_TABLE(u.bx.iDb);
    u.bx.initData.db = db;
    u.bx.initData.iDb = pOp->p1;
    u.bx.initData.pzErrMsg = &p->zErrMsg;
    u.bx.zSql = sqlite3MPrintf(db,
       "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
       db->aDb[u.bx.iDb].zName, u.bx.zMaster, pOp->p4.z);
    if( u.bx.zSql==0 ){
      rc = SQLITE_NOMEM;
    }else{
      assert( db->init.busy==0 );
      db->init.busy = 1;
      u.bx.initData.rc = SQLITE_OK;
      assert( !db->mallocFailed );
      rc = sqlite3_exec(db, u.bx.zSql, sqlite3InitCallback, &u.bx.initData, 0);
      if( rc==SQLITE_OK ) rc = u.bx.initData.rc;
      sqlite3DbFree(db, u.bx.zSql);
      db->init.busy = 0;
    }
  }
  if( rc==SQLITE_NOMEM ){
    goto no_mem;
  }
  break;







|



|

|


|
|

|
|

|

|
|












|




|






|
|



|
|
|

|
|
|
|
|

|
|




|

|
|
|







67463
67464
67465
67466
67467
67468
67469
67470
67471
67472
67473
67474
67475
67476
67477
67478
67479
67480
67481
67482
67483
67484
67485
67486
67487
67488
67489
67490
67491
67492
67493
67494
67495
67496
67497
67498
67499
67500
67501
67502
67503
67504
67505
67506
67507
67508
67509
67510
67511
67512
67513
67514
67515
67516
67517
67518
67519
67520
67521
67522
67523
67524
67525
67526
67527
67528
67529
67530
67531
67532
67533
67534
67535
67536
67537
67538
67539
67540
67541
67542
67543
67544
67545
** P1>1.  Write the root page number of the new table into
** register P2.
**
** See documentation on OP_CreateTable for additional information.
*/
case OP_CreateIndex:            /* out2-prerelease */
case OP_CreateTable: {          /* out2-prerelease */
#if 0  /* local variables moved into u.bt */
  int pgno;
  int flags;
  Db *pDb;
#endif /* local variables moved into u.bt */

  u.bt.pgno = 0;
  assert( pOp->p1>=0 && pOp->p1<db->nDb );
  assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
  u.bt.pDb = &db->aDb[pOp->p1];
  assert( u.bt.pDb->pBt!=0 );
  if( pOp->opcode==OP_CreateTable ){
    /* u.bt.flags = BTREE_INTKEY; */
    u.bt.flags = BTREE_INTKEY;
  }else{
    u.bt.flags = BTREE_BLOBKEY;
  }
  rc = sqlite3BtreeCreateTable(u.bt.pDb->pBt, &u.bt.pgno, u.bt.flags);
  pOut->u.i = u.bt.pgno;
  break;
}

/* Opcode: ParseSchema P1 * * P4 *
**
** Read and parse all entries from the SQLITE_MASTER table of database P1
** that match the WHERE clause P4. 
**
** This opcode invokes the parser to create a new virtual machine,
** then runs the new virtual machine.  It is thus a re-entrant opcode.
*/
case OP_ParseSchema: {
#if 0  /* local variables moved into u.bu */
  int iDb;
  const char *zMaster;
  char *zSql;
  InitData initData;
#endif /* local variables moved into u.bu */

  /* Any prepared statement that invokes this opcode will hold mutexes
  ** on every btree.  This is a prerequisite for invoking
  ** sqlite3InitCallback().
  */
#ifdef SQLITE_DEBUG
  for(u.bu.iDb=0; u.bu.iDb<db->nDb; u.bu.iDb++){
    assert( u.bu.iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[u.bu.iDb].pBt) );
  }
#endif

  u.bu.iDb = pOp->p1;
  assert( u.bu.iDb>=0 && u.bu.iDb<db->nDb );
  assert( DbHasProperty(db, u.bu.iDb, DB_SchemaLoaded) );
  /* Used to be a conditional */ {
    u.bu.zMaster = SCHEMA_TABLE(u.bu.iDb);
    u.bu.initData.db = db;
    u.bu.initData.iDb = pOp->p1;
    u.bu.initData.pzErrMsg = &p->zErrMsg;
    u.bu.zSql = sqlite3MPrintf(db,
       "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
       db->aDb[u.bu.iDb].zName, u.bu.zMaster, pOp->p4.z);
    if( u.bu.zSql==0 ){
      rc = SQLITE_NOMEM;
    }else{
      assert( db->init.busy==0 );
      db->init.busy = 1;
      u.bu.initData.rc = SQLITE_OK;
      assert( !db->mallocFailed );
      rc = sqlite3_exec(db, u.bu.zSql, sqlite3InitCallback, &u.bu.initData, 0);
      if( rc==SQLITE_OK ) rc = u.bu.initData.rc;
      sqlite3DbFree(db, u.bu.zSql);
      db->init.busy = 0;
    }
  }
  if( rc==SQLITE_NOMEM ){
    goto no_mem;
  }
  break;
68511
68512
68513
68514
68515
68516
68517
68518
68519
68520
68521
68522
68523
68524
68525
68526
68527
68528
68529
68530
68531
68532
68533
68534
68535
68536
68537
68538
68539
68540
68541
68542
68543
68544
68545
68546
68547
68548
68549
68550
68551
68552
68553
68554
68555
68556
68557
68558
68559
**
** If P5 is not zero, the check is done on the auxiliary database
** file, not the main database file.
**
** This opcode is used to implement the integrity_check pragma.
*/
case OP_IntegrityCk: {
#if 0  /* local variables moved into u.by */
  int nRoot;      /* Number of tables to check.  (Number of root pages.) */
  int *aRoot;     /* Array of rootpage numbers for tables to be checked */
  int j;          /* Loop counter */
  int nErr;       /* Number of errors reported */
  char *z;        /* Text of the error report */
  Mem *pnErr;     /* Register keeping track of errors remaining */
#endif /* local variables moved into u.by */

  u.by.nRoot = pOp->p2;
  assert( u.by.nRoot>0 );
  u.by.aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(u.by.nRoot+1) );
  if( u.by.aRoot==0 ) goto no_mem;
  assert( pOp->p3>0 && pOp->p3<=p->nMem );
  u.by.pnErr = &aMem[pOp->p3];
  assert( (u.by.pnErr->flags & MEM_Int)!=0 );
  assert( (u.by.pnErr->flags & (MEM_Str|MEM_Blob))==0 );
  pIn1 = &aMem[pOp->p1];
  for(u.by.j=0; u.by.j<u.by.nRoot; u.by.j++){
    u.by.aRoot[u.by.j] = (int)sqlite3VdbeIntValue(&pIn1[u.by.j]);
  }
  u.by.aRoot[u.by.j] = 0;
  assert( pOp->p5<db->nDb );
  assert( (p->btreeMask & (((yDbMask)1)<<pOp->p5))!=0 );
  u.by.z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, u.by.aRoot, u.by.nRoot,
                                 (int)u.by.pnErr->u.i, &u.by.nErr);
  sqlite3DbFree(db, u.by.aRoot);
  u.by.pnErr->u.i -= u.by.nErr;
  sqlite3VdbeMemSetNull(pIn1);
  if( u.by.nErr==0 ){
    assert( u.by.z==0 );
  }else if( u.by.z==0 ){
    goto no_mem;
  }else{
    sqlite3VdbeMemSetStr(pIn1, u.by.z, -1, SQLITE_UTF8, sqlite3_free);
  }
  UPDATE_MAX_BLOBSIZE(pIn1);
  sqlite3VdbeChangeEncoding(pIn1, encoding);
  break;
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */








|






|

|
|
|
|

|
|
|

|
|

|


|
|
|
|

|
|
|


|







67614
67615
67616
67617
67618
67619
67620
67621
67622
67623
67624
67625
67626
67627
67628
67629
67630
67631
67632
67633
67634
67635
67636
67637
67638
67639
67640
67641
67642
67643
67644
67645
67646
67647
67648
67649
67650
67651
67652
67653
67654
67655
67656
67657
67658
67659
67660
67661
67662
**
** If P5 is not zero, the check is done on the auxiliary database
** file, not the main database file.
**
** This opcode is used to implement the integrity_check pragma.
*/
case OP_IntegrityCk: {
#if 0  /* local variables moved into u.bv */
  int nRoot;      /* Number of tables to check.  (Number of root pages.) */
  int *aRoot;     /* Array of rootpage numbers for tables to be checked */
  int j;          /* Loop counter */
  int nErr;       /* Number of errors reported */
  char *z;        /* Text of the error report */
  Mem *pnErr;     /* Register keeping track of errors remaining */
#endif /* local variables moved into u.bv */

  u.bv.nRoot = pOp->p2;
  assert( u.bv.nRoot>0 );
  u.bv.aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(u.bv.nRoot+1) );
  if( u.bv.aRoot==0 ) goto no_mem;
  assert( pOp->p3>0 && pOp->p3<=p->nMem );
  u.bv.pnErr = &aMem[pOp->p3];
  assert( (u.bv.pnErr->flags & MEM_Int)!=0 );
  assert( (u.bv.pnErr->flags & (MEM_Str|MEM_Blob))==0 );
  pIn1 = &aMem[pOp->p1];
  for(u.bv.j=0; u.bv.j<u.bv.nRoot; u.bv.j++){
    u.bv.aRoot[u.bv.j] = (int)sqlite3VdbeIntValue(&pIn1[u.bv.j]);
  }
  u.bv.aRoot[u.bv.j] = 0;
  assert( pOp->p5<db->nDb );
  assert( (p->btreeMask & (((yDbMask)1)<<pOp->p5))!=0 );
  u.bv.z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, u.bv.aRoot, u.bv.nRoot,
                                 (int)u.bv.pnErr->u.i, &u.bv.nErr);
  sqlite3DbFree(db, u.bv.aRoot);
  u.bv.pnErr->u.i -= u.bv.nErr;
  sqlite3VdbeMemSetNull(pIn1);
  if( u.bv.nErr==0 ){
    assert( u.bv.z==0 );
  }else if( u.bv.z==0 ){
    goto no_mem;
  }else{
    sqlite3VdbeMemSetStr(pIn1, u.bv.z, -1, SQLITE_UTF8, sqlite3_free);
  }
  UPDATE_MAX_BLOBSIZE(pIn1);
  sqlite3VdbeChangeEncoding(pIn1, encoding);
  break;
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */

68579
68580
68581
68582
68583
68584
68585
68586
68587
68588
68589
68590
68591
68592
68593
68594
68595
68596
68597
68598
68599
68600
68601
68602
68603
68604
68605
68606
/* Opcode: RowSetRead P1 P2 P3 * *
**
** Extract the smallest value from boolean index P1 and put that value into
** register P3.  Or, if boolean index P1 is initially empty, leave P3
** unchanged and jump to instruction P2.
*/
case OP_RowSetRead: {       /* jump, in1, out3 */
#if 0  /* local variables moved into u.bz */
  i64 val;
#endif /* local variables moved into u.bz */
  CHECK_FOR_INTERRUPT;
  pIn1 = &aMem[pOp->p1];
  if( (pIn1->flags & MEM_RowSet)==0
   || sqlite3RowSetNext(pIn1->u.pRowSet, &u.bz.val)==0
  ){
    /* The boolean index is empty */
    sqlite3VdbeMemSetNull(pIn1);
    pc = pOp->p2 - 1;
  }else{
    /* A value was pulled from the index */
    sqlite3VdbeMemSetInt64(&aMem[pOp->p3], u.bz.val);
  }
  break;
}

/* Opcode: RowSetTest P1 P2 P3 P4
**
** Register P3 is assumed to hold a 64-bit integer value. If register P1







|

|



|






|







67682
67683
67684
67685
67686
67687
67688
67689
67690
67691
67692
67693
67694
67695
67696
67697
67698
67699
67700
67701
67702
67703
67704
67705
67706
67707
67708
67709
/* Opcode: RowSetRead P1 P2 P3 * *
**
** Extract the smallest value from boolean index P1 and put that value into
** register P3.  Or, if boolean index P1 is initially empty, leave P3
** unchanged and jump to instruction P2.
*/
case OP_RowSetRead: {       /* jump, in1, out3 */
#if 0  /* local variables moved into u.bw */
  i64 val;
#endif /* local variables moved into u.bw */
  CHECK_FOR_INTERRUPT;
  pIn1 = &aMem[pOp->p1];
  if( (pIn1->flags & MEM_RowSet)==0
   || sqlite3RowSetNext(pIn1->u.pRowSet, &u.bw.val)==0
  ){
    /* The boolean index is empty */
    sqlite3VdbeMemSetNull(pIn1);
    pc = pOp->p2 - 1;
  }else{
    /* A value was pulled from the index */
    sqlite3VdbeMemSetInt64(&aMem[pOp->p3], u.bw.val);
  }
  break;
}

/* Opcode: RowSetTest P1 P2 P3 P4
**
** Register P3 is assumed to hold a 64-bit integer value. If register P1
68621
68622
68623
68624
68625
68626
68627
68628
68629
68630
68631
68632
68633
68634
68635
68636
68637
68638
68639
68640
68641
68642
68643
68644
68645
68646
68647
68648
68649
68650
68651
68652
68653
68654
68655
68656
68657
68658
68659
68660
68661
68662
68663
68664
** (b) when P4==-1 there is no need to insert the value, as it will
** never be tested for, and (c) when a value that is part of set X is
** inserted, there is no need to search to see if the same value was
** previously inserted as part of set X (only if it was previously
** inserted as part of some other set).
*/
case OP_RowSetTest: {                     /* jump, in1, in3 */
#if 0  /* local variables moved into u.ca */
  int iSet;
  int exists;
#endif /* local variables moved into u.ca */

  pIn1 = &aMem[pOp->p1];
  pIn3 = &aMem[pOp->p3];
  u.ca.iSet = pOp->p4.i;
  assert( pIn3->flags&MEM_Int );

  /* If there is anything other than a rowset object in memory cell P1,
  ** delete it now and initialize P1 with an empty rowset
  */
  if( (pIn1->flags & MEM_RowSet)==0 ){
    sqlite3VdbeMemSetRowSet(pIn1);
    if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem;
  }

  assert( pOp->p4type==P4_INT32 );
  assert( u.ca.iSet==-1 || u.ca.iSet>=0 );
  if( u.ca.iSet ){
    u.ca.exists = sqlite3RowSetTest(pIn1->u.pRowSet,
                               (u8)(u.ca.iSet>=0 ? u.ca.iSet & 0xf : 0xff),
                               pIn3->u.i);
    if( u.ca.exists ){
      pc = pOp->p2 - 1;
      break;
    }
  }
  if( u.ca.iSet>=0 ){
    sqlite3RowSetInsert(pIn1->u.pRowSet, pIn3->u.i);
  }
  break;
}


#ifndef SQLITE_OMIT_TRIGGER







|


|



|











|
|
|
|

|




|







67724
67725
67726
67727
67728
67729
67730
67731
67732
67733
67734
67735
67736
67737
67738
67739
67740
67741
67742
67743
67744
67745
67746
67747
67748
67749
67750
67751
67752
67753
67754
67755
67756
67757
67758
67759
67760
67761
67762
67763
67764
67765
67766
67767
** (b) when P4==-1 there is no need to insert the value, as it will
** never be tested for, and (c) when a value that is part of set X is
** inserted, there is no need to search to see if the same value was
** previously inserted as part of set X (only if it was previously
** inserted as part of some other set).
*/
case OP_RowSetTest: {                     /* jump, in1, in3 */
#if 0  /* local variables moved into u.bx */
  int iSet;
  int exists;
#endif /* local variables moved into u.bx */

  pIn1 = &aMem[pOp->p1];
  pIn3 = &aMem[pOp->p3];
  u.bx.iSet = pOp->p4.i;
  assert( pIn3->flags&MEM_Int );

  /* If there is anything other than a rowset object in memory cell P1,
  ** delete it now and initialize P1 with an empty rowset
  */
  if( (pIn1->flags & MEM_RowSet)==0 ){
    sqlite3VdbeMemSetRowSet(pIn1);
    if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem;
  }

  assert( pOp->p4type==P4_INT32 );
  assert( u.bx.iSet==-1 || u.bx.iSet>=0 );
  if( u.bx.iSet ){
    u.bx.exists = sqlite3RowSetTest(pIn1->u.pRowSet,
                               (u8)(u.bx.iSet>=0 ? u.bx.iSet & 0xf : 0xff),
                               pIn3->u.i);
    if( u.bx.exists ){
      pc = pOp->p2 - 1;
      break;
    }
  }
  if( u.bx.iSet>=0 ){
    sqlite3RowSetInsert(pIn1->u.pRowSet, pIn3->u.i);
  }
  break;
}


#ifndef SQLITE_OMIT_TRIGGER
68673
68674
68675
68676
68677
68678
68679
68680
68681
68682
68683
68684
68685
68686
68687
68688
68689
68690
68691
68692
68693
68694
68695
68696
68697
68698
68699
68700
68701
68702
68703
68704
68705
68706
68707
68708
68709
68710
68711
68712
68713
68714
68715
68716
68717
68718
68719
68720
68721
68722
68723
68724
68725
68726
68727
68728
68729
68730
68731
68732
68733
68734
68735
68736
68737
68738
68739
68740
68741
68742
68743
68744
68745
68746
68747
68748
68749
68750
68751
68752
68753
68754
68755
68756
68757
68758
68759
68760
68761
68762
68763
68764
68765
68766
68767
68768
68769
68770
68771
68772
68773
68774
68775
68776
68777
68778
68779
68780
68781
68782
68783
68784
68785
68786
68787
68788
68789
68790
68791
68792
68793
68794
68795
68796
68797
68798
68799
68800
68801
68802
68803
68804
68805
68806
68807
68808
** exception using the RAISE() function. Register P3 contains the address 
** of a memory cell in this (the parent) VM that is used to allocate the 
** memory required by the sub-vdbe at runtime.
**
** P4 is a pointer to the VM containing the trigger program.
*/
case OP_Program: {        /* jump */
#if 0  /* local variables moved into u.cb */
  int nMem;               /* Number of memory registers for sub-program */
  int nByte;              /* Bytes of runtime space required for sub-program */
  Mem *pRt;               /* Register to allocate runtime space */
  Mem *pMem;              /* Used to iterate through memory cells */
  Mem *pEnd;              /* Last memory cell in new array */
  VdbeFrame *pFrame;      /* New vdbe frame to execute in */
  SubProgram *pProgram;   /* Sub-program to execute */
  void *t;                /* Token identifying trigger */
#endif /* local variables moved into u.cb */

  u.cb.pProgram = pOp->p4.pProgram;
  u.cb.pRt = &aMem[pOp->p3];
  assert( memIsValid(u.cb.pRt) );
  assert( u.cb.pProgram->nOp>0 );

  /* If the p5 flag is clear, then recursive invocation of triggers is
  ** disabled for backwards compatibility (p5 is set if this sub-program
  ** is really a trigger, not a foreign key action, and the flag set
  ** and cleared by the "PRAGMA recursive_triggers" command is clear).
  **
  ** It is recursive invocation of triggers, at the SQL level, that is
  ** disabled. In some cases a single trigger may generate more than one
  ** SubProgram (if the trigger may be executed with more than one different
  ** ON CONFLICT algorithm). SubProgram structures associated with a
  ** single trigger all have the same value for the SubProgram.token
  ** variable.  */
  if( pOp->p5 ){
    u.cb.t = u.cb.pProgram->token;
    for(u.cb.pFrame=p->pFrame; u.cb.pFrame && u.cb.pFrame->token!=u.cb.t; u.cb.pFrame=u.cb.pFrame->pParent);
    if( u.cb.pFrame ) break;
  }

  if( p->nFrame>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){
    rc = SQLITE_ERROR;
    sqlite3SetString(&p->zErrMsg, db, "too many levels of trigger recursion");
    break;
  }

  /* Register u.cb.pRt is used to store the memory required to save the state
  ** of the current program, and the memory required at runtime to execute
  ** the trigger program. If this trigger has been fired before, then u.cb.pRt
  ** is already allocated. Otherwise, it must be initialized.  */
  if( (u.cb.pRt->flags&MEM_Frame)==0 ){
    /* SubProgram.nMem is set to the number of memory cells used by the
    ** program stored in SubProgram.aOp. As well as these, one memory
    ** cell is required for each cursor used by the program. Set local
    ** variable u.cb.nMem (and later, VdbeFrame.nChildMem) to this value.
    */
    u.cb.nMem = u.cb.pProgram->nMem + u.cb.pProgram->nCsr;
    u.cb.nByte = ROUND8(sizeof(VdbeFrame))
              + u.cb.nMem * sizeof(Mem)
              + u.cb.pProgram->nCsr * sizeof(VdbeCursor *);
    u.cb.pFrame = sqlite3DbMallocZero(db, u.cb.nByte);
    if( !u.cb.pFrame ){
      goto no_mem;
    }
    sqlite3VdbeMemRelease(u.cb.pRt);
    u.cb.pRt->flags = MEM_Frame;
    u.cb.pRt->u.pFrame = u.cb.pFrame;

    u.cb.pFrame->v = p;
    u.cb.pFrame->nChildMem = u.cb.nMem;
    u.cb.pFrame->nChildCsr = u.cb.pProgram->nCsr;
    u.cb.pFrame->pc = pc;
    u.cb.pFrame->aMem = p->aMem;
    u.cb.pFrame->nMem = p->nMem;
    u.cb.pFrame->apCsr = p->apCsr;
    u.cb.pFrame->nCursor = p->nCursor;
    u.cb.pFrame->aOp = p->aOp;
    u.cb.pFrame->nOp = p->nOp;
    u.cb.pFrame->token = u.cb.pProgram->token;

    u.cb.pEnd = &VdbeFrameMem(u.cb.pFrame)[u.cb.pFrame->nChildMem];
    for(u.cb.pMem=VdbeFrameMem(u.cb.pFrame); u.cb.pMem!=u.cb.pEnd; u.cb.pMem++){
      u.cb.pMem->flags = MEM_Null;
      u.cb.pMem->db = db;
    }
  }else{
    u.cb.pFrame = u.cb.pRt->u.pFrame;
    assert( u.cb.pProgram->nMem+u.cb.pProgram->nCsr==u.cb.pFrame->nChildMem );
    assert( u.cb.pProgram->nCsr==u.cb.pFrame->nChildCsr );
    assert( pc==u.cb.pFrame->pc );
  }

  p->nFrame++;
  u.cb.pFrame->pParent = p->pFrame;
  u.cb.pFrame->lastRowid = lastRowid;
  u.cb.pFrame->nChange = p->nChange;
  p->nChange = 0;
  p->pFrame = u.cb.pFrame;
  p->aMem = aMem = &VdbeFrameMem(u.cb.pFrame)[-1];
  p->nMem = u.cb.pFrame->nChildMem;
  p->nCursor = (u16)u.cb.pFrame->nChildCsr;
  p->apCsr = (VdbeCursor **)&aMem[p->nMem+1];
  p->aOp = aOp = u.cb.pProgram->aOp;
  p->nOp = u.cb.pProgram->nOp;
  pc = -1;

  break;
}

/* Opcode: Param P1 P2 * * *
**
** This opcode is only ever present in sub-programs called via the 
** OP_Program instruction. Copy a value currently stored in a memory 
** cell of the calling (parent) frame to cell P2 in the current frames 
** address space. This is used by trigger programs to access the new.* 
** and old.* values.
**
** The address of the cell in the parent frame is determined by adding
** the value of the P1 argument to the value of the P1 argument to the
** calling OP_Program instruction.
*/
case OP_Param: {           /* out2-prerelease */
#if 0  /* local variables moved into u.cc */
  VdbeFrame *pFrame;
  Mem *pIn;
#endif /* local variables moved into u.cc */
  u.cc.pFrame = p->pFrame;
  u.cc.pIn = &u.cc.pFrame->aMem[pOp->p1 + u.cc.pFrame->aOp[u.cc.pFrame->pc].p1];
  sqlite3VdbeMemShallowCopy(pOut, u.cc.pIn, MEM_Ephem);
  break;
}

#endif /* #ifndef SQLITE_OMIT_TRIGGER */

#ifndef SQLITE_OMIT_FOREIGN_KEY
/* Opcode: FkCounter P1 P2 * * *







|








|

|
|
|
|













|
|
|








|

|

|



|

|
|
|
|
|
|


|
|
|

|
|
|
|
|
|
|
|
|
|
|

|
|
|
|


|
|
|
|



|
|
|

|
|
|
|

|
|


















|


|
|
|
|







67776
67777
67778
67779
67780
67781
67782
67783
67784
67785
67786
67787
67788
67789
67790
67791
67792
67793
67794
67795
67796
67797
67798
67799
67800
67801
67802
67803
67804
67805
67806
67807
67808
67809
67810
67811
67812
67813
67814
67815
67816
67817
67818
67819
67820
67821
67822
67823
67824
67825
67826
67827
67828
67829
67830
67831
67832
67833
67834
67835
67836
67837
67838
67839
67840
67841
67842
67843
67844
67845
67846
67847
67848
67849
67850
67851
67852
67853
67854
67855
67856
67857
67858
67859
67860
67861
67862
67863
67864
67865
67866
67867
67868
67869
67870
67871
67872
67873
67874
67875
67876
67877
67878
67879
67880
67881
67882
67883
67884
67885
67886
67887
67888
67889
67890
67891
67892
67893
67894
67895
67896
67897
67898
67899
67900
67901
67902
67903
67904
67905
67906
67907
67908
67909
67910
67911
** exception using the RAISE() function. Register P3 contains the address 
** of a memory cell in this (the parent) VM that is used to allocate the 
** memory required by the sub-vdbe at runtime.
**
** P4 is a pointer to the VM containing the trigger program.
*/
case OP_Program: {        /* jump */
#if 0  /* local variables moved into u.by */
  int nMem;               /* Number of memory registers for sub-program */
  int nByte;              /* Bytes of runtime space required for sub-program */
  Mem *pRt;               /* Register to allocate runtime space */
  Mem *pMem;              /* Used to iterate through memory cells */
  Mem *pEnd;              /* Last memory cell in new array */
  VdbeFrame *pFrame;      /* New vdbe frame to execute in */
  SubProgram *pProgram;   /* Sub-program to execute */
  void *t;                /* Token identifying trigger */
#endif /* local variables moved into u.by */

  u.by.pProgram = pOp->p4.pProgram;
  u.by.pRt = &aMem[pOp->p3];
  assert( memIsValid(u.by.pRt) );
  assert( u.by.pProgram->nOp>0 );

  /* If the p5 flag is clear, then recursive invocation of triggers is
  ** disabled for backwards compatibility (p5 is set if this sub-program
  ** is really a trigger, not a foreign key action, and the flag set
  ** and cleared by the "PRAGMA recursive_triggers" command is clear).
  **
  ** It is recursive invocation of triggers, at the SQL level, that is
  ** disabled. In some cases a single trigger may generate more than one
  ** SubProgram (if the trigger may be executed with more than one different
  ** ON CONFLICT algorithm). SubProgram structures associated with a
  ** single trigger all have the same value for the SubProgram.token
  ** variable.  */
  if( pOp->p5 ){
    u.by.t = u.by.pProgram->token;
    for(u.by.pFrame=p->pFrame; u.by.pFrame && u.by.pFrame->token!=u.by.t; u.by.pFrame=u.by.pFrame->pParent);
    if( u.by.pFrame ) break;
  }

  if( p->nFrame>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){
    rc = SQLITE_ERROR;
    sqlite3SetString(&p->zErrMsg, db, "too many levels of trigger recursion");
    break;
  }

  /* Register u.by.pRt is used to store the memory required to save the state
  ** of the current program, and the memory required at runtime to execute
  ** the trigger program. If this trigger has been fired before, then u.by.pRt
  ** is already allocated. Otherwise, it must be initialized.  */
  if( (u.by.pRt->flags&MEM_Frame)==0 ){
    /* SubProgram.nMem is set to the number of memory cells used by the
    ** program stored in SubProgram.aOp. As well as these, one memory
    ** cell is required for each cursor used by the program. Set local
    ** variable u.by.nMem (and later, VdbeFrame.nChildMem) to this value.
    */
    u.by.nMem = u.by.pProgram->nMem + u.by.pProgram->nCsr;
    u.by.nByte = ROUND8(sizeof(VdbeFrame))
              + u.by.nMem * sizeof(Mem)
              + u.by.pProgram->nCsr * sizeof(VdbeCursor *);
    u.by.pFrame = sqlite3DbMallocZero(db, u.by.nByte);
    if( !u.by.pFrame ){
      goto no_mem;
    }
    sqlite3VdbeMemRelease(u.by.pRt);
    u.by.pRt->flags = MEM_Frame;
    u.by.pRt->u.pFrame = u.by.pFrame;

    u.by.pFrame->v = p;
    u.by.pFrame->nChildMem = u.by.nMem;
    u.by.pFrame->nChildCsr = u.by.pProgram->nCsr;
    u.by.pFrame->pc = pc;
    u.by.pFrame->aMem = p->aMem;
    u.by.pFrame->nMem = p->nMem;
    u.by.pFrame->apCsr = p->apCsr;
    u.by.pFrame->nCursor = p->nCursor;
    u.by.pFrame->aOp = p->aOp;
    u.by.pFrame->nOp = p->nOp;
    u.by.pFrame->token = u.by.pProgram->token;

    u.by.pEnd = &VdbeFrameMem(u.by.pFrame)[u.by.pFrame->nChildMem];
    for(u.by.pMem=VdbeFrameMem(u.by.pFrame); u.by.pMem!=u.by.pEnd; u.by.pMem++){
      u.by.pMem->flags = MEM_Null;
      u.by.pMem->db = db;
    }
  }else{
    u.by.pFrame = u.by.pRt->u.pFrame;
    assert( u.by.pProgram->nMem+u.by.pProgram->nCsr==u.by.pFrame->nChildMem );
    assert( u.by.pProgram->nCsr==u.by.pFrame->nChildCsr );
    assert( pc==u.by.pFrame->pc );
  }

  p->nFrame++;
  u.by.pFrame->pParent = p->pFrame;
  u.by.pFrame->lastRowid = lastRowid;
  u.by.pFrame->nChange = p->nChange;
  p->nChange = 0;
  p->pFrame = u.by.pFrame;
  p->aMem = aMem = &VdbeFrameMem(u.by.pFrame)[-1];
  p->nMem = u.by.pFrame->nChildMem;
  p->nCursor = (u16)u.by.pFrame->nChildCsr;
  p->apCsr = (VdbeCursor **)&aMem[p->nMem+1];
  p->aOp = aOp = u.by.pProgram->aOp;
  p->nOp = u.by.pProgram->nOp;
  pc = -1;

  break;
}

/* Opcode: Param P1 P2 * * *
**
** This opcode is only ever present in sub-programs called via the 
** OP_Program instruction. Copy a value currently stored in a memory 
** cell of the calling (parent) frame to cell P2 in the current frames 
** address space. This is used by trigger programs to access the new.* 
** and old.* values.
**
** The address of the cell in the parent frame is determined by adding
** the value of the P1 argument to the value of the P1 argument to the
** calling OP_Program instruction.
*/
case OP_Param: {           /* out2-prerelease */
#if 0  /* local variables moved into u.bz */
  VdbeFrame *pFrame;
  Mem *pIn;
#endif /* local variables moved into u.bz */
  u.bz.pFrame = p->pFrame;
  u.bz.pIn = &u.bz.pFrame->aMem[pOp->p1 + u.bz.pFrame->aOp[u.bz.pFrame->pc].p1];
  sqlite3VdbeMemShallowCopy(pOut, u.bz.pIn, MEM_Ephem);
  break;
}

#endif /* #ifndef SQLITE_OMIT_TRIGGER */

#ifndef SQLITE_OMIT_FOREIGN_KEY
/* Opcode: FkCounter P1 P2 * * *
68850
68851
68852
68853
68854
68855
68856
68857
68858
68859
68860
68861
68862
68863
68864
68865
68866
68867
68868
68869
68870
68871
68872
68873
68874
68875
68876
68877
68878
68879
** within a sub-program). Set the value of register P1 to the maximum of 
** its current value and the value in register P2.
**
** This instruction throws an error if the memory cell is not initially
** an integer.
*/
case OP_MemMax: {        /* in2 */
#if 0  /* local variables moved into u.cd */
  Mem *pIn1;
  VdbeFrame *pFrame;
#endif /* local variables moved into u.cd */
  if( p->pFrame ){
    for(u.cd.pFrame=p->pFrame; u.cd.pFrame->pParent; u.cd.pFrame=u.cd.pFrame->pParent);
    u.cd.pIn1 = &u.cd.pFrame->aMem[pOp->p1];
  }else{
    u.cd.pIn1 = &aMem[pOp->p1];
  }
  assert( memIsValid(u.cd.pIn1) );
  sqlite3VdbeMemIntegerify(u.cd.pIn1);
  pIn2 = &aMem[pOp->p2];
  sqlite3VdbeMemIntegerify(pIn2);
  if( u.cd.pIn1->u.i<pIn2->u.i){
    u.cd.pIn1->u.i = pIn2->u.i;
  }
  break;
}
#endif /* SQLITE_OMIT_AUTOINCREMENT */

/* Opcode: IfPos P1 P2 * * *
**







|


|

|
|

|

|
|


|
|







67953
67954
67955
67956
67957
67958
67959
67960
67961
67962
67963
67964
67965
67966
67967
67968
67969
67970
67971
67972
67973
67974
67975
67976
67977
67978
67979
67980
67981
67982
** within a sub-program). Set the value of register P1 to the maximum of 
** its current value and the value in register P2.
**
** This instruction throws an error if the memory cell is not initially
** an integer.
*/
case OP_MemMax: {        /* in2 */
#if 0  /* local variables moved into u.ca */
  Mem *pIn1;
  VdbeFrame *pFrame;
#endif /* local variables moved into u.ca */
  if( p->pFrame ){
    for(u.ca.pFrame=p->pFrame; u.ca.pFrame->pParent; u.ca.pFrame=u.ca.pFrame->pParent);
    u.ca.pIn1 = &u.ca.pFrame->aMem[pOp->p1];
  }else{
    u.ca.pIn1 = &aMem[pOp->p1];
  }
  assert( memIsValid(u.ca.pIn1) );
  sqlite3VdbeMemIntegerify(u.ca.pIn1);
  pIn2 = &aMem[pOp->p2];
  sqlite3VdbeMemIntegerify(pIn2);
  if( u.ca.pIn1->u.i<pIn2->u.i){
    u.ca.pIn1->u.i = pIn2->u.i;
  }
  break;
}
#endif /* SQLITE_OMIT_AUTOINCREMENT */

/* Opcode: IfPos P1 P2 * * *
**
68932
68933
68934
68935
68936
68937
68938
68939
68940
68941
68942
68943
68944
68945
68946
68947
68948
68949
68950
68951
68952
68953
68954
68955
68956
68957
68958
68959
68960
68961
68962
68963
68964
68965
68966
68967
68968
68969
68970
68971
68972
68973
68974
68975
68976
68977
68978
68979
68980
68981
68982
68983
68984
68985
68986
68987
68988
68989
68990
68991
68992
68993
68994
68995
68996
68997
68998
68999
69000
69001
69002
69003
69004
69005
69006
69007
69008
69009
69010
69011
69012
69013
69014
69015
69016
69017
69018
69019
69020
69021
69022
69023
69024
69025
69026
69027
69028
69029
69030
69031
69032
69033
69034
69035
69036
69037
69038
69039
69040
69041
69042
69043
69044
69045
69046
69047
69048
69049
69050
69051
69052
69053
69054
69055
69056
69057
69058
69059
69060
69061
69062
69063
69064
69065
69066
69067
69068
69069
69070
69071
69072
69073
69074
69075
69076
69077
69078
69079
69080
69081
69082
69083
69084
69085
69086
69087
69088
69089
69090
69091
69092
69093
69094
69095
69096
69097
69098
69099
69100
69101
69102
69103
69104
69105
69106
69107
69108
69109
69110
69111
69112
69113
69114
69115
69116
69117
69118
69119
69120
69121
69122
69123
69124
69125
69126
69127
69128
69129
69130
69131
69132
69133
69134
69135
69136
69137
69138
69139
69140
69141
69142
69143
69144
69145
69146
69147
69148
69149
69150
69151
69152
69153
69154
69155
69156
69157
69158
69159
** structure that specifies the function.  Use register
** P3 as the accumulator.
**
** The P5 arguments are taken from register P2 and its
** successors.
*/
case OP_AggStep: {
#if 0  /* local variables moved into u.ce */
  int n;
  int i;
  Mem *pMem;
  Mem *pRec;
  sqlite3_context ctx;
  sqlite3_value **apVal;
#endif /* local variables moved into u.ce */

  u.ce.n = pOp->p5;
  assert( u.ce.n>=0 );
  u.ce.pRec = &aMem[pOp->p2];
  u.ce.apVal = p->apArg;
  assert( u.ce.apVal || u.ce.n==0 );
  for(u.ce.i=0; u.ce.i<u.ce.n; u.ce.i++, u.ce.pRec++){
    assert( memIsValid(u.ce.pRec) );
    u.ce.apVal[u.ce.i] = u.ce.pRec;
    memAboutToChange(p, u.ce.pRec);
    sqlite3VdbeMemStoreType(u.ce.pRec);
  }
  u.ce.ctx.pFunc = pOp->p4.pFunc;
  assert( pOp->p3>0 && pOp->p3<=p->nMem );
  u.ce.ctx.pMem = u.ce.pMem = &aMem[pOp->p3];
  u.ce.pMem->n++;
  u.ce.ctx.s.flags = MEM_Null;
  u.ce.ctx.s.z = 0;
  u.ce.ctx.s.zMalloc = 0;
  u.ce.ctx.s.xDel = 0;
  u.ce.ctx.s.db = db;
  u.ce.ctx.isError = 0;
  u.ce.ctx.pColl = 0;
  if( u.ce.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
    assert( pOp>p->aOp );
    assert( pOp[-1].p4type==P4_COLLSEQ );
    assert( pOp[-1].opcode==OP_CollSeq );
    u.ce.ctx.pColl = pOp[-1].p4.pColl;
  }
  (u.ce.ctx.pFunc->xStep)(&u.ce.ctx, u.ce.n, u.ce.apVal); /* IMP: R-24505-23230 */
  if( u.ce.ctx.isError ){
    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.ce.ctx.s));
    rc = u.ce.ctx.isError;
  }

  sqlite3VdbeMemRelease(&u.ce.ctx.s);

  break;
}

/* Opcode: AggFinal P1 P2 * P4 *
**
** Execute the finalizer function for an aggregate.  P1 is
** the memory location that is the accumulator for the aggregate.
**
** P2 is the number of arguments that the step function takes and
** P4 is a pointer to the FuncDef for this function.  The P2
** argument is not used by this opcode.  It is only there to disambiguate
** functions that can take varying numbers of arguments.  The
** P4 argument is only needed for the degenerate case where
** the step function was not previously called.
*/
case OP_AggFinal: {
#if 0  /* local variables moved into u.cf */
  Mem *pMem;
#endif /* local variables moved into u.cf */
  assert( pOp->p1>0 && pOp->p1<=p->nMem );
  u.cf.pMem = &aMem[pOp->p1];
  assert( (u.cf.pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
  rc = sqlite3VdbeMemFinalize(u.cf.pMem, pOp->p4.pFunc);
  if( rc ){
    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(u.cf.pMem));
  }
  sqlite3VdbeChangeEncoding(u.cf.pMem, encoding);
  UPDATE_MAX_BLOBSIZE(u.cf.pMem);
  if( sqlite3VdbeMemTooBig(u.cf.pMem) ){
    goto too_big;
  }
  break;
}

#ifndef SQLITE_OMIT_WAL
/* Opcode: Checkpoint P1 P2 P3 * *
**
** Checkpoint database P1. This is a no-op if P1 is not currently in
** WAL mode. Parameter P2 is one of SQLITE_CHECKPOINT_PASSIVE, FULL
** or RESTART.  Write 1 or 0 into mem[P3] if the checkpoint returns
** SQLITE_BUSY or not, respectively.  Write the number of pages in the
** WAL after the checkpoint into mem[P3+1] and the number of pages
** in the WAL that have been checkpointed after the checkpoint
** completes into mem[P3+2].  However on an error, mem[P3+1] and
** mem[P3+2] are initialized to -1.
*/
case OP_Checkpoint: {
#if 0  /* local variables moved into u.cg */
  int i;                          /* Loop counter */
  int aRes[3];                    /* Results */
  Mem *pMem;                      /* Write results here */
#endif /* local variables moved into u.cg */

  u.cg.aRes[0] = 0;
  u.cg.aRes[1] = u.cg.aRes[2] = -1;
  assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE
       || pOp->p2==SQLITE_CHECKPOINT_FULL
       || pOp->p2==SQLITE_CHECKPOINT_RESTART
  );
  rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &u.cg.aRes[1], &u.cg.aRes[2]);
  if( rc==SQLITE_BUSY ){
    rc = SQLITE_OK;
    u.cg.aRes[0] = 1;
  }
  for(u.cg.i=0, u.cg.pMem = &aMem[pOp->p3]; u.cg.i<3; u.cg.i++, u.cg.pMem++){
    sqlite3VdbeMemSetInt64(u.cg.pMem, (i64)u.cg.aRes[u.cg.i]);
  }
  break;
};  
#endif

#ifndef SQLITE_OMIT_PRAGMA
/* Opcode: JournalMode P1 P2 P3 * P5
**
** Change the journal mode of database P1 to P3. P3 must be one of the
** PAGER_JOURNALMODE_XXX values. If changing between the various rollback
** modes (delete, truncate, persist, off and memory), this is a simple
** operation. No IO is required.
**
** If changing into or out of WAL mode the procedure is more complicated.
**
** Write a string containing the final journal-mode to register P2.
*/
case OP_JournalMode: {    /* out2-prerelease */
#if 0  /* local variables moved into u.ch */
  Btree *pBt;                     /* Btree to change journal mode of */
  Pager *pPager;                  /* Pager associated with pBt */
  int eNew;                       /* New journal mode */
  int eOld;                       /* The old journal mode */
  const char *zFilename;          /* Name of database file for pPager */
#endif /* local variables moved into u.ch */

  u.ch.eNew = pOp->p3;
  assert( u.ch.eNew==PAGER_JOURNALMODE_DELETE
       || u.ch.eNew==PAGER_JOURNALMODE_TRUNCATE
       || u.ch.eNew==PAGER_JOURNALMODE_PERSIST
       || u.ch.eNew==PAGER_JOURNALMODE_OFF
       || u.ch.eNew==PAGER_JOURNALMODE_MEMORY
       || u.ch.eNew==PAGER_JOURNALMODE_WAL
       || u.ch.eNew==PAGER_JOURNALMODE_QUERY
  );
  assert( pOp->p1>=0 && pOp->p1<db->nDb );

  u.ch.pBt = db->aDb[pOp->p1].pBt;
  u.ch.pPager = sqlite3BtreePager(u.ch.pBt);
  u.ch.eOld = sqlite3PagerGetJournalMode(u.ch.pPager);
  if( u.ch.eNew==PAGER_JOURNALMODE_QUERY ) u.ch.eNew = u.ch.eOld;
  if( !sqlite3PagerOkToChangeJournalMode(u.ch.pPager) ) u.ch.eNew = u.ch.eOld;

#ifndef SQLITE_OMIT_WAL
  u.ch.zFilename = sqlite3PagerFilename(u.ch.pPager);

  /* Do not allow a transition to journal_mode=WAL for a database
  ** in temporary storage or if the VFS does not support shared memory
  */
  if( u.ch.eNew==PAGER_JOURNALMODE_WAL
   && (u.ch.zFilename[0]==0                         /* Temp file */
       || !sqlite3PagerWalSupported(u.ch.pPager))   /* No shared-memory support */
  ){
    u.ch.eNew = u.ch.eOld;
  }

  if( (u.ch.eNew!=u.ch.eOld)
   && (u.ch.eOld==PAGER_JOURNALMODE_WAL || u.ch.eNew==PAGER_JOURNALMODE_WAL)
  ){
    if( !db->autoCommit || db->activeVdbeCnt>1 ){
      rc = SQLITE_ERROR;
      sqlite3SetString(&p->zErrMsg, db,
          "cannot change %s wal mode from within a transaction",
          (u.ch.eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of")
      );
      break;
    }else{

      if( u.ch.eOld==PAGER_JOURNALMODE_WAL ){
        /* If leaving WAL mode, close the log file. If successful, the call
        ** to PagerCloseWal() checkpoints and deletes the write-ahead-log
        ** file. An EXCLUSIVE lock may still be held on the database file
        ** after a successful return.
        */
        rc = sqlite3PagerCloseWal(u.ch.pPager);
        if( rc==SQLITE_OK ){
          sqlite3PagerSetJournalMode(u.ch.pPager, u.ch.eNew);
        }
      }else if( u.ch.eOld==PAGER_JOURNALMODE_MEMORY ){
        /* Cannot transition directly from MEMORY to WAL.  Use mode OFF
        ** as an intermediate */
        sqlite3PagerSetJournalMode(u.ch.pPager, PAGER_JOURNALMODE_OFF);
      }

      /* Open a transaction on the database file. Regardless of the journal
      ** mode, this transaction always uses a rollback journal.
      */
      assert( sqlite3BtreeIsInTrans(u.ch.pBt)==0 );
      if( rc==SQLITE_OK ){
        rc = sqlite3BtreeSetVersion(u.ch.pBt, (u.ch.eNew==PAGER_JOURNALMODE_WAL ? 2 : 1));
      }
    }
  }
#endif /* ifndef SQLITE_OMIT_WAL */

  if( rc ){
    u.ch.eNew = u.ch.eOld;
  }
  u.ch.eNew = sqlite3PagerSetJournalMode(u.ch.pPager, u.ch.eNew);

  pOut = &aMem[pOp->p2];
  pOut->flags = MEM_Str|MEM_Static|MEM_Term;
  pOut->z = (char *)sqlite3JournalModename(u.ch.eNew);
  pOut->n = sqlite3Strlen30(pOut->z);
  pOut->enc = SQLITE_UTF8;
  sqlite3VdbeChangeEncoding(pOut, encoding);
  break;
};
#endif /* SQLITE_OMIT_PRAGMA */








|






|

|
|
|
|
|
|
|
|
|
|

|

|
|
|
|
|
|
|
|
|
|



|

|
|
|
|


|

















|

|

|
|
|

|

|
|
|


















|



|

|
|




|


|

|
|


















|





|

|
|
|
|
|
|
|
|



|
|
|
|
|


|




|
|
|

|


|
|





|




|





|

|

|


|





|

|






|

|



|







68035
68036
68037
68038
68039
68040
68041
68042
68043
68044
68045
68046
68047
68048
68049
68050
68051
68052
68053
68054
68055
68056
68057
68058
68059
68060
68061
68062
68063
68064
68065
68066
68067
68068
68069
68070
68071
68072
68073
68074
68075
68076
68077
68078
68079
68080
68081
68082
68083
68084
68085
68086
68087
68088
68089
68090
68091
68092
68093
68094
68095
68096
68097
68098
68099
68100
68101
68102
68103
68104
68105
68106
68107
68108
68109
68110
68111
68112
68113
68114
68115
68116
68117
68118
68119
68120
68121
68122
68123
68124
68125
68126
68127
68128
68129
68130
68131
68132
68133
68134
68135
68136
68137
68138
68139
68140
68141
68142
68143
68144
68145
68146
68147
68148
68149
68150
68151
68152
68153
68154
68155
68156
68157
68158
68159
68160
68161
68162
68163
68164
68165
68166
68167
68168
68169
68170
68171
68172
68173
68174
68175
68176
68177
68178
68179
68180
68181
68182
68183
68184
68185
68186
68187
68188
68189
68190
68191
68192
68193
68194
68195
68196
68197
68198
68199
68200
68201
68202
68203
68204
68205
68206
68207
68208
68209
68210
68211
68212
68213
68214
68215
68216
68217
68218
68219
68220
68221
68222
68223
68224
68225
68226
68227
68228
68229
68230
68231
68232
68233
68234
68235
68236
68237
68238
68239
68240
68241
68242
68243
68244
68245
68246
68247
68248
68249
68250
68251
68252
68253
68254
68255
68256
68257
68258
68259
68260
68261
68262
** structure that specifies the function.  Use register
** P3 as the accumulator.
**
** The P5 arguments are taken from register P2 and its
** successors.
*/
case OP_AggStep: {
#if 0  /* local variables moved into u.cb */
  int n;
  int i;
  Mem *pMem;
  Mem *pRec;
  sqlite3_context ctx;
  sqlite3_value **apVal;
#endif /* local variables moved into u.cb */

  u.cb.n = pOp->p5;
  assert( u.cb.n>=0 );
  u.cb.pRec = &aMem[pOp->p2];
  u.cb.apVal = p->apArg;
  assert( u.cb.apVal || u.cb.n==0 );
  for(u.cb.i=0; u.cb.i<u.cb.n; u.cb.i++, u.cb.pRec++){
    assert( memIsValid(u.cb.pRec) );
    u.cb.apVal[u.cb.i] = u.cb.pRec;
    memAboutToChange(p, u.cb.pRec);
    sqlite3VdbeMemStoreType(u.cb.pRec);
  }
  u.cb.ctx.pFunc = pOp->p4.pFunc;
  assert( pOp->p3>0 && pOp->p3<=p->nMem );
  u.cb.ctx.pMem = u.cb.pMem = &aMem[pOp->p3];
  u.cb.pMem->n++;
  u.cb.ctx.s.flags = MEM_Null;
  u.cb.ctx.s.z = 0;
  u.cb.ctx.s.zMalloc = 0;
  u.cb.ctx.s.xDel = 0;
  u.cb.ctx.s.db = db;
  u.cb.ctx.isError = 0;
  u.cb.ctx.pColl = 0;
  if( u.cb.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
    assert( pOp>p->aOp );
    assert( pOp[-1].p4type==P4_COLLSEQ );
    assert( pOp[-1].opcode==OP_CollSeq );
    u.cb.ctx.pColl = pOp[-1].p4.pColl;
  }
  (u.cb.ctx.pFunc->xStep)(&u.cb.ctx, u.cb.n, u.cb.apVal); /* IMP: R-24505-23230 */
  if( u.cb.ctx.isError ){
    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.cb.ctx.s));
    rc = u.cb.ctx.isError;
  }

  sqlite3VdbeMemRelease(&u.cb.ctx.s);

  break;
}

/* Opcode: AggFinal P1 P2 * P4 *
**
** Execute the finalizer function for an aggregate.  P1 is
** the memory location that is the accumulator for the aggregate.
**
** P2 is the number of arguments that the step function takes and
** P4 is a pointer to the FuncDef for this function.  The P2
** argument is not used by this opcode.  It is only there to disambiguate
** functions that can take varying numbers of arguments.  The
** P4 argument is only needed for the degenerate case where
** the step function was not previously called.
*/
case OP_AggFinal: {
#if 0  /* local variables moved into u.cc */
  Mem *pMem;
#endif /* local variables moved into u.cc */
  assert( pOp->p1>0 && pOp->p1<=p->nMem );
  u.cc.pMem = &aMem[pOp->p1];
  assert( (u.cc.pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
  rc = sqlite3VdbeMemFinalize(u.cc.pMem, pOp->p4.pFunc);
  if( rc ){
    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(u.cc.pMem));
  }
  sqlite3VdbeChangeEncoding(u.cc.pMem, encoding);
  UPDATE_MAX_BLOBSIZE(u.cc.pMem);
  if( sqlite3VdbeMemTooBig(u.cc.pMem) ){
    goto too_big;
  }
  break;
}

#ifndef SQLITE_OMIT_WAL
/* Opcode: Checkpoint P1 P2 P3 * *
**
** Checkpoint database P1. This is a no-op if P1 is not currently in
** WAL mode. Parameter P2 is one of SQLITE_CHECKPOINT_PASSIVE, FULL
** or RESTART.  Write 1 or 0 into mem[P3] if the checkpoint returns
** SQLITE_BUSY or not, respectively.  Write the number of pages in the
** WAL after the checkpoint into mem[P3+1] and the number of pages
** in the WAL that have been checkpointed after the checkpoint
** completes into mem[P3+2].  However on an error, mem[P3+1] and
** mem[P3+2] are initialized to -1.
*/
case OP_Checkpoint: {
#if 0  /* local variables moved into u.cd */
  int i;                          /* Loop counter */
  int aRes[3];                    /* Results */
  Mem *pMem;                      /* Write results here */
#endif /* local variables moved into u.cd */

  u.cd.aRes[0] = 0;
  u.cd.aRes[1] = u.cd.aRes[2] = -1;
  assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE
       || pOp->p2==SQLITE_CHECKPOINT_FULL
       || pOp->p2==SQLITE_CHECKPOINT_RESTART
  );
  rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &u.cd.aRes[1], &u.cd.aRes[2]);
  if( rc==SQLITE_BUSY ){
    rc = SQLITE_OK;
    u.cd.aRes[0] = 1;
  }
  for(u.cd.i=0, u.cd.pMem = &aMem[pOp->p3]; u.cd.i<3; u.cd.i++, u.cd.pMem++){
    sqlite3VdbeMemSetInt64(u.cd.pMem, (i64)u.cd.aRes[u.cd.i]);
  }
  break;
};  
#endif

#ifndef SQLITE_OMIT_PRAGMA
/* Opcode: JournalMode P1 P2 P3 * P5
**
** Change the journal mode of database P1 to P3. P3 must be one of the
** PAGER_JOURNALMODE_XXX values. If changing between the various rollback
** modes (delete, truncate, persist, off and memory), this is a simple
** operation. No IO is required.
**
** If changing into or out of WAL mode the procedure is more complicated.
**
** Write a string containing the final journal-mode to register P2.
*/
case OP_JournalMode: {    /* out2-prerelease */
#if 0  /* local variables moved into u.ce */
  Btree *pBt;                     /* Btree to change journal mode of */
  Pager *pPager;                  /* Pager associated with pBt */
  int eNew;                       /* New journal mode */
  int eOld;                       /* The old journal mode */
  const char *zFilename;          /* Name of database file for pPager */
#endif /* local variables moved into u.ce */

  u.ce.eNew = pOp->p3;
  assert( u.ce.eNew==PAGER_JOURNALMODE_DELETE
       || u.ce.eNew==PAGER_JOURNALMODE_TRUNCATE
       || u.ce.eNew==PAGER_JOURNALMODE_PERSIST
       || u.ce.eNew==PAGER_JOURNALMODE_OFF
       || u.ce.eNew==PAGER_JOURNALMODE_MEMORY
       || u.ce.eNew==PAGER_JOURNALMODE_WAL
       || u.ce.eNew==PAGER_JOURNALMODE_QUERY
  );
  assert( pOp->p1>=0 && pOp->p1<db->nDb );

  u.ce.pBt = db->aDb[pOp->p1].pBt;
  u.ce.pPager = sqlite3BtreePager(u.ce.pBt);
  u.ce.eOld = sqlite3PagerGetJournalMode(u.ce.pPager);
  if( u.ce.eNew==PAGER_JOURNALMODE_QUERY ) u.ce.eNew = u.ce.eOld;
  if( !sqlite3PagerOkToChangeJournalMode(u.ce.pPager) ) u.ce.eNew = u.ce.eOld;

#ifndef SQLITE_OMIT_WAL
  u.ce.zFilename = sqlite3PagerFilename(u.ce.pPager);

  /* Do not allow a transition to journal_mode=WAL for a database
  ** in temporary storage or if the VFS does not support shared memory
  */
  if( u.ce.eNew==PAGER_JOURNALMODE_WAL
   && (u.ce.zFilename[0]==0                         /* Temp file */
       || !sqlite3PagerWalSupported(u.ce.pPager))   /* No shared-memory support */
  ){
    u.ce.eNew = u.ce.eOld;
  }

  if( (u.ce.eNew!=u.ce.eOld)
   && (u.ce.eOld==PAGER_JOURNALMODE_WAL || u.ce.eNew==PAGER_JOURNALMODE_WAL)
  ){
    if( !db->autoCommit || db->activeVdbeCnt>1 ){
      rc = SQLITE_ERROR;
      sqlite3SetString(&p->zErrMsg, db,
          "cannot change %s wal mode from within a transaction",
          (u.ce.eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of")
      );
      break;
    }else{

      if( u.ce.eOld==PAGER_JOURNALMODE_WAL ){
        /* If leaving WAL mode, close the log file. If successful, the call
        ** to PagerCloseWal() checkpoints and deletes the write-ahead-log
        ** file. An EXCLUSIVE lock may still be held on the database file
        ** after a successful return.
        */
        rc = sqlite3PagerCloseWal(u.ce.pPager);
        if( rc==SQLITE_OK ){
          sqlite3PagerSetJournalMode(u.ce.pPager, u.ce.eNew);
        }
      }else if( u.ce.eOld==PAGER_JOURNALMODE_MEMORY ){
        /* Cannot transition directly from MEMORY to WAL.  Use mode OFF
        ** as an intermediate */
        sqlite3PagerSetJournalMode(u.ce.pPager, PAGER_JOURNALMODE_OFF);
      }

      /* Open a transaction on the database file. Regardless of the journal
      ** mode, this transaction always uses a rollback journal.
      */
      assert( sqlite3BtreeIsInTrans(u.ce.pBt)==0 );
      if( rc==SQLITE_OK ){
        rc = sqlite3BtreeSetVersion(u.ce.pBt, (u.ce.eNew==PAGER_JOURNALMODE_WAL ? 2 : 1));
      }
    }
  }
#endif /* ifndef SQLITE_OMIT_WAL */

  if( rc ){
    u.ce.eNew = u.ce.eOld;
  }
  u.ce.eNew = sqlite3PagerSetJournalMode(u.ce.pPager, u.ce.eNew);

  pOut = &aMem[pOp->p2];
  pOut->flags = MEM_Str|MEM_Static|MEM_Term;
  pOut->z = (char *)sqlite3JournalModename(u.ce.eNew);
  pOut->n = sqlite3Strlen30(pOut->z);
  pOut->enc = SQLITE_UTF8;
  sqlite3VdbeChangeEncoding(pOut, encoding);
  break;
};
#endif /* SQLITE_OMIT_PRAGMA */

69174
69175
69176
69177
69178
69179
69180
69181
69182
69183
69184
69185
69186
69187
69188
69189
69190
69191
69192
69193
69194
69195
/* Opcode: IncrVacuum P1 P2 * * *
**
** Perform a single step of the incremental vacuum procedure on
** the P1 database. If the vacuum has finished, jump to instruction
** P2. Otherwise, fall through to the next instruction.
*/
case OP_IncrVacuum: {        /* jump */
#if 0  /* local variables moved into u.ci */
  Btree *pBt;
#endif /* local variables moved into u.ci */

  assert( pOp->p1>=0 && pOp->p1<db->nDb );
  assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
  u.ci.pBt = db->aDb[pOp->p1].pBt;
  rc = sqlite3BtreeIncrVacuum(u.ci.pBt);
  if( rc==SQLITE_DONE ){
    pc = pOp->p2 - 1;
    rc = SQLITE_OK;
  }
  break;
}
#endif







|

|



|
|







68277
68278
68279
68280
68281
68282
68283
68284
68285
68286
68287
68288
68289
68290
68291
68292
68293
68294
68295
68296
68297
68298
/* Opcode: IncrVacuum P1 P2 * * *
**
** Perform a single step of the incremental vacuum procedure on
** the P1 database. If the vacuum has finished, jump to instruction
** P2. Otherwise, fall through to the next instruction.
*/
case OP_IncrVacuum: {        /* jump */
#if 0  /* local variables moved into u.cf */
  Btree *pBt;
#endif /* local variables moved into u.cf */

  assert( pOp->p1>=0 && pOp->p1<db->nDb );
  assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
  u.cf.pBt = db->aDb[pOp->p1].pBt;
  rc = sqlite3BtreeIncrVacuum(u.cf.pBt);
  if( rc==SQLITE_DONE ){
    pc = pOp->p2 - 1;
    rc = SQLITE_OK;
  }
  break;
}
#endif
69251
69252
69253
69254
69255
69256
69257
69258
69259
69260
69261
69262
69263
69264
69265
69266
69267
69268
69269
69270
** xBegin method for that table.
**
** Also, whether or not P4 is set, check that this is not being called from
** within a callback to a virtual table xSync() method. If it is, the error
** code will be set to SQLITE_LOCKED.
*/
case OP_VBegin: {
#if 0  /* local variables moved into u.cj */
  VTable *pVTab;
#endif /* local variables moved into u.cj */
  u.cj.pVTab = pOp->p4.pVtab;
  rc = sqlite3VtabBegin(db, u.cj.pVTab);
  if( u.cj.pVTab ) importVtabErrMsg(p, u.cj.pVTab->pVtab);
  break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */

#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VCreate P1 * * P4 *
**







|

|
|
|
|







68354
68355
68356
68357
68358
68359
68360
68361
68362
68363
68364
68365
68366
68367
68368
68369
68370
68371
68372
68373
** xBegin method for that table.
**
** Also, whether or not P4 is set, check that this is not being called from
** within a callback to a virtual table xSync() method. If it is, the error
** code will be set to SQLITE_LOCKED.
*/
case OP_VBegin: {
#if 0  /* local variables moved into u.cg */
  VTable *pVTab;
#endif /* local variables moved into u.cg */
  u.cg.pVTab = pOp->p4.pVtab;
  rc = sqlite3VtabBegin(db, u.cg.pVTab);
  if( u.cg.pVTab ) importVtabErrMsg(p, u.cg.pVTab->pVtab);
  break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */

#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VCreate P1 * * P4 *
**
69295
69296
69297
69298
69299
69300
69301
69302
69303
69304
69305
69306
69307
69308
69309
69310
69311
69312
69313
69314
69315
69316
69317
69318
69319
69320
69321
69322
69323
69324
69325
69326
69327
69328
69329
69330
69331
69332
69333
69334
/* Opcode: VOpen P1 * * P4 *
**
** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
** P1 is a cursor number.  This opcode opens a cursor to the virtual
** table and stores that cursor in P1.
*/
case OP_VOpen: {
#if 0  /* local variables moved into u.ck */
  VdbeCursor *pCur;
  sqlite3_vtab_cursor *pVtabCursor;
  sqlite3_vtab *pVtab;
  sqlite3_module *pModule;
#endif /* local variables moved into u.ck */

  u.ck.pCur = 0;
  u.ck.pVtabCursor = 0;
  u.ck.pVtab = pOp->p4.pVtab->pVtab;
  u.ck.pModule = (sqlite3_module *)u.ck.pVtab->pModule;
  assert(u.ck.pVtab && u.ck.pModule);
  rc = u.ck.pModule->xOpen(u.ck.pVtab, &u.ck.pVtabCursor);
  importVtabErrMsg(p, u.ck.pVtab);
  if( SQLITE_OK==rc ){
    /* Initialize sqlite3_vtab_cursor base class */
    u.ck.pVtabCursor->pVtab = u.ck.pVtab;

    /* Initialise vdbe cursor object */
    u.ck.pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
    if( u.ck.pCur ){
      u.ck.pCur->pVtabCursor = u.ck.pVtabCursor;
      u.ck.pCur->pModule = u.ck.pVtabCursor->pVtab->pModule;
    }else{
      db->mallocFailed = 1;
      u.ck.pModule->xClose(u.ck.pVtabCursor);
    }
  }
  break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */

#ifndef SQLITE_OMIT_VIRTUALTABLE







|




|

|
|
|
|
|
|
|


|


|
|
|
|


|







68398
68399
68400
68401
68402
68403
68404
68405
68406
68407
68408
68409
68410
68411
68412
68413
68414
68415
68416
68417
68418
68419
68420
68421
68422
68423
68424
68425
68426
68427
68428
68429
68430
68431
68432
68433
68434
68435
68436
68437
/* Opcode: VOpen P1 * * P4 *
**
** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
** P1 is a cursor number.  This opcode opens a cursor to the virtual
** table and stores that cursor in P1.
*/
case OP_VOpen: {
#if 0  /* local variables moved into u.ch */
  VdbeCursor *pCur;
  sqlite3_vtab_cursor *pVtabCursor;
  sqlite3_vtab *pVtab;
  sqlite3_module *pModule;
#endif /* local variables moved into u.ch */

  u.ch.pCur = 0;
  u.ch.pVtabCursor = 0;
  u.ch.pVtab = pOp->p4.pVtab->pVtab;
  u.ch.pModule = (sqlite3_module *)u.ch.pVtab->pModule;
  assert(u.ch.pVtab && u.ch.pModule);
  rc = u.ch.pModule->xOpen(u.ch.pVtab, &u.ch.pVtabCursor);
  importVtabErrMsg(p, u.ch.pVtab);
  if( SQLITE_OK==rc ){
    /* Initialize sqlite3_vtab_cursor base class */
    u.ch.pVtabCursor->pVtab = u.ch.pVtab;

    /* Initialise vdbe cursor object */
    u.ch.pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
    if( u.ch.pCur ){
      u.ch.pCur->pVtabCursor = u.ch.pVtabCursor;
      u.ch.pCur->pModule = u.ch.pVtabCursor->pVtab->pModule;
    }else{
      db->mallocFailed = 1;
      u.ch.pModule->xClose(u.ch.pVtabCursor);
    }
  }
  break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */

#ifndef SQLITE_OMIT_VIRTUALTABLE
69347
69348
69349
69350
69351
69352
69353
69354
69355
69356
69357
69358
69359
69360
69361
69362
69363
69364
69365
69366
69367
69368
69369
69370
69371
69372
69373
69374
69375
69376
69377
69378
69379
69380
69381
69382
69383
69384
69385
69386
69387
69388
69389
69390
69391
69392
69393
69394
69395
69396
69397
69398
69399
69400
69401
69402
69403
69404
69405
69406
69407
69408
69409
69410
69411
69412
69413
69414
69415
69416
69417
69418
69419
69420
69421
69422
69423
69424
69425
69426
69427
69428
69429
69430
69431
69432
69433
69434
69435
69436
69437
69438
69439
69440
69441
69442
69443
69444
69445
69446
69447
69448
69449
69450
69451
69452
69453
69454
69455
69456
69457
69458
69459
69460
69461
69462
69463
69464
69465
69466
69467
69468
69469
69470
69471
69472
69473
69474
69475
69476
69477
69478
69479
69480
69481
69482
69483
69484
69485
69486
69487
69488
69489
69490
69491
69492
69493
69494
69495
69496
69497
69498
69499
69500
69501
69502
69503
69504
69505
69506
69507
69508
69509
69510
69511
69512
69513
69514
69515
69516
69517
69518
69519
69520
69521
69522
69523
69524
69525
69526
69527
69528
69529
69530
69531
69532
69533
69534
69535
69536
69537
69538
69539
69540
69541
69542
69543
** xFilter method. Registers P3+2..P3+1+argc are the argc
** additional parameters which are passed to
** xFilter as argv. Register P3+2 becomes argv[0] when passed to xFilter.
**
** A jump is made to P2 if the result set after filtering would be empty.
*/
case OP_VFilter: {   /* jump */
#if 0  /* local variables moved into u.cl */
  int nArg;
  int iQuery;
  const sqlite3_module *pModule;
  Mem *pQuery;
  Mem *pArgc;
  sqlite3_vtab_cursor *pVtabCursor;
  sqlite3_vtab *pVtab;
  VdbeCursor *pCur;
  int res;
  int i;
  Mem **apArg;
#endif /* local variables moved into u.cl */

  u.cl.pQuery = &aMem[pOp->p3];
  u.cl.pArgc = &u.cl.pQuery[1];
  u.cl.pCur = p->apCsr[pOp->p1];
  assert( memIsValid(u.cl.pQuery) );
  REGISTER_TRACE(pOp->p3, u.cl.pQuery);
  assert( u.cl.pCur->pVtabCursor );
  u.cl.pVtabCursor = u.cl.pCur->pVtabCursor;
  u.cl.pVtab = u.cl.pVtabCursor->pVtab;
  u.cl.pModule = u.cl.pVtab->pModule;

  /* Grab the index number and argc parameters */
  assert( (u.cl.pQuery->flags&MEM_Int)!=0 && u.cl.pArgc->flags==MEM_Int );
  u.cl.nArg = (int)u.cl.pArgc->u.i;
  u.cl.iQuery = (int)u.cl.pQuery->u.i;

  /* Invoke the xFilter method */
  {
    u.cl.res = 0;
    u.cl.apArg = p->apArg;
    for(u.cl.i = 0; u.cl.i<u.cl.nArg; u.cl.i++){
      u.cl.apArg[u.cl.i] = &u.cl.pArgc[u.cl.i+1];
      sqlite3VdbeMemStoreType(u.cl.apArg[u.cl.i]);
    }

    p->inVtabMethod = 1;
    rc = u.cl.pModule->xFilter(u.cl.pVtabCursor, u.cl.iQuery, pOp->p4.z, u.cl.nArg, u.cl.apArg);
    p->inVtabMethod = 0;
    importVtabErrMsg(p, u.cl.pVtab);
    if( rc==SQLITE_OK ){
      u.cl.res = u.cl.pModule->xEof(u.cl.pVtabCursor);
    }

    if( u.cl.res ){
      pc = pOp->p2 - 1;
    }
  }
  u.cl.pCur->nullRow = 0;

  break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */

#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VColumn P1 P2 P3 * *
**
** Store the value of the P2-th column of
** the row of the virtual-table that the 
** P1 cursor is pointing to into register P3.
*/
case OP_VColumn: {
#if 0  /* local variables moved into u.cm */
  sqlite3_vtab *pVtab;
  const sqlite3_module *pModule;
  Mem *pDest;
  sqlite3_context sContext;
#endif /* local variables moved into u.cm */

  VdbeCursor *pCur = p->apCsr[pOp->p1];
  assert( pCur->pVtabCursor );
  assert( pOp->p3>0 && pOp->p3<=p->nMem );
  u.cm.pDest = &aMem[pOp->p3];
  memAboutToChange(p, u.cm.pDest);
  if( pCur->nullRow ){
    sqlite3VdbeMemSetNull(u.cm.pDest);
    break;
  }
  u.cm.pVtab = pCur->pVtabCursor->pVtab;
  u.cm.pModule = u.cm.pVtab->pModule;
  assert( u.cm.pModule->xColumn );
  memset(&u.cm.sContext, 0, sizeof(u.cm.sContext));

  /* The output cell may already have a buffer allocated. Move
  ** the current contents to u.cm.sContext.s so in case the user-function
  ** can use the already allocated buffer instead of allocating a
  ** new one.
  */
  sqlite3VdbeMemMove(&u.cm.sContext.s, u.cm.pDest);
  MemSetTypeFlag(&u.cm.sContext.s, MEM_Null);

  rc = u.cm.pModule->xColumn(pCur->pVtabCursor, &u.cm.sContext, pOp->p2);
  importVtabErrMsg(p, u.cm.pVtab);
  if( u.cm.sContext.isError ){
    rc = u.cm.sContext.isError;
  }

  /* Copy the result of the function to the P3 register. We
  ** do this regardless of whether or not an error occurred to ensure any
  ** dynamic allocation in u.cm.sContext.s (a Mem struct) is  released.
  */
  sqlite3VdbeChangeEncoding(&u.cm.sContext.s, encoding);
  sqlite3VdbeMemMove(u.cm.pDest, &u.cm.sContext.s);
  REGISTER_TRACE(pOp->p3, u.cm.pDest);
  UPDATE_MAX_BLOBSIZE(u.cm.pDest);

  if( sqlite3VdbeMemTooBig(u.cm.pDest) ){
    goto too_big;
  }
  break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */

#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VNext P1 P2 * * *
**
** Advance virtual table P1 to the next row in its result set and
** jump to instruction P2.  Or, if the virtual table has reached
** the end of its result set, then fall through to the next instruction.
*/
case OP_VNext: {   /* jump */
#if 0  /* local variables moved into u.cn */
  sqlite3_vtab *pVtab;
  const sqlite3_module *pModule;
  int res;
  VdbeCursor *pCur;
#endif /* local variables moved into u.cn */

  u.cn.res = 0;
  u.cn.pCur = p->apCsr[pOp->p1];
  assert( u.cn.pCur->pVtabCursor );
  if( u.cn.pCur->nullRow ){
    break;
  }
  u.cn.pVtab = u.cn.pCur->pVtabCursor->pVtab;
  u.cn.pModule = u.cn.pVtab->pModule;
  assert( u.cn.pModule->xNext );

  /* Invoke the xNext() method of the module. There is no way for the
  ** underlying implementation to return an error if one occurs during
  ** xNext(). Instead, if an error occurs, true is returned (indicating that
  ** data is available) and the error code returned when xColumn or
  ** some other method is next invoked on the save virtual table cursor.
  */
  p->inVtabMethod = 1;
  rc = u.cn.pModule->xNext(u.cn.pCur->pVtabCursor);
  p->inVtabMethod = 0;
  importVtabErrMsg(p, u.cn.pVtab);
  if( rc==SQLITE_OK ){
    u.cn.res = u.cn.pModule->xEof(u.cn.pCur->pVtabCursor);
  }

  if( !u.cn.res ){
    /* If there is data, jump to P2 */
    pc = pOp->p2 - 1;
  }
  break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */

#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VRename P1 * * P4 *
**
** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
** This opcode invokes the corresponding xRename method. The value
** in register P1 is passed as the zName argument to the xRename method.
*/
case OP_VRename: {
#if 0  /* local variables moved into u.co */
  sqlite3_vtab *pVtab;
  Mem *pName;
#endif /* local variables moved into u.co */

  u.co.pVtab = pOp->p4.pVtab->pVtab;
  u.co.pName = &aMem[pOp->p1];
  assert( u.co.pVtab->pModule->xRename );
  assert( memIsValid(u.co.pName) );
  REGISTER_TRACE(pOp->p1, u.co.pName);
  assert( u.co.pName->flags & MEM_Str );
  rc = u.co.pVtab->pModule->xRename(u.co.pVtab, u.co.pName->z);
  importVtabErrMsg(p, u.co.pVtab);
  p->expired = 0;

  break;
}
#endif

#ifndef SQLITE_OMIT_VIRTUALTABLE







|











|

|
|
|
|
|
|
|
|
|


|
|
|



|
|
|
|
|



|

|

|


|



|













|




|




|
|

|


|
|
|
|


|



|
|

|
|
|
|




|

|
|
|
|

|














|




|

|
|
|
|


|
|
|








|

|

|


|















|


|

|
|
|
|
|
|
|
|







68450
68451
68452
68453
68454
68455
68456
68457
68458
68459
68460
68461
68462
68463
68464
68465
68466
68467
68468
68469
68470
68471
68472
68473
68474
68475
68476
68477
68478
68479
68480
68481
68482
68483
68484
68485
68486
68487
68488
68489
68490
68491
68492
68493
68494
68495
68496
68497
68498
68499
68500
68501
68502
68503
68504
68505
68506
68507
68508
68509
68510
68511
68512
68513
68514
68515
68516
68517
68518
68519
68520
68521
68522
68523
68524
68525
68526
68527
68528
68529
68530
68531
68532
68533
68534
68535
68536
68537
68538
68539
68540
68541
68542
68543
68544
68545
68546
68547
68548
68549
68550
68551
68552
68553
68554
68555
68556
68557
68558
68559
68560
68561
68562
68563
68564
68565
68566
68567
68568
68569
68570
68571
68572
68573
68574
68575
68576
68577
68578
68579
68580
68581
68582
68583
68584
68585
68586
68587
68588
68589
68590
68591
68592
68593
68594
68595
68596
68597
68598
68599
68600
68601
68602
68603
68604
68605
68606
68607
68608
68609
68610
68611
68612
68613
68614
68615
68616
68617
68618
68619
68620
68621
68622
68623
68624
68625
68626
68627
68628
68629
68630
68631
68632
68633
68634
68635
68636
68637
68638
68639
68640
68641
68642
68643
68644
68645
68646
** xFilter method. Registers P3+2..P3+1+argc are the argc
** additional parameters which are passed to
** xFilter as argv. Register P3+2 becomes argv[0] when passed to xFilter.
**
** A jump is made to P2 if the result set after filtering would be empty.
*/
case OP_VFilter: {   /* jump */
#if 0  /* local variables moved into u.ci */
  int nArg;
  int iQuery;
  const sqlite3_module *pModule;
  Mem *pQuery;
  Mem *pArgc;
  sqlite3_vtab_cursor *pVtabCursor;
  sqlite3_vtab *pVtab;
  VdbeCursor *pCur;
  int res;
  int i;
  Mem **apArg;
#endif /* local variables moved into u.ci */

  u.ci.pQuery = &aMem[pOp->p3];
  u.ci.pArgc = &u.ci.pQuery[1];
  u.ci.pCur = p->apCsr[pOp->p1];
  assert( memIsValid(u.ci.pQuery) );
  REGISTER_TRACE(pOp->p3, u.ci.pQuery);
  assert( u.ci.pCur->pVtabCursor );
  u.ci.pVtabCursor = u.ci.pCur->pVtabCursor;
  u.ci.pVtab = u.ci.pVtabCursor->pVtab;
  u.ci.pModule = u.ci.pVtab->pModule;

  /* Grab the index number and argc parameters */
  assert( (u.ci.pQuery->flags&MEM_Int)!=0 && u.ci.pArgc->flags==MEM_Int );
  u.ci.nArg = (int)u.ci.pArgc->u.i;
  u.ci.iQuery = (int)u.ci.pQuery->u.i;

  /* Invoke the xFilter method */
  {
    u.ci.res = 0;
    u.ci.apArg = p->apArg;
    for(u.ci.i = 0; u.ci.i<u.ci.nArg; u.ci.i++){
      u.ci.apArg[u.ci.i] = &u.ci.pArgc[u.ci.i+1];
      sqlite3VdbeMemStoreType(u.ci.apArg[u.ci.i]);
    }

    p->inVtabMethod = 1;
    rc = u.ci.pModule->xFilter(u.ci.pVtabCursor, u.ci.iQuery, pOp->p4.z, u.ci.nArg, u.ci.apArg);
    p->inVtabMethod = 0;
    importVtabErrMsg(p, u.ci.pVtab);
    if( rc==SQLITE_OK ){
      u.ci.res = u.ci.pModule->xEof(u.ci.pVtabCursor);
    }

    if( u.ci.res ){
      pc = pOp->p2 - 1;
    }
  }
  u.ci.pCur->nullRow = 0;

  break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */

#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VColumn P1 P2 P3 * *
**
** Store the value of the P2-th column of
** the row of the virtual-table that the 
** P1 cursor is pointing to into register P3.
*/
case OP_VColumn: {
#if 0  /* local variables moved into u.cj */
  sqlite3_vtab *pVtab;
  const sqlite3_module *pModule;
  Mem *pDest;
  sqlite3_context sContext;
#endif /* local variables moved into u.cj */

  VdbeCursor *pCur = p->apCsr[pOp->p1];
  assert( pCur->pVtabCursor );
  assert( pOp->p3>0 && pOp->p3<=p->nMem );
  u.cj.pDest = &aMem[pOp->p3];
  memAboutToChange(p, u.cj.pDest);
  if( pCur->nullRow ){
    sqlite3VdbeMemSetNull(u.cj.pDest);
    break;
  }
  u.cj.pVtab = pCur->pVtabCursor->pVtab;
  u.cj.pModule = u.cj.pVtab->pModule;
  assert( u.cj.pModule->xColumn );
  memset(&u.cj.sContext, 0, sizeof(u.cj.sContext));

  /* The output cell may already have a buffer allocated. Move
  ** the current contents to u.cj.sContext.s so in case the user-function
  ** can use the already allocated buffer instead of allocating a
  ** new one.
  */
  sqlite3VdbeMemMove(&u.cj.sContext.s, u.cj.pDest);
  MemSetTypeFlag(&u.cj.sContext.s, MEM_Null);

  rc = u.cj.pModule->xColumn(pCur->pVtabCursor, &u.cj.sContext, pOp->p2);
  importVtabErrMsg(p, u.cj.pVtab);
  if( u.cj.sContext.isError ){
    rc = u.cj.sContext.isError;
  }

  /* Copy the result of the function to the P3 register. We
  ** do this regardless of whether or not an error occurred to ensure any
  ** dynamic allocation in u.cj.sContext.s (a Mem struct) is  released.
  */
  sqlite3VdbeChangeEncoding(&u.cj.sContext.s, encoding);
  sqlite3VdbeMemMove(u.cj.pDest, &u.cj.sContext.s);
  REGISTER_TRACE(pOp->p3, u.cj.pDest);
  UPDATE_MAX_BLOBSIZE(u.cj.pDest);

  if( sqlite3VdbeMemTooBig(u.cj.pDest) ){
    goto too_big;
  }
  break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */

#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VNext P1 P2 * * *
**
** Advance virtual table P1 to the next row in its result set and
** jump to instruction P2.  Or, if the virtual table has reached
** the end of its result set, then fall through to the next instruction.
*/
case OP_VNext: {   /* jump */
#if 0  /* local variables moved into u.ck */
  sqlite3_vtab *pVtab;
  const sqlite3_module *pModule;
  int res;
  VdbeCursor *pCur;
#endif /* local variables moved into u.ck */

  u.ck.res = 0;
  u.ck.pCur = p->apCsr[pOp->p1];
  assert( u.ck.pCur->pVtabCursor );
  if( u.ck.pCur->nullRow ){
    break;
  }
  u.ck.pVtab = u.ck.pCur->pVtabCursor->pVtab;
  u.ck.pModule = u.ck.pVtab->pModule;
  assert( u.ck.pModule->xNext );

  /* Invoke the xNext() method of the module. There is no way for the
  ** underlying implementation to return an error if one occurs during
  ** xNext(). Instead, if an error occurs, true is returned (indicating that
  ** data is available) and the error code returned when xColumn or
  ** some other method is next invoked on the save virtual table cursor.
  */
  p->inVtabMethod = 1;
  rc = u.ck.pModule->xNext(u.ck.pCur->pVtabCursor);
  p->inVtabMethod = 0;
  importVtabErrMsg(p, u.ck.pVtab);
  if( rc==SQLITE_OK ){
    u.ck.res = u.ck.pModule->xEof(u.ck.pCur->pVtabCursor);
  }

  if( !u.ck.res ){
    /* If there is data, jump to P2 */
    pc = pOp->p2 - 1;
  }
  break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */

#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VRename P1 * * P4 *
**
** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
** This opcode invokes the corresponding xRename method. The value
** in register P1 is passed as the zName argument to the xRename method.
*/
case OP_VRename: {
#if 0  /* local variables moved into u.cl */
  sqlite3_vtab *pVtab;
  Mem *pName;
#endif /* local variables moved into u.cl */

  u.cl.pVtab = pOp->p4.pVtab->pVtab;
  u.cl.pName = &aMem[pOp->p1];
  assert( u.cl.pVtab->pModule->xRename );
  assert( memIsValid(u.cl.pName) );
  REGISTER_TRACE(pOp->p1, u.cl.pName);
  assert( u.cl.pName->flags & MEM_Str );
  rc = u.cl.pVtab->pModule->xRename(u.cl.pVtab, u.cl.pName->z);
  importVtabErrMsg(p, u.cl.pVtab);
  p->expired = 0;

  break;
}
#endif

#ifndef SQLITE_OMIT_VIRTUALTABLE
69561
69562
69563
69564
69565
69566
69567
69568
69569
69570
69571
69572
69573
69574
69575
69576
69577
69578
69579
69580
69581
69582
69583
69584
69585
69586
69587
69588
69589
69590
69591
69592
69593
69594
69595
69596
69597
69598
69599
69600
69601
69602
69603
69604
69605
69606
69607
69608
69609
** a row to delete.
**
** P1 is a boolean flag. If it is set to true and the xUpdate call
** is successful, then the value returned by sqlite3_last_insert_rowid() 
** is set to the value of the rowid for the row just inserted.
*/
case OP_VUpdate: {
#if 0  /* local variables moved into u.cp */
  sqlite3_vtab *pVtab;
  sqlite3_module *pModule;
  int nArg;
  int i;
  sqlite_int64 rowid;
  Mem **apArg;
  Mem *pX;
#endif /* local variables moved into u.cp */

  assert( pOp->p2==1        || pOp->p5==OE_Fail   || pOp->p5==OE_Rollback
       || pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace
  );
  u.cp.pVtab = pOp->p4.pVtab->pVtab;
  u.cp.pModule = (sqlite3_module *)u.cp.pVtab->pModule;
  u.cp.nArg = pOp->p2;
  assert( pOp->p4type==P4_VTAB );
  if( ALWAYS(u.cp.pModule->xUpdate) ){
    u8 vtabOnConflict = db->vtabOnConflict;
    u.cp.apArg = p->apArg;
    u.cp.pX = &aMem[pOp->p3];
    for(u.cp.i=0; u.cp.i<u.cp.nArg; u.cp.i++){
      assert( memIsValid(u.cp.pX) );
      memAboutToChange(p, u.cp.pX);
      sqlite3VdbeMemStoreType(u.cp.pX);
      u.cp.apArg[u.cp.i] = u.cp.pX;
      u.cp.pX++;
    }
    db->vtabOnConflict = pOp->p5;
    rc = u.cp.pModule->xUpdate(u.cp.pVtab, u.cp.nArg, u.cp.apArg, &u.cp.rowid);
    db->vtabOnConflict = vtabOnConflict;
    importVtabErrMsg(p, u.cp.pVtab);
    if( rc==SQLITE_OK && pOp->p1 ){
      assert( u.cp.nArg>1 && u.cp.apArg[0] && (u.cp.apArg[0]->flags&MEM_Null) );
      db->lastRowid = lastRowid = u.cp.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);
      }







|







|




|
|
|

|

|
|
|
|
|
|
|
|


|

|

|
|







68664
68665
68666
68667
68668
68669
68670
68671
68672
68673
68674
68675
68676
68677
68678
68679
68680
68681
68682
68683
68684
68685
68686
68687
68688
68689
68690
68691
68692
68693
68694
68695
68696
68697
68698
68699
68700
68701
68702
68703
68704
68705
68706
68707
68708
68709
68710
68711
68712
** a row to delete.
**
** P1 is a boolean flag. If it is set to true and the xUpdate call
** is successful, then the value returned by sqlite3_last_insert_rowid() 
** is set to the value of the rowid for the row just inserted.
*/
case OP_VUpdate: {
#if 0  /* local variables moved into u.cm */
  sqlite3_vtab *pVtab;
  sqlite3_module *pModule;
  int nArg;
  int i;
  sqlite_int64 rowid;
  Mem **apArg;
  Mem *pX;
#endif /* local variables moved into u.cm */

  assert( pOp->p2==1        || pOp->p5==OE_Fail   || pOp->p5==OE_Rollback
       || pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace
  );
  u.cm.pVtab = pOp->p4.pVtab->pVtab;
  u.cm.pModule = (sqlite3_module *)u.cm.pVtab->pModule;
  u.cm.nArg = pOp->p2;
  assert( pOp->p4type==P4_VTAB );
  if( ALWAYS(u.cm.pModule->xUpdate) ){
    u8 vtabOnConflict = db->vtabOnConflict;
    u.cm.apArg = p->apArg;
    u.cm.pX = &aMem[pOp->p3];
    for(u.cm.i=0; u.cm.i<u.cm.nArg; u.cm.i++){
      assert( memIsValid(u.cm.pX) );
      memAboutToChange(p, u.cm.pX);
      sqlite3VdbeMemStoreType(u.cm.pX);
      u.cm.apArg[u.cm.i] = u.cm.pX;
      u.cm.pX++;
    }
    db->vtabOnConflict = pOp->p5;
    rc = u.cm.pModule->xUpdate(u.cm.pVtab, u.cm.nArg, u.cm.apArg, &u.cm.rowid);
    db->vtabOnConflict = vtabOnConflict;
    importVtabErrMsg(p, u.cm.pVtab);
    if( rc==SQLITE_OK && pOp->p1 ){
      assert( u.cm.nArg>1 && u.cm.apArg[0] && (u.cm.apArg[0]->flags&MEM_Null) );
      db->lastRowid = lastRowid = u.cm.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);
      }
69655
69656
69657
69658
69659
69660
69661
69662
69663
69664
69665
69666
69667
69668
69669
69670
69671
69672
69673
69674
69675
69676
69677
69678
69679
69680
69681
69682
69683
#ifndef SQLITE_OMIT_TRACE
/* Opcode: Trace * * * P4 *
**
** If tracing is enabled (by the sqlite3_trace()) interface, then
** the UTF-8 string contained in P4 is emitted on the trace callback.
*/
case OP_Trace: {
#if 0  /* local variables moved into u.cq */
  char *zTrace;
  char *z;
#endif /* local variables moved into u.cq */

  if( db->xTrace && (u.cq.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0 ){
    u.cq.z = sqlite3VdbeExpandSql(p, u.cq.zTrace);
    db->xTrace(db->pTraceArg, u.cq.z);
    sqlite3DbFree(db, u.cq.z);
  }
#ifdef SQLITE_DEBUG
  if( (db->flags & SQLITE_SqlTrace)!=0
   && (u.cq.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
  ){
    sqlite3DebugPrintf("SQL-trace: %s\n", u.cq.zTrace);
  }
#endif /* SQLITE_DEBUG */
  break;
}
#endif









|


|

|
|
|
|



|

|







68758
68759
68760
68761
68762
68763
68764
68765
68766
68767
68768
68769
68770
68771
68772
68773
68774
68775
68776
68777
68778
68779
68780
68781
68782
68783
68784
68785
68786
#ifndef SQLITE_OMIT_TRACE
/* Opcode: Trace * * * P4 *
**
** If tracing is enabled (by the sqlite3_trace()) interface, then
** the UTF-8 string contained in P4 is emitted on the trace callback.
*/
case OP_Trace: {
#if 0  /* local variables moved into u.cn */
  char *zTrace;
  char *z;
#endif /* local variables moved into u.cn */

  if( db->xTrace && (u.cn.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0 ){
    u.cn.z = sqlite3VdbeExpandSql(p, u.cn.zTrace);
    db->xTrace(db->pTraceArg, u.cn.z);
    sqlite3DbFree(db, u.cn.z);
  }
#ifdef SQLITE_DEBUG
  if( (db->flags & SQLITE_SqlTrace)!=0
   && (u.cn.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
  ){
    sqlite3DebugPrintf("SQL-trace: %s\n", u.cn.zTrace);
  }
#endif /* SQLITE_DEBUG */
  break;
}
#endif


70072
70073
70074
70075
70076
70077
70078
70079
70080
70081
70082
70083
70084
70085
70086
70087
70088
70089
70090
70091
70092
70093
70094
70095
70096
      sqlite3VdbeChangeP3(v, 1, pTab->pSchema->iGeneration);

      /* Make sure a mutex is held on the table to be accessed */
      sqlite3VdbeUsesBtree(v, iDb); 

      /* Configure the OP_TableLock instruction */
#ifdef SQLITE_OMIT_SHARED_CACHE
      sqlite3VdbeChangeToNoop(v, 2);
#else
      sqlite3VdbeChangeP1(v, 2, iDb);
      sqlite3VdbeChangeP2(v, 2, pTab->tnum);
      sqlite3VdbeChangeP3(v, 2, flags);
      sqlite3VdbeChangeP4(v, 2, pTab->zName, P4_TRANSIENT);
#endif

      /* Remove either the OP_OpenWrite or OpenRead. Set the P2 
      ** parameter of the other to pTab->tnum.  */
      sqlite3VdbeChangeToNoop(v, 4 - flags);
      sqlite3VdbeChangeP2(v, 3 + flags, pTab->tnum);
      sqlite3VdbeChangeP3(v, 3 + flags, iDb);

      /* Configure the number of columns. Configure the cursor to
      ** think that the table has one more column than it really
      ** does. An OP_Column to retrieve this imaginary column will
      ** always return an SQL NULL. This is useful because it means







|









|







69175
69176
69177
69178
69179
69180
69181
69182
69183
69184
69185
69186
69187
69188
69189
69190
69191
69192
69193
69194
69195
69196
69197
69198
69199
      sqlite3VdbeChangeP3(v, 1, pTab->pSchema->iGeneration);

      /* Make sure a mutex is held on the table to be accessed */
      sqlite3VdbeUsesBtree(v, iDb); 

      /* Configure the OP_TableLock instruction */
#ifdef SQLITE_OMIT_SHARED_CACHE
      sqlite3VdbeChangeToNoop(v, 2, 1);
#else
      sqlite3VdbeChangeP1(v, 2, iDb);
      sqlite3VdbeChangeP2(v, 2, pTab->tnum);
      sqlite3VdbeChangeP3(v, 2, flags);
      sqlite3VdbeChangeP4(v, 2, pTab->zName, P4_TRANSIENT);
#endif

      /* Remove either the OP_OpenWrite or OpenRead. Set the P2 
      ** parameter of the other to pTab->tnum.  */
      sqlite3VdbeChangeToNoop(v, 4 - flags, 1);
      sqlite3VdbeChangeP2(v, 3 + flags, pTab->tnum);
      sqlite3VdbeChangeP3(v, 3 + flags, iDb);

      /* Configure the number of columns. Configure the cursor to
      ** think that the table has one more column than it really
      ** does. An OP_Column to retrieve this imaginary column will
      ** always return an SQL NULL. This is useful because it means
70268
70269
70270
70271
70272
70273
70274
70275
70276
70277
70278
70279
70280
70281
70282
70283
70284
70285
70286
70287
70288
70289
70290
70291
70292
70293
70294
70295
70296
70297
70298
70299
70300
70301
70302
70303
70304
70305
70306
70307
70308
70309
70310
70311
70312
70313
70314
70315
70316
70317
70318
70319
70320
70321
70322
70323
70324
70325
70326
70327
70328
70329
70330
70331
70332
70333
70334
70335
70336
70337
70338
70339
70340
70341
70342
70343
70344
70345
70346
70347
70348
70349
70350
70351
70352
70353
70354
70355
70356
70357
70358
70359
70360
70361
70362
70363
70364
70365
70366
70367
70368
70369
70370
70371
70372
70373
70374
70375
70376
70377
70378
70379
70380
70381
70382
70383
70384
70385
70386
70387
70388
70389
70390
70391
70392
70393
70394
70395
70396
70397
70398
70399
70400
70401
70402
70403
70404
70405
70406
70407
70408
70409
70410
70411
70412
70413
70414
70415
70416
70417
70418
70419
70420
70421
70422
70423
70424
70425
70426
70427
70428
70429
70430
70431
70432
70433
70434
70435
70436
70437
70438
70439
70440
70441
70442
70443
70444
70445
70446
70447
70448
70449
70450
70451
70452
70453
70454
70455
70456
70457
70458
70459
70460
70461
70462
70463
70464
70465
70466
70467
70468
70469
70470
70471
70472
70473
70474
70475
70476
70477
70478
70479
70480
70481
70482
70483
70484
70485
70486
70487
70488
70489
70490
70491
70492
70493
70494
70495
70496
70497
70498
70499
70500
70501
70502
70503
70504
70505
70506
70507
70508
70509
70510
70511
70512
70513
70514
70515
70516
70517
70518
70519
70520
70521
70522
70523
70524
70525
70526
70527
70528
70529
70530
70531
70532
70533
70534
70535
70536
70537
70538
70539
70540
70541
70542
70543
70544
70545
70546
70547
70548
70549
70550
70551
70552
70553
70554
70555
70556
70557
70558
70559
70560
70561
70562
70563
70564
70565
70566
70567
70568
70569
70570
70571
70572
70573
70574
70575
70576
70577
70578
70579
70580
70581
70582
70583
70584
70585
70586
70587
70588
70589
70590
70591
70592
70593
70594
70595
70596
70597
70598
70599
70600
70601
70602
70603
70604
70605
70606
70607
70608
70609
70610
70611
70612
70613
70614
70615
70616
70617
70618
70619
70620
70621
70622
70623
70624
70625
70626
70627
70628
70629
70630
70631
70632
70633
70634
70635
70636
70637
70638
70639
70640
70641
70642
70643
70644
70645
70646
70647
70648
70649
70650
70651
70652
70653
70654
70655
70656
70657
70658
70659
70660
70661
70662
70663
70664
70665
70666
70667
70668
70669
70670
70671
70672
70673
70674
70675
70676
70677
70678
70679
70680
70681
70682
70683
70684
70685
70686
70687
70688
70689
70690
70691
70692
70693
70694
70695
70696
70697
70698
70699
70700
70701
70702
70703
70704
70705
70706
70707
70708
70709
70710
70711
70712
70713
70714
70715
70716
70717
70718
70719
70720
70721
70722
70723
70724
70725
70726
70727
70728
70729
70730
70731
70732
70733
70734
70735
70736
70737
70738
70739
70740
70741
70742
70743
70744
70745
70746
70747
70748
70749
70750
70751
70752
70753
70754
70755
70756
70757
70758
70759
70760
70761
70762
70763
70764
70765
70766
70767
70768
70769
70770
70771
70772
70773
70774
70775
70776
70777
70778
70779
70780
70781
70782
70783
70784
70785
70786
70787
70788
70789
70790
70791
70792
70793
70794
70795
70796
70797
70798
70799
70800
70801
70802
70803
70804
70805
70806
70807
70808
70809
70810
70811
70812
70813
70814
70815
70816
70817
70818
70819
70820
70821
70822
70823
70824
70825
70826
70827
70828
70829
70830
70831
70832
70833
70834
70835
70836
70837
70838
70839
70840
70841
70842
70843
70844
70845
70846
70847
70848
70849
70850
70851
70852
70853
70854
70855
70856
70857
70858
70859
70860
70861
70862
70863
70864
70865
70866
70867
70868
70869
70870
70871
70872
70873
70874
70875
70876
70877
70878
70879
70880
70881
70882
70883
70884
70885
70886
70887
70888
70889
70890
70891
70892
70893
70894
70895
70896
70897
70898
70899
70900
70901
70902
70903
70904
70905
70906
70907
70908
70909
70910
70911
70912
70913
70914
70915
70916
70917
70918
70919
70920
70921
70922
70923
70924
70925
70926
70927
70928
70929
70930
70931
70932
70933
70934
70935
70936
70937
70938
70939
70940
70941
70942
70943
70944
70945
70946
70947
70948
70949
70950
70951
70952
70953
70954
70955
70956
70957
70958
70959
70960
70961
70962
70963
70964
70965
70966
70967
70968
70969
70970
70971
70972
70973
70974
70975
70976
70977
70978
70979
70980
70981
70982
70983
70984
70985
70986
70987
70988
70989
70990
70991
70992
70993
70994
70995
70996
70997
70998
70999
71000
71001
71002
71003
71004
71005
71006
71007
71008
71009
71010
71011
71012
71013
71014
71015
71016
71017
71018
71019
71020
71021
71022
71023
71024
71025
71026
71027
71028
71029
71030
71031
71032
71033
71034
71035
71036
71037
71038
71039
71040
71041
71042
71043
71044
71045
71046
71047
71048
71049
71050
71051
71052
71053
71054
71055
71056
71057
71058
71059
71060
71061
71062
71063
71064
71065
71066
71067
71068
71069
71070
71071
71072
71073
71074
71075
71076
71077
71078
71079
71080
71081
71082
71083
71084
71085
71086
71087
71088
71089
71090
71091
71092
71093
71094
71095
71096
71097
71098
71099
71100
71101
71102
71103
71104
71105
71106
71107
71108
71109
71110
71111
71112
71113
71114
71115
71116
71117
71118
71119
71120
71121
71122
71123
71124
71125
71126
71127
71128
71129
71130
71131
71132
71133
71134
71135
71136
71137
71138
71139
71140
71141
71142
71143
71144
71145
71146
71147
71148
71149
71150
71151
71152
71153
71154
71155
71156
71157
71158
71159
71160
71161
71162
71163
71164
  sqlite3_mutex_leave(db->mutex);
  return rc;
}

#endif /* #ifndef SQLITE_OMIT_INCRBLOB */

/************** End of vdbeblob.c ********************************************/
/************** Begin file vdbesort.c ****************************************/
/*
** 2011 July 9
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code for the VdbeSorter object, used in concert with
** a VdbeCursor to sort large numbers of keys (as may be required, for
** example, by CREATE INDEX statements on tables too large to fit in main
** memory).
*/


#ifndef SQLITE_OMIT_MERGE_SORT

typedef struct VdbeSorterIter VdbeSorterIter;
typedef struct SorterRecord SorterRecord;

/*
** NOTES ON DATA STRUCTURE USED FOR N-WAY MERGES:
**
** As keys are added to the sorter, they are written to disk in a series
** of sorted packed-memory-arrays (PMAs). The size of each PMA is roughly
** the same as the cache-size allowed for temporary databases. In order
** to allow the caller to extract keys from the sorter in sorted order,
** all PMAs currently stored on disk must be merged together. This comment
** describes the data structure used to do so. The structure supports 
** merging any number of arrays in a single pass with no redundant comparison 
** operations.
**
** The aIter[] array contains an iterator for each of the PMAs being merged.
** An aIter[] iterator either points to a valid key or else is at EOF. For 
** the purposes of the paragraphs below, we assume that the array is actually 
** N elements in size, where N is the smallest power of 2 greater to or equal 
** to the number of iterators being merged. The extra aIter[] elements are 
** treated as if they are empty (always at EOF).
**
** The aTree[] array is also N elements in size. The value of N is stored in
** the VdbeSorter.nTree variable.
**
** The final (N/2) elements of aTree[] contain the results of comparing
** pairs of iterator keys together. Element i contains the result of 
** comparing aIter[2*i-N] and aIter[2*i-N+1]. Whichever key is smaller, the
** aTree element is set to the index of it. 
**
** For the purposes of this comparison, EOF is considered greater than any
** other key value. If the keys are equal (only possible with two EOF
** values), it doesn't matter which index is stored.
**
** The (N/4) elements of aTree[] that preceed the final (N/2) described 
** above contains the index of the smallest of each block of 4 iterators.
** And so on. So that aTree[1] contains the index of the iterator that 
** currently points to the smallest key value. aTree[0] is unused.
**
** Example:
**
**     aIter[0] -> Banana
**     aIter[1] -> Feijoa
**     aIter[2] -> Elderberry
**     aIter[3] -> Currant
**     aIter[4] -> Grapefruit
**     aIter[5] -> Apple
**     aIter[6] -> Durian
**     aIter[7] -> EOF
**
**     aTree[] = { X, 5   0, 5    0, 3, 5, 6 }
**
** The current element is "Apple" (the value of the key indicated by 
** iterator 5). When the Next() operation is invoked, iterator 5 will
** be advanced to the next key in its segment. Say the next key is
** "Eggplant":
**
**     aIter[5] -> Eggplant
**
** The contents of aTree[] are updated first by comparing the new iterator
** 5 key to the current key of iterator 4 (still "Grapefruit"). The iterator
** 5 value is still smaller, so aTree[6] is set to 5. And so on up the tree.
** The value of iterator 6 - "Durian" - is now smaller than that of iterator
** 5, so aTree[3] is set to 6. Key 0 is smaller than key 6 (Banana<Durian),
** so the value written into element 1 of the array is 0. As follows:
**
**     aTree[] = { X, 0   0, 6    0, 3, 5, 6 }
**
** In other words, each time we advance to the next sorter element, log2(N)
** key comparison operations are required, where N is the number of segments
** being merged (rounded up to the next power of 2).
*/
struct VdbeSorter {
  int nInMemory;                  /* Current size of pRecord list as PMA */
  int nTree;                      /* Used size of aTree/aIter (power of 2) */
  VdbeSorterIter *aIter;          /* Array of iterators to merge */
  int *aTree;                     /* Current state of incremental merge */
  i64 iWriteOff;                  /* Current write offset within file pTemp1 */
  i64 iReadOff;                   /* Current read offset within file pTemp1 */
  sqlite3_file *pTemp1;           /* PMA file 1 */
  int nPMA;                       /* Number of PMAs stored in pTemp1 */
  SorterRecord *pRecord;          /* Head of in-memory record list */
  int mnPmaSize;                  /* Minimum PMA size, in bytes */
  int mxPmaSize;                  /* Maximum PMA size, in bytes.  0==no limit */
  UnpackedRecord *pUnpacked;      /* Used to unpack keys */
};

/*
** The following type is an iterator for a PMA. It caches the current key in 
** variables nKey/aKey. If the iterator is at EOF, pFile==0.
*/
struct VdbeSorterIter {
  i64 iReadOff;                   /* Current read offset */
  i64 iEof;                       /* 1 byte past EOF for this iterator */
  sqlite3_file *pFile;            /* File iterator is reading from */
  int nAlloc;                     /* Bytes of space at aAlloc */
  u8 *aAlloc;                     /* Allocated space */
  int nKey;                       /* Number of bytes in key */
  u8 *aKey;                       /* Pointer to current key */
};

/*
** A structure to store a single record. All in-memory records are connected
** together into a linked list headed at VdbeSorter.pRecord using the 
** SorterRecord.pNext pointer.
*/
struct SorterRecord {
  void *pVal;
  int nVal;
  SorterRecord *pNext;
};

/* Minimum allowable value for the VdbeSorter.nWorking variable */
#define SORTER_MIN_WORKING 10

/* Maximum number of segments to merge in a single pass. */
#define SORTER_MAX_MERGE_COUNT 16

/*
** Free all memory belonging to the VdbeSorterIter object passed as the second
** argument. All structure fields are set to zero before returning.
*/
static void vdbeSorterIterZero(sqlite3 *db, VdbeSorterIter *pIter){
  sqlite3DbFree(db, pIter->aAlloc);
  memset(pIter, 0, sizeof(VdbeSorterIter));
}

/*
** Advance iterator pIter to the next key in its PMA. Return SQLITE_OK if
** no error occurs, or an SQLite error code if one does.
*/
static int vdbeSorterIterNext(
  sqlite3 *db,                    /* Database handle (for sqlite3DbMalloc() ) */
  VdbeSorterIter *pIter           /* Iterator to advance */
){
  int rc;                         /* Return Code */
  int nRead;                      /* Number of bytes read */
  int nRec = 0;                   /* Size of record in bytes */
  int iOff = 0;                   /* Size of serialized size varint in bytes */

  assert( pIter->iEof>=pIter->iReadOff );
  if( pIter->iEof-pIter->iReadOff>5 ){
    nRead = 5;
  }else{
    nRead = (int)(pIter->iEof - pIter->iReadOff);
  }
  if( nRead<=0 ){
    /* This is an EOF condition */
    vdbeSorterIterZero(db, pIter);
    return SQLITE_OK;
  }

  rc = sqlite3OsRead(pIter->pFile, pIter->aAlloc, nRead, pIter->iReadOff);
  if( rc==SQLITE_OK ){
    iOff = getVarint32(pIter->aAlloc, nRec);
    if( (iOff+nRec)>nRead ){
      int nRead2;                   /* Number of extra bytes to read */
      if( (iOff+nRec)>pIter->nAlloc ){
        int nNew = pIter->nAlloc*2;
        while( (iOff+nRec)>nNew ) nNew = nNew*2;
        pIter->aAlloc = sqlite3DbReallocOrFree(db, pIter->aAlloc, nNew);
        if( !pIter->aAlloc ) return SQLITE_NOMEM;
        pIter->nAlloc = nNew;
      }
  
      nRead2 = iOff + nRec - nRead;
      rc = sqlite3OsRead(
          pIter->pFile, &pIter->aAlloc[nRead], nRead2, pIter->iReadOff+nRead
      );
    }
  }

  assert( rc!=SQLITE_OK || nRec>0 );
  pIter->iReadOff += iOff+nRec;
  pIter->nKey = nRec;
  pIter->aKey = &pIter->aAlloc[iOff];
  return rc;
}

/*
** Write a single varint, value iVal, to file-descriptor pFile. Return
** SQLITE_OK if successful, or an SQLite error code if some error occurs.
**
** The value of *piOffset when this function is called is used as the byte
** offset in file pFile to write to. Before returning, *piOffset is 
** incremented by the number of bytes written.
*/
static int vdbeSorterWriteVarint(
  sqlite3_file *pFile,            /* File to write to */
  i64 iVal,                       /* Value to write as a varint */
  i64 *piOffset                   /* IN/OUT: Write offset in file pFile */
){
  u8 aVarint[9];                  /* Buffer large enough for a varint */
  int nVarint;                    /* Number of used bytes in varint */
  int rc;                         /* Result of write() call */

  nVarint = sqlite3PutVarint(aVarint, iVal);
  rc = sqlite3OsWrite(pFile, aVarint, nVarint, *piOffset);
  *piOffset += nVarint;

  return rc;
}

/*
** Read a single varint from file-descriptor pFile. Return SQLITE_OK if
** successful, or an SQLite error code if some error occurs.
**
** The value of *piOffset when this function is called is used as the
** byte offset in file pFile from whence to read the varint. If successful
** (i.e. if no IO error occurs), then *piOffset is set to the offset of
** the first byte past the end of the varint before returning. *piVal is
** set to the integer value read. If an error occurs, the final values of
** both *piOffset and *piVal are undefined.
*/
static int vdbeSorterReadVarint(
  sqlite3_file *pFile,            /* File to read from */
  i64 *piOffset,                  /* IN/OUT: Read offset in pFile */
  i64 *piVal                      /* OUT: Value read from file */
){
  u8 aVarint[9];                  /* Buffer large enough for a varint */
  i64 iOff = *piOffset;           /* Offset in file to read from */
  int rc;                         /* Return code */

  rc = sqlite3OsRead(pFile, aVarint, 9, iOff);
  if( rc==SQLITE_OK ){
    *piOffset += getVarint(aVarint, (u64 *)piVal);
  }

  return rc;
}

/*
** Initialize iterator pIter to scan through the PMA stored in file pFile
** starting at offset iStart and ending at offset iEof-1. This function 
** leaves the iterator pointing to the first key in the PMA (or EOF if the 
** PMA is empty).
*/
static int vdbeSorterIterInit(
  sqlite3 *db,                    /* Database handle */
  VdbeSorter *pSorter,            /* Sorter object */
  i64 iStart,                     /* Start offset in pFile */
  VdbeSorterIter *pIter,          /* Iterator to populate */
  i64 *pnByte                     /* IN/OUT: Increment this value by PMA size */
){
  int rc;

  assert( pSorter->iWriteOff>iStart );
  assert( pIter->aAlloc==0 );
  pIter->pFile = pSorter->pTemp1;
  pIter->iReadOff = iStart;
  pIter->nAlloc = 128;
  pIter->aAlloc = (u8 *)sqlite3DbMallocRaw(db, pIter->nAlloc);
  if( !pIter->aAlloc ){
    rc = SQLITE_NOMEM;
  }else{
    i64 nByte;                         /* Total size of PMA in bytes */
    rc = vdbeSorterReadVarint(pSorter->pTemp1, &pIter->iReadOff, &nByte);
    *pnByte += nByte;
    pIter->iEof = pIter->iReadOff + nByte;
  }
  if( rc==SQLITE_OK ){
    rc = vdbeSorterIterNext(db, pIter);
  }
  return rc;
}


/*
** Compare key1 (buffer pKey1, size nKey1 bytes) with key2 (buffer pKey2, 
** size nKey2 bytes).  Argument pKeyInfo supplies the collation functions
** used by the comparison. If an error occurs, return an SQLite error code.
** Otherwise, return SQLITE_OK and set *pRes to a negative, zero or positive
** value, depending on whether key1 is smaller, equal to or larger than key2.
**
** If the bOmitRowid argument is non-zero, assume both keys end in a rowid
** field. For the purposes of the comparison, ignore it. Also, if bOmitRowid
** is true and key1 contains even a single NULL value, it is considered to
** be less than key2. Even if key2 also contains NULL values.
**
** If pKey2 is passed a NULL pointer, then it is assumed that the pCsr->aSpace
** has been allocated and contains an unpacked record that is used as key2.
*/
static void vdbeSorterCompare(
  VdbeCursor *pCsr,               /* Cursor object (for pKeyInfo) */
  int bOmitRowid,                 /* Ignore rowid field at end of keys */
  void *pKey1, int nKey1,         /* Left side of comparison */
  void *pKey2, int nKey2,         /* Right side of comparison */
  int *pRes                       /* OUT: Result of comparison */
){
  KeyInfo *pKeyInfo = pCsr->pKeyInfo;
  VdbeSorter *pSorter = pCsr->pSorter;
  UnpackedRecord *r2 = pSorter->pUnpacked;
  int i;

  if( pKey2 ){
    sqlite3VdbeRecordUnpack(pKeyInfo, nKey2, pKey2, r2);
  }

  if( bOmitRowid ){
    r2->nField = pKeyInfo->nField;
    assert( r2->nField>0 );
    for(i=0; i<r2->nField; i++){
      if( r2->aMem[i].flags & MEM_Null ){
        *pRes = -1;
        return;
      }
    }
    r2->flags |= UNPACKED_PREFIX_MATCH;
  }

  *pRes = sqlite3VdbeRecordCompare(nKey1, pKey1, r2);
}

/*
** This function is called to compare two iterator keys when merging 
** multiple b-tree segments. Parameter iOut is the index of the aTree[] 
** value to recalculate.
*/
static int vdbeSorterDoCompare(VdbeCursor *pCsr, int iOut){
  VdbeSorter *pSorter = pCsr->pSorter;
  int i1;
  int i2;
  int iRes;
  VdbeSorterIter *p1;
  VdbeSorterIter *p2;

  assert( iOut<pSorter->nTree && iOut>0 );

  if( iOut>=(pSorter->nTree/2) ){
    i1 = (iOut - pSorter->nTree/2) * 2;
    i2 = i1 + 1;
  }else{
    i1 = pSorter->aTree[iOut*2];
    i2 = pSorter->aTree[iOut*2+1];
  }

  p1 = &pSorter->aIter[i1];
  p2 = &pSorter->aIter[i2];

  if( p1->pFile==0 ){
    iRes = i2;
  }else if( p2->pFile==0 ){
    iRes = i1;
  }else{
    int res;
    assert( pCsr->pSorter->pUnpacked!=0 );  /* allocated in vdbeSorterMerge() */
    vdbeSorterCompare(
        pCsr, 0, p1->aKey, p1->nKey, p2->aKey, p2->nKey, &res
    );
    if( res<=0 ){
      iRes = i1;
    }else{
      iRes = i2;
    }
  }

  pSorter->aTree[iOut] = iRes;
  return SQLITE_OK;
}

/*
** Initialize the temporary index cursor just opened as a sorter cursor.
*/
SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *db, VdbeCursor *pCsr){
  int pgsz;                       /* Page size of main database */
  int mxCache;                    /* Cache size */
  VdbeSorter *pSorter;            /* The new sorter */
  char *d;                        /* Dummy */

  assert( pCsr->pKeyInfo && pCsr->pBt==0 );
  pCsr->pSorter = pSorter = sqlite3DbMallocZero(db, sizeof(VdbeSorter));
  if( pSorter==0 ){
    return SQLITE_NOMEM;
  }
  
  pSorter->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pCsr->pKeyInfo, 0, 0, &d);
  if( pSorter->pUnpacked==0 ) return SQLITE_NOMEM;
  assert( pSorter->pUnpacked==(UnpackedRecord *)d );

  if( !sqlite3TempInMemory(db) ){
    pgsz = sqlite3BtreeGetPageSize(db->aDb[0].pBt);
    pSorter->mnPmaSize = SORTER_MIN_WORKING * pgsz;
    mxCache = db->aDb[0].pSchema->cache_size;
    if( mxCache<SORTER_MIN_WORKING ) mxCache = SORTER_MIN_WORKING;
    pSorter->mxPmaSize = mxCache * pgsz;
  }

  return SQLITE_OK;
}

/*
** Free the list of sorted records starting at pRecord.
*/
static void vdbeSorterRecordFree(sqlite3 *db, SorterRecord *pRecord){
  SorterRecord *p;
  SorterRecord *pNext;
  for(p=pRecord; p; p=pNext){
    pNext = p->pNext;
    sqlite3DbFree(db, p);
  }
}

/*
** Free any cursor components allocated by sqlite3VdbeSorterXXX routines.
*/
SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *db, VdbeCursor *pCsr){
  VdbeSorter *pSorter = pCsr->pSorter;
  if( pSorter ){
    if( pSorter->aIter ){
      int i;
      for(i=0; i<pSorter->nTree; i++){
        vdbeSorterIterZero(db, &pSorter->aIter[i]);
      }
      sqlite3DbFree(db, pSorter->aIter);
    }
    if( pSorter->pTemp1 ){
      sqlite3OsCloseFree(pSorter->pTemp1);
    }
    vdbeSorterRecordFree(db, pSorter->pRecord);
    sqlite3DbFree(db, pSorter->pUnpacked);
    sqlite3DbFree(db, pSorter);
    pCsr->pSorter = 0;
  }
}

/*
** Allocate space for a file-handle and open a temporary file. If successful,
** set *ppFile to point to the malloc'd file-handle and return SQLITE_OK.
** Otherwise, set *ppFile to 0 and return an SQLite error code.
*/
static int vdbeSorterOpenTempFile(sqlite3 *db, sqlite3_file **ppFile){
  int dummy;
  return sqlite3OsOpenMalloc(db->pVfs, 0, ppFile,
      SQLITE_OPEN_TEMP_JOURNAL |
      SQLITE_OPEN_READWRITE    | SQLITE_OPEN_CREATE |
      SQLITE_OPEN_EXCLUSIVE    | SQLITE_OPEN_DELETEONCLOSE, &dummy
  );
}

/*
** Merge the two sorted lists p1 and p2 into a single list.
** Set *ppOut to the head of the new list.
*/
static void vdbeSorterMerge(
  VdbeCursor *pCsr,               /* For pKeyInfo */
  SorterRecord *p1,               /* First list to merge */
  SorterRecord *p2,               /* Second list to merge */
  SorterRecord **ppOut            /* OUT: Head of merged list */
){
  SorterRecord *pFinal = 0;
  SorterRecord **pp = &pFinal;
  void *pVal2 = p2 ? p2->pVal : 0;

  while( p1 && p2 ){
    int res;
    vdbeSorterCompare(pCsr, 0, p1->pVal, p1->nVal, pVal2, p2->nVal, &res);
    if( res<=0 ){
      *pp = p1;
      pp = &p1->pNext;
      p1 = p1->pNext;
      pVal2 = 0;
    }else{
      *pp = p2;
       pp = &p2->pNext;
      p2 = p2->pNext;
      if( p2==0 ) break;
      pVal2 = p2->pVal;
    }
  }
  *pp = p1 ? p1 : p2;
  *ppOut = pFinal;
}

/*
** Sort the linked list of records headed at pCsr->pRecord. Return SQLITE_OK
** if successful, or an SQLite error code (i.e. SQLITE_NOMEM) if an error
** occurs.
*/
static int vdbeSorterSort(VdbeCursor *pCsr){
  int i;
  SorterRecord **aSlot;
  SorterRecord *p;
  VdbeSorter *pSorter = pCsr->pSorter;

  aSlot = (SorterRecord **)sqlite3MallocZero(64 * sizeof(SorterRecord *));
  if( !aSlot ){
    return SQLITE_NOMEM;
  }

  p = pSorter->pRecord;
  while( p ){
    SorterRecord *pNext = p->pNext;
    p->pNext = 0;
    for(i=0; aSlot[i]; i++){
      vdbeSorterMerge(pCsr, p, aSlot[i], &p);
      aSlot[i] = 0;
    }
    aSlot[i] = p;
    p = pNext;
  }

  p = 0;
  for(i=0; i<64; i++){
    vdbeSorterMerge(pCsr, p, aSlot[i], &p);
  }
  pSorter->pRecord = p;

  sqlite3_free(aSlot);
  return SQLITE_OK;
}


/*
** Write the current contents of the in-memory linked-list to a PMA. Return
** SQLITE_OK if successful, or an SQLite error code otherwise.
**
** The format of a PMA is:
**
**     * A varint. This varint contains the total number of bytes of content
**       in the PMA (not including the varint itself).
**
**     * One or more records packed end-to-end in order of ascending keys. 
**       Each record consists of a varint followed by a blob of data (the 
**       key). The varint is the number of bytes in the blob of data.
*/
static int vdbeSorterListToPMA(sqlite3 *db, VdbeCursor *pCsr){
  int rc = SQLITE_OK;             /* Return code */
  VdbeSorter *pSorter = pCsr->pSorter;

  if( pSorter->nInMemory==0 ){
    assert( pSorter->pRecord==0 );
    return rc;
  }

  rc = vdbeSorterSort(pCsr);

  /* If the first temporary PMA file has not been opened, open it now. */
  if( rc==SQLITE_OK && pSorter->pTemp1==0 ){
    rc = vdbeSorterOpenTempFile(db, &pSorter->pTemp1);
    assert( rc!=SQLITE_OK || pSorter->pTemp1 );
    assert( pSorter->iWriteOff==0 );
    assert( pSorter->nPMA==0 );
  }

  if( rc==SQLITE_OK ){
    i64 iOff = pSorter->iWriteOff;
    SorterRecord *p;
    SorterRecord *pNext = 0;
    static const char eightZeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };

    pSorter->nPMA++;
    rc = vdbeSorterWriteVarint(pSorter->pTemp1, pSorter->nInMemory, &iOff);
    for(p=pSorter->pRecord; rc==SQLITE_OK && p; p=pNext){
      pNext = p->pNext;
      rc = vdbeSorterWriteVarint(pSorter->pTemp1, p->nVal, &iOff);

      if( rc==SQLITE_OK ){
        rc = sqlite3OsWrite(pSorter->pTemp1, p->pVal, p->nVal, iOff);
        iOff += p->nVal;
      }

      sqlite3DbFree(db, p);
    }

    /* This assert verifies that unless an error has occurred, the size of 
    ** the PMA on disk is the same as the expected size stored in
    ** pSorter->nInMemory. */ 
    assert( rc!=SQLITE_OK || pSorter->nInMemory==(
          iOff-pSorter->iWriteOff-sqlite3VarintLen(pSorter->nInMemory)
    ));

    pSorter->iWriteOff = iOff;
    if( rc==SQLITE_OK ){
      /* Terminate each file with 8 extra bytes so that from any offset
      ** in the file we can always read 9 bytes without a SHORT_READ error */
      rc = sqlite3OsWrite(pSorter->pTemp1, eightZeros, 8, iOff);
    }
    pSorter->pRecord = p;
  }

  return rc;
}

/*
** Add a record to the sorter.
*/
SQLITE_PRIVATE int sqlite3VdbeSorterWrite(
  sqlite3 *db,                    /* Database handle */
  VdbeCursor *pCsr,               /* Sorter cursor */
  Mem *pVal                       /* Memory cell containing record */
){
  VdbeSorter *pSorter = pCsr->pSorter;
  int rc = SQLITE_OK;             /* Return Code */
  SorterRecord *pNew;             /* New list element */

  assert( pSorter );
  pSorter->nInMemory += sqlite3VarintLen(pVal->n) + pVal->n;

  pNew = (SorterRecord *)sqlite3DbMallocRaw(db, pVal->n + sizeof(SorterRecord));
  if( pNew==0 ){
    rc = SQLITE_NOMEM;
  }else{
    pNew->pVal = (void *)&pNew[1];
    memcpy(pNew->pVal, pVal->z, pVal->n);
    pNew->nVal = pVal->n;
    pNew->pNext = pSorter->pRecord;
    pSorter->pRecord = pNew;
  }

  /* See if the contents of the sorter should now be written out. They
  ** are written out when either of the following are true:
  **
  **   * The total memory allocated for the in-memory list is greater 
  **     than (page-size * cache-size), or
  **
  **   * The total memory allocated for the in-memory list is greater 
  **     than (page-size * 10) and sqlite3HeapNearlyFull() returns true.
  */
  if( rc==SQLITE_OK && pSorter->mxPmaSize>0 && (
        (pSorter->nInMemory>pSorter->mxPmaSize)
     || (pSorter->nInMemory>pSorter->mnPmaSize && sqlite3HeapNearlyFull())
  )){
    rc = vdbeSorterListToPMA(db, pCsr);
    pSorter->nInMemory = 0;
  }

  return rc;
}

/*
** Helper function for sqlite3VdbeSorterRewind(). 
*/
static int vdbeSorterInitMerge(
  sqlite3 *db,                    /* Database handle */
  VdbeCursor *pCsr,               /* Cursor handle for this sorter */
  i64 *pnByte                     /* Sum of bytes in all opened PMAs */
){
  VdbeSorter *pSorter = pCsr->pSorter;
  int rc = SQLITE_OK;             /* Return code */
  int i;                          /* Used to iterator through aIter[] */
  i64 nByte = 0;                  /* Total bytes in all opened PMAs */

  /* Initialize the iterators. */
  for(i=0; i<SORTER_MAX_MERGE_COUNT; i++){
    VdbeSorterIter *pIter = &pSorter->aIter[i];
    rc = vdbeSorterIterInit(db, pSorter, pSorter->iReadOff, pIter, &nByte);
    pSorter->iReadOff = pIter->iEof;
    assert( rc!=SQLITE_OK || pSorter->iReadOff<=pSorter->iWriteOff );
    if( rc!=SQLITE_OK || pSorter->iReadOff>=pSorter->iWriteOff ) break;
  }

  /* Initialize the aTree[] array. */
  for(i=pSorter->nTree-1; rc==SQLITE_OK && i>0; i--){
    rc = vdbeSorterDoCompare(pCsr, i);
  }

  *pnByte = nByte;
  return rc;
}

/*
** Once the sorter has been populated, this function is called to prepare
** for iterating through its contents in sorted order.
*/
SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *db, VdbeCursor *pCsr, int *pbEof){
  VdbeSorter *pSorter = pCsr->pSorter;
  int rc;                         /* Return code */
  sqlite3_file *pTemp2 = 0;       /* Second temp file to use */
  i64 iWrite2 = 0;                /* Write offset for pTemp2 */
  int nIter;                      /* Number of iterators used */
  int nByte;                      /* Bytes of space required for aIter/aTree */
  int N = 2;                      /* Power of 2 >= nIter */

  assert( pSorter );

  /* If no data has been written to disk, then do not do so now. Instead,
  ** sort the VdbeSorter.pRecord list. The vdbe layer will read data directly
  ** from the in-memory list.  */
  if( pSorter->nPMA==0 ){
    *pbEof = !pSorter->pRecord;
    assert( pSorter->aTree==0 );
    return vdbeSorterSort(pCsr);
  }

  /* Write the current b-tree to a PMA. Close the b-tree cursor. */
  rc = vdbeSorterListToPMA(db, pCsr);
  if( rc!=SQLITE_OK ) return rc;

  /* Allocate space for aIter[] and aTree[]. */
  nIter = pSorter->nPMA;
  if( nIter>SORTER_MAX_MERGE_COUNT ) nIter = SORTER_MAX_MERGE_COUNT;
  assert( nIter>0 );
  while( N<nIter ) N += N;
  nByte = N * (sizeof(int) + sizeof(VdbeSorterIter));
  pSorter->aIter = (VdbeSorterIter *)sqlite3DbMallocZero(db, nByte);
  if( !pSorter->aIter ) return SQLITE_NOMEM;
  pSorter->aTree = (int *)&pSorter->aIter[N];
  pSorter->nTree = N;

  do {
    int iNew;                     /* Index of new, merged, PMA */

    for(iNew=0; 
        rc==SQLITE_OK && iNew*SORTER_MAX_MERGE_COUNT<pSorter->nPMA; 
        iNew++
    ){
      i64 nWrite;                 /* Number of bytes in new PMA */

      /* If there are SORTER_MAX_MERGE_COUNT or less PMAs in file pTemp1,
      ** initialize an iterator for each of them and break out of the loop.
      ** These iterators will be incrementally merged as the VDBE layer calls
      ** sqlite3VdbeSorterNext().
      **
      ** Otherwise, if pTemp1 contains more than SORTER_MAX_MERGE_COUNT PMAs,
      ** initialize interators for SORTER_MAX_MERGE_COUNT of them. These PMAs
      ** are merged into a single PMA that is written to file pTemp2.
      */
      rc = vdbeSorterInitMerge(db, pCsr, &nWrite);
      assert( rc!=SQLITE_OK || pSorter->aIter[ pSorter->aTree[1] ].pFile );
      if( rc!=SQLITE_OK || pSorter->nPMA<=SORTER_MAX_MERGE_COUNT ){
        break;
      }

      /* Open the second temp file, if it is not already open. */
      if( pTemp2==0 ){
        assert( iWrite2==0 );
        rc = vdbeSorterOpenTempFile(db, &pTemp2);
      }

      if( rc==SQLITE_OK ){
        rc = vdbeSorterWriteVarint(pTemp2, nWrite, &iWrite2);
      }

      if( rc==SQLITE_OK ){
        int bEof = 0;
        while( rc==SQLITE_OK && bEof==0 ){
          int nToWrite;
          VdbeSorterIter *pIter = &pSorter->aIter[ pSorter->aTree[1] ];
          assert( pIter->pFile );
          nToWrite = pIter->nKey + sqlite3VarintLen(pIter->nKey);
          rc = sqlite3OsWrite(pTemp2, pIter->aAlloc, nToWrite, iWrite2);
          iWrite2 += nToWrite;
          if( rc==SQLITE_OK ){
            rc = sqlite3VdbeSorterNext(db, pCsr, &bEof);
          }
        }
      }
    }

    if( pSorter->nPMA<=SORTER_MAX_MERGE_COUNT ){
      break;
    }else{
      sqlite3_file *pTmp = pSorter->pTemp1;
      pSorter->nPMA = iNew;
      pSorter->pTemp1 = pTemp2;
      pTemp2 = pTmp;
      pSorter->iWriteOff = iWrite2;
      pSorter->iReadOff = 0;
      iWrite2 = 0;
    }
  }while( rc==SQLITE_OK );

  if( pTemp2 ){
    sqlite3OsCloseFree(pTemp2);
  }
  *pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0);
  return rc;
}

/*
** Advance to the next element in the sorter.
*/
SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *db, VdbeCursor *pCsr, int *pbEof){
  VdbeSorter *pSorter = pCsr->pSorter;
  int rc;                         /* Return code */

  if( pSorter->aTree ){
    int iPrev = pSorter->aTree[1];/* Index of iterator to advance */
    int i;                        /* Index of aTree[] to recalculate */

    rc = vdbeSorterIterNext(db, &pSorter->aIter[iPrev]);
    for(i=(pSorter->nTree+iPrev)/2; rc==SQLITE_OK && i>0; i=i/2){
      rc = vdbeSorterDoCompare(pCsr, i);
    }

    *pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0);
  }else{
    SorterRecord *pFree = pSorter->pRecord;
    pSorter->pRecord = pFree->pNext;
    pFree->pNext = 0;
    vdbeSorterRecordFree(db, pFree);
    *pbEof = !pSorter->pRecord;
    rc = SQLITE_OK;
  }
  return rc;
}

/*
** Return a pointer to a buffer owned by the sorter that contains the 
** current key.
*/
static void *vdbeSorterRowkey(
  VdbeSorter *pSorter,            /* Sorter object */
  int *pnKey                      /* OUT: Size of current key in bytes */
){
  void *pKey;
  if( pSorter->aTree ){
    VdbeSorterIter *pIter;
    pIter = &pSorter->aIter[ pSorter->aTree[1] ];
    *pnKey = pIter->nKey;
    pKey = pIter->aKey;
  }else{
    *pnKey = pSorter->pRecord->nVal;
    pKey = pSorter->pRecord->pVal;
  }
  return pKey;
}

/*
** Copy the current sorter key into the memory cell pOut.
*/
SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(VdbeCursor *pCsr, Mem *pOut){
  VdbeSorter *pSorter = pCsr->pSorter;
  void *pKey; int nKey;           /* Sorter key to copy into pOut */

  pKey = vdbeSorterRowkey(pSorter, &nKey);
  if( sqlite3VdbeMemGrow(pOut, nKey, 0) ){
    return SQLITE_NOMEM;
  }
  pOut->n = nKey;
  MemSetTypeFlag(pOut, MEM_Blob);
  memcpy(pOut->z, pKey, nKey);

  return SQLITE_OK;
}

/*
** Compare the key in memory cell pVal with the key that the sorter cursor
** passed as the first argument currently points to. For the purposes of
** the comparison, ignore the rowid field at the end of each record.
**
** If an error occurs, return an SQLite error code (i.e. SQLITE_NOMEM).
** Otherwise, set *pRes to a negative, zero or positive value if the
** key in pVal is smaller than, equal to or larger than the current sorter
** key.
*/
SQLITE_PRIVATE int sqlite3VdbeSorterCompare(
  VdbeCursor *pCsr,               /* Sorter cursor */
  Mem *pVal,                      /* Value to compare to current sorter key */
  int *pRes                       /* OUT: Result of comparison */
){
  VdbeSorter *pSorter = pCsr->pSorter;
  void *pKey; int nKey;           /* Sorter key to compare pVal with */

  pKey = vdbeSorterRowkey(pSorter, &nKey);
  vdbeSorterCompare(pCsr, 1, pVal->z, pVal->n, pKey, nKey, pRes);
  return SQLITE_OK;
}

#endif /* #ifndef SQLITE_OMIT_MERGE_SORT */

/************** End of vdbesort.c ********************************************/
/************** Begin file journal.c *****************************************/
/*
** 2007 August 22
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**







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







69371
69372
69373
69374
69375
69376
69377



















































































































































































































































































































































































































































































































































































































































































































































































































































































































69378
69379
69380
69381
69382
69383
69384
  sqlite3_mutex_leave(db->mutex);
  return rc;
}

#endif /* #ifndef SQLITE_OMIT_INCRBLOB */

/************** End of vdbeblob.c ********************************************/



















































































































































































































































































































































































































































































































































































































































































































































































































































































































/************** Begin file journal.c *****************************************/
/*
** 2007 August 22
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
71667
71668
71669
71670
71671
71672
71673
71674
71675
71676
71677
71678
71679
71680
71681
71682
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for walking the parser tree for
** an SQL statement.
*/
/* #include <stdlib.h> */
/* #include <string.h> */


/*
** Walk an expression tree.  Invoke the callback once for each node
** of the expression, while decending.  (In other words, the callback
** is invoked before visiting children.)
**







<
<







69887
69888
69889
69890
69891
69892
69893


69894
69895
69896
69897
69898
69899
69900
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for walking the parser tree for
** an SQL statement.
*/




/*
** Walk an expression tree.  Invoke the callback once for each node
** of the expression, while decending.  (In other words, the callback
** is invoked before visiting children.)
**
71807
71808
71809
71810
71811
71812
71813
71814
71815
71816
71817
71818
71819
71820
71821
71822
**
*************************************************************************
**
** This file contains routines used for walking the parser tree and
** resolve all identifiers by associating them with a particular
** table and column.
*/
/* #include <stdlib.h> */
/* #include <string.h> */

/*
** Turn the pExpr expression into an alias for the iCol-th column of the
** result set in pEList.
**
** If the result set column is a simple column reference, then this routine
** makes an exact copy.  But for any other kind of expression, this







<
<







70025
70026
70027
70028
70029
70030
70031


70032
70033
70034
70035
70036
70037
70038
**
*************************************************************************
**
** This file contains routines used for walking the parser tree and
** resolve all identifiers by associating them with a particular
** table and column.
*/



/*
** Turn the pExpr expression into an alias for the iCol-th column of the
** result set in pEList.
**
** If the result set column is a simple column reference, then this routine
** makes an exact copy.  But for any other kind of expression, this
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
    }
  
    /* 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 */
        const char *zSavedContext = pParse->zAuthContext;

        /* Count the total number of references to pOuterNC and all of its
        ** parent contexts. After resolving references to expressions in
        ** pItem->pSelect, check if this value has changed. If so, then
        ** SELECT statement pItem->pSelect must be correlated. Set the
        ** pItem->isCorrelated flag if this is the case. */
        for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef += pNC->nRef;

        if( pItem->zName ) pParse->zAuthContext = pItem->zName;
        sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC);
        pParse->zAuthContext = zSavedContext;
        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 );







<
<

<
<
<
<
<
<
<
<




<
<
<
<







71004
71005
71006
71007
71008
71009
71010


71011








71012
71013
71014
71015




71016
71017
71018
71019
71020
71021
71022
    }
  
    /* 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 ){


        const char *zSavedContext = pParse->zAuthContext;








        if( pItem->zName ) pParse->zAuthContext = pItem->zName;
        sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC);
        pParse->zAuthContext = zSavedContext;
        if( pParse->nErr || db->mallocFailed ) 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 );
73913
73914
73915
73916
73917
73918
73919
73920
73921
73922
73923
73924
73925
73926
73927
73928
73929
    struct SrcList_item *pOldItem = &p->a[i];
    Table *pTab;
    pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase);
    pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
    pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
    pNewItem->jointype = pOldItem->jointype;
    pNewItem->iCursor = pOldItem->iCursor;
    pNewItem->addrFillSub = pOldItem->addrFillSub;
    pNewItem->regReturn = pOldItem->regReturn;
    pNewItem->isCorrelated = pOldItem->isCorrelated;
    pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex);
    pNewItem->notIndexed = pOldItem->notIndexed;
    pNewItem->pIndex = pOldItem->pIndex;
    pTab = pNewItem->pTab = pOldItem->pTab;
    if( pTab ){
      pTab->nRef++;
    }







<
<
|







72115
72116
72117
72118
72119
72120
72121


72122
72123
72124
72125
72126
72127
72128
72129
    struct SrcList_item *pOldItem = &p->a[i];
    Table *pTab;
    pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase);
    pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
    pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
    pNewItem->jointype = pOldItem->jointype;
    pNewItem->iCursor = pOldItem->iCursor;


    pNewItem->isPopulated = pOldItem->isPopulated;
    pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex);
    pNewItem->notIndexed = pOldItem->notIndexed;
    pNewItem->pIndex = pOldItem->pIndex;
    pTab = pNewItem->pTab = pOldItem->pTab;
    if( pTab ){
      pTab->nRef++;
    }
74474
74475
74476
74477
74478
74479
74480
74481

74482
74483
74484
74485
74486
74487
74488
    ** successful here.
    */
    assert(v);
    if( iCol<0 ){
      int iMem = ++pParse->nMem;
      int iAddr;

      iAddr = sqlite3VdbeAddOp1(v, OP_Once, iMem);


      sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
      eType = IN_INDEX_ROWID;

      sqlite3VdbeJumpHere(v, iAddr);
    }else{
      Index *pIdx;                         /* Iterator variable */







|
>







72674
72675
72676
72677
72678
72679
72680
72681
72682
72683
72684
72685
72686
72687
72688
72689
    ** successful here.
    */
    assert(v);
    if( iCol<0 ){
      int iMem = ++pParse->nMem;
      int iAddr;

      iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem);
      sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);

      sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
      eType = IN_INDEX_ROWID;

      sqlite3VdbeJumpHere(v, iAddr);
    }else{
      Index *pIdx;                         /* Iterator variable */
74505
74506
74507
74508
74509
74510
74511
74512

74513
74514
74515
74516
74517
74518
74519
         && (!mustBeUnique || (pIdx->nColumn==1 && pIdx->onError!=OE_None))
        ){
          int iMem = ++pParse->nMem;
          int iAddr;
          char *pKey;
  
          pKey = (char *)sqlite3IndexKeyinfo(pParse, pIdx);
          iAddr = sqlite3VdbeAddOp1(v, OP_Once, iMem);

  
          sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb,
                               pKey,P4_KEYINFO_HANDOFF);
          VdbeComment((v, "%s", pIdx->zName));
          eType = IN_INDEX_INDEX;

          sqlite3VdbeJumpHere(v, iAddr);







|
>







72706
72707
72708
72709
72710
72711
72712
72713
72714
72715
72716
72717
72718
72719
72720
72721
         && (!mustBeUnique || (pIdx->nColumn==1 && pIdx->onError!=OE_None))
        ){
          int iMem = ++pParse->nMem;
          int iAddr;
          char *pKey;
  
          pKey = (char *)sqlite3IndexKeyinfo(pParse, pIdx);
          iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem);
          sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);
  
          sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb,
                               pKey,P4_KEYINFO_HANDOFF);
          VdbeComment((v, "%s", pIdx->zName));
          eType = IN_INDEX_INDEX;

          sqlite3VdbeJumpHere(v, iAddr);
74586
74587
74588
74589
74590
74591
74592
74593
74594
74595
74596
74597
74598
74599
74600
74601
74602
74603
74604
74605
74606
74607
74608
74609
74610

74611

74612
74613
74614
74615
74616
74617
74618
74619
74620
74621
74622
74623
74624
#ifndef SQLITE_OMIT_SUBQUERY
SQLITE_PRIVATE int sqlite3CodeSubselect(
  Parse *pParse,          /* Parsing context */
  Expr *pExpr,            /* The IN, SELECT, or EXISTS operator */
  int rMayHaveNull,       /* Register that records whether NULLs exist in RHS */
  int isRowid             /* If true, LHS of IN operator is a rowid */
){
  int testAddr = -1;                      /* One-time test address */
  int rReg = 0;                           /* Register storing resulting */
  Vdbe *v = sqlite3GetVdbe(pParse);
  if( NEVER(v==0) ) return 0;
  sqlite3ExprCachePush(pParse);

  /* This code must be run in its entirety every time it is encountered
  ** if any of the following is true:
  **
  **    *  The right-hand side is a correlated subquery
  **    *  The right-hand side is an expression list containing variables
  **    *  We are inside a trigger
  **
  ** If all of the above are false, then we can run this code just once
  ** save the results, and reuse the same result on subsequent invocations.
  */
  if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->pTriggerTab ){
    int mem = ++pParse->nMem;

    testAddr = sqlite3VdbeAddOp1(v, OP_Once, mem);

  }

#ifndef SQLITE_OMIT_EXPLAIN
  if( pParse->explain==2 ){
    char *zMsg = sqlite3MPrintf(
        pParse->db, "EXECUTE %s%s SUBQUERY %d", testAddr>=0?"":"CORRELATED ",
        pExpr->op==TK_IN?"LIST":"SCALAR", pParse->iNextSelectId
    );
    sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
  }
#endif

  switch( pExpr->op ){







|

















>
|
>





|







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
#ifndef SQLITE_OMIT_SUBQUERY
SQLITE_PRIVATE int sqlite3CodeSubselect(
  Parse *pParse,          /* Parsing context */
  Expr *pExpr,            /* The IN, SELECT, or EXISTS operator */
  int rMayHaveNull,       /* Register that records whether NULLs exist in RHS */
  int isRowid             /* If true, LHS of IN operator is a rowid */
){
  int testAddr = 0;                       /* One-time test address */
  int rReg = 0;                           /* Register storing resulting */
  Vdbe *v = sqlite3GetVdbe(pParse);
  if( NEVER(v==0) ) return 0;
  sqlite3ExprCachePush(pParse);

  /* This code must be run in its entirety every time it is encountered
  ** if any of the following is true:
  **
  **    *  The right-hand side is a correlated subquery
  **    *  The right-hand side is an expression list containing variables
  **    *  We are inside a trigger
  **
  ** If all of the above are false, then we can run this code just once
  ** save the results, and reuse the same result on subsequent invocations.
  */
  if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->pTriggerTab ){
    int mem = ++pParse->nMem;
    sqlite3VdbeAddOp1(v, OP_If, mem);
    testAddr = sqlite3VdbeAddOp2(v, OP_Integer, 1, mem);
    assert( testAddr>0 || pParse->db->mallocFailed );
  }

#ifndef SQLITE_OMIT_EXPLAIN
  if( pParse->explain==2 ){
    char *zMsg = sqlite3MPrintf(
        pParse->db, "EXECUTE %s%s SUBQUERY %d", testAddr?"":"CORRELATED ",
        pExpr->op==TK_IN?"LIST":"SCALAR", pParse->iNextSelectId
    );
    sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
  }
#endif

  switch( pExpr->op ){
74702
74703
74704
74705
74706
74707
74708
74709
74710
74711
74712
74713
74714
74715
74716
74717
74718
          int iValToIns;

          /* If the expression is not constant then we will need to
          ** disable the test that was generated above that makes sure
          ** this code only executes once.  Because for a non-constant
          ** expression we need to rerun this code each time.
          */
          if( testAddr>=0 && !sqlite3ExprIsConstant(pE2) ){
            sqlite3VdbeChangeToNoop(v, testAddr);
            testAddr = -1;
          }

          /* Evaluate the expression and insert it into the temp table */
          if( isRowid && sqlite3ExprIsInteger(pE2, &iValToIns) ){
            sqlite3VdbeAddOp3(v, OP_InsertInt, pExpr->iTable, r2, iValToIns);
          }else{
            r3 = sqlite3ExprCodeTarget(pParse, pE2, r1);







|
|
|







72906
72907
72908
72909
72910
72911
72912
72913
72914
72915
72916
72917
72918
72919
72920
72921
72922
          int iValToIns;

          /* If the expression is not constant then we will need to
          ** disable the test that was generated above that makes sure
          ** this code only executes once.  Because for a non-constant
          ** expression we need to rerun this code each time.
          */
          if( testAddr && !sqlite3ExprIsConstant(pE2) ){
            sqlite3VdbeChangeToNoop(v, testAddr-1, 2);
            testAddr = 0;
          }

          /* Evaluate the expression and insert it into the temp table */
          if( isRowid && sqlite3ExprIsInteger(pE2, &iValToIns) ){
            sqlite3VdbeAddOp3(v, OP_InsertInt, pExpr->iTable, r2, iValToIns);
          }else{
            r3 = sqlite3ExprCodeTarget(pParse, pE2, r1);
74773
74774
74775
74776
74777
74778
74779
74780
74781
74782
74783
74784
74785
74786
74787
74788
      }
      rReg = dest.iParm;
      ExprSetIrreducible(pExpr);
      break;
    }
  }

  if( testAddr>=0 ){
    sqlite3VdbeJumpHere(v, testAddr);
  }
  sqlite3ExprCachePop(pParse, 1);

  return rReg;
}
#endif /* SQLITE_OMIT_SUBQUERY */








|
|







72977
72978
72979
72980
72981
72982
72983
72984
72985
72986
72987
72988
72989
72990
72991
72992
      }
      rReg = dest.iParm;
      ExprSetIrreducible(pExpr);
      break;
    }
  }

  if( testAddr ){
    sqlite3VdbeJumpHere(v, testAddr-1);
  }
  sqlite3ExprCachePop(pParse, 1);

  return rReg;
}
#endif /* SQLITE_OMIT_SUBQUERY */

75296
75297
75298
75299
75300
75301
75302
75303
75304
75305
75306
75307
75308
75309
75310
      AggInfo *pAggInfo = pExpr->pAggInfo;
      struct AggInfo_col *pCol = &pAggInfo->aCol[pExpr->iAgg];
      if( !pAggInfo->directMode ){
        assert( pCol->iMem>0 );
        inReg = pCol->iMem;
        break;
      }else if( pAggInfo->useSortingIdx ){
        sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab,
                              pCol->iSorterColumn, target);
        break;
      }
      /* Otherwise, fall thru into the TK_COLUMN case */
    }
    case TK_COLUMN: {
      if( pExpr->iTable<0 ){







|







73500
73501
73502
73503
73504
73505
73506
73507
73508
73509
73510
73511
73512
73513
73514
      AggInfo *pAggInfo = pExpr->pAggInfo;
      struct AggInfo_col *pCol = &pAggInfo->aCol[pExpr->iAgg];
      if( !pAggInfo->directMode ){
        assert( pCol->iMem>0 );
        inReg = pCol->iMem;
        break;
      }else if( pAggInfo->useSortingIdx ){
        sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdx,
                              pCol->iSorterColumn, target);
        break;
      }
      /* Otherwise, fall thru into the TK_COLUMN case */
    }
    case TK_COLUMN: {
      if( pExpr->iTable<0 ){
80802
80803
80804
80805
80806
80807
80808
80809
80810
80811
80812
80813
80814
80815
80816
  int noErr          /* Suppress error messages if VIEW already exists */
){
  Table *p;
  int n;
  const char *z;
  Token sEnd;
  DbFixer sFix;
  Token *pName = 0;
  int iDb;
  sqlite3 *db = pParse->db;

  if( pParse->nVar>0 ){
    sqlite3ErrorMsg(pParse, "parameters are not allowed in views");
    sqlite3SelectDelete(db, pSelect);
    return;







|







79006
79007
79008
79009
79010
79011
79012
79013
79014
79015
79016
79017
79018
79019
79020
  int noErr          /* Suppress error messages if VIEW already exists */
){
  Table *p;
  int n;
  const char *z;
  Token sEnd;
  DbFixer sFix;
  Token *pName;
  int iDb;
  sqlite3 *db = pParse->db;

  if( pParse->nVar>0 ){
    sqlite3ErrorMsg(pParse, "parameters are not allowed in views");
    sqlite3SelectDelete(db, pSelect);
    return;
81108
81109
81110
81111
81112
81113
81114
81115
81116
81117
81118
81119
81120
81121
81122
81123
81124
81125
81126
81127
81128
81129
81130
81131
81132
81133
81134
81135
81136
81137
81138
81139
81140
81141
81142
81143
81144
      destroyRootPage(pParse, iLargest, iDb);
      iDestroyed = iLargest;
    }
  }
#endif
}

/*
** Remove entries from the sqlite_stat1 and sqlite_stat2 tables
** after a DROP INDEX or DROP TABLE command.
*/
static void sqlite3ClearStatTables(
  Parse *pParse,         /* The parsing context */
  int iDb,               /* The database number */
  const char *zType,     /* "idx" or "tbl" */
  const char *zName      /* Name of index or table */
){
  static const char *azStatTab[] = { "sqlite_stat1", "sqlite_stat2" };
  int i;
  const char *zDbName = pParse->db->aDb[iDb].zName;
  for(i=0; i<ArraySize(azStatTab); i++){
    if( sqlite3FindTable(pParse->db, azStatTab[i], zDbName) ){
      sqlite3NestedParse(pParse,
        "DELETE FROM %Q.%s WHERE %s=%Q",
        zDbName, azStatTab[i], zType, zName
      );
    }
  }
}

/*
** This routine is called to do the work of a DROP TABLE statement.
** pName is the name of the table to be dropped.
*/
SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
  Table *pTab;
  Vdbe *v;







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







79312
79313
79314
79315
79316
79317
79318























79319
79320
79321
79322
79323
79324
79325
      destroyRootPage(pParse, iLargest, iDb);
      iDestroyed = iLargest;
    }
  }
#endif
}
























/*
** This routine is called to do the work of a DROP TABLE statement.
** pName is the name of the table to be dropped.
*/
SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
  Table *pTab;
  Vdbe *v;
81270
81271
81272
81273
81274
81275
81276
81277







81278
81279
81280
81281
81282
81283
81284
    ** dropped. Triggers are handled seperately because a trigger can be
    ** created in the temp database that refers to a table in another
    ** database.
    */
    sqlite3NestedParse(pParse, 
        "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",
        pDb->zName, SCHEMA_TABLE(iDb), pTab->zName);
    sqlite3ClearStatTables(pParse, iDb, "tbl", pTab->zName);







    if( !isView && !IsVirtual(pTab) ){
      destroyTable(pParse, pTab);
    }

    /* Remove the table entry from SQLite's internal schema and modify
    ** the schema cookie.
    */







|
>
>
>
>
>
>
>







79451
79452
79453
79454
79455
79456
79457
79458
79459
79460
79461
79462
79463
79464
79465
79466
79467
79468
79469
79470
79471
79472
    ** dropped. Triggers are handled seperately because a trigger can be
    ** created in the temp database that refers to a table in another
    ** database.
    */
    sqlite3NestedParse(pParse, 
        "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",
        pDb->zName, SCHEMA_TABLE(iDb), pTab->zName);

    /* Drop any statistics from the sqlite_stat1 table, if it exists */
    if( sqlite3FindTable(db, "sqlite_stat1", db->aDb[iDb].zName) ){
      sqlite3NestedParse(pParse,
        "DELETE FROM %Q.sqlite_stat1 WHERE tbl=%Q", pDb->zName, pTab->zName
      );
    }

    if( !isView && !IsVirtual(pTab) ){
      destroyTable(pParse, pTab);
    }

    /* Remove the table entry from SQLite's internal schema and modify
    ** the schema cookie.
    */
81452
81453
81454
81455
81456
81457
81458
81459
81460
81461
81462
81463
81464
81465
81466
81467
81468
** the index already exists and must be cleared before being refilled and
** the root page number of the index is taken from pIndex->tnum.
*/
static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
  Table *pTab = pIndex->pTable;  /* The table that is indexed */
  int iTab = pParse->nTab++;     /* Btree cursor used for pTab */
  int iIdx = pParse->nTab++;     /* Btree cursor used for pIndex */
  int iSorter = iTab;            /* Cursor opened by OpenSorter (if in use) */
  int addr1;                     /* Address of top of loop */
  int addr2;                     /* Address to jump to for next iteration */
  int tnum;                      /* Root page of index */
  Vdbe *v;                       /* Generate code into this virtual machine */
  KeyInfo *pKey;                 /* KeyInfo for index */
  int regIdxKey;                 /* Registers containing the index key */
  int regRecord;                 /* Register holding assemblied index record */
  sqlite3 *db = pParse->db;      /* The database connection */
  int iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);







<

<







79640
79641
79642
79643
79644
79645
79646

79647

79648
79649
79650
79651
79652
79653
79654
** the index already exists and must be cleared before being refilled and
** the root page number of the index is taken from pIndex->tnum.
*/
static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
  Table *pTab = pIndex->pTable;  /* The table that is indexed */
  int iTab = pParse->nTab++;     /* Btree cursor used for pTab */
  int iIdx = pParse->nTab++;     /* Btree cursor used for pIndex */

  int addr1;                     /* Address of top of loop */

  int tnum;                      /* Root page of index */
  Vdbe *v;                       /* Generate code into this virtual machine */
  KeyInfo *pKey;                 /* KeyInfo for index */
  int regIdxKey;                 /* Registers containing the index key */
  int regRecord;                 /* Register holding assemblied index record */
  sqlite3 *db = pParse->db;      /* The database connection */
  int iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
81487
81488
81489
81490
81491
81492
81493
81494
81495
81496
81497
81498
81499
81500
81501
81502
81503
81504
81505
81506
81507
81508
81509
81510
81511
81512
81513
81514
81515
81516
81517
81518
81519
81520
81521
81522
81523
81524
81525
81526
81527
81528
81529
81530
81531
81532
81533
81534
81535
81536
81537
81538
81539
81540
81541
81542
81543
81544
81545
81546
81547
81548
81549
81550
81551
81552
81553
81554
81555
81556
81557
81558
81559
81560
81561
81562
81563
  }
  pKey = sqlite3IndexKeyinfo(pParse, pIndex);
  sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb, 
                    (char *)pKey, P4_KEYINFO_HANDOFF);
  if( memRootPage>=0 ){
    sqlite3VdbeChangeP5(v, 1);
  }

#ifndef SQLITE_OMIT_MERGE_SORT
  /* Open the sorter cursor if we are to use one. */
  iSorter = pParse->nTab++;
  sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, 0, (char*)pKey, P4_KEYINFO);
#endif

  /* Open the table. Loop through all rows of the table, inserting index
  ** records into the sorter. */
  sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
  addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
  addr2 = addr1 + 1;
  regRecord = sqlite3GetTempReg(pParse);
  regIdxKey = sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1);

#ifndef SQLITE_OMIT_MERGE_SORT
  sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord);
  sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1);
  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);
#else
  if( pIndex->onError!=OE_None ){
    const int regRowid = regIdxKey + pIndex->nColumn;
    const int j2 = sqlite3VdbeCurrentAddr(v) + 2;
    void * const pRegKey = SQLITE_INT_TO_PTR(regIdxKey);

    /* The registers accessed by the OP_IsUnique opcode were allocated
    ** using sqlite3GetTempRange() inside of the sqlite3GenerateIndexKey()
    ** call above. Just before that function was freed they were released
    ** (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);

  sqlite3VdbeAddOp1(v, OP_Close, iTab);
  sqlite3VdbeAddOp1(v, OP_Close, iIdx);
  sqlite3VdbeAddOp1(v, OP_Close, iSorter);
}

/*
** Create a new index for an SQL table.  pName1.pName2 is the name of the index 
** and pTblList is the name of the table that is to be indexed.  Both will 
** be NULL for a primary key or an index that is created to satisfy a
** UNIQUE constraint.  If pTable and pIndex are NULL, use pParse->pNewTable







<
<
<
<
<
<
<
<
<


<


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


















|

<

|

<


<







79673
79674
79675
79676
79677
79678
79679









79680
79681

79682
79683





















79684
79685
79686
79687
79688
79689
79690
79691
79692
79693
79694
79695
79696
79697
79698
79699
79700
79701
79702
79703

79704
79705
79706

79707
79708

79709
79710
79711
79712
79713
79714
79715
  }
  pKey = sqlite3IndexKeyinfo(pParse, pIndex);
  sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb, 
                    (char *)pKey, P4_KEYINFO_HANDOFF);
  if( memRootPage>=0 ){
    sqlite3VdbeChangeP5(v, 1);
  }









  sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
  addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);

  regRecord = sqlite3GetTempReg(pParse);
  regIdxKey = sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1);





















  if( pIndex->onError!=OE_None ){
    const int regRowid = regIdxKey + pIndex->nColumn;
    const int j2 = sqlite3VdbeCurrentAddr(v) + 2;
    void * const pRegKey = SQLITE_INT_TO_PTR(regIdxKey);

    /* The registers accessed by the OP_IsUnique opcode were allocated
    ** using sqlite3GetTempRange() inside of the sqlite3GenerateIndexKey()
    ** call above. Just before that function was freed they were released
    ** (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);
  }
  sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdx, regRecord);
  sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);

  sqlite3ReleaseTempReg(pParse, regRecord);
  sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1);
  sqlite3VdbeJumpHere(v, addr1);

  sqlite3VdbeAddOp1(v, OP_Close, iTab);
  sqlite3VdbeAddOp1(v, OP_Close, iIdx);

}

/*
** Create a new index for an SQL table.  pName1.pName2 is the name of the index 
** and pTblList is the name of the table that is to be indexed.  Both will 
** be NULL for a primary key or an index that is created to satisfy a
** UNIQUE constraint.  If pTable and pIndex are NULL, use pParse->pNewTable
81971
81972
81973
81974
81975
81976
81977
81978
81979
81980
81981
81982
81983
81984
81985
    ** the zStmt variable
    */
    if( pStart ){
      assert( pEnd!=0 );
      /* A named index with an explicit CREATE INDEX statement */
      zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s",
        onError==OE_None ? "" : " UNIQUE",
        (int)(pEnd->z - pName->z) + 1,
        pName->z);
    }else{
      /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */
      /* zStmt = sqlite3MPrintf(""); */
      zStmt = 0;
    }








|







80123
80124
80125
80126
80127
80128
80129
80130
80131
80132
80133
80134
80135
80136
80137
    ** the zStmt variable
    */
    if( pStart ){
      assert( pEnd!=0 );
      /* A named index with an explicit CREATE INDEX statement */
      zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s",
        onError==OE_None ? "" : " UNIQUE",
        pEnd->z - pName->z + 1,
        pName->z);
    }else{
      /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */
      /* zStmt = sqlite3MPrintf(""); */
      zStmt = 0;
    }

82129
82130
82131
82132
82133
82134
82135
82136

82137



82138


82139
82140
82141
82142
82143
82144
82145

  /* Generate code to remove the index and from the master table */
  v = sqlite3GetVdbe(pParse);
  if( v ){
    sqlite3BeginWriteOperation(pParse, 1, iDb);
    sqlite3NestedParse(pParse,
       "DELETE FROM %Q.%s WHERE name=%Q AND type='index'",
       db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pIndex->zName

    );



    sqlite3ClearStatTables(pParse, iDb, "idx", pIndex->zName);


    sqlite3ChangeCookie(pParse, iDb);
    destroyRootPage(pParse, pIndex->tnum, iDb);
    sqlite3VdbeAddOp4(v, OP_DropIndex, iDb, 0, 0, pIndex->zName, 0);
  }

exit_drop_index:
  sqlite3SrcListDelete(db, pName);







|
>

>
>
>
|
>
>







80281
80282
80283
80284
80285
80286
80287
80288
80289
80290
80291
80292
80293
80294
80295
80296
80297
80298
80299
80300
80301
80302
80303

  /* Generate code to remove the index and from the master table */
  v = sqlite3GetVdbe(pParse);
  if( v ){
    sqlite3BeginWriteOperation(pParse, 1, iDb);
    sqlite3NestedParse(pParse,
       "DELETE FROM %Q.%s WHERE name=%Q AND type='index'",
       db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
       pIndex->zName
    );
    if( sqlite3FindTable(db, "sqlite_stat1", db->aDb[iDb].zName) ){
      sqlite3NestedParse(pParse,
        "DELETE FROM %Q.sqlite_stat1 WHERE idx=%Q",
        db->aDb[iDb].zName, pIndex->zName
      );
    }
    sqlite3ChangeCookie(pParse, iDb);
    destroyRootPage(pParse, pIndex->tnum, iDb);
    sqlite3VdbeAddOp4(v, OP_DropIndex, iDb, 0, 0, pIndex->zName, 0);
  }

exit_drop_index:
  sqlite3SrcListDelete(db, pName);
82503
82504
82505
82506
82507
82508
82509
82510
82511
82512
82513
82514
82515
82516
82517
82518
82519
**           A natural cross join B
**
** The operator is "natural cross join".  The A and B operands are stored
** in p->a[0] and p->a[1], respectively.  The parser initially stores the
** operator with A.  This routine shifts that operator over to B.
*/
SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(SrcList *p){
  if( p ){
    int i;
    assert( p->a || p->nSrc==0 );
    for(i=p->nSrc-1; i>0; i--){
      p->a[i].jointype = p->a[i-1].jointype;
    }
    p->a[0].jointype = 0;
  }
}








|

<







80661
80662
80663
80664
80665
80666
80667
80668
80669

80670
80671
80672
80673
80674
80675
80676
**           A natural cross join B
**
** The operator is "natural cross join".  The A and B operands are stored
** in p->a[0] and p->a[1], respectively.  The parser initially stores the
** operator with A.  This routine shifts that operator over to B.
*/
SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(SrcList *p){
  if( p && p->a ){
    int i;

    for(i=p->nSrc-1; i>0; i--){
      p->a[i].jointype = p->a[i-1].jointype;
    }
    p->a[0].jointype = 0;
  }
}

83761
83762
83763
83764
83765
83766
83767
83768
83769
83770
83771
83772
83773
83774
83775
83776
83777
    int iRowSet = ++pParse->nMem;   /* Register for rowset of rows to delete */
    int iRowid = ++pParse->nMem;    /* Used for storing rowid values. */
    int regRowid;                   /* Actual register containing rowids */

    /* Collect rowids of every row to be deleted.
    */
    sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
    pWInfo = sqlite3WhereBegin(
        pParse, pTabList, pWhere, 0, 0, WHERE_DUPLICATES_OK
    );
    if( pWInfo==0 ) goto delete_from_cleanup;
    regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid);
    sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid);
    if( db->flags & SQLITE_CountRows ){
      sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
    }
    sqlite3WhereEnd(pWInfo);







|
<
<







81918
81919
81920
81921
81922
81923
81924
81925


81926
81927
81928
81929
81930
81931
81932
    int iRowSet = ++pParse->nMem;   /* Register for rowset of rows to delete */
    int iRowid = ++pParse->nMem;    /* Used for storing rowid values. */
    int regRowid;                   /* Actual register containing rowids */

    /* Collect rowids of every row to be deleted.
    */
    sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0,WHERE_DUPLICATES_OK);


    if( pWInfo==0 ) goto delete_from_cleanup;
    regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid);
    sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid);
    if( db->flags & SQLITE_CountRows ){
      sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
    }
    sqlite3WhereEnd(pWInfo);
84061
84062
84063
84064
84065
84066
84067
84068
84069
84070
84071
84072
84073
84074
84075
84076
** This file contains the C functions that implement various SQL
** functions of SQLite.  
**
** There is only one exported symbol in this file - the function
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
*/
/* #include <stdlib.h> */
/* #include <assert.h> */

/*
** Return the collating function associated with a function.
*/
static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){
  return context->pColl;
}







<
<







82216
82217
82218
82219
82220
82221
82222


82223
82224
82225
82226
82227
82228
82229
** This file contains the C functions that implement various SQL
** functions of SQLite.  
**
** There is only one exported symbol in this file - the function
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
*/



/*
** Return the collating function associated with a function.
*/
static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){
  return context->pColl;
}
86212
86213
86214
86215
86216
86217
86218
86219
86220
86221
86222
86223
86224
86225
86226
  sNameContext.pParse = pParse;
  sqlite3ResolveExprNames(&sNameContext, pWhere);

  /* Create VDBE to loop through the entries in pSrc that match the WHERE
  ** clause. If the constraint is not deferred, throw an exception for
  ** each row found. Otherwise, for deferred constraints, increment the
  ** deferred constraint counter by nIncr for each row selected.  */
  pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0);
  if( nIncr>0 && pFKey->isDeferred==0 ){
    sqlite3ParseToplevel(pParse)->mayAbort = 1;
  }
  sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
  if( pWInfo ){
    sqlite3WhereEnd(pWInfo);
  }







|







84365
84366
84367
84368
84369
84370
84371
84372
84373
84374
84375
84376
84377
84378
84379
  sNameContext.pParse = pParse;
  sqlite3ResolveExprNames(&sNameContext, pWhere);

  /* Create VDBE to loop through the entries in pSrc that match the WHERE
  ** clause. If the constraint is not deferred, throw an exception for
  ** each row found. Otherwise, for deferred constraints, increment the
  ** deferred constraint counter by nIncr for each row selected.  */
  pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0);
  if( nIncr>0 && pFKey->isDeferred==0 ){
    sqlite3ParseToplevel(pParse)->mayAbort = 1;
  }
  sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
  if( pWInfo ){
    sqlite3WhereEnd(pWInfo);
  }
86386
86387
86388
86389
86390
86391
86392
86393
86394
86395
86396
86397
86398
86399
86400
86401
86402
86403
86404
86405
86406
86407
86408
86409
86410
86411
86412
86413
86414
86415
86416
86417
    ** 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
        ** missing, behave as if it is empty. i.e. decrement the relevant
        ** FK counter for each row of the current table with non-NULL keys.
        */
        Vdbe *v = sqlite3GetVdbe(pParse);
        int iJump = sqlite3VdbeCurrentAddr(v) + pFKey->nCol + 1;
        for(i=0; i<pFKey->nCol; i++){
          int iReg = pFKey->aCol[i].iFrom + regOld + 1;
          sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iJump);
        }
        sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, -1);
      }
      continue;
    }
    assert( pFKey->nCol==1 || (aiFree && pIdx) );

    if( aiFree ){
      aiCol = aiFree;
    }else{







<

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







84539
84540
84541
84542
84543
84544
84545

84546
















84547
84548
84549
84550
84551
84552
84553
    ** 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) ){

      if( !isIgnoreErrors || db->mallocFailed ) return;
















      continue;
    }
    assert( pFKey->nCol==1 || (aiFree && pIdx) );

    if( aiFree ){
      aiCol = aiFree;
    }else{
89096
89097
89098
89099
89100
89101
89102
89103
89104
89105
89106
89107
89108
89109
89110
89111
89112
  const char *(*sourceid)(void);
  int (*stmt_status)(sqlite3_stmt*,int,int);
  int (*strnicmp)(const char*,const char*,int);
  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







<
<
<







87232
87233
87234
87235
87236
87237
87238



87239
87240
87241
87242
87243
87244
87245
  const char *(*sourceid)(void);
  int (*stmt_status)(sqlite3_stmt*,int,int);
  int (*strnicmp)(const char*,const char*,int);
  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*);



};

/*
** 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
89299
89300
89301
89302
89303
89304
89305
89306
89307
89308
89309
89310
89311
89312
89313
89314
89315
89316
89317
89318
89319
89320
89321
89322
89323
89324
89325
#define sqlite3_sourceid               sqlite3_api->sourceid
#define sqlite3_stmt_status            sqlite3_api->stmt_status
#define sqlite3_strnicmp               sqlite3_api->strnicmp
#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_ */

/************** End of sqlite3ext.h ******************************************/
/************** Continuing where we left off in loadext.c ********************/
/* #include <string.h> */

#ifndef SQLITE_OMIT_LOAD_EXTENSION

/*
** Some API routines are omitted when various features are
** excluded from a build of SQLite.  Substitute a NULL pointer
** for any missing APIs.







<
<
<









<







87432
87433
87434
87435
87436
87437
87438



87439
87440
87441
87442
87443
87444
87445
87446
87447

87448
87449
87450
87451
87452
87453
87454
#define sqlite3_sourceid               sqlite3_api->sourceid
#define sqlite3_stmt_status            sqlite3_api->stmt_status
#define sqlite3_strnicmp               sqlite3_api->strnicmp
#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



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

/************** End of sqlite3ext.h ******************************************/
/************** Continuing where we left off in loadext.c ********************/


#ifndef SQLITE_OMIT_LOAD_EXTENSION

/*
** Some API routines are omitted when various features are
** excluded from a build of SQLite.  Substitute a NULL pointer
** for any missing APIs.
89377
89378
89379
89380
89381
89382
89383
89384
89385
89386
89387
89388
89389
89390
89391
89392
# define sqlite3_progress_handler 0
#endif

#ifdef SQLITE_OMIT_VIRTUALTABLE
# define sqlite3_create_module 0
# define sqlite3_create_module_v2 0
# define sqlite3_declare_vtab 0
# define sqlite3_vtab_config 0
# define sqlite3_vtab_on_conflict 0
#endif

#ifdef SQLITE_OMIT_SHARED_CACHE
# define sqlite3_enable_shared_cache 0
#endif

#ifdef SQLITE_OMIT_TRACE







<
<







87506
87507
87508
87509
87510
87511
87512


87513
87514
87515
87516
87517
87518
87519
# define sqlite3_progress_handler 0
#endif

#ifdef SQLITE_OMIT_VIRTUALTABLE
# define sqlite3_create_module 0
# define sqlite3_create_module_v2 0
# define sqlite3_declare_vtab 0


#endif

#ifdef SQLITE_OMIT_SHARED_CACHE
# define sqlite3_enable_shared_cache 0
#endif

#ifdef SQLITE_OMIT_TRACE
89402
89403
89404
89405
89406
89407
89408
89409
89410
89411
89412
89413
89414
89415
89416
#ifdef SQLITE_OMIT_INCRBLOB
#define sqlite3_bind_zeroblob  0
#define sqlite3_blob_bytes     0
#define sqlite3_blob_close     0
#define sqlite3_blob_open      0
#define sqlite3_blob_read      0
#define sqlite3_blob_write     0
#define sqlite3_blob_reopen    0
#endif

/*
** The following structure contains pointers to all SQLite API routines.
** A pointer to this structure is passed into extensions when they are
** loaded so that the extension can make calls back into the SQLite
** library.







<







87529
87530
87531
87532
87533
87534
87535

87536
87537
87538
87539
87540
87541
87542
#ifdef SQLITE_OMIT_INCRBLOB
#define sqlite3_bind_zeroblob  0
#define sqlite3_blob_bytes     0
#define sqlite3_blob_close     0
#define sqlite3_blob_open      0
#define sqlite3_blob_read      0
#define sqlite3_blob_write     0

#endif

/*
** The following structure contains pointers to all SQLite API routines.
** A pointer to this structure is passed into extensions when they are
** loaded so that the extension can make calls back into the SQLite
** library.
89668
89669
89670
89671
89672
89673
89674
89675
89676
89677
89678
89679
89680
89681
89682
89683
89684
  sqlite3_wal_checkpoint,
  sqlite3_wal_hook,
#else
  0,
  0,
  0,
#endif
  sqlite3_blob_reopen,
  sqlite3_vtab_config,
  sqlite3_vtab_on_conflict,
};

/*
** Attempt to load an SQLite extension library contained in the file
** zFile.  The entry point is zProc.  zProc may be 0 in which case a
** default entry point name (sqlite3_extension_init) is used.  Use
** of the default name is recommended.







<
<
<







87794
87795
87796
87797
87798
87799
87800



87801
87802
87803
87804
87805
87806
87807
  sqlite3_wal_checkpoint,
  sqlite3_wal_hook,
#else
  0,
  0,
  0,
#endif



};

/*
** Attempt to load an SQLite extension library contained in the file
** zFile.  The entry point is zProc.  zProc may be 0 in which case a
** default entry point name (sqlite3_extension_init) is used.  Use
** of the default name is recommended.
92428
92429
92430
92431
92432
92433
92434
92435
92436
92437
92438
92439
92440
92441
92442
92443
  pNew->addrOpenEphm[0] = -1;
  pNew->addrOpenEphm[1] = -1;
  pNew->addrOpenEphm[2] = -1;
  if( db->mallocFailed ) {
    clearSelect(db, pNew);
    if( pNew!=&standin ) sqlite3DbFree(db, pNew);
    pNew = 0;
  }else{
    assert( pNew->pSrc!=0 || pParse->nErr>0 );
  }
  return pNew;
}

/*
** Delete the given Select structure and all of its substructures.
*/







<
<







90551
90552
90553
90554
90555
90556
90557


90558
90559
90560
90561
90562
90563
90564
  pNew->addrOpenEphm[0] = -1;
  pNew->addrOpenEphm[1] = -1;
  pNew->addrOpenEphm[2] = -1;
  if( db->mallocFailed ) {
    clearSelect(db, pNew);
    if( pNew!=&standin ) sqlite3DbFree(db, pNew);
    pNew = 0;


  }
  return pNew;
}

/*
** Delete the given Select structure and all of its substructures.
*/
92760
92761
92762
92763
92764
92765
92766
92767
92768
92769
92770
92771
92772
92773
92774
92775
92776
92777
92778
92779
92780
92781
92782
92783
92784
92785
  Select *pSelect,       /* The whole SELECT statement */
  int regData            /* Register holding data to be sorted */
){
  Vdbe *v = pParse->pVdbe;
  int nExpr = pOrderBy->nExpr;
  int regBase = sqlite3GetTempRange(pParse, nExpr+2);
  int regRecord = sqlite3GetTempReg(pParse);
  int op;
  sqlite3ExprCacheClear(pParse);
  sqlite3ExprCodeExprList(pParse, pOrderBy, regBase, 0);
  sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr);
  sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+1, 1);
  sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nExpr + 2, regRecord);
  if( pSelect->selFlags & SF_UseSorter ){
    op = OP_SorterInsert;
  }else{
    op = OP_IdxInsert;
  }
  sqlite3VdbeAddOp2(v, op, pOrderBy->iECursor, regRecord);
  sqlite3ReleaseTempReg(pParse, regRecord);
  sqlite3ReleaseTempRange(pParse, regBase, nExpr+2);
  if( pSelect->iLimit ){
    int addr1, addr2;
    int iLimit;
    if( pSelect->iOffset ){
      iLimit = pSelect->iOffset+1;







<





<
<
<
<
<
|







90881
90882
90883
90884
90885
90886
90887

90888
90889
90890
90891
90892





90893
90894
90895
90896
90897
90898
90899
90900
  Select *pSelect,       /* The whole SELECT statement */
  int regData            /* Register holding data to be sorted */
){
  Vdbe *v = pParse->pVdbe;
  int nExpr = pOrderBy->nExpr;
  int regBase = sqlite3GetTempRange(pParse, nExpr+2);
  int regRecord = sqlite3GetTempReg(pParse);

  sqlite3ExprCacheClear(pParse);
  sqlite3ExprCodeExprList(pParse, pOrderBy, regBase, 0);
  sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr);
  sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+1, 1);
  sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nExpr + 2, regRecord);





  sqlite3VdbeAddOp2(v, OP_IdxInsert, pOrderBy->iECursor, regRecord);
  sqlite3ReleaseTempReg(pParse, regRecord);
  sqlite3ReleaseTempRange(pParse, regBase, nExpr+2);
  if( pSelect->iLimit ){
    int addr1, addr2;
    int iLimit;
    if( pSelect->iOffset ){
      iLimit = pSelect->iOffset+1;
93240
93241
93242
93243
93244
93245
93246
93247
93248
93249
93250
93251
93252
93253
93254
93255
93256
93257
93258
93259
93260
93261
93262
93263
93264
93265
93266
93267
  if( eDest==SRT_Output || eDest==SRT_Coroutine ){
    pseudoTab = pParse->nTab++;
    sqlite3VdbeAddOp3(v, OP_OpenPseudo, pseudoTab, regRow, nColumn);
    regRowid = 0;
  }else{
    regRowid = sqlite3GetTempReg(pParse);
  }
  if( p->selFlags & SF_UseSorter ){
    int regSortOut = ++pParse->nMem;
    int ptab2 = pParse->nTab++;
    sqlite3VdbeAddOp3(v, OP_OpenPseudo, ptab2, regSortOut, pOrderBy->nExpr+2);
    addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak);
    codeOffset(v, p, addrContinue);
    sqlite3VdbeAddOp2(v, OP_SorterData, iTab, regSortOut);
    sqlite3VdbeAddOp3(v, OP_Column, ptab2, pOrderBy->nExpr+1, regRow);
    sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE);
  }else{
    addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak);
    codeOffset(v, p, addrContinue);
    sqlite3VdbeAddOp3(v, OP_Column, iTab, pOrderBy->nExpr+1, regRow);
  }
  switch( eDest ){
    case SRT_Table:
    case SRT_EphemTab: {
      testcase( eDest==SRT_Table );
      testcase( eDest==SRT_EphemTab );
      sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, regRowid);
      sqlite3VdbeAddOp3(v, OP_Insert, iParm, regRow, regRowid);







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







91355
91356
91357
91358
91359
91360
91361










91362
91363
91364

91365
91366
91367
91368
91369
91370
91371
  if( eDest==SRT_Output || eDest==SRT_Coroutine ){
    pseudoTab = pParse->nTab++;
    sqlite3VdbeAddOp3(v, OP_OpenPseudo, pseudoTab, regRow, nColumn);
    regRowid = 0;
  }else{
    regRowid = sqlite3GetTempReg(pParse);
  }










  addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak);
  codeOffset(v, p, addrContinue);
  sqlite3VdbeAddOp3(v, OP_Column, iTab, pOrderBy->nExpr + 1, regRow);

  switch( eDest ){
    case SRT_Table:
    case SRT_EphemTab: {
      testcase( eDest==SRT_Table );
      testcase( eDest==SRT_EphemTab );
      sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, regRowid);
      sqlite3VdbeAddOp3(v, OP_Insert, iParm, regRow, regRowid);
93306
93307
93308
93309
93310
93311
93312
93313
93314
93315
93316
93317
93318
93319
93320
93321
93322
93323
93324
  }
  sqlite3ReleaseTempReg(pParse, regRow);
  sqlite3ReleaseTempReg(pParse, regRowid);

  /* The bottom of the loop
  */
  sqlite3VdbeResolveLabel(v, addrContinue);
  if( p->selFlags & SF_UseSorter ){
    sqlite3VdbeAddOp2(v, OP_SorterNext, iTab, addr);
  }else{
    sqlite3VdbeAddOp2(v, OP_Next, iTab, addr);
  }
  sqlite3VdbeResolveLabel(v, addrBreak);
  if( eDest==SRT_Output || eDest==SRT_Coroutine ){
    sqlite3VdbeAddOp2(v, OP_Close, pseudoTab, 0);
  }
}

/*







<
<
<
|
<







91410
91411
91412
91413
91414
91415
91416



91417

91418
91419
91420
91421
91422
91423
91424
  }
  sqlite3ReleaseTempReg(pParse, regRow);
  sqlite3ReleaseTempReg(pParse, regRowid);

  /* The bottom of the loop
  */
  sqlite3VdbeResolveLabel(v, addrContinue);



  sqlite3VdbeAddOp2(v, OP_Next, iTab, addr);

  sqlite3VdbeResolveLabel(v, addrBreak);
  if( eDest==SRT_Output || eDest==SRT_Coroutine ){
    sqlite3VdbeAddOp2(v, OP_Close, pseudoTab, 0);
  }
}

/*
96083
96084
96085
96086
96087
96088
96089
96090
96091
96092
96093
96094
96095
96096
96097
  ExprList *pOrderBy;    /* The ORDER BY clause.  May be NULL */
  ExprList *pGroupBy;    /* The GROUP BY clause.  May be NULL */
  Expr *pHaving;         /* The HAVING clause.  May be NULL */
  int isDistinct;        /* True if the DISTINCT keyword is present */
  int distinct;          /* Table to use for the distinct set */
  int rc = 1;            /* Value to return from this function */
  int addrSortIndex;     /* Address of an OP_OpenEphemeral instruction */
  int addrDistinctIndex; /* Address of an OP_OpenEphemeral instruction */
  AggInfo sAggInfo;      /* Information used by aggregate queries */
  int iEnd;              /* Address of the end of the query */
  sqlite3 *db;           /* The database connection */

#ifndef SQLITE_OMIT_EXPLAIN
  int iRestoreSelectId = pParse->iSelectId;
  pParse->iSelectId = pParse->iNextSelectId++;







<







94183
94184
94185
94186
94187
94188
94189

94190
94191
94192
94193
94194
94195
94196
  ExprList *pOrderBy;    /* The ORDER BY clause.  May be NULL */
  ExprList *pGroupBy;    /* The GROUP BY clause.  May be NULL */
  Expr *pHaving;         /* The HAVING clause.  May be NULL */
  int isDistinct;        /* True if the DISTINCT keyword is present */
  int distinct;          /* Table to use for the distinct set */
  int rc = 1;            /* Value to return from this function */
  int addrSortIndex;     /* Address of an OP_OpenEphemeral instruction */

  AggInfo sAggInfo;      /* Information used by aggregate queries */
  int iEnd;              /* Address of the end of the query */
  sqlite3 *db;           /* The database connection */

#ifndef SQLITE_OMIT_EXPLAIN
  int iRestoreSelectId = pParse->iSelectId;
  pParse->iSelectId = pParse->iNextSelectId++;
96142
96143
96144
96145
96146
96147
96148
96149
96150
96151
96152
96153
96154
96155
96156
96157
96158
96159
96160
96161
96162
96163

96164
96165
96166
96167
96168
96169
96170
96171
96172
96173
96174
96175
96176
96177
96178
96179
96180
96181
96182
96183
96184
96185
96186
96187
96188
96189
96190
96191
96192
96193

96194
96195

96196
96197
96198
96199
96200
96201
96202
96203
96204
96205
96206
96207
96208
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
  for(i=0; !p->pPrior && i<pTabList->nSrc; i++){
    struct SrcList_item *pItem = &pTabList->a[i];
    SelectDest dest;
    Select *pSub = pItem->pSelect;
    int isAggSub;

    if( pSub==0 ) continue;
    if( pItem->addrFillSub ){
      sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub);
      continue;
    }

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


    isAggSub = (pSub->selFlags & SF_Aggregate)!=0;
    if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){
      /* This subquery can be absorbed into its parent. */
      if( isAggSub ){
        isAgg = 1;
        p->selFlags |= SF_Aggregate;
      }
      i = -1;
    }else{
      /* Generate a subroutine that will fill an ephemeral table with
      ** the content of this subquery.  pItem->addrFillSub will point
      ** to the address of the generated subroutine.  pItem->regReturn
      ** is a register allocated to hold the subroutine return address
      */
      int topAddr;
      int onceAddr = 0;
      int retAddr;
      assert( pItem->addrFillSub==0 );
      pItem->regReturn = ++pParse->nMem;
      topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
      pItem->addrFillSub = topAddr+1;
      VdbeNoopComment((v, "materialize %s", pItem->pTab->zName));
      if( pItem->isCorrelated==0 && pParse->pTriggerTab==0 ){
        /* If the subquery is no correlated and if we are not inside of
        ** a trigger, then we only need to compute the value of the subquery
        ** once. */
        int regOnce = ++pParse->nMem;
        onceAddr = sqlite3VdbeAddOp1(v, OP_Once, regOnce);
      }
      sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);

      explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
      sqlite3Select(pParse, pSub, &dest);

      pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;
      if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
      retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
      VdbeComment((v, "end %s", pItem->pTab->zName));
      sqlite3VdbeChangeP1(v, topAddr, retAddr);

    }
    if( /*pParse->nErr ||*/ db->mallocFailed ){
      goto select_end;
    }
    pParse->nHeight -= sqlite3SelectExprHeight(p);
    pTabList = p->pSrc;
    if( !IgnorableOrderby(pDest) ){







|
<
<
<
<










>


<






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

>


>

<
<
<
<
<







94241
94242
94243
94244
94245
94246
94247
94248




94249
94250
94251
94252
94253
94254
94255
94256
94257
94258
94259
94260
94261

94262
94263
94264
94265
94266
94267




















94268
94269
94270
94271
94272
94273





94274
94275
94276
94277
94278
94279
94280
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
  for(i=0; !p->pPrior && i<pTabList->nSrc; i++){
    struct SrcList_item *pItem = &pTabList->a[i];
    SelectDest dest;
    Select *pSub = pItem->pSelect;
    int isAggSub;

    if( pSub==0 || pItem->isPopulated ) continue;





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

    /* Check to see if the subquery can be absorbed into the parent. */
    isAggSub = (pSub->selFlags & SF_Aggregate)!=0;
    if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){

      if( isAggSub ){
        isAgg = 1;
        p->selFlags |= SF_Aggregate;
      }
      i = -1;
    }else{




















      sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
      assert( pItem->isPopulated==0 );
      explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
      sqlite3Select(pParse, pSub, &dest);
      pItem->isPopulated = 1;
      pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;





    }
    if( /*pParse->nErr ||*/ db->mallocFailed ){
      goto select_end;
    }
    pParse->nHeight -= sqlite3SelectExprHeight(p);
    pTabList = p->pSrc;
    if( !IgnorableOrderby(pDest) ){
96236
96237
96238
96239
96240
96241
96242










96243
96244
96245
96246
96247
96248
96249
96250
96251
96252
96253
96254
96255
96256
96257
96258
96259
96260
96261
96262
96263
96264
96265
96266
96267
96268
96269
96270
96271
96272
96273
96274
96275
96276
96277
96278
96279
96280
96281
96282
96283
96284
96285
96286
      }
    }
    rc = multiSelect(pParse, p, pDest);
    explainSetInteger(pParse->iSelectId, iRestoreSelectId);
    return rc;
  }
#endif











  /* If there is both a GROUP BY and an ORDER BY clause and they are
  ** identical, then disable the ORDER BY clause since the GROUP BY
  ** will cause elements to come out in the correct order.  This is
  ** an optimization - the correct answer should result regardless.
  ** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER
  ** to disable this optimization for testing purposes.
  */
  if( sqlite3ExprListCompare(p->pGroupBy, pOrderBy)==0
         && (db->flags & SQLITE_GroupByOrder)==0 ){
    pOrderBy = 0;
  }

  /* If the query is DISTINCT with an ORDER BY but is not an aggregate, and 
  ** if the select-list is the same as the ORDER BY list, then this query
  ** can be rewritten as a GROUP BY. In other words, this:
  **
  **     SELECT DISTINCT xyz FROM ... ORDER BY xyz
  **
  ** is transformed to:
  **
  **     SELECT xyz FROM ... GROUP BY xyz
  **
  ** The second form is preferred as a single index (or temp-table) may be 
  ** used for both the ORDER BY and DISTINCT processing. As originally 
  ** written the query must use a temp-table for at least one of the ORDER 
  ** BY and DISTINCT, and an index or separate temp-table for the other.
  */
  if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct 
   && sqlite3ExprListCompare(pOrderBy, p->pEList)==0
  ){
    p->selFlags &= ~SF_Distinct;
    p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
    pGroupBy = p->pGroupBy;
    pOrderBy = 0;
  }

  /* If there is an ORDER BY clause, then this sorting
  ** index might end up being unused if the data can be 
  ** extracted in pre-sorted order.  If that is the case, then the
  ** OP_OpenEphemeral instruction will be changed to an OP_Noop once
  ** we figure out that the sorting index is not needed.  The addrSortIndex
  ** variable is used to facilitate that change.
  */







>
>
>
>
>
>
>
>
>
>













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







94308
94309
94310
94311
94312
94313
94314
94315
94316
94317
94318
94319
94320
94321
94322
94323
94324
94325
94326
94327
94328
94329
94330
94331
94332
94333
94334
94335
94336
94337
























94338
94339
94340
94341
94342
94343
94344
      }
    }
    rc = multiSelect(pParse, p, pDest);
    explainSetInteger(pParse->iSelectId, iRestoreSelectId);
    return rc;
  }
#endif

  /* If possible, rewrite the query to use GROUP BY instead of DISTINCT.
  ** GROUP BY might use an index, DISTINCT never does.
  */
  assert( p->pGroupBy==0 || (p->selFlags & SF_Aggregate)!=0 );
  if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct ){
    p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
    pGroupBy = p->pGroupBy;
    p->selFlags &= ~SF_Distinct;
  }

  /* If there is both a GROUP BY and an ORDER BY clause and they are
  ** identical, then disable the ORDER BY clause since the GROUP BY
  ** will cause elements to come out in the correct order.  This is
  ** an optimization - the correct answer should result regardless.
  ** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER
  ** to disable this optimization for testing purposes.
  */
  if( sqlite3ExprListCompare(p->pGroupBy, pOrderBy)==0
         && (db->flags & SQLITE_GroupByOrder)==0 ){
    pOrderBy = 0;
  }

























  /* If there is an ORDER BY clause, then this sorting
  ** index might end up being unused if the data can be 
  ** extracted in pre-sorted order.  If that is the case, then the
  ** OP_OpenEphemeral instruction will be changed to an OP_Noop once
  ** we figure out that the sorting index is not needed.  The addrSortIndex
  ** variable is used to facilitate that change.
  */
96303
96304
96305
96306
96307
96308
96309
96310
96311
96312
96313
96314
96315
96316
96317
96318

96319
96320
96321
96322
96323
96324
96325
96326
96327
96328
96329
96330
96331
96332

96333
96334
96335
96336
96337
96338
96339
96340
96341
96342
96343
96344
96345
96346
96347
96348
96349
96350
96351
96352
96353
96354
96355
96356
96357
96358
96359
96360
96361
96362
96363
96364
96365
96366
96367
96368
96369
96370
96371
96372
96373
96374
96375
96376
96377
96378
96379
96380
96381
96382
96383
96384
96385
96386
96387
96388
96389
96390
96391
96392
96393
96394
96395
96396
96397
96398
96399
96400
96401
96402
96403
96404
96405
96406
96407
96408
96409
96410
96411
96412
96413
96414
96415
96416
  }

  /* Set the limiter.
  */
  iEnd = sqlite3VdbeMakeLabel(v);
  p->nSelectRow = (double)LARGEST_INT64;
  computeLimitRegisters(pParse, p, iEnd);
  if( p->iLimit==0 && addrSortIndex>=0 ){
    sqlite3VdbeGetOp(v, addrSortIndex)->opcode = OP_SorterOpen;
    p->selFlags |= SF_UseSorter;
  }

  /* Open a virtual index to use for the distinct set.
  */
  if( p->selFlags & SF_Distinct ){
    KeyInfo *pKeyInfo;

    distinct = pParse->nTab++;
    pKeyInfo = keyInfoFromExprList(pParse, p->pEList);
    addrDistinctIndex = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, distinct, 0, 0,
        (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
    sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
  }else{
    distinct = addrDistinctIndex = -1;
  }

  /* Aggregate and non-aggregate queries are handled differently */
  if( !isAgg && pGroupBy==0 ){
    ExprList *pDist = (isDistinct ? p->pEList : 0);

    /* Begin the database scan. */

    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, pDist, 0);
    if( pWInfo==0 ) goto select_end;
    if( pWInfo->nRowOut < p->nSelectRow ) p->nSelectRow = pWInfo->nRowOut;

    /* If sorting index that was created by a prior OP_OpenEphemeral 
    ** instruction ended up not being needed, then change the OP_OpenEphemeral
    ** into an OP_Noop.
    */
    if( addrSortIndex>=0 && pOrderBy==0 ){
      sqlite3VdbeChangeToNoop(v, addrSortIndex);
      p->addrOpenEphm[2] = -1;
    }

    if( pWInfo->eDistinct ){
      VdbeOp *pOp;                /* No longer required OpenEphemeral instr. */
     
      assert( addrDistinctIndex>=0 );
      pOp = sqlite3VdbeGetOp(v, addrDistinctIndex);

      assert( isDistinct );
      assert( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED 
           || pWInfo->eDistinct==WHERE_DISTINCT_UNIQUE 
      );
      distinct = -1;
      if( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED ){
        int iJump;
        int iExpr;
        int iFlag = ++pParse->nMem;
        int iBase = pParse->nMem+1;
        int iBase2 = iBase + pEList->nExpr;
        pParse->nMem += (pEList->nExpr*2);

        /* Change the OP_OpenEphemeral coded earlier to an OP_Integer. The
        ** OP_Integer initializes the "first row" flag.  */
        pOp->opcode = OP_Integer;
        pOp->p1 = 1;
        pOp->p2 = iFlag;

        sqlite3ExprCodeExprList(pParse, pEList, iBase, 1);
        iJump = sqlite3VdbeCurrentAddr(v) + 1 + pEList->nExpr + 1 + 1;
        sqlite3VdbeAddOp2(v, OP_If, iFlag, iJump-1);
        for(iExpr=0; iExpr<pEList->nExpr; iExpr++){
          CollSeq *pColl = sqlite3ExprCollSeq(pParse, pEList->a[iExpr].pExpr);
          sqlite3VdbeAddOp3(v, OP_Ne, iBase+iExpr, iJump, iBase2+iExpr);
          sqlite3VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ);
          sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
        }
        sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo->iContinue);

        sqlite3VdbeAddOp2(v, OP_Integer, 0, iFlag);
        assert( sqlite3VdbeCurrentAddr(v)==iJump );
        sqlite3VdbeAddOp3(v, OP_Move, iBase, iBase2, pEList->nExpr);
      }else{
        pOp->opcode = OP_Noop;
      }
    }

    /* Use the standard inner loop. */
    selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, pDest,
                    pWInfo->iContinue, pWInfo->iBreak);

    /* End the database scan loop.
    */
    sqlite3WhereEnd(pWInfo);
  }else{
    /* This is the processing for aggregate queries */
    NameContext sNC;    /* Name context for processing aggregate information */
    int iAMem;          /* First Mem address for storing current GROUP BY */
    int iBMem;          /* First Mem address for previous GROUP BY */
    int iUseFlag;       /* Mem address holding flag indicating that at least
                        ** one row of the input to the aggregator has been
                        ** processed */
    int iAbortFlag;     /* Mem address which causes query abort if positive */
    int groupBySort;    /* Rows come from source in GROUP BY order */
    int addrEnd;        /* End of processing for this SELECT */
    int sortPTab = 0;   /* Pseudotable used to decode sorting results */
    int sortOut = 0;    /* Output register from the sorter */

    /* Remove any and all aliases between the result set and the
    ** GROUP BY clause.
    */
    if( pGroupBy ){
      int k;                        /* Loop counter */
      struct ExprList_item *pItem;  /* For looping over expression in a list */







<
<
<
<





>


|
|


|




<
|
|
>
|








|



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
















<
<







94361
94362
94363
94364
94365
94366
94367




94368
94369
94370
94371
94372
94373
94374
94375
94376
94377
94378
94379
94380
94381
94382
94383
94384

94385
94386
94387
94388
94389
94390
94391
94392
94393
94394
94395
94396
94397
94398
94399
94400


94401


94402
94403






































94404
94405
94406
94407
94408
94409
94410
94411
94412
94413
94414
94415
94416
94417
94418
94419
94420


94421
94422
94423
94424
94425
94426
94427
  }

  /* Set the limiter.
  */
  iEnd = sqlite3VdbeMakeLabel(v);
  p->nSelectRow = (double)LARGEST_INT64;
  computeLimitRegisters(pParse, p, iEnd);





  /* Open a virtual index to use for the distinct set.
  */
  if( p->selFlags & SF_Distinct ){
    KeyInfo *pKeyInfo;
    assert( isAgg || pGroupBy );
    distinct = pParse->nTab++;
    pKeyInfo = keyInfoFromExprList(pParse, p->pEList);
    sqlite3VdbeAddOp4(v, OP_OpenEphemeral, distinct, 0, 0,
                        (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
    sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
  }else{
    distinct = -1;
  }

  /* Aggregate and non-aggregate queries are handled differently */
  if( !isAgg && pGroupBy==0 ){

    /* This case is for non-aggregate queries
    ** Begin the database scan
    */
    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, 0);
    if( pWInfo==0 ) goto select_end;
    if( pWInfo->nRowOut < p->nSelectRow ) p->nSelectRow = pWInfo->nRowOut;

    /* If sorting index that was created by a prior OP_OpenEphemeral 
    ** instruction ended up not being needed, then change the OP_OpenEphemeral
    ** into an OP_Noop.
    */
    if( addrSortIndex>=0 && pOrderBy==0 ){
      sqlite3VdbeChangeToNoop(v, addrSortIndex, 1);
      p->addrOpenEphm[2] = -1;
    }



    /* Use the standard inner loop


    */
    assert(!isDistinct);






































    selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, -1, pDest,
                    pWInfo->iContinue, pWInfo->iBreak);

    /* End the database scan loop.
    */
    sqlite3WhereEnd(pWInfo);
  }else{
    /* This is the processing for aggregate queries */
    NameContext sNC;    /* Name context for processing aggregate information */
    int iAMem;          /* First Mem address for storing current GROUP BY */
    int iBMem;          /* First Mem address for previous GROUP BY */
    int iUseFlag;       /* Mem address holding flag indicating that at least
                        ** one row of the input to the aggregator has been
                        ** processed */
    int iAbortFlag;     /* Mem address which causes query abort if positive */
    int groupBySort;    /* Rows come from source in GROUP BY order */
    int addrEnd;        /* End of processing for this SELECT */



    /* Remove any and all aliases between the result set and the
    ** GROUP BY clause.
    */
    if( pGroupBy ){
      int k;                        /* Loop counter */
      struct ExprList_item *pItem;  /* For looping over expression in a list */
96464
96465
96466
96467
96468
96469
96470
96471
96472
96473
96474
96475
96476
96477
96478
96479
96480
96481
96482
96483
      int addrTopOfLoop;  /* Top of the input loop */
      int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */
      int addrReset;      /* Subroutine for resetting the accumulator */
      int regReset;       /* Return address register for reset subroutine */

      /* If there is a GROUP BY clause we might need a sorting index to
      ** implement it.  Allocate that sorting index now.  If it turns out
      ** that we do not need it after all, the OP_SorterOpen instruction
      ** will be converted into a Noop.  
      */
      sAggInfo.sortingIdx = pParse->nTab++;
      pKeyInfo = keyInfoFromExprList(pParse, pGroupBy);
      addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen, 
          sAggInfo.sortingIdx, sAggInfo.nSortingColumn, 
          0, (char*)pKeyInfo, P4_KEYINFO_HANDOFF);

      /* Initialize memory locations used by GROUP BY aggregate processing
      */
      iUseFlag = ++pParse->nMem;
      iAbortFlag = ++pParse->nMem;







|




|







94475
94476
94477
94478
94479
94480
94481
94482
94483
94484
94485
94486
94487
94488
94489
94490
94491
94492
94493
94494
      int addrTopOfLoop;  /* Top of the input loop */
      int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */
      int addrReset;      /* Subroutine for resetting the accumulator */
      int regReset;       /* Return address register for reset subroutine */

      /* If there is a GROUP BY clause we might need a sorting index to
      ** implement it.  Allocate that sorting index now.  If it turns out
      ** that we do not need it after all, the OpenEphemeral instruction
      ** will be converted into a Noop.  
      */
      sAggInfo.sortingIdx = pParse->nTab++;
      pKeyInfo = keyInfoFromExprList(pParse, pGroupBy);
      addrSortingIdx = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, 
          sAggInfo.sortingIdx, sAggInfo.nSortingColumn, 
          0, (char*)pKeyInfo, P4_KEYINFO_HANDOFF);

      /* Initialize memory locations used by GROUP BY aggregate processing
      */
      iUseFlag = ++pParse->nMem;
      iAbortFlag = ++pParse->nMem;
96496
96497
96498
96499
96500
96501
96502
96503
96504
96505
96506
96507
96508
96509
96510

      /* Begin a loop that will extract all source rows in GROUP BY order.
      ** This might involve two separate loops with an OP_Sort in between, or
      ** it might be a single loop that uses an index to extract information
      ** in the right order to begin with.
      */
      sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
      pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0, 0);
      if( pWInfo==0 ) goto select_end;
      if( pGroupBy==0 ){
        /* The optimizer is able to deliver rows in group by order so
        ** we do not have to sort.  The OP_OpenEphemeral table will be
        ** cancelled later because we still need to use the pKeyInfo
        */
        pGroupBy = p->pGroupBy;







|







94507
94508
94509
94510
94511
94512
94513
94514
94515
94516
94517
94518
94519
94520
94521

      /* Begin a loop that will extract all source rows in GROUP BY order.
      ** This might involve two separate loops with an OP_Sort in between, or
      ** it might be a single loop that uses an index to extract information
      ** in the right order to begin with.
      */
      sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
      pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0);
      if( pWInfo==0 ) goto select_end;
      if( pGroupBy==0 ){
        /* The optimizer is able to deliver rows in group by order so
        ** we do not have to sort.  The OP_OpenEphemeral table will be
        ** cancelled later because we still need to use the pKeyInfo
        */
        pGroupBy = p->pGroupBy;
96550
96551
96552
96553
96554
96555
96556
96557
96558
96559
96560
96561
96562
96563
96564
96565
96566
96567
96568
96569
96570
96571
96572
96573
96574
96575
96576
96577
96578
96579
96580
96581
96582
96583
96584
96585
96586
96587
96588
96589
96590
              sqlite3VdbeAddOp2(v, OP_SCopy, r2, r1);
            }
            j++;
          }
        }
        regRecord = sqlite3GetTempReg(pParse);
        sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord);
        sqlite3VdbeAddOp2(v, OP_SorterInsert, sAggInfo.sortingIdx, regRecord);
        sqlite3ReleaseTempReg(pParse, regRecord);
        sqlite3ReleaseTempRange(pParse, regBase, nCol);
        sqlite3WhereEnd(pWInfo);
        sAggInfo.sortingIdxPTab = sortPTab = pParse->nTab++;
        sortOut = sqlite3GetTempReg(pParse);
        sqlite3VdbeAddOp3(v, OP_OpenPseudo, sortPTab, sortOut, nCol);
        sqlite3VdbeAddOp2(v, OP_SorterSort, sAggInfo.sortingIdx, addrEnd);
        VdbeComment((v, "GROUP BY sort"));
        sAggInfo.useSortingIdx = 1;
        sqlite3ExprCacheClear(pParse);
      }

      /* Evaluate the current GROUP BY terms and store in b0, b1, b2...
      ** (b0 is memory location iBMem+0, b1 is iBMem+1, and so forth)
      ** Then compare the current GROUP BY terms against the GROUP BY terms
      ** from the previous row currently stored in a0, a1, a2...
      */
      addrTopOfLoop = sqlite3VdbeCurrentAddr(v);
      sqlite3ExprCacheClear(pParse);
      if( groupBySort ){
        sqlite3VdbeAddOp2(v, OP_SorterData, sAggInfo.sortingIdx, sortOut);
      }
      for(j=0; j<pGroupBy->nExpr; j++){
        if( groupBySort ){
          sqlite3VdbeAddOp3(v, OP_Column, sortPTab, j, iBMem+j);
          if( j==0 ) sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE);
        }else{
          sAggInfo.directMode = 1;
          sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j);
        }
      }
      sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr,
                          (char*)pKeyInfo, P4_KEYINFO);







|



<
<
<
|












<
<
<


|
<







94561
94562
94563
94564
94565
94566
94567
94568
94569
94570
94571



94572
94573
94574
94575
94576
94577
94578
94579
94580
94581
94582
94583
94584



94585
94586
94587

94588
94589
94590
94591
94592
94593
94594
              sqlite3VdbeAddOp2(v, OP_SCopy, r2, r1);
            }
            j++;
          }
        }
        regRecord = sqlite3GetTempReg(pParse);
        sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord);
        sqlite3VdbeAddOp2(v, OP_IdxInsert, sAggInfo.sortingIdx, regRecord);
        sqlite3ReleaseTempReg(pParse, regRecord);
        sqlite3ReleaseTempRange(pParse, regBase, nCol);
        sqlite3WhereEnd(pWInfo);



        sqlite3VdbeAddOp2(v, OP_Sort, sAggInfo.sortingIdx, addrEnd);
        VdbeComment((v, "GROUP BY sort"));
        sAggInfo.useSortingIdx = 1;
        sqlite3ExprCacheClear(pParse);
      }

      /* Evaluate the current GROUP BY terms and store in b0, b1, b2...
      ** (b0 is memory location iBMem+0, b1 is iBMem+1, and so forth)
      ** Then compare the current GROUP BY terms against the GROUP BY terms
      ** from the previous row currently stored in a0, a1, a2...
      */
      addrTopOfLoop = sqlite3VdbeCurrentAddr(v);
      sqlite3ExprCacheClear(pParse);



      for(j=0; j<pGroupBy->nExpr; j++){
        if( groupBySort ){
          sqlite3VdbeAddOp3(v, OP_Column, sAggInfo.sortingIdx, j, iBMem+j);

        }else{
          sAggInfo.directMode = 1;
          sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j);
        }
      }
      sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr,
                          (char*)pKeyInfo, P4_KEYINFO);
96615
96616
96617
96618
96619
96620
96621
96622
96623
96624
96625
96626
96627
96628
96629
96630
96631
96632
      updateAccumulator(pParse, &sAggInfo);
      sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag);
      VdbeComment((v, "indicate data in accumulator"));

      /* End of the loop
      */
      if( groupBySort ){
        sqlite3VdbeAddOp2(v, OP_SorterNext, sAggInfo.sortingIdx, addrTopOfLoop);
      }else{
        sqlite3WhereEnd(pWInfo);
        sqlite3VdbeChangeToNoop(v, addrSortingIdx);
      }

      /* Output the final row of result
      */
      sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
      VdbeComment((v, "output final row"));








|


|







94619
94620
94621
94622
94623
94624
94625
94626
94627
94628
94629
94630
94631
94632
94633
94634
94635
94636
      updateAccumulator(pParse, &sAggInfo);
      sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag);
      VdbeComment((v, "indicate data in accumulator"));

      /* End of the loop
      */
      if( groupBySort ){
        sqlite3VdbeAddOp2(v, OP_Next, sAggInfo.sortingIdx, addrTopOfLoop);
      }else{
        sqlite3WhereEnd(pWInfo);
        sqlite3VdbeChangeToNoop(v, addrSortingIdx, 1);
      }

      /* Output the final row of result
      */
      sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
      VdbeComment((v, "output final row"));

96765
96766
96767
96768
96769
96770
96771
96772
96773
96774
96775
96776
96777
96778
96779
        }
  
        /* This case runs if the aggregate has no GROUP BY clause.  The
        ** processing is much simpler since there is only a single row
        ** of output.
        */
        resetAccumulator(pParse, &sAggInfo);
        pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax, 0, flag);
        if( pWInfo==0 ){
          sqlite3ExprListDelete(db, pDel);
          goto select_end;
        }
        updateAccumulator(pParse, &sAggInfo);
        if( !pMinMax && flag ){
          sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo->iBreak);







|







94769
94770
94771
94772
94773
94774
94775
94776
94777
94778
94779
94780
94781
94782
94783
        }
  
        /* This case runs if the aggregate has no GROUP BY clause.  The
        ** processing is much simpler since there is only a single row
        ** of output.
        */
        resetAccumulator(pParse, &sAggInfo);
        pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax, flag);
        if( pWInfo==0 ){
          sqlite3ExprListDelete(db, pDel);
          goto select_end;
        }
        updateAccumulator(pParse, &sAggInfo);
        if( !pMinMax && flag ){
          sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo->iBreak);
96944
96945
96946
96947
96948
96949
96950
96951
96952
96953
96954
96955
96956
96957
96958
96959
** This file contains the sqlite3_get_table() and sqlite3_free_table()
** interface routines.  These are just wrappers around the main
** interface routine of sqlite3_exec().
**
** These routines are in a separate files so that they will not be linked
** if they are not used.
*/
/* #include <stdlib.h> */
/* #include <string.h> */

#ifndef SQLITE_OMIT_GET_TABLE

/*
** This structure is used to pass data from sqlite3_get_table() through
** to the callback function is uses to build the result.
*/







<
<







94948
94949
94950
94951
94952
94953
94954


94955
94956
94957
94958
94959
94960
94961
** This file contains the sqlite3_get_table() and sqlite3_free_table()
** interface routines.  These are just wrappers around the main
** interface routine of sqlite3_exec().
**
** These routines are in a separate files so that they will not be linked
** if they are not used.
*/



#ifndef SQLITE_OMIT_GET_TABLE

/*
** This structure is used to pass data from sqlite3_get_table() through
** to the callback function is uses to build the result.
*/
97243
97244
97245
97246
97247
97248
97249
97250
97251
97252
97253
97254
97255
97256
97257
97258
97259
97260
97261
97262
97263
97264
97265
97266
97267
97268
97269
97270
97271



97272
97273
97274
97275
97276
97277
97278
  }else{
    /* Figure out the db that the the trigger will be created in */
    iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
    if( iDb<0 ){
      goto trigger_cleanup;
    }
  }
  if( !pTableName || db->mallocFailed ){
    goto trigger_cleanup;
  }

  /* A long-standing parser bug is that this syntax was allowed:
  **
  **    CREATE TRIGGER attached.demo AFTER INSERT ON attached.tab ....
  **                                                 ^^^^^^^^
  **
  ** To maintain backwards compatibility, ignore the database
  ** name on pTableName if we are reparsing our of SQLITE_MASTER.
  */
  if( db->init.busy && iDb!=1 ){
    sqlite3DbFree(db, pTableName->a[0].zDatabase);
    pTableName->a[0].zDatabase = 0;
  }

  /* If the trigger name was unqualified, and the table is a temp table,
  ** then set iDb to 1 to create the trigger in the temporary database.
  ** If sqlite3SrcListLookup() returns 0, indicating the table does not
  ** exist, the error is caught by the block below.
  */



  pTab = sqlite3SrcListLookup(pParse, pTableName);
  if( db->init.busy==0 && pName2->n==0 && pTab
        && pTab->pSchema==db->aDb[1].pSchema ){
    iDb = 1;
  }

  /* Ensure the table name matches database name and that the table exists */







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






>
>
>







95245
95246
95247
95248
95249
95250
95251
















95252
95253
95254
95255
95256
95257
95258
95259
95260
95261
95262
95263
95264
95265
95266
95267
  }else{
    /* Figure out the db that the the trigger will be created in */
    iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
    if( iDb<0 ){
      goto trigger_cleanup;
    }
  }

















  /* If the trigger name was unqualified, and the table is a temp table,
  ** then set iDb to 1 to create the trigger in the temporary database.
  ** If sqlite3SrcListLookup() returns 0, indicating the table does not
  ** exist, the error is caught by the block below.
  */
  if( !pTableName || db->mallocFailed ){
    goto trigger_cleanup;
  }
  pTab = sqlite3SrcListLookup(pParse, pTableName);
  if( db->init.busy==0 && pName2->n==0 && pTab
        && pTab->pSchema==db->aDb[1].pSchema ){
    iDb = 1;
  }

  /* Ensure the table name matches database name and that the table exists */
98562
98563
98564
98565
98566
98567
98568
98569
98570
98571
98572
98573
98574
98575
98576
98577
98578
  if( sqlite3ResolveExprNames(&sNC, pWhere) ){
    goto update_cleanup;
  }

  /* Begin the database scan
  */
  sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid);
  pWInfo = sqlite3WhereBegin(
      pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED
  );
  if( pWInfo==0 ) goto update_cleanup;
  okOnePass = pWInfo->okOnePass;

  /* Remember the rowid of every item to be updated.
  */
  sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regOldRowid);
  if( !okOnePass ){







|
<
<







96551
96552
96553
96554
96555
96556
96557
96558


96559
96560
96561
96562
96563
96564
96565
  if( sqlite3ResolveExprNames(&sNC, pWhere) ){
    goto update_cleanup;
  }

  /* Begin the database scan
  */
  sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid);
  pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0, WHERE_ONEPASS_DESIRED);


  if( pWInfo==0 ) goto update_cleanup;
  okOnePass = pWInfo->okOnePass;

  /* Remember the rowid of every item to be updated.
  */
  sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regOldRowid);
  if( !okOnePass ){
100590
100591
100592
100593
100594
100595
100596
100597
100598
100599
100600
100601
100602
100603
100604
#define WHERE_IDX_ONLY     0x00800000  /* Use index only - omit table */
#define WHERE_ORDERBY      0x01000000  /* Output will appear in correct order */
#define WHERE_REVERSE      0x02000000  /* Scan in reverse order */
#define WHERE_UNIQUE       0x04000000  /* Selects no more than one row */
#define WHERE_VIRTUALTABLE 0x08000000  /* Use virtual-table processing */
#define WHERE_MULTI_OR     0x10000000  /* OR using multiple indices */
#define WHERE_TEMP_INDEX   0x20000000  /* Uses an ephemeral index */
#define WHERE_DISTINCT     0x40000000  /* Correct order for DISTINCT */

/*
** Initialize a preallocated WhereClause structure.
*/
static void whereClauseInit(
  WhereClause *pWC,        /* The WhereClause to be initialized */
  Parse *pParse,           /* The parsing context */







<







98577
98578
98579
98580
98581
98582
98583

98584
98585
98586
98587
98588
98589
98590
#define WHERE_IDX_ONLY     0x00800000  /* Use index only - omit table */
#define WHERE_ORDERBY      0x01000000  /* Output will appear in correct order */
#define WHERE_REVERSE      0x02000000  /* Scan in reverse order */
#define WHERE_UNIQUE       0x04000000  /* Selects no more than one row */
#define WHERE_VIRTUALTABLE 0x08000000  /* Use virtual-table processing */
#define WHERE_MULTI_OR     0x10000000  /* OR using multiple indices */
#define WHERE_TEMP_INDEX   0x20000000  /* Uses an ephemeral index */


/*
** Initialize a preallocated WhereClause structure.
*/
static void whereClauseInit(
  WhereClause *pWC,        /* The WhereClause to be initialized */
  Parse *pParse,           /* The parsing context */
100804
100805
100806
100807
100808
100809
100810
100811
100812
100813
100814
100815
100816
100817
100818
100819
100820
100821
100822
100823
100824
100825
100826
100827
100828
100829
100830
    }
  }
  return mask;
}
static Bitmask exprSelectTableUsage(WhereMaskSet *pMaskSet, Select *pS){
  Bitmask mask = 0;
  while( pS ){
    SrcList *pSrc = pS->pSrc;
    mask |= exprListTableUsage(pMaskSet, pS->pEList);
    mask |= exprListTableUsage(pMaskSet, pS->pGroupBy);
    mask |= exprListTableUsage(pMaskSet, pS->pOrderBy);
    mask |= exprTableUsage(pMaskSet, pS->pWhere);
    mask |= exprTableUsage(pMaskSet, pS->pHaving);
    if( ALWAYS(pSrc!=0) ){
      int i;
      for(i=0; i<pSrc->nSrc; i++){
        mask |= exprSelectTableUsage(pMaskSet, pSrc->a[i].pSelect);
        mask |= exprTableUsage(pMaskSet, pSrc->a[i].pOn);
      }
    }
    pS = pS->pPrior;
  }
  return mask;
}

/*
** Return TRUE if the given operator is one of the operators that is







<





<
<
<
<
<
<
<







98790
98791
98792
98793
98794
98795
98796

98797
98798
98799
98800
98801







98802
98803
98804
98805
98806
98807
98808
    }
  }
  return mask;
}
static Bitmask exprSelectTableUsage(WhereMaskSet *pMaskSet, Select *pS){
  Bitmask mask = 0;
  while( pS ){

    mask |= exprListTableUsage(pMaskSet, pS->pEList);
    mask |= exprListTableUsage(pMaskSet, pS->pGroupBy);
    mask |= exprListTableUsage(pMaskSet, pS->pOrderBy);
    mask |= exprTableUsage(pMaskSet, pS->pWhere);
    mask |= exprTableUsage(pMaskSet, pS->pHaving);







    pS = pS->pPrior;
  }
  return mask;
}

/*
** Return TRUE if the given operator is one of the operators that is
101743
101744
101745
101746
101747
101748
101749
101750
101751
101752
101753
101754
101755
101756
101757
101758
101759
101760
101761
101762
101763
101764
101765
101766
101767
101768
101769
101770
101771
101772
101773
101774
101775
101776
101777
101778
101779
101780
101781
101782
101783
101784
101785
101786
101787
101788
101789
101790
101791
101792
101793
101794
101795
101796
101797
101798
101799
101800
101801
101802
101803
101804
101805
101806
101807
101808
101809
101810
101811
101812
101813
101814
101815
101816
101817
101818
101819
101820
101821
101822
101823
101824
101825
101826
101827
101828
101829
101830
101831
101832
101833
101834
101835
101836
101837
101838
101839
101840
101841
101842
101843
101844
101845
101846
101847
101848
101849
101850
101851
101852
101853
101854
101855
101856
101857
101858
101859
101860
101861
101862
101863
101864
101865
101866
101867
101868
101869
101870
101871
101872
101873
101874
101875
101876
101877
101878
101879
101880
101881
101882
101883
101884
101885
101886
101887
101888
101889
101890
101891
101892
101893
101894
101895
101896
101897
101898
101899
101900
101901
101902
101903
101904
101905
101906
101907
101908
101909
101910
101911
101912
    if( (exprTableUsage(pMaskSet, pList->a[iFirst++].pExpr)&allowed)!=0 ){
      return 1;
    }
  }
  return 0;
}

/*
** This function searches the expression list passed as the second argument
** for an expression of type TK_COLUMN that refers to the same column and
** uses the same collation sequence as the iCol'th column of index pIdx.
** Argument iBase is the cursor number used for the table that pIdx refers
** to.
**
** If such an expression is found, its index in pList->a[] is returned. If
** no expression is found, -1 is returned.
*/
static int findIndexCol(
  Parse *pParse,                  /* Parse context */
  ExprList *pList,                /* Expression list to search */
  int iBase,                      /* Cursor for table associated with pIdx */
  Index *pIdx,                    /* Index to match column of */
  int iCol                        /* Column of index to match */
){
  int i;
  const char *zColl = pIdx->azColl[iCol];

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

  return -1;
}

/*
** This routine determines if pIdx can be used to assist in processing a
** DISTINCT qualifier. In other words, it tests whether or not using this
** index for the outer loop guarantees that rows with equal values for
** all expressions in the pDistinct list are delivered grouped together.
**
** For example, the query 
**
**   SELECT DISTINCT a, b, c FROM tbl WHERE a = ?
**
** can benefit from any index on columns "b" and "c".
*/
static int isDistinctIndex(
  Parse *pParse,                  /* Parsing context */
  WhereClause *pWC,               /* The WHERE clause */
  Index *pIdx,                    /* The index being considered */
  int base,                       /* Cursor number for the table pIdx is on */
  ExprList *pDistinct,            /* The DISTINCT expressions */
  int nEqCol                      /* Number of index columns with == */
){
  Bitmask mask = 0;               /* Mask of unaccounted for pDistinct exprs */
  int i;                          /* Iterator variable */

  if( pIdx->zName==0 || pDistinct==0 || pDistinct->nExpr>=BMS ) return 0;
  testcase( pDistinct->nExpr==BMS-1 );

  /* Loop through all the expressions in the distinct list. If any of them
  ** are not simple column references, return early. Otherwise, test if the
  ** WHERE clause contains a "col=X" clause. If it does, the expression
  ** can be ignored. If it does not, and the column does not belong to the
  ** same table as index pIdx, return early. Finally, if there is no
  ** matching "col=X" expression and the column is on the same table as pIdx,
  ** set the corresponding bit in variable mask.
  */
  for(i=0; i<pDistinct->nExpr; i++){
    WhereTerm *pTerm;
    Expr *p = pDistinct->a[i].pExpr;
    if( p->op!=TK_COLUMN ) return 0;
    pTerm = findTerm(pWC, p->iTable, p->iColumn, ~(Bitmask)0, WO_EQ, 0);
    if( pTerm ){
      Expr *pX = pTerm->pExpr;
      CollSeq *p1 = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
      CollSeq *p2 = sqlite3ExprCollSeq(pParse, p);
      if( p1==p2 ) continue;
    }
    if( p->iTable!=base ) return 0;
    mask |= (((Bitmask)1) << i);
  }

  for(i=nEqCol; mask && i<pIdx->nColumn; i++){
    int iExpr = findIndexCol(pParse, pDistinct, base, pIdx, i);
    if( iExpr<0 ) break;
    mask &= ~(((Bitmask)1) << iExpr);
  }

  return (mask==0);
}


/*
** Return true if the DISTINCT expression-list passed as the third argument
** is redundant. A DISTINCT list is redundant if the database contains a
** UNIQUE index that guarantees that the result of the query will be distinct
** anyway.
*/
static int isDistinctRedundant(
  Parse *pParse,
  SrcList *pTabList,
  WhereClause *pWC,
  ExprList *pDistinct
){
  Table *pTab;
  Index *pIdx;
  int i;                          
  int iBase;

  /* If there is more than one table or sub-select in the FROM clause of
  ** this query, then it will not be possible to show that the DISTINCT 
  ** clause is redundant. */
  if( pTabList->nSrc!=1 ) return 0;
  iBase = pTabList->a[0].iCursor;
  pTab = pTabList->a[0].pTab;

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

  /* Loop through all indices on the table, checking each to see if it makes
  ** the DISTINCT qualifier redundant. It does so if:
  **
  **   1. The index is itself UNIQUE, and
  **
  **   2. All of the columns in the index are either part of the pDistinct
  **      list, or else the WHERE clause contains a term of the form "col=X",
  **      where X is a constant value. The collation sequences of the
  **      comparison and select-list expressions must match those of the index.
  */
  for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
    if( pIdx->onError==OE_None ) continue;
    for(i=0; i<pIdx->nColumn; i++){
      int iCol = pIdx->aiColumn[i];
      if( 0==findTerm(pWC, iBase, iCol, ~(Bitmask)0, WO_EQ, pIdx) 
       && 0>findIndexCol(pParse, pDistinct, iBase, pIdx, i)
      ){
        break;
      }
    }
    if( i==pIdx->nColumn ){
      /* This index implies that the DISTINCT qualifier is redundant. */
      return 1;
    }
  }

  return 0;
}

/*
** This routine decides if pIdx can be used to satisfy the ORDER BY
** clause.  If it can, it returns 1.  If pIdx cannot satisfy the
** ORDER BY clause, this routine returns 0.
**
** pOrderBy is an ORDER BY clause from a SELECT statement.  pTab is the







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







99721
99722
99723
99724
99725
99726
99727




























































































































































99728
99729
99730
99731
99732
99733
99734
    if( (exprTableUsage(pMaskSet, pList->a[iFirst++].pExpr)&allowed)!=0 ){
      return 1;
    }
  }
  return 0;
}






























































































































































/*
** This routine decides if pIdx can be used to satisfy the ORDER BY
** clause.  If it can, it returns 1.  If pIdx cannot satisfy the
** ORDER BY clause, this routine returns 0.
**
** pOrderBy is an ORDER BY clause from a SELECT statement.  pTab is the
101935
101936
101937
101938
101939
101940
101941
101942
101943
101944
101945
101946
101947
101948
101949
101950
101951
101952
){
  int i, j;                       /* Loop counters */
  int sortOrder = 0;              /* XOR of index and ORDER BY sort direction */
  int nTerm;                      /* Number of ORDER BY terms */
  struct ExprList_item *pTerm;    /* A term of the ORDER BY clause */
  sqlite3 *db = pParse->db;

  if( !pOrderBy ) return 0;
  if( wsFlags & WHERE_COLUMN_IN ) return 0;
  if( pIdx->bUnordered ) return 0;

  nTerm = pOrderBy->nExpr;
  assert( nTerm>0 );

  /* Argument pIdx must either point to a 'real' named index structure, 
  ** or an index structure allocated on the stack by bestBtreeIndex() to
  ** represent the rowid index that is part of every table.  */
  assert( pIdx->zName || (pIdx->nColumn==1 && pIdx->aiColumn[0]==-1) );







|
<
<
<







99757
99758
99759
99760
99761
99762
99763
99764



99765
99766
99767
99768
99769
99770
99771
){
  int i, j;                       /* Loop counters */
  int sortOrder = 0;              /* XOR of index and ORDER BY sort direction */
  int nTerm;                      /* Number of ORDER BY terms */
  struct ExprList_item *pTerm;    /* A term of the ORDER BY clause */
  sqlite3 *db = pParse->db;

  assert( pOrderBy!=0 );



  nTerm = pOrderBy->nExpr;
  assert( nTerm>0 );

  /* Argument pIdx must either point to a 'real' named index structure, 
  ** or an index structure allocated on the stack by bestBtreeIndex() to
  ** represent the rowid index that is part of every table.  */
  assert( pIdx->zName || (pIdx->nColumn==1 && pIdx->aiColumn[0]==-1) );
102251
102252
102253
102254
102255
102256
102257
102258
102259
102260
102261
102262
102263
102264
102265
102266
102267
102268
102269
102270
102271
102272
102273
102274
102275
102276
102277
102278
102279
102280
102281
102282
102283
102284
  double nTableRow;           /* Rows in the input table */
  double logN;                /* log(nTableRow) */
  double costTempIdx;         /* per-query cost of the transient index */
  WhereTerm *pTerm;           /* A single term of the WHERE clause */
  WhereTerm *pWCEnd;          /* End of pWC->a[] */
  Table *pTable;              /* Table tht might be indexed */

  if( pParse->nQueryLoop<=(double)1 ){
    /* There is no point in building an automatic index for a single scan */
    return;
  }
  if( (pParse->db->flags & SQLITE_AutoIndex)==0 ){
    /* Automatic indices are disabled at run-time */
    return;
  }
  if( (pCost->plan.wsFlags & WHERE_NOT_FULLSCAN)!=0 ){
    /* We already have some kind of index in use for this query. */
    return;
  }
  if( pSrc->notIndexed ){
    /* The NOT INDEXED clause appears in the SQL. */
    return;
  }
  if( pSrc->isCorrelated ){
    /* The source is a correlated sub-query. No point in indexing it. */
    return;
  }

  assert( pParse->nQueryLoop >= (double)1 );
  pTable = pSrc->pTab;
  nTableRow = pTable->nRowEst;
  logN = estLog(nTableRow);
  costTempIdx = 2*logN*(nTableRow/pParse->nQueryLoop + 1);
  if( costTempIdx>=pCost->rCost ){







<
<
<
<












<
<
<
<







100070
100071
100072
100073
100074
100075
100076




100077
100078
100079
100080
100081
100082
100083
100084
100085
100086
100087
100088




100089
100090
100091
100092
100093
100094
100095
  double nTableRow;           /* Rows in the input table */
  double logN;                /* log(nTableRow) */
  double costTempIdx;         /* per-query cost of the transient index */
  WhereTerm *pTerm;           /* A single term of the WHERE clause */
  WhereTerm *pWCEnd;          /* End of pWC->a[] */
  Table *pTable;              /* Table tht might be indexed */





  if( (pParse->db->flags & SQLITE_AutoIndex)==0 ){
    /* Automatic indices are disabled at run-time */
    return;
  }
  if( (pCost->plan.wsFlags & WHERE_NOT_FULLSCAN)!=0 ){
    /* We already have some kind of index in use for this query. */
    return;
  }
  if( pSrc->notIndexed ){
    /* The NOT INDEXED clause appears in the SQL. */
    return;
  }





  assert( pParse->nQueryLoop >= (double)1 );
  pTable = pSrc->pTab;
  nTableRow = pTable->nRowEst;
  logN = estLog(nTableRow);
  costTempIdx = 2*logN*(nTableRow/pParse->nQueryLoop + 1);
  if( costTempIdx>=pCost->rCost ){
102339
102340
102341
102342
102343
102344
102345
102346

102347
102348
102349
102350
102351
102352
102353
  Bitmask extraCols;          /* Bitmap of additional columns */

  /* Generate code to skip over the creation and initialization of the
  ** transient index on 2nd and subsequent iterations of the loop. */
  v = pParse->pVdbe;
  assert( v!=0 );
  regIsInit = ++pParse->nMem;
  addrInit = sqlite3VdbeAddOp1(v, OP_Once, regIsInit);


  /* Count the number of columns that will be added to the index
  ** and used to match WHERE clause constraints */
  nColumn = 0;
  pTable = pSrc->pTab;
  pWCEnd = &pWC->a[pWC->nTerm];
  idxCols = 0;







|
>







100150
100151
100152
100153
100154
100155
100156
100157
100158
100159
100160
100161
100162
100163
100164
100165
  Bitmask extraCols;          /* Bitmap of additional columns */

  /* Generate code to skip over the creation and initialization of the
  ** transient index on 2nd and subsequent iterations of the loop. */
  v = pParse->pVdbe;
  assert( v!=0 );
  regIsInit = ++pParse->nMem;
  addrInit = sqlite3VdbeAddOp1(v, OP_If, regIsInit);
  sqlite3VdbeAddOp2(v, OP_Integer, 1, regIsInit);

  /* Count the number of columns that will be added to the index
  ** and used to match WHERE clause constraints */
  nColumn = 0;
  pTable = pSrc->pTab;
  pWCEnd = &pWC->a[pWC->nTerm];
  idxCols = 0;
102486
102487
102488
102489
102490
102491
102492
102493
102494
102495
102496
102497
102498
102499
102500
  ** 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.
  */







<







100298
100299
100300
100301
100302
100303
100304

100305
100306
100307
100308
100309
100310
100311
  ** 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;

    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.
  */
102537
102538
102539
102540
102541
102542
102543
102544
102545
102546
102547
102548
102549
102550
102551

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







<







100348
100349
100350
100351
100352
100353
100354

100355
100356
100357
100358
100359
100360
100361

  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;

    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 );
103203
103204
103205
103206
103207
103208
103209
103210
103211
103212
103213
103214
103215
103216
103217
static void bestBtreeIndex(
  Parse *pParse,              /* The parsing context */
  WhereClause *pWC,           /* The WHERE clause */
  struct SrcList_item *pSrc,  /* The FROM clause term to search */
  Bitmask notReady,           /* Mask of cursors not available for indexing */
  Bitmask notValid,           /* Cursors not available for any purpose */
  ExprList *pOrderBy,         /* The ORDER BY clause */
  ExprList *pDistinct,        /* The select-list if query is DISTINCT */
  WhereCost *pCost            /* Lowest cost query plan */
){
  int iCur = pSrc->iCursor;   /* The cursor of the table to be accessed */
  Index *pProbe;              /* An index we are evaluating */
  Index *pIdx;                /* Copy of pProbe, or zero for IPK index */
  int eqTermMask;             /* Current mask of valid equality operators */
  int idxEqTermMask;          /* Index mask of valid equality operators */







<







101013
101014
101015
101016
101017
101018
101019

101020
101021
101022
101023
101024
101025
101026
static void bestBtreeIndex(
  Parse *pParse,              /* The parsing context */
  WhereClause *pWC,           /* The WHERE clause */
  struct SrcList_item *pSrc,  /* The FROM clause term to search */
  Bitmask notReady,           /* Mask of cursors not available for indexing */
  Bitmask notValid,           /* Cursors not available for any purpose */
  ExprList *pOrderBy,         /* The ORDER BY clause */

  WhereCost *pCost            /* Lowest cost query plan */
){
  int iCur = pSrc->iCursor;   /* The cursor of the table to be accessed */
  Index *pProbe;              /* An index we are evaluating */
  Index *pIdx;                /* Copy of pProbe, or zero for IPK index */
  int eqTermMask;             /* Current mask of valid equality operators */
  int idxEqTermMask;          /* Index mask of valid equality operators */
103344
103345
103346
103347
103348
103349
103350
103351
103352
103353
103354
103355
103356
103357
103358
103359
    **             SELECT a, b, c FROM tbl WHERE a = 1;
    */
    int nEq;                      /* Number of == or IN terms matching index */
    int bInEst = 0;               /* True if "x IN (SELECT...)" seen */
    int nInMul = 1;               /* Number of distinct equalities to lookup */
    int estBound = 100;           /* Estimated reduction in search space */
    int nBound = 0;               /* Number of range constraints seen */
    int bSort = !!pOrderBy;       /* True if external sort required */
    int bDist = !!pDistinct;      /* True if index cannot help with DISTINCT */
    int bLookup = 0;              /* True if not a covering index */
    WhereTerm *pTerm;             /* A single term of the WHERE clause */
#ifdef SQLITE_ENABLE_STAT2
    WhereTerm *pFirstTerm = 0;    /* First term matching the index */
#endif

    /* Determine the values of nEq and nInMul */







|
<







101153
101154
101155
101156
101157
101158
101159
101160

101161
101162
101163
101164
101165
101166
101167
    **             SELECT a, b, c FROM tbl WHERE a = 1;
    */
    int nEq;                      /* Number of == or IN terms matching index */
    int bInEst = 0;               /* True if "x IN (SELECT...)" seen */
    int nInMul = 1;               /* Number of distinct equalities to lookup */
    int estBound = 100;           /* Estimated reduction in search space */
    int nBound = 0;               /* Number of range constraints seen */
    int bSort = 0;                /* True if external sort required */

    int bLookup = 0;              /* True if not a covering index */
    WhereTerm *pTerm;             /* A single term of the WHERE clause */
#ifdef SQLITE_ENABLE_STAT2
    WhereTerm *pFirstTerm = 0;    /* First term matching the index */
#endif

    /* Determine the values of nEq and nInMul */
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
      }
    }

    /* If there is an ORDER BY clause and the index being considered will
    ** naturally scan rows in the required order, set the appropriate flags
    ** in wsFlags. Otherwise, if there is an ORDER BY clause but the index
    ** will scan rows in a different order, set the bSort variable.  */
    if( isSortingIndex(


          pParse, pWC->pMaskSet, pProbe, iCur, pOrderBy, nEq, wsFlags, &rev)

    ){
      bSort = 0;
      wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_ORDERBY;
      wsFlags |= (rev ? WHERE_REVERSE : 0);
    }


    /* If there is a DISTINCT qualifier and this index will scan rows in
    ** order of the DISTINCT expressions, clear bDist and set the appropriate
    ** flags in wsFlags. */
    if( isDistinctIndex(pParse, pWC, pProbe, iCur, pDistinct, nEq) ){
      bDist = 0;
      wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_DISTINCT;
    }

    /* If currently calculating the cost of using an index (not the IPK
    ** index), determine if all required column data may be obtained without 
    ** using the main table (i.e. if the index is a covering
    ** index for this query). If it is, set the WHERE_IDX_ONLY flag in
    ** wsFlags. Otherwise, set the bLookup variable to true.  */







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







101217
101218
101219
101220
101221
101222
101223
101224
101225
101226
101227
101228
101229

101230
101231
101232
101233
101234






101235
101236
101237
101238
101239
101240
101241
      }
    }

    /* If there is an ORDER BY clause and the index being considered will
    ** naturally scan rows in the required order, set the appropriate flags
    ** in wsFlags. Otherwise, if there is an ORDER BY clause but the index
    ** will scan rows in a different order, set the bSort variable.  */
    if( pOrderBy ){
      if( (wsFlags & WHERE_COLUMN_IN)==0
        && pProbe->bUnordered==0
        && isSortingIndex(pParse, pWC->pMaskSet, pProbe, iCur, pOrderBy,
                          nEq, wsFlags, &rev)
      ){

        wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_ORDERBY;
        wsFlags |= (rev ? WHERE_REVERSE : 0);
      }else{
        bSort = 1;
      }






    }

    /* If currently calculating the cost of using an index (not the IPK
    ** index), determine if all required column data may be obtained without 
    ** using the main table (i.e. if the index is a covering
    ** index for this query). If it is, set the WHERE_IDX_ONLY flag in
    ** wsFlags. Otherwise, set the bLookup variable to true.  */
103457
103458
103459
103460
103461
103462
103463
103464
103465
103466
103467
103468
103469
103470
103471
103472
103473
103474
103475
103476
103477
    nRow = (double)(aiRowEst[nEq] * nInMul);
    if( bInEst && nRow*2>aiRowEst[0] ){
      nRow = aiRowEst[0]/2;
      nInMul = (int)(nRow / aiRowEst[nEq]);
    }

#ifdef SQLITE_ENABLE_STAT2
    /* If the constraint is of the form x=VALUE or x IN (E1,E2,...)
    ** and we do not think that values of x are unique and if histogram
    ** data is available for column x, then it might be possible
    ** to get a better estimate on the number of rows based on
    ** VALUE and how common that value is according to the histogram.
    */
    if( nRow>(double)1 && nEq==1 && pFirstTerm!=0 && aiRowEst[1]>1 ){
      if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){
        testcase( pFirstTerm->eOperator==WO_EQ );
        testcase( pFirstTerm->eOperator==WO_ISNULL );
        whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight, &nRow);
      }else if( pFirstTerm->eOperator==WO_IN && bInEst==0 ){
        whereInScanEst(pParse, pProbe, pFirstTerm->pExpr->x.pList, &nRow);
      }







|
<




|







101262
101263
101264
101265
101266
101267
101268
101269

101270
101271
101272
101273
101274
101275
101276
101277
101278
101279
101280
101281
    nRow = (double)(aiRowEst[nEq] * nInMul);
    if( bInEst && nRow*2>aiRowEst[0] ){
      nRow = aiRowEst[0]/2;
      nInMul = (int)(nRow / aiRowEst[nEq]);
    }

#ifdef SQLITE_ENABLE_STAT2
    /* If the constraint is of the form x=VALUE and histogram

    ** data is available for column x, then it might be possible
    ** to get a better estimate on the number of rows based on
    ** VALUE and how common that value is according to the histogram.
    */
    if( nRow>(double)1 && nEq==1 && pFirstTerm!=0 ){
      if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){
        testcase( pFirstTerm->eOperator==WO_EQ );
        testcase( pFirstTerm->eOperator==WO_ISNULL );
        whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight, &nRow);
      }else if( pFirstTerm->eOperator==WO_IN && bInEst==0 ){
        whereInScanEst(pParse, pProbe, pFirstTerm->pExpr->x.pList, &nRow);
      }
103538
103539
103540
103541
103542
103543
103544
103545
103546
103547
103548
103549
103550
103551
103552
103553
103554
    /* Add in the estimated cost of sorting the result.  Actual experimental
    ** measurements of sorting performance in SQLite show that sorting time
    ** adds C*N*log10(N) to the cost, where N is the number of rows to be 
    ** sorted and C is a factor between 1.95 and 4.3.  We will split the
    ** difference and select C of 3.0.
    */
    if( bSort ){
      cost += nRow*estLog(nRow)*3;
    }
    if( bDist ){
      cost += nRow*estLog(nRow)*3;
    }

    /**** Cost of using this index has now been computed ****/

    /* If there are additional constraints on this table that cannot
    ** be used with the current index, but which might lower the number







<
<
<







101342
101343
101344
101345
101346
101347
101348



101349
101350
101351
101352
101353
101354
101355
    /* Add in the estimated cost of sorting the result.  Actual experimental
    ** measurements of sorting performance in SQLite show that sorting time
    ** adds C*N*log10(N) to the cost, where N is the number of rows to be 
    ** sorted and C is a factor between 1.95 and 4.3.  We will split the
    ** difference and select C of 3.0.
    */
    if( bSort ){



      cost += nRow*estLog(nRow)*3;
    }

    /**** Cost of using this index has now been computed ****/

    /* If there are additional constraints on this table that cannot
    ** be used with the current index, but which might lower the number
103688
103689
103690
103691
103692
103693
103694
103695
103696
103697
103698
103699
103700
103701
103702
    if( p->needToFreeIdxStr ){
      sqlite3_free(p->idxStr);
    }
    sqlite3DbFree(pParse->db, p);
  }else
#endif
  {
    bestBtreeIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, 0, pCost);
  }
}

/*
** Disable a term in the WHERE clause.  Except, do not disable the term
** if it controls a LEFT OUTER JOIN and it did not originate in the ON
** or USING clause of that join.







|







101489
101490
101491
101492
101493
101494
101495
101496
101497
101498
101499
101500
101501
101502
101503
    if( p->needToFreeIdxStr ){
      sqlite3_free(p->idxStr);
    }
    sqlite3DbFree(pParse->db, p);
  }else
#endif
  {
    bestBtreeIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost);
  }
}

/*
** Disable a term in the WHERE clause.  Except, do not disable the term
** if it controls a LEFT OUTER JOIN and it did not originate in the ON
** or USING clause of that join.
104650
104651
104652
104653
104654
104655
104656
104657
104658
104659
104660
104661
104662
104663
104664
    iRetInit = sqlite3VdbeAddOp2(v, OP_Integer, 0, regReturn);

    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 */
        /* Loop through table entries that match term pOrTerm. */
        pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrTerm->pExpr, 0, 0,
                        WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE |
                        WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY);
        if( pSubWInfo ){
          explainOneScan(
              pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0
          );
          if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){







|







102451
102452
102453
102454
102455
102456
102457
102458
102459
102460
102461
102462
102463
102464
102465
    iRetInit = sqlite3VdbeAddOp2(v, OP_Integer, 0, regReturn);

    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 */
        /* Loop through table entries that match term pOrTerm. */
        pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrTerm->pExpr, 0,
                        WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE |
                        WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY);
        if( pSubWInfo ){
          explainOneScan(
              pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0
          );
          if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
104891
104892
104893
104894
104895
104896
104897
104898
104899
104900
104901
104902
104903
104904
104905
** output order, then the *ppOrderBy is unchanged.
*/
SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
  Parse *pParse,        /* The parser context */
  SrcList *pTabList,    /* A list of all tables to be scanned */
  Expr *pWhere,         /* The WHERE clause */
  ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */
  ExprList *pDistinct,  /* The select-list for DISTINCT queries - or NULL */
  u16 wctrlFlags        /* One of the WHERE_* flags defined in sqliteInt.h */
){
  int i;                     /* Loop counter */
  int nByteWInfo;            /* Num. bytes allocated for WhereInfo struct */
  int nTabList;              /* Number of elements in pTabList */
  WhereInfo *pWInfo;         /* Will become the return value of this function */
  Vdbe *v = pParse->pVdbe;   /* The virtual database engine */







<







102692
102693
102694
102695
102696
102697
102698

102699
102700
102701
102702
102703
102704
102705
** output order, then the *ppOrderBy is unchanged.
*/
SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
  Parse *pParse,        /* The parser context */
  SrcList *pTabList,    /* A list of all tables to be scanned */
  Expr *pWhere,         /* The WHERE clause */
  ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */

  u16 wctrlFlags        /* One of the WHERE_* flags defined in sqliteInt.h */
){
  int i;                     /* Loop counter */
  int nByteWInfo;            /* Num. bytes allocated for WhereInfo struct */
  int nTabList;              /* Number of elements in pTabList */
  WhereInfo *pWInfo;         /* Will become the return value of this function */
  Vdbe *v = pParse->pVdbe;   /* The virtual database engine */
104952
104953
104954
104955
104956
104957
104958
104959
104960
104961
104962
104963
104964
104965
104966
104967
104968
104969
  pWInfo->pTabList = pTabList;
  pWInfo->iBreak = sqlite3VdbeMakeLabel(v);
  pWInfo->pWC = pWC = (WhereClause *)&((u8 *)pWInfo)[nByteWInfo];
  pWInfo->wctrlFlags = wctrlFlags;
  pWInfo->savedNQueryLoop = pParse->nQueryLoop;
  pMaskSet = (WhereMaskSet*)&pWC[1];

  /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
  ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
  if( db->flags & SQLITE_DistinctOpt ) pDistinct = 0;

  /* Split the WHERE clause into separate subexpressions where each
  ** subexpression is separated by an AND operator.
  */
  initMaskSet(pMaskSet);
  whereClauseInit(pWC, pParse, pMaskSet);
  sqlite3ExprCodeConstants(pParse, pWhere);
  whereSplit(pWC, pWhere, TK_AND);   /* IMP: R-15842-53296 */







<
<
<
<







102752
102753
102754
102755
102756
102757
102758




102759
102760
102761
102762
102763
102764
102765
  pWInfo->pTabList = pTabList;
  pWInfo->iBreak = sqlite3VdbeMakeLabel(v);
  pWInfo->pWC = pWC = (WhereClause *)&((u8 *)pWInfo)[nByteWInfo];
  pWInfo->wctrlFlags = wctrlFlags;
  pWInfo->savedNQueryLoop = pParse->nQueryLoop;
  pMaskSet = (WhereMaskSet*)&pWC[1];





  /* Split the WHERE clause into separate subexpressions where each
  ** subexpression is separated by an AND operator.
  */
  initMaskSet(pMaskSet);
  whereClauseInit(pWC, pParse, pMaskSet);
  sqlite3ExprCodeConstants(pParse, pWhere);
  whereSplit(pWC, pWhere, TK_AND);   /* IMP: R-15842-53296 */
105023
105024
105025
105026
105027
105028
105029
105030
105031
105032
105033
105034
105035
105036
105037
105038
105039
105040
105041
105042
105043
105044
105045
  ** and work forward so that the added virtual terms are never processed.
  */
  exprAnalyzeAll(pTabList, pWC);
  if( db->mallocFailed ){
    goto whereBeginError;
  }

  /* Check if the DISTINCT qualifier, if there is one, is redundant. 
  ** If it is, then set pDistinct to NULL and WhereInfo.eDistinct to
  ** WHERE_DISTINCT_UNIQUE to tell the caller to ignore the DISTINCT.
  */
  if( pDistinct && isDistinctRedundant(pParse, pTabList, pWC, pDistinct) ){
    pDistinct = 0;
    pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
  }

  /* Chose the best index to use for each table in the FROM clause.
  **
  ** This loop fills in the following fields:
  **
  **   pWInfo->a[].pIdx      The index to use for this level of the loop.
  **   pWInfo->a[].wsFlags   WHERE_xxx flags associated with pIdx
  **   pWInfo->a[].nEq       The number of == and IN constraints







<
<
<
<
<
<
<
<
<







102819
102820
102821
102822
102823
102824
102825









102826
102827
102828
102829
102830
102831
102832
  ** and work forward so that the added virtual terms are never processed.
  */
  exprAnalyzeAll(pTabList, pWC);
  if( db->mallocFailed ){
    goto whereBeginError;
  }










  /* Chose the best index to use for each table in the FROM clause.
  **
  ** This loop fills in the following fields:
  **
  **   pWInfo->a[].pIdx      The index to use for this level of the loop.
  **   pWInfo->a[].wsFlags   WHERE_xxx flags associated with pIdx
  **   pWInfo->a[].nEq       The number of == and IN constraints
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
    notIndexed = 0;
    for(isOptimal=(iFrom<nTabList-1); isOptimal>=0 && bestJ<0; isOptimal--){
      Bitmask mask;             /* Mask of tables not yet ready */
      for(j=iFrom, pTabItem=&pTabList->a[j]; j<nTabList; j++, pTabItem++){
        int doNotReorder;    /* True if this table should not be reordered */
        WhereCost sCost;     /* Cost information from best[Virtual]Index() */
        ExprList *pOrderBy;  /* ORDER BY clause for index to optimize */
        ExprList *pDist;     /* DISTINCT clause for index to optimize */
  
        doNotReorder =  (pTabItem->jointype & (JT_LEFT|JT_CROSS))!=0;
        if( j!=iFrom && doNotReorder ) break;
        m = getMask(pMaskSet, pTabItem->iCursor);
        if( (m & notReady)==0 ){
          if( j==iFrom ) iFrom++;
          continue;
        }
        mask = (isOptimal ? m : notReady);
        pOrderBy = ((i==0 && ppOrderBy )?*ppOrderBy:0);
        pDist = (i==0 ? pDistinct : 0);
        if( pTabItem->pIndex==0 ) nUnconstrained++;
  
        WHERETRACE(("=== trying table %d with isOptimal=%d ===\n",
                    j, isOptimal));
        assert( pTabItem->pTab );
#ifndef SQLITE_OMIT_VIRTUALTABLE
        if( IsVirtual(pTabItem->pTab) ){
          sqlite3_index_info **pp = &pWInfo->a[j].pIdxInfo;
          bestVirtualIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy,
                           &sCost, pp);
        }else 
#endif
        {
          bestBtreeIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy,
              pDist, &sCost);
        }
        assert( isOptimal || (sCost.used&notReady)==0 );

        /* If an INDEXED BY clause is present, then the plan must use that
        ** index if it uses any index at all */
        assert( pTabItem->pIndex==0 
                  || (sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0







<










<














|







102902
102903
102904
102905
102906
102907
102908

102909
102910
102911
102912
102913
102914
102915
102916
102917
102918

102919
102920
102921
102922
102923
102924
102925
102926
102927
102928
102929
102930
102931
102932
102933
102934
102935
102936
102937
102938
102939
102940
    notIndexed = 0;
    for(isOptimal=(iFrom<nTabList-1); isOptimal>=0 && bestJ<0; isOptimal--){
      Bitmask mask;             /* Mask of tables not yet ready */
      for(j=iFrom, pTabItem=&pTabList->a[j]; j<nTabList; j++, pTabItem++){
        int doNotReorder;    /* True if this table should not be reordered */
        WhereCost sCost;     /* Cost information from best[Virtual]Index() */
        ExprList *pOrderBy;  /* ORDER BY clause for index to optimize */

  
        doNotReorder =  (pTabItem->jointype & (JT_LEFT|JT_CROSS))!=0;
        if( j!=iFrom && doNotReorder ) break;
        m = getMask(pMaskSet, pTabItem->iCursor);
        if( (m & notReady)==0 ){
          if( j==iFrom ) iFrom++;
          continue;
        }
        mask = (isOptimal ? m : notReady);
        pOrderBy = ((i==0 && ppOrderBy )?*ppOrderBy:0);

        if( pTabItem->pIndex==0 ) nUnconstrained++;
  
        WHERETRACE(("=== trying table %d with isOptimal=%d ===\n",
                    j, isOptimal));
        assert( pTabItem->pTab );
#ifndef SQLITE_OMIT_VIRTUALTABLE
        if( IsVirtual(pTabItem->pTab) ){
          sqlite3_index_info **pp = &pWInfo->a[j].pIdxInfo;
          bestVirtualIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy,
                           &sCost, pp);
        }else 
#endif
        {
          bestBtreeIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy,
                         &sCost);
        }
        assert( isOptimal || (sCost.used&notReady)==0 );

        /* If an INDEXED BY clause is present, then the plan must use that
        ** index if it uses any index at all */
        assert( pTabItem->pIndex==0 
                  || (sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0
105202
105203
105204
105205
105206
105207
105208
105209
105210
105211
105212
105213
105214
105215
105216
105217
105218
105219
    assert( notReady & getMask(pMaskSet, pTabList->a[bestJ].iCursor) );
    WHERETRACE(("*** Optimizer selects table %d for loop %d"
                " with cost=%g and nRow=%g\n",
                bestJ, pLevel-pWInfo->a, bestPlan.rCost, bestPlan.plan.nRow));
    if( (bestPlan.plan.wsFlags & WHERE_ORDERBY)!=0 ){
      *ppOrderBy = 0;
    }
    if( (bestPlan.plan.wsFlags & WHERE_DISTINCT)!=0 ){
      assert( pWInfo->eDistinct==0 );
      pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
    }
    andFlags &= bestPlan.plan.wsFlags;
    pLevel->plan = bestPlan.plan;
    testcase( bestPlan.plan.wsFlags & WHERE_INDEXED );
    testcase( bestPlan.plan.wsFlags & WHERE_TEMP_INDEX );
    if( bestPlan.plan.wsFlags & (WHERE_INDEXED|WHERE_TEMP_INDEX) ){
      pLevel->iIdxCur = pParse->nTab++;
    }else{







<
<
<
<







102987
102988
102989
102990
102991
102992
102993




102994
102995
102996
102997
102998
102999
103000
    assert( notReady & getMask(pMaskSet, pTabList->a[bestJ].iCursor) );
    WHERETRACE(("*** Optimizer selects table %d for loop %d"
                " with cost=%g and nRow=%g\n",
                bestJ, pLevel-pWInfo->a, bestPlan.rCost, bestPlan.plan.nRow));
    if( (bestPlan.plan.wsFlags & WHERE_ORDERBY)!=0 ){
      *ppOrderBy = 0;
    }




    andFlags &= bestPlan.plan.wsFlags;
    pLevel->plan = bestPlan.plan;
    testcase( bestPlan.plan.wsFlags & WHERE_INDEXED );
    testcase( bestPlan.plan.wsFlags & WHERE_TEMP_INDEX );
    if( bestPlan.plan.wsFlags & (WHERE_INDEXED|WHERE_TEMP_INDEX) ){
      pLevel->iIdxCur = pParse->nTab++;
    }else{
105540
105541
105542
105543
105544
105545
105546
105547
105548
105549
105550
105551
105552
105553
105554
** The only modifications are the addition of a couple of NEVER()
** macros to disable tests that are needed in the case of a general
** LALR(1) grammar but which are always false in the
** specific grammar used by SQLite.
*/
/* First off, code is included that follows the "include" declaration
** in the input grammar file. */
/* #include <stdio.h> */


/*
** Disable all error recovery processing in the parser push-down
** automaton.
*/
#define YYNOERRORRECOVERY 1







<







103321
103322
103323
103324
103325
103326
103327

103328
103329
103330
103331
103332
103333
103334
** The only modifications are the addition of a couple of NEVER()
** macros to disable tests that are needed in the case of a general
** LALR(1) grammar but which are always false in the
** specific grammar used by SQLite.
*/
/* First off, code is included that follows the "include" declaration
** in the input grammar file. */



/*
** Disable all error recovery processing in the parser push-down
** automaton.
*/
#define YYNOERRORRECOVERY 1
106401
106402
106403
106404
106405
106406
106407
106408
106409
106410
106411
106412
106413
106414
106415
#else
  yyStackEntry yystack[YYSTACKDEPTH];  /* The parser's stack */
#endif
};
typedef struct yyParser yyParser;

#ifndef NDEBUG
/* #include <stdio.h> */
static FILE *yyTraceFILE = 0;
static char *yyTracePrompt = 0;
#endif /* NDEBUG */

#ifndef NDEBUG
/* 
** Turn parser tracing on by giving a stream to which to write the trace







<







104181
104182
104183
104184
104185
104186
104187

104188
104189
104190
104191
104192
104193
104194
#else
  yyStackEntry yystack[YYSTACKDEPTH];  /* The parser's stack */
#endif
};
typedef struct yyParser yyParser;

#ifndef NDEBUG

static FILE *yyTraceFILE = 0;
static char *yyTracePrompt = 0;
#endif /* NDEBUG */

#ifndef NDEBUG
/* 
** Turn parser tracing on by giving a stream to which to write the trace
108977
108978
108979
108980
108981
108982
108983
108984
108985
108986
108987
108988
108989
108990
108991
*************************************************************************
** An tokenizer for SQL
**
** This file contains C code that splits an SQL input string up into
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
*/
/* #include <stdlib.h> */

/*
** The charMap() macro maps alphabetic characters into their
** lower-case ASCII equivalent.  On ASCII machines, this is just
** an upper-to-lower case map.  On EBCDIC machines we also need
** to adjust the encoding.  Only alphabetic characters and underscores
** need to be translated.







<







106756
106757
106758
106759
106760
106761
106762

106763
106764
106765
106766
106767
106768
106769
*************************************************************************
** An tokenizer for SQL
**
** This file contains C code that splits an SQL input string up into
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
*/


/*
** The charMap() macro maps alphabetic characters into their
** lower-case ASCII equivalent.  On ASCII machines, this is just
** an upper-to-lower case map.  On EBCDIC machines we also need
** to adjust the encoding.  Only alphabetic characters and underscores
** need to be translated.
110368
110369
110370
110371
110372
110373
110374
110375
110376
110377
110378
110379
110380
110381
110382
110383
110384
110385
110386
110387
110388
110389
110390
110391
    double y;
    assert(sizeof(x)==8);
    assert(sizeof(x)==sizeof(y));
    memcpy(&y, &x, 8);
    assert( sqlite3IsNaN(y) );
  }
#endif
#endif

  /* Do extra initialization steps requested by the SQLITE_EXTRA_INIT
  ** compile-time option.
  */
#ifdef SQLITE_EXTRA_INIT
  if( rc==SQLITE_OK && sqlite3GlobalConfig.isInit ){
    int SQLITE_EXTRA_INIT(void);
    rc = SQLITE_EXTRA_INIT();
  }
#endif

  return rc;
}

/*
** Undo the effects of sqlite3_initialize().  Must not be called while







<
<
<
<
<
<
<
<
<
<







108146
108147
108148
108149
108150
108151
108152










108153
108154
108155
108156
108157
108158
108159
    double y;
    assert(sizeof(x)==8);
    assert(sizeof(x)==sizeof(y));
    memcpy(&y, &x, 8);
    assert( sqlite3IsNaN(y) );
  }
#endif










#endif

  return rc;
}

/*
** Undo the effects of sqlite3_initialize().  Must not be called while
113748
113749
113750
113751
113752
113753
113754
113755
113756
113757
113758
113759
113760
113761
113762
113763
113764
113765
113766
113767
113768
** SQLITE_ENABLE_FTS3 macro.  But to avoid confusion we also all
** the SQLITE_ENABLE_FTS4 macro to serve as an alisse for SQLITE_ENABLE_FTS3.
*/
#if defined(SQLITE_ENABLE_FTS4) && !defined(SQLITE_ENABLE_FTS3)
# define SQLITE_ENABLE_FTS3
#endif

#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)

/* If not building as part of the core, include sqlite3ext.h. */
#ifndef SQLITE_CORE
SQLITE_API extern const sqlite3_api_routines *sqlite3_api;
#endif

/************** Include fts3_tokenizer.h in the middle of fts3Int.h **********/
/************** Begin file fts3_tokenizer.h **********************************/
/*
** 2006 July 10
**
** The author disclaims copyright to this source code.
**







<
<
<
|
<
<
<







111516
111517
111518
111519
111520
111521
111522



111523



111524
111525
111526
111527
111528
111529
111530
** SQLITE_ENABLE_FTS3 macro.  But to avoid confusion we also all
** the SQLITE_ENABLE_FTS4 macro to serve as an alisse for SQLITE_ENABLE_FTS3.
*/
#if defined(SQLITE_ENABLE_FTS4) && !defined(SQLITE_ENABLE_FTS3)
# define SQLITE_ENABLE_FTS3
#endif




#ifdef SQLITE_ENABLE_FTS3



/************** Include fts3_tokenizer.h in the middle of fts3Int.h **********/
/************** Begin file fts3_tokenizer.h **********************************/
/*
** 2006 July 10
**
** The author disclaims copyright to this source code.
**
114287
114288
114289
114290
114291
114292
114293
114294
114295
114296
114297
114298
114299
114300
114301
  int nAll;                      /* Size of a[] in bytes */
  char *pNextDocid;              /* Pointer to next docid */

  sqlite3_int64 iDocid;          /* Current docid (if pList!=0) */
  int bFreeList;                 /* True if pList should be sqlite3_free()d */
  char *pList;                   /* Pointer to position list following iDocid */
  int nList;                     /* Length of position list */
};

/*
** A "phrase" is a sequence of one or more tokens that must match in
** sequence.  A single token is the base case and the most common case.
** For a sequence of tokens contained in double-quotes (i.e. "one two three")
** nToken will be the number of tokens in the string.
*/







|







112049
112050
112051
112052
112053
112054
112055
112056
112057
112058
112059
112060
112061
112062
112063
  int nAll;                      /* Size of a[] in bytes */
  char *pNextDocid;              /* Pointer to next docid */

  sqlite3_int64 iDocid;          /* Current docid (if pList!=0) */
  int bFreeList;                 /* True if pList should be sqlite3_free()d */
  char *pList;                   /* Pointer to position list following iDocid */
  int nList;                     /* Length of position list */
} doclist;

/*
** A "phrase" is a sequence of one or more tokens that must match in
** sequence.  A single token is the base case and the most common case.
** For a sequence of tokens contained in double-quotes (i.e. "one two three")
** nToken will be the number of tokens in the string.
*/
114486
114487
114488
114489
114490
114491
114492
114493








114494



114495
114496
114497
114498
114499
114500
114501
114502
114503
114504
114505
114506
114507
114508
114509
114510
114511
114512
114513
114514
114515
114516
114517
114518
114519
114520
114521
114522
114523
114524
114525
114526
114527
114528
114529
114530
114531
114532
114533
114534
114535
114536
114537
114538
114539
#ifdef SQLITE_TEST
SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db);
SQLITE_PRIVATE int sqlite3Fts3InitTerm(sqlite3 *db);
#endif

/* fts3_aux.c */
SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db);









SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *);




SQLITE_PRIVATE int sqlite3Fts3MsrIncrStart(
    Fts3Table*, Fts3MultiSegReader*, int, const char*, int);
SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext(
    Fts3Table *, Fts3MultiSegReader *, sqlite3_int64 *, char **, int *);
SQLITE_PRIVATE char *sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol); 
SQLITE_PRIVATE int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *);
SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);

SQLITE_PRIVATE int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, int *);

#endif /* !SQLITE_CORE || SQLITE_ENABLE_FTS3 */
#endif /* _FTSINT_H */

/************** End of fts3Int.h *********************************************/
/************** Continuing where we left off in fts3.c ***********************/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)

#if defined(SQLITE_ENABLE_FTS3) && !defined(SQLITE_CORE)
# define SQLITE_CORE 1
#endif

/* #include <assert.h> */
/* #include <stdlib.h> */
/* #include <stddef.h> */
/* #include <stdio.h> */
/* #include <string.h> */
/* #include <stdarg.h> */

#ifndef SQLITE_CORE 
  SQLITE_EXTENSION_INIT1
#endif

static int fts3EvalNext(Fts3Cursor *pCsr);
static int fts3EvalStart(Fts3Cursor *pCsr);
static int fts3TermSegReaderCursor(
    Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **);

/* 
** Write a 64-bit variable-length integer to memory starting at p[0].
** The length of data written will be between 1 and FTS3_VARINT_MAX bytes.
** The number of bytes written is returned.
*/
SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){
  unsigned char *q = (unsigned char *) p;








>
>
>
>
>
>
>
>

>
>
>











|










<
<
<
<
<
<





<
<
<
<
<







112248
112249
112250
112251
112252
112253
112254
112255
112256
112257
112258
112259
112260
112261
112262
112263
112264
112265
112266
112267
112268
112269
112270
112271
112272
112273
112274
112275
112276
112277
112278
112279
112280
112281
112282
112283
112284
112285
112286
112287
112288
112289






112290
112291
112292
112293
112294





112295
112296
112297
112298
112299
112300
112301
#ifdef SQLITE_TEST
SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db);
SQLITE_PRIVATE int sqlite3Fts3InitTerm(sqlite3 *db);
#endif

/* fts3_aux.c */
SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db);

SQLITE_PRIVATE int sqlite3Fts3TermSegReaderCursor(
  Fts3Cursor *pCsr,               /* Virtual table cursor handle */
  const char *zTerm,              /* Term to query for */
  int nTerm,                      /* Size of zTerm in bytes */
  int isPrefix,                   /* True for a prefix search */
  Fts3MultiSegReader **ppSegcsr   /* OUT: Allocated seg-reader cursor */
);

SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *);

SQLITE_PRIVATE int sqlite3Fts3EvalStart(Fts3Cursor *, Fts3Expr *, int);
SQLITE_PRIVATE int sqlite3Fts3EvalNext(Fts3Cursor *pCsr);

SQLITE_PRIVATE int sqlite3Fts3MsrIncrStart(
    Fts3Table*, Fts3MultiSegReader*, int, const char*, int);
SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext(
    Fts3Table *, Fts3MultiSegReader *, sqlite3_int64 *, char **, int *);
SQLITE_PRIVATE char *sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol); 
SQLITE_PRIVATE int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *);
SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);

SQLITE_PRIVATE int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, int *);

#endif /* SQLITE_ENABLE_FTS3 */
#endif /* _FTSINT_H */

/************** End of fts3Int.h *********************************************/
/************** Continuing where we left off in fts3.c ***********************/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)

#if defined(SQLITE_ENABLE_FTS3) && !defined(SQLITE_CORE)
# define SQLITE_CORE 1
#endif








#ifndef SQLITE_CORE 
  SQLITE_EXTENSION_INIT1
#endif






/* 
** Write a 64-bit variable-length integer to memory starting at p[0].
** The length of data written will be between 1 and FTS3_VARINT_MAX bytes.
** The number of bytes written is returned.
*/
SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){
  unsigned char *q = (unsigned char *) p;
115034
115035
115036
115037
115038
115039
115040
115041
115042
115043
115044
115045
115046
115047
115048
115049
115050
115051
115052
115053
115054
115055
115056
115057
115058
115059
115060
115061
115062
115063
115064
115065
115066
115067
115068
115069
115070
115071
115072
115073
115074
115075
115076
115077
115078
115079
115080
115081
115082
115083
115084
115085
115086
115087

115088
115089
115090
115091
115092
115093
115094
115095
115096
115097
115098
115099
115100
115101
115102
115103
115104
115105
115106
115107
115108
  for(i=0; i<p->nColumn; i++){
    fts3Appendf(pRc, &zRet, ",%s(?)", zFunction);
  }
  sqlite3_free(zFree);
  return zRet;
}

/*
** This function interprets the string at (*pp) as a non-negative integer
** value. It reads the integer and sets *pnOut to the value read, then 
** sets *pp to point to the byte immediately following the last byte of
** the integer value.
**
** Only decimal digits ('0'..'9') may be part of an integer value. 
**
** If *pp does not being with a decimal digit SQLITE_ERROR is returned and
** the output value undefined. Otherwise SQLITE_OK is returned.
**
** This function is used when parsing the "prefix=" FTS4 parameter.
*/
static int fts3GobbleInt(const char **pp, int *pnOut){
  const char *p = *pp;            /* Iterator pointer */
  int nInt = 0;                   /* Output value */

  for(p=*pp; p[0]>='0' && p[0]<='9'; p++){
    nInt = nInt * 10 + (p[0] - '0');
  }
  if( p==*pp ) return SQLITE_ERROR;
  *pnOut = nInt;
  *pp = p;
  return SQLITE_OK;
}

/*
** This function is called to allocate an array of Fts3Index structures
** representing the indexes maintained by the current FTS table. FTS tables
** always maintain the main "terms" index, but may also maintain one or
** more "prefix" indexes, depending on the value of the "prefix=" parameter
** (if any) specified as part of the CREATE VIRTUAL TABLE statement.
**
** Argument zParam is passed the value of the "prefix=" option if one was
** specified, or NULL otherwise.
**
** If no error occurs, SQLITE_OK is returned and *apIndex set to point to
** the allocated array. *pnIndex is set to the number of elements in the
** array. If an error does occur, an SQLite error code is returned.
**
** Regardless of whether or not an error is returned, it is the responsibility
** of the caller to call sqlite3_free() on the output array to free it.
*/
static int fts3PrefixParameter(
  const char *zParam,             /* ABC in prefix=ABC parameter to parse */
  int *pnIndex,                   /* OUT: size of *apIndex[] array */
  struct Fts3Index **apIndex      /* OUT: Array of indexes for this table */

){
  struct Fts3Index *aIndex;       /* Allocated array */
  int nIndex = 1;                 /* Number of entries in array */

  if( zParam && zParam[0] ){
    const char *p;
    nIndex++;
    for(p=zParam; *p; p++){
      if( *p==',' ) nIndex++;
    }
  }

  aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex);
  *apIndex = aIndex;
  *pnIndex = nIndex;
  if( !aIndex ){
    return SQLITE_NOMEM;
  }

  memset(aIndex, 0, sizeof(struct Fts3Index) * nIndex);
  if( zParam ){







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

|
|
<









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



|
>

|
|










|







112796
112797
112798
112799
112800
112801
112802













112803
112804
112805

112806
112807
112808
112809
112810
112811
112812
112813
112814
112815
















112816
112817
112818
112819
112820
112821
112822
112823
112824
112825
112826
112827
112828
112829
112830
112831
112832
112833
112834
112835
112836
112837
112838
112839
112840
112841
  for(i=0; i<p->nColumn; i++){
    fts3Appendf(pRc, &zRet, ",%s(?)", zFunction);
  }
  sqlite3_free(zFree);
  return zRet;
}














static int fts3GobbleInt(const char **pp, int *pnOut){
  const char *p = *pp;
  int nInt = 0;

  for(p=*pp; p[0]>='0' && p[0]<='9'; p++){
    nInt = nInt * 10 + (p[0] - '0');
  }
  if( p==*pp ) return SQLITE_ERROR;
  *pnOut = nInt;
  *pp = p;
  return SQLITE_OK;
}


















static int fts3PrefixParameter(
  const char *zParam,             /* ABC in prefix=ABC parameter to parse */
  int *pnIndex,                   /* OUT: size of *apIndex[] array */
  struct Fts3Index **apIndex,     /* OUT: Array of indexes for this table */
  struct Fts3Index **apFree       /* OUT: Free this with sqlite3_free() */
){
  struct Fts3Index *aIndex;
  int nIndex = 1;

  if( zParam && zParam[0] ){
    const char *p;
    nIndex++;
    for(p=zParam; *p; p++){
      if( *p==',' ) nIndex++;
    }
  }

  aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex);
  *apIndex = *apFree = aIndex;
  *pnIndex = nIndex;
  if( !aIndex ){
    return SQLITE_NOMEM;
  }

  memset(aIndex, 0, sizeof(struct Fts3Index) * nIndex);
  if( zParam ){
115151
115152
115153
115154
115155
115156
115157
115158

115159
115160
115161
115162
115163
115164
115165
  int nDb;                        /* Bytes required to hold database name */
  int nName;                      /* Bytes required to hold table name */
  int isFts4 = (argv[0][3]=='4'); /* True for FTS4, false for FTS3 */
  const char **aCol;              /* Array of column names */
  sqlite3_tokenizer *pTokenizer = 0;        /* Tokenizer for this table */

  int nIndex;                     /* Size of aIndex[] array */
  struct Fts3Index *aIndex = 0;   /* Array of indexes for this table */


  /* The results of parsing supported FTS4 key=value options: */
  int bNoDocsize = 0;             /* True to omit %_docsize table */
  int bDescIdx = 0;               /* True to store descending indexes */
  char *zPrefix = 0;              /* Prefix parameter value (or NULL) */
  char *zCompress = 0;            /* compress=? parameter (or NULL) */
  char *zUncompress = 0;          /* uncompress=? parameter (or NULL) */







|
>







112884
112885
112886
112887
112888
112889
112890
112891
112892
112893
112894
112895
112896
112897
112898
112899
  int nDb;                        /* Bytes required to hold database name */
  int nName;                      /* Bytes required to hold table name */
  int isFts4 = (argv[0][3]=='4'); /* True for FTS4, false for FTS3 */
  const char **aCol;              /* Array of column names */
  sqlite3_tokenizer *pTokenizer = 0;        /* Tokenizer for this table */

  int nIndex;                     /* Size of aIndex[] array */
  struct Fts3Index *aIndex;       /* Array of indexes for this table */
  struct Fts3Index *aFree = 0;    /* Free this before returning */

  /* The results of parsing supported FTS4 key=value options: */
  int bNoDocsize = 0;             /* True to omit %_docsize table */
  int bDescIdx = 0;               /* True to store descending indexes */
  char *zPrefix = 0;              /* Prefix parameter value (or NULL) */
  char *zCompress = 0;            /* compress=? parameter (or NULL) */
  char *zUncompress = 0;          /* uncompress=? parameter (or NULL) */
115288
115289
115290
115291
115292
115293
115294
115295
115296
115297
115298
115299
115300
115301
115302

  if( pTokenizer==0 ){
    rc = sqlite3Fts3InitTokenizer(pHash, "simple", &pTokenizer, pzErr);
    if( rc!=SQLITE_OK ) goto fts3_init_out;
  }
  assert( pTokenizer );

  rc = fts3PrefixParameter(zPrefix, &nIndex, &aIndex);
  if( rc==SQLITE_ERROR ){
    assert( zPrefix );
    *pzErr = sqlite3_mprintf("error parsing prefix parameter: %s", zPrefix);
  }
  if( rc!=SQLITE_OK ) goto fts3_init_out;

  /* Allocate and populate the Fts3Table structure. */







|







113022
113023
113024
113025
113026
113027
113028
113029
113030
113031
113032
113033
113034
113035
113036

  if( pTokenizer==0 ){
    rc = sqlite3Fts3InitTokenizer(pHash, "simple", &pTokenizer, pzErr);
    if( rc!=SQLITE_OK ) goto fts3_init_out;
  }
  assert( pTokenizer );

  rc = fts3PrefixParameter(zPrefix, &nIndex, &aIndex, &aFree);
  if( rc==SQLITE_ERROR ){
    assert( zPrefix );
    *pzErr = sqlite3_mprintf("error parsing prefix parameter: %s", zPrefix);
  }
  if( rc!=SQLITE_OK ) goto fts3_init_out;

  /* Allocate and populate the Fts3Table structure. */
115375
115376
115377
115378
115379
115380
115381
115382
115383
115384
115385
115386
115387
115388
115389
  p->nNodeSize = p->nPgsz-35;

  /* Declare the table schema to SQLite. */
  fts3DeclareVtab(&rc, p);

fts3_init_out:
  sqlite3_free(zPrefix);
  sqlite3_free(aIndex);
  sqlite3_free(zCompress);
  sqlite3_free(zUncompress);
  sqlite3_free((void *)aCol);
  if( rc!=SQLITE_OK ){
    if( p ){
      fts3DisconnectMethod((sqlite3_vtab *)p);
    }else if( pTokenizer ){







|







113109
113110
113111
113112
113113
113114
113115
113116
113117
113118
113119
113120
113121
113122
113123
  p->nNodeSize = p->nPgsz-35;

  /* Declare the table schema to SQLite. */
  fts3DeclareVtab(&rc, p);

fts3_init_out:
  sqlite3_free(zPrefix);
  sqlite3_free(aFree);
  sqlite3_free(zCompress);
  sqlite3_free(zUncompress);
  sqlite3_free((void *)aCol);
  if( rc!=SQLITE_OK ){
    if( p ){
      fts3DisconnectMethod((sqlite3_vtab *)p);
    }else if( pTokenizer ){
115966
115967
115968
115969
115970
115971
115972


115973
115974
115975
115976
115977
115978
115979
115980
115981
115982
115983
115984
115985
115986
115987
115988
115989
115990
115991
115992
115993
115994
115995
115996
115997
115998
115999
116000
  *p++ = POS_END;
  *pp = p;
  *pp1 = p1 + 1;
  *pp2 = p2 + 1;
}

/*


** This function is used to merge two position lists into one. When it is
** called, *pp1 and *pp2 must both point to position lists. A position-list is
** the part of a doclist that follows each document id. For example, if a row
** contains:
**
**     'a b c'|'x y z'|'a b b a'
**
** Then the position list for this row for token 'b' would consist of:
**
**     0x02 0x01 0x02 0x03 0x03 0x00
**
** When this function returns, both *pp1 and *pp2 are left pointing to the
** byte following the 0x00 terminator of their respective position lists.
**
** If isSaveLeft is 0, an entry is added to the output position list for 
** each position in *pp2 for which there exists one or more positions in
** *pp1 so that (pos(*pp2)>pos(*pp1) && pos(*pp2)-pos(*pp1)<=nToken). i.e.
** when the *pp1 token appears before the *pp2 token, but not more than nToken
** slots before it.
**
** e.g. nToken==1 searches for adjacent positions.
*/
static int fts3PoslistPhraseMerge(
  char **pp,                      /* IN/OUT: Preallocated output buffer */
  int nToken,                     /* Maximum difference in token positions */
  int isSaveLeft,                 /* Save the left position */
  int isExact,                    /* If *pp1 is exactly nTokens before *pp2 */
  char **pp1,                     /* IN/OUT: Left input list */







>
>



















<
<







113700
113701
113702
113703
113704
113705
113706
113707
113708
113709
113710
113711
113712
113713
113714
113715
113716
113717
113718
113719
113720
113721
113722
113723
113724
113725
113726
113727


113728
113729
113730
113731
113732
113733
113734
  *p++ = POS_END;
  *pp = p;
  *pp1 = p1 + 1;
  *pp2 = p2 + 1;
}

/*
** nToken==1 searches for adjacent positions.
**
** This function is used to merge two position lists into one. When it is
** called, *pp1 and *pp2 must both point to position lists. A position-list is
** the part of a doclist that follows each document id. For example, if a row
** contains:
**
**     'a b c'|'x y z'|'a b b a'
**
** Then the position list for this row for token 'b' would consist of:
**
**     0x02 0x01 0x02 0x03 0x03 0x00
**
** When this function returns, both *pp1 and *pp2 are left pointing to the
** byte following the 0x00 terminator of their respective position lists.
**
** If isSaveLeft is 0, an entry is added to the output position list for 
** each position in *pp2 for which there exists one or more positions in
** *pp1 so that (pos(*pp2)>pos(*pp1) && pos(*pp2)-pos(*pp1)<=nToken). i.e.
** when the *pp1 token appears before the *pp2 token, but not more than nToken
** slots before it.


*/
static int fts3PoslistPhraseMerge(
  char **pp,                      /* IN/OUT: Preallocated output buffer */
  int nToken,                     /* Maximum difference in token positions */
  int isSaveLeft,                 /* Save the left position */
  int isExact,                    /* If *pp1 is exactly nTokens before *pp2 */
  char **pp1,                     /* IN/OUT: Left input list */
116153
116154
116155
116156
116157
116158
116159
116160
116161
116162
116163
116164
116165

116166
116167
116168
116169
116170
116171
116172
116173
116174
116175
116176
116177
116178
116179
116180
116181
116182
116183
116184
116185
116186
116187
116188
116189
116190
116191
116192
116193
116194
116195
116196
116197
116198
116199
116200
116201
116202
116203
116204
116205
116206
116207
116208
116209
116210
116211
116212
116213
116214
116215
116216
116217
116218
116219
116220
116221
116222
116223
116224
116225
116226
116227
116228
116229
116230
116231
116232
116233
116234
116235
116236
116237
116238
116239
116240
116241
116242
116243
116244
116245
116246
116247
116248
116249
116250
116251
116252
116253
116254
116255
116256
116257
116258
116259
116260
116261
116262
116263
116264
116265
116266
116267
116268
116269
116270
116271
116272
116273
116274
116275
116276
116277
116278
116279
116280
116281
116282
116283
116284
116285
116286
116287
116288
116289
116290
116291
116292
116293
116294
116295
116296
116297
116298
116299
116300
116301
116302
116303
116304
116305
116306
116307
116308
116309
116310
116311
116312
116313
116314
116315
116316
116317
116318
116319
116320
116321
116322
116323
116324
116325
116326
116327
116328
116329
116330
116331
116332
116333
116334
116335
116336
116337
116338
116339
116340
116341
116342
116343
116344
116345
116346
116347
116348
116349
116350
116351
116352
116353
116354
116355
116356
116357
116358
116359
116360
116361
116362
116363
    res = 0;
  }

  return res;
}

/* 
** An instance of this function is used to merge together the (potentially
** large number of) doclists for each term that matches a prefix query.
** See function fts3TermSelectMerge() for details.
*/
typedef struct TermSelect TermSelect;
struct TermSelect {

  char *aaOutput[16];             /* Malloc'd output buffers */
  int anOutput[16];               /* Size each output buffer in bytes */
};

/*
** This function is used to read a single varint from a buffer. Parameter
** pEnd points 1 byte past the end of the buffer. When this function is
** called, if *pp points to pEnd or greater, then the end of the buffer
** has been reached. In this case *pp is set to 0 and the function returns.
**
** If *pp does not point to or past pEnd, then a single varint is read
** from *pp. *pp is then set to point 1 byte past the end of the read varint.
**
** If bDescIdx is false, the value read is added to *pVal before returning.
** If it is true, the value read is subtracted from *pVal before this 
** function returns.
*/
static void fts3GetDeltaVarint3(
  char **pp,                      /* IN/OUT: Point to read varint from */
  char *pEnd,                     /* End of buffer */
  int bDescIdx,                   /* True if docids are descending */
  sqlite3_int64 *pVal             /* IN/OUT: Integer value */
){
  if( *pp>=pEnd ){
    *pp = 0;
  }else{
    sqlite3_int64 iVal;
    *pp += sqlite3Fts3GetVarint(*pp, &iVal);
    if( bDescIdx ){
      *pVal -= iVal;
    }else{
      *pVal += iVal;
    }
  }
}

/*
** This function is used to write a single varint to a buffer. The varint
** is written to *pp. Before returning, *pp is set to point 1 byte past the
** end of the value written.
**
** If *pbFirst is zero when this function is called, the value written to
** the buffer is that of parameter iVal. 
**
** If *pbFirst is non-zero when this function is called, then the value 
** written is either (iVal-*piPrev) (if bDescIdx is zero) or (*piPrev-iVal)
** (if bDescIdx is non-zero).
**
** Before returning, this function always sets *pbFirst to 1 and *piPrev
** to the value of parameter iVal.
*/
static void fts3PutDeltaVarint3(
  char **pp,                      /* IN/OUT: Output pointer */
  int bDescIdx,                   /* True for descending docids */
  sqlite3_int64 *piPrev,          /* IN/OUT: Previous value written to list */
  int *pbFirst,                   /* IN/OUT: True after first int written */
  sqlite3_int64 iVal              /* Write this value to the list */
){
  sqlite3_int64 iWrite;
  if( bDescIdx==0 || *pbFirst==0 ){
    iWrite = iVal - *piPrev;
  }else{
    iWrite = *piPrev - iVal;
  }
  assert( *pbFirst || *piPrev==0 );
  assert( *pbFirst==0 || iWrite>0 );
  *pp += sqlite3Fts3PutVarint(*pp, iWrite);
  *piPrev = iVal;
  *pbFirst = 1;
}


/*
** This macro is used by various functions that merge doclists. The two
** arguments are 64-bit docid values. If the value of the stack variable
** bDescDoclist is 0 when this macro is invoked, then it returns (i1-i2). 
** Otherwise, (i2-i1).
**
** Using this makes it easier to write code that can merge doclists that are
** sorted in either ascending or descending order.
*/
#define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1-i2))

/*
** This function does an "OR" merge of two doclists (output contains all
** positions contained in either argument doclist). If the docids in the 
** input doclists are sorted in ascending order, parameter bDescDoclist
** should be false. If they are sorted in ascending order, it should be
** passed a non-zero value.
**
** If no error occurs, *paOut is set to point at an sqlite3_malloc'd buffer
** containing the output doclist and SQLITE_OK is returned. In this case
** *pnOut is set to the number of bytes in the output doclist.
**
** If an error occurs, an SQLite error code is returned. The output values
** are undefined in this case.
*/
static int fts3DoclistOrMerge(
  int bDescDoclist,               /* True if arguments are desc */
  char *a1, int n1,               /* First doclist */
  char *a2, int n2,               /* Second doclist */
  char **paOut, int *pnOut        /* OUT: Malloc'd doclist */
){
  sqlite3_int64 i1 = 0;
  sqlite3_int64 i2 = 0;
  sqlite3_int64 iPrev = 0;
  char *pEnd1 = &a1[n1];
  char *pEnd2 = &a2[n2];
  char *p1 = a1;
  char *p2 = a2;
  char *p;
  char *aOut;
  int bFirstOut = 0;

  *paOut = 0;
  *pnOut = 0;

  /* Allocate space for the output. Both the input and output doclists
  ** are delta encoded. If they are in ascending order (bDescDoclist==0),
  ** then the first docid in each list is simply encoded as a varint. For
  ** each subsequent docid, the varint stored is the difference between the
  ** current and previous docid (a positive number - since the list is in
  ** ascending order).
  **
  ** The first docid written to the output is therefore encoded using the 
  ** same number of bytes as it is in whichever of the input lists it is
  ** read from. And each subsequent docid read from the same input list 
  ** consumes either the same or less bytes as it did in the input (since
  ** the difference between it and the previous value in the output must
  ** be a positive value less than or equal to the delta value read from 
  ** the input list). The same argument applies to all but the first docid
  ** read from the 'other' list. And to the contents of all position lists
  ** that will be copied and merged from the input to the output.
  **
  ** However, if the first docid copied to the output is a negative number,
  ** then the encoding of the first docid from the 'other' input list may
  ** be larger in the output than it was in the input (since the delta value
  ** may be a larger positive integer than the actual docid).
  **
  ** The space required to store the output is therefore the sum of the
  ** sizes of the two inputs, plus enough space for exactly one of the input
  ** docids to grow. 
  **
  ** A symetric argument may be made if the doclists are in descending 
  ** order.
  */
  aOut = sqlite3_malloc(n1+n2+FTS3_VARINT_MAX-1);
  if( !aOut ) return SQLITE_NOMEM;

  p = aOut;
  fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
  fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
  while( p1 || p2 ){
    sqlite3_int64 iDiff = DOCID_CMP(i1, i2);

    if( p2 && p1 && iDiff==0 ){
      fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1);
      fts3PoslistMerge(&p, &p1, &p2);
      fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
      fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
    }else if( !p2 || (p1 && iDiff<0) ){
      fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1);
      fts3PoslistCopy(&p, &p1);
      fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
    }else{
      fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i2);
      fts3PoslistCopy(&p, &p2);
      fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
    }
  }

  *paOut = aOut;
  *pnOut = (p-aOut);
  assert( *pnOut<=n1+n2+FTS3_VARINT_MAX-1 );
  return SQLITE_OK;
}

/*
** This function does a "phrase" merge of two doclists. In a phrase merge,
** the output contains a copy of each position from the right-hand input
** doclist for which there is a position in the left-hand input doclist
** exactly nDist tokens before it.
**
** If the docids in the input doclists are sorted in ascending order,
** parameter bDescDoclist should be false. If they are sorted in ascending 
** order, it should be passed a non-zero value.
**
** The right-hand input doclist is overwritten by this function.
*/
static void fts3DoclistPhraseMerge(
  int bDescDoclist,               /* True if arguments are desc */
  int nDist,                      /* Distance from left to right (1=adjacent) */
  char *aLeft, int nLeft,         /* Left doclist */
  char *aRight, int *pnRight      /* IN/OUT: Right/output doclist */
){
  sqlite3_int64 i1 = 0;
  sqlite3_int64 i2 = 0;
  sqlite3_int64 iPrev = 0;







|
|
<



>
|
|


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

|
|
|
|














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




















|
<
<
<
<
<
<
<
<
<
<

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

|

















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






|


|

|
|

|

|

|

|





<



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

|







113887
113888
113889
113890
113891
113892
113893
113894
113895

113896
113897
113898
113899
113900
113901
113902
113903
113904












113905
113906
113907
113908
113909
113910
113911
113912
113913
113914
113915
113916
113917
113918
113919
113920
113921
113922
113923















113924
113925
113926
113927
113928
113929
113930
113931
113932
113933
113934
113935
113936
113937
113938
113939
113940
113941
113942
113943
113944










113945














113946
113947
113948
113949
113950
113951
113952
113953
113954
113955
113956
113957
113958
113959
113960
113961
113962
113963
113964






























113965
113966
113967
113968
113969
113970
113971
113972
113973
113974
113975
113976
113977
113978
113979
113980
113981
113982
113983
113984
113985
113986
113987
113988
113989
113990
113991

113992
113993
113994












113995
113996
113997
113998
113999
114000
114001
114002
114003
    res = 0;
  }

  return res;
}

/* 
** A pointer to an instance of this structure is used as the context 
** argument to sqlite3Fts3SegReaderIterate()

*/
typedef struct TermSelect TermSelect;
struct TermSelect {
  int isReqPos;
  char *aaOutput[16];             /* Malloc'd output buffer */
  int anOutput[16];               /* Size of output in bytes */
};














static void fts3GetDeltaVarint3(
  char **pp, 
  char *pEnd, 
  int bDescIdx,
  sqlite3_int64 *pVal
){
  if( *pp>=pEnd ){
    *pp = 0;
  }else{
    sqlite3_int64 iVal;
    *pp += sqlite3Fts3GetVarint(*pp, &iVal);
    if( bDescIdx ){
      *pVal -= iVal;
    }else{
      *pVal += iVal;
    }
  }
}
















static void fts3PutDeltaVarint3(
  char **pp,                      /* IN/OUT: Output pointer */
  int bDescIdx,                   /* True for descending docids */
  sqlite3_int64 *piPrev,          /* IN/OUT: Previous value written to list */
  int *pbFirst,                   /* IN/OUT: True after first int written */
  sqlite3_int64 iVal              /* Write this value to the list */
){
  sqlite3_int64 iWrite;
  if( bDescIdx==0 || *pbFirst==0 ){
    iWrite = iVal - *piPrev;
  }else{
    iWrite = *piPrev - iVal;
  }
  assert( *pbFirst || *piPrev==0 );
  assert( *pbFirst==0 || iWrite>0 );
  *pp += sqlite3Fts3PutVarint(*pp, iWrite);
  *piPrev = iVal;
  *pbFirst = 1;
}

#define COMPARE_DOCID(i1, i2) ((bDescIdx?-1:1) * (i1-i2))

























static int fts3DoclistOrMerge(
  int bDescIdx,                   /* True if arguments are desc */
  char *a1, int n1,               /* First doclist */
  char *a2, int n2,               /* Second doclist */
  char **paOut, int *pnOut        /* OUT: Malloc'd doclist */
){
  sqlite3_int64 i1 = 0;
  sqlite3_int64 i2 = 0;
  sqlite3_int64 iPrev = 0;
  char *pEnd1 = &a1[n1];
  char *pEnd2 = &a2[n2];
  char *p1 = a1;
  char *p2 = a2;
  char *p;
  char *aOut;
  int bFirstOut = 0;

  *paOut = 0;
  *pnOut = 0;






























  aOut = sqlite3_malloc(n1+n2);
  if( !aOut ) return SQLITE_NOMEM;

  p = aOut;
  fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
  fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
  while( p1 || p2 ){
    sqlite3_int64 iDiff = COMPARE_DOCID(i1, i2);

    if( p2 && p1 && iDiff==0 ){
      fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i1);
      fts3PoslistMerge(&p, &p1, &p2);
      fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
      fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
    }else if( !p2 || (p1 && iDiff<0) ){
      fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i1);
      fts3PoslistCopy(&p, &p1);
      fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
    }else{
      fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i2);
      fts3PoslistCopy(&p, &p2);
      fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
    }
  }

  *paOut = aOut;
  *pnOut = (p-aOut);

  return SQLITE_OK;
}













static void fts3DoclistPhraseMerge(
  int bDescIdx,                   /* True if arguments are desc */
  int nDist,                      /* Distance from left to right (1=adjacent) */
  char *aLeft, int nLeft,         /* Left doclist */
  char *aRight, int *pnRight      /* IN/OUT: Right/output doclist */
){
  sqlite3_int64 i1 = 0;
  sqlite3_int64 i2 = 0;
  sqlite3_int64 iPrev = 0;
116372
116373
116374
116375
116376
116377
116378
116379
116380
116381
116382
116383
116384
116385
116386
116387
116388
116389
116390
116391
116392
116393
116394
116395
116396
116397
116398
116399
116400
116401
116402
116403
116404
116405
116406
116407
116408
116409
116410
116411
116412
116413
116414
116415
116416
116417
116418
116419
116420
116421
116422
  assert( nDist>0 );

  p = aOut;
  fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
  fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);

  while( p1 && p2 ){
    sqlite3_int64 iDiff = DOCID_CMP(i1, i2);
    if( iDiff==0 ){
      char *pSave = p;
      sqlite3_int64 iPrevSave = iPrev;
      int bFirstOutSave = bFirstOut;

      fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1);
      if( 0==fts3PoslistPhraseMerge(&p, nDist, 0, 1, &p1, &p2) ){
        p = pSave;
        iPrev = iPrevSave;
        bFirstOut = bFirstOutSave;
      }
      fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
      fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
    }else if( iDiff<0 ){
      fts3PoslistCopy(0, &p1);
      fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
    }else{
      fts3PoslistCopy(0, &p2);
      fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
    }
  }

  *pnRight = p - aOut;
}


/*
** Merge all doclists in the TermSelect.aaOutput[] array into a single
** doclist stored in TermSelect.aaOutput[0]. If successful, delete all
** other doclists (except the aaOutput[0] one) and return SQLITE_OK.
**
** If an OOM error occurs, return SQLITE_NOMEM. In this case it is
** the responsibility of the caller to free any doclists left in the
** TermSelect.aaOutput[] array.
*/
static int fts3TermSelectFinishMerge(Fts3Table *p, TermSelect *pTS){
  char *aOut = 0;
  int nOut = 0;
  int i;

  /* Loop through the doclists in the aaOutput[] array. Merge them all
  ** into a single doclist.
  */







|





|





|
|


|


|
















|







114012
114013
114014
114015
114016
114017
114018
114019
114020
114021
114022
114023
114024
114025
114026
114027
114028
114029
114030
114031
114032
114033
114034
114035
114036
114037
114038
114039
114040
114041
114042
114043
114044
114045
114046
114047
114048
114049
114050
114051
114052
114053
114054
114055
114056
114057
114058
114059
114060
114061
114062
  assert( nDist>0 );

  p = aOut;
  fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
  fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);

  while( p1 && p2 ){
    sqlite3_int64 iDiff = COMPARE_DOCID(i1, i2);
    if( iDiff==0 ){
      char *pSave = p;
      sqlite3_int64 iPrevSave = iPrev;
      int bFirstOutSave = bFirstOut;

      fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i1);
      if( 0==fts3PoslistPhraseMerge(&p, nDist, 0, 1, &p1, &p2) ){
        p = pSave;
        iPrev = iPrevSave;
        bFirstOut = bFirstOutSave;
      }
      fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
      fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
    }else if( iDiff<0 ){
      fts3PoslistCopy(0, &p1);
      fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
    }else{
      fts3PoslistCopy(0, &p2);
      fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
    }
  }

  *pnRight = p - aOut;
}


/*
** Merge all doclists in the TermSelect.aaOutput[] array into a single
** doclist stored in TermSelect.aaOutput[0]. If successful, delete all
** other doclists (except the aaOutput[0] one) and return SQLITE_OK.
**
** If an OOM error occurs, return SQLITE_NOMEM. In this case it is
** the responsibility of the caller to free any doclists left in the
** TermSelect.aaOutput[] array.
*/
static int fts3TermSelectMerge(Fts3Table *p, TermSelect *pTS){
  char *aOut = 0;
  int nOut = 0;
  int i;

  /* Loop through the doclists in the aaOutput[] array. Merge them all
  ** into a single doclist.
  */
116449
116450
116451
116452
116453
116454
116455
116456
116457
116458
116459
116460
116461
116462
116463
116464
116465
116466
116467
116468
116469
116470
116471


116472
116473
116474






116475
116476
116477
116478
116479
116480
116481

  pTS->aaOutput[0] = aOut;
  pTS->anOutput[0] = nOut;
  return SQLITE_OK;
}

/*
** Merge the doclist aDoclist/nDoclist into the TermSelect object passed
** as the first argument. The merge is an "OR" merge (see function
** fts3DoclistOrMerge() for details).
**
** This function is called with the doclist for each term that matches
** a queried prefix. It merges all these doclists into one, the doclist
** for the specified prefix. Since there can be a very large number of
** doclists to merge, the merging is done pair-wise using the TermSelect
** object.
**
** This function returns SQLITE_OK if the merge is successful, or an
** SQLite error code (SQLITE_NOMEM) if an error occurs.
*/
static int fts3TermSelectMerge(
  Fts3Table *p,                   /* FTS table handle */
  TermSelect *pTS,                /* TermSelect object to merge into */


  char *aDoclist,                 /* Pointer to doclist */
  int nDoclist                    /* Size of aDoclist in bytes */
){






  if( pTS->aaOutput[0]==0 ){
    /* If this is the first term selected, copy the doclist to the output
    ** buffer using memcpy(). */
    pTS->aaOutput[0] = sqlite3_malloc(nDoclist);
    pTS->anOutput[0] = nDoclist;
    if( pTS->aaOutput[0] ){
      memcpy(pTS->aaOutput[0], aDoclist, nDoclist);







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

|
|
|
>
>
|
|

>
>
>
>
>
>







114089
114090
114091
114092
114093
114094
114095




114096


114097
114098



114099
114100
114101
114102
114103
114104
114105
114106
114107
114108
114109
114110
114111
114112
114113
114114
114115
114116
114117
114118
114119
114120

  pTS->aaOutput[0] = aOut;
  pTS->anOutput[0] = nOut;
  return SQLITE_OK;
}

/*




** This function is used as the sqlite3Fts3SegReaderIterate() callback when


** querying the full-text index for a doclist associated with a term or
** term-prefix.



*/
static int fts3TermSelectCb(
  Fts3Table *p,                   /* Virtual table object */
  void *pContext,                 /* Pointer to TermSelect structure */
  char *zTerm,
  int nTerm,
  char *aDoclist,
  int nDoclist
){
  TermSelect *pTS = (TermSelect *)pContext;

  UNUSED_PARAMETER(p);
  UNUSED_PARAMETER(zTerm);
  UNUSED_PARAMETER(nTerm);

  if( pTS->aaOutput[0]==0 ){
    /* If this is the first term selected, copy the doclist to the output
    ** buffer using memcpy(). */
    pTS->aaOutput[0] = sqlite3_malloc(nDoclist);
    pTS->anOutput[0] = nDoclist;
    if( pTS->aaOutput[0] ){
      memcpy(pTS->aaOutput[0], aDoclist, nDoclist);
116538
116539
116540
116541
116542
116543
116544
116545
116546
116547
116548
116549
116550
116551
116552
116553
116554
116555
116556
116557
116558
116559
116560
116561
116562

116563
116564
116565
116566
116567
116568
116569
116570
116571
    }
    pCsr->apSegment = apNew;
  }
  pCsr->apSegment[pCsr->nSegment++] = pNew;
  return SQLITE_OK;
}

/*
** Add seg-reader objects to the Fts3MultiSegReader object passed as the
** 8th argument.
**
** This function returns SQLITE_OK if successful, or an SQLite error code
** otherwise.
*/
static int fts3SegReaderCursor(
  Fts3Table *p,                   /* FTS3 table handle */
  int iIndex,                     /* Index to search (from 0 to p->nIndex-1) */
  int iLevel,                     /* Level of segments to scan */
  const char *zTerm,              /* Term to query for */
  int nTerm,                      /* Size of zTerm in bytes */
  int isPrefix,                   /* True for a prefix search */
  int isScan,                     /* True to scan from zTerm to EOF */
  Fts3MultiSegReader *pCsr        /* Cursor object to populate */
){
  int rc = SQLITE_OK;             /* Error code */

  sqlite3_stmt *pStmt = 0;        /* Statement to iterate through segments */
  int rc2;                        /* Result of sqlite3_reset() */

  /* If iLevel is less than 0 and this is not a scan, include a seg-reader 
  ** for the pending-terms. If this is a scan, then this call must be being
  ** made by an fts4aux module, not an FTS table. In this case calling
  ** Fts3SegReaderPending might segfault, as the data structures used by 
  ** fts4aux are not completely populated. So it's easiest to filter these
  ** calls out here.  */







<
<
<
<
<
<
<








|

|
>
|
<







114177
114178
114179
114180
114181
114182
114183







114184
114185
114186
114187
114188
114189
114190
114191
114192
114193
114194
114195
114196

114197
114198
114199
114200
114201
114202
114203
    }
    pCsr->apSegment = apNew;
  }
  pCsr->apSegment[pCsr->nSegment++] = pNew;
  return SQLITE_OK;
}








static int fts3SegReaderCursor(
  Fts3Table *p,                   /* FTS3 table handle */
  int iIndex,                     /* Index to search (from 0 to p->nIndex-1) */
  int iLevel,                     /* Level of segments to scan */
  const char *zTerm,              /* Term to query for */
  int nTerm,                      /* Size of zTerm in bytes */
  int isPrefix,                   /* True for a prefix search */
  int isScan,                     /* True to scan from zTerm to EOF */
  Fts3MultiSegReader *pCsr       /* Cursor object to populate */
){
  int rc = SQLITE_OK;
  int rc2;
  sqlite3_stmt *pStmt = 0;


  /* If iLevel is less than 0 and this is not a scan, include a seg-reader 
  ** for the pending-terms. If this is a scan, then this call must be being
  ** made by an fts4aux module, not an FTS table. In this case calling
  ** Fts3SegReaderPending might segfault, as the data structures used by 
  ** fts4aux are not completely populated. So it's easiest to filter these
  ** calls out here.  */
116646
116647
116648
116649
116650
116651
116652
116653
116654
116655
116656
116657
116658
116659
116660
116661
116662
116663
116664
116665
116666
116667
116668
116669
116670
116671
116672
116673
116674
116675
116676
116677
116678
116679
116680
116681
116682
116683
116684
116685
116686
116687
116688
116689
116690
116691
116692
116693
116694
116695
  memset(pCsr, 0, sizeof(Fts3MultiSegReader));

  return fts3SegReaderCursor(
      p, iIndex, iLevel, zTerm, nTerm, isPrefix, isScan, pCsr
  );
}

/*
** In addition to its current configuration, have the Fts3MultiSegReader
** passed as the 4th argument also scan the doclist for term zTerm/nTerm.
**
** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
*/
static int fts3SegReaderCursorAddZero(
  Fts3Table *p,                   /* FTS virtual table handle */
  const char *zTerm,              /* Term to scan doclist of */
  int nTerm,                      /* Number of bytes in zTerm */
  Fts3MultiSegReader *pCsr        /* Fts3MultiSegReader to modify */
){
  return fts3SegReaderCursor(p, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0,pCsr);
}

/*
** Open an Fts3MultiSegReader to scan the doclist for term zTerm/nTerm. Or,
** if isPrefix is true, to scan the doclist for all terms for which 
** zTerm/nTerm is a prefix. If successful, return SQLITE_OK and write
** a pointer to the new Fts3MultiSegReader to *ppSegcsr. Otherwise, return
** an SQLite error code.
**
** It is the responsibility of the caller to free this object by eventually
** passing it to fts3SegReaderCursorFree() 
**
** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
** Output parameter *ppSegcsr is set to 0 if an error occurs.
*/
static int fts3TermSegReaderCursor(
  Fts3Cursor *pCsr,               /* Virtual table cursor handle */
  const char *zTerm,              /* Term to query for */
  int nTerm,                      /* Size of zTerm in bytes */
  int isPrefix,                   /* True for a prefix search */
  Fts3MultiSegReader **ppSegcsr   /* OUT: Allocated seg-reader cursor */
){
  Fts3MultiSegReader *pSegcsr;    /* Object to allocate and return */
  int rc = SQLITE_NOMEM;          /* Return code */

  pSegcsr = sqlite3_malloc(sizeof(Fts3MultiSegReader));
  if( pSegcsr ){
    int i;
    int bFound = 0;               /* True once an index has been found */
    Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;







<
<
<
<
<
<

|
|
|
|




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






|







114278
114279
114280
114281
114282
114283
114284






114285
114286
114287
114288
114289
114290
114291
114292
114293
114294












114295
114296
114297
114298
114299
114300
114301
114302
114303
114304
114305
114306
114307
114308
114309
  memset(pCsr, 0, sizeof(Fts3MultiSegReader));

  return fts3SegReaderCursor(
      p, iIndex, iLevel, zTerm, nTerm, isPrefix, isScan, pCsr
  );
}







static int fts3SegReaderCursorAddZero(
  Fts3Table *p,
  const char *zTerm,
  int nTerm,
  Fts3MultiSegReader *pCsr
){
  return fts3SegReaderCursor(p, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0,pCsr);
}














SQLITE_PRIVATE int sqlite3Fts3TermSegReaderCursor(
  Fts3Cursor *pCsr,               /* Virtual table cursor handle */
  const char *zTerm,              /* Term to query for */
  int nTerm,                      /* Size of zTerm in bytes */
  int isPrefix,                   /* True for a prefix search */
  Fts3MultiSegReader **ppSegcsr   /* OUT: Allocated seg-reader cursor */
){
  Fts3MultiSegReader *pSegcsr;   /* Object to allocate and return */
  int rc = SQLITE_NOMEM;          /* Return code */

  pSegcsr = sqlite3_malloc(sizeof(Fts3MultiSegReader));
  if( pSegcsr ){
    int i;
    int bFound = 0;               /* True once an index has been found */
    Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
116725
116726
116727
116728
116729
116730
116731
116732
116733
116734
116735
116736
116737
116738
116739
116740
116741
116742







116743
116744
116745
116746
116747

116748
116749
116750
116751
116752
116753
116754
116755
116756
116757

116758
116759
116760

116761
116762
116763
116764
116765
116766
116767
116768
116769

116770

116771
116772
116773
116774
116775
116776
116777
116778
116779
116780
116781
    }
  }

  *ppSegcsr = pSegcsr;
  return rc;
}

/*
** Free an Fts3MultiSegReader allocated by fts3TermSegReaderCursor().
*/
static void fts3SegReaderCursorFree(Fts3MultiSegReader *pSegcsr){
  sqlite3Fts3SegReaderFinish(pSegcsr);
  sqlite3_free(pSegcsr);
}

/*
** This function retreives the doclist for the specified term (or term
** prefix) from the database.







*/
static int fts3TermSelect(
  Fts3Table *p,                   /* Virtual table handle */
  Fts3PhraseToken *pTok,          /* Token to query for */
  int iColumn,                    /* Column to query (or -ve for all columns) */

  int *pnOut,                     /* OUT: Size of buffer at *ppOut */
  char **ppOut                    /* OUT: Malloced result buffer */
){
  int rc;                         /* Return code */
  Fts3MultiSegReader *pSegcsr;    /* Seg-reader cursor for this term */
  TermSelect tsc;                 /* Object for pair-wise doclist merging */
  Fts3SegFilter filter;           /* Segment term filter configuration */

  pSegcsr = pTok->pSegcsr;
  memset(&tsc, 0, sizeof(TermSelect));


  filter.flags = FTS3_SEGMENT_IGNORE_EMPTY | FTS3_SEGMENT_REQUIRE_POS
        | (pTok->isPrefix ? FTS3_SEGMENT_PREFIX : 0)

        | (iColumn<p->nColumn ? FTS3_SEGMENT_COLUMN_FILTER : 0);
  filter.iCol = iColumn;
  filter.zTerm = pTok->z;
  filter.nTerm = pTok->n;

  rc = sqlite3Fts3SegReaderStart(p, pSegcsr, &filter);
  while( SQLITE_OK==rc
      && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pSegcsr)) 
  ){

    rc = fts3TermSelectMerge(p, &tsc, pSegcsr->aDoclist, pSegcsr->nDoclist);

  }

  if( rc==SQLITE_OK ){
    rc = fts3TermSelectFinishMerge(p, &tsc);
  }
  if( rc==SQLITE_OK ){
    *ppOut = tsc.aaOutput[0];
    *pnOut = tsc.anOutput[0];
  }else{
    int i;
    for(i=0; i<SizeofArray(tsc.aaOutput); i++){







<
<
<







|
>
>
>
>
>
>
>





>




|
|




>

|

>









>
|
>



|







114339
114340
114341
114342
114343
114344
114345



114346
114347
114348
114349
114350
114351
114352
114353
114354
114355
114356
114357
114358
114359
114360
114361
114362
114363
114364
114365
114366
114367
114368
114369
114370
114371
114372
114373
114374
114375
114376
114377
114378
114379
114380
114381
114382
114383
114384
114385
114386
114387
114388
114389
114390
114391
114392
114393
114394
114395
114396
114397
114398
114399
114400
114401
114402
114403
114404
    }
  }

  *ppSegcsr = pSegcsr;
  return rc;
}




static void fts3SegReaderCursorFree(Fts3MultiSegReader *pSegcsr){
  sqlite3Fts3SegReaderFinish(pSegcsr);
  sqlite3_free(pSegcsr);
}

/*
** This function retreives the doclist for the specified term (or term
** prefix) from the database. 
**
** The returned doclist may be in one of two formats, depending on the 
** value of parameter isReqPos. If isReqPos is zero, then the doclist is
** a sorted list of delta-compressed docids (a bare doclist). If isReqPos
** is non-zero, then the returned list is in the same format as is stored 
** in the database without the found length specifier at the start of on-disk
** doclists.
*/
static int fts3TermSelect(
  Fts3Table *p,                   /* Virtual table handle */
  Fts3PhraseToken *pTok,          /* Token to query for */
  int iColumn,                    /* Column to query (or -ve for all columns) */
  int isReqPos,                   /* True to include position lists in output */
  int *pnOut,                     /* OUT: Size of buffer at *ppOut */
  char **ppOut                    /* OUT: Malloced result buffer */
){
  int rc;                         /* Return code */
  Fts3MultiSegReader *pSegcsr;   /* Seg-reader cursor for this term */
  TermSelect tsc;                 /* Context object for fts3TermSelectCb() */
  Fts3SegFilter filter;           /* Segment term filter configuration */

  pSegcsr = pTok->pSegcsr;
  memset(&tsc, 0, sizeof(TermSelect));
  tsc.isReqPos = isReqPos;

  filter.flags = FTS3_SEGMENT_IGNORE_EMPTY 
        | (pTok->isPrefix ? FTS3_SEGMENT_PREFIX : 0)
        | (isReqPos ? FTS3_SEGMENT_REQUIRE_POS : 0)
        | (iColumn<p->nColumn ? FTS3_SEGMENT_COLUMN_FILTER : 0);
  filter.iCol = iColumn;
  filter.zTerm = pTok->z;
  filter.nTerm = pTok->n;

  rc = sqlite3Fts3SegReaderStart(p, pSegcsr, &filter);
  while( SQLITE_OK==rc
      && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pSegcsr)) 
  ){
    rc = fts3TermSelectCb(p, (void *)&tsc, 
        pSegcsr->zTerm, pSegcsr->nTerm, pSegcsr->aDoclist, pSegcsr->nDoclist
    );
  }

  if( rc==SQLITE_OK ){
    rc = fts3TermSelectMerge(p, &tsc);
  }
  if( rc==SQLITE_OK ){
    *ppOut = tsc.aaOutput[0];
    *pnOut = tsc.anOutput[0];
  }else{
    int i;
    for(i=0; i<SizeofArray(tsc.aaOutput); i++){
116793
116794
116795
116796
116797
116798
116799
116800
116801
116802
116803
116804








116805
116806
116807
116808

116809
116810
116811
116812
116813
116814
116815
** in buffer aList[], size nList bytes.
**
** If the isPoslist argument is true, then it is assumed that the doclist
** contains a position-list following each docid. Otherwise, it is assumed
** that the doclist is simply a list of docids stored as delta encoded 
** varints.
*/
static int fts3DoclistCountDocids(char *aList, int nList){
  int nDoc = 0;                   /* Return value */
  if( aList ){
    char *aEnd = &aList[nList];   /* Pointer to one byte after EOF */
    char *p = aList;              /* Cursor */








    while( p<aEnd ){
      nDoc++;
      while( (*p++)&0x80 );     /* Skip docid varint */
      fts3PoslistCopy(0, &p);   /* Skip over position list */

    }
  }

  return nDoc;
}

/*







|




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







114416
114417
114418
114419
114420
114421
114422
114423
114424
114425
114426
114427
114428
114429
114430
114431
114432
114433
114434
114435
114436
114437
114438
114439
114440
114441
114442
114443
114444
114445
114446
114447
** in buffer aList[], size nList bytes.
**
** If the isPoslist argument is true, then it is assumed that the doclist
** contains a position-list following each docid. Otherwise, it is assumed
** that the doclist is simply a list of docids stored as delta encoded 
** varints.
*/
static int fts3DoclistCountDocids(int isPoslist, char *aList, int nList){
  int nDoc = 0;                   /* Return value */
  if( aList ){
    char *aEnd = &aList[nList];   /* Pointer to one byte after EOF */
    char *p = aList;              /* Cursor */
    if( !isPoslist ){
      /* The number of docids in the list is the same as the number of 
      ** varints. In FTS3 a varint consists of a single byte with the 0x80 
      ** bit cleared and zero or more bytes with the 0x80 bit set. So to
      ** count the varints in the buffer, just count the number of bytes
      ** with the 0x80 bit clear.  */
      while( p<aEnd ) nDoc += (((*p++)&0x80)==0);
    }else{
      while( p<aEnd ){
        nDoc++;
        while( (*p++)&0x80 );     /* Skip docid varint */
        fts3PoslistCopy(0, &p);   /* Skip over position list */
      }
    }
  }

  return nDoc;
}

/*
116831
116832
116833
116834
116835
116836
116837
116838
116839
116840
116841
116842
116843
116844
116845
      pCsr->isEof = 1;
      rc = sqlite3_reset(pCsr->pStmt);
    }else{
      pCsr->iPrevId = sqlite3_column_int64(pCsr->pStmt, 0);
      rc = SQLITE_OK;
    }
  }else{
    rc = fts3EvalNext((Fts3Cursor *)pCursor);
  }
  assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
  return rc;
}

/*
** This is the xFilter interface for the virtual table.  See







|







114463
114464
114465
114466
114467
114468
114469
114470
114471
114472
114473
114474
114475
114476
114477
      pCsr->isEof = 1;
      rc = sqlite3_reset(pCsr->pStmt);
    }else{
      pCsr->iPrevId = sqlite3_column_int64(pCsr->pStmt, 0);
      rc = SQLITE_OK;
    }
  }else{
    rc = sqlite3Fts3EvalNext((Fts3Cursor *)pCursor);
  }
  assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
  return rc;
}

/*
** This is the xFilter interface for the virtual table.  See
116908
116909
116910
116911
116912
116913
116914
116915
116916
116917
116918
116919
116920
116921
116922
      }
      return rc;
    }

    rc = sqlite3Fts3ReadLock(p);
    if( rc!=SQLITE_OK ) return rc;

    rc = fts3EvalStart(pCsr);

    sqlite3Fts3SegmentsClose(p);
    if( rc!=SQLITE_OK ) return rc;
    pCsr->pNextId = pCsr->aDoclist;
    pCsr->iPrevId = 0;
  }








|







114540
114541
114542
114543
114544
114545
114546
114547
114548
114549
114550
114551
114552
114553
114554
      }
      return rc;
    }

    rc = sqlite3Fts3ReadLock(p);
    if( rc!=SQLITE_OK ) return rc;

    rc = sqlite3Fts3EvalStart(pCsr, pCsr->pExpr, 1);

    sqlite3Fts3SegmentsClose(p);
    if( rc!=SQLITE_OK ) return rc;
    pCsr->pNextId = pCsr->aDoclist;
    pCsr->iPrevId = 0;
  }

117315
117316
117317
117318
117319
117320
117321
117322
117323
117324
117325
117326
117327
117328
117329
117330
117331
117332
117333
117334
117335
117336
117337
117338
117339
117340
117341
117342
117343
117344
117345
117346
117347
117348
117349
117350
117351
117352
117353
117354
117355
117356
117357
117358
117359
117360
117361
  fts3DbExec(&rc, db,
    "ALTER TABLE %Q.'%q_segdir'   RENAME TO '%q_segdir';",
    p->zDb, p->zName, zName
  );
  return rc;
}

/*
** The xSavepoint() method.
**
** Flush the contents of the pending-terms table to disk.
*/
static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
  UNUSED_PARAMETER(iSavepoint);
  assert( ((Fts3Table *)pVtab)->inTransaction );
  assert( ((Fts3Table *)pVtab)->mxSavepoint < iSavepoint );
  TESTONLY( ((Fts3Table *)pVtab)->mxSavepoint = iSavepoint );
  return fts3SyncMethod(pVtab);
}

/*
** The xRelease() method.
**
** This is a no-op.
*/
static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
  TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
  UNUSED_PARAMETER(iSavepoint);
  UNUSED_PARAMETER(pVtab);
  assert( p->inTransaction );
  assert( p->mxSavepoint >= iSavepoint );
  TESTONLY( p->mxSavepoint = iSavepoint-1 );
  return SQLITE_OK;
}

/*
** The xRollbackTo() method.
**
** Discard the contents of the pending terms table.
*/
static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
  Fts3Table *p = (Fts3Table*)pVtab;
  UNUSED_PARAMETER(iSavepoint);
  assert( p->inTransaction );
  assert( p->mxSavepoint >= iSavepoint );
  TESTONLY( p->mxSavepoint = iSavepoint );
  sqlite3Fts3PendingTermsClear(p);







<
<
<
<
<







<
<
<
<
<
<









<
<
<
<
<
<







114947
114948
114949
114950
114951
114952
114953





114954
114955
114956
114957
114958
114959
114960






114961
114962
114963
114964
114965
114966
114967
114968
114969






114970
114971
114972
114973
114974
114975
114976
  fts3DbExec(&rc, db,
    "ALTER TABLE %Q.'%q_segdir'   RENAME TO '%q_segdir';",
    p->zDb, p->zName, zName
  );
  return rc;
}






static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
  UNUSED_PARAMETER(iSavepoint);
  assert( ((Fts3Table *)pVtab)->inTransaction );
  assert( ((Fts3Table *)pVtab)->mxSavepoint < iSavepoint );
  TESTONLY( ((Fts3Table *)pVtab)->mxSavepoint = iSavepoint );
  return fts3SyncMethod(pVtab);
}






static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
  TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
  UNUSED_PARAMETER(iSavepoint);
  UNUSED_PARAMETER(pVtab);
  assert( p->inTransaction );
  assert( p->mxSavepoint >= iSavepoint );
  TESTONLY( p->mxSavepoint = iSavepoint-1 );
  return SQLITE_OK;
}






static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
  Fts3Table *p = (Fts3Table*)pVtab;
  UNUSED_PARAMETER(iSavepoint);
  assert( p->inTransaction );
  assert( p->mxSavepoint >= iSavepoint );
  TESTONLY( p->mxSavepoint = iSavepoint );
  sqlite3Fts3PendingTermsClear(p);
117496
117497
117498
117499
117500
117501
117502












117503
117504
117505
117506
117507
117508
117509
117510
117511
117512
117513
117514
117515
117516
117517
117518
117519
117520
117521
117522
117523
117524
117525
117526
117527
117528
117529
117530
117531
117532
117533
117534
117535
117536
117537
117538
117539
117540
117541
117542
117543
117544
117545
117546
117547
117548
117549
117550
117551
117552
117553
117554
117555
117556
117557
117558
117559
117560
117561
117562
117563
117564
117565
117566
117567
117568
117569
117570
117571
  assert( rc!=SQLITE_OK );
  if( pHash ){
    sqlite3Fts3HashClear(pHash);
    sqlite3_free(pHash);
  }
  return rc;
}













/*
** Allocate an Fts3MultiSegReader for each token in the expression headed
** by pExpr. 
**
** An Fts3SegReader object is a cursor that can seek or scan a range of
** entries within a single segment b-tree. An Fts3MultiSegReader uses multiple
** Fts3SegReader objects internally to provide an interface to seek or scan
** within the union of all segments of a b-tree. Hence the name.
**
** If the allocated Fts3MultiSegReader just seeks to a single entry in a
** segment b-tree (if the term is not a prefix or it is a prefix for which
** there exists prefix b-tree of the right length) then it may be traversed
** and merged incrementally. Otherwise, it has to be merged into an in-memory 
** doclist and then traversed.
*/
static void fts3EvalAllocateReaders(
  Fts3Cursor *pCsr,               /* FTS cursor handle */
  Fts3Expr *pExpr,                /* Allocate readers for this expression */
  int *pnToken,                   /* OUT: Total number of tokens in phrase. */
  int *pnOr,                      /* OUT: Total number of OR nodes in expr. */
  int *pRc                        /* IN/OUT: Error code */
){
  if( pExpr && SQLITE_OK==*pRc ){
    if( pExpr->eType==FTSQUERY_PHRASE ){
      int i;
      int nToken = pExpr->pPhrase->nToken;
      *pnToken += nToken;
      for(i=0; i<nToken; i++){
        Fts3PhraseToken *pToken = &pExpr->pPhrase->aToken[i];
        int rc = fts3TermSegReaderCursor(pCsr, 
            pToken->z, pToken->n, pToken->isPrefix, &pToken->pSegcsr
        );
        if( rc!=SQLITE_OK ){
          *pRc = rc;
          return;
        }
      }
      assert( pExpr->pPhrase->iDoclistToken==0 );
      pExpr->pPhrase->iDoclistToken = -1;
    }else{
      *pnOr += (pExpr->eType==FTSQUERY_OR);
      fts3EvalAllocateReaders(pCsr, pExpr->pLeft, pnToken, pnOr, pRc);
      fts3EvalAllocateReaders(pCsr, pExpr->pRight, pnToken, pnOr, pRc);
    }
  }
}

/*
** Arguments pList/nList contain the doclist for token iToken of phrase p.
** It is merged into the main doclist stored in p->doclist.aAll/nAll.
**
** This function assumes that pList points to a buffer allocated using
** sqlite3_malloc(). This function takes responsibility for eventually
** freeing the buffer.
*/
static void fts3EvalPhraseMergeToken(
  Fts3Table *pTab,                /* FTS Table pointer */
  Fts3Phrase *p,                  /* Phrase to merge pList/nList into */
  int iToken,                     /* Token pList/nList corresponds to */
  char *pList,                    /* Pointer to doclist */
  int nList                       /* Number of bytes in pList */
){
  assert( iToken!=p->iDoclistToken );

  if( pList==0 ){
    sqlite3_free(p->doclist.aAll);
    p->doclist.aAll = 0;
    p->doclist.nAll = 0;







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

















|
|


|








|

















<
<
<
<
<
<
<
<

|
|
|
|
|







115111
115112
115113
115114
115115
115116
115117
115118
115119
115120
115121
115122
115123
115124
115125
115126
115127
115128
115129
115130
115131
115132
115133
115134
115135
115136
115137
115138
115139
115140
115141
115142
115143
115144
115145
115146
115147
115148
115149
115150
115151
115152
115153
115154
115155
115156
115157
115158
115159
115160
115161
115162
115163
115164
115165
115166
115167
115168
115169
115170
115171
115172
115173
115174
115175
115176
115177








115178
115179
115180
115181
115182
115183
115184
115185
115186
115187
115188
115189
115190
  assert( rc!=SQLITE_OK );
  if( pHash ){
    sqlite3Fts3HashClear(pHash);
    sqlite3_free(pHash);
  }
  return rc;
}

#if !SQLITE_CORE
SQLITE_API int sqlite3_extension_init(
  sqlite3 *db, 
  char **pzErrMsg,
  const sqlite3_api_routines *pApi
){
  SQLITE_EXTENSION_INIT2(pApi)
  return sqlite3Fts3Init(db);
}
#endif


/*
** Allocate an Fts3MultiSegReader for each token in the expression headed
** by pExpr. 
**
** An Fts3SegReader object is a cursor that can seek or scan a range of
** entries within a single segment b-tree. An Fts3MultiSegReader uses multiple
** Fts3SegReader objects internally to provide an interface to seek or scan
** within the union of all segments of a b-tree. Hence the name.
**
** If the allocated Fts3MultiSegReader just seeks to a single entry in a
** segment b-tree (if the term is not a prefix or it is a prefix for which
** there exists prefix b-tree of the right length) then it may be traversed
** and merged incrementally. Otherwise, it has to be merged into an in-memory 
** doclist and then traversed.
*/
static void fts3EvalAllocateReaders(
  Fts3Cursor *pCsr, 
  Fts3Expr *pExpr, 
  int *pnToken,                   /* OUT: Total number of tokens in phrase. */
  int *pnOr,                      /* OUT: Total number of OR nodes in expr. */
  int *pRc
){
  if( pExpr && SQLITE_OK==*pRc ){
    if( pExpr->eType==FTSQUERY_PHRASE ){
      int i;
      int nToken = pExpr->pPhrase->nToken;
      *pnToken += nToken;
      for(i=0; i<nToken; i++){
        Fts3PhraseToken *pToken = &pExpr->pPhrase->aToken[i];
        int rc = sqlite3Fts3TermSegReaderCursor(pCsr, 
            pToken->z, pToken->n, pToken->isPrefix, &pToken->pSegcsr
        );
        if( rc!=SQLITE_OK ){
          *pRc = rc;
          return;
        }
      }
      assert( pExpr->pPhrase->iDoclistToken==0 );
      pExpr->pPhrase->iDoclistToken = -1;
    }else{
      *pnOr += (pExpr->eType==FTSQUERY_OR);
      fts3EvalAllocateReaders(pCsr, pExpr->pLeft, pnToken, pnOr, pRc);
      fts3EvalAllocateReaders(pCsr, pExpr->pRight, pnToken, pnOr, pRc);
    }
  }
}









static void fts3EvalPhraseMergeToken(
  Fts3Table *pTab,
  Fts3Phrase *p,
  int iToken,
  char *pList,
  int nList
){
  assert( iToken!=p->iDoclistToken );

  if( pList==0 ){
    sqlite3_free(p->doclist.aAll);
    p->doclist.aAll = 0;
    p->doclist.nAll = 0;
117606
117607
117608
117609
117610
117611
117612
117613
117614
117615
117616
117617
117618
117619
117620
117621
117622
117623
117624
117625
117626
117627
117628
117629
117630
117631
117632
117633
117634
117635
117636
117637
117638
117639
117640
117641
117642
117643
117644
117645
117646
117647
117648
117649
117650
117651
117652
117653
117654
117655
117656
117657


117658
117659
117660
117661
117662
117663
117664
117665
117666
117667
    p->doclist.aAll = pRight;
    p->doclist.nAll = nRight;
  }

  if( iToken>p->iDoclistToken ) p->iDoclistToken = iToken;
}

/*
** Load the doclist for phrase p into p->doclist.aAll/nAll. The loaded doclist
** does not take deferred tokens into account.
**
** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
*/
static int fts3EvalPhraseLoad(
  Fts3Cursor *pCsr,               /* FTS Cursor handle */
  Fts3Phrase *p                   /* Phrase object */
){
  Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
  int iToken;
  int rc = SQLITE_OK;

  for(iToken=0; rc==SQLITE_OK && iToken<p->nToken; iToken++){
    Fts3PhraseToken *pToken = &p->aToken[iToken];
    assert( pToken->pDeferred==0 || pToken->pSegcsr==0 );

    if( pToken->pSegcsr ){
      int nThis = 0;
      char *pThis = 0;
      rc = fts3TermSelect(pTab, pToken, p->iColumn, &nThis, &pThis);
      if( rc==SQLITE_OK ){
        fts3EvalPhraseMergeToken(pTab, p, iToken, pThis, nThis);
      }
    }
    assert( pToken->pSegcsr==0 );
  }

  return rc;
}

/*
** This function is called on each phrase after the position lists for
** any deferred tokens have been loaded into memory. It updates the phrases
** current position list to include only those positions that are really
** instances of the phrase (after considering deferred tokens). If this
** means that the phrase does not appear in the current row, doclist.pList
** and doclist.nList are both zeroed.
**
** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
*/
static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
  int iToken;                     /* Used to iterate through phrase tokens */
  int rc = SQLITE_OK;             /* Return code */


  char *aPoslist = 0;             /* Position list for deferred tokens */
  int nPoslist = 0;               /* Number of bytes in aPoslist */
  int iPrev = -1;                 /* Token number of previous deferred token */

  assert( pPhrase->doclist.bFreeList==0 );

  for(iToken=0; rc==SQLITE_OK && iToken<pPhrase->nToken; iToken++){
    Fts3PhraseToken *pToken = &pPhrase->aToken[iToken];
    Fts3DeferredToken *pDeferred = pToken->pDeferred;








<
<
<
<
<
<

|
|












|










<
<
<
<
<
<
<
<
<
<

|
|
>
>
|
|
|







115225
115226
115227
115228
115229
115230
115231






115232
115233
115234
115235
115236
115237
115238
115239
115240
115241
115242
115243
115244
115245
115246
115247
115248
115249
115250
115251
115252
115253
115254
115255
115256
115257










115258
115259
115260
115261
115262
115263
115264
115265
115266
115267
115268
115269
115270
115271
115272
    p->doclist.aAll = pRight;
    p->doclist.nAll = nRight;
  }

  if( iToken>p->iDoclistToken ) p->iDoclistToken = iToken;
}







static int fts3EvalPhraseLoad(
  Fts3Cursor *pCsr, 
  Fts3Phrase *p
){
  Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
  int iToken;
  int rc = SQLITE_OK;

  for(iToken=0; rc==SQLITE_OK && iToken<p->nToken; iToken++){
    Fts3PhraseToken *pToken = &p->aToken[iToken];
    assert( pToken->pDeferred==0 || pToken->pSegcsr==0 );

    if( pToken->pSegcsr ){
      int nThis = 0;
      char *pThis = 0;
      rc = fts3TermSelect(pTab, pToken, p->iColumn, 1, &nThis, &pThis);
      if( rc==SQLITE_OK ){
        fts3EvalPhraseMergeToken(pTab, p, iToken, pThis, nThis);
      }
    }
    assert( pToken->pSegcsr==0 );
  }

  return rc;
}











static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
  int iToken;
  int rc = SQLITE_OK;

  int nMaxUndeferred = pPhrase->iDoclistToken;
  char *aPoslist = 0;
  int nPoslist = 0;
  int iPrev = -1;

  assert( pPhrase->doclist.bFreeList==0 );

  for(iToken=0; rc==SQLITE_OK && iToken<pPhrase->nToken; iToken++){
    Fts3PhraseToken *pToken = &pPhrase->aToken[iToken];
    Fts3DeferredToken *pDeferred = pToken->pDeferred;

117699
117700
117701
117702
117703
117704
117705
117706
117707
117708
117709
117710
117711
117712
117713
        }
      }
      iPrev = iToken;
    }
  }

  if( iPrev>=0 ){
    int nMaxUndeferred = pPhrase->iDoclistToken;
    if( nMaxUndeferred<0 ){
      pPhrase->doclist.pList = aPoslist;
      pPhrase->doclist.nList = nPoslist;
      pPhrase->doclist.iDocid = pCsr->iPrevId;
      pPhrase->doclist.bFreeList = 1;
    }else{
      int nDistance;







<







115304
115305
115306
115307
115308
115309
115310

115311
115312
115313
115314
115315
115316
115317
        }
      }
      iPrev = iToken;
    }
  }

  if( iPrev>=0 ){

    if( nMaxUndeferred<0 ){
      pPhrase->doclist.pList = aPoslist;
      pPhrase->doclist.nList = nPoslist;
      pPhrase->doclist.iDocid = pCsr->iPrevId;
      pPhrase->doclist.bFreeList = 1;
    }else{
      int nDistance;
117748
117749
117750
117751
117752
117753
117754
117755
117756
117757
117758
117759
117760
117761
117762
117763
117764
117765
117766
117767
117768
117769
117770
}

/*
** This function is called for each Fts3Phrase in a full-text query 
** expression to initialize the mechanism for returning rows. Once this
** function has been called successfully on an Fts3Phrase, it may be
** used with fts3EvalPhraseNext() to iterate through the matching docids.
**
** If parameter bOptOk is true, then the phrase may (or may not) use the
** incremental loading strategy. Otherwise, the entire doclist is loaded into
** memory within this call.
**
** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
*/
static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){
  int rc;                         /* Error code */
  Fts3PhraseToken *pFirst = &p->aToken[0];
  Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;

  if( pCsr->bDesc==pTab->bDescIdx 
   && bOptOk==1 
   && p->nToken==1 
   && pFirst->pSegcsr 







<
<
<
<
<
<


|







115352
115353
115354
115355
115356
115357
115358






115359
115360
115361
115362
115363
115364
115365
115366
115367
115368
}

/*
** This function is called for each Fts3Phrase in a full-text query 
** expression to initialize the mechanism for returning rows. Once this
** function has been called successfully on an Fts3Phrase, it may be
** used with fts3EvalPhraseNext() to iterate through the matching docids.






*/
static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){
  int rc;
  Fts3PhraseToken *pFirst = &p->aToken[0];
  Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;

  if( pCsr->bDesc==pTab->bDescIdx 
   && bOptOk==1 
   && p->nToken==1 
   && pFirst->pSegcsr 
117784
117785
117786
117787
117788
117789
117790
117791
117792
117793
117794
117795
117796
117797
117798
117799
117800
117801
117802
117803
117804

  assert( rc!=SQLITE_OK || p->nToken<1 || p->aToken[0].pSegcsr==0 || p->bIncr );
  return rc;
}

/*
** This function is used to iterate backwards (from the end to start) 
** through doclists. It is used by this module to iterate through phrase
** doclists in reverse and by the fts3_write.c module to iterate through
** pending-terms lists when writing to databases with "order=desc".
**
** The doclist may be sorted in ascending (parameter bDescIdx==0) or 
** descending (parameter bDescIdx==1) order of docid. Regardless, this
** function iterates from the end of the doclist to the beginning.
*/
SQLITE_PRIVATE void sqlite3Fts3DoclistPrev(
  int bDescIdx,                   /* True if the doclist is desc */
  char *aDoclist,                 /* Pointer to entire doclist */
  int nDoclist,                   /* Length of aDoclist in bytes */
  char **ppIter,                  /* IN/OUT: Iterator pointer */
  sqlite3_int64 *piDocid,         /* IN/OUT: Docid pointer */







|
<
<
<
<
<
<







115382
115383
115384
115385
115386
115387
115388
115389






115390
115391
115392
115393
115394
115395
115396

  assert( rc!=SQLITE_OK || p->nToken<1 || p->aToken[0].pSegcsr==0 || p->bIncr );
  return rc;
}

/*
** This function is used to iterate backwards (from the end to start) 
** through doclists.






*/
SQLITE_PRIVATE void sqlite3Fts3DoclistPrev(
  int bDescIdx,                   /* True if the doclist is desc */
  char *aDoclist,                 /* Pointer to entire doclist */
  int nDoclist,                   /* Length of aDoclist in bytes */
  char **ppIter,                  /* IN/OUT: Iterator pointer */
  sqlite3_int64 *piDocid,         /* IN/OUT: Docid pointer */
117855
117856
117857
117858
117859
117860
117861
117862
117863
117864
117865
117866
117867
117868
117869
117870
117871
** SQLITE_OK.
**
** If there is no "next" entry and no error occurs, then *pbEof is set to
** 1 before returning. Otherwise, if no error occurs and the iterator is
** successfully advanced, *pbEof is set to 0.
*/
static int fts3EvalPhraseNext(
  Fts3Cursor *pCsr,               /* FTS Cursor handle */
  Fts3Phrase *p,                  /* Phrase object to advance to next docid */
  u8 *pbEof                       /* OUT: Set to 1 if EOF */
){
  int rc = SQLITE_OK;
  Fts3Doclist *pDL = &p->doclist;
  Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;

  if( p->bIncr ){
    assert( p->nToken==1 );







|
|
|







115447
115448
115449
115450
115451
115452
115453
115454
115455
115456
115457
115458
115459
115460
115461
115462
115463
** SQLITE_OK.
**
** If there is no "next" entry and no error occurs, then *pbEof is set to
** 1 before returning. Otherwise, if no error occurs and the iterator is
** successfully advanced, *pbEof is set to 0.
*/
static int fts3EvalPhraseNext(
  Fts3Cursor *pCsr, 
  Fts3Phrase *p, 
  u8 *pbEof
){
  int rc = SQLITE_OK;
  Fts3Doclist *pDL = &p->doclist;
  Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;

  if( p->bIncr ){
    assert( p->nToken==1 );
117903
117904
117905
117906
117907
117908
117909
117910
117911
117912
117913
117914
117915
117916
117917
117918
117919
117920
117921
117922
117923
117924
117925
117926
117927
117928
117929
117930
117931
117932
117933
117934
117935
117936
117937
117938
117939
117940
117941
117942
117943
117944
117945
117946
117947
117948
117949
117950
117951
117952
117953
117954
117955
117956
117957
117958
117959
117960
117961
117962
117963
117964
117965
117966
117967
117968
117969
117970
117971
117972
117973
117974
117975
117976
117977
117978
117979
117980
117981
117982
117983
117984
117985
117986
117987
117988
117989
117990
117991
117992
117993
117994
117995
117996
117997
117998
117999
118000
118001
118002
118003
118004
118005
118006
      }
      pDL->pList = pIter;
      fts3PoslistCopy(0, &pIter);
      pDL->nList = (pIter - pDL->pList);

      /* pIter now points just past the 0x00 that terminates the position-
      ** list for document pDL->iDocid. However, if this position-list was
      ** edited in place by fts3EvalNearTrim(), then pIter may not actually
      ** point to the start of the next docid value. The following line deals
      ** with this case by advancing pIter past the zero-padding added by
      ** fts3EvalNearTrim().  */
      while( pIter<pEnd && *pIter==0 ) pIter++;

      pDL->pNextDocid = pIter;
      assert( pIter>=&pDL->aAll[pDL->nAll] || *pIter );
      *pbEof = 0;
    }
  }

  return rc;
}

/*
**
** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
** Otherwise, fts3EvalPhraseStart() is called on all phrases within the
** expression. Also the Fts3Expr.bDeferred variable is set to true for any
** expressions for which all descendent tokens are deferred.
**
** If parameter bOptOk is zero, then it is guaranteed that the
** Fts3Phrase.doclist.aAll/nAll variables contain the entire doclist for
** each phrase in the expression (subject to deferred token processing).
** Or, if bOptOk is non-zero, then one or more tokens within the expression
** may be loaded incrementally, meaning doclist.aAll/nAll is not available.
**
** If an error occurs within this function, *pRc is set to an SQLite error
** code before returning.
*/
static void fts3EvalStartReaders(
  Fts3Cursor *pCsr,               /* FTS Cursor handle */
  Fts3Expr *pExpr,                /* Expression to initialize phrases in */
  int bOptOk,                     /* True to enable incremental loading */
  int *pRc                        /* IN/OUT: Error code */
){
  if( pExpr && SQLITE_OK==*pRc ){
    if( pExpr->eType==FTSQUERY_PHRASE ){
      int i;
      int nToken = pExpr->pPhrase->nToken;
      for(i=0; i<nToken; i++){
        if( pExpr->pPhrase->aToken[i].pDeferred==0 ) break;
      }
      pExpr->bDeferred = (i==nToken);
      *pRc = fts3EvalPhraseStart(pCsr, bOptOk, pExpr->pPhrase);
    }else{
      fts3EvalStartReaders(pCsr, pExpr->pLeft, bOptOk, pRc);
      fts3EvalStartReaders(pCsr, pExpr->pRight, bOptOk, pRc);
      pExpr->bDeferred = (pExpr->pLeft->bDeferred && pExpr->pRight->bDeferred);
    }
  }
}

/*
** An array of the following structures is assembled as part of the process
** of selecting tokens to defer before the query starts executing (as part
** of the xFilter() method). There is one element in the array for each
** token in the FTS expression.
**
** Tokens are divided into AND/NEAR clusters. All tokens in a cluster belong
** to phrases that are connected only by AND and NEAR operators (not OR or
** NOT). When determining tokens to defer, each AND/NEAR cluster is considered
** separately. The root of a tokens AND/NEAR cluster is stored in 
** Fts3TokenAndCost.pRoot.
*/
typedef struct Fts3TokenAndCost Fts3TokenAndCost;
struct Fts3TokenAndCost {
  Fts3Phrase *pPhrase;            /* The phrase the token belongs to */
  int iToken;                     /* Position of token in phrase */
  Fts3PhraseToken *pToken;        /* The token itself */
  Fts3Expr *pRoot;                /* Root of NEAR/AND cluster */
  int nOvfl;                      /* Number of overflow pages to load doclist */
  int iCol;                       /* The column the token must match */
};

/*
** This function is used to populate an allocated Fts3TokenAndCost array.
**
** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
** Otherwise, if an error occurs during execution, *pRc is set to an
** SQLite error code.
*/
static void fts3EvalTokenCosts(
  Fts3Cursor *pCsr,               /* FTS Cursor handle */
  Fts3Expr *pRoot,                /* Root of current AND/NEAR cluster */
  Fts3Expr *pExpr,                /* Expression to consider */
  Fts3TokenAndCost **ppTC,        /* Write new entries to *(*ppTC)++ */
  Fts3Expr ***ppOr,               /* Write new OR root to *(*ppOr)++ */
  int *pRc                        /* IN/OUT: Error code */
){
  if( *pRc==SQLITE_OK && pExpr ){
    if( pExpr->eType==FTSQUERY_PHRASE ){
      Fts3Phrase *pPhrase = pExpr->pPhrase;
      int i;
      for(i=0; *pRc==SQLITE_OK && i<pPhrase->nToken; i++){
        Fts3TokenAndCost *pTC = (*ppTC)++;







|


|











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

|
|
|
|


















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





|
|



<
<
<
<
<
<
<

|
|
|
|
|
|







115495
115496
115497
115498
115499
115500
115501
115502
115503
115504
115505
115506
115507
115508
115509
115510
115511
115512
115513
115514
115515
115516
















115517
115518
115519
115520
115521
115522
115523
115524
115525
115526
115527
115528
115529
115530
115531
115532
115533
115534
115535
115536
115537
115538
115539












115540
115541
115542
115543
115544
115545
115546
115547
115548
115549







115550
115551
115552
115553
115554
115555
115556
115557
115558
115559
115560
115561
115562
115563
      }
      pDL->pList = pIter;
      fts3PoslistCopy(0, &pIter);
      pDL->nList = (pIter - pDL->pList);

      /* pIter now points just past the 0x00 that terminates the position-
      ** list for document pDL->iDocid. However, if this position-list was
      ** edited in place by fts3EvalNearTrim2(), then pIter may not actually
      ** point to the start of the next docid value. The following line deals
      ** with this case by advancing pIter past the zero-padding added by
      ** fts3EvalNearTrim2().  */
      while( pIter<pEnd && *pIter==0 ) pIter++;

      pDL->pNextDocid = pIter;
      assert( pIter>=&pDL->aAll[pDL->nAll] || *pIter );
      *pbEof = 0;
    }
  }

  return rc;
}

















static void fts3EvalStartReaders(
  Fts3Cursor *pCsr, 
  Fts3Expr *pExpr, 
  int bOptOk,
  int *pRc
){
  if( pExpr && SQLITE_OK==*pRc ){
    if( pExpr->eType==FTSQUERY_PHRASE ){
      int i;
      int nToken = pExpr->pPhrase->nToken;
      for(i=0; i<nToken; i++){
        if( pExpr->pPhrase->aToken[i].pDeferred==0 ) break;
      }
      pExpr->bDeferred = (i==nToken);
      *pRc = fts3EvalPhraseStart(pCsr, bOptOk, pExpr->pPhrase);
    }else{
      fts3EvalStartReaders(pCsr, pExpr->pLeft, bOptOk, pRc);
      fts3EvalStartReaders(pCsr, pExpr->pRight, bOptOk, pRc);
      pExpr->bDeferred = (pExpr->pLeft->bDeferred && pExpr->pRight->bDeferred);
    }
  }
}













typedef struct Fts3TokenAndCost Fts3TokenAndCost;
struct Fts3TokenAndCost {
  Fts3Phrase *pPhrase;            /* The phrase the token belongs to */
  int iToken;                     /* Position of token in phrase */
  Fts3PhraseToken *pToken;        /* The token itself */
  Fts3Expr *pRoot; 
  int nOvfl;
  int iCol;                       /* The column the token must match */
};








static void fts3EvalTokenCosts(
  Fts3Cursor *pCsr, 
  Fts3Expr *pRoot, 
  Fts3Expr *pExpr, 
  Fts3TokenAndCost **ppTC,
  Fts3Expr ***ppOr,
  int *pRc
){
  if( *pRc==SQLITE_OK && pExpr ){
    if( pExpr->eType==FTSQUERY_PHRASE ){
      Fts3Phrase *pPhrase = pExpr->pPhrase;
      int i;
      for(i=0; *pRc==SQLITE_OK && i<pPhrase->nToken; i++){
        Fts3TokenAndCost *pTC = (*ppTC)++;
118024
118025
118026
118027
118028
118029
118030
118031
118032
118033
118034
118035
118036
118037
118038
118039
118040
118041
118042
118043
118044
118045
118046
118047
118048
118049
118050
118051
118052
118053
118054
118055
118056
118057
118058
118059
118060
118061
        (*ppOr)++;
      }
      fts3EvalTokenCosts(pCsr, pRoot, pExpr->pRight, ppTC, ppOr, pRc);
    }
  }
}

/*
** Determine the average document (row) size in pages. If successful,
** write this value to *pnPage and return SQLITE_OK. Otherwise, return
** an SQLite error code.
**
** The average document size in pages is calculated by first calculating 
** determining the average size in bytes, B. If B is less than the amount
** of data that will fit on a single leaf page of an intkey table in
** this database, then the average docsize is 1. Otherwise, it is 1 plus
** the number of overflow pages consumed by a record B bytes in size.
*/
static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
  if( pCsr->nRowAvg==0 ){
    /* The average document size, which is required to calculate the cost
    ** of each doclist, has not yet been determined. Read the required 
    ** data from the %_stat table to calculate it.
    **
    ** Entry 0 of the %_stat table is a blob containing (nCol+1) FTS3 
    ** varints, where nCol is the number of columns in the FTS3 table.
    ** The first varint is the number of documents currently stored in
    ** the table. The following nCol varints contain the total amount of
    ** data stored in all rows of each column of the table, from left
    ** to right.
    */
    int rc;
    Fts3Table *p = (Fts3Table*)pCsr->base.pVtab;
    sqlite3_stmt *pStmt;
    sqlite3_int64 nDoc = 0;
    sqlite3_int64 nByte = 0;
    const char *pEnd;
    const char *a;







<
<
<
<
<
<
<
<
<
<
<



|
|
|
|
|
|
|
|
|
|







115581
115582
115583
115584
115585
115586
115587











115588
115589
115590
115591
115592
115593
115594
115595
115596
115597
115598
115599
115600
115601
115602
115603
115604
115605
115606
115607
        (*ppOr)++;
      }
      fts3EvalTokenCosts(pCsr, pRoot, pExpr->pRight, ppTC, ppOr, pRc);
    }
  }
}












static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
  if( pCsr->nRowAvg==0 ){
    /* The average document size, which is required to calculate the cost
     ** of each doclist, has not yet been determined. Read the required 
     ** data from the %_stat table to calculate it.
     **
     ** Entry 0 of the %_stat table is a blob containing (nCol+1) FTS3 
     ** varints, where nCol is the number of columns in the FTS3 table.
     ** The first varint is the number of documents currently stored in
     ** the table. The following nCol varints contain the total amount of
     ** data stored in all rows of each column of the table, from left
     ** to right.
     */
    int rc;
    Fts3Table *p = (Fts3Table*)pCsr->base.pVtab;
    sqlite3_stmt *pStmt;
    sqlite3_int64 nDoc = 0;
    sqlite3_int64 nByte = 0;
    const char *pEnd;
    const char *a;
118082
118083
118084
118085
118086
118087
118088
118089
118090
118091
118092
118093
118094
118095
118096
118097
118098
118099
118100
118101
118102
118103
118104
118105
118106
118107
118108
118109
118110

118111

118112
118113
118114
118115
118116
118117
118118
118119
118120
118121
118122
118123
118124
118125
118126
118127
118128
118129
118130
118131
118132
118133
118134
118135
118136
118137
118138
118139
118140
118141
118142
118143
118144
118145
118146
118147
118148
118149
118150
118151
118152
118153
118154
118155
118156
118157
118158
118159
118160
118161
118162
118163
118164
118165
118166
118167
118168
118169
118170

118171
118172
118173
118174
118175
118176
118177
118178
118179

118180
118181
118182
118183
118184
118185
118186
118187
118188
118189
118190

118191
118192
118193
118194
118195
118196
118197
118198
118199








118200
118201
118202
118203
118204
118205
118206
118207
118208
118209
118210
118211
118212
118213
118214
118215
118216
118217
118218
118219
118220
118221
118222
118223
118224
118225
118226
118227

















118228


118229
118230
118231
118232
118233
118234
118235
118236
118237
118238
118239
118240
118241
118242
118243
118244
118245
118246
118247
118248
118249
118250
118251
118252
118253
118254
118255
118256
118257
118258
118259
118260
118261
118262
118263
118264
118265
118266
118267
118268
118269
118270
118271
118272
118273
118274
118275
118276
118277
118278
118279
118280
118281
118282
118283
118284
118285
118286
118287
118288
118289
118290
118291
118292
118293
118294
118295
118296
118297
118298
118299
118300
118301
118302
118303
118304
118305
118306
    if( rc!=SQLITE_OK ) return rc;
  }

  *pnPage = pCsr->nRowAvg;
  return SQLITE_OK;
}

/*
** This function is called to select the tokens (if any) that will be 
** deferred. The array aTC[] has already been populated when this is
** called.
**
** This function is called once for each AND/NEAR cluster in the 
** expression. Each invocation determines which tokens to defer within
** the cluster with root node pRoot. See comments above the definition
** of struct Fts3TokenAndCost for more details.
**
** If no error occurs, SQLITE_OK is returned and sqlite3Fts3DeferToken()
** called on each token to defer. Otherwise, an SQLite error code is
** returned.
*/
static int fts3EvalSelectDeferred(
  Fts3Cursor *pCsr,               /* FTS Cursor handle */
  Fts3Expr *pRoot,                /* Consider tokens with this root node */
  Fts3TokenAndCost *aTC,          /* Array of expression tokens and costs */
  int nTC                         /* Number of entries in aTC[] */
){
  Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
  int nDocSize = 0;               /* Number of pages per doc loaded */

  int rc = SQLITE_OK;             /* Return code */

  int ii;                         /* Iterator variable for various purposes */
  int nOvfl = 0;                  /* Total overflow pages used by doclists */
  int nToken = 0;                 /* Total number of tokens in cluster */

  int nMinEst = 0;                /* The minimum count for any phrase so far. */
  int nLoad4 = 1;                 /* (Phrases that will be loaded)^4. */

  /* Count the tokens in this AND/NEAR cluster. If none of the doclists
  ** associated with the tokens spill onto overflow pages, or if there is
  ** only 1 token, exit early. No tokens to defer in this case. */
  for(ii=0; ii<nTC; ii++){
    if( aTC[ii].pRoot==pRoot ){
      nOvfl += aTC[ii].nOvfl;
      nToken++;
    }
  }
  if( nOvfl==0 || nToken<2 ) return SQLITE_OK;

  /* Obtain the average docsize (in pages). */
  rc = fts3EvalAverageDocsize(pCsr, &nDocSize);
  assert( rc!=SQLITE_OK || nDocSize>0 );


  /* Iterate through all tokens in this AND/NEAR cluster, in ascending order 
  ** of the number of overflow pages that will be loaded by the pager layer 
  ** to retrieve the entire doclist for the token from the full-text index.
  ** Load the doclists for tokens that are either:
  **
  **   a. The cheapest token in the entire query (i.e. the one visited by the
  **      first iteration of this loop), or
  **
  **   b. Part of a multi-token phrase.
  **
  ** After each token doclist is loaded, merge it with the others from the
  ** same phrase and count the number of documents that the merged doclist
  ** contains. Set variable "nMinEst" to the smallest number of documents in 
  ** any phrase doclist for which 1 or more token doclists have been loaded.
  ** Let nOther be the number of other phrases for which it is certain that
  ** one or more tokens will not be deferred.
  **
  ** Then, for each token, defer it if loading the doclist would result in
  ** loading N or more overflow pages into memory, where N is computed as:
  **
  **    (nMinEst + 4^nOther - 1) / (4^nOther)
  */
  for(ii=0; ii<nToken && rc==SQLITE_OK; ii++){
    int iTC;                      /* Used to iterate through aTC[] array. */
    Fts3TokenAndCost *pTC = 0;    /* Set to cheapest remaining token. */

    /* Set pTC to point to the cheapest remaining token. */
    for(iTC=0; iTC<nTC; iTC++){
      if( aTC[iTC].pToken && aTC[iTC].pRoot==pRoot 
       && (!pTC || aTC[iTC].nOvfl<pTC->nOvfl) 
      ){
        pTC = &aTC[iTC];
      }
    }
    assert( pTC );


    if( ii && pTC->nOvfl>=((nMinEst+(nLoad4/4)-1)/(nLoad4/4))*nDocSize ){
      /* The number of overflow pages to load for this (and therefore all
      ** subsequent) tokens is greater than the estimated number of pages 
      ** that will be loaded if all subsequent tokens are deferred.
      */
      Fts3PhraseToken *pToken = pTC->pToken;
      rc = sqlite3Fts3DeferToken(pCsr, pToken, pTC->iCol);
      fts3SegReaderCursorFree(pToken->pSegcsr);
      pToken->pSegcsr = 0;

    }else{
      nLoad4 = nLoad4*4;
      if( ii==0 || pTC->pPhrase->nToken>1 ){
        /* Either this is the cheapest token in the entire query, or it is
        ** part of a multi-token phrase. Either way, the entire doclist will
        ** (eventually) be loaded into memory. It may as well be now. */
        Fts3PhraseToken *pToken = pTC->pToken;
        int nList = 0;
        char *pList = 0;
        rc = fts3TermSelect(pTab, pToken, pTC->iCol, &nList, &pList);
        assert( rc==SQLITE_OK || pList==0 );

        if( rc==SQLITE_OK ){
          int nCount;
          fts3EvalPhraseMergeToken(pTab, pTC->pPhrase, pTC->iToken,pList,nList);
          nCount = fts3DoclistCountDocids(
              pTC->pPhrase->doclist.aAll, pTC->pPhrase->doclist.nAll
          );
          if( ii==0 || nCount<nMinEst ) nMinEst = nCount;
        }
      }








    }
    pTC->pToken = 0;
  }

  return rc;
}

/*
** This function is called from within the xFilter method. It initializes
** the full-text query currently stored in pCsr->pExpr. To iterate through
** the results of a query, the caller does:
**
**    fts3EvalStart(pCsr);
**    while( 1 ){
**      fts3EvalNext(pCsr);
**      if( pCsr->bEof ) break;
**      ... return row pCsr->iPrevId to the caller ...
**    }
*/
static int fts3EvalStart(Fts3Cursor *pCsr){
  Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
  int rc = SQLITE_OK;
  int nToken = 0;
  int nOr = 0;

  /* Allocate a MultiSegReader for each token in the expression. */
  fts3EvalAllocateReaders(pCsr, pCsr->pExpr, &nToken, &nOr, &rc);


















  /* Determine which, if any, tokens in the expression should be deferred. */


  if( rc==SQLITE_OK && nToken>1 && pTab->bHasStat ){
    Fts3TokenAndCost *aTC;
    Fts3Expr **apOr;
    aTC = (Fts3TokenAndCost *)sqlite3_malloc(
        sizeof(Fts3TokenAndCost) * nToken
      + sizeof(Fts3Expr *) * nOr * 2
    );
    apOr = (Fts3Expr **)&aTC[nToken];

    if( !aTC ){
      rc = SQLITE_NOMEM;
    }else{
      int ii;
      Fts3TokenAndCost *pTC = aTC;
      Fts3Expr **ppOr = apOr;

      fts3EvalTokenCosts(pCsr, 0, pCsr->pExpr, &pTC, &ppOr, &rc);
      nToken = pTC-aTC;
      nOr = ppOr-apOr;

      if( rc==SQLITE_OK ){
        rc = fts3EvalSelectDeferred(pCsr, 0, aTC, nToken);
        for(ii=0; rc==SQLITE_OK && ii<nOr; ii++){
          rc = fts3EvalSelectDeferred(pCsr, apOr[ii], aTC, nToken);
        }
      }

      sqlite3_free(aTC);
    }
  }

  fts3EvalStartReaders(pCsr, pCsr->pExpr, 1, &rc);
  return rc;
}

/*
** Invalidate the current position list for phrase pPhrase.
*/
static void fts3EvalInvalidatePoslist(Fts3Phrase *pPhrase){
  if( pPhrase->doclist.bFreeList ){
    sqlite3_free(pPhrase->doclist.pList);
  }
  pPhrase->doclist.pList = 0;
  pPhrase->doclist.nList = 0;
  pPhrase->doclist.bFreeList = 0;
}

/*
** This function is called to edit the position list associated with
** the phrase object passed as the fifth argument according to a NEAR
** condition. For example:
**
**     abc NEAR/5 "def ghi"
**
** Parameter nNear is passed the NEAR distance of the expression (5 in
** the example above). When this function is called, *paPoslist points to
** the position list, and *pnToken is the number of phrase tokens in, the
** phrase on the other side of the NEAR operator to pPhrase. For example,
** if pPhrase refers to the "def ghi" phrase, then *paPoslist points to
** the position list associated with phrase "abc".
**
** All positions in the pPhrase position list that are not sufficiently
** close to a position in the *paPoslist position list are removed. If this
** leaves 0 positions, zero is returned. Otherwise, non-zero.
**
** Before returning, *paPoslist is set to point to the position lsit 
** associated with pPhrase. And *pnToken is set to the number of tokens in
** pPhrase.
*/
static int fts3EvalNearTrim(
  int nNear,                      /* NEAR distance. As in "NEAR/nNear". */
  char *aTmp,                     /* Temporary space to use */
  char **paPoslist,               /* IN/OUT: Position list */
  int *pnToken,                   /* IN/OUT: Tokens in phrase of *paPoslist */
  Fts3Phrase *pPhrase             /* The phrase object to trim the doclist of */
){
  int nParam1 = nNear + pPhrase->nToken;
  int nParam2 = nNear + *pnToken;







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

|
|
|
|

<
|
>
|
>
|
<
<

|
|

<
<
<



|


|

<

<

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

<
|
|
|

|




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



|

>

|

<
<
<
<


>
>
>
>
>
>
>
>







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






|

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















|














|



<
<
<
|








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







115628
115629
115630
115631
115632
115633
115634














115635
115636
115637
115638
115639
115640

115641
115642
115643
115644
115645


115646
115647
115648
115649



115650
115651
115652
115653
115654
115655
115656
115657

115658

115659























115660
115661
115662
115663

115664
115665
115666
115667
115668
115669
115670
115671
115672
115673
115674




115675



115676
115677





115678
115679
115680
115681
115682
115683
115684
115685
115686




115687
115688
115689
115690
115691
115692
115693
115694
115695
115696
115697
115698
115699
115700
115701
115702
115703












115704
115705
115706
115707
115708
115709
115710
115711
115712
115713
115714
115715
115716
115717
115718
115719
115720
115721
115722
115723
115724
115725
115726
115727
115728
115729
115730
115731
115732
115733
115734
115735
115736
115737
115738
115739
115740
115741
115742
115743
115744
115745
115746
115747
115748
115749
115750
115751
115752
115753
115754
115755
115756
115757
115758
115759
115760
115761
115762
115763
115764
115765
115766
115767



115768
115769
115770
115771
115772
115773
115774
115775
115776






















115777
115778
115779
115780
115781
115782
115783
115784
115785
    if( rc!=SQLITE_OK ) return rc;
  }

  *pnPage = pCsr->nRowAvg;
  return SQLITE_OK;
}















static int fts3EvalSelectDeferred(
  Fts3Cursor *pCsr,
  Fts3Expr *pRoot,
  Fts3TokenAndCost *aTC,
  int nTC
){

  int nDocSize = 0;
  int nDocEst = 0;
  int rc = SQLITE_OK;
  Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
  int ii;



  int nOvfl = 0;
  int nTerm = 0;




  for(ii=0; ii<nTC; ii++){
    if( aTC[ii].pRoot==pRoot ){
      nOvfl += aTC[ii].nOvfl;
      nTerm++;
    }
  }
  if( nOvfl==0 || nTerm<2 ) return SQLITE_OK;


  rc = fts3EvalAverageDocsize(pCsr, &nDocSize);

























  for(ii=0; ii<nTerm && rc==SQLITE_OK; ii++){
    int jj;
    Fts3TokenAndCost *pTC = 0;


    for(jj=0; jj<nTC; jj++){
      if( aTC[jj].pToken && aTC[jj].pRoot==pRoot 
       && (!pTC || aTC[jj].nOvfl<pTC->nOvfl) 
      ){
        pTC = &aTC[jj];
      }
    }
    assert( pTC );

    /* At this point pTC points to the cheapest remaining token. */
    if( ii==0 ){




      if( pTC->nOvfl ){



        nDocEst = (pTC->nOvfl * pTab->nPgsz + pTab->nPgsz) / 10;
      }else{





        Fts3PhraseToken *pToken = pTC->pToken;
        int nList = 0;
        char *pList = 0;
        rc = fts3TermSelect(pTab, pToken, pTC->iCol, 1, &nList, &pList);
        assert( rc==SQLITE_OK || pList==0 );

        if( rc==SQLITE_OK ){
          nDocEst = fts3DoclistCountDocids(1, pList, nList);
          fts3EvalPhraseMergeToken(pTab, pTC->pPhrase, pTC->iToken,pList,nList);




        }
      }
    }else{
      if( pTC->nOvfl>=(nDocEst*nDocSize) ){
        Fts3PhraseToken *pToken = pTC->pToken;
        rc = sqlite3Fts3DeferToken(pCsr, pToken, pTC->iCol);
        fts3SegReaderCursorFree(pToken->pSegcsr);
        pToken->pSegcsr = 0;
      }
      nDocEst = 1 + (nDocEst/4);
    }
    pTC->pToken = 0;
  }

  return rc;
}













SQLITE_PRIVATE int sqlite3Fts3EvalStart(Fts3Cursor *pCsr, Fts3Expr *pExpr, int bOptOk){
  Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
  int rc = SQLITE_OK;
  int nToken = 0;
  int nOr = 0;

  /* Allocate a MultiSegReader for each token in the expression. */
  fts3EvalAllocateReaders(pCsr, pExpr, &nToken, &nOr, &rc);

  /* Call fts3EvalPhraseStart() on all phrases in the expression. TODO:
  ** This call will eventually also be responsible for determining which
  ** tokens are 'deferred' until the document text is loaded into memory.
  **
  ** Each token in each phrase is dealt with using one of the following
  ** three strategies:
  **
  **   1. Entire doclist loaded into memory as part of the
  **      fts3EvalStartReaders() call.
  **
  **   2. Doclist loaded into memory incrementally, as part of each
  **      sqlite3Fts3EvalNext() call.
  **
  **   3. Token doclist is never loaded. Instead, documents are loaded into
  **      memory and scanned for the token as part of the sqlite3Fts3EvalNext()
  **      call. This is known as a "deferred" token.
  */

  /* If bOptOk is true, check if there are any tokens that should be deferred.
  */
  if( rc==SQLITE_OK && bOptOk && nToken>1 && pTab->bHasStat ){
    Fts3TokenAndCost *aTC;
    Fts3Expr **apOr;
    aTC = (Fts3TokenAndCost *)sqlite3_malloc(
        sizeof(Fts3TokenAndCost) * nToken
      + sizeof(Fts3Expr *) * nOr * 2
    );
    apOr = (Fts3Expr **)&aTC[nToken];

    if( !aTC ){
      rc = SQLITE_NOMEM;
    }else{
      int ii;
      Fts3TokenAndCost *pTC = aTC;
      Fts3Expr **ppOr = apOr;

      fts3EvalTokenCosts(pCsr, 0, pExpr, &pTC, &ppOr, &rc);
      nToken = pTC-aTC;
      nOr = ppOr-apOr;

      if( rc==SQLITE_OK ){
        rc = fts3EvalSelectDeferred(pCsr, 0, aTC, nToken);
        for(ii=0; rc==SQLITE_OK && ii<nOr; ii++){
          rc = fts3EvalSelectDeferred(pCsr, apOr[ii], aTC, nToken);
        }
      }

      sqlite3_free(aTC);
    }
  }

  fts3EvalStartReaders(pCsr, pExpr, bOptOk, &rc);
  return rc;
}




static void fts3EvalZeroPoslist(Fts3Phrase *pPhrase){
  if( pPhrase->doclist.bFreeList ){
    sqlite3_free(pPhrase->doclist.pList);
  }
  pPhrase->doclist.pList = 0;
  pPhrase->doclist.nList = 0;
  pPhrase->doclist.bFreeList = 0;
}























static int fts3EvalNearTrim2(
  int nNear,
  char *aTmp,                     /* Temporary space to use */
  char **paPoslist,               /* IN/OUT: Position list */
  int *pnToken,                   /* IN/OUT: Tokens in phrase of *paPoslist */
  Fts3Phrase *pPhrase             /* The phrase object to trim the doclist of */
){
  int nParam1 = nNear + pPhrase->nToken;
  int nParam2 = nNear + *pnToken;
118324
118325
118326
118327
118328
118329
118330
118331
118332
118333
118334
118335
118336
118337
118338
118339
118340
118341
118342
118343
118344
118345
118346
118347
118348
118349
118350
118351
118352
118353
118354
118355
118356
118357
118358
118359
118360
118361
118362
118363
118364
118365
118366
118367
118368
118369
118370
118371
118372
118373
118374
118375
118376
118377
118378
118379
118380
118381
118382
118383
118384
118385
118386
118387
118388
118389
118390
118391
118392
118393
118394
118395
118396
118397
118398
118399
118400
118401
118402
118403
118404
118405
118406
118407
118408
118409
118410
118411
118412
118413
118414
118415
118416
118417
118418
118419
118420
118421
118422
118423
118424
118425
118426
118427
118428
118429
118430
118431
118432
118433
118434
118435
118436
118437
118438
118439
118440
118441
118442
118443
118444
118445
118446
118447
118448
118449
118450
118451
118452
118453
118454
118455
118456
118457
118458
118459
118460
118461
118462
118463
118464
118465
118466
118467
118468
118469
118470
118471
118472
118473
118474
118475
118476
118477
118478
118479
118480
118481
118482
118483
118484
118485
118486
118487
118488
118489
118490
118491
118492
118493
118494
118495
118496
118497
118498
118499
118500
118501
118502
118503
    *paPoslist = pPhrase->doclist.pList;
    *pnToken = pPhrase->nToken;
  }

  return res;
}

/*
** This function is a no-op if *pRc is other than SQLITE_OK when it is called.
** Otherwise, it advances the expression passed as the second argument to
** point to the next matching row in the database. Expressions iterate through
** matching rows in docid order. Ascending order if Fts3Cursor.bDesc is zero,
** or descending if it is non-zero.
**
** If an error occurs, *pRc is set to an SQLite error code. Otherwise, if
** successful, the following variables in pExpr are set:
**
**   Fts3Expr.bEof                (non-zero if EOF - there is no next row)
**   Fts3Expr.iDocid              (valid if bEof==0. The docid of the next row)
**
** If the expression is of type FTSQUERY_PHRASE, and the expression is not
** at EOF, then the following variables are populated with the position list
** for the phrase for the visited row:
**
**   FTs3Expr.pPhrase->doclist.nList        (length of pList in bytes)
**   FTs3Expr.pPhrase->doclist.pList        (pointer to position list)
**
** It says above that this function advances the expression to the next
** matching row. This is usually true, but there are the following exceptions:
**
**   1. Deferred tokens are not taken into account. If a phrase consists
**      entirely of deferred tokens, it is assumed to match every row in
**      the db. In this case the position-list is not populated at all. 
**
**      Or, if a phrase contains one or more deferred tokens and one or
**      more non-deferred tokens, then the expression is advanced to the 
**      next possible match, considering only non-deferred tokens. In other
**      words, if the phrase is "A B C", and "B" is deferred, the expression
**      is advanced to the next row that contains an instance of "A * C", 
**      where "*" may match any single token. The position list in this case
**      is populated as for "A * C" before returning.
**
**   2. NEAR is treated as AND. If the expression is "x NEAR y", it is 
**      advanced to point to the next row that matches "x AND y".
** 
** See fts3EvalTestDeferredAndNear() for details on testing if a row is
** really a match, taking into account deferred tokens and NEAR operators.
*/
static void fts3EvalNextRow(
  Fts3Cursor *pCsr,               /* FTS Cursor handle */
  Fts3Expr *pExpr,                /* Expr. to advance to next matching row */
  int *pRc                        /* IN/OUT: Error code */
){
  if( *pRc==SQLITE_OK ){
    int bDescDoclist = pCsr->bDesc;         /* Used by DOCID_CMP() macro */
    assert( pExpr->bEof==0 );
    pExpr->bStart = 1;

    switch( pExpr->eType ){
      case FTSQUERY_NEAR:
      case FTSQUERY_AND: {
        Fts3Expr *pLeft = pExpr->pLeft;
        Fts3Expr *pRight = pExpr->pRight;
        assert( !pLeft->bDeferred || !pRight->bDeferred );

        if( pLeft->bDeferred ){
          /* LHS is entirely deferred. So we assume it matches every row.
          ** Advance the RHS iterator to find the next row visited. */
          fts3EvalNextRow(pCsr, pRight, pRc);
          pExpr->iDocid = pRight->iDocid;
          pExpr->bEof = pRight->bEof;
        }else if( pRight->bDeferred ){
          /* RHS is entirely deferred. So we assume it matches every row.
          ** Advance the LHS iterator to find the next row visited. */
          fts3EvalNextRow(pCsr, pLeft, pRc);
          pExpr->iDocid = pLeft->iDocid;
          pExpr->bEof = pLeft->bEof;
        }else{
          /* Neither the RHS or LHS are deferred. */
          fts3EvalNextRow(pCsr, pLeft, pRc);
          fts3EvalNextRow(pCsr, pRight, pRc);
          while( !pLeft->bEof && !pRight->bEof && *pRc==SQLITE_OK ){
            sqlite3_int64 iDiff = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
            if( iDiff==0 ) break;
            if( iDiff<0 ){
              fts3EvalNextRow(pCsr, pLeft, pRc);
            }else{
              fts3EvalNextRow(pCsr, pRight, pRc);
            }
          }
          pExpr->iDocid = pLeft->iDocid;
          pExpr->bEof = (pLeft->bEof || pRight->bEof);
        }
        break;
      }
  
      case FTSQUERY_OR: {
        Fts3Expr *pLeft = pExpr->pLeft;
        Fts3Expr *pRight = pExpr->pRight;
        sqlite3_int64 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);

        assert( pLeft->bStart || pLeft->iDocid==pRight->iDocid );
        assert( pRight->bStart || pLeft->iDocid==pRight->iDocid );

        if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
          fts3EvalNextRow(pCsr, pLeft, pRc);
        }else if( pLeft->bEof || (pRight->bEof==0 && iCmp>0) ){
          fts3EvalNextRow(pCsr, pRight, pRc);
        }else{
          fts3EvalNextRow(pCsr, pLeft, pRc);
          fts3EvalNextRow(pCsr, pRight, pRc);
        }

        pExpr->bEof = (pLeft->bEof && pRight->bEof);
        iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
        if( pRight->bEof || (pLeft->bEof==0 &&  iCmp<0) ){
          pExpr->iDocid = pLeft->iDocid;
        }else{
          pExpr->iDocid = pRight->iDocid;
        }

        break;
      }

      case FTSQUERY_NOT: {
        Fts3Expr *pLeft = pExpr->pLeft;
        Fts3Expr *pRight = pExpr->pRight;

        if( pRight->bStart==0 ){
          fts3EvalNextRow(pCsr, pRight, pRc);
          assert( *pRc!=SQLITE_OK || pRight->bStart );
        }

        fts3EvalNextRow(pCsr, pLeft, pRc);
        if( pLeft->bEof==0 ){
          while( !*pRc 
              && !pRight->bEof 
              && DOCID_CMP(pLeft->iDocid, pRight->iDocid)>0 
          ){
            fts3EvalNextRow(pCsr, pRight, pRc);
          }
        }
        pExpr->iDocid = pLeft->iDocid;
        pExpr->bEof = pLeft->bEof;
        break;
      }

      default: {
        Fts3Phrase *pPhrase = pExpr->pPhrase;
        fts3EvalInvalidatePoslist(pPhrase);
        *pRc = fts3EvalPhraseNext(pCsr, pPhrase, &pExpr->bEof);
        pExpr->iDocid = pPhrase->doclist.iDocid;
        break;
      }
    }
  }
}

/*
** If *pRc is not SQLITE_OK, or if pExpr is not the root node of a NEAR
** cluster, then this function returns 1 immediately.
**
** Otherwise, it checks if the current row really does match the NEAR 
** expression, using the data currently stored in the position lists 
** (Fts3Expr->pPhrase.doclist.pList/nList) for each phrase in the expression. 
**
** If the current row is a match, the position list associated with each
** phrase in the NEAR expression is edited in place to contain only those
** phrase instances sufficiently close to their peers to satisfy all NEAR
** constraints. In this case it returns 1. If the NEAR expression does not 
** match the current row, 0 is returned. The position lists may or may not
** be edited if 0 is returned.
*/
static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
  int res = 1;

  /* The following block runs if pExpr is the root of a NEAR query.
  ** For example, the query:
  **
  **         "w" NEAR "x" NEAR "y" NEAR "z"







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







115803
115804
115805
115806
115807
115808
115809






































































































































































115810
115811
115812
115813
115814
115815
115816
    *paPoslist = pPhrase->doclist.pList;
    *pnToken = pPhrase->nToken;
  }

  return res;
}







































































































































































static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
  int res = 1;

  /* The following block runs if pExpr is the root of a NEAR query.
  ** For example, the query:
  **
  **         "w" NEAR "x" NEAR "y" NEAR "z"
118511
118512
118513
118514
118515
118516
118517
118518
118519
118520
118521
118522
118523
118524
118525
  **                     |        |
  **                +--NEAR--+   "y"
  **                |        |
  **               "w"      "x"
  **
  ** The right-hand child of a NEAR node is always a phrase. The 
  ** left-hand child may be either a phrase or a NEAR node. There are
  ** no exceptions to this - it's the way the parser in fts3_expr.c works.
  */
  if( *pRc==SQLITE_OK 
   && pExpr->eType==FTSQUERY_NEAR 
   && pExpr->bEof==0
   && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
  ){
    Fts3Expr *p; 







|







115824
115825
115826
115827
115828
115829
115830
115831
115832
115833
115834
115835
115836
115837
115838
  **                     |        |
  **                +--NEAR--+   "y"
  **                |        |
  **               "w"      "x"
  **
  ** The right-hand child of a NEAR node is always a phrase. The 
  ** left-hand child may be either a phrase or a NEAR node. There are
  ** no exceptions to this.
  */
  if( *pRc==SQLITE_OK 
   && pExpr->eType==FTSQUERY_NEAR 
   && pExpr->bEof==0
   && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
  ){
    Fts3Expr *p; 
118538
118539
118540
118541
118542
118543
118544
118545
118546
118547
118548
118549
118550
118551
118552
118553
118554
118555
118556
118557
118558
118559
118560
118561
118562
118563
118564
118565
118566
118567
118568
118569
118570
118571
118572
118573
118574
118575

118576

118577
118578
118579
118580





































































































118581
118582
118583
118584
118585
118586
118587
118588
118589
118590
118591
118592
118593
118594
118595
    }else{
      char *aPoslist = p->pPhrase->doclist.pList;
      int nToken = p->pPhrase->nToken;

      for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
        Fts3Phrase *pPhrase = p->pRight->pPhrase;
        int nNear = p->nNear;
        res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
      }
  
      aPoslist = pExpr->pRight->pPhrase->doclist.pList;
      nToken = pExpr->pRight->pPhrase->nToken;
      for(p=pExpr->pLeft; p && res; p=p->pLeft){
        int nNear = p->pParent->nNear;
        Fts3Phrase *pPhrase = (
            p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
        );
        res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
      }
    }

    sqlite3_free(aTmp);
  }

  return res;
}

/*
** This function is a helper function for fts3EvalTestDeferredAndNear().
** Assuming no error occurs or has occurred, It returns non-zero if the
** expression passed as the second argument matches the row that pCsr 
** currently points to, or zero if it does not.
**
** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
** If an error occurs during execution of this function, *pRc is set to 
** the appropriate SQLite error code. In this case the returned value is 
** undefined.
*/

static int fts3EvalTestExpr(

  Fts3Cursor *pCsr,               /* FTS cursor handle */
  Fts3Expr *pExpr,                /* Expr to test. May or may not be root. */
  int *pRc                        /* IN/OUT: Error code */
){





































































































  int bHit = 1;                   /* Return value */
  if( *pRc==SQLITE_OK ){
    switch( pExpr->eType ){
      case FTSQUERY_NEAR:
      case FTSQUERY_AND:
        bHit = (
            fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc)
         && fts3EvalTestExpr(pCsr, pExpr->pRight, pRc)
         && fts3EvalNearTest(pExpr, pRc)
        );

        /* If the NEAR expression does not match any rows, zero the doclist for 
        ** all phrases involved in the NEAR. This is because the snippet(),
        ** offsets() and matchinfo() functions are not supposed to recognize 
        ** any instances of phrases that are part of unmatched NEAR queries. 







|









|










|
|
|
|
<
<
<
<
|

>
|
>
|
|
|

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





|
|







115851
115852
115853
115854
115855
115856
115857
115858
115859
115860
115861
115862
115863
115864
115865
115866
115867
115868
115869
115870
115871
115872
115873
115874
115875
115876
115877
115878
115879
115880
115881
115882




115883
115884
115885
115886
115887
115888
115889
115890
115891
115892
115893
115894
115895
115896
115897
115898
115899
115900
115901
115902
115903
115904
115905
115906
115907
115908
115909
115910
115911
115912
115913
115914
115915
115916
115917
115918
115919
115920
115921
115922
115923
115924
115925
115926
115927
115928
115929
115930
115931
115932
115933
115934
115935
115936
115937
115938
115939
115940
115941
115942
115943
115944
115945
115946
115947
115948
115949
115950
115951
115952
115953
115954
115955
115956
115957
115958
115959
115960
115961
115962
115963
115964
115965
115966
115967
115968
115969
115970
115971
115972
115973
115974
115975
115976
115977
115978
115979
115980
115981
115982
115983
115984
115985
115986
115987
115988
115989
115990
115991
115992
115993
115994
115995
115996
115997
115998
115999
116000
116001
116002
116003
116004
116005
116006
116007
    }else{
      char *aPoslist = p->pPhrase->doclist.pList;
      int nToken = p->pPhrase->nToken;

      for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
        Fts3Phrase *pPhrase = p->pRight->pPhrase;
        int nNear = p->nNear;
        res = fts3EvalNearTrim2(nNear, aTmp, &aPoslist, &nToken, pPhrase);
      }
  
      aPoslist = pExpr->pRight->pPhrase->doclist.pList;
      nToken = pExpr->pRight->pPhrase->nToken;
      for(p=pExpr->pLeft; p && res; p=p->pLeft){
        int nNear = p->pParent->nNear;
        Fts3Phrase *pPhrase = (
            p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
        );
        res = fts3EvalNearTrim2(nNear, aTmp, &aPoslist, &nToken, pPhrase);
      }
    }

    sqlite3_free(aTmp);
  }

  return res;
}

/*
** This macro is used by the fts3EvalNext() function. The two arguments are
** 64-bit docid values. If the current query is "ORDER BY docid ASC", then
** the macro returns (i1 - i2). Or if it is "ORDER BY docid DESC", then
** it returns (i2 - i1). This allows the same code to be used for merging




** doclists in ascending or descending order.
*/
#define DOCID_CMP(i1, i2) ((pCsr->bDesc?-1:1) * (i1-i2))

static void fts3EvalNext(
  Fts3Cursor *pCsr, 
  Fts3Expr *pExpr, 
  int *pRc
){
  if( *pRc==SQLITE_OK ){
    assert( pExpr->bEof==0 );
    pExpr->bStart = 1;

    switch( pExpr->eType ){
      case FTSQUERY_NEAR:
      case FTSQUERY_AND: {
        Fts3Expr *pLeft = pExpr->pLeft;
        Fts3Expr *pRight = pExpr->pRight;
        assert( !pLeft->bDeferred || !pRight->bDeferred );
        if( pLeft->bDeferred ){
          fts3EvalNext(pCsr, pRight, pRc);
          pExpr->iDocid = pRight->iDocid;
          pExpr->bEof = pRight->bEof;
        }else if( pRight->bDeferred ){
          fts3EvalNext(pCsr, pLeft, pRc);
          pExpr->iDocid = pLeft->iDocid;
          pExpr->bEof = pLeft->bEof;
        }else{
          fts3EvalNext(pCsr, pLeft, pRc);
          fts3EvalNext(pCsr, pRight, pRc);

          while( !pLeft->bEof && !pRight->bEof && *pRc==SQLITE_OK ){
            sqlite3_int64 iDiff = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
            if( iDiff==0 ) break;
            if( iDiff<0 ){
              fts3EvalNext(pCsr, pLeft, pRc);
            }else{
              fts3EvalNext(pCsr, pRight, pRc);
            }
          }

          pExpr->iDocid = pLeft->iDocid;
          pExpr->bEof = (pLeft->bEof || pRight->bEof);
        }
        break;
      }
  
      case FTSQUERY_OR: {
        Fts3Expr *pLeft = pExpr->pLeft;
        Fts3Expr *pRight = pExpr->pRight;
        sqlite3_int64 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);

        assert( pLeft->bStart || pLeft->iDocid==pRight->iDocid );
        assert( pRight->bStart || pLeft->iDocid==pRight->iDocid );

        if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
          fts3EvalNext(pCsr, pLeft, pRc);
        }else if( pLeft->bEof || (pRight->bEof==0 && iCmp>0) ){
          fts3EvalNext(pCsr, pRight, pRc);
        }else{
          fts3EvalNext(pCsr, pLeft, pRc);
          fts3EvalNext(pCsr, pRight, pRc);
        }

        pExpr->bEof = (pLeft->bEof && pRight->bEof);
        iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
        if( pRight->bEof || (pLeft->bEof==0 &&  iCmp<0) ){
          pExpr->iDocid = pLeft->iDocid;
        }else{
          pExpr->iDocid = pRight->iDocid;
        }

        break;
      }

      case FTSQUERY_NOT: {
        Fts3Expr *pLeft = pExpr->pLeft;
        Fts3Expr *pRight = pExpr->pRight;

        if( pRight->bStart==0 ){
          fts3EvalNext(pCsr, pRight, pRc);
          assert( *pRc!=SQLITE_OK || pRight->bStart );
        }

        fts3EvalNext(pCsr, pLeft, pRc);
        if( pLeft->bEof==0 ){
          while( !*pRc 
              && !pRight->bEof 
              && DOCID_CMP(pLeft->iDocid, pRight->iDocid)>0 
          ){
            fts3EvalNext(pCsr, pRight, pRc);
          }
        }
        pExpr->iDocid = pLeft->iDocid;
        pExpr->bEof = pLeft->bEof;
        break;
      }

      default: {
        Fts3Phrase *pPhrase = pExpr->pPhrase;
        fts3EvalZeroPoslist(pPhrase);
        *pRc = fts3EvalPhraseNext(pCsr, pPhrase, &pExpr->bEof);
        pExpr->iDocid = pPhrase->doclist.iDocid;
        break;
      }
    }
  }
}

static int fts3EvalDeferredTest(Fts3Cursor *pCsr, Fts3Expr *pExpr, int *pRc){
  int bHit = 1;
  if( *pRc==SQLITE_OK ){
    switch( pExpr->eType ){
      case FTSQUERY_NEAR:
      case FTSQUERY_AND:
        bHit = (
            fts3EvalDeferredTest(pCsr, pExpr->pLeft, pRc)
         && fts3EvalDeferredTest(pCsr, pExpr->pRight, pRc)
         && fts3EvalNearTest(pExpr, pRc)
        );

        /* If the NEAR expression does not match any rows, zero the doclist for 
        ** all phrases involved in the NEAR. This is because the snippet(),
        ** offsets() and matchinfo() functions are not supposed to recognize 
        ** any instances of phrases that are part of unmatched NEAR queries. 
118607
118608
118609
118610
118611
118612
118613
118614
118615
118616
118617
118618
118619
118620
118621
118622
118623
118624
118625
118626
118627
118628
118629
118630
118631
118632
118633
118634
118635
118636
118637
118638
118639
118640
118641
118642
118643
118644
118645
118646
118647
118648
118649
118650
118651
118652
118653
118654
118655
118656
118657
118658
118659
118660
118661
118662
118663
118664
118665
118666
118667
118668
118669
118670
118671
118672
118673
118674
118675
118676
118677
118678
118679
118680
118681
118682
118683
118684
118685
118686
118687
118688
118689
118690
118691
118692
118693
118694
118695
118696
118697
118698
118699
118700
118701
118702
118703
118704
118705
118706
118707
118708
118709
118710
118711
118712
118713
118714
118715
118716
118717
118718
118719
118720
118721
118722
118723
118724
118725
118726
118727
118728
118729
118730
118731
118732
118733
118734
118735
118736
118737
118738
118739
118740
118741
118742
118743
118744
118745
118746
118747
118748
118749
118750
118751
118752
118753
118754
118755
118756
118757
118758
118759
118760
118761
        if( bHit==0 
         && pExpr->eType==FTSQUERY_NEAR 
         && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
        ){
          Fts3Expr *p;
          for(p=pExpr; p->pPhrase==0; p=p->pLeft){
            if( p->pRight->iDocid==pCsr->iPrevId ){
              fts3EvalInvalidatePoslist(p->pRight->pPhrase);
            }
          }
          if( p->iDocid==pCsr->iPrevId ){
            fts3EvalInvalidatePoslist(p->pPhrase);
          }
        }

        break;

      case FTSQUERY_OR: {
        int bHit1 = fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc);
        int bHit2 = fts3EvalTestExpr(pCsr, pExpr->pRight, pRc);
        bHit = bHit1 || bHit2;
        break;
      }

      case FTSQUERY_NOT:
        bHit = (
            fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc)
         && !fts3EvalTestExpr(pCsr, pExpr->pRight, pRc)
        );
        break;

      default: {
        if( pCsr->pDeferred 
         && (pExpr->iDocid==pCsr->iPrevId || pExpr->bDeferred)
        ){
          Fts3Phrase *pPhrase = pExpr->pPhrase;
          assert( pExpr->bDeferred || pPhrase->doclist.bFreeList==0 );
          if( pExpr->bDeferred ){
            fts3EvalInvalidatePoslist(pPhrase);
          }
          *pRc = fts3EvalDeferredPhrase(pCsr, pPhrase);
          bHit = (pPhrase->doclist.pList!=0);
          pExpr->iDocid = pCsr->iPrevId;
        }else{
          bHit = (pExpr->bEof==0 && pExpr->iDocid==pCsr->iPrevId);
        }
        break;
      }
    }
  }
  return bHit;
}

/*
** This function is called as the second part of each xNext operation when
** iterating through the results of a full-text query. At this point the
** cursor points to a row that matches the query expression, with the
** following caveats:
**
**   * Up until this point, "NEAR" operators in the expression have been
**     treated as "AND".
**
**   * Deferred tokens have not yet been considered.
**
** If *pRc is not SQLITE_OK when this function is called, it immediately
** returns 0. Otherwise, it tests whether or not after considering NEAR
** operators and deferred tokens the current row is still a match for the
** expression. It returns 1 if both of the following are true:
**
**   1. *pRc is SQLITE_OK when this function returns, and
**
**   2. After scanning the current FTS table row for the deferred tokens,
**      it is determined that the row does *not* match the query.
**
** Or, if no error occurs and it seems the current row does match the FTS
** query, return 0.
*/
static int fts3EvalTestDeferredAndNear(Fts3Cursor *pCsr, int *pRc){
  int rc = *pRc;
  int bMiss = 0;
  if( rc==SQLITE_OK ){

    /* If there are one or more deferred tokens, load the current row into
    ** memory and scan it to determine the position list for each deferred
    ** token. Then, see if this row is really a match, considering deferred
    ** tokens and NEAR operators (neither of which were taken into account
    ** earlier, by fts3EvalNextRow()). 
    */
    if( pCsr->pDeferred ){
      rc = fts3CursorSeek(0, pCsr);
      if( rc==SQLITE_OK ){
        rc = sqlite3Fts3CacheDeferredDoclists(pCsr);
      }
    }
    bMiss = (0==fts3EvalTestExpr(pCsr, pCsr->pExpr, &rc));

    /* Free the position-lists accumulated for each deferred token above. */
    sqlite3Fts3FreeDeferredDoclists(pCsr);
    *pRc = rc;
  }
  return (rc==SQLITE_OK && bMiss);
}

/*
** Advance to the next document that matches the FTS expression in
** Fts3Cursor.pExpr.
*/
static int fts3EvalNext(Fts3Cursor *pCsr){
  int rc = SQLITE_OK;             /* Return Code */
  Fts3Expr *pExpr = pCsr->pExpr;
  assert( pCsr->isEof==0 );
  if( pExpr==0 ){
    pCsr->isEof = 1;
  }else{
    do {
      if( pCsr->isRequireSeek==0 ){
        sqlite3_reset(pCsr->pStmt);
      }
      assert( sqlite3_data_count(pCsr->pStmt)==0 );
      fts3EvalNextRow(pCsr, pExpr, &rc);
      pCsr->isEof = pExpr->bEof;
      pCsr->isRequireSeek = 1;
      pCsr->isMatchinfoNeeded = 1;
      pCsr->iPrevId = pExpr->iDocid;
    }while( pCsr->isEof==0 && fts3EvalTestDeferredAndNear(pCsr, &rc) );
  }
  return rc;
}

/*
** Restart interation for expression pExpr so that the next call to
** fts3EvalNext() visits the first row. Do not allow incremental 
** loading or merging of phrase doclists for this iteration.
**
** If *pRc is other than SQLITE_OK when this function is called, it is
** a no-op. If an error occurs within this function, *pRc is set to an
** SQLite error code before returning.
*/
static void fts3EvalRestart(
  Fts3Cursor *pCsr,
  Fts3Expr *pExpr,
  int *pRc
){
  if( pExpr && *pRc==SQLITE_OK ){
    Fts3Phrase *pPhrase = pExpr->pPhrase;

    if( pPhrase ){
      fts3EvalInvalidatePoslist(pPhrase);
      if( pPhrase->bIncr ){
        assert( pPhrase->nToken==1 );
        assert( pPhrase->aToken[0].pSegcsr );
        sqlite3Fts3MsrIncrRestart(pPhrase->aToken[0].pSegcsr);
        *pRc = fts3EvalPhraseStart(pCsr, 0, pPhrase);
      }








|



|






|
|






|
|










|















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




|




|



<
<
<
<
<
<
<






|
<
<










|











|




|






|















|







116019
116020
116021
116022
116023
116024
116025
116026
116027
116028
116029
116030
116031
116032
116033
116034
116035
116036
116037
116038
116039
116040
116041
116042
116043
116044
116045
116046
116047
116048
116049
116050
116051
116052
116053
116054
116055
116056
116057
116058
116059
116060
116061
116062
116063
116064
116065
116066
116067
116068
116069
116070
116071
116072













116073
116074
116075
116076
116077
116078
116079
116080
116081
116082
116083
116084
116085
116086







116087
116088
116089
116090
116091
116092
116093


116094
116095
116096
116097
116098
116099
116100
116101
116102
116103
116104
116105
116106
116107
116108
116109
116110
116111
116112
116113
116114
116115
116116
116117
116118
116119
116120
116121
116122
116123
116124
116125
116126
116127
116128
116129
116130
116131
116132
116133
116134
116135
116136
116137
116138
116139
116140
116141
116142
116143
116144
116145
116146
116147
116148
116149
116150
116151
        if( bHit==0 
         && pExpr->eType==FTSQUERY_NEAR 
         && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
        ){
          Fts3Expr *p;
          for(p=pExpr; p->pPhrase==0; p=p->pLeft){
            if( p->pRight->iDocid==pCsr->iPrevId ){
              fts3EvalZeroPoslist(p->pRight->pPhrase);
            }
          }
          if( p->iDocid==pCsr->iPrevId ){
            fts3EvalZeroPoslist(p->pPhrase);
          }
        }

        break;

      case FTSQUERY_OR: {
        int bHit1 = fts3EvalDeferredTest(pCsr, pExpr->pLeft, pRc);
        int bHit2 = fts3EvalDeferredTest(pCsr, pExpr->pRight, pRc);
        bHit = bHit1 || bHit2;
        break;
      }

      case FTSQUERY_NOT:
        bHit = (
            fts3EvalDeferredTest(pCsr, pExpr->pLeft, pRc)
         && !fts3EvalDeferredTest(pCsr, pExpr->pRight, pRc)
        );
        break;

      default: {
        if( pCsr->pDeferred 
         && (pExpr->iDocid==pCsr->iPrevId || pExpr->bDeferred)
        ){
          Fts3Phrase *pPhrase = pExpr->pPhrase;
          assert( pExpr->bDeferred || pPhrase->doclist.bFreeList==0 );
          if( pExpr->bDeferred ){
            fts3EvalZeroPoslist(pPhrase);
          }
          *pRc = fts3EvalDeferredPhrase(pCsr, pPhrase);
          bHit = (pPhrase->doclist.pList!=0);
          pExpr->iDocid = pCsr->iPrevId;
        }else{
          bHit = (pExpr->bEof==0 && pExpr->iDocid==pCsr->iPrevId);
        }
        break;
      }
    }
  }
  return bHit;
}

/*













** Return 1 if both of the following are true:
**
**   1. *pRc is SQLITE_OK when this function returns, and
**
**   2. After scanning the current FTS table row for the deferred tokens,
**      it is determined that the row does not match the query.
**
** Or, if no error occurs and it seems the current row does match the FTS
** query, return 0.
*/
static int fts3EvalLoadDeferred(Fts3Cursor *pCsr, int *pRc){
  int rc = *pRc;
  int bMiss = 0;
  if( rc==SQLITE_OK ){







    if( pCsr->pDeferred ){
      rc = fts3CursorSeek(0, pCsr);
      if( rc==SQLITE_OK ){
        rc = sqlite3Fts3CacheDeferredDoclists(pCsr);
      }
    }
    bMiss = (0==fts3EvalDeferredTest(pCsr, pCsr->pExpr, &rc));


    sqlite3Fts3FreeDeferredDoclists(pCsr);
    *pRc = rc;
  }
  return (rc==SQLITE_OK && bMiss);
}

/*
** Advance to the next document that matches the FTS expression in
** Fts3Cursor.pExpr.
*/
SQLITE_PRIVATE int sqlite3Fts3EvalNext(Fts3Cursor *pCsr){
  int rc = SQLITE_OK;             /* Return Code */
  Fts3Expr *pExpr = pCsr->pExpr;
  assert( pCsr->isEof==0 );
  if( pExpr==0 ){
    pCsr->isEof = 1;
  }else{
    do {
      if( pCsr->isRequireSeek==0 ){
        sqlite3_reset(pCsr->pStmt);
      }
      assert( sqlite3_data_count(pCsr->pStmt)==0 );
      fts3EvalNext(pCsr, pExpr, &rc);
      pCsr->isEof = pExpr->bEof;
      pCsr->isRequireSeek = 1;
      pCsr->isMatchinfoNeeded = 1;
      pCsr->iPrevId = pExpr->iDocid;
    }while( pCsr->isEof==0 && fts3EvalLoadDeferred(pCsr, &rc) );
  }
  return rc;
}

/*
** Restart interation for expression pExpr so that the next call to
** sqlite3Fts3EvalNext() visits the first row. Do not allow incremental 
** loading or merging of phrase doclists for this iteration.
**
** If *pRc is other than SQLITE_OK when this function is called, it is
** a no-op. If an error occurs within this function, *pRc is set to an
** SQLite error code before returning.
*/
static void fts3EvalRestart(
  Fts3Cursor *pCsr,
  Fts3Expr *pExpr,
  int *pRc
){
  if( pExpr && *pRc==SQLITE_OK ){
    Fts3Phrase *pPhrase = pExpr->pPhrase;

    if( pPhrase ){
      fts3EvalZeroPoslist(pPhrase);
      if( pPhrase->bIncr ){
        assert( pPhrase->nToken==1 );
        assert( pPhrase->aToken[0].pSegcsr );
        sqlite3Fts3MsrIncrRestart(pPhrase->aToken[0].pSegcsr);
        *pRc = fts3EvalPhraseStart(pCsr, 0, pPhrase);
      }

118863
118864
118865
118866
118867
118868
118869
118870
118871
118872
118873
118874
118875
118876
118877
118878
118879
118880
118881
118882
118883
118884

      do {
        /* Ensure the %_content statement is reset. */
        if( pCsr->isRequireSeek==0 ) sqlite3_reset(pCsr->pStmt);
        assert( sqlite3_data_count(pCsr->pStmt)==0 );

        /* Advance to the next document */
        fts3EvalNextRow(pCsr, pRoot, &rc);
        pCsr->isEof = pRoot->bEof;
        pCsr->isRequireSeek = 1;
        pCsr->isMatchinfoNeeded = 1;
        pCsr->iPrevId = pRoot->iDocid;
      }while( pCsr->isEof==0 
           && pRoot->eType==FTSQUERY_NEAR 
           && fts3EvalTestDeferredAndNear(pCsr, &rc) 
      );

      if( rc==SQLITE_OK && pCsr->isEof==0 ){
        fts3EvalUpdateCounts(pRoot);
      }
    }








|






|







116253
116254
116255
116256
116257
116258
116259
116260
116261
116262
116263
116264
116265
116266
116267
116268
116269
116270
116271
116272
116273
116274

      do {
        /* Ensure the %_content statement is reset. */
        if( pCsr->isRequireSeek==0 ) sqlite3_reset(pCsr->pStmt);
        assert( sqlite3_data_count(pCsr->pStmt)==0 );

        /* Advance to the next document */
        fts3EvalNext(pCsr, pRoot, &rc);
        pCsr->isEof = pRoot->bEof;
        pCsr->isRequireSeek = 1;
        pCsr->isMatchinfoNeeded = 1;
        pCsr->iPrevId = pRoot->iDocid;
      }while( pCsr->isEof==0 
           && pRoot->eType==FTSQUERY_NEAR 
           && fts3EvalLoadDeferred(pCsr, &rc) 
      );

      if( rc==SQLITE_OK && pCsr->isEof==0 ){
        fts3EvalUpdateCounts(pRoot);
      }
    }

118892
118893
118894
118895
118896
118897
118898
118899
118900
118901
118902
118903
118904
118905
118906
118907
118908
118909
      ** order. For this reason, even though it seems more defensive, the 
      ** do loop can not be written:
      **
      **   do {...} while( pRoot->iDocid<iDocid && rc==SQLITE_OK );
      */
      fts3EvalRestart(pCsr, pRoot, &rc);
      do {
        fts3EvalNextRow(pCsr, pRoot, &rc);
        assert( pRoot->bEof==0 );
      }while( pRoot->iDocid!=iDocid && rc==SQLITE_OK );
      fts3EvalTestDeferredAndNear(pCsr, &rc);
    }
  }
  return rc;
}

/*
** This function is used by the matchinfo() module to query a phrase 







|


|







116282
116283
116284
116285
116286
116287
116288
116289
116290
116291
116292
116293
116294
116295
116296
116297
116298
116299
      ** order. For this reason, even though it seems more defensive, the 
      ** do loop can not be written:
      **
      **   do {...} while( pRoot->iDocid<iDocid && rc==SQLITE_OK );
      */
      fts3EvalRestart(pCsr, pRoot, &rc);
      do {
        fts3EvalNext(pCsr, pRoot, &rc);
        assert( pRoot->bEof==0 );
      }while( pRoot->iDocid!=iDocid && rc==SQLITE_OK );
      fts3EvalLoadDeferred(pCsr, &rc);
    }
  }
  return rc;
}

/*
** This function is used by the matchinfo() module to query a phrase 
119026
119027
119028
119029
119030
119031
119032
119033
119034
119035
119036
119037
119038
119039
119040
119041
119042
119043
119044
119045
119046
119047
119048
119049
119050
119051
119052
119053
119054
119055
119056
119057
119058
119059
119060
119061
119062
119063
119064
119065
119066
119067
119068
119069
119070
119071
119072
119073
119074
119075
119076
119077
119078
119079
119080
119081
119082
119083
**   * the contents of pPhrase->doclist, and
**   * any Fts3MultiSegReader objects held by phrase tokens.
*/
SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *pPhrase){
  if( pPhrase ){
    int i;
    sqlite3_free(pPhrase->doclist.aAll);
    fts3EvalInvalidatePoslist(pPhrase);
    memset(&pPhrase->doclist, 0, sizeof(Fts3Doclist));
    for(i=0; i<pPhrase->nToken; i++){
      fts3SegReaderCursorFree(pPhrase->aToken[i].pSegcsr);
      pPhrase->aToken[i].pSegcsr = 0;
    }
  }
}

#if !SQLITE_CORE
/*
** Initialize API pointer table, if required.
*/
SQLITE_API int sqlite3_extension_init(
  sqlite3 *db, 
  char **pzErrMsg,
  const sqlite3_api_routines *pApi
){
  SQLITE_EXTENSION_INIT2(pApi)
  return sqlite3Fts3Init(db);
}
#endif

#endif

/************** End of fts3.c ************************************************/
/************** Begin file fts3_aux.c ****************************************/
/*
** 2011 Jan 27
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)

/* #include <string.h> */
/* #include <assert.h> */

typedef struct Fts3auxTable Fts3auxTable;
typedef struct Fts3auxCursor Fts3auxCursor;

struct Fts3auxTable {
  sqlite3_vtab base;              /* Base class used by SQLite core */
  Fts3Table *pFts3Tab;







|








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



















<
<







116416
116417
116418
116419
116420
116421
116422
116423
116424
116425
116426
116427
116428
116429
116430
116431














116432
116433
116434
116435
116436
116437
116438
116439
116440
116441
116442
116443
116444
116445
116446
116447
116448
116449
116450


116451
116452
116453
116454
116455
116456
116457
**   * the contents of pPhrase->doclist, and
**   * any Fts3MultiSegReader objects held by phrase tokens.
*/
SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *pPhrase){
  if( pPhrase ){
    int i;
    sqlite3_free(pPhrase->doclist.aAll);
    fts3EvalZeroPoslist(pPhrase);
    memset(&pPhrase->doclist, 0, sizeof(Fts3Doclist));
    for(i=0; i<pPhrase->nToken; i++){
      fts3SegReaderCursorFree(pPhrase->aToken[i].pSegcsr);
      pPhrase->aToken[i].pSegcsr = 0;
    }
  }
}















#endif

/************** End of fts3.c ************************************************/
/************** Begin file fts3_aux.c ****************************************/
/*
** 2011 Jan 27
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)




typedef struct Fts3auxTable Fts3auxTable;
typedef struct Fts3auxCursor Fts3auxCursor;

struct Fts3auxTable {
  sqlite3_vtab base;              /* Base class used by SQLite core */
  Fts3Table *pFts3Tab;
119608
119609
119610
119611
119612
119613
119614
119615
119616
119617
119618
119619
119620
119621
119622
119623
#endif

/*
** Default span for NEAR operators.
*/
#define SQLITE_FTS3_DEFAULT_NEAR_PARAM 10

/* #include <string.h> */
/* #include <assert.h> */

/*
** isNot:
**   This variable is used by function getNextNode(). When getNextNode() is
**   called, it sets ParseContext.isNot to true if the 'next node' is a 
**   FTSQUERY_PHRASE with a unary "-" attached to it. i.e. "mysql" in the
**   FTS3 query "sqlite -mysql". Otherwise, ParseContext.isNot is set to







<
<







116982
116983
116984
116985
116986
116987
116988


116989
116990
116991
116992
116993
116994
116995
#endif

/*
** Default span for NEAR operators.
*/
#define SQLITE_FTS3_DEFAULT_NEAR_PARAM 10




/*
** isNot:
**   This variable is used by function getNextNode(). When getNextNode() is
**   called, it sets ParseContext.isNot to true if the 'next node' is a 
**   FTSQUERY_PHRASE with a unary "-" attached to it. i.e. "mysql" in the
**   FTS3 query "sqlite -mysql". Otherwise, ParseContext.isNot is set to
120311
120312
120313
120314
120315
120316
120317
120318
120319
120320
120321
120322
120323
120324
120325
/****************************************************************************
*****************************************************************************
** Everything after this point is just test code.
*/

#ifdef SQLITE_TEST

/* #include <stdio.h> */

/*
** Function to query the hash-table of tokenizers (see README.tokenizers).
*/
static int queryTestTokenizer(
  sqlite3 *db, 
  const char *zName,  







<







117683
117684
117685
117686
117687
117688
117689

117690
117691
117692
117693
117694
117695
117696
/****************************************************************************
*****************************************************************************
** Everything after this point is just test code.
*/

#ifdef SQLITE_TEST



/*
** Function to query the hash-table of tokenizers (see README.tokenizers).
*/
static int queryTestTokenizer(
  sqlite3 *db, 
  const char *zName,  
120522
120523
120524
120525
120526
120527
120528
120529
120530
120531
120532
120533
120534
120535
120536
120537
120538
**       (in which case SQLITE_CORE is not defined), or
**
**     * The FTS3 module is being built into the core of
**       SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)

/* #include <assert.h> */
/* #include <stdlib.h> */
/* #include <string.h> */


/*
** Malloc and Free functions
*/
static void *fts3HashMalloc(int n){
  void *p = sqlite3_malloc(n);







<
<
<







117893
117894
117895
117896
117897
117898
117899



117900
117901
117902
117903
117904
117905
117906
**       (in which case SQLITE_CORE is not defined), or
**
**     * The FTS3 module is being built into the core of
**       SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)






/*
** Malloc and Free functions
*/
static void *fts3HashMalloc(int n){
  void *p = sqlite3_malloc(n);
120905
120906
120907
120908
120909
120910
120911
120912
120913
120914
120915
120916
120917
120918
120919
120920
120921
120922
**       (in which case SQLITE_CORE is not defined), or
**
**     * The FTS3 module is being built into the core of
**       SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)

/* #include <assert.h> */
/* #include <stdlib.h> */
/* #include <stdio.h> */
/* #include <string.h> */


/*
** Class derived from sqlite3_tokenizer
*/
typedef struct porter_tokenizer {
  sqlite3_tokenizer base;      /* Base class */







<
<
<
<







118273
118274
118275
118276
118277
118278
118279




118280
118281
118282
118283
118284
118285
118286
**       (in which case SQLITE_CORE is not defined), or
**
**     * The FTS3 module is being built into the core of
**       SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)







/*
** Class derived from sqlite3_tokenizer
*/
typedef struct porter_tokenizer {
  sqlite3_tokenizer base;      /* Base class */
121550
121551
121552
121553
121554
121555
121556




121557
121558
121559
121560
121561
121562
121563
121564
121565
121566
121567
**
**     * The FTS3 module is being built as an extension
**       (in which case SQLITE_CORE is not defined), or
**
**     * The FTS3 module is being built into the core of
**       SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
*/




#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)

/* #include <assert.h> */
/* #include <string.h> */

/*
** Implementation of the SQL scalar function for accessing the underlying 
** hash table. This function may be called as follows:
**
**   SELECT <function-name>(<key-name>);
**   SELECT <function-name>(<key-name>, <pointer>);







>
>
>
>


<
<







118914
118915
118916
118917
118918
118919
118920
118921
118922
118923
118924
118925
118926


118927
118928
118929
118930
118931
118932
118933
**
**     * The FTS3 module is being built as an extension
**       (in which case SQLITE_CORE is not defined), or
**
**     * The FTS3 module is being built into the core of
**       SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
*/
#ifndef SQLITE_CORE
  SQLITE_EXTENSION_INIT1
#endif

#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)




/*
** Implementation of the SQL scalar function for accessing the underlying 
** hash table. This function may be called as follows:
**
**   SELECT <function-name>(<key-name>);
**   SELECT <function-name>(<key-name>, <pointer>);
121729
121730
121731
121732
121733
121734
121735
121736
121737
121738
121739
121740
121741
121742
121743
121744
  sqlite3_free(zCopy);
  return rc;
}


#ifdef SQLITE_TEST

/* #include <tcl.h> */
/* #include <string.h> */

/*
** Implementation of a special SQL scalar function for testing tokenizers 
** designed to be used in concert with the Tcl testing framework. This
** function must be called with two arguments:
**
**   SELECT <function-name>(<key-name>, <input-string>);







<
<







119095
119096
119097
119098
119099
119100
119101


119102
119103
119104
119105
119106
119107
119108
  sqlite3_free(zCopy);
  return rc;
}


#ifdef SQLITE_TEST




/*
** Implementation of a special SQL scalar function for testing tokenizers 
** designed to be used in concert with the Tcl testing framework. This
** function must be called with two arguments:
**
**   SELECT <function-name>(<key-name>, <input-string>);
122042
122043
122044
122045
122046
122047
122048
122049
122050
122051
122052
122053
122054
122055
122056
122057
122058
122059
**       (in which case SQLITE_CORE is not defined), or
**
**     * The FTS3 module is being built into the core of
**       SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)

/* #include <assert.h> */
/* #include <stdlib.h> */
/* #include <stdio.h> */
/* #include <string.h> */


typedef struct simple_tokenizer {
  sqlite3_tokenizer base;
  char delim[128];             /* flag ASCII delimiters */
} simple_tokenizer;








<
<
<
<







119406
119407
119408
119409
119410
119411
119412




119413
119414
119415
119416
119417
119418
119419
**       (in which case SQLITE_CORE is not defined), or
**
**     * The FTS3 module is being built into the core of
**       SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)







typedef struct simple_tokenizer {
  sqlite3_tokenizer base;
  char delim[128];             /* flag ASCII delimiters */
} simple_tokenizer;

122271
122272
122273
122274
122275
122276
122277
122278
122279
122280
122281
122282
122283
122284
122285
122286
122287
** tables. It also contains code to merge FTS3 b-tree segments. Some
** of the sub-routines used to merge segments are also used by the query 
** code in fts3.c.
*/

#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)

/* #include <string.h> */
/* #include <assert.h> */
/* #include <stdlib.h> */

/*
** When full-text index nodes are loaded from disk, the buffer that they
** are loaded into has the following number of bytes of padding at the end 
** of it. i.e. if a full-text index node is 900 bytes in size, then a buffer
** of 920 bytes is allocated for it.
**







<
<
<







119631
119632
119633
119634
119635
119636
119637



119638
119639
119640
119641
119642
119643
119644
** tables. It also contains code to merge FTS3 b-tree segments. Some
** of the sub-routines used to merge segments are also used by the query 
** code in fts3.c.
*/

#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)





/*
** When full-text index nodes are loaded from disk, the buffer that they
** are loaded into has the following number of bytes of padding at the end 
** of it. i.e. if a full-text index node is 900 bytes in size, then a buffer
** of 920 bytes is allocated for it.
**
125535
125536
125537
125538
125539
125540
125541
125542
125543
125544
125545
125546
125547
125548
125549
125550
**    May you share freely, never taking more than you give.
**
******************************************************************************
*/

#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)

/* #include <string.h> */
/* #include <assert.h> */

/*
** Characters that may appear in the second argument to matchinfo().
*/
#define FTS3_MATCHINFO_NPHRASE   'p'        /* 1 value */
#define FTS3_MATCHINFO_NCOL      'c'        /* 1 value */
#define FTS3_MATCHINFO_NDOC      'n'        /* 1 value */







<
<







122892
122893
122894
122895
122896
122897
122898


122899
122900
122901
122902
122903
122904
122905
**    May you share freely, never taking more than you give.
**
******************************************************************************
*/

#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)




/*
** Characters that may appear in the second argument to matchinfo().
*/
#define FTS3_MATCHINFO_NPHRASE   'p'        /* 1 value */
#define FTS3_MATCHINFO_NCOL      'c'        /* 1 value */
#define FTS3_MATCHINFO_NDOC      'n'        /* 1 value */
127124
127125
127126
127127
127128
127129
127130
127131
127132
127133
127134
127135
127136
127137
127138
127139
#endif

#ifndef SQLITE_CORE
  SQLITE_EXTENSION_INIT1
#else
#endif

/* #include <string.h> */
/* #include <assert.h> */

#ifndef SQLITE_AMALGAMATION
#include "sqlite3rtree.h"
typedef sqlite3_int64 i64;
typedef unsigned char u8;
typedef unsigned int u32;
#endif







<
<







124479
124480
124481
124482
124483
124484
124485


124486
124487
124488
124489
124490
124491
124492
#endif

#ifndef SQLITE_CORE
  SQLITE_EXTENSION_INIT1
#else
#endif




#ifndef SQLITE_AMALGAMATION
#include "sqlite3rtree.h"
typedef sqlite3_int64 i64;
typedef unsigned char u8;
typedef unsigned int u32;
#endif
130340
130341
130342
130343
130344
130345
130346
130347
130348
130349
130350
130351
130352
130353
130354

/* Include ICU headers */
#include <unicode/utypes.h>
#include <unicode/uregex.h>
#include <unicode/ustring.h>
#include <unicode/ucol.h>

/* #include <assert.h> */

#ifndef SQLITE_CORE
  SQLITE_EXTENSION_INIT1
#else
#endif

/*







<







127693
127694
127695
127696
127697
127698
127699

127700
127701
127702
127703
127704
127705
127706

/* Include ICU headers */
#include <unicode/utypes.h>
#include <unicode/uregex.h>
#include <unicode/ustring.h>
#include <unicode/ucol.h>



#ifndef SQLITE_CORE
  SQLITE_EXTENSION_INIT1
#else
#endif

/*
130820
130821
130822
130823
130824
130825
130826
130827
130828
130829
130830
130831
130832
130833
130834
130835
130836
130837
130838
130839
**
*************************************************************************
** This file implements a tokenizer for fts3 based on the ICU library.
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
#ifdef SQLITE_ENABLE_ICU

/* #include <assert.h> */
/* #include <string.h> */

#include <unicode/ubrk.h>
/* #include <unicode/ucol.h> */
/* #include <unicode/ustring.h> */
#include <unicode/utf16.h>

typedef struct IcuTokenizer IcuTokenizer;
typedef struct IcuCursor IcuCursor;

struct IcuTokenizer {
  sqlite3_tokenizer base;







<
<


<
<







128172
128173
128174
128175
128176
128177
128178


128179
128180


128181
128182
128183
128184
128185
128186
128187
**
*************************************************************************
** This file implements a tokenizer for fts3 based on the ICU library.
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
#ifdef SQLITE_ENABLE_ICU




#include <unicode/ubrk.h>


#include <unicode/utf16.h>

typedef struct IcuTokenizer IcuTokenizer;
typedef struct IcuCursor IcuCursor;

struct IcuTokenizer {
  sqlite3_tokenizer base;
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.8"
#define SQLITE_VERSION_NUMBER 3007008
#define SQLITE_SOURCE_ID      "2011-09-19 14:49:19 3e0da808d2f5b4d12046e05980ca04578f581177"

/*
** 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.7.1"
#define SQLITE_VERSION_NUMBER 3007007
#define SQLITE_SOURCE_ID      "2011-06-28 17:39:05 af0d91adf497f5f36ec3813f04235a6e195a605f"

/*
** 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
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
** when the database connection has [PRAGMA synchronous] set to OFF.)^
** Some specialized VFSes need this signal in order to operate correctly
** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most 
** VFSes do not need this signal and should silently ignore this opcode.
** Applications should not call [sqlite3_file_control()] with this
** opcode as doing so may disrupt the operation of the specialized VFSes
** that do require it.  
**
** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
** retry counts and intervals for certain disk I/O operations for the
** windows [VFS] in order to work to provide robustness against
** anti-virus programs.  By default, the windows VFS will retry file read,
** file write, and file delete opertions up to 10 times, with a delay
** of 25 milliseconds before the first retry and with the delay increasing
** by an additional 25 milliseconds with each subsequent retry.  This
** opcode allows those to values (10 retries and 25 milliseconds of delay)
** to be adjusted.  The values are changed for all database connections
** within the same process.  The argument is a pointer to an array of two
** integers where the first integer i the new retry count and the second
** integer is the delay.  If either integer is negative, then the setting
** is not changed but instead the prior value of that setting is written
** into the array entry, allowing the current retry settings to be
** interrogated.  The zDbName parameter is ignored.
**
** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the
** persistent [WAL | Write AHead Log] setting.  By default, the auxiliary
** write ahead log and shared memory files used for transaction control
** are automatically deleted when the latest connection to the database
** closes.  Setting persistent WAL mode causes those files to persist after
** close.  Persisting the files is useful when other processes that do not
** have write permission on the directory containing the database file want
** to read the database file, as the WAL and shared memory files must exist
** in order for the database to be readable.  The fourth parameter to
** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
** That integer is 0 to disable persistent WAL mode or 1 to enable persistent
** WAL mode.  If the integer is -1, then it is overwritten with the current
** WAL persistence setting.
** 
*/
#define SQLITE_FCNTL_LOCKSTATE        1
#define SQLITE_GET_LOCKPROXYFILE      2
#define SQLITE_SET_LOCKPROXYFILE      3
#define SQLITE_LAST_ERRNO             4
#define SQLITE_FCNTL_SIZE_HINT        5
#define SQLITE_FCNTL_CHUNK_SIZE       6
#define SQLITE_FCNTL_FILE_POINTER     7
#define SQLITE_FCNTL_SYNC_OMITTED     8
#define SQLITE_FCNTL_WIN32_AV_RETRY   9
#define SQLITE_FCNTL_PERSIST_WAL     10

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







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









|
<







737
738
739
740
741
742
743































744
745
746
747
748
749
750
751
752
753

754
755
756
757
758
759
760
** when the database connection has [PRAGMA synchronous] set to OFF.)^
** Some specialized VFSes need this signal in order to operate correctly
** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most 
** VFSes do not need this signal and should silently ignore this opcode.
** Applications should not call [sqlite3_file_control()] with this
** opcode as doing so may disrupt the operation of the specialized VFSes
** that do require it.  































*/
#define SQLITE_FCNTL_LOCKSTATE        1
#define SQLITE_GET_LOCKPROXYFILE      2
#define SQLITE_SET_LOCKPROXYFILE      3
#define SQLITE_LAST_ERRNO             4
#define SQLITE_FCNTL_SIZE_HINT        5
#define SQLITE_FCNTL_CHUNK_SIZE       6
#define SQLITE_FCNTL_FILE_POINTER     7
#define SQLITE_FCNTL_SYNC_OMITTED     8



/*
** CAPI3REF: Mutex Handle
**
** The mutex module within SQLite defines [sqlite3_mutex] to be an
** abstract type for a mutex object.  The SQLite core never looks
** at the internal representation of an [sqlite3_mutex].  It only
1206
1207
1208
1209
1210
1211
1212
1213
1214



1215
1216



1217
1218
1219
1220
1221
1222
1223
** and that this object is only useful to a tiny minority of applications
** with specialized memory allocation requirements.  This object is
** also used during testing of SQLite in order to specify an alternative
** memory allocator that simulates memory out-of-memory conditions in
** order to verify that SQLite recovers gracefully from such
** conditions.
**
** The xMalloc, xRealloc, and xFree methods must work like the
** malloc(), realloc() and free() functions from the standard C library.



** ^SQLite guarantees that the second argument to
** xRealloc is always a value returned by a prior call to xRoundup.



**
** xSize should return the allocated size of a memory allocation
** previously obtained from xMalloc or xRealloc.  The allocated size
** is always at least as big as the requested size but may be larger.
**
** The xRoundup method returns what would be the allocated size of
** a memory allocation given a particular requested size.  Most memory







|
|
>
>
>
|

>
>
>







1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
** and that this object is only useful to a tiny minority of applications
** with specialized memory allocation requirements.  This object is
** also used during testing of SQLite in order to specify an alternative
** memory allocator that simulates memory out-of-memory conditions in
** order to verify that SQLite recovers gracefully from such
** conditions.
**
** The xMalloc and xFree methods must work like the
** malloc() and free() functions from the standard C library.
** The xRealloc method must work like realloc() from the standard C library
** with the exception that if the second argument to xRealloc is zero,
** xRealloc must be a no-op - it must not perform any allocation or
** deallocation.  ^SQLite guarantees that the second argument to
** xRealloc is always a value returned by a prior call to xRoundup.
** And so in cases where xRoundup always returns a positive number,
** xRealloc can perform exactly as the standard library realloc() and
** still be in compliance with this specification.
**
** xSize should return the allocated size of a memory allocation
** previously obtained from xMalloc or xRealloc.  The allocated size
** is always at least as big as the requested size but may be larger.
**
** The xRoundup method returns what would be the allocated size of
** a memory allocation given a particular requested size.  Most memory
Changes to SQLite.Interop/src/core/sqlite3ext.h.
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
  const char *(*sourceid)(void);
  int (*stmt_status)(sqlite3_stmt*,int,int);
  int (*strnicmp)(const char*,const char*,int);
  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







<
<
<







208
209
210
211
212
213
214



215
216
217
218
219
220
221
  const char *(*sourceid)(void);
  int (*stmt_status)(sqlite3_stmt*,int,int);
  int (*strnicmp)(const char*,const char*,int);
  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*);



};

/*
** 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
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
#define sqlite3_sourceid               sqlite3_api->sourceid
#define sqlite3_stmt_status            sqlite3_api->stmt_status
#define sqlite3_strnicmp               sqlite3_api->strnicmp
#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_ */







<
<
<






408
409
410
411
412
413
414



415
416
417
418
419
420
#define sqlite3_sourceid               sqlite3_api->sourceid
#define sqlite3_stmt_status            sqlite3_api->stmt_status
#define sqlite3_strnicmp               sqlite3_api->strnicmp
#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



#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/crypt.c.
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
    //db->aDb[0].xFreeAux = DestroyCryptBlock;
  }
  else // Change the writekey for an already-encrypted database
  {
    pBlock->hWriteKey = hKey;
  }

  sqlite3_mutex_enter(db->mutex);

  // Start a transaction
  rc = sqlite3BtreeBeginTrans(pbt, 1);

  if (!rc)
  {
    // Rewrite all the pages in the database using the new encryption key
    Pgno nPage;







<
<







335
336
337
338
339
340
341


342
343
344
345
346
347
348
    //db->aDb[0].xFreeAux = DestroyCryptBlock;
  }
  else // Change the writekey for an already-encrypted database
  {
    pBlock->hWriteKey = hKey;
  }



  // Start a transaction
  rc = sqlite3BtreeBeginTrans(pbt, 1);

  if (!rc)
  {
    // Rewrite all the pages in the database using the new encryption key
    Pgno nPage;
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
  // If the readkey and writekey are both empty, there's no need for a codec on this
  // pager anymore.  Destroy the crypt block and remove the codec from the pager.
  if (!pBlock->hReadKey && !pBlock->hWriteKey)
  {
    sqlite3PagerSetCodec(p, NULL, NULL, NULL, NULL);
  }

  sqlite3_mutex_leave(db->mutex);

  return rc;
}

#endif // SQLITE_HAS_CODEC

#endif // SQLITE_OMIT_DISKIO







<
<






402
403
404
405
406
407
408


409
410
411
412
413
414
  // If the readkey and writekey are both empty, there's no need for a codec on this
  // pager anymore.  Destroy the crypt block and remove the codec from the pager.
  if (!pBlock->hReadKey && !pBlock->hWriteKey)
  {
    sqlite3PagerSetCodec(p, NULL, NULL, NULL, NULL);
  }



  return rc;
}

#endif // SQLITE_HAS_CODEC

#endif // SQLITE_OMIT_DISKIO
Changes to SQLite.Interop/src/win/interop.c.
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

// Additional open flags, we use this one privately
//#define SQLITE_OPEN_SHAREDCACHE      0x01000000

typedef void (*SQLITEUSERFUNC)(sqlite3_context *, int, sqlite3_value **);
typedef void (*SQLITEFUNCFINAL)(sqlite3_context *);

SQLITE_PRIVATE void * sqlite3DbMallocZero_interop(sqlite3 *db, int n)
{
  void *p;
  if (db) {
    sqlite3_mutex_enter(db->mutex);
  }
  p = sqlite3DbMallocZero(db,n);
  if (db) {
    sqlite3_mutex_leave(db->mutex);
  }
  return p;
}

SQLITE_PRIVATE void sqlite3DbFree_interop(sqlite3 *db, void *p)
{
  if (db) {
    sqlite3_mutex_enter(db->mutex);
  }
  if (p) {
    sqlite3MemdebugSetType(p, MEMTYPE_DB|MEMTYPE_HEAP);
  }
  sqlite3DbFree(db,p);
  if (db) {
    sqlite3_mutex_leave(db->mutex);
  }
}

/*
    The goal of this version of close is different than that of sqlite3_close(), and is designed to lend itself better to .NET's non-deterministic finalizers and
    the GC thread.  SQLite will not close a database if statements are open on it -- but for our purposes, we'd rather finalize all active statements
    and forcibly close the database.  The reason is simple -- a lot of people don't Dispose() of their objects correctly and let the garbage collector
    do it.  This leads to unexpected behavior when a user thinks they've closed a database, but it's still open because not all the statements have
    hit the GC yet.

    So, here we have a problem ... .NET has a pointer to any number of sqlite3_stmt objects.  We can't call sqlite3_finalize() on these because
    their memory is freed and can be used for something else.  The GC thread could potentially try and call finalize again on the statement after
    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;
  
  ret = sqlite3_close(db);

  if (ret == SQLITE_BUSY && db->pVdbe)
  {
    while (db->pVdbe)
    {
      // Make a copy of the first prepared statement
      Vdbe *p = (Vdbe *)sqlite3DbMallocZero_interop(db, sizeof(Vdbe));
      Vdbe *po = db->pVdbe;

      if (!p) 
      {
        ret = SQLITE_NOMEM;
        break;
      }







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













|










|







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

// Additional open flags, we use this one privately
//#define SQLITE_OPEN_SHAREDCACHE      0x01000000

typedef void (*SQLITEUSERFUNC)(sqlite3_context *, int, sqlite3_value **);
typedef void (*SQLITEFUNCFINAL)(sqlite3_context *);




























/*
    The goal of this version of close is different than that of sqlite3_close(), and is designed to lend itself better to .NET's non-deterministic finalizers and
    the GC thread.  SQLite will not close a database if statements are open on it -- but for our purposes, we'd rather finalize all active statements
    and forcibly close the database.  The reason is simple -- a lot of people don't Dispose() of their objects correctly and let the garbage collector
    do it.  This leads to unexpected behavior when a user thinks they've closed a database, but it's still open because not all the statements have
    hit the GC yet.

    So, here we have a problem ... .NET has a pointer to any number of sqlite3_stmt objects.  We can't call sqlite3_finalize() on these because
    their memory is freed and can be used for something else.  The GC thread could potentially try and call finalize again on the statement after
    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.
*/
__declspec(dllexport) int WINAPI sqlite3_close_interop(sqlite3 *db)
{
  int ret;
  
  ret = sqlite3_close(db);

  if (ret == SQLITE_BUSY && db->pVdbe)
  {
    while (db->pVdbe)
    {
      // Make a copy of the first prepared statement
      Vdbe *p = (Vdbe *)sqlite3_malloc(sizeof(Vdbe));
      Vdbe *po = db->pVdbe;

      if (!p) 
      {
        ret = SQLITE_NOMEM;
        break;
      }
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
    }
    ret = sqlite3_close(db);
  }

  return ret;
}

SQLITE_API int WINAPI sqlite3_open_interop(const char*filename, int flags, sqlite3 **ppdb)
{
  int ret;
  //int sharedcache = ((flags & SQLITE_OPEN_SHAREDCACHE) != 0);
  //flags &= ~SQLITE_OPEN_SHAREDCACHE;

  //sqlite3_enable_shared_cache(sharedcache);
  ret = sqlite3_open_v2(filename, ppdb, flags, NULL);
  //sqlite3_enable_shared_cache(0);

  if (ret == 0)
    RegisterExtensionFunctions(*ppdb);

  return ret;
}

SQLITE_API int WINAPI sqlite3_open16_interop(const char *filename, int flags, sqlite3 **ppdb)
{
  int ret = sqlite3_open_interop(filename, flags, ppdb);
  if (!ret)
  {
    if(!DbHasProperty(*ppdb, 0, DB_SchemaLoaded))
      ENC(*ppdb) = SQLITE_UTF16NATIVE;
  }
  return ret;
}

SQLITE_API const char * WINAPI sqlite3_errmsg_interop(sqlite3 *db, int *plen)
{
  const char *pval = sqlite3_errmsg(db);
  *plen = (pval != 0) ? strlen(pval) : 0;
  return pval;
}

SQLITE_API int WINAPI sqlite3_prepare_interop(sqlite3 *db, const char *sql, int nbytes, sqlite3_stmt **ppstmt, const char **pztail, int *plen)
{
  int n;

  n = sqlite3_prepare(db, sql, nbytes, ppstmt, pztail);
  *plen = (*pztail != 0) ? strlen(*pztail) : 0;

  return n;
}

SQLITE_API int WINAPI sqlite3_prepare16_interop(sqlite3 *db, const void *sql, int nchars, sqlite3_stmt **ppstmt, const void **pztail, int *plen)
{
  int n;

  n = sqlite3_prepare16(db, sql, nchars * sizeof(wchar_t), ppstmt, pztail);
  *plen = (*pztail != 0) ? wcslen((wchar_t *)*pztail) * sizeof(wchar_t) : 0;

  return n;
}

SQLITE_API int WINAPI sqlite3_bind_double_interop(sqlite3_stmt *stmt, int iCol, double *val)
{
	return sqlite3_bind_double(stmt,iCol,*val);
}

SQLITE_API int WINAPI sqlite3_bind_int64_interop(sqlite3_stmt *stmt, int iCol, sqlite_int64 *val)
{
	return sqlite3_bind_int64(stmt,iCol,*val);
}

SQLITE_API const char * WINAPI sqlite3_bind_parameter_name_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
  const char *pval = sqlite3_bind_parameter_name(stmt, iCol);
  *plen = (pval != 0) ? strlen(pval) : 0;
  return pval;
}

SQLITE_API const char * WINAPI sqlite3_column_name_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
  const char *pval = sqlite3_column_name(stmt, iCol);
  *plen = (pval != 0) ? strlen(pval) : 0;
  return pval;
}

SQLITE_API const void * WINAPI sqlite3_column_name16_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
  const void *pval = sqlite3_column_name16(stmt, iCol);
  *plen = (pval != 0) ? wcslen((wchar_t *)pval) * sizeof(wchar_t) : 0;
  return pval;
}

SQLITE_API const char * WINAPI sqlite3_column_decltype_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
  const char *pval = sqlite3_column_decltype(stmt, iCol);
  *plen = (pval != 0) ? strlen(pval) : 0;
  return pval;
}

SQLITE_API const void * WINAPI sqlite3_column_decltype16_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
  const void *pval = sqlite3_column_decltype16(stmt, iCol);
  *plen = (pval != 0) ? wcslen((wchar_t *)pval) * sizeof(wchar_t) : 0;
  return pval;
}

SQLITE_API void WINAPI sqlite3_column_double_interop(sqlite3_stmt *stmt, int iCol, double *val)
{
	*val = sqlite3_column_double(stmt,iCol);
}

SQLITE_API void WINAPI sqlite3_column_int64_interop(sqlite3_stmt *stmt, int iCol, sqlite_int64 *val)
{
	*val = sqlite3_column_int64(stmt,iCol);
}

SQLITE_API const unsigned char * WINAPI sqlite3_column_text_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
  const unsigned char *pval = sqlite3_column_text(stmt, iCol);
  *plen = (pval != 0) ? strlen((char *)pval) : 0;
  return pval;
}

SQLITE_API const void * WINAPI sqlite3_column_text16_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
  const void *pval = sqlite3_column_text16(stmt, iCol);
  *plen = (pval != 0) ? wcslen((wchar_t *)pval) * sizeof(wchar_t): 0;
  return pval;
}

SQLITE_API int WINAPI sqlite3_finalize_interop(sqlite3_stmt *stmt)
{
  Vdbe *p;
  sqlite3 *db;
  int ret;

  p = (Vdbe *)stmt;
  if (p && p->magic == VDBE_MAGIC_DEAD)
  {
    db = p->db;
    if (db == NULL)
    {
      sqlite3DbFree_interop(db, p);
      ret = SQLITE_OK;
    }
  }
  else
    ret = sqlite3_finalize(stmt);

  return ret;
}

SQLITE_API int WINAPI sqlite3_reset_interop(sqlite3_stmt *stmt)
{
  int ret;

  if (((Vdbe *)stmt)->magic == VDBE_MAGIC_DEAD) return SQLITE_SCHEMA;
  ret = sqlite3_reset(stmt);
  return ret;
}

SQLITE_API int WINAPI sqlite3_create_function_interop(sqlite3 *psql, const char *zFunctionName, int nArg, int eTextRep, void *pvUser, SQLITEUSERFUNC func, SQLITEUSERFUNC funcstep, SQLITEFUNCFINAL funcfinal, int needCollSeq)
{
  int n;

  if (eTextRep == SQLITE_UTF16)
    eTextRep = SQLITE_UTF16NATIVE;

  n = sqlite3_create_function(psql, zFunctionName, nArg, eTextRep, 0, func, funcstep, funcfinal);







|















|










|






|









|









|




|




|






|






|






|






|






|




|




|






|






|











|









|








|







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
    }
    ret = sqlite3_close(db);
  }

  return ret;
}

__declspec(dllexport) int WINAPI sqlite3_open_interop(const char*filename, int flags, sqlite3 **ppdb)
{
  int ret;
  //int sharedcache = ((flags & SQLITE_OPEN_SHAREDCACHE) != 0);
  //flags &= ~SQLITE_OPEN_SHAREDCACHE;

  //sqlite3_enable_shared_cache(sharedcache);
  ret = sqlite3_open_v2(filename, ppdb, flags, NULL);
  //sqlite3_enable_shared_cache(0);

  if (ret == 0)
    RegisterExtensionFunctions(*ppdb);

  return ret;
}

__declspec(dllexport) int WINAPI sqlite3_open16_interop(const char *filename, int flags, sqlite3 **ppdb)
{
  int ret = sqlite3_open_interop(filename, flags, ppdb);
  if (!ret)
  {
    if(!DbHasProperty(*ppdb, 0, DB_SchemaLoaded))
      ENC(*ppdb) = SQLITE_UTF16NATIVE;
  }
  return ret;
}

__declspec(dllexport) const char * WINAPI sqlite3_errmsg_interop(sqlite3 *db, int *plen)
{
  const char *pval = sqlite3_errmsg(db);
  *plen = (pval != 0) ? strlen(pval) : 0;
  return pval;
}

__declspec(dllexport) int WINAPI sqlite3_prepare_interop(sqlite3 *db, const char *sql, int nbytes, sqlite3_stmt **ppstmt, const char **pztail, int *plen)
{
  int n;

  n = sqlite3_prepare(db, sql, nbytes, ppstmt, pztail);
  *plen = (*pztail != 0) ? strlen(*pztail) : 0;

  return n;
}

__declspec(dllexport) int WINAPI sqlite3_prepare16_interop(sqlite3 *db, const void *sql, int nchars, sqlite3_stmt **ppstmt, const void **pztail, int *plen)
{
  int n;

  n = sqlite3_prepare16(db, sql, nchars * sizeof(wchar_t), ppstmt, pztail);
  *plen = (*pztail != 0) ? wcslen((wchar_t *)*pztail) * sizeof(wchar_t) : 0;

  return n;
}

__declspec(dllexport) int WINAPI sqlite3_bind_double_interop(sqlite3_stmt *stmt, int iCol, double *val)
{
	return sqlite3_bind_double(stmt,iCol,*val);
}

__declspec(dllexport) int WINAPI sqlite3_bind_int64_interop(sqlite3_stmt *stmt, int iCol, sqlite_int64 *val)
{
	return sqlite3_bind_int64(stmt,iCol,*val);
}

__declspec(dllexport) const char * WINAPI sqlite3_bind_parameter_name_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
  const char *pval = sqlite3_bind_parameter_name(stmt, iCol);
  *plen = (pval != 0) ? strlen(pval) : 0;
  return pval;
}

__declspec(dllexport) const char * WINAPI sqlite3_column_name_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
  const char *pval = sqlite3_column_name(stmt, iCol);
  *plen = (pval != 0) ? strlen(pval) : 0;
  return pval;
}

__declspec(dllexport) const void * WINAPI sqlite3_column_name16_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
  const void *pval = sqlite3_column_name16(stmt, iCol);
  *plen = (pval != 0) ? wcslen((wchar_t *)pval) * sizeof(wchar_t) : 0;
  return pval;
}

__declspec(dllexport) const char * WINAPI sqlite3_column_decltype_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
  const char *pval = sqlite3_column_decltype(stmt, iCol);
  *plen = (pval != 0) ? strlen(pval) : 0;
  return pval;
}

__declspec(dllexport) const void * WINAPI sqlite3_column_decltype16_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
  const void *pval = sqlite3_column_decltype16(stmt, iCol);
  *plen = (pval != 0) ? wcslen((wchar_t *)pval) * sizeof(wchar_t) : 0;
  return pval;
}

__declspec(dllexport) void WINAPI sqlite3_column_double_interop(sqlite3_stmt *stmt, int iCol, double *val)
{
	*val = sqlite3_column_double(stmt,iCol);
}

__declspec(dllexport) void WINAPI sqlite3_column_int64_interop(sqlite3_stmt *stmt, int iCol, sqlite_int64 *val)
{
	*val = sqlite3_column_int64(stmt,iCol);
}

__declspec(dllexport) const unsigned char * WINAPI sqlite3_column_text_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
  const unsigned char *pval = sqlite3_column_text(stmt, iCol);
  *plen = (pval != 0) ? strlen((char *)pval) : 0;
  return pval;
}

__declspec(dllexport) const void * WINAPI sqlite3_column_text16_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
  const void *pval = sqlite3_column_text16(stmt, iCol);
  *plen = (pval != 0) ? wcslen((wchar_t *)pval) * sizeof(wchar_t): 0;
  return pval;
}

__declspec(dllexport) int WINAPI sqlite3_finalize_interop(sqlite3_stmt *stmt)
{
  Vdbe *p;
  sqlite3 *db;
  int ret;

  p = (Vdbe *)stmt;
  if (p && p->magic == VDBE_MAGIC_DEAD)
  {
    db = p->db;
    if (db == NULL)
    {
      sqlite3_free(p);
      ret = SQLITE_OK;
    }
  }
  else
    ret = sqlite3_finalize(stmt);

  return ret;
}

__declspec(dllexport) int WINAPI sqlite3_reset_interop(sqlite3_stmt *stmt)
{
  int ret;

  if (((Vdbe *)stmt)->magic == VDBE_MAGIC_DEAD) return SQLITE_SCHEMA;
  ret = sqlite3_reset(stmt);
  return ret;
}

__declspec(dllexport) int WINAPI sqlite3_create_function_interop(sqlite3 *psql, const char *zFunctionName, int nArg, int eTextRep, void *pvUser, SQLITEUSERFUNC func, SQLITEUSERFUNC funcstep, SQLITEFUNCFINAL funcfinal, int needCollSeq)
{
  int n;

  if (eTextRep == SQLITE_UTF16)
    eTextRep = SQLITE_UTF16NATIVE;

  n = sqlite3_create_function(psql, zFunctionName, nArg, eTextRep, 0, func, funcstep, funcfinal);
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
      }
    }
  }

  return n;
}

SQLITE_API void WINAPI sqlite3_value_double_interop(sqlite3_value *pval, double *val)
{
  *val = sqlite3_value_double(pval);
}

SQLITE_API void WINAPI sqlite3_value_int64_interop(sqlite3_value *pval, sqlite_int64 *val)
{
  *val = sqlite3_value_int64(pval);
}

SQLITE_API const unsigned char * WINAPI sqlite3_value_text_interop(sqlite3_value *val, int *plen)
{
  const unsigned char *pval = sqlite3_value_text(val);
  *plen = (pval != 0) ? strlen((char *)pval) : 0;
  return pval;
}

SQLITE_API const void * WINAPI sqlite3_value_text16_interop(sqlite3_value *val, int *plen)
{
  const void *pval = sqlite3_value_text16(val);
  *plen = (pval != 0) ? wcslen((wchar_t *)pval) * sizeof(wchar_t) : 0;
  return pval;
}

SQLITE_API void WINAPI sqlite3_result_double_interop(sqlite3_context *pctx, double *val)
{
  sqlite3_result_double(pctx, *val);
}

SQLITE_API void WINAPI sqlite3_result_int64_interop(sqlite3_context *pctx, sqlite_int64 *val)
{
  sqlite3_result_int64(pctx, *val);
}

SQLITE_API int WINAPI sqlite3_context_collcompare(sqlite3_context *ctx, const void *p1, int p1len, const void *p2, int p2len)
{
  if ((ctx->pFunc->flags & SQLITE_FUNC_NEEDCOLL) == 0) return 2;
  return ctx->pColl->xCmp(ctx->pColl->pUser, p1len, p1, p2len, p2);
}

SQLITE_API const char * WINAPI sqlite3_context_collseq(sqlite3_context *ctx, int *ptype, int *enc, int *plen)
{
  CollSeq *pColl = ctx->pColl;
  *ptype = 0;
  *plen = 0;
  *enc = 0;

  if ((ctx->pFunc->flags & SQLITE_FUNC_NEEDCOLL) == 0) return NULL;

  if (pColl)
  {
    *enc = pColl->enc;
    *ptype = pColl->type;
    *plen = (pColl->zName != 0) ? strlen(pColl->zName) : 0;

    return pColl->zName;
  }
  return NULL;
}

SQLITE_API const char * WINAPI sqlite3_column_database_name_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
  const char *pval = sqlite3_column_database_name(stmt, iCol);
  *plen = (pval != 0) ? strlen(pval) : 0;
  return pval;
}

SQLITE_API const void * WINAPI sqlite3_column_database_name16_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
  const void *pval = sqlite3_column_database_name16(stmt, iCol);
  *plen = (pval != 0) ? wcslen((wchar_t *)pval) * sizeof(wchar_t) : 0;
  return pval;
}

SQLITE_API const char * WINAPI sqlite3_column_table_name_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
  const char *pval = sqlite3_column_table_name(stmt, iCol);
  *plen = (pval != 0) ? strlen(pval) : 0;
  return pval;
}

SQLITE_API const void * WINAPI sqlite3_column_table_name16_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
  const void *pval = sqlite3_column_table_name16(stmt, iCol);
  *plen = (pval != 0) ? wcslen((wchar_t *)pval) * sizeof(wchar_t) : 0;
  return pval;
}

SQLITE_API const char * WINAPI sqlite3_column_origin_name_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
  const char *pval = sqlite3_column_origin_name(stmt, iCol);
  *plen = (pval != 0) ? strlen(pval) : 0;
  return pval;
}

SQLITE_API const void * WINAPI sqlite3_column_origin_name16_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
  const void *pval = sqlite3_column_origin_name16(stmt, iCol);
  *plen = (pval != 0) ? wcslen((wchar_t *)pval) * sizeof(wchar_t) : 0;
  return pval;
}

SQLITE_API int WINAPI sqlite3_table_column_metadata_interop(sqlite3 *db, const char *zDbName, const char *zTableName, const char *zColumnName, char **pzDataType, char **pzCollSeq, int *pNotNull, int *pPrimaryKey, int *pAutoinc, int *pdtLen, int *pcsLen)
{
  int n;
  
  n = sqlite3_table_column_metadata(db, zDbName, zTableName, zColumnName, pzDataType, pzCollSeq, pNotNull, pPrimaryKey, pAutoinc);
  *pdtLen = (*pzDataType != 0) ? strlen(*pzDataType) : 0;
  *pcsLen = (*pzCollSeq != 0) ? strlen(*pzCollSeq) : 0;

  return n;
}

SQLITE_API int WINAPI sqlite3_index_column_info_interop(sqlite3 *db, const char *zDb, const char *zIndexName, const char *zColumnName, int *sortOrder, int *onError, char **pzColl, int *plen)
{
  Index *pIdx;
  Table *pTab;
  int n;

  sqlite3_mutex_enter(db->mutex);
  sqlite3BtreeEnterAll(db);

  pIdx = sqlite3FindIndex(db, zIndexName, zDb);

  sqlite3BtreeLeaveAll(db);
  sqlite3_mutex_leave(db->mutex);

  if (!pIdx) return SQLITE_ERROR;

  pTab = pIdx->pTable;
  for (n = 0; n < pIdx->nColumn; n++)
  {
    int cnum = pIdx->aiColumn[n];
    if (sqlite3StrICmp(pTab->aCol[cnum].zName, zColumnName) == 0)
    {
      *sortOrder = pIdx->aSortOrder[n];
      *pzColl = pIdx->azColl[n];
      *plen = strlen(*pzColl);
      *onError = pIdx->onError;

      return SQLITE_OK;
    }
  }
  return SQLITE_ERROR;
}

SQLITE_API int WINAPI sqlite3_table_cursor(sqlite3_stmt *pstmt, int iDb, Pgno tableRootPage)
{
  Vdbe *p = (Vdbe *)pstmt;
  sqlite3 *db = (p == NULL) ? NULL : p->db;
  int n;
  int ret = -1;

  sqlite3_mutex_enter(db->mutex);







|




|




|






|






|




|




|





|



















|






|






|






|






|






|






|










|




<
<
<
<

<
<
<
<



















|







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

  return n;
}

__declspec(dllexport) void WINAPI sqlite3_value_double_interop(sqlite3_value *pval, double *val)
{
  *val = sqlite3_value_double(pval);
}

__declspec(dllexport) void WINAPI sqlite3_value_int64_interop(sqlite3_value *pval, sqlite_int64 *val)
{
  *val = sqlite3_value_int64(pval);
}

__declspec(dllexport) const unsigned char * WINAPI sqlite3_value_text_interop(sqlite3_value *val, int *plen)
{
  const unsigned char *pval = sqlite3_value_text(val);
  *plen = (pval != 0) ? strlen((char *)pval) : 0;
  return pval;
}

__declspec(dllexport) const void * WINAPI sqlite3_value_text16_interop(sqlite3_value *val, int *plen)
{
  const void *pval = sqlite3_value_text16(val);
  *plen = (pval != 0) ? wcslen((wchar_t *)pval) * sizeof(wchar_t) : 0;
  return pval;
}

__declspec(dllexport) void WINAPI sqlite3_result_double_interop(sqlite3_context *pctx, double *val)
{
  sqlite3_result_double(pctx, *val);
}

__declspec(dllexport) void WINAPI sqlite3_result_int64_interop(sqlite3_context *pctx, sqlite_int64 *val)
{
  sqlite3_result_int64(pctx, *val);
}

__declspec(dllexport) int WINAPI sqlite3_context_collcompare(sqlite3_context *ctx, const void *p1, int p1len, const void *p2, int p2len)
{
  if ((ctx->pFunc->flags & SQLITE_FUNC_NEEDCOLL) == 0) return 2;
  return ctx->pColl->xCmp(ctx->pColl->pUser, p1len, p1, p2len, p2);
}

__declspec(dllexport) const char * WINAPI sqlite3_context_collseq(sqlite3_context *ctx, int *ptype, int *enc, int *plen)
{
  CollSeq *pColl = ctx->pColl;
  *ptype = 0;
  *plen = 0;
  *enc = 0;

  if ((ctx->pFunc->flags & SQLITE_FUNC_NEEDCOLL) == 0) return NULL;

  if (pColl)
  {
    *enc = pColl->enc;
    *ptype = pColl->type;
    *plen = (pColl->zName != 0) ? strlen(pColl->zName) : 0;

    return pColl->zName;
  }
  return NULL;
}

__declspec(dllexport) const char * WINAPI sqlite3_column_database_name_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
  const char *pval = sqlite3_column_database_name(stmt, iCol);
  *plen = (pval != 0) ? strlen(pval) : 0;
  return pval;
}

__declspec(dllexport) const void * WINAPI sqlite3_column_database_name16_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
  const void *pval = sqlite3_column_database_name16(stmt, iCol);
  *plen = (pval != 0) ? wcslen((wchar_t *)pval) * sizeof(wchar_t) : 0;
  return pval;
}

__declspec(dllexport) const char * WINAPI sqlite3_column_table_name_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
  const char *pval = sqlite3_column_table_name(stmt, iCol);
  *plen = (pval != 0) ? strlen(pval) : 0;
  return pval;
}

__declspec(dllexport) const void * WINAPI sqlite3_column_table_name16_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
  const void *pval = sqlite3_column_table_name16(stmt, iCol);
  *plen = (pval != 0) ? wcslen((wchar_t *)pval) * sizeof(wchar_t) : 0;
  return pval;
}

__declspec(dllexport) const char * WINAPI sqlite3_column_origin_name_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
  const char *pval = sqlite3_column_origin_name(stmt, iCol);
  *plen = (pval != 0) ? strlen(pval) : 0;
  return pval;
}

__declspec(dllexport) const void * WINAPI sqlite3_column_origin_name16_interop(sqlite3_stmt *stmt, int iCol, int *plen)
{
  const void *pval = sqlite3_column_origin_name16(stmt, iCol);
  *plen = (pval != 0) ? wcslen((wchar_t *)pval) * sizeof(wchar_t) : 0;
  return pval;
}

__declspec(dllexport) int WINAPI sqlite3_table_column_metadata_interop(sqlite3 *db, const char *zDbName, const char *zTableName, const char *zColumnName, char **pzDataType, char **pzCollSeq, int *pNotNull, int *pPrimaryKey, int *pAutoinc, int *pdtLen, int *pcsLen)
{
  int n;
  
  n = sqlite3_table_column_metadata(db, zDbName, zTableName, zColumnName, pzDataType, pzCollSeq, pNotNull, pPrimaryKey, pAutoinc);
  *pdtLen = (*pzDataType != 0) ? strlen(*pzDataType) : 0;
  *pcsLen = (*pzCollSeq != 0) ? strlen(*pzCollSeq) : 0;

  return n;
}

__declspec(dllexport) int WINAPI sqlite3_index_column_info_interop(sqlite3 *db, const char *zDb, const char *zIndexName, const char *zColumnName, int *sortOrder, int *onError, char **pzColl, int *plen)
{
  Index *pIdx;
  Table *pTab;
  int n;




  pIdx = sqlite3FindIndex(db, zIndexName, zDb);




  if (!pIdx) return SQLITE_ERROR;

  pTab = pIdx->pTable;
  for (n = 0; n < pIdx->nColumn; n++)
  {
    int cnum = pIdx->aiColumn[n];
    if (sqlite3StrICmp(pTab->aCol[cnum].zName, zColumnName) == 0)
    {
      *sortOrder = pIdx->aSortOrder[n];
      *pzColl = pIdx->azColl[n];
      *plen = strlen(*pzColl);
      *onError = pIdx->onError;

      return SQLITE_OK;
    }
  }
  return SQLITE_ERROR;
}

__declspec(dllexport) int WINAPI sqlite3_table_cursor(sqlite3_stmt *pstmt, int iDb, Pgno tableRootPage)
{
  Vdbe *p = (Vdbe *)pstmt;
  sqlite3 *db = (p == NULL) ? NULL : p->db;
  int n;
  int ret = -1;

  sqlite3_mutex_enter(db->mutex);
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
    }
  }
  sqlite3_mutex_leave(db->mutex);

  return ret;
}

SQLITE_API int WINAPI sqlite3_cursor_rowid(sqlite3_stmt *pstmt, int cursor, sqlite_int64 *prowid)
{
  Vdbe *p = (Vdbe *)pstmt;
  sqlite3 *db = (p == NULL) ? NULL : p->db;
  VdbeCursor *pC;
  int ret = 0;

  sqlite3_mutex_enter(db->mutex);







|







404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
    }
  }
  sqlite3_mutex_leave(db->mutex);

  return ret;
}

__declspec(dllexport) int WINAPI sqlite3_cursor_rowid(sqlite3_stmt *pstmt, int cursor, sqlite_int64 *prowid)
{
  Vdbe *p = (Vdbe *)pstmt;
  sqlite3 *db = (p == NULL) ? NULL : p->db;
  VdbeCursor *pC;
  int ret = 0;

  sqlite3_mutex_enter(db->mutex);
498
499
500
501
502
503
504

  }
  sqlite3_mutex_leave(db->mutex);

  return ret;
}

#endif // SQLITE_OS_WIN








>
463
464
465
466
467
468
469
470
  }
  sqlite3_mutex_leave(db->mutex);

  return ret;
}

#endif // SQLITE_OS_WIN

Changes to SQLite.Interop/src/win/interop.h.
1
2
3
4
5
6
7
8
9
10
11
12
/*
 *
 * interop.h -
 *
 * Written by Joe Mistachkin.
 * Released to the public domain, use at your own risk!
 *
 */

#ifndef INTEROP_VERSION
#define INTEROP_VERSION       "1.0.76.0"
#endif










|

1
2
3
4
5
6
7
8
9
10
11
12
/*
 *
 * interop.h -
 *
 * Written by Joe Mistachkin.
 * Released to the public domain, use at your own risk!
 *
 */

#ifndef INTEROP_VERSION
#define INTEROP_VERSION       "1.0.74.0"
#endif
Deleted SQLite.MSIL.nuspec.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="utf-8"?>
<package>
  <metadata>
    <id>System.Data.SQLite.MSIL</id>
    <version>1.0.76.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>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










































Changes to SQLite.NET.2008.MSBuild.sln.
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Data.SQLite.Compact.2008", "System.Data.SQLite\System.Data.SQLite.Compact.2008.csproj", "{AC139951-261A-4463-B6FA-AEBC25283A66}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SQLite.Interop.CE.2008", "SQLite.Interop\SQLite.Interop.CE.2008.vcproj", "{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "testce.2008", "testce\testce.2008.csproj", "{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SQLite.Interop.Static.2008", "SQLite.Interop\SQLite.Interop.Static.2008.vcproj", "{490CBC51-A3B2-4397-89F9-16E858DCB4F8}"
	ProjectSection(ProjectDependencies) = postProject
		{AC139952-261A-4463-B6FA-AEBC25284A66} = {AC139952-261A-4463-B6FA-AEBC25284A66}
	EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Installer.2008", "tools\install\Installer.2008.csproj", "{A41FE2A5-07AD-4CE7-B836-1544634816F5}"
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|Any CPU = Debug|Any CPU
		Debug|Mixed Platforms = Debug|Mixed Platforms
		Debug|Pocket PC 2003 (ARMV4) = Debug|Pocket PC 2003 (ARMV4)
		Debug|Win32 = Debug|Win32
		Debug|x64 = Debug|x64







<
<
<
<
<
<
<







30
31
32
33
34
35
36







37
38
39
40
41
42
43
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Data.SQLite.Compact.2008", "System.Data.SQLite\System.Data.SQLite.Compact.2008.csproj", "{AC139951-261A-4463-B6FA-AEBC25283A66}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SQLite.Interop.CE.2008", "SQLite.Interop\SQLite.Interop.CE.2008.vcproj", "{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "testce.2008", "testce\testce.2008.csproj", "{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}"
EndProject







Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|Any CPU = Debug|Any CPU
		Debug|Mixed Platforms = Debug|Mixed Platforms
		Debug|Pocket PC 2003 (ARMV4) = Debug|Pocket PC 2003 (ARMV4)
		Debug|Win32 = Debug|Win32
		Debug|x64 = Debug|x64
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
		{E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.ReleaseNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Any CPU
		{E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.ReleaseNativeOnly|Win32.ActiveCfg = Release|Any CPU
		{E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.ReleaseNativeOnly|x64.ActiveCfg = Release|Any CPU
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Any CPU.ActiveCfg = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Any CPU.Build.0 = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Mixed Platforms.Build.0 = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Win32.ActiveCfg = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Win32.Build.0 = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|x64.ActiveCfg = Debug|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|x64.Build.0 = Debug|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugManagedOnly|Any CPU.ActiveCfg = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugManagedOnly|Mixed Platforms.ActiveCfg = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugManagedOnly|Pocket PC 2003 (ARMV4).ActiveCfg = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugManagedOnly|Win32.ActiveCfg = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugManagedOnly|x64.ActiveCfg = DebugNativeOnly|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Any CPU.ActiveCfg = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Any CPU.Build.0 = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Mixed Platforms.ActiveCfg = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Mixed Platforms.Build.0 = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Win32.ActiveCfg = DebugNativeOnly|Win32







|







|







206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
		{E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.ReleaseNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Any CPU
		{E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.ReleaseNativeOnly|Win32.ActiveCfg = Release|Any CPU
		{E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.ReleaseNativeOnly|x64.ActiveCfg = Release|Any CPU
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Any CPU.ActiveCfg = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Any CPU.Build.0 = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Mixed Platforms.Build.0 = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Win32.ActiveCfg = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Win32.Build.0 = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|x64.ActiveCfg = Debug|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|x64.Build.0 = Debug|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugManagedOnly|Any CPU.ActiveCfg = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugManagedOnly|Mixed Platforms.ActiveCfg = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugManagedOnly|Pocket PC 2003 (ARMV4).ActiveCfg = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugManagedOnly|Win32.ActiveCfg = DebugNativeOnly|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugManagedOnly|x64.ActiveCfg = DebugNativeOnly|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Any CPU.ActiveCfg = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Any CPU.Build.0 = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Mixed Platforms.ActiveCfg = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Mixed Platforms.Build.0 = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Win32.ActiveCfg = DebugNativeOnly|Win32
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
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseManagedOnly|Win32.ActiveCfg = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseManagedOnly|x64.ActiveCfg = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseNativeOnly|Any CPU.ActiveCfg = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseNativeOnly|Mixed Platforms.ActiveCfg = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseNativeOnly|Win32.ActiveCfg = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseNativeOnly|x64.ActiveCfg = Release|Any CPU
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|Any CPU.ActiveCfg = Debug|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|Any CPU.Build.0 = Debug|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|Mixed Platforms.Build.0 = Debug|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|Win32.ActiveCfg = Debug|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|Win32.Build.0 = Debug|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|x64.ActiveCfg = Debug|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|x64.Build.0 = Debug|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugManagedOnly|Any CPU.ActiveCfg = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugManagedOnly|Mixed Platforms.ActiveCfg = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugManagedOnly|Pocket PC 2003 (ARMV4).ActiveCfg = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugManagedOnly|Win32.ActiveCfg = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugManagedOnly|x64.ActiveCfg = DebugNativeOnly|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|Any CPU.ActiveCfg = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|Any CPU.Build.0 = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|Mixed Platforms.ActiveCfg = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|Mixed Platforms.Build.0 = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|Win32.ActiveCfg = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|Win32.Build.0 = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|x64.ActiveCfg = DebugNativeOnly|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|x64.Build.0 = DebugNativeOnly|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|Any CPU.ActiveCfg = Release|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|Any CPU.Build.0 = Release|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|Mixed Platforms.ActiveCfg = Release|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|Mixed Platforms.Build.0 = Release|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|Win32.ActiveCfg = Release|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|Win32.Build.0 = Release|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|x64.ActiveCfg = Release|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|x64.Build.0 = Release|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseManagedOnly|Any CPU.ActiveCfg = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseManagedOnly|Mixed Platforms.ActiveCfg = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseManagedOnly|Pocket PC 2003 (ARMV4).ActiveCfg = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseManagedOnly|Win32.ActiveCfg = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseManagedOnly|x64.ActiveCfg = ReleaseNativeOnly|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|Any CPU.ActiveCfg = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|Any CPU.Build.0 = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|Mixed Platforms.ActiveCfg = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|Mixed Platforms.Build.0 = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|Win32.ActiveCfg = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|Win32.Build.0 = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|x64.ActiveCfg = ReleaseNativeOnly|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|x64.Build.0 = ReleaseNativeOnly|x64
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|Win32.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|Win32.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|x64.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|x64.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugManagedOnly|Any CPU.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugManagedOnly|Any CPU.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugManagedOnly|Mixed Platforms.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugManagedOnly|Mixed Platforms.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugManagedOnly|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugManagedOnly|Win32.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugManagedOnly|Win32.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugManagedOnly|x64.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugManagedOnly|x64.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugNativeOnly|Any CPU.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugNativeOnly|Mixed Platforms.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugNativeOnly|Win32.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugNativeOnly|x64.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|Any CPU.Build.0 = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|Mixed Platforms.Build.0 = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|Win32.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|Win32.Build.0 = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|x64.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|x64.Build.0 = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseManagedOnly|Any CPU.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseManagedOnly|Any CPU.Build.0 = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseManagedOnly|Mixed Platforms.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseManagedOnly|Mixed Platforms.Build.0 = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseManagedOnly|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseManagedOnly|Win32.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseManagedOnly|Win32.Build.0 = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseManagedOnly|x64.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseManagedOnly|x64.Build.0 = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseNativeOnly|Any CPU.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseNativeOnly|Mixed Platforms.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseNativeOnly|Win32.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseNativeOnly|x64.ActiveCfg = Release|Any CPU
	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
EndGlobal







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





490
491
492
493
494
495
496




























































































497
498
499
500
501
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseManagedOnly|Win32.ActiveCfg = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseManagedOnly|x64.ActiveCfg = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseNativeOnly|Any CPU.ActiveCfg = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseNativeOnly|Mixed Platforms.ActiveCfg = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseNativeOnly|Win32.ActiveCfg = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseNativeOnly|x64.ActiveCfg = Release|Any CPU




























































































	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
EndGlobal
Changes to SQLite.NET.2008.sln.
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
		{E6BF9F74-58E2-413B-A7CE-EA653ECB728D} = {E6BF9F74-58E2-413B-A7CE-EA653ECB728D}
	EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "testce.2008", "testce\testce.2008.csproj", "{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SQLite.Interop.CE.2008", "SQLite.Interop\SQLite.Interop.CE.2008.vcproj", "{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SQLite.Interop.Static.2008", "SQLite.Interop\SQLite.Interop.Static.2008.vcproj", "{490CBC51-A3B2-4397-89F9-16E858DCB4F8}"
	ProjectSection(ProjectDependencies) = postProject
		{AC139952-261A-4463-B6FA-AEBC25284A66} = {AC139952-261A-4463-B6FA-AEBC25284A66}
	EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Installer.2008", "tools\install\Installer.2008.csproj", "{A41FE2A5-07AD-4CE7-B836-1544634816F5}"
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|Any CPU = Debug|Any CPU
		Debug|Mixed Platforms = Debug|Mixed Platforms
		Debug|Pocket PC 2003 (ARMV4) = Debug|Pocket PC 2003 (ARMV4)
		Debug|Win32 = Debug|Win32
		Debug|x64 = Debug|x64







<
<
<
<
<
<
<







35
36
37
38
39
40
41







42
43
44
45
46
47
48
		{E6BF9F74-58E2-413B-A7CE-EA653ECB728D} = {E6BF9F74-58E2-413B-A7CE-EA653ECB728D}
	EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "testce.2008", "testce\testce.2008.csproj", "{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SQLite.Interop.CE.2008", "SQLite.Interop\SQLite.Interop.CE.2008.vcproj", "{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}"
EndProject







Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|Any CPU = Debug|Any CPU
		Debug|Mixed Platforms = Debug|Mixed Platforms
		Debug|Pocket PC 2003 (ARMV4) = Debug|Pocket PC 2003 (ARMV4)
		Debug|Win32 = Debug|Win32
		Debug|x64 = Debug|x64
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
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Debug|Pocket PC 2003 (ARMV4).Build.0 = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Debug|Win32.ActiveCfg = Debug|Any CPU

		{AC139951-261A-4463-B6FA-AEBC25283A66}.Debug|x64.ActiveCfg = Debug|Any CPU

		{AC139951-261A-4463-B6FA-AEBC25283A66}.DebugNativeOnly|Any CPU.ActiveCfg = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.DebugNativeOnly|Any CPU.Build.0 = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.DebugNativeOnly|Mixed Platforms.ActiveCfg = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.DebugNativeOnly|Mixed Platforms.Build.0 = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.DebugNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.DebugNativeOnly|Pocket PC 2003 (ARMV4).Build.0 = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.DebugNativeOnly|Win32.ActiveCfg = Debug|Any CPU

		{AC139951-261A-4463-B6FA-AEBC25283A66}.DebugNativeOnly|x64.ActiveCfg = Debug|Any CPU

		{AC139951-261A-4463-B6FA-AEBC25283A66}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Release|Any CPU.Build.0 = Release|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Release|Mixed Platforms.Build.0 = Release|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Release|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Release|Pocket PC 2003 (ARMV4).Build.0 = Release|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Release|Win32.ActiveCfg = Release|Any CPU

		{AC139951-261A-4463-B6FA-AEBC25283A66}.Release|x64.ActiveCfg = Release|Any CPU

		{AC139951-261A-4463-B6FA-AEBC25283A66}.ReleaseNativeOnly|Any CPU.ActiveCfg = Release|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.ReleaseNativeOnly|Any CPU.Build.0 = Release|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.ReleaseNativeOnly|Mixed Platforms.ActiveCfg = Release|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.ReleaseNativeOnly|Mixed Platforms.Build.0 = Release|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.ReleaseNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.ReleaseNativeOnly|Pocket PC 2003 (ARMV4).Build.0 = Release|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.ReleaseNativeOnly|Win32.ActiveCfg = Release|Any CPU

		{AC139951-261A-4463-B6FA-AEBC25283A66}.ReleaseNativeOnly|x64.ActiveCfg = Release|Any CPU

		{E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
		{E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
		{E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Any CPU
		{E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.Debug|Win32.ActiveCfg = Debug|Any CPU
		{E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.Debug|Win32.Build.0 = Debug|Any CPU







>

>







>

>







>

>







>

>







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
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Debug|Pocket PC 2003 (ARMV4).Build.0 = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Debug|Win32.ActiveCfg = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Debug|Win32.Build.0 = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Debug|x64.ActiveCfg = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Debug|x64.Build.0 = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.DebugNativeOnly|Any CPU.ActiveCfg = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.DebugNativeOnly|Any CPU.Build.0 = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.DebugNativeOnly|Mixed Platforms.ActiveCfg = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.DebugNativeOnly|Mixed Platforms.Build.0 = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.DebugNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.DebugNativeOnly|Pocket PC 2003 (ARMV4).Build.0 = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.DebugNativeOnly|Win32.ActiveCfg = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.DebugNativeOnly|Win32.Build.0 = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.DebugNativeOnly|x64.ActiveCfg = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.DebugNativeOnly|x64.Build.0 = Debug|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Release|Any CPU.Build.0 = Release|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Release|Mixed Platforms.Build.0 = Release|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Release|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Release|Pocket PC 2003 (ARMV4).Build.0 = Release|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Release|Win32.ActiveCfg = Release|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Release|Win32.Build.0 = Release|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Release|x64.ActiveCfg = Release|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.Release|x64.Build.0 = Release|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.ReleaseNativeOnly|Any CPU.ActiveCfg = Release|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.ReleaseNativeOnly|Any CPU.Build.0 = Release|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.ReleaseNativeOnly|Mixed Platforms.ActiveCfg = Release|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.ReleaseNativeOnly|Mixed Platforms.Build.0 = Release|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.ReleaseNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.ReleaseNativeOnly|Pocket PC 2003 (ARMV4).Build.0 = Release|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.ReleaseNativeOnly|Win32.ActiveCfg = Release|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.ReleaseNativeOnly|Win32.Build.0 = Release|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.ReleaseNativeOnly|x64.ActiveCfg = Release|Any CPU
		{AC139951-261A-4463-B6FA-AEBC25283A66}.ReleaseNativeOnly|x64.Build.0 = Release|Any CPU
		{E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
		{E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
		{E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Any CPU
		{E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.Debug|Win32.ActiveCfg = Debug|Any CPU
		{E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.Debug|Win32.Build.0 = Debug|Any CPU
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
		{E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.ReleaseNativeOnly|Win32.Build.0 = Release|Any CPU
		{E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.ReleaseNativeOnly|x64.ActiveCfg = Release|Any CPU
		{E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.ReleaseNativeOnly|x64.Build.0 = Release|Any CPU
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Any CPU.ActiveCfg = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Any CPU.Build.0 = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Mixed Platforms.Build.0 = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Win32.ActiveCfg = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Win32.Build.0 = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|x64.ActiveCfg = Debug|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|x64.Build.0 = Debug|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Any CPU.ActiveCfg = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Any CPU.Build.0 = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Mixed Platforms.ActiveCfg = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Mixed Platforms.Build.0 = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Win32.ActiveCfg = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Win32.Build.0 = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|x64.ActiveCfg = DebugNativeOnly|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|x64.Build.0 = DebugNativeOnly|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Release|Any CPU.ActiveCfg = Release|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Release|Any CPU.Build.0 = Release|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Release|Mixed Platforms.ActiveCfg = Release|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Release|Mixed Platforms.Build.0 = Release|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Release|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Release|Win32.ActiveCfg = Release|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Release|Win32.Build.0 = Release|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Release|x64.ActiveCfg = Release|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Release|x64.Build.0 = Release|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.ReleaseNativeOnly|Any CPU.ActiveCfg = ReleaseNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.ReleaseNativeOnly|Any CPU.Build.0 = ReleaseNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.ReleaseNativeOnly|Mixed Platforms.ActiveCfg = ReleaseNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.ReleaseNativeOnly|Mixed Platforms.Build.0 = ReleaseNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.ReleaseNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = ReleaseNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.ReleaseNativeOnly|Win32.ActiveCfg = ReleaseNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.ReleaseNativeOnly|Win32.Build.0 = ReleaseNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.ReleaseNativeOnly|x64.ActiveCfg = ReleaseNativeOnly|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.ReleaseNativeOnly|x64.Build.0 = ReleaseNativeOnly|x64
		{E6BF9F74-58E2-413B-A7CE-EA653ECB728D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{E6BF9F74-58E2-413B-A7CE-EA653ECB728D}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{E6BF9F74-58E2-413B-A7CE-EA653ECB728D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU







|








|








|








|







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
		{E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.ReleaseNativeOnly|Win32.Build.0 = Release|Any CPU
		{E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.ReleaseNativeOnly|x64.ActiveCfg = Release|Any CPU
		{E27B1B1E-19C0-45E8-AA74-B6E1C041A130}.ReleaseNativeOnly|x64.Build.0 = Release|Any CPU
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Any CPU.ActiveCfg = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Any CPU.Build.0 = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Mixed Platforms.Build.0 = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Win32.ActiveCfg = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Win32.Build.0 = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|x64.ActiveCfg = Debug|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|x64.Build.0 = Debug|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Any CPU.ActiveCfg = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Any CPU.Build.0 = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Mixed Platforms.ActiveCfg = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Mixed Platforms.Build.0 = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = DebugNativeOnly|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Win32.ActiveCfg = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Win32.Build.0 = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|x64.ActiveCfg = DebugNativeOnly|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|x64.Build.0 = DebugNativeOnly|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Release|Any CPU.ActiveCfg = Release|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Release|Any CPU.Build.0 = Release|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Release|Mixed Platforms.ActiveCfg = Release|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Release|Mixed Platforms.Build.0 = Release|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Release|Pocket PC 2003 (ARMV4).ActiveCfg = Release|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Release|Win32.ActiveCfg = Release|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Release|Win32.Build.0 = Release|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Release|x64.ActiveCfg = Release|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Release|x64.Build.0 = Release|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.ReleaseNativeOnly|Any CPU.ActiveCfg = ReleaseNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.ReleaseNativeOnly|Any CPU.Build.0 = ReleaseNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.ReleaseNativeOnly|Mixed Platforms.ActiveCfg = ReleaseNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.ReleaseNativeOnly|Mixed Platforms.Build.0 = ReleaseNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.ReleaseNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = ReleaseNativeOnly|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.ReleaseNativeOnly|Win32.ActiveCfg = ReleaseNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.ReleaseNativeOnly|Win32.Build.0 = ReleaseNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.ReleaseNativeOnly|x64.ActiveCfg = ReleaseNativeOnly|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.ReleaseNativeOnly|x64.Build.0 = ReleaseNativeOnly|x64
		{E6BF9F74-58E2-413B-A7CE-EA653ECB728D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{E6BF9F74-58E2-413B-A7CE-EA653ECB728D}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{E6BF9F74-58E2-413B-A7CE-EA653ECB728D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
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
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Debug|Pocket PC 2003 (ARMV4).Build.0 = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Debug|Pocket PC 2003 (ARMV4).Deploy.0 = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Debug|Win32.ActiveCfg = Debug|Any CPU

		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Debug|x64.ActiveCfg = Debug|Any CPU

		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.DebugNativeOnly|Any CPU.ActiveCfg = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.DebugNativeOnly|Any CPU.Build.0 = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.DebugNativeOnly|Mixed Platforms.ActiveCfg = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.DebugNativeOnly|Mixed Platforms.Build.0 = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.DebugNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.DebugNativeOnly|Pocket PC 2003 (ARMV4).Build.0 = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.DebugNativeOnly|Pocket PC 2003 (ARMV4).Deploy.0 = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.DebugNativeOnly|Win32.ActiveCfg = Debug|Any CPU

		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.DebugNativeOnly|x64.ActiveCfg = Debug|Any CPU

		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Release|Any CPU.Build.0 = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Release|Mixed Platforms.Build.0 = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Release|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Release|Pocket PC 2003 (ARMV4).Build.0 = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Release|Pocket PC 2003 (ARMV4).Deploy.0 = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Release|Win32.ActiveCfg = Release|Any CPU

		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Release|x64.ActiveCfg = Release|Any CPU

		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseNativeOnly|Any CPU.ActiveCfg = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseNativeOnly|Any CPU.Build.0 = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseNativeOnly|Mixed Platforms.ActiveCfg = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseNativeOnly|Mixed Platforms.Build.0 = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseNativeOnly|Pocket PC 2003 (ARMV4).Build.0 = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseNativeOnly|Pocket PC 2003 (ARMV4).Deploy.0 = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseNativeOnly|Win32.ActiveCfg = Release|Any CPU

		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseNativeOnly|x64.ActiveCfg = Release|Any CPU

		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Debug|Any CPU.ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Debug|Any CPU.Build.0 = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Debug|Mixed Platforms.ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Debug|Mixed Platforms.Build.0 = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Debug|Pocket PC 2003 (ARMV4).Build.0 = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Debug|Pocket PC 2003 (ARMV4).Deploy.0 = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Debug|Win32.ActiveCfg = Debug|Pocket PC 2003 (ARMV4)

		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Debug|x64.ActiveCfg = Debug|Pocket PC 2003 (ARMV4)

		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.DebugNativeOnly|Any CPU.ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.DebugNativeOnly|Any CPU.Build.0 = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.DebugNativeOnly|Mixed Platforms.ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.DebugNativeOnly|Mixed Platforms.Build.0 = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.DebugNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.DebugNativeOnly|Pocket PC 2003 (ARMV4).Build.0 = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.DebugNativeOnly|Pocket PC 2003 (ARMV4).Deploy.0 = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.DebugNativeOnly|Win32.ActiveCfg = Debug|Pocket PC 2003 (ARMV4)

		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.DebugNativeOnly|x64.ActiveCfg = Debug|Pocket PC 2003 (ARMV4)

		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Release|Any CPU.ActiveCfg = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Release|Any CPU.Build.0 = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Release|Mixed Platforms.ActiveCfg = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Release|Mixed Platforms.Build.0 = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Release|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Release|Pocket PC 2003 (ARMV4).Build.0 = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Release|Pocket PC 2003 (ARMV4).Deploy.0 = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Release|Win32.ActiveCfg = Release|Pocket PC 2003 (ARMV4)

		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Release|x64.ActiveCfg = Release|Pocket PC 2003 (ARMV4)

		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.ReleaseNativeOnly|Any CPU.ActiveCfg = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.ReleaseNativeOnly|Any CPU.Build.0 = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.ReleaseNativeOnly|Mixed Platforms.ActiveCfg = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.ReleaseNativeOnly|Mixed Platforms.Build.0 = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.ReleaseNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.ReleaseNativeOnly|Pocket PC 2003 (ARMV4).Build.0 = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.ReleaseNativeOnly|Pocket PC 2003 (ARMV4).Deploy.0 = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.ReleaseNativeOnly|Win32.ActiveCfg = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.ReleaseNativeOnly|x64.ActiveCfg = Release|Pocket PC 2003 (ARMV4)
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|Any CPU.ActiveCfg = Debug|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|Any CPU.Build.0 = Debug|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|Mixed Platforms.Build.0 = Debug|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|Win32.ActiveCfg = Debug|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|Win32.Build.0 = Debug|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|x64.ActiveCfg = Debug|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|x64.Build.0 = Debug|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|Any CPU.ActiveCfg = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|Any CPU.Build.0 = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|Mixed Platforms.ActiveCfg = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|Mixed Platforms.Build.0 = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|Win32.ActiveCfg = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|Win32.Build.0 = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|x64.ActiveCfg = DebugNativeOnly|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|x64.Build.0 = DebugNativeOnly|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|Any CPU.ActiveCfg = Release|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|Any CPU.Build.0 = Release|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|Mixed Platforms.ActiveCfg = Release|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|Mixed Platforms.Build.0 = Release|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|Win32.ActiveCfg = Release|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|Win32.Build.0 = Release|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|x64.ActiveCfg = Release|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|x64.Build.0 = Release|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|Any CPU.ActiveCfg = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|Any CPU.Build.0 = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|Mixed Platforms.ActiveCfg = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|Mixed Platforms.Build.0 = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|Win32.ActiveCfg = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|Win32.Build.0 = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|x64.ActiveCfg = ReleaseNativeOnly|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|x64.Build.0 = ReleaseNativeOnly|x64
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|Win32.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|Win32.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|x64.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|x64.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugNativeOnly|Any CPU.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugNativeOnly|Any CPU.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugNativeOnly|Mixed Platforms.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugNativeOnly|Mixed Platforms.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugNativeOnly|Win32.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugNativeOnly|Win32.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugNativeOnly|x64.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugNativeOnly|x64.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|Any CPU.Build.0 = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|Mixed Platforms.Build.0 = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|Win32.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|Win32.Build.0 = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|x64.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|x64.Build.0 = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseNativeOnly|Any CPU.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseNativeOnly|Any CPU.Build.0 = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseNativeOnly|Mixed Platforms.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseNativeOnly|Mixed Platforms.Build.0 = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseNativeOnly|Win32.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseNativeOnly|Win32.Build.0 = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseNativeOnly|x64.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseNativeOnly|x64.Build.0 = Release|Any CPU
	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
EndGlobal







>

>








>

>








>

>








>

>








>

>








>

>








>

>








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





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
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Debug|Pocket PC 2003 (ARMV4).Build.0 = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Debug|Pocket PC 2003 (ARMV4).Deploy.0 = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Debug|Win32.ActiveCfg = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Debug|Win32.Build.0 = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Debug|x64.ActiveCfg = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Debug|x64.Build.0 = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.DebugNativeOnly|Any CPU.ActiveCfg = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.DebugNativeOnly|Any CPU.Build.0 = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.DebugNativeOnly|Mixed Platforms.ActiveCfg = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.DebugNativeOnly|Mixed Platforms.Build.0 = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.DebugNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.DebugNativeOnly|Pocket PC 2003 (ARMV4).Build.0 = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.DebugNativeOnly|Pocket PC 2003 (ARMV4).Deploy.0 = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.DebugNativeOnly|Win32.ActiveCfg = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.DebugNativeOnly|Win32.Build.0 = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.DebugNativeOnly|x64.ActiveCfg = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.DebugNativeOnly|x64.Build.0 = Debug|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Release|Any CPU.Build.0 = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Release|Mixed Platforms.Build.0 = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Release|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Release|Pocket PC 2003 (ARMV4).Build.0 = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Release|Pocket PC 2003 (ARMV4).Deploy.0 = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Release|Win32.ActiveCfg = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Release|Win32.Build.0 = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Release|x64.ActiveCfg = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.Release|x64.Build.0 = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseNativeOnly|Any CPU.ActiveCfg = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseNativeOnly|Any CPU.Build.0 = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseNativeOnly|Mixed Platforms.ActiveCfg = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseNativeOnly|Mixed Platforms.Build.0 = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseNativeOnly|Pocket PC 2003 (ARMV4).Build.0 = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseNativeOnly|Pocket PC 2003 (ARMV4).Deploy.0 = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseNativeOnly|Win32.ActiveCfg = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseNativeOnly|Win32.Build.0 = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseNativeOnly|x64.ActiveCfg = Release|Any CPU
		{B86CE504-C4E4-496F-A0F0-E613BCFD3DF7}.ReleaseNativeOnly|x64.Build.0 = Release|Any CPU
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Debug|Any CPU.ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Debug|Any CPU.Build.0 = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Debug|Mixed Platforms.ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Debug|Mixed Platforms.Build.0 = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Debug|Pocket PC 2003 (ARMV4).Build.0 = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Debug|Pocket PC 2003 (ARMV4).Deploy.0 = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Debug|Win32.ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Debug|Win32.Build.0 = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Debug|x64.ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Debug|x64.Build.0 = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.DebugNativeOnly|Any CPU.ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.DebugNativeOnly|Any CPU.Build.0 = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.DebugNativeOnly|Mixed Platforms.ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.DebugNativeOnly|Mixed Platforms.Build.0 = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.DebugNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.DebugNativeOnly|Pocket PC 2003 (ARMV4).Build.0 = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.DebugNativeOnly|Pocket PC 2003 (ARMV4).Deploy.0 = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.DebugNativeOnly|Win32.ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.DebugNativeOnly|Win32.Build.0 = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.DebugNativeOnly|x64.ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.DebugNativeOnly|x64.Build.0 = Debug|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Release|Any CPU.ActiveCfg = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Release|Any CPU.Build.0 = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Release|Mixed Platforms.ActiveCfg = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Release|Mixed Platforms.Build.0 = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Release|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Release|Pocket PC 2003 (ARMV4).Build.0 = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Release|Pocket PC 2003 (ARMV4).Deploy.0 = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Release|Win32.ActiveCfg = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Release|Win32.Build.0 = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Release|x64.ActiveCfg = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.Release|x64.Build.0 = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.ReleaseNativeOnly|Any CPU.ActiveCfg = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.ReleaseNativeOnly|Any CPU.Build.0 = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.ReleaseNativeOnly|Mixed Platforms.ActiveCfg = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.ReleaseNativeOnly|Mixed Platforms.Build.0 = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.ReleaseNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.ReleaseNativeOnly|Pocket PC 2003 (ARMV4).Build.0 = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.ReleaseNativeOnly|Pocket PC 2003 (ARMV4).Deploy.0 = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.ReleaseNativeOnly|Win32.ActiveCfg = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.ReleaseNativeOnly|Win32.Build.0 = Release|Pocket PC 2003 (ARMV4)






































































		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.ReleaseNativeOnly|x64.ActiveCfg = Release|Pocket PC 2003 (ARMV4)
		{9E5A8F20-5F04-4629-B2E1-27B5E30F2AF6}.ReleaseNativeOnly|x64.Build.0 = Release|Pocket PC 2003 (ARMV4)
	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
EndGlobal
Changes to SQLite.NET.2010.MSBuild.sln.
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "testlinq.2010", "testlinq\testlinq.2010.csproj", "{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}"
	ProjectSection(ProjectDependencies) = postProject
		{AC139952-261A-4463-B6FA-AEBC25283A66} = {AC139952-261A-4463-B6FA-AEBC25283A66}
		{E6BF9F74-58E2-413B-A7CE-EA653ECB728D} = {E6BF9F74-58E2-413B-A7CE-EA653ECB728D}
	EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SQLite.Interop.Static.2010", "SQLite.Interop\SQLite.Interop.Static.2010.vcxproj", "{490CBC51-A3B2-4397-89F9-16E858DCB4F8}"
	ProjectSection(ProjectDependencies) = postProject
		{AC139952-261A-4463-B6FA-AEBC25284A66} = {AC139952-261A-4463-B6FA-AEBC25284A66}
	EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Installer.2010", "tools\install\Installer.2010.csproj", "{A41FE2A5-07AD-4CE7-B836-1544634816F5}"
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|Any CPU = Debug|Any CPU
		Debug|Mixed Platforms = Debug|Mixed Platforms
		Debug|Win32 = Debug|Win32
		Debug|x64 = Debug|x64
		DebugManagedOnly|Any CPU = DebugManagedOnly|Any CPU







<
<
<
<
<
<
<







24
25
26
27
28
29
30







31
32
33
34
35
36
37
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "testlinq.2010", "testlinq\testlinq.2010.csproj", "{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}"
	ProjectSection(ProjectDependencies) = postProject
		{AC139952-261A-4463-B6FA-AEBC25283A66} = {AC139952-261A-4463-B6FA-AEBC25283A66}
		{E6BF9F74-58E2-413B-A7CE-EA653ECB728D} = {E6BF9F74-58E2-413B-A7CE-EA653ECB728D}
	EndProjectSection
EndProject







Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|Any CPU = Debug|Any CPU
		Debug|Mixed Platforms = Debug|Mixed Platforms
		Debug|Win32 = Debug|Win32
		Debug|x64 = Debug|x64
		DebugManagedOnly|Any CPU = DebugManagedOnly|Any CPU
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Mixed Platforms.Build.0 = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Win32.ActiveCfg = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Win32.Build.0 = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|x64.ActiveCfg = Debug|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|x64.Build.0 = Debug|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugManagedOnly|Any CPU.ActiveCfg = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugManagedOnly|Mixed Platforms.ActiveCfg = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugManagedOnly|Win32.ActiveCfg = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugManagedOnly|x64.ActiveCfg = DebugNativeOnly|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Any CPU.ActiveCfg = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Any CPU.Build.0 = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Mixed Platforms.ActiveCfg = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Mixed Platforms.Build.0 = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Win32.ActiveCfg = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Win32.Build.0 = DebugNativeOnly|Win32







|







182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Mixed Platforms.Build.0 = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Win32.ActiveCfg = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|Win32.Build.0 = Debug|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|x64.ActiveCfg = Debug|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.Debug|x64.Build.0 = Debug|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugManagedOnly|Any CPU.ActiveCfg = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugManagedOnly|Mixed Platforms.ActiveCfg = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugManagedOnly|Win32.ActiveCfg = DebugNativeOnly|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugManagedOnly|x64.ActiveCfg = DebugNativeOnly|x64
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Any CPU.ActiveCfg = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Any CPU.Build.0 = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Mixed Platforms.ActiveCfg = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Mixed Platforms.Build.0 = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Win32.ActiveCfg = DebugNativeOnly|Win32
		{53784BC1-A8BC-4AC8-8A3E-158D6807345A}.DebugNativeOnly|Win32.Build.0 = DebugNativeOnly|Win32
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
		{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}.ReleaseManagedOnly|Win32.Build.0 = Release|Any CPU
		{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}.ReleaseManagedOnly|x64.ActiveCfg = Release|Any CPU
		{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}.ReleaseManagedOnly|x64.Build.0 = Release|Any CPU
		{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}.ReleaseNativeOnly|Any CPU.ActiveCfg = Release|Any CPU
		{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}.ReleaseNativeOnly|Mixed Platforms.ActiveCfg = Release|Any CPU
		{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}.ReleaseNativeOnly|Win32.ActiveCfg = Release|Any CPU
		{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}.ReleaseNativeOnly|x64.ActiveCfg = Release|Any CPU
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|Any CPU.ActiveCfg = Debug|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|Any CPU.Build.0 = Debug|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|Mixed Platforms.Build.0 = Debug|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|Win32.ActiveCfg = Debug|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|Win32.Build.0 = Debug|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|x64.ActiveCfg = Debug|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|x64.Build.0 = Debug|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugManagedOnly|Any CPU.ActiveCfg = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugManagedOnly|Mixed Platforms.ActiveCfg = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugManagedOnly|Win32.ActiveCfg = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugManagedOnly|x64.ActiveCfg = DebugNativeOnly|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|Any CPU.ActiveCfg = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|Any CPU.Build.0 = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|Mixed Platforms.ActiveCfg = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|Mixed Platforms.Build.0 = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|Win32.ActiveCfg = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|Win32.Build.0 = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|x64.ActiveCfg = DebugNativeOnly|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|x64.Build.0 = DebugNativeOnly|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|Any CPU.ActiveCfg = Release|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|Any CPU.Build.0 = Release|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|Mixed Platforms.ActiveCfg = Release|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|Mixed Platforms.Build.0 = Release|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|Win32.ActiveCfg = Release|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|Win32.Build.0 = Release|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|x64.ActiveCfg = Release|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|x64.Build.0 = Release|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseManagedOnly|Any CPU.ActiveCfg = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseManagedOnly|Mixed Platforms.ActiveCfg = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseManagedOnly|Win32.ActiveCfg = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseManagedOnly|x64.ActiveCfg = ReleaseNativeOnly|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|Any CPU.ActiveCfg = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|Any CPU.Build.0 = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|Mixed Platforms.ActiveCfg = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|Mixed Platforms.Build.0 = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|Win32.ActiveCfg = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|Win32.Build.0 = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|x64.ActiveCfg = ReleaseNativeOnly|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|x64.Build.0 = ReleaseNativeOnly|x64
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|Win32.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|Win32.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|x64.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|x64.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugManagedOnly|Any CPU.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugManagedOnly|Any CPU.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugManagedOnly|Mixed Platforms.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugManagedOnly|Mixed Platforms.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugManagedOnly|Win32.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugManagedOnly|Win32.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugManagedOnly|x64.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugManagedOnly|x64.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugNativeOnly|Any CPU.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugNativeOnly|Mixed Platforms.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugNativeOnly|Win32.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugNativeOnly|x64.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|Any CPU.Build.0 = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|Mixed Platforms.Build.0 = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|Win32.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|Win32.Build.0 = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|x64.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|x64.Build.0 = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseManagedOnly|Any CPU.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseManagedOnly|Any CPU.Build.0 = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseManagedOnly|Mixed Platforms.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseManagedOnly|Mixed Platforms.Build.0 = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseManagedOnly|Win32.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseManagedOnly|Win32.Build.0 = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseManagedOnly|x64.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseManagedOnly|x64.Build.0 = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseNativeOnly|Any CPU.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseNativeOnly|Mixed Platforms.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseNativeOnly|Win32.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseNativeOnly|x64.ActiveCfg = Release|Any CPU
	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
EndGlobal







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





292
293
294
295
296
297
298
















































































299
300
301
302
303
		{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}.ReleaseManagedOnly|Win32.Build.0 = Release|Any CPU
		{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}.ReleaseManagedOnly|x64.ActiveCfg = Release|Any CPU
		{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}.ReleaseManagedOnly|x64.Build.0 = Release|Any CPU
		{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}.ReleaseNativeOnly|Any CPU.ActiveCfg = Release|Any CPU
		{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}.ReleaseNativeOnly|Mixed Platforms.ActiveCfg = Release|Any CPU
		{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}.ReleaseNativeOnly|Win32.ActiveCfg = Release|Any CPU
		{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}.ReleaseNativeOnly|x64.ActiveCfg = Release|Any CPU
















































































	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
EndGlobal
Changes to SQLite.NET.2010.sln.
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "testlinq.2010", "testlinq\testlinq.2010.csproj", "{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}"
	ProjectSection(ProjectDependencies) = postProject
		{AC139952-261A-4463-B6FA-AEBC25283A66} = {AC139952-261A-4463-B6FA-AEBC25283A66}
		{E6BF9F74-58E2-413B-A7CE-EA653ECB728D} = {E6BF9F74-58E2-413B-A7CE-EA653ECB728D}
	EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SQLite.Interop.Static.2010", "SQLite.Interop\SQLite.Interop.Static.2010.vcxproj", "{490CBC51-A3B2-4397-89F9-16E858DCB4F8}"
	ProjectSection(ProjectDependencies) = postProject
		{AC139952-261A-4463-B6FA-AEBC25284A66} = {AC139952-261A-4463-B6FA-AEBC25284A66}
	EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Installer.2010", "tools\install\Installer.2010.csproj", "{A41FE2A5-07AD-4CE7-B836-1544634816F5}"
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|Any CPU = Debug|Any CPU
		Debug|Mixed Platforms = Debug|Mixed Platforms
		Debug|Win32 = Debug|Win32
		Debug|x64 = Debug|x64
		DebugNativeOnly|Any CPU = DebugNativeOnly|Any CPU







<
<
<
<
<
<
<







26
27
28
29
30
31
32







33
34
35
36
37
38
39
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "testlinq.2010", "testlinq\testlinq.2010.csproj", "{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}"
	ProjectSection(ProjectDependencies) = postProject
		{AC139952-261A-4463-B6FA-AEBC25283A66} = {AC139952-261A-4463-B6FA-AEBC25283A66}
		{E6BF9F74-58E2-413B-A7CE-EA653ECB728D} = {E6BF9F74-58E2-413B-A7CE-EA653ECB728D}
	EndProjectSection
EndProject







Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|Any CPU = Debug|Any CPU
		Debug|Mixed Platforms = Debug|Mixed Platforms
		Debug|Win32 = Debug|Win32
		Debug|x64 = Debug|x64
		DebugNativeOnly|Any CPU = DebugNativeOnly|Any CPU
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
		{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}.ReleaseNativeOnly|Any CPU.Build.0 = Release|Any CPU
		{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}.ReleaseNativeOnly|Mixed Platforms.ActiveCfg = Release|Any CPU
		{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}.ReleaseNativeOnly|Mixed Platforms.Build.0 = Release|Any CPU
		{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}.ReleaseNativeOnly|Win32.ActiveCfg = Release|Any CPU
		{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}.ReleaseNativeOnly|Win32.Build.0 = Release|Any CPU
		{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}.ReleaseNativeOnly|x64.ActiveCfg = Release|Any CPU
		{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}.ReleaseNativeOnly|x64.Build.0 = Release|Any CPU
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|Any CPU.ActiveCfg = Debug|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|Any CPU.Build.0 = Debug|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|Mixed Platforms.Build.0 = Debug|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|Win32.ActiveCfg = Debug|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|Win32.Build.0 = Debug|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|x64.ActiveCfg = Debug|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Debug|x64.Build.0 = Debug|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|Any CPU.ActiveCfg = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|Any CPU.Build.0 = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|Mixed Platforms.ActiveCfg = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|Mixed Platforms.Build.0 = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|Win32.ActiveCfg = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|Win32.Build.0 = DebugNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|x64.ActiveCfg = DebugNativeOnly|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.DebugNativeOnly|x64.Build.0 = DebugNativeOnly|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|Any CPU.ActiveCfg = Release|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|Any CPU.Build.0 = Release|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|Mixed Platforms.ActiveCfg = Release|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|Mixed Platforms.Build.0 = Release|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|Win32.ActiveCfg = Release|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|Win32.Build.0 = Release|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|x64.ActiveCfg = Release|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.Release|x64.Build.0 = Release|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|Any CPU.ActiveCfg = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|Any CPU.Build.0 = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|Mixed Platforms.ActiveCfg = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|Mixed Platforms.Build.0 = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|Win32.ActiveCfg = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|Win32.Build.0 = ReleaseNativeOnly|Win32
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|x64.ActiveCfg = ReleaseNativeOnly|x64
		{490CBC51-A3B2-4397-89F9-16E858DCB4F8}.ReleaseNativeOnly|x64.Build.0 = ReleaseNativeOnly|x64
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|Win32.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|Win32.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|x64.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Debug|x64.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugNativeOnly|Any CPU.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugNativeOnly|Any CPU.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugNativeOnly|Mixed Platforms.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugNativeOnly|Mixed Platforms.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugNativeOnly|Win32.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugNativeOnly|Win32.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugNativeOnly|x64.ActiveCfg = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.DebugNativeOnly|x64.Build.0 = Debug|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|Any CPU.Build.0 = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|Mixed Platforms.Build.0 = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|Win32.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|Win32.Build.0 = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|x64.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.Release|x64.Build.0 = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseNativeOnly|Any CPU.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseNativeOnly|Any CPU.Build.0 = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseNativeOnly|Mixed Platforms.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseNativeOnly|Mixed Platforms.Build.0 = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseNativeOnly|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseNativeOnly|Win32.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseNativeOnly|Win32.Build.0 = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseNativeOnly|x64.ActiveCfg = Release|Any CPU
		{A41FE2A5-07AD-4CE7-B836-1544634816F5}.ReleaseNativeOnly|x64.Build.0 = Release|Any CPU
	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
EndGlobal







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





270
271
272
273
274
275
276




































































277
278
279
280
281
		{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}.ReleaseNativeOnly|Any CPU.Build.0 = Release|Any CPU
		{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}.ReleaseNativeOnly|Mixed Platforms.ActiveCfg = Release|Any CPU
		{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}.ReleaseNativeOnly|Mixed Platforms.Build.0 = Release|Any CPU
		{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}.ReleaseNativeOnly|Win32.ActiveCfg = Release|Any CPU
		{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}.ReleaseNativeOnly|Win32.Build.0 = Release|Any CPU
		{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}.ReleaseNativeOnly|x64.ActiveCfg = Release|Any CPU
		{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}.ReleaseNativeOnly|x64.Build.0 = Release|Any CPU




































































	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
EndGlobal
Deleted SQLite.nuspec.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="utf-8"?>
<package>
  <metadata>
    <id>System.Data.SQLite</id>
    <title>System.Data.SQLite (x86)</title>
    <version>1.0.76.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>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<












































Deleted SQLite.x64.nuspec.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="utf-8"?>
<package>
  <metadata>
    <id>System.Data.SQLite.x64</id>
    <version>1.0.76.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>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










































Deleted SQLite.x86.nuspec.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="utf-8"?>
<package>
  <metadata>
    <id>System.Data.SQLite.x86</id>
    <version>1.0.76.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>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










































Changes to Setup/SQLite.iss.
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
AppPublisherURL={#AppURL}
AppSupportURL={#AppURL}
AppUpdatesURL={#AppURL}
AppVerName=System.Data.SQLite v{#AppVersion}
AppVersion={#AppVersion}
AppComments=The ADO.NET adapter for the SQLite database engine.
AppReadmeFile={app}\readme.htm
DefaultDirName={pf}\System.Data.SQLite\{#Year}
DefaultGroupName=System.Data.SQLite\{#Year}
OutputBaseFilename=sqlite-{#Framework}-{#OutputConfiguration}-{#AppProcessor}-{#Year}-{#AppVersion}
OutputManifestFile=sqlite-{#Framework}-{#OutputConfiguration}-{#AppProcessor}-{#Year}-{#AppVersion}-manifest.txt
SetupLogging=true
UninstallFilesDir={app}\uninstall
VersionInfoVersion={#AppVersion}
ExtraDiskSpaceRequired=2097152
ChangesEnvironment=true







|
|







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
AppPublisherURL={#AppURL}
AppSupportURL={#AppURL}
AppUpdatesURL={#AppURL}
AppVerName=System.Data.SQLite v{#AppVersion}
AppVersion={#AppVersion}
AppComments=The ADO.NET adapter for the SQLite database engine.
AppReadmeFile={app}\readme.htm
DefaultDirName={pf}\System.Data.SQLite
DefaultGroupName=System.Data.SQLite
OutputBaseFilename=sqlite-{#Framework}-{#OutputConfiguration}-{#AppProcessor}-{#Year}-{#AppVersion}
OutputManifestFile=sqlite-{#Framework}-{#OutputConfiguration}-{#AppProcessor}-{#Year}-{#AppVersion}-manifest.txt
SetupLogging=true
UninstallFilesDir={app}\uninstall
VersionInfoVersion={#AppVersion}
ExtraDiskSpaceRequired=2097152
ChangesEnvironment=true
Changes to Setup/archive.bat.
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85

:skip_mungeVersion

%_VECHO% Version = '%VERSION%'

CALL :fn_ResetErrorLevel

%_ECHO% IF NOT EXIST Setup\Output (
  MKDIR Setup\Output

  IF ERRORLEVEL 1 (
    ECHO Could not create directory "Setup\Output".
    GOTO errors
  )
)

%_ECHO% zip.exe -v -r Setup\Output\sqlite-netFx-source-%VERSION%.zip * -x @exclude_src.txt

IF ERRORLEVEL 1 (
  ECHO Failed to archive source files.
  GOTO errors
)

%_ECHO% POPD







<
<
<
<
<
<
<
<
<
|







62
63
64
65
66
67
68









69
70
71
72
73
74
75
76

:skip_mungeVersion

%_VECHO% Version = '%VERSION%'

CALL :fn_ResetErrorLevel










%_ECHO% zip.exe -r Setup\Output\sqlite-netFx-source-%VERSION%.zip * -x@exclude_src.txt

IF ERRORLEVEL 1 (
  ECHO Failed to archive source files.
  GOTO errors
)

%_ECHO% POPD
Changes to Setup/bake_all.bat.
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
%_AECHO% Running %0 %*

SET TOOLS=%~dp0
SET TOOLS=%TOOLS:~0,-1%

%_VECHO% Tools = '%TOOLS%'

CALL :fn_ResetErrorLevel

%_ECHO% CALL "%TOOLS%\vsSp.bat"

IF ERRORLEVEL 1 (
  ECHO Could not detect Visual Studio.
  GOTO errors
)

%_ECHO% CALL "%TOOLS%\set_common.bat"

IF ERRORLEVEL 1 (
  ECHO Could not set common variables.
  GOTO errors
)

IF NOT DEFINED BAKE_CONFIGURATIONS (
  SET BAKE_CONFIGURATIONS=Release
)

%_VECHO% BakeConfigurations = '%BAKE_CONFIGURATIONS%'

IF NOT DEFINED PROCESSORS (
  SET PROCESSORS=x86
)

%_VECHO% Processors = '%PROCESSORS%'

IF NOT DEFINED YEARS (
  SET YEARS=2008
)

%_VECHO% Years = '%YEARS%'

FOR %%C IN (%BAKE_CONFIGURATIONS%) DO (
  FOR %%P IN (%PROCESSORS%) DO (
    FOR %%Y IN (%YEARS%) DO (
      %_ECHO% CALL "%TOOLS%\set_%%C_%%P_%%Y.bat"

      IF ERRORLEVEL 1 (
        ECHO Could not set variables for %%C/%%P/%%Y.
        GOTO errors







<
<














|
|


|













|







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
%_AECHO% Running %0 %*

SET TOOLS=%~dp0
SET TOOLS=%TOOLS:~0,-1%

%_VECHO% Tools = '%TOOLS%'



%_ECHO% CALL "%TOOLS%\vsSp.bat"

IF ERRORLEVEL 1 (
  ECHO Could not detect Visual Studio.
  GOTO errors
)

%_ECHO% CALL "%TOOLS%\set_common.bat"

IF ERRORLEVEL 1 (
  ECHO Could not set common variables.
  GOTO errors
)

IF NOT DEFINED CONFIGURATIONS (
  SET CONFIGURATIONS=Release
)

%_VECHO% Configurations = '%CONFIGURATIONS%'

IF NOT DEFINED PROCESSORS (
  SET PROCESSORS=x86
)

%_VECHO% Processors = '%PROCESSORS%'

IF NOT DEFINED YEARS (
  SET YEARS=2008
)

%_VECHO% Years = '%YEARS%'

FOR %%C IN (%CONFIGURATIONS%) DO (
  FOR %%P IN (%PROCESSORS%) DO (
    FOR %%Y IN (%YEARS%) DO (
      %_ECHO% CALL "%TOOLS%\set_%%C_%%P_%%Y.bat"

      IF ERRORLEVEL 1 (
        ECHO Could not set variables for %%C/%%P/%%Y.
        GOTO errors
Changes to Setup/build.bat.
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

SET TOOLS=%~dp0
SET TOOLS=%TOOLS:\\=\%

%_VECHO% Tools = '%TOOLS%'

IF EXIST "%TOOLS%\set_%CONFIGURATION%_%PLATFORM%.bat" (
  CALL :fn_ResetErrorLevel

  %_AECHO% Running "%TOOLS%\set_%CONFIGURATION%_%PLATFORM%.bat"...
  %_ECHO% CALL "%TOOLS%\set_%CONFIGURATION%_%PLATFORM%.bat"

  IF ERRORLEVEL 1 (
    ECHO File "%TOOLS%\set_%CONFIGURATION%_%PLATFORM%.bat" failed.
    GOTO errors
  )







<
<







47
48
49
50
51
52
53


54
55
56
57
58
59
60

SET TOOLS=%~dp0
SET TOOLS=%TOOLS:\\=\%

%_VECHO% Tools = '%TOOLS%'

IF EXIST "%TOOLS%\set_%CONFIGURATION%_%PLATFORM%.bat" (


  %_AECHO% Running "%TOOLS%\set_%CONFIGURATION%_%PLATFORM%.bat"...
  %_ECHO% CALL "%TOOLS%\set_%CONFIGURATION%_%PLATFORM%.bat"

  IF ERRORLEVEL 1 (
    ECHO File "%TOOLS%\set_%CONFIGURATION%_%PLATFORM%.bat" failed.
    GOTO errors
  )
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
IF DEFINED NETFX40ONLY (
  %_AECHO% Forcing the use of the .NET Framework 4.0...
  SET YEAR=2010
  SET FRAMEWORKDIR=%windir%\Microsoft.NET\Framework\v4.0.30319
  GOTO skip_netFxCheck
)

IF DEFINED FRAMEWORKDIR (
  IF NOT EXIST "%FRAMEWORKDIR%" (
    CALL :fn_UnsetVariable FRAMEWORKDIR
  )
)

IF DEFINED FRAMEWORKDIR (
  IF NOT EXIST "%FRAMEWORKDIR%\csc.exe" (
    CALL :fn_UnsetVariable FRAMEWORKDIR
  )
)

IF NOT DEFINED FRAMEWORKDIR (
  %_AECHO% Checking for the .NET Framework 4.0...
  SET YEAR=2010
  SET FRAMEWORKDIR=%windir%\Microsoft.NET\Framework\v4.0.30319
)

IF NOT EXIST "%FRAMEWORKDIR%" (







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







77
78
79
80
81
82
83












84
85
86
87
88
89
90
IF DEFINED NETFX40ONLY (
  %_AECHO% Forcing the use of the .NET Framework 4.0...
  SET YEAR=2010
  SET FRAMEWORKDIR=%windir%\Microsoft.NET\Framework\v4.0.30319
  GOTO skip_netFxCheck
)













IF NOT DEFINED FRAMEWORKDIR (
  %_AECHO% Checking for the .NET Framework 4.0...
  SET YEAR=2010
  SET FRAMEWORKDIR=%windir%\Microsoft.NET\Framework\v4.0.30319
)

IF NOT EXIST "%FRAMEWORKDIR%" (
Changes to Setup/build_all.bat.
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
%_AECHO% Running %0 %*

SET TOOLS=%~dp0
SET TOOLS=%TOOLS:~0,-1%

%_VECHO% Tools = '%TOOLS%'

CALL :fn_ResetErrorLevel

%_ECHO% CALL "%TOOLS%\vsSp.bat"

IF ERRORLEVEL 1 (
  ECHO Could not detect Visual Studio.
  GOTO errors
)

%_ECHO% CALL "%TOOLS%\set_common.bat"

IF ERRORLEVEL 1 (
  ECHO Could not set common variables.
  GOTO errors
)

IF NOT DEFINED BUILD_CONFIGURATIONS (
  SET BUILD_CONFIGURATIONS=Release
)

%_VECHO% BuildConfigurations = '%BUILD_CONFIGURATIONS%'

IF NOT DEFINED PLATFORMS (
  SET PLATFORMS=Win32
)

%_VECHO% Platforms = '%PLATFORMS%'

IF NOT DEFINED YEARS (
  SET YEARS=2008
)

%_VECHO% Years = '%YEARS%'

FOR %%C IN (%BUILD_CONFIGURATIONS%) DO (
  FOR %%P IN (%PLATFORMS%) DO (
    FOR %%Y IN (%YEARS%) DO (
      %_ECHO% CALL "%TOOLS%\set_%%Y.bat"

      IF ERRORLEVEL 1 (
        ECHO Could not set variables for %%Y.
        GOTO errors







<
<














|
|


|













|







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
%_AECHO% Running %0 %*

SET TOOLS=%~dp0
SET TOOLS=%TOOLS:~0,-1%

%_VECHO% Tools = '%TOOLS%'



%_ECHO% CALL "%TOOLS%\vsSp.bat"

IF ERRORLEVEL 1 (
  ECHO Could not detect Visual Studio.
  GOTO errors
)

%_ECHO% CALL "%TOOLS%\set_common.bat"

IF ERRORLEVEL 1 (
  ECHO Could not set common variables.
  GOTO errors
)

IF NOT DEFINED CONFIGURATIONS (
  SET CONFIGURATIONS=Release
)

%_VECHO% Configurations = '%CONFIGURATIONS%'

IF NOT DEFINED PLATFORMS (
  SET PLATFORMS=Win32
)

%_VECHO% Platforms = '%PLATFORMS%'

IF NOT DEFINED YEARS (
  SET YEARS=2008
)

%_VECHO% Years = '%YEARS%'

FOR %%C IN (%CONFIGURATIONS%) DO (
  FOR %%P IN (%PLATFORMS%) DO (
    FOR %%Y IN (%YEARS%) DO (
      %_ECHO% CALL "%TOOLS%\set_%%Y.bat"

      IF ERRORLEVEL 1 (
        ECHO Could not set variables for %%Y.
        GOTO errors
Changes to Setup/build_ce.bat.
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
%_AECHO% Running %0 %*

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

%_ECHO% CALL "%TOOLS%\build_all.bat"

IF ERRORLEVEL 1 (
  ECHO Failed to build PocketPC binaries.
  GOTO errors
)








|
|





<
<







19
20
21
22
23
24
25
26
27
28
29
30
31
32


33
34
35
36
37
38
39
%_AECHO% Running %0 %*

SET TOOLS=%~dp0
SET TOOLS=%TOOLS:~0,-1%

%_VECHO% Tools = '%TOOLS%'

SET CONFIGURATIONS=Release
SET CONFIGURATIONSUFFIX=Compact
SET PLATFORMS="Pocket PC 2003 (ARMV4)"
SET PROCESSORS=arm
SET YEARS=2008
SET BASE_PLATFORM=PocketPC



%_ECHO% CALL "%TOOLS%\build_all.bat"

IF ERRORLEVEL 1 (
  ECHO Failed to build PocketPC binaries.
  GOTO errors
)

Deleted Setup/clean.bat.
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
@ECHO OFF

::
:: clean.bat --
::
:: Build Cleaning Tool
::
:: Written by Joe Mistachkin.
:: Released to the public domain, use at your own risk!
::

SETLOCAL

REM SET _ECHO=ECHO
IF NOT DEFINED _AECHO (SET _AECHO=REM)
IF NOT DEFINED _CECHO (SET _CECHO=REM)
IF NOT DEFINED _VECHO (SET _VECHO=REM)

%_AECHO% Running %0 %*

SET DUMMY2=%1

IF DEFINED DUMMY2 (
  GOTO usage
)

SET SOURCE=%~dp0\..
SET SOURCE=%SOURCE:\\=\%

%_VECHO% Source = '%SOURCE%'
%_VECHO% Temp = '%TEMP%'

IF NOT DEFINED TEMP (
  ECHO The TEMP environment variable must be set first.
  GOTO usage
)

IF NOT EXIST "%TEMP%" (
  ECHO The TEMP directory, "%TEMP%", does not exist.
  GOTO usage
)

IF DEFINED CLEANDIRS GOTO skip_cleanDirs

SET CLEANDIRS=bin obj Doc\Output Membership\bin Membership\obj Setup\Output
SET CLEANDIRS=%CLEANDIRS% SQLite.Designer\bin SQLite.Designer\obj
SET CLEANDIRS=%CLEANDIRS% SQLite.Interop\bin SQLite.Interop\obj
SET CLEANDIRS=%CLEANDIRS% System.Data.SQLite\bin System.Data.SQLite\obj
SET CLEANDIRS=%CLEANDIRS% System.Data.SQLite.Linq\bin System.Data.SQLite.Linq\obj
SET CLEANDIRS=%CLEANDIRS% test\bin test\obj testce\bin testce\obj testlinq\bin
SET CLEANDIRS=%CLEANDIRS% testlinq\obj tools\install\bin tools\install\obj

:skip_cleanDirs

%_VECHO% CleanDirs = '%CLEANDIRS%'

CALL :fn_ResetErrorLevel

%_AECHO%.

FOR %%D IN (%CLEANDIRS%) DO (
  IF EXIST "%SOURCE%\%%D" (
    %_ECHO% RMDIR /S /Q "%SOURCE%\%%D"

    IF ERRORLEVEL 1 (
      ECHO Could not remove directory "%SOURCE%\%%D".
      ECHO.
      GOTO errors
    ) ELSE (
      %_AECHO% Removed directory "%SOURCE%\%%D".
      %_AECHO%.
    )
  ) ELSE (
    %_AECHO% Directory "%SOURCE%\%%D" does not exist.
    %_AECHO%.
  )
)

IF EXIST "%SOURCE%\*.nupkg" (
  %_ECHO% DEL /Q "%SOURCE%\*.nupkg"

  IF ERRORLEVEL 1 (
    ECHO Could not delete "%SOURCE%\*.nupkg".
    ECHO.
    GOTO errors
  ) ELSE (
    %_AECHO% Deleted "%SOURCE%\*.nupkg".
    %_AECHO%.
  )
) ELSE (
  %_AECHO% No files matching "%SOURCE%\*.nupkg" exist.
  %_AECHO%.
)

IF EXIST "%SOURCE%\Doc\SQLite.NET.chw" (
  %_ECHO% DEL /Q "%SOURCE%\Doc\SQLite.NET.chw"

  IF ERRORLEVEL 1 (
    ECHO Could not delete "%SOURCE%\Doc\SQLite.NET.chw".
    ECHO.
    GOTO errors
  ) ELSE (
    %_AECHO% Deleted "%SOURCE%\Doc\SQLite.NET.chw".
    %_AECHO%.
  )
) ELSE (
  %_AECHO% No files matching "%SOURCE%\Doc\SQLite.NET.chw" exist.
  %_AECHO%.
)

IF EXIST "%SOURCE%\Externals\Eagle\bin\sqlite3.*" (
  %_ECHO% DEL /Q "%SOURCE%\Externals\Eagle\bin\sqlite3.*"

  IF ERRORLEVEL 1 (
    ECHO Could not delete "%SOURCE%\Externals\Eagle\bin\sqlite3.*".
    ECHO.
    GOTO errors
  ) ELSE (
    %_AECHO% Deleted "%SOURCE%\Externals\Eagle\bin\sqlite3.*".
    %_AECHO%.
  )
) ELSE (
  %_AECHO% No files matching "%SOURCE%\Externals\Eagle\bin\sqlite3.*" exist.
  %_AECHO%.
)

IF EXIST "%SOURCE%\Externals\Eagle\bin\SQLite.Interop.*" (
  %_ECHO% DEL /Q "%SOURCE%\Externals\Eagle\bin\SQLite.Interop.*"

  IF ERRORLEVEL 1 (
    ECHO Could not delete "%SOURCE%\Externals\Eagle\bin\SQLite.Interop.*".
    ECHO.
    GOTO errors
  ) ELSE (
    %_AECHO% Deleted "%SOURCE%\Externals\Eagle\bin\SQLite.Interop.*".
    %_AECHO%.
  )
) ELSE (
  %_AECHO% No files matching "%SOURCE%\Externals\Eagle\bin\SQLite.Interop.*" exist.
  %_AECHO%.
)

IF EXIST "%SOURCE%\Externals\Eagle\bin\System.Data.SQLite.*" (
  %_ECHO% DEL /Q "%SOURCE%\Externals\Eagle\bin\System.Data.SQLite.*"

  IF ERRORLEVEL 1 (
    ECHO Could not delete "%SOURCE%\Externals\Eagle\bin\System.Data.SQLite.*".
    ECHO.
    GOTO errors
  ) ELSE (
    %_AECHO% Deleted "%SOURCE%\Externals\Eagle\bin\System.Data.SQLite.*".
    %_AECHO%.
  )
) ELSE (
  %_AECHO% No files matching "%SOURCE%\Externals\Eagle\bin\System.Data.SQLite.*" exist.
  %_AECHO%.
)

IF EXIST "%SOURCE%\Externals\Eagle\bin\System.Data.SQLite.Linq.*" (
  %_ECHO% DEL /Q "%SOURCE%\Externals\Eagle\bin\System.Data.SQLite.Linq.*"

  IF ERRORLEVEL 1 (
    ECHO Could not delete "%SOURCE%\Externals\Eagle\bin\System.Data.SQLite.Linq.*".
    ECHO.
    GOTO errors
  ) ELSE (
    %_AECHO% Deleted "%SOURCE%\Externals\Eagle\bin\System.Data.SQLite.Linq.*".
    %_AECHO%.
  )
) ELSE (
  %_AECHO% No files matching "%SOURCE%\Externals\Eagle\bin\System.Data.SQLite.Linq.*" exist.
  %_AECHO%.
)

IF EXIST "%TEMP%\EagleShell.exe.test.*.log" (
  %_ECHO% DEL /Q "%TEMP%\EagleShell.exe.test.*.log"

  IF ERRORLEVEL 1 (
    ECHO Could not delete "%TEMP%\EagleShell.exe.test.*.log".
    ECHO.
    GOTO errors
  ) ELSE (
    %_AECHO% Deleted "%TEMP%\EagleShell.exe.test.*.log".
    %_AECHO%.
  )
) ELSE (
  %_AECHO% No files matching "%TEMP%\EagleShell.exe.test.*.log" exist.
  %_AECHO%.
)

IF EXIST "%TEMP%\mono.exe.test.*.log" (
  %_ECHO% DEL /Q "%TEMP%\mono.exe.test.*.log"

  IF ERRORLEVEL 1 (
    ECHO Could not delete "%TEMP%\mono.exe.test.*.log".
    ECHO.
    GOTO errors
  ) ELSE (
    %_AECHO% Deleted "%TEMP%\mono.exe.test.*.log".
    %_AECHO%.
  )
) ELSE (
  %_AECHO% No files matching "%TEMP%\mono.exe.test.*.log" exist.
  %_AECHO%.
)

IF EXIST "%TEMP%\tclsh*.exe.test.*.log" (
  %_ECHO% DEL /Q "%TEMP%\tclsh*.exe.test.*.log"

  IF ERRORLEVEL 1 (
    ECHO Could not delete "%TEMP%\tclsh*.exe.test.*.log".
    ECHO.
    GOTO errors
  ) ELSE (
    %_AECHO% Deleted "%TEMP%\tclsh*.exe.test.*.log".
    %_AECHO%.
  )
) ELSE (
  %_AECHO% No files matching "%TEMP%\tclsh*.exe.test.*.log" exist.
  %_AECHO%.
)

GOTO no_errors

:fn_ResetErrorLevel
  VERIFY > NUL
  GOTO :EOF

:fn_SetErrorLevel
  VERIFY MAYBE 2> NUL
  GOTO :EOF

:usage
  ECHO.
  ECHO Usage: %~nx0
  ECHO.
  ECHO The TEMP environment variable must be set to the full path of the existing
  ECHO directory used to store temporary files.
  GOTO errors

:errors
  CALL :fn_SetErrorLevel
  ENDLOCAL
  ECHO.
  ECHO Clean failure, errors were encountered.
  GOTO end_of_file

:no_errors
  CALL :fn_ResetErrorLevel
  ENDLOCAL
  ECHO.
  ECHO Clean success, no errors were encountered.
  GOTO end_of_file

:end_of_file
%_ECHO% EXIT /B %ERRORLEVEL%
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
































































































































































































































































































































































































































































































































Changes to Setup/release.bat.
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
%_VECHO% Year = '%YEAR%'

SET BASE_CONFIGURATION=%CONFIGURATION%
SET BASE_CONFIGURATION=%BASE_CONFIGURATION:ManagedOnly=%
SET BASE_CONFIGURATION=%BASE_CONFIGURATION:NativeOnly=%

%_VECHO% BaseConfiguration = '%BASE_CONFIGURATION%'
%_VECHO% BaseConfigurationSuffix = '%BASE_CONFIGURATIONSUFFIX%'

IF NOT DEFINED BASE_PLATFORM (
  CALL :fn_SetVariable BASE_PLATFORM PLATFORM
)

%_VECHO% BasePlatform = '%BASE_PLATFORM%'

IF NOT DEFINED TYPE (
  IF /I "%CONFIGURATION%" == "%BASE_CONFIGURATION%" (
    SET TYPE=%TYPE_PREFIX%binary-bundle
  ) ELSE (
    SET TYPE=%TYPE_PREFIX%binary
  )
)

%_VECHO% Type = '%TYPE%'

CALL :fn_ResetErrorLevel

%_ECHO% CALL "%TOOLS%\set_common.bat"

IF ERRORLEVEL 1 (
  ECHO Could not set common variables.
  GOTO errors
)








<









|

|





<
<







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
%_VECHO% Year = '%YEAR%'

SET BASE_CONFIGURATION=%CONFIGURATION%
SET BASE_CONFIGURATION=%BASE_CONFIGURATION:ManagedOnly=%
SET BASE_CONFIGURATION=%BASE_CONFIGURATION:NativeOnly=%

%_VECHO% BaseConfiguration = '%BASE_CONFIGURATION%'


IF NOT DEFINED BASE_PLATFORM (
  CALL :fn_SetVariable BASE_PLATFORM PLATFORM
)

%_VECHO% BasePlatform = '%BASE_PLATFORM%'

IF NOT DEFINED TYPE (
  IF /I "%CONFIGURATION%" == "%BASE_CONFIGURATION%" (
    SET TYPE=binary-bundle
  ) ELSE (
    SET TYPE=binary
  )
)

%_VECHO% Type = '%TYPE%'



%_ECHO% CALL "%TOOLS%\set_common.bat"

IF ERRORLEVEL 1 (
  ECHO Could not set common variables.
  GOTO errors
)

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

:skip_mungeVersion

%_VECHO% Version = '%VERSION%'

CALL :fn_ResetErrorLevel

%_ECHO% IF NOT EXIST Setup\Output (
  MKDIR Setup\Output

  IF ERRORLEVEL 1 (
    ECHO Could not create directory "Setup\Output".
    GOTO errors
  )
)

IF DEFINED BASE_CONFIGURATIONSUFFIX (
  %_ECHO% zip.exe -v -j -r "Setup\Output\sqlite-%FRAMEWORK%-%TYPE%-%BASE_PLATFORM%-%YEAR%-%VERSION%.zip" "bin\%YEAR%\%BASE_CONFIGURATION%%BASE_CONFIGURATIONSUFFIX%\bin" -x @exclude_bin.txt
) ELSE (
  %_ECHO% zip.exe -v -j -r "Setup\Output\sqlite-%FRAMEWORK%-%TYPE%-%BASE_PLATFORM%-%YEAR%-%VERSION%.zip" "bin\%YEAR%\%BASE_CONFIGURATION%\bin" -x @exclude_bin.txt
)

IF /I "%CONFIGURATION%" == "%BASE_CONFIGURATION%" (
  IF NOT DEFINED BASE_CONFIGURATIONSUFFIX (
    %_ECHO% zip -v -d "Setup\Output\sqlite-%FRAMEWORK%-%TYPE%-%BASE_PLATFORM%-%YEAR%-%VERSION%.zip" SQLite.Interop.*
  )
)

%_ECHO% zip.exe -v -j -r "Setup\Output\sqlite-%FRAMEWORK%-%TYPE%-%BASE_PLATFORM%-%YEAR%-%VERSION%.zip" "bin\%YEAR%\%PLATFORM%\%CONFIGURATION%%CONFIGURATIONSUFFIX%" -x @exclude_bin.txt

IF ERRORLEVEL 1 (
  ECHO Failed to archive binary files.
  GOTO errors
)

%_ECHO% POPD







<
<
<
<
<
<
<
<
<
|
|

|



|
|



|







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

:skip_mungeVersion

%_VECHO% Version = '%VERSION%'

CALL :fn_ResetErrorLevel










IF DEFINED CONFIGURATIONSUFFIX (
  %_ECHO% zip.exe -j -r "Setup\Output\sqlite-%FRAMEWORK%-%TYPE%-%BASE_PLATFORM%-%YEAR%-%VERSION%.zip" "bin\%YEAR%\%BASE_CONFIGURATION%%CONFIGURATIONSUFFIX%\bin" -x @exclude_bin.txt
) ELSE (
  %_ECHO% zip.exe -j -r "Setup\Output\sqlite-%FRAMEWORK%-%TYPE%-%BASE_PLATFORM%-%YEAR%-%VERSION%.zip" "bin\%YEAR%\%BASE_CONFIGURATION%\bin" -x @exclude_bin.txt
)

IF /I "%CONFIGURATION%" == "%BASE_CONFIGURATION%" (
  IF NOT DEFINED CONFIGURATIONSUFFIX (
    %_ECHO% zip -d "Setup\Output\sqlite-%FRAMEWORK%-%TYPE%-%BASE_PLATFORM%-%YEAR%-%VERSION%.zip" SQLite.Interop.*
  )
)

%_ECHO% zip.exe -j -r "Setup\Output\sqlite-%FRAMEWORK%-%TYPE%-%BASE_PLATFORM%-%YEAR%-%VERSION%.zip" "bin\%YEAR%\%PLATFORM%\%CONFIGURATION%" -x @exclude_bin.txt

IF ERRORLEVEL 1 (
  ECHO Failed to archive binary files.
  GOTO errors
)

%_ECHO% POPD
Changes to Setup/release_all.bat.
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
%_AECHO% Running %0 %*

SET TOOLS=%~dp0
SET TOOLS=%TOOLS:~0,-1%

%_VECHO% Tools = '%TOOLS%'

CALL :fn_ResetErrorLevel

%_ECHO% CALL "%TOOLS%\vsSp.bat"

IF ERRORLEVEL 1 (
  ECHO Could not detect Visual Studio.
  GOTO errors
)

%_ECHO% CALL "%TOOLS%\set_common.bat"

IF ERRORLEVEL 1 (
  ECHO Could not set common variables.
  GOTO errors
)

IF NOT DEFINED RELEASE_CONFIGURATIONS (
  SET RELEASE_CONFIGURATIONS=Release
)

%_VECHO% ReleaseConfigurations = '%RELEASE_CONFIGURATIONS%'

IF NOT DEFINED PLATFORMS (
  SET PLATFORMS=Win32
)

%_VECHO% Platforms = '%PLATFORMS%'

IF NOT DEFINED YEARS (
  SET YEARS=2008
)

%_VECHO% Years = '%YEARS%'

FOR %%C IN (%RELEASE_CONFIGURATIONS%) DO (
  FOR %%P IN (%PLATFORMS%) DO (
    FOR %%Y IN (%YEARS%) DO (
      %_ECHO% CALL "%TOOLS%\release.bat" %%C %%P %%Y

      IF ERRORLEVEL 1 (
        ECHO Could not build release archive for %%C/%%P/%%Y.
        GOTO errors







<
<














|
|


|













|







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
%_AECHO% Running %0 %*

SET TOOLS=%~dp0
SET TOOLS=%TOOLS:~0,-1%

%_VECHO% Tools = '%TOOLS%'



%_ECHO% CALL "%TOOLS%\vsSp.bat"

IF ERRORLEVEL 1 (
  ECHO Could not detect Visual Studio.
  GOTO errors
)

%_ECHO% CALL "%TOOLS%\set_common.bat"

IF ERRORLEVEL 1 (
  ECHO Could not set common variables.
  GOTO errors
)

IF NOT DEFINED CONFIGURATIONS (
  SET CONFIGURATIONS=Release
)

%_VECHO% Configurations = '%CONFIGURATIONS%'

IF NOT DEFINED PLATFORMS (
  SET PLATFORMS=Win32
)

%_VECHO% Platforms = '%PLATFORMS%'

IF NOT DEFINED YEARS (
  SET YEARS=2008
)

%_VECHO% Years = '%YEARS%'

FOR %%C IN (%CONFIGURATIONS%) DO (
  FOR %%P IN (%PLATFORMS%) DO (
    FOR %%Y IN (%YEARS%) DO (
      %_ECHO% CALL "%TOOLS%\release.bat" %%C %%P %%Y

      IF ERRORLEVEL 1 (
        ECHO Could not build release archive for %%C/%%P/%%Y.
        GOTO errors
Changes to Setup/release_ce.bat.
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
%_AECHO% Running %0 %*

SET TOOLS=%~dp0
SET TOOLS=%TOOLS:~0,-1%

%_VECHO% Tools = '%TOOLS%'

SET RELEASE_CONFIGURATIONS=Release
SET BASE_CONFIGURATIONSUFFIX=Compact
SET PLATFORMS="Pocket PC 2003 (ARMV4)"
SET PROCESSORS=arm
SET YEARS=2008
SET BASE_PLATFORM=PocketPC
SET TYPE=binary

CALL :fn_ResetErrorLevel

%_ECHO% CALL "%TOOLS%\release_all.bat"

IF ERRORLEVEL 1 (
  ECHO Failed to build PocketPC release files.
  GOTO errors
)








|
|






<
<







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33


34
35
36
37
38
39
40
%_AECHO% Running %0 %*

SET TOOLS=%~dp0
SET TOOLS=%TOOLS:~0,-1%

%_VECHO% Tools = '%TOOLS%'

SET CONFIGURATIONS=Release
SET CONFIGURATIONSUFFIX=Compact
SET PLATFORMS="Pocket PC 2003 (ARMV4)"
SET PROCESSORS=arm
SET YEARS=2008
SET BASE_PLATFORM=PocketPC
SET TYPE=binary



%_ECHO% CALL "%TOOLS%\release_all.bat"

IF ERRORLEVEL 1 (
  ECHO Failed to build PocketPC release files.
  GOTO errors
)

Deleted Setup/release_static.bat.
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
@ECHO OFF

::
:: release_static.bat --
::
:: Static Binary Release Tool
::
:: Written by Joe Mistachkin.
:: Released to the public domain, use at your own risk!
::

SETLOCAL

REM SET _ECHO=ECHO
IF NOT DEFINED _AECHO (SET _AECHO=REM)
IF NOT DEFINED _CECHO (SET _CECHO=REM)
IF NOT DEFINED _VECHO (SET _VECHO=REM)

%_AECHO% Running %0 %*

SET TOOLS=%~dp0
SET TOOLS=%TOOLS:~0,-1%

%_VECHO% Tools = '%TOOLS%'

SET CONFIGURATIONSUFFIX=Static
SET TYPE_PREFIX=static-

CALL :fn_ResetErrorLevel

%_ECHO% CALL "%TOOLS%\release_all.bat"

IF ERRORLEVEL 1 (
  ECHO Failed to build static release files.
  GOTO errors
)

:fn_ResetErrorLevel
  VERIFY > NUL
  GOTO :EOF

:fn_SetErrorLevel
  VERIFY MAYBE 2> NUL
  GOTO :EOF

:usage
  ECHO.
  ECHO Usage: %~nx0
  ECHO.
  GOTO errors

:errors
  CALL :fn_SetErrorLevel
  ENDLOCAL
  ECHO.
  ECHO Release failure, errors were encountered.
  GOTO end_of_file

:no_errors
  CALL :fn_ResetErrorLevel
  ENDLOCAL
  ECHO.
  ECHO Release success, no errors were encountered.
  GOTO end_of_file

:end_of_file
%_ECHO% EXIT /B %ERRORLEVEL%
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






































































































































Changes to Setup/set_Release.bat.
1
2
3
4
5
6
7
8
9
10
@ECHO OFF

::
:: set_Release.bat --
::
:: Written by Joe Mistachkin.
:: Released to the public domain, use at your own risk!
::

REM SET MSBUILD_ARGS=/p:TargetFrameworkVersion=v3.5 /p:PlatformToolset=v100









|
1
2
3
4
5
6
7
8
9
10
@ECHO OFF

::
:: set_Release.bat --
::
:: Written by Joe Mistachkin.
:: Released to the public domain, use at your own risk!
::

REM SET MSBUILD_ARGS=/property:TargetFrameworkVersion=v3.5
Changes to Setup/set_common.bat.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
  SET URL=http://system.data.sqlite.org/
)

IF NOT DEFINED PUBLICKEY (
  SET PUBLICKEY=db937bc2d44ff139
)

IF NOT DEFINED BUILD_CONFIGURATIONS (
  SET BUILD_CONFIGURATIONS=Release ReleaseNativeOnly
)

IF NOT DEFINED BAKE_CONFIGURATIONS (
  SET BAKE_CONFIGURATIONS=Release ReleaseNativeOnly
)

IF NOT DEFINED RELEASE_CONFIGURATIONS (
  SET RELEASE_CONFIGURATIONS=Release ReleaseNativeOnly
)

IF NOT DEFINED PLATFORMS (
  SET PLATFORMS=Win32 x64
)

IF NOT DEFINED PROCESSORS (







<
<
<
<
|
|
<
<
<
<







15
16
17
18
19
20
21




22
23




24
25
26
27
28
29
30
  SET URL=http://system.data.sqlite.org/
)

IF NOT DEFINED PUBLICKEY (
  SET PUBLICKEY=db937bc2d44ff139
)





IF NOT DEFINED CONFIGURATIONS (
  SET CONFIGURATIONS=Release ReleaseNativeOnly




)

IF NOT DEFINED PLATFORMS (
  SET PLATFORMS=Win32 x64
)

IF NOT DEFINED PROCESSORS (
Deleted Setup/test_all.bat.
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
@ECHO OFF

::
:: test_all.bat --
::
:: Multiplexing Wrapper Tool for Unit Tests
::
:: Written by Joe Mistachkin.
:: Released to the public domain, use at your own risk!
::

SETLOCAL

REM SET _ECHO=ECHO
IF NOT DEFINED _AECHO (SET _AECHO=REM)
IF NOT DEFINED _CECHO (SET _CECHO=REM)
IF NOT DEFINED _VECHO (SET _VECHO=REM)

%_AECHO% Running %0 %*

SET DUMMY2=%1

IF DEFINED DUMMY2 (
  GOTO usage
)

REM SET DFLAGS=/L

%_VECHO% DFlags = '%DFLAGS%'

SET FFLAGS=/V /F /G /H /I /R /Y /Z

%_VECHO% FFlags = '%FFLAGS%'

SET ROOT=%~dp0\..
SET ROOT=%ROOT:\\=\%

%_VECHO% Root = '%ROOT%'

SET TOOLS=%~dp0
SET TOOLS=%TOOLS:~0,-1%

%_VECHO% Tools = '%TOOLS%'

CALL :fn_ResetErrorLevel

%_ECHO% CALL "%TOOLS%\vsSp.bat"

IF ERRORLEVEL 1 (
  ECHO Could not detect Visual Studio.
  GOTO errors
)

%_ECHO% CALL "%TOOLS%\set_common.bat"

IF ERRORLEVEL 1 (
  ECHO Could not set common variables.
  GOTO errors
)

IF NOT DEFINED YEARS (
  SET YEARS=2008
)

%_VECHO% Years = '%YEARS%'

IF "%PROCESSOR_ARCHITECTURE%" == "x86" (
  SET PLATFORM=Win32
)

IF "%PROCESSOR_ARCHITECTURE%" == "amd64" (
  SET PLATFORM=x64
)

IF NOT DEFINED PLATFORM (
  ECHO Unsupported platform.
  GOTO errors
)

%_VECHO% Platform = '%PLATFORM%'

%_ECHO% PUSHD "%ROOT%"

IF ERRORLEVEL 1 (
  ECHO Could not change directory to "%ROOT%".
  GOTO errors
)

FOR %%Y IN (%YEARS%) DO (
  %_ECHO% Externals\Eagle\bin\EagleShell.exe -preInitialize "set test_year {%%Y}" -file Tests\all.eagle

  IF ERRORLEVEL 1 (
    ECHO Testing of "%%Y" managed-only assembly failed.
    GOTO errors
  )

  %_ECHO% XCOPY "bin\%%Y\Release\bin\test.*" "bin\%%Y\%PLATFORM%\Release" %FFLAGS% %DFLAGS%

  IF ERRORLEVEL 1 (
    ECHO Failed to copy "bin\%%Y\Release\bin\test.*" to "bin\%%Y\%PLATFORM%\Release".
    GOTO errors
  )

  %_ECHO% XCOPY "bin\%%Y\Release\bin\System.Data.SQLite.Linq.*" "bin\%%Y\%PLATFORM%\Release" %FFLAGS% %DFLAGS%

  IF ERRORLEVEL 1 (
    ECHO Failed to copy "bin\%%Y\Release\bin\System.Data.SQLite.Linq.*" to "bin\%%Y\%PLATFORM%\Release".
    GOTO errors
  )

  %_ECHO% XCOPY "bin\%%Y\Release\bin\testlinq.*" "bin\%%Y\%PLATFORM%\Release" %FFLAGS% %DFLAGS%

  IF ERRORLEVEL 1 (
    ECHO Failed to copy "bin\%%Y\Release\bin\testlinq.*" to "bin\%%Y\%PLATFORM%\Release".
    GOTO errors
  )

  %_ECHO% XCOPY "bin\%%Y\Release\bin\northwindEF.db" "bin\%%Y\%PLATFORM%\Release" %FFLAGS% %DFLAGS%

  IF ERRORLEVEL 1 (
    ECHO Failed to copy "bin\%%Y\Release\bin\northwindEF.db" to "bin\%%Y\%PLATFORM%\Release".
    GOTO errors
  )

  %_ECHO% Externals\Eagle\bin\EagleShell.exe -preInitialize "set test_year {%%Y}" -initialize -runtimeOption native -file Tests\all.eagle

  IF ERRORLEVEL 1 (
    ECHO Testing of "%%Y" mixed-mode assembly failed.
    GOTO errors
  )
)

%_ECHO% POPD

IF ERRORLEVEL 1 (
  ECHO Could not restore directory.
  GOTO errors
)

GOTO no_errors

:fn_ResetErrorLevel
  VERIFY > NUL
  GOTO :EOF

:fn_SetErrorLevel
  VERIFY MAYBE 2> NUL
  GOTO :EOF

:usage
  ECHO.
  ECHO Usage: %~nx0
  GOTO errors

:errors
  CALL :fn_SetErrorLevel
  ENDLOCAL
  ECHO.
  ECHO Test failure, errors were encountered.
  GOTO end_of_file

:no_errors
  CALL :fn_ResetErrorLevel
  ENDLOCAL
  ECHO.
  ECHO Test success, no errors were encountered.
  GOTO end_of_file

:end_of_file
%_ECHO% EXIT /B %ERRORLEVEL%
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




















































































































































































































































































































































Deleted Setup/updateFileInfo.tcl.
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
###############################################################################
#
# updateFileInfo.tcl -- File Metadata Updating Tool
#
# WARNING: This tool requires the Fossil binary to exist somewhere along the
#          PATH.
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################

proc readFile { fileName } {
  set file_id [open $fileName RDONLY]
  fconfigure $file_id -encoding binary -translation binary
  set result [read $file_id]
  close $file_id
  return $result
}

proc writeFile { fileName data } {
  set file_id [open $fileName {WRONLY CREAT TRUNC}]
  fconfigure $file_id -encoding binary -translation binary
  puts -nonewline $file_id $data
  close $file_id
  return ""
}

proc getFileSize { fileName } {
  #
  # NOTE: Return the number of mebibytes in the file with two digits after the
  #       decimal.
  #
  return [format %.2f [expr {[file size $fileName] / 1048576.0}]]
}

proc getFileHash { fileName } {
  #
  # NOTE: Return the SHA1 hash of the file, making use of Fossil via [exec] to
  #       actually calculate it.
  #
  return [string trim [lindex [regexp -inline -nocase -- {[0-9A-F]{40} } \
      [exec fossil sha1sum $fileName]] 0]]
}

#
# NOTE: Grab the fully qualified directory name of the directory containing
#       this script file.
#
set path [file normalize [file dirname [info script]]]

#
# NOTE: *WARNING* This assumes that the root of the source check-out is one
#       directory above the directory containing this script.
#
set root [file normalize [file dirname $path]]

#
# NOTE: Grab the name of the file to be updated from the command line, if
#       available; otherwise, use the default (i.e. "../www/downloads.wiki").
#
if {[info exists argv] && [llength $argv] > 0} then {
  set updateFileName [lindex $argv 0]
} else {
  set updateFileName [file join $root www downloads.wiki]
}

#
# NOTE: Grab the directory containing the files referenced in the data of the
#       file to be updated from the command line, if available; otherwise, use
#       the default (i.e. "./Output").
#
if {[info exists argv] && [llength $argv] > 1} then {
  set directory [lindex $argv 1]
} else {
  set directory [file join $path Output]
}

#
# NOTE: Setup the regular expression pattern with the necessary captures.  This
#       pattern is mostly non-greedy; however, at the end we need to match
#       exactly 40 hexadecimal characters.  In theory, in Tcl, this could have
#       an undefined result due to the mixing of greedy and non-greedy
#       quantifiers; however, in practice, this seems to work properly.  Also,
#       this pattern assumes a particular structure for the [HTML] file to be
#       updated.
#
set pattern {<a\
    href=".*?/(.*?\.(?:exe|zip))">.*?\((\d+?\.\d+?) MiB\).*?sha1:\
    ([0-9A-F]{40})}

#
# NOTE: Grab all the data from the file to be updated.
#
set data [readFile $updateFileName]

#
# NOTE: Process each match in the data and capture the file name, size, and
#       hash.
#
set count 0

foreach {dummy fileName fileSize fileHash} \
    [regexp -all -inline -nocase -- $pattern $data] {
  #
  # NOTE: Get the fully qualified file name based on the configured directory.
  #
  set fullFileName [file join $directory $fileName]

  #
  # NOTE: If the file does not exist, issue a warning and skip it.
  #
  if {![file exists $fullFileName]} then {
    puts stdout "WARNING: File \"$fullFileName\" does not exist, skipped."
    continue
  }

  #
  # NOTE: Replace the captured size and hash with ones calculated from the
  #       actual file name.  This will only replace the first instance of
  #       each (literal) match.  Since we are processing the matches in the
  #       exact order they appear in the data AND we are only replacing one
  #       literal instance per match AND the size sub-pattern is nothing like
  #       the hash sub-pattern, this should be 100% reliable.
  #
  incr count [regsub -nocase -- "***=$fileSize" $data [getFileSize \
      $fullFileName] data]

  incr count [regsub -nocase -- "***=$fileHash" $data [getFileHash \
      $fullFileName] data]
}

#
# NOTE: Write the [modified] data to the file to be updated.
#
if {$count > 0} then {
  writeFile $updateFileName $data
} else {
  puts stdout "WARNING: No changes, update of \"$updateFileName\" skipped."
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
























































































































































































































































































Changes to System.Data.SQLite.Linq/AssemblyInfo.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
using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security;
using System.Runtime.ConstrainedExecution;

// General Information about an assembly is controlled through the following 
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("System.Data.SQLite for LINQ")]
[assembly: AssemblyDescription("ADO.NET Data Provider for SQLite")]

[assembly: AssemblyCompany("http://system.data.sqlite.org/")]
[assembly: AssemblyProduct("System.Data.SQLite")]
[assembly: AssemblyCopyright("Public Domain")]

#if DEBUG
[assembly: AssemblyConfiguration("Debug")]
#else
[assembly: AssemblyConfiguration("Release")]
#endif

// Setting ComVisible to false makes the types in this assembly not visible 
// to COM components.  If you need to access a type in this assembly from 
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
[assembly: CLSCompliant(true)]
[assembly: AllowPartiallyTrustedCallers]
[assembly: ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      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.76.0")]
[assembly: AssemblyFileVersion("1.0.76.0")]









|
|
>
|


<
<
|
<
|
<



















|
|
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
using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security;
using System.Runtime.ConstrainedExecution;

// General Information about an assembly is controlled through the following 
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("System.Data.SQLite.Linq")]
[assembly: AssemblyDescription("ADO.NET Entity Framework support for SQLite")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("http://system.data.sqlite.org")]
[assembly: AssemblyProduct("System.Data.SQLite")]
[assembly: AssemblyCopyright("Public Domain")]


[assembly: AssemblyTrademark("")]

[assembly: AssemblyCulture("")]


// Setting ComVisible to false makes the types in this assembly not visible 
// to COM components.  If you need to access a type in this assembly from 
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
[assembly: CLSCompliant(true)]
[assembly: AllowPartiallyTrustedCallers]
[assembly: ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      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.74.0")]
[assembly: AssemblyFileVersion("1.0.74.0")]
Deleted System.Data.SQLite.Linq/SQL Generation/SkipClause.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
//---------------------------------------------------------------------
// <copyright file="SkipClause.cs" company="Microsoft">
//      Portions of this file copyright (c) Microsoft Corporation
//      and are released under the Microsoft Pulic License.  See
//      http://archive.msdn.microsoft.com/EFSampleProvider/Project/License.aspx
//      or License.txt for details.
//      All rights reserved.
// </copyright>
//---------------------------------------------------------------------

namespace System.Data.SQLite
{
    using System.Globalization;

    /// <summary>
    /// SkipClause represents the a SKIP expression in a SqlSelectStatement.
    /// It has a count property, which indicates how many rows should be skipped.
    /// </summary>
    class SkipClause : ISqlFragment
    {
        ISqlFragment skipCount;

        /// <summary>
        /// How many rows should be skipped.
        /// </summary>
        internal ISqlFragment SkipCount
        {
            get { return skipCount; }
        }

        /// <summary>
        /// Creates a SkipClause with the given skipCount.
        /// </summary>
        /// <param name="skipCount"></param>
        internal SkipClause(ISqlFragment skipCount)
        {
            this.skipCount = skipCount;
        }

        /// <summary>
        /// Creates a SkipClause with the given skipCount.
        /// </summary>
        /// <param name="skipCount"></param>
        internal SkipClause(int skipCount)
        {
            SqlBuilder sqlBuilder = new SqlBuilder();
            sqlBuilder.Append(skipCount.ToString(CultureInfo.InvariantCulture));
            this.skipCount = sqlBuilder;
        }

        #region ISqlFragment Members
        /// <summary>
        /// Write out the SKIP part of sql select statement 
        /// It basically writes OFFSET (X).
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="sqlGenerator"></param>
        public void WriteSql(SqlWriter writer, SqlGenerator sqlGenerator)
        {
            writer.Write(" OFFSET ");
            this.SkipCount.WriteSql(writer, sqlGenerator);
        }
        #endregion
    }
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


































































































































Changes to System.Data.SQLite.Linq/SQL Generation/SqlChecker.cs.
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
{
  using System;
  using System.Collections.Generic;
  using System.Data.Common.CommandTrees;

    internal class SqlChecker : DbExpressionVisitor<bool>
  {
#if false
    private static Type sql8rewriter;

    static SqlChecker()
    {
        string version =
#if NET_20
            "3.5.0.0";
#else
            "4.0.0.0";
#endif

        sql8rewriter = Type.GetType(String.Format("System.Data.SqlClient.SqlGen.Sql8ExpressionRewriter, System.Data.Entity, Version={0}, Culture=neutral, PublicKeyToken=b77a5c561934e089", version), false);
    }
#endif

    private SqlChecker()
    {
    }

#if false
    /// <summary>
    /// SQLite doesn't support things like SKIP and a few other things.  
    /// So determine if the query has to be rewritten
    /// </summary>
    /// <remarks>
    /// Microsoft went to all the trouble of making things like SKIP work 
    /// on Sql Server 2000 by doing a rewrite of the commandtree.







<




<
<
<
<
<
<
<
|

<





<







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
{
  using System;
  using System.Collections.Generic;
  using System.Data.Common.CommandTrees;

    internal class SqlChecker : DbExpressionVisitor<bool>
  {

    private static Type sql8rewriter;

    static SqlChecker()
    {







      sql8rewriter = Type.GetType("System.Data.SqlClient.SqlGen.Sql8ExpressionRewriter, System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", false);
    }


    private SqlChecker()
    {
    }


    /// <summary>
    /// SQLite doesn't support things like SKIP and a few other things.  
    /// So determine if the query has to be rewritten
    /// </summary>
    /// <remarks>
    /// Microsoft went to all the trouble of making things like SKIP work 
    /// on Sql Server 2000 by doing a rewrite of the commandtree.
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
      SqlChecker visitor = new SqlChecker();
      if (tree.Query.Accept<bool>(visitor))
      {
        tree = sql8rewriter.InvokeMember("Rewrite", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Static, null, null, new object[] { tree }) as DbQueryCommandTree;
      }      
      return tree;
    }
#endif

    public override bool Visit(DbAndExpression expression)
    {
      return VisitBinaryExpression(expression);
    }

    public override bool Visit(DbApplyExpression expression)







<







42
43
44
45
46
47
48

49
50
51
52
53
54
55
      SqlChecker visitor = new SqlChecker();
      if (tree.Query.Accept<bool>(visitor))
      {
        tree = sql8rewriter.InvokeMember("Rewrite", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Static, null, null, new object[] { tree }) as DbQueryCommandTree;
      }      
      return tree;
    }


    public override bool Visit(DbAndExpression expression)
    {
      return VisitBinaryExpression(expression);
    }

    public override bool Visit(DbApplyExpression expression)
Changes to System.Data.SQLite.Linq/SQL Generation/SqlGenerator.cs.
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
      functionHandlers.Add("IndexOf", HandleCanonicalFunctionIndexOf);
      functionHandlers.Add("Length", HandleCanonicalFunctionLength);
      functionHandlers.Add("NewGuid", HandleCanonicalFunctionNewGuid);
      functionHandlers.Add("Round", HandleCanonicalFunctionRound);
      functionHandlers.Add("ToLower", HandleCanonicalFunctionToLower);
      functionHandlers.Add("ToUpper", HandleCanonicalFunctionToUpper);
      functionHandlers.Add("Trim", HandleCanonicalFunctionTrim);
      functionHandlers.Add("Right", HandleCanonicalFunctionRight);
      functionHandlers.Add("CurrentDateTime", HandleGetDateFunction);
      functionHandlers.Add("CurrentUtcDateTime", HandleGetUtcDateFunction);

      //DatePartFunctions
      functionHandlers.Add("Year", HandleCanonicalFunctionDatepart);
      functionHandlers.Add("Month", HandleCanonicalFunctionDatepart);
      functionHandlers.Add("Day", HandleCanonicalFunctionDatepart);







<







331
332
333
334
335
336
337

338
339
340
341
342
343
344
      functionHandlers.Add("IndexOf", HandleCanonicalFunctionIndexOf);
      functionHandlers.Add("Length", HandleCanonicalFunctionLength);
      functionHandlers.Add("NewGuid", HandleCanonicalFunctionNewGuid);
      functionHandlers.Add("Round", HandleCanonicalFunctionRound);
      functionHandlers.Add("ToLower", HandleCanonicalFunctionToLower);
      functionHandlers.Add("ToUpper", HandleCanonicalFunctionToUpper);
      functionHandlers.Add("Trim", HandleCanonicalFunctionTrim);

      functionHandlers.Add("CurrentDateTime", HandleGetDateFunction);
      functionHandlers.Add("CurrentUtcDateTime", HandleGetUtcDateFunction);

      //DatePartFunctions
      functionHandlers.Add("Year", HandleCanonicalFunctionDatepart);
      functionHandlers.Add("Month", HandleCanonicalFunctionDatepart);
      functionHandlers.Add("Day", HandleCanonicalFunctionDatepart);
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
    /// CollectionType => select statement
    /// non collection type => select expression
    /// </summary>
    /// <param name="tree"></param>
    /// <returns>The string representing the SQL to be executed.</returns>
    private string GenerateSql(DbQueryCommandTree tree)
    {
#if false
      tree = SqlChecker.Rewrite(tree);
#endif

      selectStatementStack = new Stack<SqlSelectStatement>();
      isParentAJoinStack = new Stack<bool>();

      allExtentNames = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
      allColumnNames = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);

      // Literals will not be converted to parameters.







<

<
<







505
506
507
508
509
510
511

512


513
514
515
516
517
518
519
    /// CollectionType => select statement
    /// non collection type => select expression
    /// </summary>
    /// <param name="tree"></param>
    /// <returns>The string representing the SQL to be executed.</returns>
    private string GenerateSql(DbQueryCommandTree tree)
    {

      tree = SqlChecker.Rewrite(tree);


      selectStatementStack = new Stack<SqlSelectStatement>();
      isParentAJoinStack = new Stack<bool>();

      allExtentNames = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
      allColumnNames = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);

      // Literals will not be converted to parameters.
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
    /// WHERE Y.[row_number] > count 
    /// ORDER BY sk1, sk2, ...
    /// </summary>
    /// <param name="e"></param>
    /// <returns>A <see cref="SqlBuilder"/></returns>
    public override ISqlFragment Visit(DbSkipExpression e)
    {
        Debug.Assert(e.Count is DbConstantExpression || e.Count is DbParameterReferenceExpression, "DbLimitExpression.Count is of invalid expression type");

        Symbol fromSymbol;
        SqlSelectStatement result = VisitInputExpression(e.Input.Expression, e.Input.VariableName, e.Input.VariableType, out fromSymbol);

        if (!IsCompatible(result, e.ExpressionKind))
        {
            result = CreateNewSelectStatement(result, e.Input.VariableName, e.Input.VariableType, out fromSymbol);
        }

        selectStatementStack.Push(result);
        symbolTable.EnterScope();

        AddFromSymbol(result, e.Input.VariableName, fromSymbol);

        AddSortKeys(result.OrderBy, e.SortOrder);

        symbolTable.ExitScope();
        selectStatementStack.Pop();

        ISqlFragment skipCount = HandleCountExpression(e.Count);

        result.Skip = new SkipClause(skipCount);
        return result;
    }

    /// <summary>
    /// <see cref="Visit(DbFilterExpression)"/>
    /// </summary>
    /// <param name="e"></param>
    /// <returns>A <see cref="SqlSelectStatement"/></returns>







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







1803
1804
1805
1806
1807
1808
1809

1810


1811



















1812
1813
1814
1815
1816
1817
1818
    /// WHERE Y.[row_number] > count 
    /// ORDER BY sk1, sk2, ...
    /// </summary>
    /// <param name="e"></param>
    /// <returns>A <see cref="SqlBuilder"/></returns>
    public override ISqlFragment Visit(DbSkipExpression e)
    {

      // Should never get here.  The Sql2000 rewriter would've rewritten the command tree not to use this


      throw new NotSupportedException();



















    }

    /// <summary>
    /// <see cref="Visit(DbFilterExpression)"/>
    /// </summary>
    /// <param name="e"></param>
    /// <returns>A <see cref="SqlSelectStatement"/></returns>
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
      result.Append(e.Arguments[0].Accept(sqlgen));

      result.Append(")");

      return result;
    }

    /// <summary>
    /// RIGHT(string, length) -> SUBSTR(string, -(length), length)
    /// </summary>
    /// <param name="sqlgen"></param>
    /// <param name="e"></param>
    /// <returns></returns>
    private static ISqlFragment HandleCanonicalFunctionRight(SqlGenerator sqlgen, DbFunctionExpression e)
    {
        SqlBuilder result = new SqlBuilder();

        result.Append("SUBSTR(");

        Debug.Assert(e.Arguments.Count == 2, "Right should have two arguments");
        result.Append(e.Arguments[0].Accept(sqlgen));
        result.Append(", -(");
        result.Append(e.Arguments[1].Accept(sqlgen));
        result.Append("), ");
        result.Append(e.Arguments[1].Accept(sqlgen));
        result.Append(")");

        return result;
    }

    /// <summary>
    ///  Function rename ToLower -> LOWER
    /// </summary>
    /// <param name="sqlgen"></param>
    /// <param name="e"></param>
    /// <returns></returns>
    private static ISqlFragment HandleCanonicalFunctionToLower(SqlGenerator sqlgen, DbFunctionExpression e)







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







2915
2916
2917
2918
2919
2920
2921























2922
2923
2924
2925
2926
2927
2928
      result.Append(e.Arguments[0].Accept(sqlgen));

      result.Append(")");

      return result;
    }
























    /// <summary>
    ///  Function rename ToLower -> LOWER
    /// </summary>
    /// <param name="sqlgen"></param>
    /// <param name="e"></param>
    /// <returns></returns>
    private static ISqlFragment HandleCanonicalFunctionToLower(SqlGenerator sqlgen, DbFunctionExpression e)
Changes to System.Data.SQLite.Linq/SQL Generation/SqlSelectStatement.cs.
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
      set
      {
        Debug.Assert(top == null, "SqlSelectStatement.Top has already been set");
        top = value;
      }
    }

    private SkipClause skip;
    internal SkipClause Skip
    {
      get { return skip; }
      set
      {
          Debug.Assert(skip == null, "SqlSelectStatement.Skip has already been set");
          skip = value;
      }
    }

    private SqlBuilder select = new SqlBuilder();
    internal SqlBuilder Select
    {
      get { return select; }
    }

    private SqlBuilder from = new SqlBuilder();







<
<
<
<
<
<
<
<
<
<
<







111
112
113
114
115
116
117











118
119
120
121
122
123
124
      set
      {
        Debug.Assert(top == null, "SqlSelectStatement.Top has already been set");
        top = value;
      }
    }












    private SqlBuilder select = new SqlBuilder();
    internal SqlBuilder Select
    {
      get { return select; }
    }

    private SqlBuilder from = new SqlBuilder();
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
      }

      if (this.Top != null)
      {
        this.Top.WriteSql(writer, sqlGenerator);
      }

      if (this.skip != null)
      {
        this.Skip.WriteSql(writer, sqlGenerator);
      }

      --writer.Indent;
    }

    #endregion
  }
}







<
<
<
<







300
301
302
303
304
305
306




307
308
309
310
311
312
313
      }

      if (this.Top != null)
      {
        this.Top.WriteSql(writer, sqlGenerator);
      }






      --writer.Indent;
    }

    #endregion
  }
}
Changes to System.Data.SQLite.Linq/SQL Generation/TopClause.cs.
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
      this.withTies = withTies;
    }

    #region ISqlFragment Members

    /// <summary>
    /// Write out the TOP part of sql select statement 
    /// It basically writes LIMIT (X).
    /// </summary>
    /// <param name="writer"></param>
    /// <param name="sqlGenerator"></param>
    public void WriteSql(SqlWriter writer, SqlGenerator sqlGenerator)
    {
      writer.Write(" LIMIT ");
      this.TopCount.WriteSql(writer, sqlGenerator);







|







63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
      this.withTies = withTies;
    }

    #region ISqlFragment Members

    /// <summary>
    /// Write out the TOP part of sql select statement 
    /// It basically writes TOP (X) [WITH TIES].
    /// </summary>
    /// <param name="writer"></param>
    /// <param name="sqlGenerator"></param>
    public void WriteSql(SqlWriter writer, SqlGenerator sqlGenerator)
    {
      writer.Write(" LIMIT ");
      this.TopCount.WriteSql(writer, sqlGenerator);
Changes to System.Data.SQLite.Linq/System.Data.SQLite.Linq.2008.csproj.
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
    </Compile>
    <Compile Include="SQL Generation\DmlSqlGenerator.cs" />
    <Compile Include="SQL Generation\InternalBase.cs" />
    <Compile Include="SQL Generation\ISqlFragment.cs" />
    <Compile Include="SQL Generation\JoinSymbol.cs" />
    <Compile Include="SQL Generation\KeyToListMap.cs" />
    <Compile Include="SQL Generation\MetadataHelpers.cs" />
    <Compile Include="SQL Generation\SkipClause.cs" />
    <Compile Include="SQL Generation\SqlBuilder.cs" />
    <Compile Include="SQL Generation\SqlChecker.cs" />
    <Compile Include="SQL Generation\SqlGenerator.cs" />
    <Compile Include="SQL Generation\SqlSelectStatement.cs" />
    <Compile Include="SQL Generation\SqlWriter.cs" />
    <Compile Include="SQL Generation\StringUtil.cs" />
    <Compile Include="SQL Generation\Symbol.cs" />







<







57
58
59
60
61
62
63

64
65
66
67
68
69
70
    </Compile>
    <Compile Include="SQL Generation\DmlSqlGenerator.cs" />
    <Compile Include="SQL Generation\InternalBase.cs" />
    <Compile Include="SQL Generation\ISqlFragment.cs" />
    <Compile Include="SQL Generation\JoinSymbol.cs" />
    <Compile Include="SQL Generation\KeyToListMap.cs" />
    <Compile Include="SQL Generation\MetadataHelpers.cs" />

    <Compile Include="SQL Generation\SqlBuilder.cs" />
    <Compile Include="SQL Generation\SqlChecker.cs" />
    <Compile Include="SQL Generation\SqlGenerator.cs" />
    <Compile Include="SQL Generation\SqlSelectStatement.cs" />
    <Compile Include="SQL Generation\SqlWriter.cs" />
    <Compile Include="SQL Generation\StringUtil.cs" />
    <Compile Include="SQL Generation\Symbol.cs" />
Changes to System.Data.SQLite.Linq/System.Data.SQLite.Linq.2010.csproj.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{E6BF9F74-58E2-413B-A7CE-EA653ECB728D}</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>System.Data.SQLite.Linq</RootNamespace>
    <AssemblyName>System.Data.SQLite.Linq</AssemblyName>
    <OldToolsVersion>3.5</OldToolsVersion>
    <TargetFrameworkProfile>Client</TargetFrameworkProfile>
    <SQLiteNetDir>$(MSBuildProjectDirectory)\..</SQLiteNetDir>
    <ConfigurationYear>2010</ConfigurationYear>
  </PropertyGroup>
  <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets" />
  <PropertyGroup Condition="'$(BinaryOutputPath)' != ''">
    <OutputPath>$(BinaryOutputPath)</OutputPath>
    <DocumentationFile>$(BinaryOutputPath)System.Data.SQLite.Linq.xml</DocumentationFile>







<







15
16
17
18
19
20
21

22
23
24
25
26
27
28
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{E6BF9F74-58E2-413B-A7CE-EA653ECB728D}</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>System.Data.SQLite.Linq</RootNamespace>
    <AssemblyName>System.Data.SQLite.Linq</AssemblyName>
    <OldToolsVersion>3.5</OldToolsVersion>

    <SQLiteNetDir>$(MSBuildProjectDirectory)\..</SQLiteNetDir>
    <ConfigurationYear>2010</ConfigurationYear>
  </PropertyGroup>
  <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets" />
  <PropertyGroup Condition="'$(BinaryOutputPath)' != ''">
    <OutputPath>$(BinaryOutputPath)</OutputPath>
    <DocumentationFile>$(BinaryOutputPath)System.Data.SQLite.Linq.xml</DocumentationFile>
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
    </Compile>
    <Compile Include="SQL Generation\DmlSqlGenerator.cs" />
    <Compile Include="SQL Generation\InternalBase.cs" />
    <Compile Include="SQL Generation\ISqlFragment.cs" />
    <Compile Include="SQL Generation\JoinSymbol.cs" />
    <Compile Include="SQL Generation\KeyToListMap.cs" />
    <Compile Include="SQL Generation\MetadataHelpers.cs" />
    <Compile Include="SQL Generation\SkipClause.cs" />
    <Compile Include="SQL Generation\SqlBuilder.cs" />
    <Compile Include="SQL Generation\SqlChecker.cs" />
    <Compile Include="SQL Generation\SqlGenerator.cs" />
    <Compile Include="SQL Generation\SqlSelectStatement.cs" />
    <Compile Include="SQL Generation\SqlWriter.cs" />
    <Compile Include="SQL Generation\StringUtil.cs" />
    <Compile Include="SQL Generation\Symbol.cs" />







<







56
57
58
59
60
61
62

63
64
65
66
67
68
69
    </Compile>
    <Compile Include="SQL Generation\DmlSqlGenerator.cs" />
    <Compile Include="SQL Generation\InternalBase.cs" />
    <Compile Include="SQL Generation\ISqlFragment.cs" />
    <Compile Include="SQL Generation\JoinSymbol.cs" />
    <Compile Include="SQL Generation\KeyToListMap.cs" />
    <Compile Include="SQL Generation\MetadataHelpers.cs" />

    <Compile Include="SQL Generation\SqlBuilder.cs" />
    <Compile Include="SQL Generation\SqlChecker.cs" />
    <Compile Include="SQL Generation\SqlGenerator.cs" />
    <Compile Include="SQL Generation\SqlSelectStatement.cs" />
    <Compile Include="SQL Generation\SqlWriter.cs" />
    <Compile Include="SQL Generation\StringUtil.cs" />
    <Compile Include="SQL Generation\Symbol.cs" />
Changes to System.Data.SQLite/AssemblyInfo.cs.
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
using System.Security;
using System.Runtime.ConstrainedExecution;
#endif

// General Information about an assembly is controlled through the following 
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("System.Data.SQLite Core")]
[assembly: AssemblyDescription("ADO.NET Data Provider for SQLite")]

[assembly: AssemblyCompany("http://system.data.sqlite.org/")]
[assembly: AssemblyProduct("System.Data.SQLite")]
[assembly: AssemblyCopyright("Public Domain")]

#if DEBUG
[assembly: AssemblyConfiguration("Debug")]
#else
[assembly: AssemblyConfiguration("Release")]
#endif

#if PLATFORM_COMPACTFRAMEWORK && RETARGETABLE
[assembly: AssemblyFlags(AssemblyNameFlags.Retargetable)]
#endif

//  Setting ComVisible to false makes the types in this assembly not visible 
//  to COM componenets.  If you need to access a type in this assembly from 







|

>
|


<
<
|
<
|
<







8
9
10
11
12
13
14
15
16
17
18
19
20


21

22

23
24
25
26
27
28
29
using System.Security;
using System.Runtime.ConstrainedExecution;
#endif

// General Information about an assembly is controlled through the following 
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("System.Data.SQLite")]
[assembly: AssemblyDescription("ADO.NET Data Provider for SQLite")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("http://system.data.sqlite.org")]
[assembly: AssemblyProduct("System.Data.SQLite")]
[assembly: AssemblyCopyright("Public Domain")]


[assembly: AssemblyTrademark("")]

[assembly: AssemblyCulture("")]


#if PLATFORM_COMPACTFRAMEWORK && RETARGETABLE
[assembly: AssemblyFlags(AssemblyNameFlags.Retargetable)]
#endif

//  Setting ComVisible to false makes the types in this assembly not visible 
//  to COM componenets.  If you need to access a type in this assembly from 
53
54
55
56
57
58
59
60
61
62
63
//      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.76.0")]
#if !PLATFORM_COMPACTFRAMEWORK
[assembly: AssemblyFileVersion("1.0.76.0")]
#endif







|

|

50
51
52
53
54
55
56
57
58
59
60
//      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.74.0")]
#if !PLATFORM_COMPACTFRAMEWORK
[assembly: AssemblyFileVersion("1.0.74.0")]
#endif
Changes to System.Data.SQLite/LINQ/SQLiteFactory_Linq.cs.
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
  public sealed partial class SQLiteFactory : IServiceProvider
  {
    private static Type _dbProviderServicesType;
    private static object _sqliteServices;

    static SQLiteFactory()
    {
#if !PLATFORM_COMPACTFRAMEWORK
        SQLiteLog.Initialize();
#endif

        string version =
#if NET_20
            "3.5.0.0";
#else
            "4.0.0.0";
#endif








<
<
<
<







17
18
19
20
21
22
23




24
25
26
27
28
29
30
  public sealed partial class SQLiteFactory : IServiceProvider
  {
    private static Type _dbProviderServicesType;
    private static object _sqliteServices;

    static SQLiteFactory()
    {




        string version =
#if NET_20
            "3.5.0.0";
#else
            "4.0.0.0";
#endif

Changes to System.Data.SQLite/SQLite3.cs.
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
  internal delegate void SQLiteLogCallback(IntPtr puser, int err_code, IntPtr message);

  /// <summary>
  /// This class implements SQLiteBase completely, and is the guts of the code that interop's SQLite with .NET
  /// </summary>
  internal class SQLite3 : SQLiteBase
  {
#if !PLATFORM_COMPACTFRAMEWORK
    internal const string DesignerVersion = "1.0.76.0";
#endif

    /// <summary>
    /// The opaque pointer returned to us by the sqlite provider
    /// </summary>
    protected SQLiteConnectionHandle _sql;
    protected string _fileName;
    protected bool _usePool;
    protected int _poolVersion;

#if !PLATFORM_COMPACTFRAMEWORK
    private bool _buildingSchema;
#endif
    /// <summary>
    /// The user-defined functions registered on this connection
    /// </summary>
    protected SQLiteFunction[] _functionsArray;

    internal SQLite3(SQLiteDateFormats fmt, DateTimeKind kind)
      : base(fmt, kind)
    {
    }

    protected override void Dispose(bool bDisposing)
    {
      if (bDisposing)
        Close();







<
<
<
<
















|
|







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
  internal delegate void SQLiteLogCallback(IntPtr puser, int err_code, IntPtr message);

  /// <summary>
  /// This class implements SQLiteBase completely, and is the guts of the code that interop's SQLite with .NET
  /// </summary>
  internal class SQLite3 : SQLiteBase
  {




    /// <summary>
    /// The opaque pointer returned to us by the sqlite provider
    /// </summary>
    protected SQLiteConnectionHandle _sql;
    protected string _fileName;
    protected bool _usePool;
    protected int _poolVersion;

#if !PLATFORM_COMPACTFRAMEWORK
    private bool _buildingSchema;
#endif
    /// <summary>
    /// The user-defined functions registered on this connection
    /// </summary>
    protected SQLiteFunction[] _functionsArray;

    internal SQLite3(SQLiteDateFormats fmt)
      : base(fmt)
    {
    }

    protected override void Dispose(bool bDisposing)
    {
      if (bDisposing)
        Close();
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
    {
      get
      {
        return IsAutocommit(_sql);
      }
    }

    internal override long LastInsertRowId
    {
      get
      {
        return UnsafeNativeMethods.sqlite3_last_insert_rowid(_sql);
      }
    }

    internal override int Changes
    {
      get
      {
        return UnsafeNativeMethods.sqlite3_changes(_sql);
      }
    }

    /// <summary>
    /// Shutdown the SQLite engine so that it can be restarted with different config options.
    /// We depend on auto initialization to recover.
    /// </summary>
    /// <returns>Returns a result code</returns>
    internal override int Shutdown()
    {
        int rc = UnsafeNativeMethods.sqlite3_shutdown();
        return rc;
    }

    internal override bool IsOpen()
    {
        return (_sql != null);
    }

    internal override void Open(string strFilename, SQLiteOpenFlagsEnum flags, int maxPoolSize, bool usePool)
    {
      if (_sql != null) return;

      _usePool = usePool;
      if (usePool)
      {







<
<
<
<
<
<
<
<



















<
<
<
<
<







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
    {
      get
      {
        return IsAutocommit(_sql);
      }
    }









    internal override int Changes
    {
      get
      {
        return UnsafeNativeMethods.sqlite3_changes(_sql);
      }
    }

    /// <summary>
    /// Shutdown the SQLite engine so that it can be restarted with different config options.
    /// We depend on auto initialization to recover.
    /// </summary>
    /// <returns>Returns a result code</returns>
    internal override int Shutdown()
    {
        int rc = UnsafeNativeMethods.sqlite3_shutdown();
        return rc;
    }






    internal override void Open(string strFilename, SQLiteOpenFlagsEnum flags, int maxPoolSize, bool usePool)
    {
      if (_sql != null) return;

      _usePool = usePool;
      if (usePool)
      {
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
    internal override string SQLiteLastError()
    {
      return SQLiteBase.SQLiteLastError(_sql);
    }

    internal override SQLiteStatement Prepare(SQLiteConnection cnn, string strSql, SQLiteStatement previous, uint timeoutMS, out string strRemain)
    {
      if (!String.IsNullOrEmpty(strSql))
      {
        //
        // NOTE: SQLite does not support the concept of separate schemas
        //       in one database; therefore, remove the base schema name
        //       used to smooth integration with the base .NET Framework
        //       data classes.
        //
        string baseSchemaName = (cnn != null) ? cnn._baseSchemaName : null;

        if (!String.IsNullOrEmpty(baseSchemaName))
        {
          strSql = strSql.Replace(
              String.Format("[{0}].", baseSchemaName), String.Empty);

          strSql = strSql.Replace(
              String.Format("{0}.", baseSchemaName), String.Empty);
        }
      }

      IntPtr stmt = IntPtr.Zero;
      IntPtr ptr = IntPtr.Zero;
      int len = 0;
      int n = 17;
      int retries = 0;
      byte[] b = ToUTF8(strSql);
      string typedefs = null;







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







243
244
245
246
247
248
249




















250
251
252
253
254
255
256
    internal override string SQLiteLastError()
    {
      return SQLiteBase.SQLiteLastError(_sql);
    }

    internal override SQLiteStatement Prepare(SQLiteConnection cnn, string strSql, SQLiteStatement previous, uint timeoutMS, out string strRemain)
    {




















      IntPtr stmt = IntPtr.Zero;
      IntPtr ptr = IntPtr.Zero;
      int len = 0;
      int n = 17;
      int retries = 0;
      byte[] b = ToUTF8(strSql);
      string typedefs = null;
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
      byte[] b = ToUTF8(value);
      int n = UnsafeNativeMethods.sqlite3_bind_text(stmt._sqlite_stmt, index, b, b.Length - 1, (IntPtr)(-1));
      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
    }

    internal override void Bind_DateTime(SQLiteStatement stmt, int index, DateTime dt)
    {
        switch (_datetimeFormat)
        {
            case SQLiteDateFormats.Ticks:
                {
                    long value = dt.Ticks;

#if !PLATFORM_COMPACTFRAMEWORK
                    int n = UnsafeNativeMethods.sqlite3_bind_int64(stmt._sqlite_stmt, index, value);
#else
                    int n = UnsafeNativeMethods.sqlite3_bind_int64_interop(stmt._sqlite_stmt, index, ref value);
#endif
                    if (n > 0) throw new SQLiteException(n, SQLiteLastError());
                    break;
                }
            case SQLiteDateFormats.JulianDay:
                {
                    double value = ToJulianDay(dt);

#if !PLATFORM_COMPACTFRAMEWORK
                    int n = UnsafeNativeMethods.sqlite3_bind_double(stmt._sqlite_stmt, index, value);
#else
                    int n = UnsafeNativeMethods.sqlite3_bind_double_interop(stmt._sqlite_stmt, index, ref value);
#endif
                    if (n > 0) throw new SQLiteException(n, SQLiteLastError());
                    break;
                }
            case SQLiteDateFormats.UnixEpoch:
                {
                    long value = Convert.ToInt64(dt.Subtract(UnixEpoch).TotalSeconds);

#if !PLATFORM_COMPACTFRAMEWORK
                    int n = UnsafeNativeMethods.sqlite3_bind_int64(stmt._sqlite_stmt, index, value);
#else
                    int n = UnsafeNativeMethods.sqlite3_bind_int64_interop(stmt._sqlite_stmt, index, ref value);
#endif
                    if (n > 0) throw new SQLiteException(n, SQLiteLastError());
                    break;
                }
            default:
                {
                    byte[] b = ToUTF8(dt);
                    int n = UnsafeNativeMethods.sqlite3_bind_text(stmt._sqlite_stmt, index, b, b.Length - 1, (IntPtr)(-1));
                    if (n > 0) throw new SQLiteException(n, SQLiteLastError());
                    break;
                }
        }
    }

    internal override void Bind_Blob(SQLiteStatement stmt, int index, byte[] blobData)
    {
      int n = UnsafeNativeMethods.sqlite3_bind_blob(stmt._sqlite_stmt, index, blobData, blobData.Length, (IntPtr)(-1));
      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
    }







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







387
388
389
390
391
392
393








































394
395
396



397
398
399
400
401
402
403
      byte[] b = ToUTF8(value);
      int n = UnsafeNativeMethods.sqlite3_bind_text(stmt._sqlite_stmt, index, b, b.Length - 1, (IntPtr)(-1));
      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
    }

    internal override void Bind_DateTime(SQLiteStatement stmt, int index, DateTime dt)
    {








































      byte[] b = ToUTF8(dt);
      int n = UnsafeNativeMethods.sqlite3_bind_text(stmt._sqlite_stmt, index, b, b.Length - 1, (IntPtr)(-1));
      if (n > 0) throw new SQLiteException(n, SQLiteLastError());



    }

    internal override void Bind_Blob(SQLiteStatement stmt, int index, byte[] blobData)
    {
      int n = UnsafeNativeMethods.sqlite3_bind_blob(stmt._sqlite_stmt, index, blobData, blobData.Length, (IntPtr)(-1));
      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
    }
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
      collationSequence = UTF8ToString(coll, colllen);
#else
      sortMode = 0;
      onError = 2;
      collationSequence = "BINARY";
#endif
    }

    internal override int FileControl(string zDbName, int op, IntPtr pArg)
    {
      return UnsafeNativeMethods.sqlite3_file_control(_sql, (zDbName != null) ? ToUTF8(zDbName) : null, op, pArg);
    }
  }
}







|
<
<
<
|
<
<
1024
1025
1026
1027
1028
1029
1030
1031



1032


      collationSequence = UTF8ToString(coll, colllen);
#else
      sortMode = 0;
      onError = 2;
      collationSequence = "BINARY";
#endif
    }
  }



}


Changes to System.Data.SQLite/SQLite3_UTF16.cs.
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  using System.Runtime.InteropServices;

  /// <summary>
  /// Alternate SQLite3 object, overriding many text behaviors to support UTF-16 (Unicode)
  /// </summary>
  internal class SQLite3_UTF16 : SQLite3
  {
    internal SQLite3_UTF16(SQLiteDateFormats fmt, DateTimeKind kind)
      : base(fmt, kind)
    {
    }

    /// <summary>
    /// Overrides SQLiteConvert.ToString() to marshal UTF-16 strings instead of UTF-8
    /// </summary>
    /// <param name="b">A pointer to a UTF-16 string</param>







|
|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  using System.Runtime.InteropServices;

  /// <summary>
  /// Alternate SQLite3 object, overriding many text behaviors to support UTF-16 (Unicode)
  /// </summary>
  internal class SQLite3_UTF16 : SQLite3
  {
    internal SQLite3_UTF16(SQLiteDateFormats fmt)
      : base(fmt)
    {
    }

    /// <summary>
    /// Overrides SQLiteConvert.ToString() to marshal UTF-16 strings instead of UTF-8
    /// </summary>
    /// <param name="b">A pointer to a UTF-16 string</param>
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
        _sql = db;
      }
      _functionsArray = SQLiteFunction.BindFunctions(this);
    }

    internal override void Bind_DateTime(SQLiteStatement stmt, int index, DateTime dt)
    {
        switch (_datetimeFormat)
        {
            case SQLiteDateFormats.Ticks:
                {
                    long value = dt.Ticks;

#if !PLATFORM_COMPACTFRAMEWORK
                    int n = UnsafeNativeMethods.sqlite3_bind_int64(stmt._sqlite_stmt, index, value);
#else
                    int n = UnsafeNativeMethods.sqlite3_bind_int64_interop(stmt._sqlite_stmt, index, ref value);
#endif
                    if (n > 0) throw new SQLiteException(n, SQLiteLastError());
                    break;
                }
            case SQLiteDateFormats.JulianDay:
                {
                    double value = ToJulianDay(dt);

#if !PLATFORM_COMPACTFRAMEWORK
                    int n = UnsafeNativeMethods.sqlite3_bind_double(stmt._sqlite_stmt, index, value);
#else
                    int n = UnsafeNativeMethods.sqlite3_bind_double_interop(stmt._sqlite_stmt, index, ref value);
#endif
                    if (n > 0) throw new SQLiteException(n, SQLiteLastError());
                    break;
                }
            case SQLiteDateFormats.UnixEpoch:
                {
                    long value = Convert.ToInt64(dt.Subtract(UnixEpoch).TotalSeconds);

#if !PLATFORM_COMPACTFRAMEWORK
                    int n = UnsafeNativeMethods.sqlite3_bind_int64(stmt._sqlite_stmt, index, value);
#else
                    int n = UnsafeNativeMethods.sqlite3_bind_int64_interop(stmt._sqlite_stmt, index, ref value);
#endif
                    if (n > 0) throw new SQLiteException(n, SQLiteLastError());
                    break;
                }
            default:
                {
                    Bind_Text(stmt, index, ToString(dt));
                    break;
                }
        }
    }

    internal override void Bind_Text(SQLiteStatement stmt, int index, string value)
    {
      int n = UnsafeNativeMethods.sqlite3_bind_text16(stmt._sqlite_stmt, index, value, value.Length * 2, (IntPtr)(-1));
      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
    }







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







69
70
71
72
73
74
75








































76



77
78
79
80
81
82
83
        _sql = db;
      }
      _functionsArray = SQLiteFunction.BindFunctions(this);
    }

    internal override void Bind_DateTime(SQLiteStatement stmt, int index, DateTime dt)
    {








































      Bind_Text(stmt, index, ToString(dt));



    }

    internal override void Bind_Text(SQLiteStatement stmt, int index, string value)
    {
      int n = UnsafeNativeMethods.sqlite3_bind_text16(stmt._sqlite_stmt, index, value, value.Length * 2, (IntPtr)(-1));
      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
    }
Changes to System.Data.SQLite/SQLiteBase.cs.
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

  /// <summary>
  /// This internal class provides the foundation of SQLite support.  It defines all the abstract members needed to implement
  /// a SQLite data provider, and inherits from SQLiteConvert which allows for simple translations of string to and from SQLite.
  /// </summary>
  internal abstract class SQLiteBase : SQLiteConvert, IDisposable
  {
    internal SQLiteBase(SQLiteDateFormats fmt, DateTimeKind kind)
      : base(fmt, kind) { }

    static internal object _lock = new object();

    /// <summary>
    /// Returns a string representing the active version of SQLite
    /// </summary>
    internal abstract string Version { get; }
    /// <summary>
    /// Returns the rowid of the most recent successful INSERT into the database from this connection.
    /// </summary>
    internal abstract long LastInsertRowId { get; }
    /// <summary>
    /// Returns the number of changes the last executing insert/update caused.
    /// </summary>
    internal abstract int Changes { get; }
    /// <summary>
    /// Shutdown the SQLite engine so that it can be restarted with different config options.
    /// We depend on auto initialization to recover.
    /// </summary>
    internal abstract int Shutdown();
    /// <summary>
    /// Returns non-zero if a database connection is open.
    /// </summary>
    /// <returns></returns>
    internal abstract bool IsOpen();
    /// <summary>
    /// Opens a database.
    /// </summary>
    /// <remarks>
    /// Implementers should call SQLiteFunction.BindFunctions() and save the array after opening a connection
    /// to bind all attributed user-defined functions and collating sequences to the new connection.
    /// </remarks>
    /// <param name="strFilename">The filename of the database to open.  SQLite automatically creates it if it doesn't exist.</param>







|
|








<
<
<
<









<
<
<
<
<







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

  /// <summary>
  /// This internal class provides the foundation of SQLite support.  It defines all the abstract members needed to implement
  /// a SQLite data provider, and inherits from SQLiteConvert which allows for simple translations of string to and from SQLite.
  /// </summary>
  internal abstract class SQLiteBase : SQLiteConvert, IDisposable
  {
    internal SQLiteBase(SQLiteDateFormats fmt)
      : base(fmt) { }

    static internal object _lock = new object();

    /// <summary>
    /// Returns a string representing the active version of SQLite
    /// </summary>
    internal abstract string Version { get; }
    /// <summary>




    /// Returns the number of changes the last executing insert/update caused.
    /// </summary>
    internal abstract int Changes { get; }
    /// <summary>
    /// Shutdown the SQLite engine so that it can be restarted with different config options.
    /// We depend on auto initialization to recover.
    /// </summary>
    internal abstract int Shutdown();
    /// <summary>





    /// Opens a database.
    /// </summary>
    /// <remarks>
    /// Implementers should call SQLiteFunction.BindFunctions() and save the array after opening a connection
    /// to bind all attributed user-defined functions and collating sequences to the new connection.
    /// </remarks>
    /// <param name="strFilename">The filename of the database to open.  SQLite automatically creates it if it doesn't exist.</param>
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
    internal abstract object GetValue(SQLiteStatement stmt, int index, SQLiteType typ);

    internal abstract bool AutoCommit
    {
      get;
    }

    internal abstract int FileControl(string zDbName, int op, IntPtr pArg);

    protected virtual void Dispose(bool bDisposing)
    {
    }

    public void Dispose()
    {
      Dispose(true);







<
<







196
197
198
199
200
201
202


203
204
205
206
207
208
209
    internal abstract object GetValue(SQLiteStatement stmt, int index, SQLiteType typ);

    internal abstract bool AutoCommit
    {
      get;
    }



    protected virtual void Dispose(bool bDisposing)
    {
    }

    public void Dispose()
    {
      Dispose(true);
Changes to System.Data.SQLite/SQLiteCommand.cs.
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  using System.Collections.Generic;
  using System.ComponentModel;

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







|







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  using System.Collections.Generic;
  using System.ComponentModel;

  /// <summary>
  /// SQLite implementation of DbCommand.
  /// </summary>
#if !PLATFORM_COMPACTFRAMEWORK
  [Designer("SQLite.Designer.SQLiteCommandDesigner, SQLite.Designer, Version=1.0.38.1, 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;
Changes to System.Data.SQLite/SQLiteConnection.cs.
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
  /// <item>
  /// <description>DateTimeFormat</description>
  /// <description><b>Ticks</b> - Use DateTime.Ticks<br/><b>ISO8601</b> - Use ISO8601 DateTime format</description>
  /// <description>N</description>
  /// <description>ISO8601</description>
  /// </item>
  /// <item>
  /// <description>DateTimeKind</description>
  /// <description><b>Unspecified</b> - Not specified as either UTC or local time.<br/><b>Utc</b> - The time represented is UTC.<br/><b>Local</b> - The time represented is local time.</description>
  /// <description>N</description>
  /// <description>Unspecified</description>
  /// </item>
  /// <item>
  /// <description>BaseSchemaName</description>
  /// <description>Some base data classes in the framework (e.g. those that build SQL queries dynamically)
  /// assume that an ADO.NET provider cannot support an alternate catalog (i.e. database) without supporting
  /// alternate schemas as well; however, SQLite does not fit into this model.  Therefore, this value is used
  /// as a placeholder and removed prior to preparing any SQL statements that may contain it.</description>
  /// <description>N</description>
  /// <description>sqlite_default_schema</description>
  /// </item>
  /// <item>
  /// <description>BinaryGUID</description>
  /// <description><b>True</b> - Store GUID columns in binary form<br/><b>False</b> - Store GUID columns as text</description>
  /// <description>N</description>
  /// <description>True</description>
  /// </item>
  /// <item>
  /// <description>Cache Size</description>







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







49
50
51
52
53
54
55















56
57
58
59
60
61
62
  /// <item>
  /// <description>DateTimeFormat</description>
  /// <description><b>Ticks</b> - Use DateTime.Ticks<br/><b>ISO8601</b> - Use ISO8601 DateTime format</description>
  /// <description>N</description>
  /// <description>ISO8601</description>
  /// </item>
  /// <item>















  /// <description>BinaryGUID</description>
  /// <description><b>True</b> - Store GUID columns in binary form<br/><b>False</b> - Store GUID columns as text</description>
  /// <description>N</description>
  /// <description>True</description>
  /// </item>
  /// <item>
  /// <description>Cache Size</description>
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
  /// <description>N</description>
  /// <description>False</description>
  /// </item>
  /// </list>
  /// </remarks>
  public sealed partial class SQLiteConnection : DbConnection, ICloneable
  {
    /// <summary>
    /// The default "stub" (i.e. placeholder) base schema name to use when
    /// returning column schema information.  Used as the initial value of
    /// the BaseSchemaName property.  This should start with "sqlite_*"
    /// because those names are reserved for use by SQLite (i.e. they cannot
    /// be confused with the names of user objects).
    /// </summary>
    private const string DefaultBaseSchemaName = "sqlite_default_schema";

    private const int SQLITE_FCNTL_WIN32_AV_RETRY = 9;

    private const string _dataDirectory = "|DataDirectory|";
    private const string _masterdb = "sqlite_master";
    private const string _tempmasterdb = "sqlite_temp_master";

    /// <summary>
    /// State of the current connection
    /// </summary>







<
<
<
<
<
<
<
<
<
<
<







148
149
150
151
152
153
154











155
156
157
158
159
160
161
  /// <description>N</description>
  /// <description>False</description>
  /// </item>
  /// </list>
  /// </remarks>
  public sealed partial class SQLiteConnection : DbConnection, ICloneable
  {











    private const string _dataDirectory = "|DataDirectory|";
    private const string _masterdb = "sqlite_master";
    private const string _tempmasterdb = "sqlite_temp_master";

    /// <summary>
    /// State of the current connection
    /// </summary>
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
    /// </summary>
    private string _dataSource;
    /// <summary>
    /// Temporary password storage, emptied after the database has been opened
    /// </summary>
    private byte[] _password;

    /// <summary>
    /// The "stub" (i.e. placeholder) base schema name to use when returning
    /// column schema information.
    /// </summary>
    internal string _baseSchemaName;

    /// <summary>
    /// Default command timeout
    /// </summary>
    private int _defaultTimeout = 30;

    internal bool _binaryGuid;








<
<
<
<
<
<







189
190
191
192
193
194
195






196
197
198
199
200
201
202
    /// </summary>
    private string _dataSource;
    /// <summary>
    /// Temporary password storage, emptied after the database has been opened
    /// </summary>
    private byte[] _password;







    /// <summary>
    /// Default command timeout
    /// </summary>
    private int _defaultTimeout = 30;

    internal bool _binaryGuid;

262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279

    /// <summary>
    /// Initializes the connection with the specified connection string
    /// </summary>
    /// <param name="connectionString">The connection string to use on the connection</param>
    public SQLiteConnection(string connectionString)
    {
#if !PLATFORM_COMPACTFRAMEWORK
      SQLiteLog.Initialize();
#endif

      _connectionState = ConnectionState.Closed;
      _connectionString = "";
      //_commandList = new List<WeakReference>();

      if (connectionString != null)
        ConnectionString = connectionString;
    }







<
<
<
<







230
231
232
233
234
235
236




237
238
239
240
241
242
243

    /// <summary>
    /// Initializes the connection with the specified connection string
    /// </summary>
    /// <param name="connectionString">The connection string to use on the connection</param>
    public SQLiteConnection(string connectionString)
    {




      _connectionState = ConnectionState.Closed;
      _connectionString = "";
      //_commandList = new List<WeakReference>();

      if (connectionString != null)
        ConnectionString = connectionString;
    }
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
    /// <description>N</description>
    /// <description>Serializable</description>
    /// </item>
    /// </list>
    /// </remarks>
#if !PLATFORM_COMPACTFRAMEWORK
    [RefreshProperties(RefreshProperties.All), DefaultValue("")]
    [Editor("SQLite.Designer.SQLiteConnectionStringEditor, SQLite.Designer, Version=" + SQLite3.DesignerVersion + ", Culture=neutral, PublicKeyToken=db937bc2d44ff139", "System.Drawing.Design.UITypeEditor, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
#endif
    public override string ConnectionString
    {
      get
      {
        return _connectionString;
      }







|







602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
    /// <description>N</description>
    /// <description>Serializable</description>
    /// </item>
    /// </list>
    /// </remarks>
#if !PLATFORM_COMPACTFRAMEWORK
    [RefreshProperties(RefreshProperties.All), DefaultValue("")]
    [Editor("SQLite.Designer.SQLiteConnectionStringEditor, SQLite.Designer, Version=1.0.38.1, Culture=neutral, PublicKeyToken=db937bc2d44ff139", "System.Drawing.Design.UITypeEditor, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
#endif
    public override string ConnectionString
    {
      get
      {
        return _connectionString;
      }
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
      get
      {
        return _dataSource;
      }
    }

    /// <summary>
    /// Returns the string "main".
    /// </summary>
#if !PLATFORM_COMPACTFRAMEWORK
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
#endif
    public override string Database
    {
      get







|







655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
      get
      {
        return _dataSource;
      }
    }

    /// <summary>
    /// Returns an empty string
    /// </summary>
#if !PLATFORM_COMPACTFRAMEWORK
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
#endif
    public override string Database
    {
      get
753
754
755
756
757
758
759



760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
#if !PLATFORM_COMPACTFRAMEWORK
    /// <summary>
    /// Manual distributed transaction enlistment support
    /// </summary>
    /// <param name="transaction">The distributed transaction to enlist in</param>
    public override void EnlistTransaction(System.Transactions.Transaction transaction)
    {



      if (_enlistment != null && transaction == _enlistment._scope)
        return;
      else if (_enlistment != null)
        throw new ArgumentException("Already enlisted in a transaction");

      if (_transactionLevel > 0 && transaction != null)
        throw new ArgumentException("Unable to enlist in transaction, a local transaction already exists");
      else if (transaction == null)
        throw new ArgumentNullException("Unable to enlist in transaction, it is null");

      _enlistment = new SQLiteEnlistment(this, transaction);
    }
#endif

    /// <summary>
    /// Looks for a key in the array of key/values of the parameter string.  If not found, return the specified default value
    /// </summary>







>
>
>





<
<
<
<
<







717
718
719
720
721
722
723
724
725
726
727
728
729
730
731





732
733
734
735
736
737
738
#if !PLATFORM_COMPACTFRAMEWORK
    /// <summary>
    /// Manual distributed transaction enlistment support
    /// </summary>
    /// <param name="transaction">The distributed transaction to enlist in</param>
    public override void EnlistTransaction(System.Transactions.Transaction transaction)
    {
      if (_transactionLevel > 0 && transaction != null)
        throw new ArgumentException("Unable to enlist in transaction, a local transaction already exists");

      if (_enlistment != null && transaction == _enlistment._scope)
        return;
      else if (_enlistment != null)
        throw new ArgumentException("Already enlisted in a transaction");






      _enlistment = new SQLiteEnlistment(this, transaction);
    }
#endif

    /// <summary>
    /// Looks for a key in the array of key/values of the parameter string.  If not found, return the specified default value
    /// </summary>
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

        _defaultTimeout = Convert.ToInt32(FindKey(opts, "Default Timeout", "30"), CultureInfo.CurrentCulture);

        _defaultIsolation = (IsolationLevel)Enum.Parse(typeof(IsolationLevel), FindKey(opts, "Default IsolationLevel", "Serializable"), true);
        if (_defaultIsolation != IsolationLevel.Serializable && _defaultIsolation != IsolationLevel.ReadCommitted)
          throw new NotSupportedException("Invalid Default IsolationLevel specified");

        _baseSchemaName = FindKey(opts, "BaseSchemaName", DefaultBaseSchemaName);

        //string temp = FindKey(opts, "DateTimeFormat", "ISO8601");
        //if (String.Compare(temp, "ticks", StringComparison.OrdinalIgnoreCase) == 0) dateFormat = SQLiteDateFormats.Ticks;
        //else if (String.Compare(temp, "julianday", StringComparison.OrdinalIgnoreCase) == 0) dateFormat = SQLiteDateFormats.JulianDay;

        if (_sql == null)
        {
          bool bUTF16 = (SQLiteConvert.ToBoolean(FindKey(opts, "UseUTF16Encoding", Boolean.FalseString)) == true);
          SQLiteDateFormats dateFormat = (SQLiteDateFormats)Enum.Parse(typeof(SQLiteDateFormats),
                                                                       FindKey(opts, "DateTimeFormat", "ISO8601"),
                                                                       true);

          DateTimeKind kind = (DateTimeKind)Enum.Parse(typeof(DateTimeKind),
              FindKey(opts, "DateTimeKind", "Unspecified"), true);

          if (bUTF16) // SQLite automatically sets the encoding of the database to UTF16 if called from sqlite3_open16()
            _sql = new SQLite3_UTF16(dateFormat, kind);
          else
            _sql = new SQLite3(dateFormat, kind);
        }

        SQLiteOpenFlagsEnum flags = SQLiteOpenFlagsEnum.None;

        if (SQLiteConvert.ToBoolean(FindKey(opts, "FailIfMissing", Boolean.FalseString)) == false)
          flags |= SQLiteOpenFlagsEnum.Create;








<
<











<
<
<

|

|







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

        _defaultTimeout = Convert.ToInt32(FindKey(opts, "Default Timeout", "30"), CultureInfo.CurrentCulture);

        _defaultIsolation = (IsolationLevel)Enum.Parse(typeof(IsolationLevel), FindKey(opts, "Default IsolationLevel", "Serializable"), true);
        if (_defaultIsolation != IsolationLevel.Serializable && _defaultIsolation != IsolationLevel.ReadCommitted)
          throw new NotSupportedException("Invalid Default IsolationLevel specified");



        //string temp = FindKey(opts, "DateTimeFormat", "ISO8601");
        //if (String.Compare(temp, "ticks", StringComparison.OrdinalIgnoreCase) == 0) dateFormat = SQLiteDateFormats.Ticks;
        //else if (String.Compare(temp, "julianday", StringComparison.OrdinalIgnoreCase) == 0) dateFormat = SQLiteDateFormats.JulianDay;

        if (_sql == null)
        {
          bool bUTF16 = (SQLiteConvert.ToBoolean(FindKey(opts, "UseUTF16Encoding", Boolean.FalseString)) == true);
          SQLiteDateFormats dateFormat = (SQLiteDateFormats)Enum.Parse(typeof(SQLiteDateFormats),
                                                                       FindKey(opts, "DateTimeFormat", "ISO8601"),
                                                                       true);




          if (bUTF16) // SQLite automatically sets the encoding of the database to UTF16 if called from sqlite3_open16()
            _sql = new SQLite3_UTF16(dateFormat);
          else
            _sql = new SQLite3(dateFormat);
        }

        SQLiteOpenFlagsEnum flags = SQLiteOpenFlagsEnum.None;

        if (SQLiteConvert.ToBoolean(FindKey(opts, "FailIfMissing", Boolean.FalseString)) == false)
          flags |= SQLiteOpenFlagsEnum.Create;

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
        //if (_connectionState != ConnectionState.Open)
        //  throw new InvalidOperationException();

        //return _sql.Version;
      }
    }

    /// <summary>
    /// Returns the rowid of the most recent successful INSERT into the database from this connection.
    /// </summary>
#if !PLATFORM_COMPACTFRAMEWORK
    [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
#endif
    public long LastInsertRowId
    {
      get
      {
        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)]
#endif
    public int Changes
    {
      get
      {
        if (_sql == null)
          throw new InvalidOperationException("Database connection not valid for getting number of changes.");

        return _sql.Changes;
      }
    }

    /// <summary>
    /// Returns the version of the underlying SQLite database engine
    /// </summary>
    public static string SQLiteVersion
    {
      get { return SQLite3.SQLiteVersion; }
    }







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







956
957
958
959
960
961
962



































963
964
965
966
967
968
969
        //if (_connectionState != ConnectionState.Open)
        //  throw new InvalidOperationException();

        //return _sql.Version;
      }
    }




































    /// <summary>
    /// Returns the version of the underlying SQLite database engine
    /// </summary>
    public static string SQLiteVersion
    {
      get { return SQLite3.SQLiteVersion; }
    }
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
            SortedList<string, string> opts = ParseConnectionString(_connectionString);

            bool bUTF16 = (SQLiteConvert.ToBoolean(FindKey(opts, "UseUTF16Encoding", Boolean.FalseString)) == true);
            SQLiteDateFormats dateFormat = (SQLiteDateFormats)Enum.Parse(typeof(SQLiteDateFormats),
                                                                         FindKey(opts, "DateTimeFormat", "ISO8601"),
                                                                         true);

            DateTimeKind kind = (DateTimeKind)Enum.Parse(typeof(DateTimeKind),
                FindKey(opts, "DateTimeKind", "Unspecified"), true);

            if (bUTF16) // SQLite automatically sets the encoding of the database to UTF16 if called from sqlite3_open16()
                _sql = new SQLite3_UTF16(dateFormat, kind);
            else
                _sql = new SQLite3(dateFormat, kind);
        }
        if (_sql != null) return _sql.Shutdown();
        throw new InvalidOperationException("Database connection not active.");
    }

    /// Enables or disabled extended result codes returned by SQLite
    public void SetExtendedResultCodes(bool bOnOff)







<
<
<

|

|







991
992
993
994
995
996
997



998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
            SortedList<string, string> opts = ParseConnectionString(_connectionString);

            bool bUTF16 = (SQLiteConvert.ToBoolean(FindKey(opts, "UseUTF16Encoding", Boolean.FalseString)) == true);
            SQLiteDateFormats dateFormat = (SQLiteDateFormats)Enum.Parse(typeof(SQLiteDateFormats),
                                                                         FindKey(opts, "DateTimeFormat", "ISO8601"),
                                                                         true);




            if (bUTF16) // SQLite automatically sets the encoding of the database to UTF16 if called from sqlite3_open16()
                _sql = new SQLite3_UTF16(dateFormat);
            else
                _sql = new SQLite3(dateFormat);
        }
        if (_sql != null) return _sql.Shutdown();
        throw new InvalidOperationException("Database connection not active.");
    }

    /// Enables or disabled extended result codes returned by SQLite
    public void SetExtendedResultCodes(bool bOnOff)
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

      if (databasePassword != null)
        if (databasePassword.Length == 0) databasePassword = null;

      _password = databasePassword;
    }

    /// <summary>
    /// Queries or modifies the number of retries or the retry interval (in milliseconds) for
    /// certain I/O operations that may fail due to anti-virus software.
    /// </summary>
    /// <param name="count">The number of times to retry the I/O operation.  A negative value
    /// will cause the current count to be queried and replace that negative value.</param>
    /// <param name="interval">The number of milliseconds to wait before retrying the I/O
    /// operation.  This number is multiplied by the number of retry attempts so far to come
    /// up with the final number of milliseconds to wait.  A negative value will cause the
    /// current interval to be queried and replace that negative value.</param>
    /// <returns>Zero for success, non-zero for error.</returns>
    public int SetAvRetry(ref int count, ref int interval)
    {
        if (_connectionState != ConnectionState.Open)
            throw new InvalidOperationException(
                "Database must be opened before changing the AV retry parameters.");

        int rc;
        IntPtr pArg = IntPtr.Zero;

        try
        {
            pArg = Marshal.AllocHGlobal(sizeof(int) * 2);

            Marshal.WriteInt32(pArg, 0, count);
            Marshal.WriteInt32(pArg, sizeof(int), interval);

            rc = _sql.FileControl(null, SQLITE_FCNTL_WIN32_AV_RETRY, pArg);

            if (rc == 0)
            {
                count = Marshal.ReadInt32(pArg, 0);
                interval = Marshal.ReadInt32(pArg, sizeof(int));
            }
        }
        finally
        {
            if (pArg != IntPtr.Zero)
                Marshal.FreeHGlobal(pArg);
        }

        return rc;
    }

    /// <summary>
    /// Expand the filename of the data source, resolving the |DataDirectory| macro as appropriate.
    /// </summary>
    /// <param name="sourceFile">The database filename to expand</param>
    /// <returns>The expanded path and filename of the filename</returns>
    private string ExpandFileName(string sourceFile)
    {







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







1081
1082
1083
1084
1085
1086
1087












































1088
1089
1090
1091
1092
1093
1094

      if (databasePassword != null)
        if (databasePassword.Length == 0) databasePassword = null;

      _password = databasePassword;
    }













































    /// <summary>
    /// Expand the filename of the data source, resolving the |DataDirectory| macro as appropriate.
    /// </summary>
    /// <param name="sourceFile">The database filename to expand</param>
    /// <returns>The expanded path and filename of the filename</returns>
    private string ExpandFileName(string sourceFile)
    {
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
      tbl.Columns.Add("INITIALLY_DEFERRED", typeof(bool));
      tbl.Columns.Add("FKEY_FROM_COLUMN", typeof(string));
      tbl.Columns.Add("FKEY_FROM_ORDINAL_POSITION", typeof(int));
      tbl.Columns.Add("FKEY_TO_CATALOG", typeof(string));
      tbl.Columns.Add("FKEY_TO_SCHEMA", typeof(string));
      tbl.Columns.Add("FKEY_TO_TABLE", typeof(string));
      tbl.Columns.Add("FKEY_TO_COLUMN", typeof(string));
      tbl.Columns.Add("FKEY_ON_UPDATE", typeof(string));
      tbl.Columns.Add("FKEY_ON_DELETE", typeof(string));
      tbl.Columns.Add("FKEY_MATCH", typeof(string));

      if (String.IsNullOrEmpty(strCatalog)) strCatalog = "main";

      string master = (String.Compare(strCatalog, "temp", StringComparison.OrdinalIgnoreCase) == 0) ? _tempmasterdb : _masterdb;

      tbl.BeginLoadData();








<
<
<







2150
2151
2152
2153
2154
2155
2156



2157
2158
2159
2160
2161
2162
2163
      tbl.Columns.Add("INITIALLY_DEFERRED", typeof(bool));
      tbl.Columns.Add("FKEY_FROM_COLUMN", typeof(string));
      tbl.Columns.Add("FKEY_FROM_ORDINAL_POSITION", typeof(int));
      tbl.Columns.Add("FKEY_TO_CATALOG", typeof(string));
      tbl.Columns.Add("FKEY_TO_SCHEMA", typeof(string));
      tbl.Columns.Add("FKEY_TO_TABLE", typeof(string));
      tbl.Columns.Add("FKEY_TO_COLUMN", typeof(string));




      if (String.IsNullOrEmpty(strCatalog)) strCatalog = "main";

      string master = (String.Compare(strCatalog, "temp", StringComparison.OrdinalIgnoreCase) == 0) ? _tempmasterdb : _masterdb;

      tbl.BeginLoadData();

2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
                  row["IS_DEFERRABLE"] = false;
                  row["INITIALLY_DEFERRED"] = false;
                  row["FKEY_FROM_COLUMN"] = builder.UnquoteIdentifier(rdKey[3].ToString());
                  row["FKEY_TO_CATALOG"] = strCatalog;
                  row["FKEY_TO_TABLE"] = builder.UnquoteIdentifier(rdKey[2].ToString());
                  row["FKEY_TO_COLUMN"] = builder.UnquoteIdentifier(rdKey[4].ToString());
                  row["FKEY_FROM_ORDINAL_POSITION"] = rdKey[1];
                  row["FKEY_ON_UPDATE"] = (rdKey.FieldCount > 5) ? rdKey[5] : String.Empty;
                  row["FKEY_ON_DELETE"] = (rdKey.FieldCount > 6) ? rdKey[6] : String.Empty;
                  row["FKEY_MATCH"] = (rdKey.FieldCount > 7) ? rdKey[7] : String.Empty;

                  if (String.IsNullOrEmpty(strKeyName) || String.Compare(strKeyName, row["CONSTRAINT_NAME"].ToString(), StringComparison.OrdinalIgnoreCase) == 0)
                    tbl.Rows.Add(row);
                }
              }
            }
            catch (SQLiteException)







<
<
<







2187
2188
2189
2190
2191
2192
2193



2194
2195
2196
2197
2198
2199
2200
                  row["IS_DEFERRABLE"] = false;
                  row["INITIALLY_DEFERRED"] = false;
                  row["FKEY_FROM_COLUMN"] = builder.UnquoteIdentifier(rdKey[3].ToString());
                  row["FKEY_TO_CATALOG"] = strCatalog;
                  row["FKEY_TO_TABLE"] = builder.UnquoteIdentifier(rdKey[2].ToString());
                  row["FKEY_TO_COLUMN"] = builder.UnquoteIdentifier(rdKey[4].ToString());
                  row["FKEY_FROM_ORDINAL_POSITION"] = rdKey[1];




                  if (String.IsNullOrEmpty(strKeyName) || String.Compare(strKeyName, row["CONSTRAINT_NAME"].ToString(), StringComparison.OrdinalIgnoreCase) == 0)
                    tbl.Rows.Add(row);
                }
              }
            }
            catch (SQLiteException)
Changes to System.Data.SQLite/SQLiteConnectionStringBuilder.cs.
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
      }
    }

    /// <summary>
    /// Gets/Sets the datetime format for the connection.
    /// </summary>
    [Browsable(true)]
    [DefaultValue(SQLiteDateFormats.Default)]
    public SQLiteDateFormats DateTimeFormat
    {
      get
      {
        object value;
        TryGetValue("datetimeformat", out value);
        if (value is string)







|







389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
      }
    }

    /// <summary>
    /// Gets/Sets the datetime format for the connection.
    /// </summary>
    [Browsable(true)]
    [DefaultValue(SQLiteDateFormats.ISO8601)]
    public SQLiteDateFormats DateTimeFormat
    {
      get
      {
        object value;
        TryGetValue("datetimeformat", out value);
        if (value is string)
Changes to System.Data.SQLite/SQLiteConvert.cs.
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
  using System.Text;

  /// <summary>
  /// This base class provides datatype conversion services for the SQLite provider.
  /// </summary>
  public abstract class SQLiteConvert
  {
    /// <summary>
    /// The value for the Unix epoch (e.g. January 1, 1970 at midnight, in UTC).
    /// </summary>
    protected static readonly DateTime UnixEpoch =
        new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

    /// <summary>
    /// The value of the OLE Automation epoch represented as a Julian day.
    /// </summary>
    private static readonly double OleAutomationEpochAsJulianDay = 2415018.5;

    /// <summary>
    /// The format string for DateTime values when using the InvariantCulture or CurrentCulture formats.
    /// </summary>
    private const string FullFormat = "yyyy-MM-ddTHH:mm:ss.fffffffK";

    /// <summary>
    /// An array of ISO8601 datetime formats we support conversion from
    /// </summary>
    private static string[] _datetimeFormats = new string[] {
      "THHmmssK",
      "THHmmK",
      "HH:mm:ss.FFFFFFFK",
      "HH:mm:ssK",
      "HH:mmK",
      "yyyy-MM-dd HH:mm:ss.FFFFFFFK", /* NOTE: UTC default (5). */
      "yyyy-MM-dd HH:mm:ssK",
      "yyyy-MM-dd HH:mmK",
      "yyyy-MM-ddTHH:mm:ss.FFFFFFFK",
      "yyyy-MM-ddTHH:mmK",
      "yyyy-MM-ddTHH:mm:ssK",
      "yyyyMMddHHmmssK",
      "yyyyMMddHHmmK",
      "yyyyMMddTHHmmssFFFFFFFK",
      "THHmmss",
      "THHmm",
      "HH:mm:ss.FFFFFFF",
      "HH:mm:ss",
      "HH:mm",
      "yyyy-MM-dd HH:mm:ss.FFFFFFF", /* NOTE: Non-UTC default (19). */
      "yyyy-MM-dd HH:mm:ss",
      "yyyy-MM-dd HH:mm",
      "yyyy-MM-ddTHH:mm:ss.FFFFFFF",
      "yyyy-MM-ddTHH:mm",
      "yyyy-MM-ddTHH:mm:ss",
      "yyyyMMddHHmmss",
      "yyyyMMddHHmm",
      "yyyyMMddTHHmmssFFFFFFF",
      "yyyy-MM-dd",
      "yyyyMMdd",
      "yy-MM-dd"
    };

    /// <summary>
    /// An UTF-8 Encoding instance, so we can convert strings to and from UTF-8
    /// </summary>
    private static Encoding _utf8 = new UTF8Encoding();
    /// <summary>
    /// The default DateTime format for this instance
    /// </summary>
    internal SQLiteDateFormats _datetimeFormat;
    /// <summary>
    /// The default DateTimeKind for this instance.
    /// </summary>
    internal DateTimeKind _datetimeKind;
    /// <summary>
    /// Initializes the conversion class
    /// </summary>
    /// <param name="fmt">The default date/time format to use for this instance</param>
    /// <param name="kind">The DateTimeKind to use.</param>
    internal SQLiteConvert(SQLiteDateFormats fmt, DateTimeKind kind)
    {
      _datetimeFormat = fmt;
      _datetimeKind = kind;
    }

    #region UTF-8 Conversion Functions
    /// <summary>
    /// Converts a string to a UTF-8 encoded byte array sized to include a null-terminating character.
    /// </summary>
    /// <param name="sourceText">The string to convert to UTF-8</param>







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




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

|






<
|
<











<
<
<
<



<
|


<







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
  using System.Text;

  /// <summary>
  /// This base class provides datatype conversion services for the SQLite provider.
  /// </summary>
  public abstract class SQLiteConvert
  {
















    /// <summary>
    /// An array of ISO8601 datetime formats we support conversion from
    /// </summary>
    private static string[] _datetimeFormats = new string[] {
      "THHmmss",
      "THHmm",
      "HH:mm:ss",
      "HH:mm",
      "HH:mm:ss.FFFFFFF",


      "yy-MM-dd",


      "yyyy-MM-dd",








      "yyyy-MM-dd HH:mm:ss.FFFFFFF",
      "yyyy-MM-dd HH:mm:ss",
      "yyyy-MM-dd HH:mm",                               
      "yyyy-MM-ddTHH:mm:ss.FFFFFFF",
      "yyyy-MM-ddTHH:mm",
      "yyyy-MM-ddTHH:mm:ss",
      "yyyyMMddHHmmss",
      "yyyyMMddHHmm",
      "yyyyMMddTHHmmssFFFFFFF",

      "yyyyMMdd"

    };

    /// <summary>
    /// An UTF-8 Encoding instance, so we can convert strings to and from UTF-8
    /// </summary>
    private static Encoding _utf8 = new UTF8Encoding();
    /// <summary>
    /// The default DateTime format for this instance
    /// </summary>
    internal SQLiteDateFormats _datetimeFormat;
    /// <summary>




    /// Initializes the conversion class
    /// </summary>
    /// <param name="fmt">The default date/time format to use for this instance</param>

    internal SQLiteConvert(SQLiteDateFormats fmt)
    {
      _datetimeFormat = fmt;

    }

    #region UTF-8 Conversion Functions
    /// <summary>
    /// Converts a string to a UTF-8 encoded byte array sized to include a null-terminating character.
    /// </summary>
    /// <param name="sourceText">The string to convert to UTF-8</param>
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

    #region DateTime Conversion Functions
    /// <summary>
    /// Converts a string into a DateTime, using the current DateTimeFormat specified for the connection when it was opened.
    /// </summary>
    /// <remarks>
    /// Acceptable ISO8601 DateTime formats are:
    /// <list type="bullet">
    /// <item><description>THHmmssK</description></item>
    /// <item><description>THHmmK</description></item>
    /// <item><description>HH:mm:ss.FFFFFFFK</description></item>
    /// <item><description>HH:mm:ssK</description></item>
    /// <item><description>HH:mmK</description></item>
    /// <item><description>yyyy-MM-dd HH:mm:ss.FFFFFFFK</description></item>
    /// <item><description>yyyy-MM-dd HH:mm:ssK</description></item>
    /// <item><description>yyyy-MM-dd HH:mmK</description></item>
    /// <item><description>yyyy-MM-ddTHH:mm:ss.FFFFFFFK</description></item>
    /// <item><description>yyyy-MM-ddTHH:mmK</description></item>
    /// <item><description>yyyy-MM-ddTHH:mm:ssK</description></item>
    /// <item><description>yyyyMMddHHmmssK</description></item>
    /// <item><description>yyyyMMddHHmmK</description></item>
    /// <item><description>yyyyMMddTHHmmssFFFFFFFK</description></item>
    /// <item><description>THHmmss</description></item>
    /// <item><description>THHmm</description></item>
    /// <item><description>HH:mm:ss.FFFFFFF</description></item>
    /// <item><description>HH:mm:ss</description></item>
    /// <item><description>HH:mm</description></item>
    /// <item><description>yyyy-MM-dd HH:mm:ss.FFFFFFF</description></item>
    /// <item><description>yyyy-MM-dd HH:mm:ss</description></item>
    /// <item><description>yyyy-MM-dd HH:mm</description></item>
    /// <item><description>yyyy-MM-ddTHH:mm:ss.FFFFFFF</description></item>
    /// <item><description>yyyy-MM-ddTHH:mm</description></item>
    /// <item><description>yyyy-MM-ddTHH:mm:ss</description></item>
    /// <item><description>yyyyMMddHHmmss</description></item>
    /// <item><description>yyyyMMddHHmm</description></item>
    /// <item><description>yyyyMMddTHHmmssFFFFFFF</description></item>
    /// <item><description>yyyy-MM-dd</description></item>
    /// <item><description>yyyyMMdd</description></item>
    /// <item><description>yy-MM-dd</description></item>
    /// </list>
    /// If the string cannot be matched to one of the above formats, an exception will be thrown.
    /// </remarks>
    /// <param name="dateText">The string containing either a long integer number of 100-nanosecond units since
    /// System.DateTime.MinValue, a Julian day double, an integer number of seconds since the Unix epoch, a
    /// culture-independent formatted date and time string, a formatted date and time string in the current
    /// culture, or an ISO8601-format string.</param>
    /// <returns>A DateTime value</returns>
    public DateTime ToDateTime(string dateText)
    {
      return ToDateTime(dateText, _datetimeFormat, _datetimeKind);
    }

    /// <summary>
    /// Converts a string into a DateTime, using the specified DateTimeFormat and DateTimeKind.
    /// </summary>
    /// <remarks>
    /// Acceptable ISO8601 DateTime formats are:
    /// <list type="bullet">
    /// <item><description>THHmmssK</description></item>
    /// <item><description>THHmmK</description></item>
    /// <item><description>HH:mm:ss.FFFFFFFK</description></item>
    /// <item><description>HH:mm:ssK</description></item>
    /// <item><description>HH:mmK</description></item>
    /// <item><description>yyyy-MM-dd HH:mm:ss.FFFFFFFK</description></item>
    /// <item><description>yyyy-MM-dd HH:mm:ssK</description></item>
    /// <item><description>yyyy-MM-dd HH:mmK</description></item>
    /// <item><description>yyyy-MM-ddTHH:mm:ss.FFFFFFFK</description></item>
    /// <item><description>yyyy-MM-ddTHH:mmK</description></item>
    /// <item><description>yyyy-MM-ddTHH:mm:ssK</description></item>
    /// <item><description>yyyyMMddHHmmssK</description></item>
    /// <item><description>yyyyMMddHHmmK</description></item>
    /// <item><description>yyyyMMddTHHmmssFFFFFFFK</description></item>
    /// <item><description>THHmmss</description></item>
    /// <item><description>THHmm</description></item>
    /// <item><description>HH:mm:ss.FFFFFFF</description></item>
    /// <item><description>HH:mm:ss</description></item>
    /// <item><description>HH:mm</description></item>
    /// <item><description>yyyy-MM-dd HH:mm:ss.FFFFFFF</description></item>
    /// <item><description>yyyy-MM-dd HH:mm:ss</description></item>
    /// <item><description>yyyy-MM-dd HH:mm</description></item>
    /// <item><description>yyyy-MM-ddTHH:mm:ss.FFFFFFF</description></item>
    /// <item><description>yyyy-MM-ddTHH:mm</description></item>
    /// <item><description>yyyy-MM-ddTHH:mm:ss</description></item>
    /// <item><description>yyyyMMddHHmmss</description></item>
    /// <item><description>yyyyMMddHHmm</description></item>
    /// <item><description>yyyyMMddTHHmmssFFFFFFF</description></item>
    /// <item><description>yyyy-MM-dd</description></item>
    /// <item><description>yyyyMMdd</description></item>
    /// <item><description>yy-MM-dd</description></item>
    /// </list>
    /// If the string cannot be matched to one of the above formats, an exception will be thrown.
    /// </remarks>
    /// <param name="dateText">The string containing either a long integer number of 100-nanosecond units since
    /// System.DateTime.MinValue, a Julian day double, an integer number of seconds since the Unix epoch, a
    /// culture-independent formatted date and time string, a formatted date and time string in the current
    /// culture, or an ISO8601-format string.</param>
    /// <param name="format">The SQLiteDateFormats to use.</param>
    /// <param name="kind">The DateTimeKind to use.</param>
    /// <returns>A DateTime value</returns>
    public DateTime ToDateTime(string dateText, SQLiteDateFormats format, DateTimeKind kind)
    {
        switch (format)
        {
            case SQLiteDateFormats.Ticks:
                {
                    return new DateTime(Convert.ToInt64(
                        dateText, CultureInfo.InvariantCulture), kind);
                }
            case SQLiteDateFormats.JulianDay:
                {
                    return ToDateTime(Convert.ToDouble(
                        dateText, CultureInfo.InvariantCulture), kind);
                }
            case SQLiteDateFormats.UnixEpoch:
                {
                    return DateTime.SpecifyKind(
                        UnixEpoch.AddSeconds(Convert.ToInt32(
                        dateText, CultureInfo.InvariantCulture)), kind);
                }
            case SQLiteDateFormats.InvariantCulture:
                {
                    return DateTime.SpecifyKind(DateTime.Parse(
                        dateText, DateTimeFormatInfo.InvariantInfo,
                        kind == DateTimeKind.Utc ?
                            DateTimeStyles.AdjustToUniversal :
                            DateTimeStyles.None),
                        kind);
                }
            case SQLiteDateFormats.CurrentCulture:
                {
                    return DateTime.SpecifyKind(DateTime.Parse(
                        dateText, DateTimeFormatInfo.CurrentInfo,
                        kind == DateTimeKind.Utc ?
                            DateTimeStyles.AdjustToUniversal :
                            DateTimeStyles.None),
                        kind);
                }
            default:
                {
                    return DateTime.SpecifyKind(DateTime.ParseExact(
                        dateText, _datetimeFormats,
                        DateTimeFormatInfo.InvariantInfo,
                        kind == DateTimeKind.Utc ?
                            DateTimeStyles.AdjustToUniversal :
                            DateTimeStyles.None),
                        kind);
                }
        }
    }

    /// <summary>
    /// Converts a julianday value into a DateTime
    /// </summary>
    /// <param name="julianDay">The value to convert</param>
    /// <returns>A .NET DateTime</returns>
    public DateTime ToDateTime(double julianDay)
    {
      return ToDateTime(julianDay, _datetimeKind);
    }

    /// <summary>
    /// Converts a julianday value into a DateTime
    /// </summary>
    /// <param name="julianDay">The value to convert</param>
    /// <param name="kind">The DateTimeKind to use.</param>
    /// <returns>A .NET DateTime</returns>
    public DateTime ToDateTime(double julianDay, DateTimeKind kind)
    {
        return DateTime.SpecifyKind(
            DateTime.FromOADate(julianDay - OleAutomationEpochAsJulianDay), kind);
    }

    /// <summary>
    /// Converts a DateTime struct to a JulianDay double
    /// </summary>
    /// <param name="value">The DateTime to convert</param>
    /// <returns>The JulianDay value the Datetime represents</returns>
    public double ToJulianDay(DateTime value)
    {
      return value.ToOADate() + OleAutomationEpochAsJulianDay;
    }

    /// <summary>
    /// Converts a DateTime to a string value, using the current DateTimeFormat specified for the connection when it was opened.
    /// </summary>
    /// <param name="dateValue">The DateTime value to convert</param>
    /// <returns>Either a string containing the long integer number of 100-nanosecond units since System.DateTime.MinValue, a
    /// Julian day double, an integer number of seconds since the Unix epoch, a culture-independent formatted date and time
    /// string, a formatted date and time string in the current culture, or an ISO8601-format date/time string.</returns>
    public string ToString(DateTime dateValue)
    {
      switch (_datetimeFormat)
      {
        case SQLiteDateFormats.Ticks:
          return dateValue.Ticks.ToString(CultureInfo.InvariantCulture);
        case SQLiteDateFormats.JulianDay:
          return ToJulianDay(dateValue).ToString(CultureInfo.InvariantCulture);
        case SQLiteDateFormats.UnixEpoch:
          return ((long)(dateValue.Subtract(UnixEpoch).Ticks / TimeSpan.TicksPerSecond)).ToString();
        case SQLiteDateFormats.InvariantCulture:
          return dateValue.ToString(FullFormat, CultureInfo.InvariantCulture);
        case SQLiteDateFormats.CurrentCulture:
          return dateValue.ToString(FullFormat, CultureInfo.CurrentCulture);
        default:
          return (dateValue.Kind == DateTimeKind.Utc) ?
              dateValue.ToString(_datetimeFormats[5], CultureInfo.InvariantCulture) : // include "Z"
              dateValue.ToString(_datetimeFormats[19], CultureInfo.InvariantCulture);
      }
    }

    /// <summary>
    /// Internal function to convert a UTF-8 encoded IntPtr of the specified length to a DateTime.
    /// </summary>
    /// <remarks>







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

|
<
<
<



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









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









|






|
<
<








<
<
<
<
<
<

<
<
|







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

    #region DateTime Conversion Functions
    /// <summary>
    /// Converts a string into a DateTime, using the current DateTimeFormat specified for the connection when it was opened.
    /// </summary>
    /// <remarks>
    /// Acceptable ISO8601 DateTime formats are:







    ///   yyyy-MM-dd HH:mm:ss




    ///   yyyyMMddHHmmss

    ///   yyyyMMddTHHmmssfffffff






    ///   yyyy-MM-dd







    ///   yy-MM-dd
    ///   yyyyMMdd
    ///   HH:mm:ss
    ///   THHmmss

    /// </remarks>
    /// <param name="dateText">The string containing either a Tick value, a JulianDay double, or an ISO8601-format string</param>



    /// <returns>A DateTime value</returns>
    public DateTime ToDateTime(string dateText)
    {




















































      switch (_datetimeFormat)
      {
        case SQLiteDateFormats.Ticks:

          return new DateTime(Convert.ToInt64(dateText, CultureInfo.InvariantCulture));


        case SQLiteDateFormats.JulianDay:

          return ToDateTime(Convert.ToDouble(dateText, CultureInfo.InvariantCulture));


























        default:



          return DateTime.ParseExact(dateText, _datetimeFormats, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None);




      }

    }

    /// <summary>
    /// Converts a julianday value into a DateTime
    /// </summary>
    /// <param name="julianDay">The value to convert</param>
    /// <returns>A .NET DateTime</returns>
    public DateTime ToDateTime(double julianDay)
    {











      return DateTime.FromOADate(julianDay - 2415018.5);

    }

    /// <summary>
    /// Converts a DateTime struct to a JulianDay double
    /// </summary>
    /// <param name="value">The DateTime to convert</param>
    /// <returns>The JulianDay value the Datetime represents</returns>
    public double ToJulianDay(DateTime value)
    {
      return value.ToOADate() + 2415018.5;
    }

    /// <summary>
    /// Converts a DateTime to a string value, using the current DateTimeFormat specified for the connection when it was opened.
    /// </summary>
    /// <param name="dateValue">The DateTime value to convert</param>
    /// <returns>Either a string consisting of the tick count for DateTimeFormat.Ticks, a JulianDay double, or a date/time in ISO8601 format.</returns>


    public string ToString(DateTime dateValue)
    {
      switch (_datetimeFormat)
      {
        case SQLiteDateFormats.Ticks:
          return dateValue.Ticks.ToString(CultureInfo.InvariantCulture);
        case SQLiteDateFormats.JulianDay:
          return ToJulianDay(dateValue).ToString(CultureInfo.InvariantCulture);






        default:


          return dateValue.ToString(_datetimeFormats[7], CultureInfo.InvariantCulture);
      }
    }

    /// <summary>
    /// Internal function to convert a UTF-8 encoded IntPtr of the specified length to a DateTime.
    /// </summary>
    /// <remarks>
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
    /// </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)
    {
      if (String.IsNullOrEmpty(Name)) return DbType.Object;

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

      SQLiteTypeNames value;

      if (_typeNames.TryGetValue(Name, out value))
      {
        return value.dataType;
      }
      else
      {
        int index = Name.IndexOf('(');

        if ((index > 0) &&
            _typeNames.TryGetValue(Name.Substring(0, index), out value))
        {
          return value.dataType;
        }
      }

      return DbType.Object;
    }
    #endregion

    private static object _syncRoot = new object();






    private static Dictionary<string, SQLiteTypeNames> _typeNames = null;





































  }

  /// <summary>
  /// SQLite has very limited types, and is inherently text-based.  The first 5 types below represent the sum of all types SQLite
  /// understands.  The DateTime extension to the spec is for internal use only.
  /// </summary>
  public enum TypeAffinity







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

<
<
<
<
<
<
<
<
<
<
<




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







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
    /// </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)
    {
      if (String.IsNullOrEmpty(Name)) return DbType.Object;



      int x = _typeNames.Length;



      for (int n = 0; n < x; n++)















































      {




        if (String.Compare(Name, 0, _typeNames[n].typeName, 0, _typeNames[n].typeName.Length, StringComparison.OrdinalIgnoreCase) == 0)




          return _typeNames[n].dataType; 
      }











      return DbType.Object;
    }
    #endregion

    private static SQLiteTypeNames[] _typeNames = {
      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("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("SMALLDATE", 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),
    };
  }

  /// <summary>
  /// SQLite has very limited types, and is inherently text-based.  The first 5 types below represent the sum of all types SQLite
  /// understands.  The DateTime extension to the spec is for internal use only.
  /// </summary>
  public enum TypeAffinity
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
  public enum SQLiteDateFormats
  {
    /// <summary>
    /// Using ticks is not recommended and is not well supported with LINQ.
    /// </summary>
    Ticks = 0,
    /// <summary>
    /// The ISO8601 format
    /// </summary>
    ISO8601 = 1,
    /// <summary>
    /// JulianDay format, which is what SQLite uses internally
    /// </summary>
    JulianDay = 2,
    /// <summary>
    /// The whole number of seconds since the Unix epoch (January 1, 1970).
    /// </summary>
    UnixEpoch = 3,
    /// <summary>
    /// Any culture-independent string value that the .NET Framework can interpret as a valid DateTime.
    /// </summary>
    InvariantCulture = 4,
    /// <summary>
    /// Any string value that the .NET Framework can interpret as a valid DateTime using the current culture.
    /// </summary>
    CurrentCulture = 5,
    /// <summary>
    /// The default format for this provider.
    /// </summary>
    Default = ISO8601
  }

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







|





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







738
739
740
741
742
743
744
745
746
747
748
749
750
751
















752
753
754
755
756
757
758
  public enum SQLiteDateFormats
  {
    /// <summary>
    /// Using ticks is not recommended and is not well supported with LINQ.
    /// </summary>
    Ticks = 0,
    /// <summary>
    /// The default format for this provider.
    /// </summary>
    ISO8601 = 1,
    /// <summary>
    /// JulianDay format, which is what SQLite uses internally
    /// </summary>
    JulianDay = 2
















  }

  /// <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.
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
      typeName = newtypeName;
      dataType = newdataType;
    }

    internal string typeName;
    internal DbType dataType;
  }

  internal class TypeNameStringComparer : IEqualityComparer<string>
  {
    #region IEqualityComparer<string> Members
    public bool Equals(
      string left,
      string right
      )
    {
      return String.Equals(left, right, StringComparison.OrdinalIgnoreCase);
    }

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

    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();
#endif
      else
        throw new ArgumentNullException("value");
    }
    #endregion
  }
}







|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
822
823
824
825
826
827
828
829



































      typeName = newtypeName;
      dataType = newdataType;
    }

    internal string typeName;
    internal DbType dataType;
  }
}



































Changes to System.Data.SQLite/SQLiteDataAdapter.cs.
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  using System.ComponentModel;

  /// <summary>
  /// SQLite implementation of DbDataAdapter.
  /// </summary>
#if !PLATFORM_COMPACTFRAMEWORK
  [DefaultEvent("RowUpdated")]
  [ToolboxItem("SQLite.Designer.SQLiteDataAdapterToolboxItem, SQLite.Designer, Version=" + SQLite3.DesignerVersion + ", Culture=neutral, PublicKeyToken=db937bc2d44ff139")]
  [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();








|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  using System.ComponentModel;

  /// <summary>
  /// SQLite implementation of DbDataAdapter.
  /// </summary>
#if !PLATFORM_COMPACTFRAMEWORK
  [DefaultEvent("RowUpdated")]
  [ToolboxItem("SQLite.Designer.SQLiteDataAdapterToolboxItem, SQLite.Designer, Version=1.0.38.1, Culture=neutral, PublicKeyToken=db937bc2d44ff139")]
  [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();

Changes to System.Data.SQLite/SQLiteDataReader.cs.
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
    internal bool _disposing;

    /// <summary>
    /// An array of rowid's for the active statement if CommandBehavior.KeyInfo is specified
    /// </summary>
    private SQLiteKeyReader _keyInfo;

    /// <summary>
    /// Matches the version of the connection.
    /// </summary>
    internal long _version;

    /// <summary>
    /// The "stub" (i.e. placeholder) base schema name to use when returning
    /// column schema information.  Matches the base schema name used by the
    /// associated connection.
    /// </summary>
    private string _baseSchemaName;

    /// <summary>
    /// Internal constructor, initializes the datareader and sets up to begin executing statements
    /// </summary>
    /// <param name="cmd">The SQLiteCommand this data reader is for</param>
    /// <param name="behave">The expected behavior of the data reader</param>
    internal SQLiteDataReader(SQLiteCommand cmd, CommandBehavior behave)
    {
      _throwOnDisposed = true;
      _command = cmd;
      _version = _command.Connection._version;
      _baseSchemaName = _command.Connection._baseSchemaName;

      _commandBehavior = behave;
      _activeStatementIndex = -1;
      _rowsAffected = -1;

      if (_command != null)
        NextResult();







<
<
<
|
<
<
<
<
<
<
<











<







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
    internal bool _disposing;

    /// <summary>
    /// An array of rowid's for the active statement if CommandBehavior.KeyInfo is specified
    /// </summary>
    private SQLiteKeyReader _keyInfo;




    internal long _version; // Matches the version of the connection








    /// <summary>
    /// Internal constructor, initializes the datareader and sets up to begin executing statements
    /// </summary>
    /// <param name="cmd">The SQLiteCommand this data reader is for</param>
    /// <param name="behave">The expected behavior of the data reader</param>
    internal SQLiteDataReader(SQLiteCommand cmd, CommandBehavior behave)
    {
      _throwOnDisposed = true;
      _command = cmd;
      _version = _command.Connection._version;


      _commandBehavior = behave;
      _activeStatementIndex = -1;
      _rowsAffected = -1;

      if (_command != null)
        NextResult();
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
        row[SchemaTableOptionalColumn.IsReadOnly] = false;
        row[SchemaTableOptionalColumn.IsRowVersion] = false;
        row[SchemaTableColumn.IsUnique] = false;
        row[SchemaTableColumn.IsKey] = false;
        row[SchemaTableOptionalColumn.IsAutoIncrement] = false;
        row[SchemaTableColumn.DataType] = GetFieldType(n);
        row[SchemaTableOptionalColumn.IsHidden] = false;
        row[SchemaTableColumn.BaseSchemaName] = _baseSchemaName;

        strColumn = _command.Connection._sql.ColumnOriginalName(_activeStatement, n);
        if (String.IsNullOrEmpty(strColumn) == false) row[SchemaTableColumn.BaseColumnName] = strColumn;

        row[SchemaTableColumn.IsExpression] = String.IsNullOrEmpty(strColumn);
        row[SchemaTableColumn.IsAliased] = (String.Compare(GetName(n), strColumn, StringComparison.OrdinalIgnoreCase) != 0);








<







636
637
638
639
640
641
642

643
644
645
646
647
648
649
        row[SchemaTableOptionalColumn.IsReadOnly] = false;
        row[SchemaTableOptionalColumn.IsRowVersion] = false;
        row[SchemaTableColumn.IsUnique] = false;
        row[SchemaTableColumn.IsKey] = false;
        row[SchemaTableOptionalColumn.IsAutoIncrement] = false;
        row[SchemaTableColumn.DataType] = GetFieldType(n);
        row[SchemaTableOptionalColumn.IsHidden] = false;


        strColumn = _command.Connection._sql.ColumnOriginalName(_activeStatement, n);
        if (String.IsNullOrEmpty(strColumn) == false) row[SchemaTableColumn.BaseColumnName] = strColumn;

        row[SchemaTableColumn.IsExpression] = String.IsNullOrEmpty(strColumn);
        row[SchemaTableColumn.IsAliased] = (String.Compare(GetName(n), strColumn, StringComparison.OrdinalIgnoreCase) != 0);

892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
      CheckClosed();

      SQLiteStatement stmt = null;
      int fieldCount;

      while (true)
      {
        if (stmt == null && _activeStatement != null && _activeStatement._sql != null && _activeStatement._sql.IsOpen())
        {
          // Reset the previously-executed statement
          _activeStatement._sql.Reset(_activeStatement);

          // If we're only supposed to return a single rowset, step through all remaining statements once until
          // they are all done and return false to indicate no more resultsets exist.
          if ((_commandBehavior & CommandBehavior.SingleResult) != 0)







|







880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
      CheckClosed();

      SQLiteStatement stmt = null;
      int fieldCount;

      while (true)
      {
        if (_activeStatement != null && _activeStatement._sql != null && stmt == null)
        {
          // Reset the previously-executed statement
          _activeStatement._sql.Reset(_activeStatement);

          // If we're only supposed to return a single rowset, step through all remaining statements once until
          // they are all done and return false to indicate no more resultsets exist.
          if ((_commandBehavior & CommandBehavior.SingleResult) != 0)
Changes to System.Data.SQLite/SQLiteFactory.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
/********************************************************
 * 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;
































#if !PLATFORM_COMPACTFRAMEWORK
  /// <summary>
  /// SQLite implementation of DbProviderFactory.
  /// </summary>
  public sealed partial class SQLiteFactory : DbProviderFactory
  {













    /// <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.  This event is provided for backward compatibility only.
    /// New code should use the SQLiteLog class instead.
    /// </summary>
    public event SQLiteLogEventHandler Log
    {







      add { SQLiteLog.Log += value; }

      remove { SQLiteLog.Log -= value; }


















    }

    /// <overloads>
    /// Constructs a new SQLiteFactory object
    /// </overloads>
    /// <summary>
    /// Default constructor
    /// </summary>
    public SQLiteFactory()
    {
        //
        // NOTE: Do nothing here now.  All the logging setup related code has










        //       been moved to the new SQLiteLog static class.
        //







    }

    /// <summary>
    /// Static instance member which returns an instanced SQLiteFactory class.
    /// </summary>
    public static readonly SQLiteFactory Instance = new SQLiteFactory();












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







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



|
<



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










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







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

  /// <summary>
  /// Passed during an Log callback
  /// </summary>
  public class LogEventArgs : EventArgs
  {
      /// <summary>
      /// The error code.
      /// </summary>
      public readonly int ErrorCode;

      /// <summary>
      /// SQL statement text as the statement first begins executing
      /// </summary>
      public readonly string Message;

      internal LogEventArgs(IntPtr puser, int err_code, string message)
      {
          // puser should be NULL
          ErrorCode = err_code;
          Message = message;
      }
  }

  /// <summary>
  /// Raised when a log event occurs.
  /// </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>
  /// SQLite implementation of DbProviderFactory.
  /// </summary>
  public sealed partial class SQLiteFactory : DbProviderFactory
  {
    /// <summary>
    /// Member variable to store the application log handler to call.
    /// </summary>
    internal event SQLiteLogEventHandler _logHandler;
    /// <summary>
    /// The log callback passed to SQLite engine.
    /// </summary>
    private SQLiteLogCallback _logCallback;
    /// <summary>
    /// The base SQLite object to interop with.
    /// </summary>
    internal SQLiteBase _sql;

    /// <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 event SQLiteLogEventHandler Log
    {
        add
        {
            // Remove any copies of this event handler from registered list.
            // This essentially means that a handler will be called only once
            // no matter how many times it is added.
            _logHandler -= value;
            // add this to the list of event handlers
            _logHandler += value;
        }
        remove
        {
            _logHandler -= value;
        }
    }

    /// <summary>
    /// Internal proxy function that calls any registered application log
    /// event handlers.
    /// </summary>
    private void LogCallback(IntPtr puser, int err_code, IntPtr message)
    {
      // if there are any registered event handlers
      if (_logHandler != null)
        // call them
        _logHandler(this,
                    new LogEventArgs(puser,
                                     err_code,
                                     SQLiteBase.UTF8ToString(message, -1)));
    }

    /// <overloads>
    /// Constructs a new SQLiteFactory object
    /// </overloads>
    /// <summary>
    /// Default constructor
    /// </summary>
    public SQLiteFactory()
    {


      if (_sql == null)
      {
        _sql = new SQLite3(SQLiteDateFormats.ISO8601);
        if (_sql != null)
        {
          // Create a single "global" callback to register with SQLite.
          // This callback will pass the event on to any registered
          // handler.  We only want to do this once.
          if (_logCallback == null)
          {
            _logCallback = new SQLiteLogCallback(LogCallback);

            if (_logCallback != null)
            {
              _sql.SetLogCallback(_logCallback);
            }
          }
        }
      }
    }

    /// <summary>
    /// Static instance member which returns an instanced SQLiteFactory class.
    /// </summary>
    public static readonly SQLiteFactory Instance = new SQLiteFactory();

Deleted System.Data.SQLite/SQLiteLog.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
/********************************************************
 * 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;
    using System.Diagnostics;

    /// <summary>
    /// Passed during an Log callback
    /// </summary>
    public class LogEventArgs : EventArgs
    {
        /// <summary>
        /// The error code.
        /// </summary>
        public readonly int ErrorCode;

        /// <summary>
        /// SQL statement text as the statement first begins executing
        /// </summary>
        public readonly string Message;

        /// <summary>
        /// Extra data associated with this event, if any.
        /// </summary>
        public readonly object Data;

        /// <summary>
        /// Constructs the LogEventArgs object.
        /// </summary>
        /// <param name="pUserData">Should be null.</param>
        /// <param name="errorCode">The SQLite error code.</param>
        /// <param name="message">The error message, if any.</param>
        /// <param name="data">The extra data, if any.</param>
        internal LogEventArgs(
            IntPtr pUserData,
            int errorCode,
            string message,
            object data
            )
        {
            ErrorCode = errorCode;
            Message = message;
            Data = data;
        }
    }

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

    /// <summary>
    /// Raised when a log event occurs.
    /// </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()
        {
            //
            // 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);

                //
                // NOTE: Create a single "global" (i.e. per-process) callback
                //       to register with SQLite.  This callback will pass the
                //       event on to any registered handler.  We only want to
                //       do this once.
                //
                if (_callback == null)
                {
                    _callback = new SQLiteLogCallback(LogCallback);

                    int rc = _sql.SetLogCallback(_callback);

                    if (rc != 0)
                        throw new SQLiteException(rc,
                            "Failed to initialize logging.");
                }

                //
                // NOTE: Logging is enabled by default.
                //
                _enabled = true;

                //
                // NOTE: For now, always setup the default log event handler.
                //
                AddDefaultHandler();
            }
        }

        /// <summary>
        /// Handles the AppDomain being unloaded.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void DomainUnload(
            object sender,
            EventArgs e
            )
        {
            lock (syncRoot)
            {
                //
                // NOTE: Remove the default log event handler.
                //
                RemoveDefaultHandler();

                //
                // NOTE: Disable logging.  If necessary, it can be re-enabled
                //       later by the Initialize method.
                //
                _enabled = false;

                //
                // BUGBUG: This will cause serious problems if other AppDomains
                //         have any open SQLite connections; however, there is
                //         currently no way around this limitation.
                //
                if (_sql != null)
                {
                    int rc = _sql.Shutdown();

                    if (rc != 0)
                        throw new SQLiteException(rc,
                            "Failed to shutdown interface.");

                    rc = _sql.SetLogCallback(null);

                    if (rc != 0)
                        throw new SQLiteException(rc,
                            "Failed to shutdown logging.");
                }

                //
                // BUGFIX: Make sure to reset the callback for next time.  This
                //         must be done after it has been succesfully removed
                //         as logging callback by the SQLite core library as we
                //         cannot allow native code to refer to a delegate that
                //         has been garbage collected.
                //
                if (_callback != null)
                {
                    _callback = null;
                }

                //
                // NOTE: Remove the event handler for the DomainUnload event
                //       that we added earlier.
                //
                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
        {
            add
            {
                lock (syncRoot)
                {
                    // Remove any copies of this event handler from registered
                    // list.  This essentially means that a handler will be
                    // called only once no matter how many times it is added.
                    _handlers -= value;

                    // Add this to the list of event handlers.
                    _handlers += value;
                }
            }
            remove
            {
                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>
        /// 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.
        /// </summary>
        private static void LogCallback(
            IntPtr pUserData,
            int errorCode,
            IntPtr pMessage
            )
        {
            bool enabled;
            SQLiteLogEventHandler handlers;

            lock (syncRoot)
            {
                enabled = _enabled;
                handlers = _handlers;
            }

            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(
            object sender,
            LogEventArgs e
            )
        {
            if (e == null)
                return;

            string message = e.Message;

            if (message == null)
                message = "<null>";
            else if (message.Length == 0)
                message = "<empty>";

            Trace.WriteLine(String.Format("SQLite error ({0}): {1}",
                e.ErrorCode, message));
        }
    }
#endif
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


































































































































































































































































































































































































































































































































































































































































































































































Changes to System.Data.SQLite/SQLiteStatement.cs.
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
        objType = SQLiteConvert.TypeToDbType(obj.GetType());

      switch (objType)
      {
        case DbType.Date:
        case DbType.Time:
        case DbType.DateTime:
          //
          // NOTE: The old method (commented below) does not honor the selected date format
          //       for the connection.
          // _sql.Bind_DateTime(this, index, Convert.ToDateTime(obj, CultureInfo.CurrentCulture));
          _sql.Bind_DateTime(this, index, (obj is string) ?
              _sql.ToDateTime((string)obj) : Convert.ToDateTime(obj, CultureInfo.CurrentCulture));
          break;
        case DbType.Int64:
        case DbType.UInt64:
          _sql.Bind_Int64(this, index, Convert.ToInt64(obj, CultureInfo.CurrentCulture));
          break;
        case DbType.Boolean:
        case DbType.Int16:







<
<
<
|
<
<







173
174
175
176
177
178
179



180


181
182
183
184
185
186
187
        objType = SQLiteConvert.TypeToDbType(obj.GetType());

      switch (objType)
      {
        case DbType.Date:
        case DbType.Time:
        case DbType.DateTime:



          _sql.Bind_DateTime(this, index, Convert.ToDateTime(obj, CultureInfo.CurrentCulture));


          break;
        case DbType.Int64:
        case DbType.UInt64:
          _sql.Bind_Int64(this, index, Convert.ToInt64(obj, CultureInfo.CurrentCulture));
          break;
        case DbType.Boolean:
        case DbType.Int16:
Changes to System.Data.SQLite/System.Data.SQLite.2010.csproj.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{AC139952-261A-4463-B6FA-AEBC25283A66}</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>System.Data.SQLite</RootNamespace>
    <AssemblyName>System.Data.SQLite</AssemblyName>
    <OldToolsVersion>3.5</OldToolsVersion>
    <TargetFrameworkProfile>Client</TargetFrameworkProfile>
    <SQLiteNetDir>$(MSBuildProjectDirectory)\..</SQLiteNetDir>
    <ConfigurationYear>2010</ConfigurationYear>
  </PropertyGroup>
  <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets" />
  <PropertyGroup Condition="'$(BinaryOutputPath)' != ''">
    <OutputPath>$(BinaryOutputPath)</OutputPath>
    <DocumentationFile>$(BinaryOutputPath)System.Data.SQLite.xml</DocumentationFile>







<







15
16
17
18
19
20
21

22
23
24
25
26
27
28
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{AC139952-261A-4463-B6FA-AEBC25283A66}</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>System.Data.SQLite</RootNamespace>
    <AssemblyName>System.Data.SQLite</AssemblyName>
    <OldToolsVersion>3.5</OldToolsVersion>

    <SQLiteNetDir>$(MSBuildProjectDirectory)\..</SQLiteNetDir>
    <ConfigurationYear>2010</ConfigurationYear>
  </PropertyGroup>
  <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets" />
  <PropertyGroup Condition="'$(BinaryOutputPath)' != ''">
    <OutputPath>$(BinaryOutputPath)</OutputPath>
    <DocumentationFile>$(BinaryOutputPath)System.Data.SQLite.xml</DocumentationFile>
Changes to System.Data.SQLite/System.Data.SQLite.Files.targets.
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
    </Compile>
    <Compile Include="SQLiteDataReader.cs" />
    <Compile Include="SQLiteException.cs" />
    <Compile Include="SQLiteFactory.cs" />
    <Compile Include="SQLiteFunction.cs" />
    <Compile Include="SQLiteFunctionAttribute.cs" />
    <Compile Include="SQLiteKeyReader.cs" />
    <Compile Include="SQLiteLog.cs" />
    <Compile Include="SQLiteMetaDataCollectionNames.cs" />
    <Compile Include="SQLiteParameter.cs" />
    <Compile Include="SQLiteParameterCollection.cs" />
    <Compile Include="SQLiteStatement.cs" />
    <Compile Include="SQLiteTransaction.cs" />
    <Compile Include="SR.Designer.cs">
      <DependentUpon>SR.resx</DependentUpon>







<







35
36
37
38
39
40
41

42
43
44
45
46
47
48
    </Compile>
    <Compile Include="SQLiteDataReader.cs" />
    <Compile Include="SQLiteException.cs" />
    <Compile Include="SQLiteFactory.cs" />
    <Compile Include="SQLiteFunction.cs" />
    <Compile Include="SQLiteFunctionAttribute.cs" />
    <Compile Include="SQLiteKeyReader.cs" />

    <Compile Include="SQLiteMetaDataCollectionNames.cs" />
    <Compile Include="SQLiteParameter.cs" />
    <Compile Include="SQLiteParameterCollection.cs" />
    <Compile Include="SQLiteStatement.cs" />
    <Compile Include="SQLiteTransaction.cs" />
    <Compile Include="SR.Designer.cs">
      <DependentUpon>SR.resx</DependentUpon>
Changes to System.Data.SQLite/System.Data.SQLite.Module.2010.csproj.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{AC139952-261A-4463-B6FA-AEBC25284A66}</ProjectGuid>
    <OutputType>Module</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>System.Data.SQLite</RootNamespace>
    <AssemblyName>System.Data.SQLite</AssemblyName>
    <OldToolsVersion>3.5</OldToolsVersion>
    <TargetFrameworkProfile>Client</TargetFrameworkProfile>
    <SignAssembly>false</SignAssembly>
    <SQLiteNetDir>$(MSBuildProjectDirectory)\..</SQLiteNetDir>
    <ConfigurationYear>2010</ConfigurationYear>
    <ConfigurationSuffix>Module</ConfigurationSuffix>
    <UseInteropDll>false</UseInteropDll>
    <UseSqliteStandard>false</UseSqliteStandard>
  </PropertyGroup>







<







15
16
17
18
19
20
21

22
23
24
25
26
27
28
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{AC139952-261A-4463-B6FA-AEBC25284A66}</ProjectGuid>
    <OutputType>Module</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>System.Data.SQLite</RootNamespace>
    <AssemblyName>System.Data.SQLite</AssemblyName>
    <OldToolsVersion>3.5</OldToolsVersion>

    <SignAssembly>false</SignAssembly>
    <SQLiteNetDir>$(MSBuildProjectDirectory)\..</SQLiteNetDir>
    <ConfigurationYear>2010</ConfigurationYear>
    <ConfigurationSuffix>Module</ConfigurationSuffix>
    <UseInteropDll>false</UseInteropDll>
    <UseSqliteStandard>false</UseSqliteStandard>
  </PropertyGroup>
Changes to System.Data.SQLite/UnsafeNativeMethods.cs.
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
  internal static class UnsafeNativeMethods
  {
#if !SQLITE_STANDARD

#if !USE_INTEROP_DLL

#if !PLATFORM_COMPACTFRAMEWORK
    private const string SQLITE_DLL = "System.Data.SQLite.dll";
#else
    internal const string SQLITE_DLL = "SQLite.Interop.076.dll";
#endif // PLATFORM_COMPACTFRAMEWORK

#else
    private const string SQLITE_DLL = "SQLite.Interop.dll";
#endif // USE_INTEROP_DLL

#else
    private const string SQLITE_DLL = "sqlite3";
#endif

    // This section uses interop calls that also fetch text length to optimize conversion.  







|

|



|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
  internal static class UnsafeNativeMethods
  {
#if !SQLITE_STANDARD

#if !USE_INTEROP_DLL

#if !PLATFORM_COMPACTFRAMEWORK
    private const string SQLITE_DLL = "System.Data.SQLite.DLL";
#else
    internal const string SQLITE_DLL = "SQLite.Interop.074.DLL";
#endif // PLATFORM_COMPACTFRAMEWORK

#else
    private const string SQLITE_DLL = "SQLite.Interop.DLL";
#endif // USE_INTEROP_DLL

#else
    private const string SQLITE_DLL = "sqlite3";
#endif

    // This section uses interop calls that also fetch text length to optimize conversion.  
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern void sqlite3_interrupt(IntPtr db);

#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern long sqlite3_last_insert_rowid(IntPtr db);

#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern int sqlite3_changes(IntPtr db);








<
<
<
<
<
<
<







354
355
356
357
358
359
360







361
362
363
364
365
366
367
#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern void sqlite3_interrupt(IntPtr db);








#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern int sqlite3_changes(IntPtr db);

745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern void sqlite3_log(int iErrCode, byte[] zFormat);

#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern int sqlite3_file_control(IntPtr db, byte[] zDbName, int op, IntPtr pArg);

    #endregion
  }

#if PLATFORM_COMPACTFRAMEWORK
  internal abstract class CriticalHandle : IDisposable
  {
    private bool _isClosed;







<
<
<
<
<
<
<







738
739
740
741
742
743
744







745
746
747
748
749
750
751
#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern void sqlite3_log(int iErrCode, byte[] zFormat);








    #endregion
  }

#if PLATFORM_COMPACTFRAMEWORK
  internal abstract class CriticalHandle : IDisposable
  {
    private bool _isClosed;
Changes to Tests/all.eagle.
22
23
24
25
26
27
28

29
30
31
32
33
34
35
36
37
###############################################################################

#
# NOTE: Pre-load the assembly and the necessary helper procedures now, so that
#       they do not count as being "leaked" (i.e. the test framework has no way
#       to know who procedures actually belong to).
#

package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

set no(prologue.eagle) true
set no(epilogue.eagle) true

#







>
|
|







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
###############################################################################

#
# NOTE: Pre-load the assembly and the necessary helper procedures now, so that
#       they do not count as being "leaked" (i.e. the test framework has no way
#       to know who procedures actually belong to).
#
source [file join $path common.eagle]
tryLoadAssembly System.Data.SQLite.dll
tryLoadAssembly System.Data.SQLite.Linq.dll

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

set no(prologue.eagle) true
set no(epilogue.eagle) true

#
64
65
66
67
68
69
70
71
72
unset no(epilogue.eagle)
unset no(prologue.eagle)

if {[array size no] == 0} then {unset no}

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

runSQLiteTestEpilogue
runTestEpilogue







<

65
66
67
68
69
70
71

72
unset no(epilogue.eagle)
unset no(prologue.eagle)

if {[array size no] == 0} then {unset no}

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


runTestEpilogue
Changes to Tests/basic.eagle.
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
package require EagleLibrary
package require EagleTest

runTestPrologue

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


package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

#
# NOTE: Setup the variables that refer to the various files required by the
#       tests in this file.
#
set testExeFile [getBuildFileName test.exe]
set testLinqExeFile [getBuildFileName testlinq.exe]

set testLinqOutFile [file nativename [file join $path testlinq.out]]
set northwindEfDbFile [file nativename [file join [file dirname $path] \
    testlinq northwindEF.db]]

#
# NOTE: Setup the test constraints specific to the tests in this file.
#
if {![haveConstraint [appendArgs file_ [file tail $testExeFile]]]} then {
  checkForFile $test_channel $testExeFile
}

if {![haveConstraint [appendArgs file_ [file tail $testLinqExeFile]]]} then {
  checkForFile $test_channel $testLinqExeFile
}

if {![haveConstraint [appendArgs file_ [file tail $northwindEfDbFile]]]} then {
  checkForFile $test_channel $northwindEfDbFile
}

if {![haveConstraint [appendArgs file_ [file tail $testLinqOutFile]]]} then {
  checkForFile $test_channel $testLinqOutFile
}

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

runTest {test basic-1.1 {unit tests from the 'test' project} -setup {
  catch {file delete [file join [file dirname $testExeFile] Test.db3]}
} -body {
  set output ""

  set code [catch {
    testClrExec $testExeFile [list -eventflags Wait -directory \
    [file dirname $testExeFile] -stdout output -success 0] -autoRun
  } error]

  tlog "---- BEGIN STDOUT OUTPUT\n"
  tlog $output
  tlog "\n---- END STDOUT OUTPUT\n"

  list $code [expr {$code == 0 ? "" : $error}]
} -cleanup {
  unset -nocomplain code output error
} -constraints {eagle file_test.exe} -result {0 {}}}

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

runTest {test basic-1.2 {unit tests from the 'testlinq' project} -setup {
  #
  # NOTE: Re-copy the reference database file used for this unit test to the
  #       build directory in case it has been changed by a previous test run.
  #
  file copy -force $northwindEfDbFile \
      [file join [getBuildDirectory] [file tail $northwindEfDbFile]]

  #
  # NOTE: We need to make 100% sure that the console output encoding is the
  #       same as when the 'testlinq.out' file was created.
  #
  set savedEncoding [object invoke Console OutputEncoding]
  set encoding [object invoke System.Text.Encoding GetEncoding Windows-1252]

  object invoke Console OutputEncoding $encoding

} -body {
  set output ""

  set code [catch {
    testClrExec $testLinqExeFile [list -eventflags Wait -directory \
    [file dirname $testLinqExeFile] -stdout output -success 0]
  } error]

  tlog "---- BEGIN STDOUT OUTPUT\n"
  tlog $output
  tlog "\n---- END STDOUT OUTPUT\n"

  list $code [string equal $output [readFile $testLinqOutFile]] \
      [expr {$code == 0 ? "" : $error}]
} -cleanup {
  catch {object invoke Console OutputEncoding $savedEncoding}

  unset -nocomplain code output error savedEncoding encoding
} -constraints \
{eagle monoToDo file_testlinq.exe file_northwindEF.db file_testlinq.out} \
-result {0 True {}}}

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

runTest {test basic-1.3 {SELECT scalar/reader, CREATE, INSERT} -setup {
  setupDb [set fileName basic-1.3.db]
} -body {
  set result [list]

  lappend result [sql execute -execute scalar $db \
      "SELECT sqlite_source_id();"]

  sql execute $db "CREATE TABLE t1(x INTEGER PRIMARY KEY ASC, y, z);"
  sql execute $db "INSERT INTO t1 (x, y, z) VALUES(1, 'foo', 1234);"

  sql execute -execute reader $db "SELECT x, y, z FROM t1;"

  foreach name [lsort [array names rows]] {
    lappend result [list $name $rows($name)]
  }

  set result
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain name rows result db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} \
-match regexp -result {^\{\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [0-9a-f]{40}\}\
\{1 \{\{x 1\} \{y foo\} \{z 1234\}\}\} \{count 1\} \{names \{x y z\}\}$}}

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

runTest {test basic-1.4 {GetSchema with ReservedWords} -setup {
  setupDb [set fileName basic-1.4.db]
} -body {
  set id [object invoke Interpreter.GetActive NextId]
  set dataSource [file join [getTemporaryPath] basic-1.4.db]

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {
    using System.Data;
    using System.Data.SQLite;

    namespace _Dynamic${id}
    {
      public class Test${id}
      {
        public static DataTable GetReservedWords()
        {
          using (SQLiteConnection connection = new SQLiteConnection(
              "Data Source=${dataSource};"))
          {
            connection.Open();

            return connection.GetSchema("ReservedWords");
          }
        }

        public static void Main()
        {
          // do nothing.
        }
      }
    }
  }] 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} GetReservedWords
      } result] : [set result ""]}] $result
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain result results errors code 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\
System#Data#DataTable#\d+$}}

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

runTest {test basic-1.5 {GetSchema with ForeignKeys} -setup {
  setupDb [set fileName basic-1.5.db]
} -body {
  sql execute $db {
    CREATE TABLE t1(
      x INTEGER REFERENCES t2 MATCH FULL
      ON UPDATE SET DEFAULT ON DELETE CASCADE
      DEFAULT 1
    );
  }

  sql execute $db "CREATE TABLE t2(x INTEGER REFERENCES t3);"

  set id [object invoke Interpreter.GetActive NextId]
  set dataSource [file join [getTemporaryPath] basic-1.5.db]

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {
    using System.Data;
    using System.Data.SQLite;

    namespace _Dynamic${id}
    {
      public class Test${id}
      {
        public static DataRowCollection GetForeignKeys()
        {
          using (SQLiteConnection connection = new SQLiteConnection(
              "Data Source=${dataSource};"))
          {
            connection.Open();

            return connection.GetSchema("ForeignKeys").Rows;
          }
        }

        public static void Main()
        {
          // do nothing.
        }
      }
    }
  }] results errors System.Data.SQLite.dll]

  list $code $results \
      [expr {[info exists errors] ? $errors : ""}] \
      [expr {$code eq "Ok" ? [catch {
        set rows [list]
        set foreignKeys [object invoke _Dynamic${id}.Test${id} GetForeignKeys]

        object foreach -alias foreignKey $foreignKeys {
          lappend rows [list \
              [$foreignKey Item CONSTRAINT_CATALOG] \
              [$foreignKey Item CONSTRAINT_NAME] \
              [$foreignKey Item TABLE_CATALOG] \
              [$foreignKey Item TABLE_NAME] \
              [$foreignKey Item CONSTRAINT_TYPE] \
              [$foreignKey Item IS_DEFERRABLE] \
              [$foreignKey Item INITIALLY_DEFERRED] \
              [$foreignKey Item FKEY_FROM_COLUMN] \
              [$foreignKey Item FKEY_TO_CATALOG] \
              [$foreignKey Item FKEY_TO_TABLE] \
              [$foreignKey Item FKEY_TO_COLUMN] \
              [$foreignKey Item FKEY_FROM_ORDINAL_POSITION] \
              [$foreignKey Item FKEY_ON_UPDATE] \
              [$foreignKey Item FKEY_ON_DELETE] \
              [$foreignKey Item FKEY_MATCH]]
        }

        set rows
      } result] : [set result ""]}] $result
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain result rows foreignKey foreignKeys results errors code \
      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\
\{\{main FK_t1_0 main t1 \{FOREIGN KEY\} False False x main t2 \{\} 0 \{SET\
DEFAULT\} CASCADE NONE\} \{main FK_t2_0 main t2 \{FOREIGN KEY\} False False x\
main t3 \{\} 0 \{NO ACTION\} \{NO ACTION\} NONE\}\}$}}

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

runTest {test basic-1.6 {SQLITE_FCNTL_WIN32_AV_RETRY} -setup {
  setupDb [set fileName basic-1.6.db]
} -body {
  set id [object invoke Interpreter.GetActive NextId]
  set dataSource [file join [getTemporaryPath] basic-1.6.db]

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {
    using System.Data;
    using System.Data.SQLite;

    namespace _Dynamic${id}
    {
      public class Test${id}
      {
        public static bool TestSetAvRetry(
          ref int count,
          ref int interval
          )
        {
          using (SQLiteConnection connection = new SQLiteConnection(
              "Data Source=${dataSource};"))
          {
            connection.Open();

            //
            // NOTE: Set the requested retry parameter values.
            //
            if (connection.SetAvRetry(ref count, ref interval) != 0)
              return false;

            //
            // NOTE: Query the retry parameter values.
            //
            int newCount = -1; int newInterval = -1;

            if (connection.SetAvRetry(ref newCount, ref newInterval) != 0)
              return false;

            //
            // NOTE: Make sure the retry parameter values were set.
            //
            return (newCount == count && newInterval == interval);
          }
        }

        public static void Main()
        {
          // do nothing.
        }
      }
    }
  }] results errors System.Data.SQLite.dll]

  list $code $results \
      [expr {[info exists errors] ? $errors : ""}] \
      [expr {$code eq "Ok" ? [catch {
        set savedCount -1; set savedInterval -1

        object invoke _Dynamic${id}.Test${id} TestSetAvRetry \
            savedCount savedInterval

        set count 5; set interval 50

        object invoke _Dynamic${id}.Test${id} TestSetAvRetry \
            count interval
      } result] : [set result ""]}] $result
} -cleanup {
  if {[info exists savedCount]} then {
    #
    # NOTE: Restore the saved retry count, if possible.
    #
    catch {
      set interval -1
      object invoke _Dynamic${id}.Test${id} TestSetAvRetry savedCount interval
    }
  }

  if {[info exists savedInterval]} then {
    #
    # NOTE: Restore the saved retry interval, if possible.
    #
    catch {
      set count -1
      object invoke _Dynamic${id}.Test${id} TestSetAvRetry count savedInterval
    }
  }

  cleanupDb $fileName

  unset -nocomplain result count interval savedCount savedInterval results \
      errors code 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\
True$}}

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

runTest {test basic-1.7 {properly closed database file (non-query)} -setup {
  set fileName basic-1.7.db
} -body {
  set id [object invoke Interpreter.GetActive NextId]
  set dataSource [file join [getTemporaryPath] $fileName]

  set sql { \
    BEGIN EXCLUSIVE TRANSACTION; \
    CREATE TABLE t1(x INTEGER); \
    INSERT INTO t1 (x) VALUES(1); \
    SELECT * FROM t1; \
  }

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {
    using System.Data;
    using System.Data.SQLite;

    namespace _Dynamic${id}
    {
      public class Test${id}
      {
        public static void Main()
        {
          using (SQLiteConnection connection = new SQLiteConnection(
              "Data Source=${dataSource};"))
          {
            connection.Open();

            using (SQLiteCommand command = new SQLiteCommand("${sql}",
                connection))
            {
              command.ExecuteNonQuery();
            }
          }
        }
      }
    }
  }] 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 \
      [close [open $dataSource RDONLY 0 "" -share None]]
} -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\
\{\} \{\}$}}

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

runTest {test basic-1.8 {properly closed database file (reader #1)} -setup {
  set fileName basic-1.8.db
} -body {
  set id [object invoke Interpreter.GetActive NextId]
  set dataSource [file join [getTemporaryPath] $fileName]

  set sql { \
    BEGIN EXCLUSIVE TRANSACTION; \
    CREATE TABLE t1(x INTEGER); \
    INSERT INTO t1 (x) VALUES(1); \
    SELECT * FROM t1; \
  }

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {
    using System.Data;
    using System.Data.SQLite;

    namespace _Dynamic${id}
    {
      public class Test${id}
      {
        public static void Main()
        {
          using (SQLiteConnection connection = new SQLiteConnection(
              "Data Source=${dataSource};"))
          {
            connection.Open();

            using (SQLiteCommand command = new SQLiteCommand("${sql}",
                connection))
            {
              using (SQLiteDataReader dataReader = command.ExecuteReader())
              {
                // do nothing.
              }
            }
          }
        }
      }
    }
  }] 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 \
      [close [open $dataSource RDONLY 0 "" -share None]]
} -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\
\{\} \{\}$}}

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

runTest {test basic-1.9 {properly closed database file (reader #2)} -setup {
  set fileName basic-1.9.db
} -body {
  set id [object invoke Interpreter.GetActive NextId]
  set dataSource [file join [getTemporaryPath] $fileName]

  set sql { \
    BEGIN EXCLUSIVE TRANSACTION; \
    CREATE TABLE t1(x INTEGER); \
    INSERT INTO t1 (x) VALUES(1); \
    SELECT * FROM t1; \
  }

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {
    using System.Data;
    using System.Data.SQLite;

    namespace _Dynamic${id}
    {
      public class Test${id}
      {
        public static void Main()
        {
          using (SQLiteConnection connection = new SQLiteConnection(
              "Data Source=${dataSource};"))
          {
            connection.Open();

            using (SQLiteCommand command = new SQLiteCommand("${sql}",
                connection))
            {
              using (SQLiteDataReader dataReader = command.ExecuteReader(
                  CommandBehavior.CloseConnection))
              {
                // do nothing.
              }
            }
          }
        }
      }
    }
  }] 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 \
      [close [open $dataSource RDONLY 0 "" -share None]]
} -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\
\{\} \{\}$}}

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

runTest {test basic-1.10 {Changes property} -setup {
  setupDb [set fileName basic-1.10.db]
} -body {
  set connection [object invoke -flags +NonPublic -objectflags +NoDispose \
      Interpreter.GetActive.connections Item $db]

  set result [list]

  sql execute $db "CREATE TABLE t1(x INTEGER PRIMARY KEY ASC, y, z);"

  sql execute $db "INSERT INTO t1 (x, y, z) VALUES(1, 'foo', 1234);"
  sql execute $db "INSERT INTO t1 (x, y, z) VALUES(2, 'bar', 5678);"
  lappend result [object invoke $connection Changes]

  sql execute $db "UPDATE t1 SET y = 'foobar';"
  lappend result [object invoke $connection Changes]

  sql execute -execute reader $db "SELECT x, y, z FROM t1;"
  lappend result [object invoke $connection Changes]

  foreach name [lsort -integer [array names rows -regexp {^\d+$}]] {
    lappend result [list $name $rows($name)]
  }

  set result
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain name rows result connection db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} \
-result {1 2 2 {1 {{x 1} {y foobar} {z 1234}}} {2 {{x 2} {y foobar} {z 5678}}}}}

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

runTest {test basic-1.11 {LastInsertRowId property} -setup {
  setupDb [set fileName basic-1.11.db]
} -body {
  set connection [object invoke -flags +NonPublic -objectflags +NoDispose \
      Interpreter.GetActive.connections Item $db]

  set result [list]

  sql execute $db "CREATE TABLE t1(x INTEGER PRIMARY KEY ASC, y, z);"

  sql execute $db "CREATE TABLE t2(x INTEGER PRIMARY KEY AUTOINCREMENT, y, z);"
  lappend result [object invoke $connection LastInsertRowId]

  sql execute $db "INSERT INTO t1 (x, y, z) VALUES(1, 'foo', 1234);"
  lappend result [object invoke $connection LastInsertRowId]

  sql execute $db "INSERT INTO t1 (x, y, z) VALUES(2, 'bar', 5678);"
  lappend result [object invoke $connection LastInsertRowId]

  sql execute $db "UPDATE t1 SET y = 'foobar';"
  lappend result [object invoke $connection LastInsertRowId]

  sql execute $db "INSERT INTO t2 (y, z) VALUES('foo', 1234);"
  lappend result [object invoke $connection LastInsertRowId]

  sql execute $db "INSERT INTO t2 (y, z) VALUES('bar', 5678);"
  lappend result [object invoke $connection LastInsertRowId]

  sql execute $db "UPDATE t2 SET y = 'foobar';"
  lappend result [object invoke $connection LastInsertRowId]

  sql execute -execute reader $db "SELECT x, y, z FROM t1;"
  lappend result [object invoke $connection LastInsertRowId]

  foreach name [lsort -integer [array names rows -regexp {^\d+$}]] {
    lappend result [list $name $rows($name)]
  }

  sql execute -execute reader $db "SELECT x, y, z FROM t2;"
  lappend result [object invoke $connection LastInsertRowId]

  foreach name [lsort -integer [array names rows -regexp {^\d+$}]] {
    lappend result [list $name $rows($name)]
  }

  set result
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain name rows result connection db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} \
-result {0 1 2 2 1 2 2 2 {1 {{x 1} {y foobar} {z 1234}}} {2 {{x 2} {y foobar}\
{z 5678}}} 2 {1 {{x 1} {y foobar} {z 1234}}} {2 {{x 2} {y foobar} {z 5678}}}}}

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

runTest {test basic-1.12 {DateTime using Unix epoch} -setup {
  setupDb [set fileName basic-1.12.db] "" UnixEpoch Utc
} -body {
  set result [list]

  sql execute $db "CREATE TABLE t1(x INTEGER PRIMARY KEY ASC, y DATETIME);"
  sql execute $db "INSERT INTO t1 (x, y) VALUES(1, 1302825600);"
  sql execute $db "INSERT INTO t1 (x, y) VALUES(2, 1334448000);"
  sql execute $db "INSERT INTO t1 (x, y) VALUES(3, 1365984000);"

  sql execute $db "INSERT INTO t1 (x, y) VALUES(4, ?);" \
      [list param1 Int32 1302825600]

  sql execute $db "INSERT INTO t1 (x, y) VALUES(5, ?);" \
      [list param1 Int32 1334448000]

  sql execute $db "INSERT INTO t1 (x, y) VALUES(6, ?);" \
      [list param1 Int32 1365984000]

  sql execute -verbatim $db "INSERT INTO t1 (x, y) VALUES(7, ?);" \
      [list param1 DateTime 1302825600]

  sql execute -verbatim $db "INSERT INTO t1 (x, y) VALUES(8, ?);" \
      [list param1 DateTime 1334448000]

  sql execute -verbatim $db "INSERT INTO t1 (x, y) VALUES(9, ?);" \
      [list param1 DateTime 1365984000]

  sql execute -execute reader -datetimeformat [getDateTimeFormat] $db \
      "SELECT x, y FROM t1 ORDER BY x;"

  foreach name [lsort -integer [array names rows -regexp {^\d+$}]] {
    lappend result [list $name $rows($name)]
  }

  set result
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain name rows result db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} \
-result {{1 {{x 1} {y {2011-04-15 00:00:00Z}}}} {2 {{x 2} {y {2012-04-15\
00:00:00Z}}}} {3 {{x 3} {y {2013-04-15 00:00:00Z}}}} {4 {{x 4} {y {2011-04-15\
00:00:00Z}}}} {5 {{x 5} {y {2012-04-15 00:00:00Z}}}} {6 {{x 6} {y {2013-04-15\
00:00:00Z}}}} {7 {{x 7} {y {2011-04-15 00:00:00Z}}}} {8 {{x 8} {y {2012-04-15\
00:00:00Z}}}} {9 {{x 9} {y {2013-04-15 00:00:00Z}}}}}}

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

set date [clock format [clock seconds] -format yyyy-MM-dd]

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

runTest {test basic-1.13 {DateTime using invariant culture} -setup {
  setupDb [set fileName basic-1.13.db] "" InvariantCulture Utc
} -body {
  set result [list]

  sql execute $db "CREATE TABLE t1(x INTEGER PRIMARY KEY ASC, y DATETIME);"

  sql execute $db \
      "INSERT INTO t1 (x, y) VALUES(1, 'Wednesday, 16 December 2009');"

  sql execute $db "INSERT INTO t1 (x, y) VALUES(2, '12:00:00');"

  sql execute $db \
      "INSERT INTO t1 (x, y) VALUES(3, 'Wednesday, 16 December 2009 12:00:00');"

  sql execute $db "INSERT INTO t1 (x, y) VALUES(4, '12/16/2009');"
  sql execute $db "INSERT INTO t1 (x, y) VALUES(5, '12:00');"
  sql execute $db "INSERT INTO t1 (x, y) VALUES(6, '12/16/2009 12:00');"

  sql execute $db "INSERT INTO t1 (x, y) VALUES(7, ?);" \
      [list param1 DateTime "Wednesday, 16 December 2009"]

  sql execute $db "INSERT INTO t1 (x, y) VALUES(8, ?);" \
      [list param1 DateTime 12:00:00]

  sql execute $db "INSERT INTO t1 (x, y) VALUES(9, ?);" \
      [list param1 DateTime "Wednesday, 16 December 2009 12:00:00"]

  sql execute $db "INSERT INTO t1 (x, y) VALUES(10, ?);" \
      [list param1 DateTime 12/16/2009]

  sql execute $db "INSERT INTO t1 (x, y) VALUES(11, ?);" \
      [list param1 DateTime 12:00]

  sql execute $db "INSERT INTO t1 (x, y) VALUES(12, ?);" \
      [list param1 DateTime "12/16/2009 12:00"]

  sql execute -execute reader -datetimeformat [getDateTimeFormat] $db \
      "SELECT x, CAST(y AS TEXT) AS y2 FROM t1 ORDER BY x;"

  foreach name [lsort -integer [array names rows -regexp {^\d+$}]] {
    lappend result [list $name $rows($name)]
  }

  set result
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain name rows result db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} \
-result [subst {{1 {{x 1} {y2 {Wednesday, 16 December 2009}}}} {2 {{x 2} {y2\
12:00:00}}} {3 {{x 3} {y2 {Wednesday, 16 December 2009 12:00:00}}}} {4 {{x 4}\
{y2 12/16/2009}}} {5 {{x 5} {y2 12:00}}} {6 {{x 6} {y2 {12/16/2009 12:00}}}} {7\
{{x 7} {y2 2009-12-16T00:00:00.0000000Z}}} {8 {{x 8} {y2\
${date}T12:00:00.0000000Z}}} {9 {{x 9} {y2 2009-12-16T12:00:00.0000000Z}}}\
{10 {{x 10} {y2 2009-12-16T00:00:00.0000000Z}}} {11 {{x 11} {y2\
${date}T12:00:00.0000000Z}}} {12 {{x 12} {y2 2009-12-16T12:00:00.0000000Z}}}}]}

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

runTest {test basic-1.14 {DateTime using current culture} -setup {
  setupDb [set fileName basic-1.14.db] "" CurrentCulture Utc
} -body {
  set result [list]

  sql execute $db "CREATE TABLE t1(x INTEGER PRIMARY KEY ASC, y DATETIME);"

  sql execute $db \
      "INSERT INTO t1 (x, y) VALUES(1, 'Wednesday, 16 December 2009');"

  sql execute $db "INSERT INTO t1 (x, y) VALUES(2, '12:00:00');"

  sql execute $db \
      "INSERT INTO t1 (x, y) VALUES(3, 'Wednesday, 16 December 2009 12:00:00');"

  sql execute $db "INSERT INTO t1 (x, y) VALUES(4, '12/16/2009');"
  sql execute $db "INSERT INTO t1 (x, y) VALUES(5, '12:00');"
  sql execute $db "INSERT INTO t1 (x, y) VALUES(6, '12/16/2009 12:00');"

  sql execute $db "INSERT INTO t1 (x, y) VALUES(7, ?);" \
      [list param1 DateTime "Wednesday, 16 December 2009"]

  sql execute $db "INSERT INTO t1 (x, y) VALUES(8, ?);" \
      [list param1 DateTime 12:00:00]

  sql execute $db "INSERT INTO t1 (x, y) VALUES(9, ?);" \
      [list param1 DateTime "Wednesday, 16 December 2009 12:00:00"]

  sql execute $db "INSERT INTO t1 (x, y) VALUES(10, ?);" \
      [list param1 DateTime 12/16/2009]

  sql execute $db "INSERT INTO t1 (x, y) VALUES(11, ?);" \
      [list param1 DateTime 12:00]

  sql execute $db "INSERT INTO t1 (x, y) VALUES(12, ?);" \
      [list param1 DateTime "12/16/2009 12:00"]

  sql execute -execute reader -datetimeformat [getDateTimeFormat] $db \
      "SELECT x, CAST(y AS TEXT) AS y2 FROM t1 ORDER BY x;"

  foreach name [lsort -integer [array names rows -regexp {^\d+$}]] {
    lappend result [list $name $rows($name)]
  }

  set result
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain name rows result db fileName
} -constraints \
{eagle culture.en_US monoBug28 command.sql compile.DATA SQLite\
System.Data.SQLite} -result [subst {{1 {{x 1} {y2 {Wednesday, 16 December\
2009}}}} {2 {{x 2} {y2 12:00:00}}} {3 {{x 3} {y2 {Wednesday, 16 December 2009\
12:00:00}}}} {4 {{x 4} {y2 12/16/2009}}} {5 {{x 5} {y2 12:00}}} {6 {{x 6} {y2\
{12/16/2009 12:00}}}} {7 {{x 7} {y2 2009-12-16T00:00:00.0000000Z}}} {8 {{x 8}\
{y2 ${date}T12:00:00.0000000Z}}} {9 {{x 9} {y2 2009-12-16T12:00:00.0000000Z}}}\
{10 {{x 10} {y2 2009-12-16T00:00:00.0000000Z}}} {11 {{x 11} {y2\
${date}T12:00:00.0000000Z}}} {12 {{x 12} {y2 2009-12-16T12:00:00.0000000Z}}}}]}

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

unset -nocomplain date

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

unset -nocomplain testExeFile testLinqExeFile northwindEfDbFile testLinqOutFile

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

runSQLiteTestEpilogue
runTestEpilogue







>
|
|









>
|
<
<




|



|



|



|





|
<
<
<
<

|
|









|




<
<
<
<
<
<
<





<

|
>

<
<

|
|









|

|
<
|
|




|









|










<
|



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






<

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
package require EagleLibrary
package require EagleTest

runTestPrologue

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

source [file join $path common.eagle]
tryLoadAssembly System.Data.SQLite.dll
tryLoadAssembly System.Data.SQLite.Linq.dll

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

#
# NOTE: Setup the variables that refer to the various files required by the
#       tests in this file.
#
set testExeFile [getBuildFileName test.exe]
set testLinqExeFile [getBuildFileName testlinq.exe]
set northwindEfDbFile [getBuildFileName northwindEF.db]
set testLinqOutFile [file join $path testlinq.out]



#
# NOTE: Setup the test constraints specific to the tests in this file.
#
if {![haveConstraint file_[file tail $testExeFile]]} then {
  checkForFile $test_channel $testExeFile
}

if {![haveConstraint file_[file tail $testLinqExeFile]]} then {
  checkForFile $test_channel $testLinqExeFile
}

if {![haveConstraint file_[file tail $northwindEfDbFile]]} then {
  checkForFile $test_channel $northwindEfDbFile
}

if {![haveConstraint file_[file tail $testLinqOutFile]]} then {
  checkForFile $test_channel $testLinqOutFile
}

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

runTest {test basic-1.1 {unit tests from the 'test' project} -body {




  set code [catch {
    testExec $testExeFile [list -eventflags Wait -directory \
    [file dirname $northwindEfDbFile] -stdout output -success 0] -autoRun
  } error]

  tlog "---- BEGIN STDOUT OUTPUT\n"
  tlog $output
  tlog "\n---- END STDOUT OUTPUT\n"

  list $code [expr {$code == 0 ? "" : $error}]
} -cleanup {
  unset -nocomplain code output error
} -constraints {eagle System.Data.SQLite file_test.exe} -result {0 {}}}

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

runTest {test basic-1.2 {unit tests from the 'testlinq' project} -setup {







  #
  # NOTE: We need to make 100% sure that the console output encoding is the
  #       same as when the 'testlinq.out' file was created.
  #
  set savedEncoding [object invoke Console OutputEncoding]


  object invoke Console OutputEncoding \
      [object invoke System.Text.Encoding GetEncoding Windows-1252]
} -body {


  set code [catch {
    testExec $testLinqExeFile [list -eventflags Wait -directory \
    [file dirname $northwindEfDbFile] -stdout output -success 0] -autoRun
  } error]

  tlog "---- BEGIN STDOUT OUTPUT\n"
  tlog $output
  tlog "\n---- END STDOUT OUTPUT\n"

  list $code [string equal $output [readFile $testLinqOutFile]] \
      [expr {$code == 0 ? "" : $error}]
} -cleanup {
  object invoke Console OutputEncoding $savedEncoding

  unset -nocomplain code output error savedEncoding

} -constraints {eagle System.Data.SQLite file_testlinq.exe file_northwindEF.db\
file_testlinq.out} -result {0 True {}}}

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

runTest {test basic-1.3 {SELECT scalar/reader, CREATE, INSERT} -setup {
  setupDb [set fileName basic-1.1.db]
} -body {
  set result [list]

  lappend result [sql execute -execute scalar $db \
      "SELECT sqlite_source_id();"]

  sql execute $db "CREATE TABLE t1(x INTEGER PRIMARY KEY ASC, y, z);"
  sql execute $db "INSERT INTO t1 (x, y, z) VALUES(1, 'foo', 1234);"

  sql execute -execute reader $db "SELECT * FROM t1;"

  foreach name [lsort [array names rows]] {
    lappend result [list $name $rows($name)]
  }

  set result
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain name rows result db fileName

} -constraints {eagle monoBug28 command.sql compile.DATA System.Data.SQLite} \
-match regexp -result {^\{\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [0-9a-f]{40}\}\
\{1 \{\{x 1\} \{y foo\} \{z 1234\}\}\} \{count 1\} \{names \{x y z\}\}$}}


















































































































































































































































































































































































































































































































































































































































































































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

unset -nocomplain testExeFile testLinqExeFile northwindEfDbFile testLinqOutFile

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


runTestEpilogue
Changes to Tests/common.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
###############################################################################
#
# common.eagle --
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################

#
# 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 {
  if {[isEagle]} then {
    ###########################################################################
    ############################ BEGIN Eagle ONLY #############################
    ###########################################################################

    proc getBuildYear {} {
      #
      # NOTE: See if the "year" setting has been overridden by the user (e.g. on
      #       the command line).  This helps control exactly which set of
      #       binaries we are testing, those produced using either the Visual
      #       Studio 2008 or Visual Studio 2010 build systems.  To override this
      #       value via the command line, enter a command similar to one of the
      #       following (all on one line):
      #
      #       EagleShell.exe -preInitialize "set test_year 2008"
      #         -file .\path\to\all.eagle
      #
      #       EagleShell.exe -preInitialize "set test_year 2010"
      #         -file .\path\to\all.eagle
      #
      #       EagleShell.exe -preInitialize "unset -nocomplain test_year"
      #         -file .\path\to\all.eagle
      #
      if {[info exists ::test_year] && [string length $::test_year] > 0} then {
        #
        # NOTE: Use the specified test year.  If this variable is not set, the
        #       default value will be based on whether or not Eagle has been
        #       compiled against the .NET Framework 2.0 or 4.0.
        #
        return $::test_year
      } else {
        #
        # NOTE: If Eagle has been compiled against the .NET Framework 4.0, use
        #       "2010" as the test year; otherwise, use "2008".  If another
        #       major [incompatible] version of the .NET Framework is released,
        #       this check will have to be changed.
        #
        return [expr {[haveConstraint imageRuntime40] ? "2010" : "2008"}]
      }
    }

    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
      #       command line, enter a command similar to one of the following (all
      #       on one line):
      #
      #       EagleShell.exe -preInitialize "set test_configuration Debug"
      #         -file .\path\to\all.eagle
      #
      #       EagleShell.exe -preInitialize "set test_configuration Release"
      #         -file .\path\to\all.eagle
      #
      #       EagleShell.exe -file .\path\to\all.eagle -preTest
      #         "unset -nocomplain test_configuration"
      #
      if {[info exists ::test_configuration] && \
          [string length $::test_configuration] > 0} then {
        #
        # NOTE: Use the specified test configuration.  The default value used
        #       for this variable is "Release", as set by the test suite itself.
        #
        return $::test_configuration
      } else {
        #
        # NOTE: Normally, we will never hit this case because the value of the
        #       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 added.  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):
      #
      #       EagleShell.exe -initialize -runtimeOption native
      #         -file .\path\to\all.eagle
      #
      #       To enable this option via the command line prior to the "beta 16"
      #       release of Eagle, the following command must be used instead
      #       (also all on one line):
      #
      #       EagleShell.exe -initialize -postInitialize
      #         "object invoke Interpreter.GetActive AddRuntimeOption native"
      #         -file .\path\to\all.eagle
      #
      if {[info exists ::build_directory] && \
          [string length $::build_directory] > 0} then {
        #
        # NOTE: The location of the build directory has been overridden.
        #
        return $::build_directory
      } else {
        if {[hasRuntimeOption native]} then {
          return [file join [file dirname $::path] bin [getBuildYear] \
              [machineToPlatform $::tcl_platform(machine)] \
              [getBuildConfiguration]]
        } else {
          return [file join [file dirname $::path] bin [getBuildYear] \
              [getBuildConfiguration] bin]
        }
      }
    }

    proc getBuildFileName { fileName } {
      return [file nativename \
          [file join [getBuildDirectory] [file tail $fileName]]]
    }

    proc getBinaryDirectory {} {
      #
      # NOTE: This procedure returns the directory where the test application
      #       itself (i.e. the Eagle shell) is located.  This will be used as
      #       the destination for the copied System.Data.SQLite native and
      #       managed assemblies (i.e. because this is one of the few places
      #       where the CLR will actually find and load them properly).
      #
      if {[info exists ::binary_directory] && \
          [string length $::binary_directory] > 0} then {
        #
        # NOTE: The location of the binary directory has been overridden.
        #
        return $::binary_directory
      } else {
        return [info binary]
      }
    }

    proc getBinaryFileName { fileName } {
      return [file nativename \
          [file join [getBinaryDirectory] [file tail $fileName]]]
    }

    proc getAppDomainPreamble { {prefix ""} {suffix ""} } {
      #
      # NOTE: This procedure returns a test setup script suitable for evaluation
      #       by a test interpreter created in an isolated application domain.
      #       The script being returned will be surrounded by the prefix and
      #       suffix "script fragments" specified by the caller, if any.  The
      #       entire script being returned will be substituted via [subst], in
      #       the context of the caller.  This step is necessary so that some
      #       limited context information, primarily related to the test build
      #       directory, can be transferred to the interpreter in the isolated
      #       application domain, making it able to successfully run tests that
      #       require one or more of the files in the build directory.  Callers
      #       to this procedure should keep in mind that the test script being
      #       returned cannot only rely on any script library procedures not
      #       included in the EagleLibrary package (i.e. "init.eagle").  Also,
      #       all variable references and all "nested" commands (i.e. those in
      #       square brackets), unless they are specially quoted, will end up
      #       being evaluated in the context of the calling interpreter and not
      #       the test interpreter created in the isolated application domain.
      #
      return [uplevel 1 [list subst [appendArgs $prefix {
        if {[hasRuntimeOption native]} then {
          object invoke Interpreter.GetActive AddRuntimeOption native
        }

        set ::path {$::path}
        set ::test_year {[getBuildYear]}
        set ::test_configuration {[getBuildConfiguration]}
      } $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 {
        tputs $::test_channel [appendArgs \
            "---- failed to copy build file from \"" $sourceFileName \
            "\" to \"" $targetFileName \"\n]
      }
    }

    proc tryDeleteBinaryFile { fileName } {
      set fileName [getBinaryFileName $fileName]

      if {![file exists $fileName]} then {
        tputs $::test_channel [appendArgs \
            "---- skipped deleting binary file \"" $fileName \
            "\", it does not exist\n"]

        return
      }

      if {[catch {file delete $fileName}] == 0} then {
        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]
      }
    }

    proc tryDeleteAssembly { fileName {pdb true} } {
      tryDeleteBinaryFile $fileName

      if {$pdb} then {
        tryDeleteBinaryFile [appendArgs [file rootname $fileName] .pdb]
      }
    }

    proc tryLoadAssembly { fileName } {
      set fileName [getBinaryFileName $fileName]

      if {[catch {set assembly \
          [object load -loadtype File $fileName]}] == 0} then {
        #
        # NOTE: Now, add the necessary test constraint.
        #
        addConstraint [file rootname [file tail $fileName]]

        #
        # NOTE: Return the full path of the loaded file.
        #
        return $fileName
      }

      return ""
    }

    proc checkForSQLite { channel } {
      tputs $channel "---- checking for core SQLite library... "

      if {[catch {object invoke -flags +NonPublic System.Data.SQLite.SQLite3 \
              SQLiteVersion} version] == 0} then {
        #
        # NOTE: Yes, the SQLite core library appears to be available.
        #
        addConstraint SQLite

        tputs $channel [appendArgs "yes (" $version ")\n"]
      } else {
        tputs $channel no\n
      }
    }

    proc getDateTimeFormat {} {
      #
      # NOTE: This procedure simply returns the "default" DateTime format used
      #       by the test suite.
      #
      if {[info exists ::datetime_format] && \
          [string length $::datetime_format] > 0} then {
        #
        # NOTE: Return the manually overridden value for the DateTime format.
        #
        return $::datetime_format
      } else {
        #
        # NOTE: Return an ISO8601 DateTime format compatible with SQLite,
        #       System.Data.SQLite, and suitable for round-tripping with the
        #       DateTime class of the framework.  If this value is changed,
        #       various tests may fail.
        #
        return "yyyy-MM-dd HH:mm:ss.FFFFFFFK"
      }
    }

    proc enumerableToList { enumerable } {
      set result [list]

      if {[string length $enumerable] == 0 || $enumerable eq "null"} then {
        return $result
      }

      object foreach -alias item $enumerable {
        if {[string length $item] > 0} then {
          lappend result [$item ToString]
        }
      }

      return $result
    }

    proc compileCSharpWith {
            text resultsVarName errorsVarName fileNames args } {
      #
      # NOTE: Create the base command to evaluate and add the property settings
      #       that are almost always needed by our unit tests (i.e. the System
      #       and System.Data assembly references).
      #
      set command [list compileCSharp $text results errors \
          ReferencedAssemblies.Add System.dll ReferencedAssemblies.Add \
          System.Data.dll ReferencedAssemblies.Add System.Xml.dll]

      #
      # NOTE: Add all the provided file names as assembly references.
      #
      foreach fileName $fileNames {
        lappend command ReferencedAssemblies.Add [getBinaryFileName $fileName]
      }

      #
      # NOTE: Add the extra arguments, if any, to the command to evaluate.
      #
      eval lappend command $args

      #
      # NOTE: Alias the compiler local results and errors variables to the
      #       variable names provided by our caller.
      #
      upvar 1 $resultsVarName results
      upvar 1 $errorsVarName errors

      #
      # NOTE: Evaluate the constructed [compileCSharp] command and return the
      #       result.
      #
      eval $command
    }

    proc setupDb {
            fileName {mode ""} {dateTimeFormat ""} {dateTimeKind ""} {extra ""}
            {delete true} {varName db}} {
      #
      # NOTE: For now, all test databases used by the test suite are placed into
      #       the temporary directory.  Each database used by a test should be
      #       cleaned up by that test using the "cleanupDb" procedure, below.
      #
      set fileName [file join [getTemporaryPath] [file tail $fileName]]

      #
      # NOTE: By default, delete any pre-existing database with the same file
      #       name.
      #
      if {$delete} then {
        catch {file delete $fileName}
      }

      #
      # NOTE: Refer to the specified variable (e.g. "db") in the context of the
      #       caller.  The handle to the opened database will be stored there.
      #
      upvar 1 $varName db

      #
      # NOTE: Start building the connection string.  The only required portion
      #       of the connection string is the database file name itself.
      #
      set connection {Data Source=${fileName}}

      #
      # NOTE: If the caller specified a journal mode, add the necessary portion
      #       of the connection string now.
      #
      if {[string length $mode] > 0} then {
        append connection {;Journal Mode=${mode}}
      }

      #
      # NOTE: If the caller specified a DateTime format, add the necessary
      #       portion of the connection string now.
      #
      if {[string length $dateTimeFormat] > 0} then {
        append connection {;DateTimeFormat=${dateTimeFormat}}
      }

      #
      # NOTE: If the caller specified a DateTimeKind, add the necessary portion
      #       of the connection string now.
      #
      if {[string length $dateTimeKind] > 0} then {
        append connection {;DateTimeKind=${dateTimeKind}}
      }

      #
      # NOTE: If the caller specified an extra payload to the connection string,
      #       append it now.
      #
      if {[string length $extra] > 0} then {
        append connection \; $extra
      }

      #
      # NOTE: Open the database connection now, placing the opaque handle value
      #       into the variable specified by the caller.
      #
      set db [sql open -type SQLite [subst $connection]]
    }

    proc cleanupDb { fileName {varName db} } {
      #
      # NOTE: Refer to the specified variable (e.g. "db") in the context of the
      #       caller.  The handle to the opened database is stored there.
      #
      upvar 1 $varName db

      #
      # NOTE: Close the connection to the database now.  This should allow us to
      #       delete the underlying database file.
      #
      catch {sql close $db}

      #
      # NOTE: Delete the test database file now.  For now, all test database
      #       files are stored in the temporary directory.
      #
      catch {file delete [file join [getTemporaryPath] [file tail $fileName]]}
    }

    proc runSQLiteTestPrologue {} {
      #
      # NOTE: Skip running our custom prologue if the main one has been skipped.
      #
      if {![info exists ::no(prologue.eagle)]} then {
        #
        # NOTE: Skip all System.Data.SQLite related file handling (deleting,
        #       copying, and loading) if we are so instructed.
        #
        if {![info exists ::no(sqliteFiles)]} then {
          #
          # NOTE: Skip trying to delete any files if we are so instructed.
          #
          if {![info exists ::no(deleteSqliteFiles)]} then {
            tryDeleteAssembly SQLite.Interop.dll
            tryDeleteAssembly System.Data.SQLite.dll
            tryDeleteAssembly System.Data.SQLite.Linq.dll
          }

          #
          # NOTE: Skip trying to copy any files if we are so instructed.
          #
          if {![info exists ::no(copySqliteFiles)]} then {
            tryCopyAssembly SQLite.Interop.dll
            tryCopyAssembly System.Data.SQLite.dll
            tryCopyAssembly System.Data.SQLite.Linq.dll
          }

          #
          # 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 \"SQLite.Interop.dll\"... " \
              [file version [getBinaryFileName SQLite.Interop.dll]] \n]
        }

        catch {
          tputs $::test_channel [appendArgs \
              "---- file version of \"System.Data.SQLite.dll\"... " \
              [file version [getBinaryFileName System.Data.SQLite.dll]] \n]
        }

        catch {
          tputs $::test_channel [appendArgs \
              "---- file version of \"System.Data.SQLite.Linq.dll\"... " \
              [file version [getBinaryFileName System.Data.SQLite.Linq.dll]] \n]
        }

        set assemblies [object invoke AppDomain.CurrentDomain GetAssemblies]

        object foreach assembly $assemblies {
          if {[string match \{System.Data.SQLite* $assembly]} then {
            tputs $::test_channel [appendArgs \
                "---- found assembly: " $assembly \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.
        #
        checkForSQLite $::test_channel
      }
    }

    proc runSQLiteTestEpilogue {} {
      #
      # NOTE: Skip running our custom epilogue if the main one has been skipped.
      #
      if {![info exists ::no(epilogue.eagle)]} then {
        #
        # NOTE: For now, nothing is done here.
        #
      }
    }

    ###########################################################################
    ############################# END Eagle ONLY ##############################
    ###########################################################################
  }

  #
  # NOTE: Provide the System.Data.SQLite test package to the interpreter.
  #
  package provide System.Data.SQLite.Test 1.0
}









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

|
|
|
|
|
|

|
|
|
|
|

|
|

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

|
|
|
|
|
|

|
|
|
|

|
|
|
|
|
|

|
|
|
|
|
|

|
<
<
<
<
<
<
<
|

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

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
###############################################################################
#
# common.eagle --
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################







if {[isEagle]} then {




  proc getBuildFileName { fileName } {























    return [file join [file dirname $::path] bin \







        [expr {[haveConstraint imageRuntime40] ? "2010" : "2008"}] \



























        $::test_configuration bin $fileName]








  }










































  proc copyAssembly { fileName } {

    #
    # NOTE: If we cannot copy the file then it is probably already loaded,
    #       ignore the error.



    #










    catch {
      file copy -force [getBuildFileName $fileName] \



          [file join [info binary] $fileName]























    }
  }






  proc tryLoadAssembly { fileName } {



    set fileName [getBuildFileName $fileName]






























































    if {[catch {set assembly \
        [object load -loadtype File $fileName]}] == 0} then {
      #
      # NOTE: Now, add the necessary test constraint.
      #
      addConstraint [file rootname [file tail $fileName]]

      #
      # NOTE: Return the full path of the loaded file.
      #
      return $fileName
    }

    return ""
  }
























































  proc compileCSharpWith { text resultsVarName errorsVarName fileNames args } {
    #
    # NOTE: Create the base command to evaluate and add the property settings
    #       that are almost always needed by our unit tests (i.e. the System
    #       and System.Data assembly references).
    #
    set command [list compileCSharp $text results errors \
        ReferencedAssemblies.Add System.dll ReferencedAssemblies.Add \
        System.Data.dll]

    #
    # NOTE: Add all the provided file names as assembly references.
    #
    foreach fileName $fileNames {
      lappend command ReferencedAssemblies.Add [getBuildFileName $fileName]
    }

    #
    # NOTE: Add the extra arguments, if any, to the command to evaluate.
    #
    eval lappend command $args

    #
    # NOTE: Alias the compiler local results and errors variables to the
    #       variable names provided by our caller.
    #
    upvar 1 $resultsVarName results
    upvar 1 $errorsVarName errors

    #
    # NOTE: Evaluate the constructed [compileCSharp] command and return the
    #       result.
    #
    eval $command
  }

  proc setupDb {fileName {mode ""} {delete ""} {extra ""} {varName db}} {







    set fileName [file join [getTemporaryPath] $fileName]





    if {[string length $delete] == 0 || $delete} then {
      catch {file delete $fileName}
    }




































    upvar 1 $varName db

    set connection {Data Source=${fileName}}


    if {[string length $mode] > 0} then {
      append connection {;Journal Mode=${mode}}
    }














































    if {[string length $extra] > 0} then {








      append connection \; $extra






    }

    set db [sql open -type SQLite [subst $connection]]




  }




  proc cleanupDb {fileName {varName db}} {

    upvar 1 $varName db
    catch {sql close $db}




    catch {file delete [file join [getTemporaryPath] $fileName]}

  }






































}
Deleted Tests/pkgIndex.eagle.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
###############################################################################
#
# pkgIndex.eagle --
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################

if {![package vsatisfies [package provide Tcl] 8.4]} {return}
if {![package vsatisfies [package provide Eagle] 1.0]} {return}

package ifneeded System.Data.SQLite.Test 1.0 \
    [list source [file join $dir common.eagle]]
<
<
<
<
<
<
<
<
<
<
<
<
<
<




























Deleted Tests/tkt-00f86f9739.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
###############################################################################
#
# tkt-00f86f9739.eagle --
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################

package require Eagle
package require EagleLibrary
package require EagleTest

runTestPrologue

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

package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

#
# NOTE: Setup the variables that refer to the various files required by the
#       tests in this file.
#
set testLinqExeFile [getBuildFileName testlinq.exe]
set northwindEfDbFile [file nativename [file join [file dirname $path] \
    testlinq northwindEF.db]]

#
# NOTE: Setup the test constraints specific to the tests in this file.
#
if {![haveConstraint [appendArgs file_ [file tail $testLinqExeFile]]]} then {
  checkForFile $test_channel $testLinqExeFile
}

if {![haveConstraint [appendArgs file_ [file tail $northwindEfDbFile]]]} then {
  checkForFile $test_channel $northwindEfDbFile
}

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

runTest {test tkt-00f86f9739-1.1 {LINQ with StartsWith} -body {
  set result [list]

  foreach value [list "" a b z 1+1 don notthere] {
    set output ""

    set code [catch {
      testClrExec $testLinqExeFile [list -eventflags Wait -directory \
      [file dirname $testLinqExeFile] -nocarriagereturns -stdout output \
      -success 0] -startsWith $value
    } error]

    tlog "---- BEGIN STDOUT OUTPUT\n"
    tlog $output
    tlog "\n---- END STDOUT OUTPUT\n"

    lappend result $code

    if {$code == 0} then {
      lappend result [string trim $output]
    } else {
      lappend result [string trim $error]
    }
  }

  set result
} -cleanup {
  unset -nocomplain code output error result value
} -constraints {eagle monoToDo file_testlinq.exe file_northwindEF.db} -result \
{0 {} 0 {DRACD OLDWO RATTC} 0 {ALFKI CACTU CHOPS FOLKO GALED KOENE LILAS MAGAA\
MAISD OCEAN RANCH SAVEA THECR} 0 {} 0 {} 0 {} 0 {}}}

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

unset -nocomplain testLinqExeFile northwindEfDbFile

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

runSQLiteTestEpilogue
runTestEpilogue
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






































































































































































Deleted Tests/tkt-0d5b1ef362.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
###############################################################################
#
# tkt-0d5b1ef362.eagle --
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################

package require Eagle
package require EagleLibrary
package require EagleTest

runTestPrologue

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

package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

#
# HACK: This test reads the private "_domainUnload" field of the AppDomain
#       class.  This is non-portable and will not work on Mono.  Also, this
#       may not work on versions of the .NET Framework after 4.0.
#
runTest {test tkt-0d5b1ef362-1.1 {SQLiteLog.DomainUnload event} -setup \
    [getAppDomainPreamble] -body {
  #
  # NOTE: Grab the number of DomainUnload handlers prior to doing anything
  #       else.
  #
  set x [object invoke -flags +NonPublic \
      AppDomain.CurrentDomain._domainUnload.GetInvocationList Length]

  package require EagleLibrary
  package require EagleTest
  package require System.Data.SQLite.Test

  object load -loadtype File [file join [getBinaryDirectory] \
      System.Data.SQLite.dll]

  for {set i 1} {$i < 3} {incr i} {
    set connection($i) [object create System.Data.SQLite.SQLiteConnection ""]
  }

  #
  # NOTE: Now, grab the number of DomainUnload handlers after creating the
  #       connections.
  #
  set y [object invoke -flags +NonPublic \
      AppDomain.CurrentDomain._domainUnload.GetInvocationList Length]

  #
  # NOTE: Make sure that no DomainUnload handlers were actually added while we
  #       created the two connections (i.e. because we are not in the default
  #       application domain).
  #
  expr {$x == $y}
} -cleanup {
  unset -nocomplain connection i x y
} -constraints {eagle dotNet monoBug28 compile.ISOLATED_INTERPRETERS SQLite\
System.Data.SQLite} -isolationLevel AppDomain -result {True}}

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

runSQLiteTestEpilogue
runTestEpilogue
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










































































































































Changes to Tests/tkt-201128cc88.eagle.
11
12
13
14
15
16
17

18
19
20
21
22
23


24
25
26
27
28
29
30
package require EagleLibrary
package require EagleTest

runTestPrologue

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


package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

runTest {test tkt-201128cc88-1.1 {custom function with byte[] arg} -setup {


  set fileName tkt-201128cc88-1.1.db
} -body {
  set id [object invoke Interpreter.GetActive NextId]

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {







>
|
<




>
>







11
12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
27
28
29
30
31
32
package require EagleLibrary
package require EagleTest

runTestPrologue

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

source [file join $path common.eagle]
tryLoadAssembly System.Data.SQLite.dll


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

runTest {test tkt-201128cc88-1.1 {custom function with byte[] arg} -setup {
  copyAssembly SQLite.Interop.dll
  copyAssembly System.Data.SQLite.dll
  set fileName tkt-201128cc88-1.1.db
} -body {
  set id [object invoke Interpreter.GetActive NextId]

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
      [sql execute -execute scalar $db "SELECT Base64(CAST('' AS BLOB));"] \
      [sql execute -execute scalar $db "SELECT Base64(CAST('foo' AS BLOB));"]
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain result code results errors id db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -match \
regexp -result {^Ok System#CodeDom#Compiler#CompilerResults#\d+ \{\} 0 \{\}\
SQLiteConnection#\d+ \{\} \{\} Zm9v$}}

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

runSQLiteTestEpilogue
runTestEpilogue







|
|




<

89
90
91
92
93
94
95
96
97
98
99
100
101

102
      [sql execute -execute scalar $db "SELECT Base64(CAST('' AS BLOB));"] \
      [sql execute -execute scalar $db "SELECT Base64(CAST('foo' AS BLOB));"]
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain result code results errors id db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA System.Data.SQLite} -match regexp \
-result {^Ok System#CodeDom#Compiler#CompilerResults#\d+ \{\} 0 \{\}\
SQLiteConnection#\d+ \{\} \{\} Zm9v$}}

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


runTestEpilogue
Changes to Tests/tkt-2c630bffa7.eagle.
11
12
13
14
15
16
17

18
19
20
21
22
23
24
25
26
package require EagleLibrary
package require EagleTest

runTestPrologue

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


package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

set y [list -1.79769e308 -3.40282e038 -1 0 1 3.40282e038 1.79769e308]

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








>
|
<







11
12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
package require EagleLibrary
package require EagleTest

runTestPrologue

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

source [file join $path common.eagle]
tryLoadAssembly System.Data.SQLite.dll


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

set y [list -1.79769e308 -3.40282e038 -1 0 1 3.40282e038 1.79769e308]

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

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
  set result [sql execute -execute reader -format list $db \
    "SELECT x, y FROM t1 ORDER BY x;"]
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain x result db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{0 -1.79769E+308 1 -3.40282E+38 2 -1 3 0 4 1 5 3.40282E+38 6 1.79769E+308}}

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

runTest {test tkt-2c630bffa7-1.2 {range of FLOAT type} -setup {
  setupDb [set fileName tkt-2c630bffa7-1.2.db]
} -body {







|







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
  set result [sql execute -execute reader -format list $db \
    "SELECT x, y FROM t1 ORDER BY x;"]
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain x result db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA System.Data.SQLite} -result \
{0 -1.79769E+308 1 -3.40282E+38 2 -1 3 0 4 1 5 3.40282E+38 6 1.79769E+308}}

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

runTest {test tkt-2c630bffa7-1.2 {range of FLOAT type} -setup {
  setupDb [set fileName tkt-2c630bffa7-1.2.db]
} -body {
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
  set result [sql execute -execute reader -format list $db \
    "SELECT x, y FROM t2 ORDER BY x;"]
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain x result db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{0 -1.79769E+308 1 -3.40282E+38 2 -1 3 0 4 1 5 3.40282E+38 6 1.79769E+308}}

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

runTest {test tkt-2c630bffa7-1.3 {range of DOUBLE type} -setup {
  setupDb [set fileName tkt-2c630bffa7-1.3.db]
} -body {







|







59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
  set result [sql execute -execute reader -format list $db \
    "SELECT x, y FROM t2 ORDER BY x;"]
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain x result db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA System.Data.SQLite} -result \
{0 -1.79769E+308 1 -3.40282E+38 2 -1 3 0 4 1 5 3.40282E+38 6 1.79769E+308}}

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

runTest {test tkt-2c630bffa7-1.3 {range of DOUBLE type} -setup {
  setupDb [set fileName tkt-2c630bffa7-1.3.db]
} -body {
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
  set result [sql execute -execute reader -format list $db \
    "SELECT x, y FROM t3 ORDER BY x;"]
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain x result db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{0 -1.79769E+308 1 -3.40282E+38 2 -1 3 0 4 1 5 3.40282E+38 6 1.79769E+308}}

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

unset -nocomplain y

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

runSQLiteTestEpilogue
runTestEpilogue







|








<

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

97
  set result [sql execute -execute reader -format list $db \
    "SELECT x, y FROM t3 ORDER BY x;"]
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain x result db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA System.Data.SQLite} -result \
{0 -1.79769E+308 1 -3.40282E+38 2 -1 3 0 4 1 5 3.40282E+38 6 1.79769E+308}}

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

unset -nocomplain y

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


runTestEpilogue
Deleted Tests/tkt-343d392b51.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
###############################################################################
#
# tkt-343d392b51.eagle --
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################

package require Eagle
package require EagleLibrary
package require EagleTest

runTestPrologue

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

package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

set dateTimeFormats [list "" Ticks ISO8601 JulianDay UnixEpoch]

for {set i 1} {$i < 5} {incr i} {
  set dateTimeFormat [lindex $dateTimeFormats $i]

  runTest {test [appendArgs tkt-343d392b51-1. $i] [subst {DateTime\
      binding $dateTimeFormat format}] -setup {
    setupDb [set fileName [appendArgs tkt-343d392b51-1. $i .db]] "" \
        $dateTimeFormat Utc

    set dateTime "4 October, 2011 3:27:50 PM GMT"
  } -body {
    sql execute $db "CREATE TABLE t1(x DATETIME);"

    set paramDateTime1 [clock format [clock scan $dateTime] -format \
        [getDateTimeFormat] -gmt true]

    switch -exact -- $dateTimeFormat {
      Ticks {
        set paramDateTime1 [object invoke -alias DateTime Parse $paramDateTime1]
        set paramDateTime1 [$paramDateTime1 ToUniversalTime.Ticks]
        set paramDateTime2 $paramDateTime1
      }
      ISO8601 {
        set paramDateTime2 [appendArgs ' $paramDateTime1 ']
      }
      JulianDay {
        set paramDateTime1 [object invoke -alias DateTime Parse $paramDateTime1]
        set paramDateTime1 [$paramDateTime1 -alias ToUniversalTime]

        set paramDateTime1 [expr {[$paramDateTime1 ToOADate] + \
            [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \
            OleAutomationEpochAsJulianDay]}]

        set paramDateTime2 $paramDateTime1
      }
      UnixEpoch {
        set paramDateTime1 [clock scan $dateTime]
        set paramDateTime2 $paramDateTime1
      }
    }

    sql execute $db [appendArgs "INSERT INTO t1 (x) VALUES(" $paramDateTime2 \
        ");"]

    list [sql execute -verbatim -execute reader -format list -datetimeformat \
        [getDateTimeFormat] $db "SELECT x FROM t1 WHERE x = ?;" \
        [list param1 String $paramDateTime1]] \
        [sql execute -verbatim -execute reader -format list -datetimeformat \
        [getDateTimeFormat] $db "SELECT x FROM t1 WHERE x = ?;" \
        [list param1 DateTime $paramDateTime1]]
  } -cleanup {
    cleanupDb $fileName

    unset -nocomplain paramDateTime2 paramDateTime1 dateTime db fileName
  } -constraints {eagle culture.en_US monoBug28 command.sql compile.DATA SQLite\
System.Data.SQLite} -result {{{2011-10-04 15:27:50Z}} {{2011-10-04 15:27:50Z}}}}
}

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

unset -nocomplain dateTimeFormat i dateTimeFormats

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

runTest {test tkt-343d392b51-2.1 {SQLiteDataAdapter update fail} -setup {
  setupDb [set fileName tkt-343d392b51-2.1.db]
  set otherFileName tkt-343d392b51-2.1-otherDb.db
} -body {
  set id [object invoke Interpreter.GetActive NextId]
  set dataSource [file join [getTemporaryPath] $fileName]
  set otherDataSource [file join [getTemporaryPath] $otherFileName]
  set otherDbName otherDb
  set otherTable [appendArgs $otherDbName .t1]

  set sql(inserts) ""
  set sql(1) [subst { \
    ATTACH DATABASE '${otherDataSource}' AS ${otherDbName}; \
    CREATE TABLE ${otherTable}(x INTEGER PRIMARY KEY, y DATETIME); \
    [for {set i 1} {$i < 3} {incr i} {
      append sql(inserts) [appendArgs \
          "INSERT INTO " ${otherTable} " (x, y) VALUES(" $i ", '" \
          [clock format $i -format [getDateTimeFormat]] "'); "]
    }; return [expr {[info exists sql(inserts)] ? $sql(inserts) : ""}]] \
  }]

  set sql(2) [subst { \
    SELECT x, y FROM ${otherTable} ORDER BY x; \
  }]

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {
    using System;
    using System.Data;
    using System.Data.SQLite;

    namespace _Dynamic${id}
    {
      public class Test${id}
      {
        public static void Main()
        {
          using (SQLiteConnection connection = new SQLiteConnection(
              "Data Source=${dataSource};"))
          {
            connection.Open();

            using (SQLiteCommand command = connection.CreateCommand())
            {
              command.CommandText = "${sql(1)}";
              command.ExecuteNonQuery();
            }

            using (SQLiteDataAdapter dataAdapter = new SQLiteDataAdapter(
                "${sql(2)}", connection))
            {
              using (DataSet dataSet = new DataSet())
              {
                dataAdapter.Fill(dataSet, "${otherTable}");

                DataTable dataTable = dataSet.Tables\["${otherTable}"\];

                dataTable.Columns\["x"\].Unique = true;
                dataTable.PrimaryKey = new DataColumn\[\] {
                  dataTable.Columns\["x"\]
                };

                [expr {[isMono] ? "#pragma warning disable 219" : ""}]
                SQLiteCommandBuilder commandBuilder =
                    new SQLiteCommandBuilder(dataAdapter);
                [expr {[isMono] ? "#pragma warning restore 219" : ""}]

                foreach (DataRow dataRow in dataTable.Rows)
                {
                  //
                  // NOTE: Update even rows and delete odd rows.
                  //
                  if ((long)dataRow\["x"\] % 2 == 0)
                    dataRow\["y"\] =
                        DateTime.UtcNow.ToString("[getDateTimeFormat]");
                  else
                    dataRow.Delete();
                }

                dataAdapter.Update(dataTable); // DBConcurrencyException (?)
              }
            }
          }
        }
      }
    }
  }] 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 $otherFileName
  cleanupDb $fileName

  unset -nocomplain result code results errors i sql otherTable otherDbName \
      otherDataSource dataSource id db otherFileName fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -match \
glob -result {* System.Data.DBConcurrencyException: *}}

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

runTest {test tkt-343d392b51-2.2 {SQLiteDataAdapter update success} -setup {
  setupDb [set fileName tkt-343d392b51-2.2.db] "" JulianDay
  set otherFileName tkt-343d392b51-2.2-otherDb.db
} -body {
  set id [object invoke Interpreter.GetActive NextId]
  set dataSource [file join [getTemporaryPath] $fileName]
  set otherDataSource [file join [getTemporaryPath] $otherFileName]
  set otherDbName otherDb
  set otherTable [appendArgs $otherDbName .t1]

  set sql(inserts) ""
  set sql(1) [subst { \
    ATTACH DATABASE '${otherDataSource}' AS ${otherDbName}; \
    CREATE TABLE ${otherTable}(x INTEGER PRIMARY KEY, y DATETIME); \
    [for {set i 1} {$i < 3} {incr i} {
      append sql(inserts) [appendArgs \
          "INSERT INTO " ${otherTable} " (x, y) VALUES(" $i ", JULIANDAY('" \
          [clock format $i -format [getDateTimeFormat]] "')); "]
    }; return [expr {[info exists sql(inserts)] ? $sql(inserts) : ""}]] \
  }]

  set sql(2) [subst { \
    SELECT x, y FROM ${otherTable} ORDER BY x; \
  }]

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {
    using System;
    using System.Data;
    using System.Data.SQLite;

    namespace _Dynamic${id}
    {
      public class Test${id}
      {
        public static void Main()
        {
          using (SQLiteConnection connection = new SQLiteConnection(
              "Data Source=${dataSource};DateTimeFormat=JulianDay;"))
          {
            connection.Open();

            using (SQLiteCommand command = connection.CreateCommand())
            {
              command.CommandText = "${sql(1)}";
              command.ExecuteNonQuery();
            }

            using (SQLiteDataAdapter dataAdapter = new SQLiteDataAdapter(
                "${sql(2)}", connection))
            {
              using (DataSet dataSet = new DataSet())
              {
                dataAdapter.Fill(dataSet, "${otherTable}");

                DataTable dataTable = dataSet.Tables\["${otherTable}"\];

                dataTable.Columns\["x"\].Unique = true;
                dataTable.PrimaryKey = new DataColumn\[\] {
                  dataTable.Columns\["x"\]
                };

                [expr {[isMono] ? "#pragma warning disable 219" : ""}]
                SQLiteCommandBuilder commandBuilder =
                    new SQLiteCommandBuilder(dataAdapter);
                [expr {[isMono] ? "#pragma warning restore 219" : ""}]

                foreach (DataRow dataRow in dataTable.Rows)
                {
                  //
                  // NOTE: Update even rows and delete odd rows.
                  //
                  if ((long)dataRow\["x"\] % 2 == 0)
                    dataRow\["y"\] =
                        DateTime.UtcNow.ToString("[getDateTimeFormat]");
                  else
                    dataRow.Delete();
                }

                dataAdapter.Update(dataTable); // DBConcurrencyException (?)
              }
            }
          }
        }
      }
    }
  }] 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 $otherFileName
  cleanupDb $fileName

  unset -nocomplain result code results errors i sql otherTable otherDbName \
      otherDataSource dataSource id db otherFileName fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -match \
regexp -result {^Ok System#CodeDom#Compiler#CompilerResults#\d+ \{\} 0 \{\}$}}

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

runTest {test tkt-343d392b51-3.1 {attached database, same table name} -setup {
  setupDb [set fileName tkt-343d392b51-3.1.db]
  set otherFileName tkt-343d392b51-3.1-otherDb.db
} -body {
  set otherDataSource [file join [getTemporaryPath] $otherFileName]
  set otherDbName otherDb
  set otherTable [appendArgs $otherDbName .t1]

  set sql(inserts) ""
  set sql(1) [subst { \
    CREATE TABLE t1(x INTEGER PRIMARY KEY); \
    ATTACH DATABASE '${otherDataSource}' AS ${otherDbName}; \
    CREATE TABLE ${otherTable}(x INTEGER PRIMARY KEY); \
    [for {set i 1} {$i < 3} {incr i} {
      append sql(inserts) [appendArgs \
          "INSERT INTO t1 (x) VALUES(" $i "); "]

      append sql(inserts) [appendArgs \
          "INSERT INTO " ${otherTable} " (x) VALUES(" [expr {$i * 2}] "); "]
    }; return [expr {[info exists sql(inserts)] ? $sql(inserts) : ""}]] \
  }]

  sql execute $db $sql(1)

  list [sql execute -execute reader -format list $db "SELECT x FROM t1;"] \
      [sql execute -execute reader -format list $db [appendArgs \
      "SELECT x FROM " ${otherTable} ";"]]
} -cleanup {
  cleanupDb $otherFileName
  cleanupDb $fileName

  unset -nocomplain i sql otherTable otherDbName otherDataSource db \
      otherFileName fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{{1 2} {2 4}}}

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

runTest {test tkt-343d392b51-3.2 {adapter, attached db, table names} -setup {
  setupDb [set fileName tkt-343d392b51-3.2.db]
  set otherFileName tkt-343d392b51-3.2-otherDb.db
} -body {
  set id [object invoke Interpreter.GetActive NextId]
  set dataSource [file join [getTemporaryPath] $fileName]
  set otherDataSource [file join [getTemporaryPath] $otherFileName]
  set otherDbName otherDb
  set otherTable [appendArgs $otherDbName .t1]

  set sql(inserts) ""
  set sql(1) [subst { \
    CREATE TABLE t1(x INTEGER PRIMARY KEY); \
    ATTACH DATABASE '${otherDataSource}' AS ${otherDbName}; \
    CREATE TABLE ${otherTable}(x INTEGER PRIMARY KEY); \
    [for {set i 1} {$i < 3} {incr i} {
      append sql(inserts) [appendArgs \
          "INSERT INTO t1 (x) VALUES(" $i ");"]
      append sql(inserts) [appendArgs \
          "INSERT INTO " ${otherTable} " (x) VALUES(" [expr {$i * 2}] "); "]
    }; return [expr {[info exists sql(inserts)] ? $sql(inserts) : ""}]] \
  }]

  set sql(2) [subst { \
    SELECT x FROM ${otherTable} ORDER BY x; \
  }]

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {
    using System;
    using System.Data;
    using System.Data.SQLite;

    namespace _Dynamic${id}
    {
      public class Test${id}
      {
        public static void Main()
        {
          using (SQLiteConnection connection = new SQLiteConnection(
              "Data Source=${dataSource};"))
          {
            connection.Open();

            using (SQLiteCommand command = connection.CreateCommand())
            {
              command.CommandText = "${sql(1)}";
              command.ExecuteNonQuery();
            }

            using (SQLiteDataAdapter dataAdapter = new SQLiteDataAdapter(
                "${sql(2)}", connection))
            {
              using (DataSet dataSet = new DataSet())
              {
                dataAdapter.Fill(dataSet, "${otherTable}");

                DataTable dataTable = dataSet.Tables\["${otherTable}"\];

                dataTable.Columns\["x"\].Unique = true;
                dataTable.PrimaryKey = new DataColumn\[\] {
                  dataTable.Columns\["x"\]
                };

                [expr {[isMono] ? "#pragma warning disable 219" : ""}]
                SQLiteCommandBuilder commandBuilder =
                    new SQLiteCommandBuilder(dataAdapter);
                [expr {[isMono] ? "#pragma warning restore 219" : ""}]

                foreach (DataRow dataRow in dataTable.Rows)
                  dataRow.Delete();

                dataAdapter.Update(dataTable); // DBConcurrencyException (?)
              }
            }
          }
        }
      }
    }
  }] 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 $otherFileName
  cleanupDb $fileName

  unset -nocomplain result code results errors i sql otherTable otherDbName \
      otherDataSource dataSource id db otherFileName 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-448d663d11.eagle.
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
package require EagleLibrary
package require EagleTest

runTestPrologue

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


package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

runTest {test tkt-448d663d11-1.1 {missing journal mode, new db} -body {
  setupDb [set fileName tkt-448d663d11-1.1.db]
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{delete}}

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

runTest {test tkt-448d663d11-1.2 {missing journal mode, WAL db} -body {
  set fileName tkt-448d663d11-1.2.db
  file copy -force [file join $path wal.db] \
      [file join [getTemporaryPath] $fileName]
  setupDb $fileName "" "" "" "" false
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{wal}}

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

runTest {test tkt-448d663d11-1.3 {missing journal mode, non-WAL db} -body {
  set fileName tkt-448d663d11-1.3.db
  file copy -force [file join $path nonWal.db] \
      [file join [getTemporaryPath] $fileName]
  setupDb $fileName "" "" "" "" false
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{delete}}

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

runTest {test tkt-448d663d11-1.4 {'Default' journal mode, new db} -body {
  setupDb [set fileName tkt-448d663d11-1.4.db] Default
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{delete}}

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

runTest {test tkt-448d663d11-1.5 {'Default' journal mode, WAL db} -body {
  set fileName tkt-448d663d11-1.5.db
  file copy -force [file join $path wal.db] \
      [file join [getTemporaryPath] $fileName]
  setupDb $fileName Default "" "" "" false
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{wal}}

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

runTest {test tkt-448d663d11-1.6 {'Default' journal mode, non-WAL db} -body {
  set fileName tkt-448d663d11-1.6.db
  file copy -force [file join $path nonWal.db] \
      [file join [getTemporaryPath] $fileName]
  setupDb $fileName Default "" "" "" false
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{delete}}

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

runTest {test tkt-448d663d11-1.7 {'Delete' journal mode, new db} -body {
  setupDb [set fileName tkt-448d663d11-1.7.db] Delete
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{delete}}

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

runTest {test tkt-448d663d11-1.8 {'Delete' journal mode, WAL db} -body {
  set fileName tkt-448d663d11-1.8.db
  file copy -force [file join $path wal.db] \
      [file join [getTemporaryPath] $fileName]
  setupDb $fileName Delete "" "" "" false
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{delete}}

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

runTest {test tkt-448d663d11-1.9 {'Delete' journal mode, non-WAL db} -body {
  set fileName tkt-448d663d11-1.9.db
  file copy -force [file join $path nonWal.db] \
      [file join [getTemporaryPath] $fileName]
  setupDb $fileName Delete "" "" "" false
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{delete}}

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

runTest {test tkt-448d663d11-1.10 {'Persist' journal mode, new db} -body {
  setupDb [set fileName tkt-448d663d11-1.10.db] Persist
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{persist}}

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

runTest {test tkt-448d663d11-1.11 {'Off' journal mode, new db} -body {
  setupDb [set fileName tkt-448d663d11-1.11.db] Off
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{off}}

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

runTest {test tkt-448d663d11-1.12 {'Truncate' journal mode, new db} -body {
  setupDb [set fileName tkt-448d663d11-1.12.db] Truncate
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{truncate}}

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

runTest {test tkt-448d663d11-1.13 {'Memory' journal mode, new db} -body {
  setupDb [set fileName tkt-448d663d11-1.13.db] Memory
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{memory}}

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

runTest {test tkt-448d663d11-1.14 {'Wal' journal mode, new db} -body {
  setupDb [set fileName tkt-448d663d11-1.14.db] Wal
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{wal}}

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

runTest {test tkt-448d663d11-1.15 {'Wal' journal mode, non-WAL db} -body {
  set fileName tkt-448d663d11-1.15.db
  file copy -force [file join $path nonWal.db] \
      [file join [getTemporaryPath] $fileName]
  setupDb $fileName Wal "" "" "" false
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{wal}}

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

runTest {test tkt-448d663d11-1.16 {'Wal' journal mode, WAL db} -body {
  set fileName tkt-448d663d11-1.16.db
  file copy -force [file join $path wal.db] \
      [file join [getTemporaryPath] $fileName]
  setupDb $fileName Wal "" "" "" false
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{wal}}

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

runTest {test tkt-448d663d11-1.17 {'Bad' journal mode, new db} -body {
  setupDb [set fileName tkt-448d663d11-1.17.db] Bad
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{delete}}

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

runTest {test tkt-448d663d11-1.18 {'Bad' journal mode, non-WAL db} -body {
  set fileName tkt-448d663d11-1.18.db
  file copy -force [file join $path nonWal.db] \
      [file join [getTemporaryPath] $fileName]
  setupDb $fileName Bad "" "" "" false
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{delete}}

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

runTest {test tkt-448d663d11-1.19 {'Bad' journal mode, WAL db} -body {
  set fileName tkt-448d663d11-1.19.db
  file copy -force [file join $path wal.db] \
      [file join [getTemporaryPath] $fileName]
  setupDb $fileName Bad "" "" "" false
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{wal}}

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

runSQLiteTestEpilogue
runTestEpilogue







>
|
<










|
<







|





|
<







|





|
<










|
<







|





|
<







|





|
<










|
<







|





|
<







|





|
<










|
<










|
<










|
<










|
<










|
<







|





|
<







|





|
<










|
<







|





|
<







|





|
<



<

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
package require EagleLibrary
package require EagleTest

runTestPrologue

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

source [file join $path common.eagle]
tryLoadAssembly System.Data.SQLite.dll


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

runTest {test tkt-448d663d11-1.1 {missing journal mode, new db} -body {
  setupDb [set fileName tkt-448d663d11-1.1.db]
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA System.Data.SQLite} -result {delete}}


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

runTest {test tkt-448d663d11-1.2 {missing journal mode, WAL db} -body {
  set fileName tkt-448d663d11-1.2.db
  file copy -force [file join $path wal.db] \
      [file join [getTemporaryPath] $fileName]
  setupDb $fileName "" false
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA System.Data.SQLite} -result {wal}}


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

runTest {test tkt-448d663d11-1.3 {missing journal mode, non-WAL db} -body {
  set fileName tkt-448d663d11-1.3.db
  file copy -force [file join $path nonWal.db] \
      [file join [getTemporaryPath] $fileName]
  setupDb $fileName "" false
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA System.Data.SQLite} -result {delete}}


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

runTest {test tkt-448d663d11-1.4 {'Default' journal mode, new db} -body {
  setupDb [set fileName tkt-448d663d11-1.4.db] Default
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA System.Data.SQLite} -result {delete}}


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

runTest {test tkt-448d663d11-1.5 {'Default' journal mode, WAL db} -body {
  set fileName tkt-448d663d11-1.5.db
  file copy -force [file join $path wal.db] \
      [file join [getTemporaryPath] $fileName]
  setupDb $fileName Default false
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA System.Data.SQLite} -result {wal}}


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

runTest {test tkt-448d663d11-1.6 {'Default' journal mode, non-WAL db} -body {
  set fileName tkt-448d663d11-1.6.db
  file copy -force [file join $path nonWal.db] \
      [file join [getTemporaryPath] $fileName]
  setupDb $fileName Default false
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA System.Data.SQLite} -result {delete}}


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

runTest {test tkt-448d663d11-1.7 {'Delete' journal mode, new db} -body {
  setupDb [set fileName tkt-448d663d11-1.7.db] Delete
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA System.Data.SQLite} -result {delete}}


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

runTest {test tkt-448d663d11-1.8 {'Delete' journal mode, WAL db} -body {
  set fileName tkt-448d663d11-1.8.db
  file copy -force [file join $path wal.db] \
      [file join [getTemporaryPath] $fileName]
  setupDb $fileName Delete false
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA System.Data.SQLite} -result {delete}}


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

runTest {test tkt-448d663d11-1.9 {'Delete' journal mode, non-WAL db} -body {
  set fileName tkt-448d663d11-1.9.db
  file copy -force [file join $path nonWal.db] \
      [file join [getTemporaryPath] $fileName]
  setupDb $fileName Delete false
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA System.Data.SQLite} -result {delete}}


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

runTest {test tkt-448d663d11-1.10 {'Persist' journal mode, new db} -body {
  setupDb [set fileName tkt-448d663d11-1.10.db] Persist
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA System.Data.SQLite} -result {persist}}


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

runTest {test tkt-448d663d11-1.11 {'Off' journal mode, new db} -body {
  setupDb [set fileName tkt-448d663d11-1.11.db] Off
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA System.Data.SQLite} -result {off}}


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

runTest {test tkt-448d663d11-1.12 {'Truncate' journal mode, new db} -body {
  setupDb [set fileName tkt-448d663d11-1.12.db] Truncate
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA System.Data.SQLite} -result {truncate}}


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

runTest {test tkt-448d663d11-1.13 {'Memory' journal mode, new db} -body {
  setupDb [set fileName tkt-448d663d11-1.13.db] Memory
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA System.Data.SQLite} -result {memory}}


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

runTest {test tkt-448d663d11-1.14 {'Wal' journal mode, new db} -body {
  setupDb [set fileName tkt-448d663d11-1.14.db] Wal
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA System.Data.SQLite} -result {wal}}


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

runTest {test tkt-448d663d11-1.15 {'Wal' journal mode, non-WAL db} -body {
  set fileName tkt-448d663d11-1.15.db
  file copy -force [file join $path nonWal.db] \
      [file join [getTemporaryPath] $fileName]
  setupDb $fileName Wal false
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA System.Data.SQLite} -result {wal}}


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

runTest {test tkt-448d663d11-1.16 {'Wal' journal mode, WAL db} -body {
  set fileName tkt-448d663d11-1.16.db
  file copy -force [file join $path wal.db] \
      [file join [getTemporaryPath] $fileName]
  setupDb $fileName Wal false
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA System.Data.SQLite} -result {wal}}


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

runTest {test tkt-448d663d11-1.17 {'Bad' journal mode, new db} -body {
  setupDb [set fileName tkt-448d663d11-1.17.db] Bad
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA System.Data.SQLite} -result {delete}}


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

runTest {test tkt-448d663d11-1.18 {'Bad' journal mode, non-WAL db} -body {
  set fileName tkt-448d663d11-1.18.db
  file copy -force [file join $path nonWal.db] \
      [file join [getTemporaryPath] $fileName]
  setupDb $fileName Bad false
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA System.Data.SQLite} -result {delete}}


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

runTest {test tkt-448d663d11-1.19 {'Bad' journal mode, WAL db} -body {
  set fileName tkt-448d663d11-1.19.db
  file copy -force [file join $path wal.db] \
      [file join [getTemporaryPath] $fileName]
  setupDb $fileName Bad false
  sql execute -execute scalar $db "PRAGMA journal_mode;"
} -cleanup {
  cleanupDb $fileName
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA System.Data.SQLite} -result {wal}}


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


runTestEpilogue
Deleted Tests/tkt-544dba0a2f.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
###############################################################################
#
# tkt-544dba0a2f.eagle --
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################

package require Eagle
package require EagleLibrary
package require EagleTest

runTestPrologue

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

package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

runTest {test tkt-544dba0a2f-1.1 {BOOL versus BOOLEAN} -setup {
  setupDb [set fileName tkt-544dba0a2f-1.1.db]
} -body {
  sql execute $db "CREATE TABLE t1(x BOOL, y BOOLEAN);"
  sql execute $db "INSERT INTO t1 (x, y) VALUES(0, 0);"
  sql execute $db "INSERT INTO t1 (x, y) VALUES(0, 1);"
  sql execute $db "INSERT INTO t1 (x, y) VALUES(1, 0);"
  sql execute $db "INSERT INTO t1 (x, y) VALUES(1, 1);"

  sql execute -execute reader -format list $db \
      "SELECT x, y FROM t1 ORDER BY rowid;"
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{False False False True True False True True}}

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

runSQLiteTestEpilogue
runTestEpilogue
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


























































































Deleted Tests/tkt-59edc1018b.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
###############################################################################
#
# tkt-59edc1018b.eagle --
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################

package require Eagle
package require EagleLibrary
package require EagleTest

runTestPrologue

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

package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

#
# NOTE: Setup the variables that refer to the various files required by the
#       tests in this file.
#
set testLinqExeFile [getBuildFileName testlinq.exe]
set northwindEfDbFile [file nativename [file join [file dirname $path] \
    testlinq northwindEF.db]]

#
# NOTE: Setup the test constraints specific to the tests in this file.
#
if {![haveConstraint [appendArgs file_ [file tail $testLinqExeFile]]]} then {
  checkForFile $test_channel $testLinqExeFile
}

if {![haveConstraint [appendArgs file_ [file tail $northwindEfDbFile]]]} then {
  checkForFile $test_channel $northwindEfDbFile
}

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

runTest {test tkt-59edc1018b-1.1 {LINQ with EndsWith} -body {
  set result [list]

  foreach value [list "" a b z 1+1 don notthere] {
    set output ""

    set code [catch {
      testClrExec $testLinqExeFile [list -eventflags Wait -directory \
      [file dirname $testLinqExeFile] -nocarriagereturns -stdout output \
      -success 0] -endsWith $value
    } error]

    tlog "---- BEGIN STDOUT OUTPUT\n"
    tlog $output
    tlog "\n---- END STDOUT OUTPUT\n"

    lappend result $code

    if {$code == 0} then {
      lappend result [string trim $output]
    } else {
      lappend result [string trim $error]
    }
  }

  set result
} -cleanup {
  unset -nocomplain code output error result value
} -constraints {eagle monoToDo file_testlinq.exe file_northwindEF.db} -result \
{0 {} 0 {FURIB GALED GODOS LAZYK LINOD PRINI REGGC WOLZA} 0 {} 0 ERNSH 0 {} 0\
{AROUT BSBEV CONSH EASTC NORTS SEVES} 0 {}}}

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

unset -nocomplain testLinqExeFile northwindEfDbFile

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

runSQLiteTestEpilogue
runTestEpilogue
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






































































































































































Deleted Tests/tkt-84718e79fa.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
###############################################################################
#
# tkt-84718e79fa.eagle --
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################

package require Eagle
package require EagleLibrary
package require EagleTest

runTestPrologue

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

package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

set c 10

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

runTest {test tkt-84718e79fa-1.1 {SQLiteConvert thread safety} -setup {
  proc threadStart { args } {
    lappend ::results [sql execute -execute reader -format list $::db \
        "SELECT x FROM t1;"]
  }

  object import System.Threading

  setupDb [set fileName tkt-84718e79fa-1.1.db]
} -body {
  sql execute $db "CREATE TABLE t1(x INTEGER PRIMARY KEY ASC);"
  sql execute $db "INSERT INTO t1 (x) VALUES(1);"

  for {set i 0} {$i < $c} {incr i} {
    set t($i) [object create -alias Thread threadStart]
  }

  set ::results [list]

  for {set i 0} {$i < $c} {incr i} {
    $t($i) Start
  }

  after 4000; # wait for other threads to do something...

  for {set i 0} {$i < $c} {incr i} {
    $t($i) Join
  }

  set ::results
} -cleanup {
  cleanupDb $fileName

  object unimport -importpattern System.Threading

  for {set i 0} {$i < $c} {incr i} {
    if {[info exists t($i)] && [cleanupThread $t($i)]} then {
      unset t($i)
    }
  }

  catch {object removecallback threadStart}

  unset -nocomplain results t i c db fileName

  rename threadStart ""
} -constraints \
{eagle shell monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} \
-result [lrepeat $c 1]}

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

unset -nocomplain c

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

runSQLiteTestEpilogue
runTestEpilogue
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








































































































































































Deleted Tests/tkt-8554170e09.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
###############################################################################
#
# tkt-8554170e09.eagle --
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################

package require Eagle
package require EagleLibrary
package require EagleTest

runTestPrologue

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

package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

runTest {test tkt-8554170e09-1.1 {default DATETIME value, NULL} -setup {
  setupDb [set fileName tkt-8554170e09-1.1.db]
} -body {
  sql execute $db "CREATE TABLE t1(x INTEGER, y DATETIME);"
  sql execute $db "INSERT INTO t1 (x, y) VALUES(1, NULL);"

  set result [sql execute -execute reader -format list $db \
    "SELECT x, y FROM t1 ORDER BY x;"]
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain result db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} \
-result {1}}

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

runTest {test tkt-8554170e09-1.2 {default DATETIME value, empty} -setup {
  setupDb [set fileName tkt-8554170e09-1.2.db]
} -body {
  sql execute $db "CREATE TABLE t1(x INTEGER, y DATETIME);"
  sql execute $db "INSERT INTO t1 (x, y) VALUES(1, '');"

  set result [sql execute -execute reader -format list $db \
    "SELECT x, y FROM t1 ORDER BY x;"]
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain result db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} \
-returnCodes 1 -match glob -result {*.SQLiteConvert.ToDateTime*}}

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

runSQLiteTestEpilogue
runTestEpilogue
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
























































































































Deleted Tests/tkt-8b7d179c3c.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
###############################################################################
#
# tkt-8b7d179c3c.eagle --
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################

package require Eagle
package require EagleLibrary
package require EagleTest

runTestPrologue

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

package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

#
# NOTE: Setup the variables that refer to the various files required by the
#       tests in this file.
#
set testLinqExeFile [getBuildFileName testlinq.exe]
set northwindEfDbFile [file nativename [file join [file dirname $path] \
    testlinq northwindEF.db]]

#
# NOTE: Setup the test constraints specific to the tests in this file.
#
if {![haveConstraint [appendArgs file_ [file tail $testLinqExeFile]]]} then {
  checkForFile $test_channel $testLinqExeFile
}

if {![haveConstraint [appendArgs file_ [file tail $northwindEfDbFile]]]} then {
  checkForFile $test_channel $northwindEfDbFile
}

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

runTest {test tkt-8b7d179c3c-1.1 {LINQ with Skip and Take} -body {
  set result [list]

  for {set pageSize 0} {$pageSize <= 2} {incr pageSize} {
    set output ""

    set code [catch {
      testClrExec $testLinqExeFile [list -eventflags Wait -directory \
      [file dirname $testLinqExeFile] -nocarriagereturns -stdout output \
      -success 0] -skip $pageSize
    } error]

    tlog "---- BEGIN STDOUT OUTPUT\n"
    tlog $output
    tlog "\n---- END STDOUT OUTPUT\n"

    lappend result $code

    if {$code == 0} then {
      lappend result [string trim $output]
    } else {
      lappend result [string trim $error]
    }
  }

  set result
} -cleanup {
  unset -nocomplain code output error result pageSize
} -constraints {eagle monoToDo file_testlinq.exe file_northwindEF.db} -result \
{0 {} 0 {DRACD RATTC OLDWO GALED LILAS MAGAA ALFKI CHOPS SAVEA KOENE MAISD\
FOLKO CACTU OCEAN RANCH THECR GOURL GROSR SUPRD HUNGO ISLAT QUICK HUNGC GREAL\
LEHMS RICSU ERNSH WILMK LINOD TRAIH SIMOB OTTIK SPLIR MORGK FOLIG FURIB PRINI\
AROUT BSBEV CONSH EASTC NORTS SEVES BERGS VICTE BOLID FISSA ROMEY BLAUS BONAP\
MEREP ANATR ANTON CENTC PERIC TORTU FRANK TOMSP DUMON FRANR WARTH PARIS SPECD\
LONEP THEBI REGGC VINET WELLI HANAR QUEDE RICAR PICCO HILAA LETSS COMMI FAMIA\
QUEEN TRADH WHITC GODOS SANTG BLONP WANDK FRANS LAMAI BOTTM LAUGB LACOR LAZYK\
WOLZA VAFFE} 0 {DRACD RATTC OLDWO GALED LILAS MAGAA ALFKI CHOPS SAVEA KOENE\
MAISD FOLKO CACTU OCEAN RANCH THECR GOURL GROSR SUPRD HUNGO ISLAT QUICK HUNGC\
GREAL LEHMS RICSU ERNSH WILMK LINOD TRAIH SIMOB OTTIK SPLIR MORGK FOLIG FURIB\
PRINI AROUT BSBEV CONSH EASTC NORTS SEVES BERGS VICTE BOLID FISSA ROMEY BLAUS\
BONAP MEREP ANATR ANTON CENTC PERIC TORTU FRANK TOMSP DUMON FRANR WARTH PARIS\
SPECD LONEP THEBI REGGC VINET WELLI HANAR QUEDE RICAR PICCO HILAA LETSS COMMI\
FAMIA QUEEN TRADH WHITC GODOS SANTG BLONP WANDK FRANS LAMAI BOTTM LAUGB LACOR\
LAZYK WOLZA VAFFE}}}

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

unset -nocomplain testLinqExeFile northwindEfDbFile

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

runSQLiteTestEpilogue
runTestEpilogue
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
































































































































































































Deleted Tests/tkt-ac47dd230a.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
###############################################################################
#
# tkt-ac47dd230a.eagle --
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################

package require Eagle
package require EagleLibrary
package require EagleTest

runTestPrologue

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

package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

runTest {test tkt-ac47dd230a-1.1 {multiple AppDomains} -setup {
  for {set i 1} {$i < 3} {incr i} {
    set appDomain($i) [object invoke AppDomain CreateDomain \
        tkt-ac47dd230a-1.1.$i]

    set result null
    set interpreterHelper($i) [object invoke -alias InterpreterHelper \
        Create $appDomain($i) null Default null null null result]

    if {[string length $interpreterHelper($i)] == 0} then {
      error [object invoke $result ToString]
    }

    set interpreter($i) [$interpreterHelper($i) -alias Interpreter]

    set result null
    set code [$interpreter($i) EvaluateScript [getAppDomainPreamble] result]

    if {$code ne "Ok"} then {
      error [object invoke $result ToString]
    }
  }
} -body {
  set results [list]

  for {set i 1} {$i < 3} {incr i} {
    set result null
    set code [$interpreter($i) EvaluateScript {
      package require EagleLibrary
      package require EagleTest
      package require System.Data.SQLite.Test

      object load -loadtype File [file join [getBinaryDirectory] \
          System.Data.SQLite.dll]

      setupDb tkt-ac47dd230a-1.1; cleanupDb tkt-ac47dd230a-1.1
    } result]

    lappend results $code [expr {[string length $result] > 0 ? \
        [object invoke $result ToString] : ""}]
  }

  set results
} -cleanup {
  unset -nocomplain results code result interpreter interpreterHelper

  for {set i 1} {$i < 3} {incr i} {
    object invoke AppDomain Unload $appDomain($i)
  }

  unset -nocomplain appDomain i
} -constraints {eagle monoBug28 command.sql compile.DATA\
compile.ISOLATED_INTERPRETERS SQLite System.Data.SQLite} -result {Ok 0 Ok 0}}

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

runSQLiteTestEpilogue
runTestEpilogue
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
































































































































































Deleted Tests/tkt-b4a7ddc83f.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
###############################################################################
#
# tkt-b4a7ddc83f.eagle --
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################

package require Eagle
package require EagleLibrary
package require EagleTest

runTestPrologue

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

package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

#
# NOTE: Make sure that SQLite core library is completely shutdown prior to
#       starting any of the tests in this file.
#
if {[haveConstraint SQLite]} then {
  object invoke -flags +NonPublic System.Data.SQLite.UnsafeNativeMethods \
      sqlite3_shutdown
}

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

for {set i 1} {$i < 3} {incr i} {
  runTest {test [appendArgs tkt-b4a7ddc83f-1. $i] {logging shutdown} -setup \
      [getAppDomainPreamble {
    set appDomainId(1) {[object invoke AppDomain.CurrentDomain Id]}
    set fileName {[appendArgs tkt-b4a7ddc83f-1. $i .db]}
  }] -body {
    set appDomainId(2) [object invoke AppDomain.CurrentDomain Id]

    package require EagleLibrary
    package require EagleTest
    package require System.Data.SQLite.Test

    object load -loadtype File [file join [getBinaryDirectory] \
        System.Data.SQLite.dll]

    object invoke System.Data.SQLite.SQLiteLog Initialize

    list $appDomainId(1) $appDomainId(2) \
        [expr {$appDomainId(1) != $appDomainId(2)}] [setupDb $fileName]
  } -cleanup {
    cleanupDb $fileName
    unset -nocomplain appDomainId db fileName
  } -constraints {eagle monoBug28 command.sql compile.DATA\
compile.ISOLATED_INTERPRETERS SQLite System.Data.SQLite} -isolationLevel \
AppDomain -match regexp -result {^\d+ \d+ True SQLiteConnection#\d+$}}
}

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

unset -nocomplain i

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

runSQLiteTestEpilogue
runTestEpilogue
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








































































































































Deleted Tests/tkt-ccfa69fc32.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
###############################################################################
#
# tkt-ccfa69fc32.eagle --
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################

package require Eagle
package require EagleLibrary
package require EagleTest

runTestPrologue

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

package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

#
# NOTE: Setup the variables that refer to the various files required by the
#       tests in this file.
#
set testLinqExeFile [getBuildFileName testlinq.exe]
set northwindEfDbFile [file nativename [file join [file dirname $path] \
    testlinq northwindEF.db]]

#
# NOTE: Setup the test constraints specific to the tests in this file.
#
if {![haveConstraint [appendArgs file_ [file tail $testLinqExeFile]]]} then {
  checkForFile $test_channel $testLinqExeFile
}

if {![haveConstraint [appendArgs file_ [file tail $northwindEfDbFile]]]} then {
  checkForFile $test_channel $northwindEfDbFile
}

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

runTest {test tkt-ccfa69fc32-1.1 {Entity Framework / Transaction Scope} -body {
  set result [list]

  foreach add [list false true false] {
    set output ""

    set code [catch {
      testClrExec $testLinqExeFile [list -eventflags Wait -directory \
      [file dirname $testLinqExeFile] -nocarriagereturns -stdout output \
      -success 0] -efTransaction $add
    } error]

    tlog "---- BEGIN STDOUT OUTPUT\n"
    tlog $output
    tlog "\n---- END STDOUT OUTPUT\n"

    lappend result $code

    if {$code == 0} then {
      lappend result [string trim $output]
    } else {
      lappend result [string trim $error]
    }
  }

  set result
} -cleanup {
  unset -nocomplain code output error result add
} -constraints {eagle monoToDo file_testlinq.exe file_northwindEF.db} -match \
glob -result {0 {1581 1730 1833 2116 2139} 0 {System.Data.UpdateException: * --->\
System.Data.SQLite.SQLiteException: Abort due to constraint violation
PRIMARY KEY must be unique
*} 0 {1 2 3 4 5 6 7 8 9 10 1576 1577 1578 1579 1580 1581 1730 1833 2116 2139}}}

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

unset -nocomplain testLinqExeFile northwindEfDbFile

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

runSQLiteTestEpilogue
runTestEpilogue
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










































































































































































Changes to Tests/tkt-e1b2e0f769.eagle.
11
12
13
14
15
16
17

18
19
20
21
22
23


24
25
26
27
28
29
30
package require EagleLibrary
package require EagleTest

runTestPrologue

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


package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

runTest {test tkt-e1b2e0f769-1.1 {data reader cleanup} -setup {


  setupDb [set fileName tkt-e1b2e0f769-1.1.db]
} -body {
  sql execute $db "CREATE TABLE t1(x INTEGER);"
  sql execute $db "CREATE TABLE t2(x INTEGER);"

  foreach x [list 1 2 3] {
    sql execute $db "INSERT INTO t1 (x) VALUES($x);"







>
|
<




>
>







11
12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
27
28
29
30
31
32
package require EagleLibrary
package require EagleTest

runTestPrologue

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

source [file join $path common.eagle]
tryLoadAssembly System.Data.SQLite.dll


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

runTest {test tkt-e1b2e0f769-1.1 {data reader cleanup} -setup {
  copyAssembly SQLite.Interop.dll
  copyAssembly System.Data.SQLite.dll
  setupDb [set fileName tkt-e1b2e0f769-1.1.db]
} -body {
  sql execute $db "CREATE TABLE t1(x INTEGER);"
  sql execute $db "CREATE TABLE t2(x INTEGER);"

  foreach x [list 1 2 3] {
    sql execute $db "INSERT INTO t1 (x) VALUES($x);"
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
  set result1
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain result2 result1 code results errors sql table dataSource \
      id x db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -match \
regexp -result {^Ok System#CodeDom#Compiler#CompilerResults#\d+ \{\} 0 3 Ok\
System#CodeDom#Compiler#CompilerResults#\d+ \{\} 0 0$}}

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

runSQLiteTestEpilogue
runTestEpilogue







|
|




<

117
118
119
120
121
122
123
124
125
126
127
128
129

130
  set result1
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain result2 result1 code results errors sql table dataSource \
      id x db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA System.Data.SQLite} -match regexp \
-result {^Ok System#CodeDom#Compiler#CompilerResults#\d+ \{\} 0 3 Ok\
System#CodeDom#Compiler#CompilerResults#\d+ \{\} 0 0$}}

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


runTestEpilogue
Deleted Tests/version.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
###############################################################################
#
# version.eagle --
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################

package require Eagle
package require EagleLibrary
package require EagleTest

runTestPrologue

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

package require System.Data.SQLite.Test
runSQLiteTestPrologue

###############################################################################
# ******************** BEGIN VOLATILE VERSION INFORMATION *********************
###############################################################################

#
# 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)            76; # NOTE: Incremented with each release.
set version(revision)          0

###############################################################################
# ********************* END VOLATILE VERSION INFORMATION **********************
###############################################################################

#
# NOTE: Build the full version number using the components setup above.  This
#       should not have to be changed.
#
set version(full) [appendArgs $version(major) . $version(minor) . \
                              $version(build) . $version(revision)]

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

#
# NOTE: Setup the variables that refer to the various files required by the
#       tests in this file.
#
set systemDataSQLiteDllFile [getBuildFileName System.Data.SQLite.dll]
set systemDataSQLiteLinqDllFile [getBuildFileName System.Data.SQLite.Linq.dll]
set testExeFile [getBuildFileName test.exe]
set testLinqExeFile [getBuildFileName testlinq.exe]

#
# NOTE: Setup the test constraints specific to the tests in this file.
#
if {![haveConstraint [appendArgs file_ \
    [file tail $systemDataSQLiteDllFile]]]} then {
  checkForFile $test_channel $systemDataSQLiteDllFile
}

if {![haveConstraint [appendArgs file_ \
    [file tail $systemDataSQLiteLinqDllFile]]]} then {
  checkForFile $test_channel $systemDataSQLiteLinqDllFile
}

if {![haveConstraint [appendArgs file_ [file tail $testExeFile]]]} then {
  checkForFile $test_channel $testExeFile
}

if {![haveConstraint [appendArgs file_ [file tail $testLinqExeFile]]]} then {
  checkForFile $test_channel $testLinqExeFile
}

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

runTest {test version-1.1 {'System.Data.SQLite' binary version} -body {
  file version $systemDataSQLiteDllFile
} -constraints {eagle file_System.Data.SQLite.dll} -result $version(full)}

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

runTest {test version-1.2 {'System.Data.SQLite' assembly version} -body {
  set assembly [object load System.Data.SQLite]

  foreach assembly [object assemblies] {
    if {[string match System.Data.SQLite,* $assembly]} then {
      return [regexp -- [appendArgs Version= [string map [list . \\.] \
          $version(full)] ,] $assembly]
    }
  }

  return false
} -cleanup {
  unset -nocomplain assembly
} -constraints {eagle SQLite System.Data.SQLite} -result {1}}

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

runTest {test version-1.3 {'System.Data.SQLite.Linq' binary version} -body {
  file version $systemDataSQLiteLinqDllFile
} -constraints {eagle file_System.Data.SQLite.Linq.dll} -result $version(full)}

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

runTest {test version-1.4 {'System.Data.SQLite.Linq' assembly version} -body {
  set assembly [object load System.Data.SQLite.Linq]

  foreach assembly [object assemblies] {
    if {[string match System.Data.SQLite.Linq,* $assembly]} then {
      return [regexp -- [appendArgs Version= [string map [list . \\.] \
          $version(full)] ,] $assembly]
    }
  }

  return false
} -cleanup {
  unset -nocomplain assembly
} -constraints {eagle SQLite System.Data.SQLite System.Data.SQLite.Linq} \
-result {1}}

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

runTest {test version-1.5 {'test' binary version} -body {
  file version $testExeFile
} -constraints {eagle file_test.exe} -result $version(full)}

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

runTest {test version-1.6 {'testlinq' binary version} -body {
  file version $testLinqExeFile
} -constraints {eagle file_testlinq.exe} -result $version(full)}

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

set patterns [list \
    [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)] \"\\)] \
    [appendArgs AssemblyVersion\\(\" [string map [list . \\.] \
        $version(full)] \"\\)] \
    [appendArgs AssemblyFileVersion\\(\" [string map [list . \\.] \
        $version(full)] \"\\)] \
    [appendArgs Value=\" [format %03d $version(build)] \"] \
    [appendArgs Value=\" [string map [list . \\.] $version(full)] \"] \
    [appendArgs Value=\" [string map [list . ,] $version(full)] \"] \
    [appendArgs <INTEROP_BUILD_NUMBER> [format %03d $version(build)] \
        </INTEROP_BUILD_NUMBER>] \
    [appendArgs <INTEROP_MANIFEST_VERSION> [string map [list . \\.] \
        $version(full)] </INTEROP_MANIFEST_VERSION>] \
    [appendArgs <INTEROP_RC_VERSION> [string map [list . ,] \
        $version(full)] </INTEROP_RC_VERSION>] \
    [appendArgs \" [string map [list . \\.] $version(full)] \"] \
    [appendArgs AssemblyVersion\\(\" [string map [list . \\.] \
        $version(full)] \"\\)] \
    [appendArgs AssemblyFileVersion\\(\" [string map [list . \\.] \
        $version(full)] \"\\)] \
    [appendArgs \" [string map [list . \\.] $version(full)] \"] \
    [appendArgs \"SQLite.Interop. [format %03d $version(build)] .dll\"] \
    [appendArgs AssemblyVersion\\(\" [string map [list . \\.] \
        $version(full)] \"\\)] \
    [appendArgs AssemblyFileVersion\\(\" [string map [list . \\.] \
        $version(full)] \"\\)] \
    [appendArgs AssemblyVersion\\(\" [string map [list . \\.] \
        $version(full)] \"\\)] \
    [appendArgs AssemblyFileVersion\\(\" [string map [list . \\.] \
        $version(full)] \"\\)] \
    [appendArgs Version= [string map [list . \\.] $version(full)] ,] \
    [appendArgs AssemblyVersion\\(\" [string map [list . \\.] \
        $version(full)] \"\\)] \
    [appendArgs AssemblyFileVersion\\(\" [string map [list . \\.] \
        $version(full)] \"\\)] \
    [appendArgs Version= [string map [list . \\.] $version(full)] ,] \
    [appendArgs Version= [string map [list . \\.] $version(full)] ,] \
    [appendArgs AssemblyVersion\\(\" [string map [list . \\.] \
        $version(full)] \"\\)] \
    [appendArgs AssemblyFileVersion\\(\" [string map [list . \\.] \
        $version(full)] \"\\)] \
    [appendArgs AssemblyVersion\\(\" [string map [list . \\.] \
        $version(full)] \"\\)] \
    [appendArgs AssemblyFileVersion\\(\" [string map [list . \\.] \
        $version(full)] \"\\)]]

set fileNames [list \
    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] \
    [file join SQLite.Designer AssemblyInfo.cs] \
    [file join SQLite.Designer AssemblyInfo.cs] \
    [file join SQLite.Interop props SQLite.Interop.vsprops] \
    [file join SQLite.Interop props SQLite.Interop.vsprops] \
    [file join SQLite.Interop props SQLite.Interop.vsprops] \
    [file join SQLite.Interop props SQLite.Interop.props] \
    [file join SQLite.Interop props SQLite.Interop.props] \
    [file join SQLite.Interop props SQLite.Interop.props] \
    [file join SQLite.Interop src win interop.h] \
    [file join System.Data.SQLite AssemblyInfo.cs] \
    [file join System.Data.SQLite AssemblyInfo.cs] \
    [file join System.Data.SQLite SQLite3.cs] \
    [file join System.Data.SQLite UnsafeNativeMethods.cs] \
    [file join System.Data.SQLite.Linq AssemblyInfo.cs] \
    [file join System.Data.SQLite.Linq AssemblyInfo.cs] \
    [file join test AssemblyInfo.cs] \
    [file join test AssemblyInfo.cs] \
    [file join test app.config] \
    [file join testce AssemblyInfo.cs] \
    [file join testce AssemblyInfo.cs] \
    [file join testlinq 2008 App.config] \
    [file join testlinq 2010 App.config] \
    [file join testlinq Properties AssemblyInfo.cs] \
    [file join testlinq Properties AssemblyInfo.cs] \
    [file join tools install Properties AssemblyInfo.cs] \
    [file join tools install Properties AssemblyInfo.cs]]

for {set i 1} {$i <= [llength $fileNames]} {incr i} {
  set pattern [lindex $patterns [expr {$i - 1}]]
  set fileName [lindex $fileNames [expr {$i - 1}]]
  set constraint [string map [list / _ \\ _] $fileName]
  set fileName [file join $root_path $fileName]

  if {![haveConstraint [appendArgs file_ $constraint]]} then {
    checkForFile $test_channel $fileName $constraint
  }

  runTest {test [appendArgs version-1.7. $i] \
      [appendArgs "pattern {" $pattern "} in file \"" $fileName \"] -body {
    regexp -- $pattern [readFile $fileName]
  } -constraints [list eagle [appendArgs file_ $constraint]] -result {1}}
}

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

unset -nocomplain constraint fileName pattern fileNames patterns i version

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

unset -nocomplain testLinqExeFile testExeFile systemDataSQLiteLinqDllFile \
    systemDataSQLiteDllFile

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

runSQLiteTestEpilogue
runTestEpilogue
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<












































































































































































































































































































































































































































































































































Changes to exclude_bin.txt.
1
2
3
4
5
6
*.exp
*.lib
*.map
*Installer.*
*EnvDTE.*
*Microsoft.*



<
<
|
1
2
3


4
*.exp
*.lib
*.map


*Microsoft*
Changes to exclude_src.txt.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
*.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.*
Externals/Eagle/bin/System.*
Externals/Eagle/lib/Eagle1.0/embed.eagle
Externals/Eagle/lib/Eagle1.0/init.eagle
Externals/Eagle/lib/Eagle1.0/pkgIndex.eagle
Externals/Eagle/lib/Eagle1.0/pkgIndex.tcl
Externals/Eagle/lib/Eagle1.0/safe.eagle
Externals/Eagle/lib/Eagle1.0/shell.eagle
Externals/Eagle/lib/Eagle1.0/test.eagle
Externals/Eagle/lib/Test1.0/constraints.eagle
Externals/Eagle/lib/Test1.0/epilogue.eagle
Externals/Eagle/lib/Test1.0/pkgIndex.eagle
Externals/Eagle/lib/Test1.0/pkgIndex.tcl
Externals/Eagle/lib/Test1.0/prologue.eagle
Externals/MSVCPP/*
Membership/*
Membership/obj/*
Membership/Profile/*
Membership/SiteMap/*
obj/*
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/*

<



<





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














>
|

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

*.docstates
*.fossil
*.ncb

*.suo
*.user
*.zip
_FOSSIL_
bin/*


















Externals/*

Membership/obj/*
Membership/Profile/*
Membership/SiteMap/*
obj/*
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/*
Tests/*
tools/*
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.75.0 October 3, 2011<br />
Using SQLite 3.7.8 <a href="http://www.sqlite.org/src/info/3e0da808d2">[3e0da808d2]</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?n=20&y=ci">
http://system.data.sqlite.org/index.html/timeline?n=20&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.74.0 July 4, 2011<br />
Using SQLite 3.7.7.1 <a href="http://www.sqlite.org/src/info/af0d91adf4">[af0d91adf4]</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?n=20&y=ci">
http://system.data.sqlite.org/index.html/timeline?n=20&y=ci</a>
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
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.76.0 - October 4, 2011</b>
</p>
<ul>
    <li>Prevent the domain unload event handler in SQLiteLog from being registered multiple times. Fix for [0d5b1ef362].</li>
    <li>Stop allowing non-default application domains to initialize the SQLiteLog class. Fix for [ac47dd230a].</li>
</ul>
<p>
    <b>1.0.75.0 - October 3, 2011</b>
</p>
<ul>
    <li>Updated to SQLite 3.7.8 <a href="http://www.sqlite.org/src/info/3e0da808d2">[3e0da808d2]</a>.</li>
    <li>More enhancements to the build system.</li>
    <li>Add official <a href="http://www.nuget.org/">NuGet</a> packages for x86 and x64.</li>
    <li>Add Changes and LastInsertRowId properties to the connection class.</li>
    <li>Support more formats when converting data from/to the DateTime type.</li>
    <li>Make all the assembly versioning attributes consistent.</li>
    <li>Add unit testing infrastructure using <a href="http://eagle.to/">Eagle</a>.</li>
    <li>Integrate all legacy unit tests, including the &quot;testlinq&quot; project, into the new test suite.</li>
    <li>Add projects to build the interop assembly statically linked to the Visual C++ runtime. Fix for [53f0c5cbf6].</li>
    <li>Add SQLITE_ENABLE_STAT2 compile-time option to the interop assembly.  Fix for [74807fbf27].</li>
    <li>Fix mutex issues exposed when running the test suite with the debug version of SQLite.</li>
    <li>Fix transaction enlistment when repeated attempts are made to enlist in the same transaction. Fix for [ccfa69fc32].</li>
    <li>Support the SQLITE_FCNTL_WIN32_AV_RETRY file control to mitigate the impact of file sharing violations caused by external processes.</li>
    <li>Refactor the logging interface to be thread-safe and self-initializing.</li>
    <li>Shutdown the SQLite native interface when the AppDomain is being unloaded. Fix for [b4a7ddc83f].</li>
    <li>Support Skip operation for LINQ using OFFSET. Fix for [8b7d179c3c].</li>
    <li>Support EndsWith operation for LINQ using SUBSTR. Fix for [59edc1018b].</li>
    <li>Support all SQLite journal modes. Fix for [448d663d11].</li>
    <li>Do not throw exceptions when disposing SQLiteDataReader. Fix for [e1b2e0f769].</li>
    <li>The REAL type should be mapped to System.Double. Fix for [2c630bffa7] and [b0a5990f48].</li>
    <li>Minor optimization to GetParamValueBytes(). Fix for [201128cc88].</li>
    <li>Support the ON UPDATE, ON DELETE, and MATCH clause information when generating schema metadata for foreign keys. Partial fix for [b226147b37]. VS designer changes are not yet tested.</li>
    <li>Fix incorrect resource name for SR.resx in the mixed-mode assembly.</li>
    <li>Reduce the number of String.Compare() calls in the hot path for SQLiteCommand.ExecuteReader().</li>
</ul>
<p>
    <b>1.0.74.0 - July 4, 2011</b>
</p>
<ul>
    <li>Updated to SQLite 3.7.7.1 <a href="http://www.sqlite.org/src/info/af0d91adf4">[af0d91adf4]</a>.</li>
    <li>Fix incorrect hard-coded .NET Framework version information SQLiteFactory_Linq.cs that was causing IServiceProvider.GetService to fail when running against the .NET Framework 3.5.</li>
    <li>Fix all XML documentation warnings.</li>
    <li>Restore support for the mixed-mode assembly (i.e. the one that can be registered in the Global Assembly Cache).</li>







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







186
187
188
189
190
191
192




































193
194
195
196
197
198
199
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.74.0 - July 4, 2011</b>
</p>
<ul>
    <li>Updated to SQLite 3.7.7.1 <a href="http://www.sqlite.org/src/info/af0d91adf4">[af0d91adf4]</a>.</li>
    <li>Fix incorrect hard-coded .NET Framework version information SQLiteFactory_Linq.cs that was causing IServiceProvider.GetService to fail when running against the .NET Framework 3.5.</li>
    <li>Fix all XML documentation warnings.</li>
    <li>Restore support for the mixed-mode assembly (i.e. the one that can be registered in the Global Assembly Cache).</li>
Changes to test/AssemblyInfo.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
using System.Reflection;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following 
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("System.Data.SQLite Tester")]
[assembly: AssemblyDescription("ADO.NET Data Provider for SQLite")]

[assembly: AssemblyCompany("http://system.data.sqlite.org/")]
[assembly: AssemblyProduct("System.Data.SQLite")]
[assembly: AssemblyCopyright("Public Domain")]

#if DEBUG
[assembly: AssemblyConfiguration("Debug")]
#else
[assembly: AssemblyConfiguration("Release")]
#endif

//  Setting ComVisible to false makes the types in this assembly not visible 
//  to COM componenets.  If you need to access a type in this assembly from 
//  COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("a6adbb45-c95f-44fb-bd47-f073e79c1d4b")]

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version 
//      Build Number
//      Revision
//
[assembly: AssemblyVersion("1.0.76.0")]
[assembly: AssemblyFileVersion("1.0.76.0")]






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
















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

using System.Reflection;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following 
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("test")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("test")]
[assembly: AssemblyCopyright("")]


[assembly: AssemblyTrademark("")]

[assembly: AssemblyCulture("")]


//  Setting ComVisible to false makes the types in this assembly not visible 
//  to COM componenets.  If you need to access a type in this assembly from 
//  COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("a6adbb45-c95f-44fb-bd47-f073e79c1d4b")]

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version 
//      Build Number
//      Revision
//
[assembly: AssemblyVersion("1.0.0.*")]

Changes to test/TestCases.cs.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using System;
using System.Data.Common;
using System.Data;
using System.Data.SQLite;
using System.Transactions;
using System.Collections.Generic;
using System.Text;

namespace test
{
  internal class TestCases : TestCaseBase
  {
    private const int NumThreads = 8;
    private const int ThreadTimeout = 60000;

    private List<string> droptables = new List<string>();
    private List<string> maydroptable = new List<string>();
    private long logevents = 0;
    

    internal TestCases()
    {












<
<
<







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



13
14
15
16
17
18
19
using System;
using System.Data.Common;
using System.Data;
using System.Data.SQLite;
using System.Transactions;
using System.Collections.Generic;
using System.Text;

namespace test
{
  internal class TestCases : TestCaseBase
  {



    private List<string> droptables = new List<string>();
    private List<string> maydroptable = new List<string>();
    private long logevents = 0;
    

    internal TestCases()
    {
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
            cnn.Open();

            // Decrpyt database
            cnn.ChangePassword("");

            cnn.Close();

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

            cnn.Open();

            // Re-Encrypts the database. The connection remains valid and usable afterwards.
            cnn.ChangePassword("mypassword");
            cnn.ChangePassword("mynewerpassword");

            maydroptable.Add("ChangePasswordTest2");
            if (cnn.State != ConnectionState.Open) cnn.Open();
            using (DbCommand cmd = cnn.CreateCommand())
            {
                cmd.CommandText = "CREATE TABLE ChangePasswordTest2(ID int primary key)";
                cmd.ExecuteNonQuery();
            }

            // Decrpyt database
            cnn.ChangePassword("");
            cnn.Close();

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

            // Try opening now without password
            cnn.Open();
            cnn.Close();

        }
    }








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







105
106
107
108
109
110
111






















112
113
114
115
116
117
118
            cnn.Open();

            // Decrpyt database
            cnn.ChangePassword("");

            cnn.Close();























            // Try opening now without password
            cnn.Open();
            cnn.Close();

        }
    }

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

    internal class MTTest
    {
      internal DbConnection cnn;
      internal Exception e;
      internal System.Threading.Thread t;
      internal int value;
      internal System.Threading.ManualResetEvent ev;
    }

    [Test(Sequence=11)]
    internal void MultithreadingTest()
    {
      using (DbCommand cmd = _cnn.CreateCommand())
      {
        droptables.Add("MultiThreadedTest");
        if (_fact.GetType().Name.IndexOf("SQLite", StringComparison.OrdinalIgnoreCase) == -1)
          cmd.CommandText = "CREATE TABLE MultiThreadedTest(ID integer identity primary key, ThreadId integer, MyValue integer)";
        else
          cmd.CommandText = "CREATE TABLE MultiThreadedTest(ID integer primary key, ThreadId integer, MyValue integer)";

        cmd.ExecuteNonQuery();
      }

      System.Threading.ManualResetEvent[] events = new System.Threading.ManualResetEvent[NumThreads];
      MTTest[] arr = new MTTest[NumThreads];

      for (int n = 0; n < arr.Length; n++)
      {
        arr[n] = new MTTest();
        arr[n].t = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(MultithreadedTestThread));
        arr[n].t.IsBackground = true;
        arr[n].cnn = ((ICloneable)_cnn).Clone() as DbConnection;
        arr[n].ev = events[n] = new System.Threading.ManualResetEvent(false);
        arr[n].t.Start(arr[n]);
      }

      System.Threading.WaitHandle.WaitAll(events, ThreadTimeout);

      bool failed = false;
      Exception e = null;

      for (int n = 0; n < arr.Length; n++)
      {
        if (arr[n].t.Join(0) == false)
        {
          failed = true;
          arr[n].t.Abort();
          arr[n].t.Join();
        }
        if (arr[n].e != null) e = arr[n].e;
        arr[n].cnn.Dispose();
        arr[n].ev.Close();
      }
      if (failed) throw new Exception("One or more threads deadlocked");
      if (e != null) 
        throw e;
    }

    internal void MultithreadedTestThread(object obj)
    {
      MTTest test = obj as MTTest;

      if (test.cnn.State != ConnectionState.Open)
        test.cnn.Open();

      int start = Environment.TickCount;
      try
      {
        using (DbCommand cmd = test.cnn.CreateCommand())
        {
          bool once = false;
          while (!once || ((Environment.TickCount - start) < 2000))
          {
            using (DbTransaction trans = test.cnn.BeginTransaction())
            {
              cmd.CommandText = String.Format("SELECT * FROM MultiThreadedTest WHERE ThreadId = {0}", test.t.ManagedThreadId);
              cmd.Transaction = trans;
              using (DbDataReader reader = cmd.ExecuteReader())
              {
                while (reader.Read())
                {
                  test.value += Convert.ToInt32(reader[2]);
                }
              }
              cmd.CommandText = String.Format("INSERT INTO MultiThreadedTest(ThreadId, MyValue) VALUES({0}, {1})", test.t.ManagedThreadId, Environment.TickCount);
              cmd.ExecuteNonQuery();

              trans.Commit();
            }

            once = true;
          }
        }
      }
      catch (Exception e)
      {
        test.e = e;
      }
      finally
      {
        test.ev.Set();
      }
    }

    [Test]
    internal void ParameterizedInsert()
    {
      using (DbCommand cmd = _cnn.CreateCommand())
      {







<
















<
|







<



|
<


<






<



<


















<
|

















<
<







<
<
<
<







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

    internal class MTTest
    {
      internal DbConnection cnn;
      internal Exception e;
      internal System.Threading.Thread t;
      internal int value;

    }

    [Test(Sequence=11)]
    internal void MultithreadingTest()
    {
      using (DbCommand cmd = _cnn.CreateCommand())
      {
        droptables.Add("MultiThreadedTest");
        if (_fact.GetType().Name.IndexOf("SQLite", StringComparison.OrdinalIgnoreCase) == -1)
          cmd.CommandText = "CREATE TABLE MultiThreadedTest(ID integer identity primary key, ThreadId integer, MyValue integer)";
        else
          cmd.CommandText = "CREATE TABLE MultiThreadedTest(ID integer primary key, ThreadId integer, MyValue integer)";

        cmd.ExecuteNonQuery();
      }


      MTTest[] arr = new MTTest[8];

      for (int n = 0; n < arr.Length; n++)
      {
        arr[n] = new MTTest();
        arr[n].t = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(MultithreadedTestThread));
        arr[n].t.IsBackground = true;
        arr[n].cnn = ((ICloneable)_cnn).Clone() as DbConnection;

        arr[n].t.Start(arr[n]);
      }

      System.Threading.Thread.Sleep(8000);

      bool failed = false;
      Exception e = null;

      for (int n = 0; n < arr.Length; n++)
      {
        if (arr[n].t.Join(0) == false)
        {
          failed = true;
          arr[n].t.Abort();

        }
        if (arr[n].e != null) e = arr[n].e;
        arr[n].cnn.Dispose();

      }
      if (failed) throw new Exception("One or more threads deadlocked");
      if (e != null) 
        throw e;
    }

    internal void MultithreadedTestThread(object obj)
    {
      MTTest test = obj as MTTest;

      if (test.cnn.State != ConnectionState.Open)
        test.cnn.Open();

      int start = Environment.TickCount;
      try
      {
        using (DbCommand cmd = test.cnn.CreateCommand())
        {

          while (Environment.TickCount - start < 2000)
          {
            using (DbTransaction trans = test.cnn.BeginTransaction())
            {
              cmd.CommandText = String.Format("SELECT * FROM MultiThreadedTest WHERE ThreadId = {0}", test.t.ManagedThreadId);
              cmd.Transaction = trans;
              using (DbDataReader reader = cmd.ExecuteReader())
              {
                while (reader.Read())
                {
                  test.value += Convert.ToInt32(reader[2]);
                }
              }
              cmd.CommandText = String.Format("INSERT INTO MultiThreadedTest(ThreadId, MyValue) VALUES({0}, {1})", test.t.ManagedThreadId, Environment.TickCount);
              cmd.ExecuteNonQuery();

              trans.Commit();
            }


          }
        }
      }
      catch (Exception e)
      {
        test.e = e;
      }




    }

    [Test]
    internal void ParameterizedInsert()
    {
      using (DbCommand cmd = _cnn.CreateCommand())
      {
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
            cnn.Open();

            logevents = 0;

            cnn.LogMessage(1, "test log event");

            if (logevents != 1)
                throw new Exception(String.Format(
                    "Log event count {0} incorrect.", logevents));

            cnn.Close();

            // remove the log handler before the connection is closed.
            sqlite_fact.Log -= logHandler;

        }







|
<







1602
1603
1604
1605
1606
1607
1608
1609

1610
1611
1612
1613
1614
1615
1616
            cnn.Open();

            logevents = 0;

            cnn.LogMessage(1, "test log event");

            if (logevents != 1)
                throw new Exception("Log event count incorrect.");


            cnn.Close();

            // remove the log handler before the connection is closed.
            sqlite_fact.Log -= logHandler;

        }
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
          reader.Read();
          decimal d = (decimal)reader.GetValue(0);
          d = reader.GetDecimal(0);
        }
      }
    }

    [Test(Sequence = 98)]
    internal void ScalarPreTest()
    {
      using (DbCommand cmd = _cnn.CreateCommand())
      {
        droptables.Add("SCALARTEST");

        cmd.CommandText = "CREATE TABLE SCALARTEST(x INTEGER PRIMARY KEY, y)";
        cmd.ExecuteNonQuery();

        for (int i = 1; i <= 1000; i++)
        {
          DbParameter param1 = cmd.CreateParameter();

          param1.ParameterName = "param1";
          param1.DbType = DbType.Int32;
          param1.Value = i;

          DbParameter param2 = cmd.CreateParameter();

          param2.ParameterName = "param2";
          param2.DbType = DbType.Int32;
          param2.Value = i;

          cmd.CommandText =
              "INSERT OR REPLACE INTO SCALARTEST(x, y) VALUES(?, ?)";

          cmd.Parameters.Clear();
          cmd.Parameters.Add(param1);
          cmd.Parameters.Add(param2);

          cmd.ExecuteNonQuery();
        }
      }
    }

    [Test(Sequence = 99)]
    internal void ScalarTest()
    {
      using (DbCommand cmd = _cnn.CreateCommand())
      {
        cmd.CommandText = "SELECT x FROM SCALARTEST ORDER BY x";
        cmd.ExecuteScalar();
      }
    }

    [Test(Sequence = 30)]
    internal void VerifyInsert()
    {
      using (DbCommand cmd = _cnn.CreateCommand())
      {
        cmd.CommandText = "SELECT Field1, Field2, [Fiëld3], [Fiæld4], Field5 FROM TestCase";
        cmd.Prepare();







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







1911
1912
1913
1914
1915
1916
1917














































1918
1919
1920
1921
1922
1923
1924
          reader.Read();
          decimal d = (decimal)reader.GetValue(0);
          d = reader.GetDecimal(0);
        }
      }
    }















































    [Test(Sequence = 30)]
    internal void VerifyInsert()
    {
      using (DbCommand cmd = _cnn.CreateCommand())
      {
        cmd.CommandText = "SELECT Field1, Field2, [Fiëld3], [Fiæld4], Field5 FROM TestCase";
        cmd.Prepare();
Changes to test/TestCasesDialog.cs.
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
        _grid.Rows.Add(args.TestName, "Starting", null, null);
        _grid.FirstDisplayedScrollingRowIndex = _grid.Rows.Count - 1;
      }
    }

    private void closeButton_Click(object sender, EventArgs e)
    {
      if (_autoRun)
      {
        try
        {
          Console.Write("canceled...");
        }
        catch
        {
          // do nothing, ignored.
        }

        Environment.Exit(2);
      }

      Close();
    }
  }
}







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




182
183
184
185
186
187
188














189
190
191
192
        _grid.Rows.Add(args.TestName, "Starting", null, null);
        _grid.FirstDisplayedScrollingRowIndex = _grid.Rows.Count - 1;
      }
    }

    private void closeButton_Click(object sender, EventArgs e)
    {














      Close();
    }
  }
}
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.76.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.74.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" />
    </DbProviderFactories>
  </system.data>
</configuration>
Changes to test/test.2008.csproj.
22
23
24
25
26
27
28

29
30
31
32
33
34
35
    <SQLiteNetDir>$(MSBuildProjectDirectory)\..</SQLiteNetDir>
    <NetFx20>true</NetFx20>
    <ConfigurationYear>2008</ConfigurationYear>
  </PropertyGroup>
  <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets" />
  <PropertyGroup Condition="'$(BinaryOutputPath)' != ''">
    <OutputPath>$(BinaryOutputPath)</OutputPath>

  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>







>







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
    <SQLiteNetDir>$(MSBuildProjectDirectory)\..</SQLiteNetDir>
    <NetFx20>true</NetFx20>
    <ConfigurationYear>2008</ConfigurationYear>
  </PropertyGroup>
  <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets" />
  <PropertyGroup Condition="'$(BinaryOutputPath)' != ''">
    <OutputPath>$(BinaryOutputPath)</OutputPath>
    <DocumentationFile>$(BinaryOutputPath)System.Data.SQLite.xml</DocumentationFile>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
Changes to test/test.2010.csproj.
15
16
17
18
19
20
21
22
23
24
25
26
27
28

29
30
31
32
33
34
35
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{E27B1B1E-19C0-45E8-AA74-B6E1C041A130}</ProjectGuid>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <OutputType>Exe</OutputType>
    <RootNamespace>test</RootNamespace>
    <AssemblyName>test</AssemblyName>
    <OldToolsVersion>3.5</OldToolsVersion>
    <TargetFrameworkProfile>Client</TargetFrameworkProfile>
    <SQLiteNetDir>$(MSBuildProjectDirectory)\..</SQLiteNetDir>
    <ConfigurationYear>2010</ConfigurationYear>
  </PropertyGroup>
  <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets" />
  <PropertyGroup Condition="'$(BinaryOutputPath)' != ''">
    <OutputPath>$(BinaryOutputPath)</OutputPath>

  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>







<






>







15
16
17
18
19
20
21

22
23
24
25
26
27
28
29
30
31
32
33
34
35
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{E27B1B1E-19C0-45E8-AA74-B6E1C041A130}</ProjectGuid>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <OutputType>Exe</OutputType>
    <RootNamespace>test</RootNamespace>
    <AssemblyName>test</AssemblyName>
    <OldToolsVersion>3.5</OldToolsVersion>

    <SQLiteNetDir>$(MSBuildProjectDirectory)\..</SQLiteNetDir>
    <ConfigurationYear>2010</ConfigurationYear>
  </PropertyGroup>
  <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets" />
  <PropertyGroup Condition="'$(BinaryOutputPath)' != ''">
    <OutputPath>$(BinaryOutputPath)</OutputPath>
    <DocumentationFile>$(BinaryOutputPath)System.Data.SQLite.xml</DocumentationFile>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
Changes to testce/AssemblyInfo.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
using System.Reflection;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following 
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("System.Data.SQLite Tester for Windows CE")]
[assembly: AssemblyDescription("ADO.NET Data Provider for SQLite")]

[assembly: AssemblyCompany("http://system.data.sqlite.org/")]
[assembly: AssemblyProduct("System.Data.SQLite")]
[assembly: AssemblyCopyright("Public Domain")]

#if DEBUG
[assembly: AssemblyConfiguration("Debug")]
#else
[assembly: AssemblyConfiguration("Release")]
#endif

// Setting ComVisible to false makes the types in this assembly not visible 
// to COM componenets.  If you need to access a type in this assembly from 
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("308969a2-e089-42db-afe3-bf564d8d62c3")]

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version 
//      Build Number
//      Revision
//
[assembly: AssemblyVersion("1.0.76.0")]
// [assembly: AssemblyFileVersion("1.0.76.0")]







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
















|
<

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
using System.Reflection;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following 
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("testce")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("")]


[assembly: AssemblyTrademark("")]

[assembly: AssemblyCulture("")]


// Setting ComVisible to false makes the types in this assembly not visible 
// to COM componenets.  If you need to access a type in this assembly from 
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("308969a2-e089-42db-afe3-bf564d8d62c3")]

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version 
//      Build Number
//      Revision
//
[assembly: AssemblyVersion("1.0.0.*")]


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.76.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.74.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.76.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.74.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/Program.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
using System;
using System.Diagnostics;
using System.Linq;
using System.Data.Objects;
using System.Text;
using System.Transactions;

namespace testlinq
{
  class Program
  {
      private static int Main(string[] args)
      {
          if (Environment.GetEnvironmentVariable("BREAK") != null)
          {
              Console.WriteLine(
                  "Attach a debugger to process {0} and press any key to continue.",
                  Process.GetCurrentProcess().Id);

              try
              {
                  Console.ReadKey(true); /* throw */
              }
              catch (InvalidOperationException) // Console.ReadKey
              {
                  // do nothing.
              }

              Debugger.Break();
          }

          string arg = null;

          if ((args != null) && (args.Length > 0))
              arg = args[0];

          if (arg == null)
              arg = "";

          arg = arg.Trim().TrimStart('-', '/').ToLowerInvariant();

          switch (arg)
          {
              case "": // String.Empty
              case "old":
                  {
                      return OldTests();
                  }
              case "skip":
                  {
                      int pageSize = 0;

                      if (args.Length > 1)
                      {
                          arg = args[1];

                          if (arg != null)
                              pageSize = int.Parse(arg.Trim());
                      }

                      return SkipTest(pageSize);
                  }
              case "endswith":
                  {
                      string value = null;

                      if (args.Length > 1)
                      {
                          value = args[1];

                          if (value != null)
                              value = value.Trim();
                      }

                      return EndsWithTest(value);
                  }
              case "startswith":
                  {
                      string value = null;

                      if (args.Length > 1)
                      {
                          value = args[1];

                          if (value != null)
                              value = value.Trim();
                      }

                      return StartsWithTest(value);
                  }
              case "eftransaction":
                  {
                      bool value = false;

                      if (args.Length > 1)
                      {
                          if (!bool.TryParse(args[1], out value))
                          {
                              Console.WriteLine(
                                  "cannot parse \"{0}\" as boolean",
                                  args[1]);

                              return 1;
                          }
                      }

                      return EFTransactionTest(value);
                  }
              default:
                  {
                      Console.WriteLine("unknown test \"{0}\"", arg);
                      return 1;
                  }
          }
      }

      //
      // NOTE: Used to test the fix for ticket [8b7d179c3c].
      //
      private static int SkipTest(int pageSize)
      {
          using (northwindEFEntities db = new northwindEFEntities())
          {
              bool once = false;
              int count = db.Customers.Count();

              int PageCount = (pageSize != 0) ?
                  (count / pageSize) + ((count % pageSize) == 0 ? 0 : 1) : 1;

              for (int pageIndex = 0; pageIndex < PageCount; pageIndex++)
              {
                  var query = db.Customers.OrderBy(p => p.City).
                      Skip(pageSize * pageIndex).Take(pageSize);

                  foreach (Customers customers in query)
                  {
                      if (once)
                          Console.Write(' ');

                      Console.Write(customers.CustomerID);

                      once = true;
                  }
              }
          }

          return 0;
      }

      //
      // NOTE: Used to test the fix for ticket [59edc1018b].
      //
      private static int EndsWithTest(string value)
      {
          using (northwindEFEntities db = new northwindEFEntities())
          {
              bool once = false;
              var query = from c in db.Customers
                          where c.City.EndsWith(value)
                          orderby c.CustomerID
                          select c;

              foreach (Customers customers in query)
              {
                  if (once)
                      Console.Write(' ');

                  Console.Write(customers.CustomerID);

                  once = true;
              }
          }

          return 0;
      }

      //
      // NOTE: Used to verify the behavior from ticket [00f86f9739].
      //
      private static int StartsWithTest(string value)
      {
          using (northwindEFEntities db = new northwindEFEntities())
          {
              bool once = false;
              var query = from c in db.Customers
                          where c.City.StartsWith(value)
                          orderby c.CustomerID
                          select c;

              foreach (Customers customers in query)
              {
                  if (once)
                      Console.Write(' ');

                  Console.Write(customers.CustomerID);

                  once = true;
              }
          }

          return 0;
      }

      //
      // NOTE: Used to test the fix for ticket [ccfa69fc32].
      //
      private static int EFTransactionTest(bool add)
      {
          //
          // NOTE: Some of these territories already exist and should cause
          //       an exception to be thrown when we try to INSERT them.
          //
          long[] territoryIds = new long[] {
                 1,    2,    3,    4,    5, // NOTE: Success
                 6,    7,    8,    9,   10, // NOTE: Success
              1576, 1577, 1578, 1579, 1580, // NOTE: Success
              1581, 1730, 1833, 2116, 2139, // NOTE: Fail (1581)
              2140, 2141                    // NOTE: Skipped
          };

          if (add)
          {
              using (northwindEFEntities db = new northwindEFEntities())
              {
                  using (TransactionScope scope = new TransactionScope())
                  {
                      //
                      // NOTE: *REQUIRED* This is required so that the
                      //       Entity Framework is prevented from opening
                      //       multiple connections to the underlying SQLite
                      //       database (i.e. which would result in multiple
                      //       IMMEDIATE transactions, thereby failing [later
                      //       on] with locking errors).
                      //
                      db.Connection.Open();

                      foreach (int id in territoryIds)
                      {
                          Territories territories = new Territories();

                          territories.TerritoryID = id;
                          territories.TerritoryDescription = String.Format(
                              "Test Territory #{0}", id);
                          territories.Regions = db.Regions.First();

                          db.AddObject("Territories", territories);
                      }

                      try
                      {
#if NET_20
                          db.SaveChanges(false);
#else
                          db.SaveChanges(SaveOptions.None);
#endif
                      }
                      catch (Exception e)
                      {
                          Console.WriteLine(e);
                      }
                      finally
                      {
                          scope.Complete();
                          db.AcceptAllChanges();
                      }
                  }
              }
          }
          else
          {
              using (northwindEFEntities db = new northwindEFEntities())
              {
                  bool once = false;
#if NET_20
                  //
                  // HACK: We cannot use the Contains extension method within a
                  //       LINQ query with the .NET Framework 3.5.
                  //
                  var query = from t in db.Territories
                    orderby t.TerritoryID
                    select t;

                  foreach (Territories territories in query)
                  {
                      if (Array.IndexOf(territoryIds, territories.TerritoryID) == -1)
                          continue;

                      if (once)
                          Console.Write(' ');

                      Console.Write(territories.TerritoryID);

                      once = true;
                  }
#else
                  var query = from t in db.Territories
                    where territoryIds.AsQueryable<long>().Contains<long>(t.TerritoryID)
                    orderby t.TerritoryID
                    select t;

                  foreach (Territories territories in query)
                  {
                      if (once)
                          Console.Write(' ');

                      Console.Write(territories.TerritoryID);

                      once = true;
                  }
#endif
              }
          }

          return 0;
      }

    private static int OldTests()
    {
      using (northwindEFEntities db = new northwindEFEntities())
      {
        {
          string entitySQL = "SELECT VALUE o FROM Orders AS o WHERE SQLite.DatePart('yyyy', o.OrderDate) = 1997;";
          ObjectQuery<Orders> query = db.CreateQuery<Orders>(entitySQL);


<



<





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







1

2
3
4

5
6
7
8
9
10

















































































































































































































































































































11
12
13
14
15
16
17
using System;

using System.Linq;
using System.Data.Objects;
using System.Text;


namespace testlinq
{
  class Program
  {
    static void Main(string[] args)

















































































































































































































































































































    {
      using (northwindEFEntities db = new northwindEFEntities())
      {
        {
          string entitySQL = "SELECT VALUE o FROM Orders AS o WHERE SQLite.DatePart('yyyy', o.OrderDate) = 1997;";
          ObjectQuery<Orders> query = db.CreateQuery<Orders>(entitySQL);

446
447
448
449
450
451
452
453
454
455
456
457
      }

      //
      // NOTE: (JJM) Removed on 2011/07/06, makes it harder to run this EXE via
      //       the new unit test suite.
      //
      // Console.ReadKey();

      return 0;
    }
  }
}







<
<



139
140
141
142
143
144
145


146
147
148
      }

      //
      // NOTE: (JJM) Removed on 2011/07/06, makes it harder to run this EXE via
      //       the new unit test suite.
      //
      // Console.ReadKey();


    }
  }
}
Changes to testlinq/Properties/AssemblyInfo.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
using System.Reflection;

using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following 
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("System.Data.SQLite Tester for LINQ")]
[assembly: AssemblyDescription("ADO.NET Data Provider for SQLite")]

[assembly: AssemblyCompany("http://system.data.sqlite.org/")]
[assembly: AssemblyProduct("System.Data.SQLite")]
[assembly: AssemblyCopyright("Public Domain")]

#if DEBUG
[assembly: AssemblyConfiguration("Debug")]
#else
[assembly: AssemblyConfiguration("Release")]
#endif

// Setting ComVisible to false makes the types in this assembly not visible 
// to COM components.  If you need to access a type in this assembly from 
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("8fd19c43-2fa6-487c-9201-47dd59eed056")]

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      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.76.0")]
[assembly: AssemblyFileVersion("1.0.76.0")]

>





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



















|
|
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
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following 
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("testlinq")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("")]


[assembly: AssemblyTrademark("")]

[assembly: AssemblyCulture("")]


// Setting ComVisible to false makes the types in this assembly not visible 
// to COM components.  If you need to access a type in this assembly from 
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("8fd19c43-2fa6-487c-9201-47dd59eed056")]

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      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.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
Changes to testlinq/testlinq.2008.csproj.
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
    <SQLiteNetDir>$(MSBuildProjectDirectory)\..</SQLiteNetDir>
    <NetFx20>true</NetFx20>
    <ConfigurationYear>2008</ConfigurationYear>
  </PropertyGroup>
  <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets" />
  <PropertyGroup Condition="'$(BinaryOutputPath)' != ''">
    <OutputPath>$(BinaryOutputPath)</OutputPath>

  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="System.Data.Entity" />
    <Reference Include="System.Runtime.Serialization" />
    <Reference Include="System.Transactions" />
    <Reference Include="System.Xml" />
    <Reference Include="System.Data" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="NorthwindModel2008.Designer.cs">
      <AutoGen>True</AutoGen>
      <DesignTime>True</DesignTime>







>



















<







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
    <SQLiteNetDir>$(MSBuildProjectDirectory)\..</SQLiteNetDir>
    <NetFx20>true</NetFx20>
    <ConfigurationYear>2008</ConfigurationYear>
  </PropertyGroup>
  <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets" />
  <PropertyGroup Condition="'$(BinaryOutputPath)' != ''">
    <OutputPath>$(BinaryOutputPath)</OutputPath>
    <DocumentationFile>$(BinaryOutputPath)System.Data.SQLite.xml</DocumentationFile>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="System.Data.Entity" />
    <Reference Include="System.Runtime.Serialization" />

    <Reference Include="System.Xml" />
    <Reference Include="System.Data" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="NorthwindModel2008.Designer.cs">
      <AutoGen>True</AutoGen>
      <DesignTime>True</DesignTime>
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
      <Generator>EntityModelCodeGenerator</Generator>
      <LastGenOutput>NorthwindModel2008.Designer.cs</LastGenOutput>
    </EntityDeploy>
  </ItemGroup>
  <ItemGroup>
    <Service Include="{C8F2D6AC-F9F4-4E40-A399-22F9A9A5CBD2}" />
  </ItemGroup>
  <Import Project="$(SQLiteNetDir)\System.Data.SQLite\System.Data.SQLite.Properties.targets" />
  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
</Project>







<









68
69
70
71
72
73
74

75
76
77
78
79
80
81
82
83
      <Generator>EntityModelCodeGenerator</Generator>
      <LastGenOutput>NorthwindModel2008.Designer.cs</LastGenOutput>
    </EntityDeploy>
  </ItemGroup>
  <ItemGroup>
    <Service Include="{C8F2D6AC-F9F4-4E40-A399-22F9A9A5CBD2}" />
  </ItemGroup>

  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
</Project>
Changes to testlinq/testlinq.2010.csproj.
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
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}</ProjectGuid>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <OutputType>Exe</OutputType>
    <RootNamespace>testlinq</RootNamespace>
    <AssemblyName>testlinq</AssemblyName>
    <OldToolsVersion>3.5</OldToolsVersion>
    <TargetFrameworkProfile>Client</TargetFrameworkProfile>
    <SQLiteNetDir>$(MSBuildProjectDirectory)\..</SQLiteNetDir>
    <ConfigurationYear>2010</ConfigurationYear>
  </PropertyGroup>
  <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets" />
  <PropertyGroup Condition="'$(BinaryOutputPath)' != ''">
    <OutputPath>$(BinaryOutputPath)</OutputPath>

  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="System" />
    <Reference Include="System.Data.Entity" />
    <Reference Include="System.Runtime.Serialization" />
    <Reference Include="System.Transactions" />
    <Reference Include="System.Xml" />
    <Reference Include="System.Data" />
  </ItemGroup>
  <ItemGroup>
    <Compile Condition="'$(TargetFrameworkVersion)' == 'v3.5'"
             Include="NorthwindModel2008.Designer.cs">
      <AutoGen>True</AutoGen>
      <DesignTime>True</DesignTime>
      <DependentUpon>NorthwindModel2008.edmx</DependentUpon>
    </Compile>
    <Compile Condition="'$(TargetFrameworkVersion)' == 'v4.0'"
             Include="NorthwindModel2010.Designer.cs">
      <AutoGen>True</AutoGen>
      <DesignTime>True</DesignTime>
      <DependentUpon>NorthwindModel2010.edmx</DependentUpon>
    </Compile>
    <Compile Include="Program.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
  </ItemGroup>
  <ItemGroup>
    <None Condition="'$(TargetFrameworkVersion)' == 'v3.5'"
          Include="2008\App.Config" />
    <None Condition="'$(TargetFrameworkVersion)' == 'v4.0'"
          Include="2010\App.Config" />
    <None Include="northwindEF.db">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>
    <EntityDeploy Condition="'$(TargetFrameworkVersion)' == 'v3.5'"
                  Include="NorthwindModel2008.edmx">
      <Generator>EntityModelCodeGenerator</Generator>
      <LastGenOutput>NorthwindModel2008.Designer.cs</LastGenOutput>
    </EntityDeploy>
    <EntityDeploy Condition="'$(TargetFrameworkVersion)' == 'v4.0'"
                  Include="NorthwindModel2010.edmx">
      <Generator>EntityModelCodeGenerator</Generator>
      <LastGenOutput>NorthwindModel2010.Designer.cs</LastGenOutput>
    </EntityDeploy>
  </ItemGroup>
  <ItemGroup>
    <Service Include="{C8F2D6AC-F9F4-4E40-A399-22F9A9A5CBD2}" />
  </ItemGroup>
  <Import Project="$(SQLiteNetDir)\System.Data.SQLite\System.Data.SQLite.Properties.targets" />
  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
</Project>







<






>


















<




<
<
<
<
<
<
<
|








<
<
<
|



<
<
<
<
<
<
|







<

|







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
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{9D3CF7A6-092A-4B05-B0E4-BEF6944525B3}</ProjectGuid>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <OutputType>Exe</OutputType>
    <RootNamespace>testlinq</RootNamespace>
    <AssemblyName>testlinq</AssemblyName>
    <OldToolsVersion>3.5</OldToolsVersion>

    <SQLiteNetDir>$(MSBuildProjectDirectory)\..</SQLiteNetDir>
    <ConfigurationYear>2010</ConfigurationYear>
  </PropertyGroup>
  <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets" />
  <PropertyGroup Condition="'$(BinaryOutputPath)' != ''">
    <OutputPath>$(BinaryOutputPath)</OutputPath>
    <DocumentationFile>$(BinaryOutputPath)System.Data.SQLite.xml</DocumentationFile>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="System" />
    <Reference Include="System.Data.Entity" />
    <Reference Include="System.Runtime.Serialization" />

    <Reference Include="System.Xml" />
    <Reference Include="System.Data" />
  </ItemGroup>
  <ItemGroup>







    <Compile Include="NorthwindModel2010.Designer.cs">
      <AutoGen>True</AutoGen>
      <DesignTime>True</DesignTime>
      <DependentUpon>NorthwindModel2010.edmx</DependentUpon>
    </Compile>
    <Compile Include="Program.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
  </ItemGroup>
  <ItemGroup>



    <None Include="2010\App.Config" />
    <None Include="northwindEF.db">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>






    <EntityDeploy Include="NorthwindModel2010.edmx">
      <Generator>EntityModelCodeGenerator</Generator>
      <LastGenOutput>NorthwindModel2010.Designer.cs</LastGenOutput>
    </EntityDeploy>
  </ItemGroup>
  <ItemGroup>
    <Service Include="{C8F2D6AC-F9F4-4E40-A399-22F9A9A5CBD2}" />
  </ItemGroup>

  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
</Project>
Added tools/install/GACWrap.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
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
//-------------------------------------------------------------
// GACWrap.cs
//
// This implements managed wrappers to GAC API Interfaces
//-------------------------------------------------------------

using System;
using System.Runtime.InteropServices;
using System.Text;

namespace System.GACManagedAccess
{
  //-------------------------------------------------------------
  // Interfaces defined by fusion
  //-------------------------------------------------------------
  [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("e707dcde-d1cd-11d2-bab9-00c04f8eceae")]
  internal interface IAssemblyCache
  {
    [PreserveSig()]
    int UninstallAssembly(
                        int flags,
                        [MarshalAs(UnmanagedType.LPWStr)]
                            String assemblyName,
                        InstallReference refData,
                        out AssemblyCacheUninstallDisposition disposition);

    [PreserveSig()]
    int QueryAssemblyInfo(
                        int flags,
                        [MarshalAs(UnmanagedType.LPWStr)]
                            String assemblyName,
                        ref AssemblyInfo assemblyInfo);
    [PreserveSig()]
    int Reserved(
                        int flags,
                        IntPtr pvReserved,
                        out Object ppAsmItem,
                        [MarshalAs(UnmanagedType.LPWStr)]
                            String assemblyName);
    [PreserveSig()]
    int Reserved(out Object ppAsmScavenger);

    [PreserveSig()]
    int InstallAssembly(
                        int flags,
                        [MarshalAs(UnmanagedType.LPWStr)]
                            String assemblyFilePath,
                        InstallReference refData);
  }// IAssemblyCache

  [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("CD193BC0-B4BC-11d2-9833-00C04FC31D2E")]
  internal interface IAssemblyName
  {
    [PreserveSig()]
    int SetProperty(
            int PropertyId,
            IntPtr pvProperty,
            int cbProperty);

    [PreserveSig()]
    int GetProperty(
            int PropertyId,
            IntPtr pvProperty,
            ref int pcbProperty);

    [PreserveSig()]
    int Finalize();

    [PreserveSig()]
    int GetDisplayName(
            StringBuilder pDisplayName,
            ref int pccDisplayName,
            int displayFlags);

    [PreserveSig()]
    int Reserved(ref Guid guid,
        Object obj1,
        Object obj2,
        String string1,
        Int64 llFlags,
        IntPtr pvReserved,
        int cbReserved,
        out IntPtr ppv);

    [PreserveSig()]
    int GetName(
            ref int pccBuffer,
            StringBuilder pwzName);

    [PreserveSig()]
    int GetVersion(
            out int versionHi,
            out int versionLow);
    [PreserveSig()]
    int IsEqual(
            IAssemblyName pAsmName,
            int cmpFlags);

    [PreserveSig()]
    int Clone(out IAssemblyName pAsmName);
  }// IAssemblyName

  [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("21b8916c-f28e-11d2-a473-00c04f8ef448")]
  internal interface IAssemblyEnum
  {
    [PreserveSig()]
    int GetNextAssembly(
            IntPtr pvReserved,
            out IAssemblyName ppName,
            int flags);
    [PreserveSig()]
    int Reset();
    [PreserveSig()]
    int Clone(out IAssemblyEnum ppEnum);
  }// IAssemblyEnum

  [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("582dac66-e678-449f-aba6-6faaec8a9394")]
  internal interface IInstallReferenceItem
  {
    // A pointer to a FUSION_INSTALL_REFERENCE structure. 
    // The memory is allocated by the GetReference method and is freed when 
    // IInstallReferenceItem is released. Callers must not hold a reference to this 
    // buffer after the IInstallReferenceItem object is released. 
    // This uses the InstallReferenceOutput object to avoid allocation 
    // issues with the interop layer. 
    // This cannot be marshaled directly - must use IntPtr 
    [PreserveSig()]
    int GetReference(
            out IntPtr pRefData,
            int flags,
            IntPtr pvReserced);
  }// IInstallReferenceItem

  [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("56b1a988-7c0c-4aa2-8639-c3eb5a90226f")]
  internal interface IInstallReferenceEnum
  {
    [PreserveSig()]
    int GetNextInstallReferenceItem(
            out IInstallReferenceItem ppRefItem,
            int flags,
            IntPtr pvReserced);
  }// IInstallReferenceEnum

  public enum AssemblyCommitFlags
  {
    Default = 1,
    Force = 2
  }// enum AssemblyCommitFlags

  public enum AssemblyCacheUninstallDisposition
  {
    Unknown = 0,
    Uninstalled = 1,
    StillInUse = 2,
    AlreadyUninstalled = 3,
    DeletePending = 4,
    HasInstallReference = 5,
    ReferenceNotFound = 6
  }

  [Flags]
  internal enum AssemblyCacheFlags
  {
    GAC = 2,
  }

  internal enum CreateAssemblyNameObjectFlags
  {
    CANOF_DEFAULT = 0,
    CANOF_PARSE_DISPLAY_NAME = 1,
  }

  [Flags]
  internal enum AssemblyNameDisplayFlags
  {
    VERSION = 0x01,
    CULTURE = 0x02,
    PUBLIC_KEY_TOKEN = 0x04,
    PROCESSORARCHITECTURE = 0x20,
    RETARGETABLE = 0x80,
    // This enum will change in the future to include
    // more attributes.
    ALL = VERSION
                                | CULTURE
                                | PUBLIC_KEY_TOKEN
                                | PROCESSORARCHITECTURE
                                | RETARGETABLE
  }

  [StructLayout(LayoutKind.Sequential)]
  public class InstallReference
  {
    public InstallReference(Guid guid, String id, String data)
    {
      cbSize = (int)(2 * IntPtr.Size + 16 + (id.Length + data.Length) * 2);
      flags = 0;
      // quiet compiler warning 
      if (flags == 0) { }
      guidScheme = guid;
      identifier = id;
      description = data;
    }

    public Guid GuidScheme
    {
      get { return guidScheme; }
    }

    public String Identifier
    {
      get { return identifier; }
    }

    public String Description
    {
      get { return description; }
    }

    int cbSize;
    int flags;
    Guid guidScheme;
    [MarshalAs(UnmanagedType.LPWStr)]
    String identifier;
    [MarshalAs(UnmanagedType.LPWStr)]
    String description;
  }

  [StructLayout(LayoutKind.Sequential)]
  internal struct AssemblyInfo
  {
    public int cbAssemblyInfo; // size of this structure for future expansion
    public int assemblyFlags;
    public long assemblySizeInKB;
    [MarshalAs(UnmanagedType.LPWStr)]
    public String currentAssemblyPath;
    public int cchBuf; // size of path buf.
  }

  [ComVisible(false)]
  public class InstallReferenceGuid
  {
    public static bool IsValidGuidScheme(Guid guid)
    {
      return (guid.Equals(UninstallSubkeyGuid) ||
              guid.Equals(FilePathGuid) ||
              guid.Equals(OpaqueGuid) ||
              guid.Equals(Guid.Empty));
    }

    public readonly static Guid UninstallSubkeyGuid = new Guid("8cedc215-ac4b-488b-93c0-a50a49cb2fb8");
    public readonly static Guid FilePathGuid = new Guid("b02f9d65-fb77-4f7a-afa5-b391309f11c9");
    public readonly static Guid OpaqueGuid = new Guid("2ec93463-b0c3-45e1-8364-327e96aea856");
    // these GUID cannot be used for installing into GAC.
    public readonly static Guid MsiGuid = new Guid("25df0fc1-7f97-4070-add7-4b13bbfd7cb8");
    public readonly static Guid OsInstallGuid = new Guid("d16d444c-56d8-11d5-882d-0080c847b195");
  }

  [ComVisible(false)]
  public static class AssemblyCache
  {
    public static void InstallAssembly(String assemblyPath, InstallReference reference, AssemblyCommitFlags flags)
    {
      if (reference != null)
      {
        if (!InstallReferenceGuid.IsValidGuidScheme(reference.GuidScheme))
          throw new ArgumentException("Invalid reference guid.", "guid");
      }

      IAssemblyCache ac = null;

      int hr = 0;

      hr = Utils.CreateAssemblyCache(out ac, 0);
      if (hr >= 0)
      {
        hr = ac.InstallAssembly((int)flags, assemblyPath, reference);
      }

      if (hr < 0)
      {
        Marshal.ThrowExceptionForHR(hr);
      }
    }

    // assemblyName has to be fully specified name. 
    // A.k.a, for v1.0/v1.1 assemblies, it should be "name, Version=xx, Culture=xx, PublicKeyToken=xx".
    // For v2.0 assemblies, it should be "name, Version=xx, Culture=xx, PublicKeyToken=xx, ProcessorArchitecture=xx".
    // If assemblyName is not fully specified, a random matching assembly will be uninstalled. 
    public static void UninstallAssembly(String assemblyName, InstallReference reference, out AssemblyCacheUninstallDisposition disp)
    {
      AssemblyCacheUninstallDisposition dispResult = AssemblyCacheUninstallDisposition.Uninstalled;
      if (reference != null)
      {
        if (!InstallReferenceGuid.IsValidGuidScheme(reference.GuidScheme))
          throw new ArgumentException("Invalid reference guid.", "guid");
      }

      IAssemblyCache ac = null;

      int hr = Utils.CreateAssemblyCache(out ac, 0);
      if (hr >= 0)
      {
        hr = ac.UninstallAssembly(0, assemblyName, reference, out dispResult);
      }

      if (hr < 0)
      {
        Marshal.ThrowExceptionForHR(hr);
      }

      disp = dispResult;
    }

    // See comments in UninstallAssembly
    public static String QueryAssemblyInfo(String assemblyName)
    {
      if (assemblyName == null)
      {
        throw new ArgumentException("Invalid name", "assemblyName");
      }

      AssemblyInfo aInfo = new AssemblyInfo();

      aInfo.cchBuf = 1024;
      // Get a string with the desired length
      aInfo.currentAssemblyPath = new String('\0', aInfo.cchBuf);

      IAssemblyCache ac = null;
      int hr = Utils.CreateAssemblyCache(out ac, 0);
      if (hr >= 0)
      {
        hr = ac.QueryAssemblyInfo(0, assemblyName, ref aInfo);
      }
      if (hr < 0)
      {
        Marshal.ThrowExceptionForHR(hr);
      }

      return aInfo.currentAssemblyPath;
    }
  }

  [ComVisible(false)]
  public class AssemblyCacheEnum
  {
    // null means enumerate all the assemblies
    public AssemblyCacheEnum(String assemblyName)
    {
      IAssemblyName fusionName = null;
      int hr = 0;

      if (assemblyName != null)
      {
        hr = Utils.CreateAssemblyNameObject(
                out fusionName,
                assemblyName,
                CreateAssemblyNameObjectFlags.CANOF_PARSE_DISPLAY_NAME,
                IntPtr.Zero);
      }

      if (hr >= 0)
      {
        hr = Utils.CreateAssemblyEnum(
                out m_AssemblyEnum,
                IntPtr.Zero,
                fusionName,
                AssemblyCacheFlags.GAC,
                IntPtr.Zero);
      }

      if (hr < 0)
      {
        Marshal.ThrowExceptionForHR(hr);
      }
    }

    public String GetNextAssembly()
    {
      int hr = 0;
      IAssemblyName fusionName = null;

      if (done)
      {
        return null;
      }

      // Now get next IAssemblyName from m_AssemblyEnum
      hr = m_AssemblyEnum.GetNextAssembly((IntPtr)0, out fusionName, 0);

      if (hr < 0)
      {
        Marshal.ThrowExceptionForHR(hr);
      }

      if (fusionName != null)
      {
        return GetFullName(fusionName);
      }
      else
      {
        done = true;
        return null;
      }
    }

    private String GetFullName(IAssemblyName fusionAsmName)
    {
      StringBuilder sDisplayName = new StringBuilder(1024);
      int iLen = 1024;

      int hr = fusionAsmName.GetDisplayName(sDisplayName, ref iLen, (int)AssemblyNameDisplayFlags.ALL);
      if (hr < 0)
      {
        Marshal.ThrowExceptionForHR(hr);
      }

      return sDisplayName.ToString();
    }

    private IAssemblyEnum m_AssemblyEnum = null;
    private bool done;
  }// class AssemblyCacheEnum

  public class AssemblyCacheInstallReferenceEnum
  {
    public AssemblyCacheInstallReferenceEnum(String assemblyName)
    {
      IAssemblyName fusionName = null;

      int hr = Utils.CreateAssemblyNameObject(
                  out fusionName,
                  assemblyName,
                  CreateAssemblyNameObjectFlags.CANOF_PARSE_DISPLAY_NAME,
                  IntPtr.Zero);

      if (hr >= 0)
      {
        hr = Utils.CreateInstallReferenceEnum(out refEnum, fusionName, 0, IntPtr.Zero);
      }

      if (hr < 0)
      {
        Marshal.ThrowExceptionForHR(hr);
      }
    }

    public InstallReference GetNextReference()
    {
      IInstallReferenceItem item = null;
      int hr = refEnum.GetNextInstallReferenceItem(out item, 0, IntPtr.Zero);
      if ((uint)hr == 0x80070103)
      {   // ERROR_NO_MORE_ITEMS
        return null;
      }

      if (hr < 0)
      {
        Marshal.ThrowExceptionForHR(hr);
      }

      IntPtr refData;
      InstallReference instRef = new InstallReference(Guid.Empty, String.Empty, String.Empty);

      hr = item.GetReference(out refData, 0, IntPtr.Zero);
      if (hr < 0)
      {
        Marshal.ThrowExceptionForHR(hr);
      }

      Marshal.PtrToStructure(refData, instRef);
      return instRef;
    }

    private IInstallReferenceEnum refEnum;
  }

  internal class Utils
  {
    [DllImport("fusion.dll")]
    internal static extern int CreateAssemblyEnum(
            out IAssemblyEnum ppEnum,
            IntPtr pUnkReserved,
            IAssemblyName pName,
            AssemblyCacheFlags flags,
            IntPtr pvReserved);

    [DllImport("fusion.dll")]
    internal static extern int CreateAssemblyNameObject(
            out IAssemblyName ppAssemblyNameObj,
            [MarshalAs(UnmanagedType.LPWStr)]
                String szAssemblyName,
            CreateAssemblyNameObjectFlags flags,
            IntPtr pvReserved);

    [DllImport("fusion.dll")]
    internal static extern int CreateAssemblyCache(
            out IAssemblyCache ppAsmCache,
            int reserved);

    [DllImport("fusion.dll")]
    internal static extern int CreateInstallReferenceEnum(
            out IInstallReferenceEnum ppRefEnum,
            IAssemblyName pName,
            int dwFlags,
            IntPtr pvReserved);
  }
}
Added tools/install/InstallDesigner.Designer.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
namespace install
{
  partial class InstallDesigner
  {
    /// <summary>
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.IContainer components = null;

    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
    protected override void Dispose(bool disposing)
    {
      if (disposing && (components != null))
      {
        components.Dispose();
      }
      base.Dispose(disposing);
    }

    #region Windows Form Designer generated code

    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
      System.Windows.Forms.ColumnHeader columnHeader1;
      System.Windows.Forms.Label label1;
      System.Windows.Forms.Label label3;
      System.Windows.Forms.Label label2;
      System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(InstallDesigner));
      this.installList = new System.Windows.Forms.ListView();
      this.warningPanel = new System.Windows.Forms.Panel();
      this.closeButton = new System.Windows.Forms.Button();
      columnHeader1 = new System.Windows.Forms.ColumnHeader();
      label1 = new System.Windows.Forms.Label();
      label3 = new System.Windows.Forms.Label();
      label2 = new System.Windows.Forms.Label();
      this.warningPanel.SuspendLayout();
      this.SuspendLayout();
      // 
      // columnHeader1
      // 
      columnHeader1.Text = "Environment";
      columnHeader1.Width = 800;
      // 
      // label1
      // 
      label1.AutoSize = true;
      label1.Location = new System.Drawing.Point(13, 13);
      label1.Name = "label1";
      label1.Size = new System.Drawing.Size(325, 13);
      label1.TabIndex = 0;
      label1.Text = "Install SQLite Design-Time Support for the following environments:";
      // 
      // label3
      // 
      label3.AutoSize = true;
      label3.Location = new System.Drawing.Point(0, 0);
      label3.Name = "label3";
      label3.Size = new System.Drawing.Size(13, 13);
      label3.TabIndex = 5;
      label3.Text = "*";
      // 
      // label2
      // 
      label2.Location = new System.Drawing.Point(10, 0);
      label2.Name = "label2";
      label2.Size = new System.Drawing.Size(340, 61);
      label2.TabIndex = 4;
      label2.Text = resources.GetString("label2.Text");
      // 
      // installList
      // 
      this.installList.CheckBoxes = true;
      this.installList.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
            columnHeader1});
      this.installList.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;
      this.installList.Location = new System.Drawing.Point(13, 30);
      this.installList.Name = "installList";
      this.installList.Size = new System.Drawing.Size(350, 149);
      this.installList.TabIndex = 1;
      this.installList.UseCompatibleStateImageBehavior = false;
      this.installList.View = System.Windows.Forms.View.List;
      this.installList.ItemChecked += new System.Windows.Forms.ItemCheckedEventHandler(this.installList_ItemChecked);
      // 
      // warningPanel
      // 
      this.warningPanel.Controls.Add(label3);
      this.warningPanel.Controls.Add(label2);
      this.warningPanel.Location = new System.Drawing.Point(13, 186);
      this.warningPanel.Name = "warningPanel";
      this.warningPanel.Size = new System.Drawing.Size(350, 73);
      this.warningPanel.TabIndex = 2;
      this.warningPanel.Visible = false;
      // 
      // closeButton
      // 
      this.closeButton.DialogResult = System.Windows.Forms.DialogResult.OK;
      this.closeButton.Location = new System.Drawing.Point(288, 270);
      this.closeButton.Name = "closeButton";
      this.closeButton.Size = new System.Drawing.Size(75, 23);
      this.closeButton.TabIndex = 3;
      this.closeButton.Text = "&Close";
      this.closeButton.UseVisualStyleBackColor = true;
      this.closeButton.Click += new System.EventHandler(this.closeButton_Click);
      // 
      // InstallDesigner
      // 
      this.AcceptButton = this.closeButton;
      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
      this.CancelButton = this.closeButton;
      this.ClientSize = new System.Drawing.Size(375, 305);
      this.Controls.Add(this.closeButton);
      this.Controls.Add(this.warningPanel);
      this.Controls.Add(this.installList);
      this.Controls.Add(label1);
      this.Font = new System.Drawing.Font("MS Shell Dlg 2", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
      this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
      this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
      this.MaximizeBox = false;
      this.MinimizeBox = false;
      this.Name = "InstallDesigner";
      this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
      this.Text = "SQLite Designer Installation";
      this.TopMost = true;
      this.warningPanel.ResumeLayout(false);
      this.warningPanel.PerformLayout();
      this.ResumeLayout(false);
      this.PerformLayout();

    }

    #endregion

    private System.Windows.Forms.ListView installList;
    private System.Windows.Forms.Panel warningPanel;
    private System.Windows.Forms.Button closeButton;
  }
}
Added tools/install/InstallDesigner.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
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
/********************************************************
 * 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 install
{
  using System;
  using System.ComponentModel;
  using System.Data;
  using System.Drawing;
  using System.Text;
  using System.Windows.Forms;
  using Microsoft.Win32;
  using System.IO;
  using System.GACManagedAccess;
  using System.Xml;
  using System.Diagnostics;
  using System.Collections.Generic;

  public partial class InstallDesigner : Form
  {
    private static Guid standardDataProviderGuid = new Guid("{0EBAAB6E-CA80-4b4a-8DDF-CBE6BF058C70}");
    private static Guid standardDataSourcesGuid = new Guid("{0EBAAB6E-CA80-4b4a-8DDF-CBE6BF058C71}");
    private static Guid standardCFDataSourcesGuid = new Guid("{0EBAAB6E-CA80-4b4a-8DDF-CBE6BF058C72}");
    private static Guid oledbDataProviderGuid = new Guid("{7F041D59-D76A-44ed-9AA2-FBF6B0548B80}");
    private static Guid oledbAltDataProviderGuid = new Guid("{7F041D59-D76A-44ed-9AA2-FBF6B0548B81}");
    private static Guid jetDataSourcesGuid = new Guid("{466CE797-67A4-4495-B75C-A3FD282E7FC3}");
    private static Guid jetAltDataSourcesGuid = new Guid("{466CE797-67A4-4495-B75C-A3FD282E7FC4}");
    private static string[] compactFrameworks = new string[] { /*"PocketPC", "SmartPhone", "WindowsCE"*/ };

    internal bool _remove = false;
    //private string _regRoot = "8.0";
    private System.Reflection.Assembly _assm = null;
    private bool _ignoreChecks = true;
    private string _assmLocation;

    private Dictionary<string, string> _regRoots = new Dictionary<string,string>();
    private List<string> _frameworks = new List<string>();

    string SQLiteLocation
    {
      get
      {
        System.Reflection.Assembly assm = SQLite;
        return _assmLocation;
      }
    }

    System.Reflection.Assembly SQLite
    {
      get
      {
        if (_assm == null)
        {
          Environment.CurrentDirectory = Path.GetDirectoryName(typeof(InstallDesigner).Assembly.Location);

          try
          {
            _assmLocation = Path.GetFullPath("..\\System.Data.SQLite.DLL");
            _assm = System.Reflection.Assembly.LoadFrom(_assmLocation);
          }
          catch
          {
          }
        }

        OpenFileDialog dlg = new OpenFileDialog();
        while (_assm == null)
        {
          dlg.Multiselect = false;
          dlg.InitialDirectory = Environment.CurrentDirectory;
          dlg.FileName = "System.Data.SQLite.DLL";
          dlg.Filter = "System.Data.SQLite.DLL|System.Data.SQLite.DLL";
          if (dlg.ShowDialog() == DialogResult.OK)
          {
            try
            {
              _assmLocation = dlg.FileName;
              _assm = System.Reflection.Assembly.LoadFrom(dlg.FileName);
            }
            catch
            {
            }
          }
          else
            throw new ArgumentException("Unable to find or load System.Data.SQLite.DLL");
        }
        return _assm;
      }

      set
      {
        _assm = value;
      }
    }

    public InstallDesigner()
    {
      string[] args = Environment.GetCommandLineArgs();
      RegistryKey key;
      string frameworkpath;

      //_regRoots.Add("8.0", "2005");
      //_regRoots.Add("9.0", "2008");
      _regRoots.Add("10.0", "2010");

      using (key = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\.NETFramework"))
      {
        frameworkpath = key.GetValue("InstallRoot") as string;
      }

      string[] frameworkfolders = Directory.GetDirectories(frameworkpath);
      foreach (string framework in frameworkfolders)
      {
        // Don't do this on frameworks before 4.0
        string version = Path.GetFileNameWithoutExtension(framework);
        if (String.Compare(version, "v4.0", StringComparison.OrdinalIgnoreCase) < 0)
          continue;

        if (File.Exists(Path.Combine(framework, "CONFIG\\machine.config")))
          _frameworks.Add(Path.GetFileName(framework));
      }

      for (int n = 0; n < args.Length; n++)
      {
        if (String.Compare(args[n], "/regroot", true) == 0 ||
          String.Compare(args[n], "-regroot", true) == 0)
        {
          _regRoots.Add(args[n + 1], args[n + 1]);
          break;
        }
        else if (String.Compare(args[n], "/remove", true) == 0 ||
          String.Compare(args[n], "-remove", true) == 0)
        {
          _remove = true;
        }
      }

      InitializeComponent();

      foreach (KeyValuePair<string, string> pair in _regRoots)
      {
        using (key = Registry.LocalMachine.OpenSubKey("Software\\Microsoft"))
        {
          AddItem(key, pair.Key, "VisualStudio", String.Format("Visual Studio {0} (full editions)", pair.Value), standardDataProviderGuid, null);
          AddItem(key, pair.Key, "VWDExpress", String.Format("Visual Web Developer Express {0} Edition", pair.Value), standardDataProviderGuid, null);

          warningPanel.Visible = (AddItem(key, pair.Key, "VCSExpress", String.Format("Visual C# Express {0} Edition *", pair.Value), oledbDataProviderGuid, oledbAltDataProviderGuid)
           | AddItem(key, pair.Key, "VCExpress", String.Format("Visual C++ Express {0} Edition *", pair.Value), oledbDataProviderGuid, oledbAltDataProviderGuid)
           | AddItem(key, pair.Key, "VBExpress", String.Format("Visual Basic Express {0} Edition *", pair.Value), oledbDataProviderGuid, oledbAltDataProviderGuid)
           | AddItem(key, pair.Key, "VJSExpress", String.Format("Visual J# Express {0} Edition *", pair.Value), oledbDataProviderGuid, oledbAltDataProviderGuid));
        }
        GlobalAddRemove(pair.Key);
      }

      _ignoreChecks = false;
    }

    private bool AddItem(RegistryKey parent, string version, string subkeyname, string itemName, Guid lookFor, object isChecked)
    {
      RegistryKey subkey;

      try
      {
        using (subkey = parent.OpenSubKey(String.Format("{0}\\{1}", subkeyname, version)))
        {
          ListViewItem item = new ListViewItem(itemName);

          item.Tag = new string[] { subkeyname, version };

          // Verify this edition has been installed and its not a fluke that the key exists
          string dir = (string)subkey.GetValue("InstallDir");

          using (RegistryKey subsubkey = subkey.OpenSubKey("Packages"))
          {
            if (subsubkey == null)
              throw new ArgumentException("Edition not installed");
            if (subsubkey.SubKeyCount < 5)
              throw new ArgumentException("Edition not installed");
          }
          
          using (RegistryKey subsubkey = subkey.OpenSubKey("DataProviders"))
          {
            if (subsubkey == null)
              throw new ArgumentException("Edition not installed");
          }

          using (RegistryKey subsubkey = subkey.OpenSubKey(String.Format("DataProviders\\{0}", (isChecked == null) ? lookFor.ToString("B") : ((Guid)isChecked).ToString("B"))))
          {
            if (subsubkey == null)
            {
              DoInstallUninstall(item);
            }
            else
            {
              bool itemChecked = (subsubkey.GetValue(null) != null);
              DoInstallUninstall(item);
              if (_remove == false) item.Checked = itemChecked;
            }
          }

          installList.Items.Add(item);
          if (item.Checked)
          {
            DoInstallUninstall(item);
          }
          return true;
        }
      }
      catch
      {
        return false;
      }
    }

    private void closeButton_Click(object sender, EventArgs e)
    {
      this.Close();
    }

    private void installList_ItemChecked(object sender, ItemCheckedEventArgs e)
    {
      if (_ignoreChecks) return;

      string[] arr = (string[])e.Item.Tag;

      DoInstallUninstall(e.Item);

      GlobalAddRemove(arr[1]);
    }

    private void DoInstallUninstall(ListViewItem Item)
    {
      string[] arr = (string[])Item.Tag;
      if (Item.Checked == false)
      {
        if (Item.Text.IndexOf('*') > -1)
          RestoreJet(arr[0], arr[1]);
        else
          Uninstall(arr[0], arr[1], standardDataProviderGuid, standardDataSourcesGuid);
      }
      else
      {
        if (Item.Text.IndexOf('*') > -1)
          ReplaceJet(arr[0], arr[1]);
        else
          Install(arr[0], arr[1], standardDataProviderGuid, standardDataSourcesGuid);
      }
    }

    private void GlobalAddRemove(string version)
    {
      bool install = false;
//      bool installed;

      //// Check to see if SQLite is installed in the GAC
      //try
      //{
      //  string file = AssemblyCache.QueryAssemblyInfo("System.Data.SQLite");
      //  installed = true;
      //}
      //catch
      //{
      //  installed = false;
      //}

      // Check to see if any checkboxes in the list are checked
      for (int n = 0; n < installList.Items.Count; n++)
      {
        if (installList.Items[n].Checked == true)
        {
          install = true;
          break;
        }
      }

      // If at least 1 item is checked, then install some global settings
      if (install)
      {
        string path = Path.GetDirectoryName(SQLiteLocation);

        foreach (string framework in _frameworks)
        {
          using (RegistryKey key = Registry.LocalMachine.CreateSubKey(String.Format("Software\\Microsoft\\.NETFramework\\{0}\\AssemblyFoldersEx\\SQLite", framework), RegistryKeyPermissionCheck.ReadWriteSubTree))
          {
            key.SetValue(null, path);
          }
        }

        while (String.IsNullOrEmpty(path) == false)
        {
          if (File.Exists(path + "\\CompactFramework\\System.Data.SQLite.DLL") == false)
          {
            path = Path.GetDirectoryName(path);
          }
          else break;
        }

        if (String.IsNullOrEmpty(path) == false)
        {
          path += "\\CompactFramework\\";

          for (int n = 0; n < compactFrameworks.Length; n++)
          {
            using (RegistryKey key = Registry.LocalMachine.OpenSubKey(String.Format("Software\\Microsoft\\.NETCompactFramework\\v2.0.0.0\\{0}\\AssemblyFoldersEx", compactFrameworks[n]), true))
            {

              if (key != null)
              {
                using (RegistryKey subkey = key.CreateSubKey("SQLite", RegistryKeyPermissionCheck.ReadWriteSubTree))
                {
                  subkey.SetValue(null, path);
                }
              }
            }
          }

          for (int n = 0; n < compactFrameworks.Length; n++)
          {
            using (RegistryKey key = Registry.LocalMachine.OpenSubKey(String.Format("Software\\Microsoft\\.NETCompactFramework\\v3.5.0.0\\{0}\\AssemblyFoldersEx", compactFrameworks[n]), true))
            {

              if (key != null)
              {
                using (RegistryKey subkey = key.CreateSubKey("SQLite", RegistryKeyPermissionCheck.ReadWriteSubTree))
                {
                  subkey.SetValue(null, path);
                }
              }
            }
          }
        }

        for (int n = 0; n < 2; n++)
        {
          foreach (string framework in _frameworks)
          {
            // Add factory support to the machine.config file.
            try
            {
              string xmlFileName = Environment.ExpandEnvironmentVariables(String.Format("%WinDir%\\Microsoft.NET\\{0}\\{1}\\CONFIG\\machine.config", (n == 0) ? "Framework" : "Framework64", framework));
              XmlDocument xmlDoc = new XmlDocument();
              xmlDoc.PreserveWhitespace = true;
              xmlDoc.Load(xmlFileName);


              XmlNode xmlNode = xmlDoc.SelectSingleNode("configuration/system.data/DbProviderFactories/add[@invariant=\"System.Data.SQLite\"]");
              if (xmlNode == null)
              {
                XmlNode xmlConfig = xmlDoc.SelectSingleNode("configuration");
                if (xmlConfig != null)
                {
                  XmlNode xmlData = xmlConfig.SelectSingleNode("system.data");
                  if (xmlData == null)
                  {
                    xmlData = xmlDoc.CreateNode(XmlNodeType.Element, "system.data", "");
                    xmlConfig.AppendChild(xmlData);
                  }
                  XmlNode xmlParent = xmlData.SelectSingleNode("DbProviderFactories");
                  if (xmlParent == null)
                  {
                    xmlParent = xmlDoc.CreateNode(XmlNodeType.Element, "DbProviderFactories", "");
                    xmlData.AppendChild(xmlParent);
                  }

                  //xmlNode = xmlDoc.CreateNode(XmlNodeType.Element, "remove", "");
                  //xmlNode.Attributes.SetNamedItem(xmlDoc.CreateAttribute("invariant"));
                  //xmlParent.AppendChild(xmlNode);
                  //xmlNode.Attributes.GetNamedItem("invariant").Value = "System.Data.SQLite";

                  xmlNode = xmlDoc.CreateNode(XmlNodeType.Element, "add", "");
                  xmlNode.Attributes.SetNamedItem(xmlDoc.CreateAttribute("name"));
                  xmlNode.Attributes.SetNamedItem(xmlDoc.CreateAttribute("invariant"));
                  xmlNode.Attributes.SetNamedItem(xmlDoc.CreateAttribute("description"));
                  xmlNode.Attributes.SetNamedItem(xmlDoc.CreateAttribute("type"));
                  xmlParent.AppendChild(xmlNode);
                }
              }
              xmlNode.Attributes.GetNamedItem("name").Value = "SQLite Data Provider";
              xmlNode.Attributes.GetNamedItem("invariant").Value = "System.Data.SQLite";
              xmlNode.Attributes.GetNamedItem("description").Value = ".Net Framework Data Provider for SQLite";
              xmlNode.Attributes.GetNamedItem("type").Value = "System.Data.SQLite.SQLiteFactory, " + SQLite.GetName().FullName;

              xmlDoc.Save(xmlFileName);
            }
            catch
            {
            }
          }
        }
      }
      else // No checkboxes are checked, remove some global settings
      {
        try
        {
          foreach (string framework in _frameworks)
          {
            Registry.LocalMachine.DeleteSubKey(String.Format("Software\\Microsoft\\.NETFramework\\{0}\\AssemblyFoldersEx\\SQLite", framework));
          }

          string[] versions = { /*"v2.0.0.0", "v3.5.0.0"*/ };
          for (int x = 0; x < versions.Length; x++)
          {
            for (int n = 0; n < compactFrameworks.Length; n++)
            {
              using (RegistryKey key = Registry.LocalMachine.OpenSubKey(String.Format("Software\\Microsoft\\.NETCompactFramework\\{1}\\{0}\\DataProviders", compactFrameworks[n], versions[x]), true))
              {
                try
                {
                  if (key != null) key.DeleteSubKey(standardDataProviderGuid.ToString("B"));
                }
                catch
                {
                }
              }
            }
          }

          for (int n = 0; n < compactFrameworks.Length; n++)
          {
            using (RegistryKey key = Registry.LocalMachine.OpenSubKey(String.Format("Software\\Microsoft\\.NETCompactFramework\\v2.0.0.0\\{0}\\AssemblyFoldersEx", compactFrameworks[n]), true))
            {
              try
              {
                if (key != null) key.DeleteSubKey("SQLite");
              }
              catch
              {
              }
            }
          }

          for (int n = 0; n < 2; n++)
          {
            try
            {
              foreach (string framework in _frameworks)
              {
                // Remove any entries in the machine.config if they're still there
                string xmlFileName = Environment.ExpandEnvironmentVariables(String.Format("%WinDir%\\Microsoft.NET\\{0}\\{1}\\CONFIG\\machine.config", (n == 0) ? "Framework" : "Framework64", framework));
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.PreserveWhitespace = true;
                xmlDoc.Load(xmlFileName);

                XmlNode xmlNode = xmlDoc.SelectSingleNode("configuration/system.data/DbProviderFactories/add[@invariant=\"System.Data.SQLite\"]");

                if (xmlNode != null)
                  xmlNode.ParentNode.RemoveChild(xmlNode);

                xmlNode = xmlDoc.SelectSingleNode("configuration/system.data/DbProviderFactories/remove[@invariant=\"System.Data.SQLite\"]");
                if (xmlNode != null)
                  xmlNode.ParentNode.RemoveChild(xmlNode);

                xmlDoc.Save(xmlFileName);
              }
            }
            catch
            {
            }
          }
        }
        catch
        {
        }
      }

      try
      {
        if (!install) // Remove SQLite from the GAC if its there
        {
          AssemblyCacheUninstallDisposition disp;

          string s;
          AssemblyCacheEnum entries = new AssemblyCacheEnum("System.Data.SQLite");
          while (true)
          {
            s = entries.GetNextAssembly();
            if (String.IsNullOrEmpty(s)) break;

            AssemblyCache.UninstallAssembly(s, null, out disp);
          }

          entries = new AssemblyCacheEnum("SQLite.Designer");
          while (true)
          {
            s = entries.GetNextAssembly();
            if (String.IsNullOrEmpty(s)) break;

            AssemblyCache.UninstallAssembly(s, null, out disp);
          }

          entries = new AssemblyCacheEnum("System.Data.SQLite.Linq");
          while (true)
          {
            s = entries.GetNextAssembly();
            if (String.IsNullOrEmpty(s)) break;

            AssemblyCache.UninstallAssembly(s, null, out disp);
          }
          
          SQLite = null;
        }
        else // Install SQLite into the GAC
        {
          byte[] cfdt = Properties.Resources.System_Data_SQLite;
          string tempPath = Path.GetTempPath();
          tempPath = Path.Combine(tempPath, "System.Data.SQLite.DLL");
          using (FileStream fs = File.Open(tempPath, FileMode.Create, FileAccess.Write, FileShare.None))
          {
            fs.Write(cfdt, 0, cfdt.Length);
          }

          try
          {
            AssemblyCache.InstallAssembly(tempPath, null, AssemblyCommitFlags.Default);
            AssemblyCache.InstallAssembly(Path.Combine(Path.GetDirectoryName(SQLiteLocation), "x64\\System.Data.SQLite.DLL"), null, AssemblyCommitFlags.Default);
            AssemblyCache.InstallAssembly(Path.Combine(Path.GetDirectoryName(SQLiteLocation), "itanium\\System.Data.SQLite.DLL"), null, AssemblyCommitFlags.Default);
          }
          catch
          {
          }
          finally
          {
            File.Delete(tempPath);
            if (File.Exists(Path.GetFullPath("..\\System.Data.SQLite.Linq.DLL")) == true)
              AssemblyCache.InstallAssembly(Path.GetFullPath("..\\System.Data.SQLite.Linq.DLL"), null, AssemblyCommitFlags.Default);

            AssemblyCache.InstallAssembly(Path.GetFullPath("SQLite.Designer.DLL"), null, AssemblyCommitFlags.Default);
            AssemblyCache.InstallAssembly(SQLiteLocation, null, AssemblyCommitFlags.Default);
          }
        }
      }
      catch
      {
        throw;
      }

      FixXmlLibPaths(install, version);
    }

    private void ReplaceJet(string keyname, string version)
    {
      using (RegistryKey key = Registry.LocalMachine.OpenSubKey(String.Format("Software\\Microsoft\\{0}\\{1}\\DataProviders", keyname, version), true))
      {
        using (RegistryKey source = key.OpenSubKey(oledbDataProviderGuid.ToString("B")))
        {
          using (RegistryKey dest = key.CreateSubKey(oledbAltDataProviderGuid.ToString("B")))
          {
            if (source == null) return;
            CopyKey(source, dest);
          }
        }
        key.DeleteSubKeyTree(oledbDataProviderGuid.ToString("B"));
      }

      using (RegistryKey key = Registry.LocalMachine.OpenSubKey(String.Format("Software\\Microsoft\\{0}\\{1}\\DataSources", keyname, version), true))
      {
        using (RegistryKey source = key.OpenSubKey(jetDataSourcesGuid.ToString("B")))
        {
          using (RegistryKey dest = key.CreateSubKey(jetAltDataSourcesGuid.ToString("B")))
          {
            if (source == null) return;
            CopyKey(source, dest);
          }
        }
        key.DeleteSubKeyTree(jetDataSourcesGuid.ToString("B"));
      }

      Install(keyname, version, oledbDataProviderGuid, jetDataSourcesGuid);
    }

    private void RestoreJet(string keyname, string version)
    {
      using (RegistryKey key = Registry.LocalMachine.OpenSubKey(String.Format("Software\\Microsoft\\{0}\\{1}\\DataProviders", keyname, version), true))
      {
        using (RegistryKey source = key.OpenSubKey(oledbAltDataProviderGuid.ToString("B")))
        {
          if (source == null) return;
        }
      }

      Uninstall(keyname, version, oledbDataProviderGuid, jetDataSourcesGuid);

      using (RegistryKey key = Registry.LocalMachine.OpenSubKey(String.Format("Software\\Microsoft\\{0}\\{1}\\DataProviders", keyname, version), true))
      {
        using (RegistryKey source = key.OpenSubKey(oledbAltDataProviderGuid.ToString("B")))
        {
          if (source != null)
          {
            using (RegistryKey dest = key.CreateSubKey(oledbDataProviderGuid.ToString("B")))
            {
              CopyKey(source, dest);
            }
            key.DeleteSubKeyTree(oledbAltDataProviderGuid.ToString("B"));
          }
        }
      }

      using (RegistryKey key = Registry.LocalMachine.OpenSubKey(String.Format("Software\\Microsoft\\{0}\\{1}\\DataSources", keyname, version), true))
      {
        using (RegistryKey source = key.OpenSubKey(jetAltDataSourcesGuid.ToString("B")))
        {
          if (source != null)
          {
            using (RegistryKey dest = key.CreateSubKey(jetDataSourcesGuid.ToString("B")))
            {
              CopyKey(source, dest);
            }
            key.DeleteSubKeyTree(jetAltDataSourcesGuid.ToString("B"));
          }
        }
      }
    }

    private void Install(string keyname, string version, Guid provider, Guid source)
    {
      bool usePackage = (keyname == "VisualStudio");

      using (RegistryKey key = Registry.LocalMachine.OpenSubKey(String.Format("Software\\Microsoft\\{0}\\{1}\\DataProviders", keyname, version), true))
      {
        using (RegistryKey subkey = key.CreateSubKey(provider.ToString("B"), RegistryKeyPermissionCheck.ReadWriteSubTree))
        {
          subkey.SetValue(null, ".NET Framework Data Provider for SQLite");
          subkey.SetValue("InvariantName", "System.Data.SQLite");
          subkey.SetValue("Technology", "{77AB9A9D-78B9-4ba7-91AC-873F5338F1D2}");
          subkey.SetValue("CodeBase", Path.GetFullPath("SQLite.Designer.DLL"));
          

          if (usePackage)
           subkey.SetValue("FactoryService", "{DCBE6C8D-0E57-4099-A183-98FF74C64D9D}");

          using (RegistryKey subsubkey = subkey.CreateSubKey("SupportedObjects", RegistryKeyPermissionCheck.ReadWriteSubTree))
          {
            using (RegistryKey subsubsubkey = subsubkey.CreateSubKey("DataConnectionUIControl", RegistryKeyPermissionCheck.ReadWriteSubTree))
            {
              if (!usePackage)
                subsubsubkey.SetValue(null, "SQLite.Designer.SQLiteConnectionUIControl");
            }
            using (RegistryKey subsubsubkey = subsubkey.CreateSubKey("DataConnectionProperties", RegistryKeyPermissionCheck.ReadWriteSubTree))
            {
              if (!usePackage)
                subsubsubkey.SetValue(null, "SQLite.Designer.SQLiteConnectionProperties");
            }

            subsubkey.CreateSubKey("DataObjectSupport").Close();
            subsubkey.CreateSubKey("DataViewSupport").Close();
            using (RegistryKey subsubsubkey = subsubkey.CreateSubKey("DataConnectionSupport", RegistryKeyPermissionCheck.ReadWriteSubTree))
            {
              if (!usePackage)
                subsubsubkey.SetValue(null, "SQLite.Designer.SQLiteDataConnectionSupport");
            }
          }
        }
      }

      using (RegistryKey key = Registry.LocalMachine.OpenSubKey(String.Format("Software\\Microsoft\\{0}\\{1}\\DataSources", keyname, version), true))
      {
        using (RegistryKey subkey = key.CreateSubKey(source.ToString("B"), RegistryKeyPermissionCheck.ReadWriteSubTree))
        {
          subkey.SetValue(null, "SQLite Database File");
          using (RegistryKey subsubkey = subkey.CreateSubKey("SupportingProviders", RegistryKeyPermissionCheck.ReadWriteSubTree))
          {
            subsubkey.CreateSubKey(provider.ToString("B")).Close();
          }
        }
      }

      //try
      //{
      //  using (RegistryKey key = Registry.LocalMachine.OpenSubKey("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", true))
      //  {
      //    string libpath = (string)key.GetValue("LIB");
      //    string path = Path.GetDirectoryName(SQLiteLocation);

      //    if (libpath.IndexOf(path, StringComparison.InvariantCultureIgnoreCase) == -1)
      //    {
      //      libpath += (";" + path);
      //      key.SetValue("LIB", libpath);
      //    }
      //  }
      //}
      //catch
      //{
      //}

      string[] versions = { /*"v2.0.0.0", "v3.5.0.0"*/ };

      for (int x = 0; x < versions.Length; x++)
      {
        for (int n = 0; n < compactFrameworks.Length; n++)
        {
          using (RegistryKey key = Registry.LocalMachine.CreateSubKey(String.Format("Software\\Microsoft\\.NETCompactFramework\\{1}\\{0}\\DataProviders", compactFrameworks[n], versions[x])))
          {
            if (key != null)
            {
              using (RegistryKey subkey = key.CreateSubKey(standardDataProviderGuid.ToString("B"), RegistryKeyPermissionCheck.ReadWriteSubTree))
              {
                subkey.SetValue(null, ".NET Framework Data Provider for SQLite");
                subkey.SetValue("InvariantName", "System.Data.SQLite");
                subkey.SetValue("RuntimeAssembly", "System.Data.SQLite.DLL");
              }
            }
          }
        }
      }

      if (usePackage)
      {
        using (RegistryKey key = Registry.LocalMachine.OpenSubKey(String.Format("Software\\Microsoft\\{0}\\{1}\\Packages", keyname, version), true))
        {
          using (RegistryKey subkey = key.CreateSubKey("{DCBE6C8D-0E57-4099-A183-98FF74C64D9C}", RegistryKeyPermissionCheck.ReadWriteSubTree))
          {
            subkey.SetValue(null, "SQLite Designer Package");
            subkey.SetValue("Class", "SQLite.Designer.SQLitePackage");
            subkey.SetValue("CodeBase", Path.GetFullPath("SQLite.Designer.DLL"));
            subkey.SetValue("ID", 400);
            subkey.SetValue("InprocServer32", "mscoree.dll");
            subkey.SetValue("CompanyName", "Black Castle Software, LLC");
            subkey.SetValue("MinEdition", "standard");
            subkey.SetValue("ProductName", "SQLite Data Provider");
            subkey.SetValue("ProductVersion", "1.0");
            using (RegistryKey toolboxKey = subkey.CreateSubKey("Toolbox"))
            {
              toolboxKey.SetValue("Default Items", 3);
            }
          }
        }

        using (RegistryKey key = Registry.LocalMachine.OpenSubKey(String.Format("Software\\Microsoft\\{0}\\{1}\\Menus", keyname, version), true))
        {
          key.SetValue("{DCBE6C8D-0E57-4099-A183-98FF74C64D9C}", ", 1000, 3");
        }

        using (RegistryKey key = Registry.LocalMachine.OpenSubKey(String.Format("Software\\Microsoft\\{0}\\{1}\\Services", keyname, version), true))
        {
          using (RegistryKey subkey = key.CreateSubKey("{DCBE6C8D-0E57-4099-A183-98FF74C64D9D}", RegistryKeyPermissionCheck.ReadWriteSubTree))
          {
            subkey.SetValue(null, "{DCBE6C8D-0E57-4099-A183-98FF74C64D9C}");
            subkey.SetValue("Name", "SQLite Provider Object Factory");
          }
        }
      }
    }

    private XmlDocument GetConfig(string keyname, string version, out string xmlFileName)
    {
      try
      {
        using (RegistryKey key = Registry.LocalMachine.OpenSubKey(String.Format("Software\\Microsoft\\{0}\\{1}", keyname, version), true))
        {
          xmlFileName = (string)key.GetValue("InstallDir");
          if (String.Compare(keyname, "VisualStudio", true) == 0)
            xmlFileName += "devenv.exe.config";
          else
            xmlFileName += keyname + ".exe.config";
        }

        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.PreserveWhitespace = true;
        xmlDoc.Load(xmlFileName);

        return xmlDoc;
      }
      catch
      {
        xmlFileName = null;
      }
      return null;
    }

    private void Uninstall(string keyname, string version, Guid provider, Guid source)
    {
      try
      {
        using (RegistryKey key = Registry.LocalMachine.OpenSubKey(String.Format("Software\\Microsoft\\{0}\\{1}\\DataProviders", keyname, version), true))
        {
          if (key != null) key.DeleteSubKeyTree(provider.ToString("B"));
        }
        using (RegistryKey key = Registry.LocalMachine.OpenSubKey(String.Format("Software\\Microsoft\\{0}\\{1}\\DataSources", keyname, version), true))
        {
          if (key != null) key.DeleteSubKeyTree(source.ToString("B"));
        }

        using (RegistryKey key = Registry.LocalMachine.OpenSubKey(String.Format("Software\\Microsoft\\{0}\\{1}\\Packages", keyname, version), true))
        {
          if (key != null) key.DeleteSubKeyTree("{DCBE6C8D-0E57-4099-A183-98FF74C64D9C}");
        }

        using (RegistryKey key = Registry.LocalMachine.OpenSubKey(String.Format("Software\\Microsoft\\{0}\\{1}\\Services", keyname, version), true))
        {
          if (key != null) key.DeleteSubKeyTree("{DCBE6C8D-0E57-4099-A183-98FF74C64D9D}");
        }

        using (RegistryKey key = Registry.LocalMachine.OpenSubKey(String.Format("Software\\Microsoft\\{0}\\{1}\\Menus", keyname, version), true))
        {
          key.DeleteValue("{DCBE6C8D-0E57-4099-A183-98FF74C64D9C}");
        }

        //using (RegistryKey key = Registry.LocalMachine.OpenSubKey("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", true))
        //{
        //  string libpath = (string)key.GetValue("LIB");
        //  string path = ";" + Path.GetDirectoryName(SQLiteLocation);

        //  libpath = libpath.Replace(path, "");
        //  key.SetValue("LIB", libpath);
        //}
      }
      catch
      {
      }

      // Remove factory support from the development environment config file
      string xmlFileName;
      XmlDocument xmlDoc = GetConfig(keyname, version, out xmlFileName);

      if (xmlDoc == null) return;

      XmlNode xmlNode = xmlDoc.SelectSingleNode("configuration/system.data/DbProviderFactories/add[@invariant=\"System.Data.SQLite\"]");
      if (xmlNode != null)
        xmlNode.ParentNode.RemoveChild(xmlNode);

      xmlNode = xmlDoc.SelectSingleNode("configuration/system.data/DbProviderFactories/remove[@invariant=\"System.Data.SQLite\"]");
      if (xmlNode != null)
        xmlNode.ParentNode.RemoveChild(xmlNode);

      xmlDoc.Save(xmlFileName);
    }


    private static void CopyKey(RegistryKey keySource, RegistryKey keyDest)
    {
      if (keySource.SubKeyCount > 0)
      {
        string[] subkeys = keySource.GetSubKeyNames();
        for (int n = 0; n < subkeys.Length; n++)
        {
          using (RegistryKey subkeysource = keySource.OpenSubKey(subkeys[n]))
          {
            using (RegistryKey subkeydest = keyDest.CreateSubKey(subkeys[n], RegistryKeyPermissionCheck.ReadWriteSubTree))
            {
              CopyKey(subkeysource, subkeydest);
            }
          }
        }
      }
      string[] values = keySource.GetValueNames();
      for (int n = 0; n < values.Length; n++)
      {
        keyDest.SetValue(values[n], keySource.GetValue(values[n]), keySource.GetValueKind(values[n]));
      }
    }

    private void FixXmlLibPaths(bool install, string version)
    {
      string installDir = null;
      RegistryKey key = null;

      try
      {
        key = Registry.LocalMachine.OpenSubKey(String.Format("Software\\Microsoft\\VisualStudio\\{0}", version));
        if (key != null)
        {
          try
          {
            installDir = (string)key.GetValue("InstallDir");
          }
          catch
          {
          }
          finally
          {
            if (String.IsNullOrEmpty(installDir))
            {
              ((IDisposable)key).Dispose();
              key = null;
            }
          }
        }

        if (key == null)
        {
          key = Registry.LocalMachine.OpenSubKey(String.Format("Software\\Microsoft\\VCExpress\\{0}", version));
          if (key == null) return;
        }

        try
        {
          installDir = (string)key.GetValue("InstallDir");
        }
        catch
        {
        }
      }
      finally
      {
        if (key != null) ((IDisposable)key).Dispose();
      }

      if (String.IsNullOrEmpty(installDir)) return;

      installDir = Path.Combine(Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(installDir))), "VC");

      string currentDir;
      string[] lookIn = new string[] { "vcpackages", "bin\\amd64", "bin\\ia64" };
      string sqlitePath = Path.GetDirectoryName(SQLiteLocation);

      foreach (string subfolder in lookIn)
      {
        try
        {
          currentDir = Path.Combine(installDir, subfolder);
          FixXmlLibPaths(currentDir, "VCProjectEngine.DLL*.config", sqlitePath, install);
          FixXmlLibPaths(currentDir, "AMD64.VCPlatform.config", Path.Combine(sqlitePath, "x64"), install);
          FixXmlLibPaths(currentDir, "Itanium.VCPlatform.config", Path.Combine(sqlitePath, "itanium"), install);
          FixXmlLibPaths(currentDir, "WCE.VCPlatform.config", Path.Combine(sqlitePath, "CompactFramework"), install);
        }
        catch
        {
        }
      }

      FixLocalUserPaths(install);
    }

    private void FixLocalUserPaths(bool install)
    {
      string file = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft\\VisualStudio\\8.0\\VCComponents.dat");
      StringBuilder output = new StringBuilder();
      string line;
      string sqlitePath = Path.GetDirectoryName(SQLiteLocation);
      string currPath = sqlitePath;

      try
      {
        using (StreamReader rd = new StreamReader(file))
        {
          while (rd.EndOfStream == false)
          {
            line = rd.ReadLine();
            line = line.Trim();
            if (String.IsNullOrEmpty(line)) continue;
            if (line[0] == '[')
            {
              if (line.IndexOf("Win32", StringComparison.InvariantCultureIgnoreCase) != -1)
                currPath = sqlitePath;
              else if (line.IndexOf("x64", StringComparison.InvariantCultureIgnoreCase) != -1)
                currPath = Path.Combine(sqlitePath, "x64");
              else if (line.IndexOf("Itanium", StringComparison.InvariantCultureIgnoreCase) != -1)
                currPath = Path.Combine(sqlitePath, "x64");
              else if (line.IndexOf("ARM", StringComparison.InvariantCultureIgnoreCase) != -1)
                currPath = Path.Combine(sqlitePath, "CompactFramework");
            }
            else if (line.StartsWith("Reference Dirs", StringComparison.InvariantCultureIgnoreCase) == true)
            {
              int n = line.IndexOf(";" + currPath, StringComparison.InvariantCultureIgnoreCase);
              if (n > -1) line = line.Remove(n, currPath.Length + 1);

              if (install)
              {
                if (line[line.Length - 1] == '=')
                  line += currPath;
                else
                  line += (";" + currPath);
              }
            }

            output.AppendLine(line);
          }
          rd.Close();
        }

        File.Delete(file);
        using (StreamWriter writer = new StreamWriter(file, false, Encoding.Unicode))
        {          
          writer.Write(output.ToString());
          writer.Close();
        }
      }
      catch
      {
      }
    }

    private void FixXmlLibPaths(string path, string lookFor, string sqlitePath, bool install)
    {
      // Win32
      string[] files = Directory.GetFiles(path, lookFor);
      if (files.Length > 0)
      {
        foreach (string file in files)
        {
          FixXmlLibPath(file, sqlitePath, install);
        }
      }
    }

    private void FixXmlLibPath(string fileName, string sqlitePath, bool install)
    {
      XmlDocument xmlDoc = new XmlDocument();
      xmlDoc.PreserveWhitespace = true;
      xmlDoc.Load(fileName);
      
      XmlNodeList xmlNodes = xmlDoc.SelectNodes("VCPlatformConfigurationFile/Platform/Directories");
      if (xmlNodes == null) return;

      foreach(XmlNode xmlNode in xmlNodes)
      {
        string libpath = xmlNode.Attributes.GetNamedItem("Reference").Value;
        if (String.Compare(libpath, sqlitePath, true) == 0)
          libpath = "";
        else
        {
          int n = libpath.IndexOf(";" + sqlitePath, StringComparison.InvariantCultureIgnoreCase);
          if (n > -1) libpath = libpath.Remove(n, sqlitePath.Length + 1);
        }

        if (install)
        {
          if (String.IsNullOrEmpty(libpath)) libpath = sqlitePath;
          else libpath += (";" + sqlitePath);
        }
        xmlNode.Attributes.GetNamedItem("Reference").Value = libpath;
      }

      xmlDoc.Save(fileName);
    }
  }
}
Added tools/install/InstallDesigner.resx.










































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
<?xml version="1.0" encoding="utf-8"?>
<root>
  <!-- 
    Microsoft ResX Schema 
    
    Version 2.0
    
    The primary goals of this format is to allow a simple XML format 
    that is mostly human readable. The generation and parsing of the 
    various data types are done through the TypeConverter classes 
    associated with the data types.
    
    Example:
    
    ... ado.net/XML headers & schema ...
    <resheader name="resmimetype">text/microsoft-resx</resheader>
    <resheader name="version">2.0</resheader>
    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
        <value>[base64 mime encoded serialized .NET Framework object]</value>
    </data>
    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
        <comment>This is a comment</comment>
    </data>
                
    There are any number of "resheader" rows that contain simple 
    name/value pairs.
    
    Each data row contains a name, and value. The row also contains a 
    type or mimetype. Type corresponds to a .NET class that support 
    text/value conversion through the TypeConverter architecture. 
    Classes that don't support this are serialized and stored with the 
    mimetype set.
    
    The mimetype is used for serialized objects, and tells the 
    ResXResourceReader how to depersist the object. This is currently not 
    extensible. For a given mimetype the value must be set accordingly:
    
    Note - application/x-microsoft.net.object.binary.base64 is the format 
    that the ResXResourceWriter will generate, however the reader can 
    read any of the formats listed below.
    
    mimetype: application/x-microsoft.net.object.binary.base64
    value   : The object must be serialized with 
            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
            : and then encoded with base64 encoding.
    
    mimetype: application/x-microsoft.net.object.soap.base64
    value   : The object must be serialized with 
            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
            : and then encoded with base64 encoding.

    mimetype: application/x-microsoft.net.object.bytearray.base64
    value   : The object must be serialized into a byte array 
            : using a System.ComponentModel.TypeConverter
            : and then encoded with base64 encoding.
    -->
  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
    <xsd:element name="root" msdata:IsDataSet="true">
      <xsd:complexType>
        <xsd:choice maxOccurs="unbounded">
          <xsd:element name="metadata">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" />
              </xsd:sequence>
              <xsd:attribute name="name" use="required" type="xsd:string" />
              <xsd:attribute name="type" type="xsd:string" />
              <xsd:attribute name="mimetype" type="xsd:string" />
              <xsd:attribute ref="xml:space" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="assembly">
            <xsd:complexType>
              <xsd:attribute name="alias" type="xsd:string" />
              <xsd:attribute name="name" type="xsd:string" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="data">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
              <xsd:attribute ref="xml:space" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="resheader">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" use="required" />
            </xsd:complexType>
          </xsd:element>
        </xsd:choice>
      </xsd:complexType>
    </xsd:element>
  </xsd:schema>
  <resheader name="resmimetype">
    <value>text/microsoft-resx</value>
  </resheader>
  <resheader name="version">
    <value>2.0</value>
  </resheader>
  <resheader name="reader">
    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <resheader name="writer">
    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <metadata name="columnHeader1.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
    <value>False</value>
  </metadata>
  <metadata name="label1.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
    <value>False</value>
  </metadata>
  <metadata name="label3.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
    <value>False</value>
  </metadata>
  <metadata name="label2.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
    <value>False</value>
  </metadata>
  <data name="label2.Text" xml:space="preserve">
    <value>Due to limitations in some Express Editions, checking affected products above will temporarily replace the Microsoft Jet designer with the SQLite designer.  The Microsoft Jet designer can be restored by un-checking the box(es) above.</value>
  </data>
  <assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
  <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
    <value>
        AAABAAYAICAQAAAAAADoAgAAZgAAABAQEAAAAAAAKAEAAE4DAAAgIAAAAQAIAKgIAAB2BAAAEBAAAAEA
        CABoBQAAHg0AACAgAAABACAAqBAAAIYSAAAQEAAAAQAgAGgEAAAuIwAAKAAAACAAAABAAAAAAQAEAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAACAgACAAAAAgACAAICAAACAgIAAwMDAAAAA
        /wAA/wAAAP//AP8AAAD/AP8A//8AAP///wAREREREREREXd3d3d3ARERERERERERERF4uLeLiwARERER
        ERERERERe4uHuLgDAREREREREREREXi4t4uLAzARERERERAAAA97i4e4uAMwAREREREXd3d/eLi3i4sD
        MDARERERF/iIj3uLh7i4AzAwERERERf4iI94uLeLiwMwMBEREREX+IiPd3d3d3cDMDARAAERF/iIiPe/
        v3+/sDAwEHdwERf4iIiPe/v3+/sAMHeIdwAH+IiIiPeIiHiIgDB/+ICIh/iIiIiPe/v3+/sAf/+HB3f4
        iIiIiPd3d3d3cBf/gBEX+IiIiIiP/////xERd3ERF/iIiIiIiIiIiHARERERERf4iIiIiIiIiIhwERER
        EREX+IiIiIiIiIiIcBERERERF/iIiIiIiIiIiHARERERERf4iIiIiIiIiIhwEREREREX////////////
        cBERERERF3d3d3d3d3d3d3AREREREREREXgBERF4ARERERERERERERF/ARERfwEREREREREREREReAER
        EXgBEREREREREREREQcBEREHARERERERERERERBwcBEQcHARERERERERERF4iHcBeIh3ARERERERERER
        f/iHAX/4hwEREREREREREX//hwF//4cBEREREREREREX/4ARF/+AEREREREREREREYiBERGIgREREf//
        AB///wAP//8AB///AAP/gAAB/4AAAP+AAAD/gAAA/4AAAMeAAACDgAAAAAAAAAAAAAAAAAAAg4AAA8eA
        AAP/gAAD/4AAA/+AAAP/gAAD/4AAA/+AAAP//Hx///x8f//8fH///Hx///g4P//wEB//8BAf//AQH//4
        OD///Hx/KAAAABAAAAAgAAAAAQAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAACA
        gACAAAAAgACAAICAAACAgIAAwMDAAAAA/wAA/wAAAP//AP8AAAD/AP8A//8AAP///wAREREXd3dwERER
        ERe4e4ABERERF4t4sDAREQAHuHuAMBERf3eLeLAwERF/h3d3cDCAgX+Ie/e/AA8Af4iHd3dwgIF/iIiI
        dxEREX////9wERERd3d3d3AREREREQEREREREREYCBERERERERDwERERERERGAgREREREREREREREf4D
        ERH+AYiP/gB3d/AAMDDwAAER8ACIiBAAv38AADAwEANwEfADiIjwA/v3/38AMP4/dwD+P4iI/j+IiP//
        gDAoAAAAIAAAAEAAAAABAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAgAAAAICAAIAA
        AACAAIAAgIAAAICAgADA3MAA8MqmAKo/KgD/PyoAAF8qAFVfKgCqXyoA/18qAAB/KgBVfyoAqn8qAP9/
        KgAAnyoAVZ8qAKqfKgD/nyoAAL8qAFW/KgCqvyoA/78qAADfKgBV3yoAqt8qAP/fKgAA/yoAVf8qAKr/
        KgD//yoAAABVAFUAVQCqAFUA/wBVAAAfVQBVH1UAqh9VAP8fVQAAP1UAVT9VAKo/VQD/P1UAAF9VAFVf
        VQCqX1UA/19VAAB/VQBVf1UAqn9VAP9/VQAAn1UAVZ9VAKqfVQD/n1UAAL9VAFW/VQCqv1UA/79VAADf
        VQBV31UAqt9VAP/fVQAA/1UAVf9VAKr/VQD//1UAAAB/AFUAfwCqAH8A/wB/AAAffwBVH38Aqh9/AP8f
        fwAAP38AVT9/AKo/fwD/P38AAF9/AFVffwCqX38A/19/AAB/fwBVf38Aqn9/AP9/fwAAn38AVZ9/AKqf
        fwD/n38AAL9/AFW/fwCqv38A/79/AADffwBV338Aqt9/AP/ffwAA/38AVf9/AKr/fwD//38AAACqAFUA
        qgCqAKoA/wCqAAAfqgBVH6oAqh+qAP8fqgAAP6oAVT+qAKo/qgD/P6oAAF+qAFVfqgCqX6oA/1+qAAB/
        qgBVf6oAqn+qAP9/qgAAn6oAVZ+qAKqfqgD/n6oAAL+qAFW/qgCqv6oA/7+qAADfqgBV36oAqt+qAP/f
        qgAA/6oAVf+qAKr/qgD//6oAAADUAFUA1ACqANQA/wDUAAAf1ABVH9QAqh/UAP8f1AAAP9QAVT/UAKo/
        1AD/P9QAAF/UAFVf1ACqX9QA/1/UAAB/1ABVf9QAqn/UAP9/1AAAn9QAVZ/UAKqf1AD/n9QAAL/UAFW/
        1ACqv9QA/7/UAADf1ABV39QAqt/UAP/f1AAA/9QAVf/UAKr/1AD//9QAVQD/AKoA/wAAH/8AVR//AKof
        /wD/H/8AAD//AFU//wCqP/8A/z//AABf/wBVX/8Aql//AP9f/wAAf/8AVX//AKp//wD/f/8AAJ//AFWf
        /wCqn/8A/5//AAC//wBVv/8Aqr//AP+//wAA3/8AVd//AKrf/wD/3/8AVf//AKr//wD/zMwA/8z/AP//
        MwD//2YA//+ZAP//zAAAfwAAVX8AAKp/AAD/fwAAAJ8AAFWfAACqnwAA/58AAAC/AABVvwAAqr8AAP+/
        AAAA3wAAVd8AAKrfAAD/3wAAVf8AAKr/AAAAACoAVQAqAKoAKgD/ACoAAB8qAFUfKgCqHyoA/x8qAAA/
        KgBVPyoA8Pv/AKSgoACAgIAAAAD/AAD/AAAA//8A/wAAAAAAAAD//wAA////AP39/f39/f39/f39/f39
        /f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39
        /f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/YF9fVlVWVVVVf39/f39/f39/f39
        /f39/f39/f39/f39pcuoylSkpMakVP39/f39/f39/f39/f39/f39/f39/f2pqcvLVMrKpMZ8LP39/f39
        /f39/f39/f39/f39/f39/anP0KkDy6jLpHxUeP39/f39/f39/f39/f39/f39/f39qc/Pz1nLy6ikfFR8
        eP39/f39/f39/f39/f39/f39/f2p0K7QWc+py8Z8VHx8/f39/f39/f39/f0yMTIxMjEyManP0M99z8+t
        z3xUfHz9/f39/f39/f39XggJCYIJgoKDqfb29gf29tDTfFR8fP39/f39/f39/YKzrwgICAirCAiqy9DT
        0IHPy8vLVHx8/f39/f39/f39htH2r6+vrwivCNQIy/eFMS0wWXxUfHz9/VoHNjL9/f2Gs/b29q/2r6+v
        CNQIpVXQLNBUqcvKfP2ChtSCWjX9/YL/9q/29q/2rwjRrwgHqVWpVctVqcul/V7/rwiCMjYyhv//9vav
        9q/2r68Ir4JZhquCMVr3Df39gvb2rwhagl6C//////bR9q/2r/avr68ICAjUhoMx/f2G1P//CV79/Qn/
        //////az9vavr9EIr6+vCKsJhg39/f0Igl6G/f39gv////////b2r/b2r/avCNGvCAiCMv39/f39/f39
        /f2G////////////9q/2r/avrwivCIMx/f39/f39/f39/f2G//////////////b2r/avr68IB/39/f39
        /f39/f39/f2GgoaCgl73Xl5eWl5aWgc2Bzb9/f39/f39/f39/f39/f39/f1eMf39/f39/V4x/f39/f39
        /f39/f39/f39/f39/f39/YIy/f39/f39gjL9/f39/f39/f39/f39/f39/f39/f1aNgcy/f39/Vo2BzL9
        /f39/f39/f39/f39/f39/f39gobUgjYH/f2ChtSCNgf9/f39/f39/f39/f39/f39/f1e/68IgjL9/V7/
        rwiCMv39/f39/f39/f39/f39/f39/ffR/68IB/3999H/rwgH/f39/f39/f39/f39/f39/f39CAj//wle
        /f0ICP//CV79/f39/f39/f39/f39/f39/f39CYL3hv39/f0JgveG/f39/f39/f39/f39/f39/f39/f39
        /f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3/////////////
        /////8Af///AD///wAf//8AD///AAf//wAH/wAAB/4AAAf8AAAH/AAABhwAAAQMAAAEAAAADAAAAAwMA
        AAOHAAAD/wAAA/+AAAf/wAAP//z8///8/P//+Hh///AwP//wMD//8DA///AwP//4eH///////////ygA
        AAAQAAAAIAAAAAEACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAACAAAAAgIAAgAAAAIAA
        gACAgAAAgICAAMDcwADwyqYAqj8qAP8/KgAAXyoAVV8qAKpfKgD/XyoAAH8qAFV/KgCqfyoA/38qAACf
        KgBVnyoAqp8qAP+fKgAAvyoAVb8qAKq/KgD/vyoAAN8qAFXfKgCq3yoA/98qAAD/KgBV/yoAqv8qAP//
        KgAAAFUAVQBVAKoAVQD/AFUAAB9VAFUfVQCqH1UA/x9VAAA/VQBVP1UAqj9VAP8/VQAAX1UAVV9VAKpf
        VQD/X1UAAH9VAFV/VQCqf1UA/39VAACfVQBVn1UAqp9VAP+fVQAAv1UAVb9VAKq/VQD/v1UAAN9VAFXf
        VQCq31UA/99VAAD/VQBV/1UAqv9VAP//VQAAAH8AVQB/AKoAfwD/AH8AAB9/AFUffwCqH38A/x9/AAA/
        fwBVP38Aqj9/AP8/fwAAX38AVV9/AKpffwD/X38AAH9/AFV/fwCqf38A/39/AACffwBVn38Aqp9/AP+f
        fwAAv38AVb9/AKq/fwD/v38AAN9/AFXffwCq338A/99/AAD/fwBV/38Aqv9/AP//fwAAAKoAVQCqAKoA
        qgD/AKoAAB+qAFUfqgCqH6oA/x+qAAA/qgBVP6oAqj+qAP8/qgAAX6oAVV+qAKpfqgD/X6oAAH+qAFV/
        qgCqf6oA/3+qAACfqgBVn6oAqp+qAP+fqgAAv6oAVb+qAKq/qgD/v6oAAN+qAFXfqgCq36oA/9+qAAD/
        qgBV/6oAqv+qAP//qgAAANQAVQDUAKoA1AD/ANQAAB/UAFUf1ACqH9QA/x/UAAA/1ABVP9QAqj/UAP8/
        1AAAX9QAVV/UAKpf1AD/X9QAAH/UAFV/1ACqf9QA/3/UAACf1ABVn9QAqp/UAP+f1AAAv9QAVb/UAKq/
        1AD/v9QAAN/UAFXf1ACq39QA/9/UAAD/1ABV/9QAqv/UAP//1ABVAP8AqgD/AAAf/wBVH/8Aqh//AP8f
        /wAAP/8AVT//AKo//wD/P/8AAF//AFVf/wCqX/8A/1//AAB//wBVf/8Aqn//AP9//wAAn/8AVZ//AKqf
        /wD/n/8AAL//AFW//wCqv/8A/7//AADf/wBV3/8Aqt//AP/f/wBV//8Aqv//AP/MzAD/zP8A//8zAP//
        ZgD//5kA///MAAB/AABVfwAAqn8AAP9/AAAAnwAAVZ8AAKqfAAD/nwAAAL8AAFW/AACqvwAA/78AAADf
        AABV3wAAqt8AAP/fAABV/wAAqv8AAAAAKgBVACoAqgAqAP8AKgAAHyoAVR8qAKofKgD/HyoAAD8qAFU/
        KgDw+/8ApKCgAICAgAAAAP8AAP8AAAD//wD/AAAAAAAAAP//AAD///8A/f39/f39/f39/f39/f39/f39
        /f39/YF9fVlVWVVV/f39/f39/f2ly6jGVKTGpCz9/f39/f39qc/Qz1nLqcZUeP39/f39/anQrdBZz8uk
        VHz9/f39/f2p0NDPfc+uz1R8/f39/f0xqfb29vf209BUfP39/f0yr/epgYUxLCx9VHz99f39WtH2r6lV
        pTGlVKmlXv/19V7/9q/2rzAHVf39/f1e/f1e///29q+v1PX9/f39/f39/fdeXlpaBzH9/f39/f39/f39
        /f31/f39/f39/f39/f39/f399f39/f39/f39/f39/f39Xv/1/f39/f39/f39/f39/f1e/f39/f39/f//
        /f38A/39/AH9/fwA/f38AKnQ/ABZz/gAxnzwAHz9sAD9/QAH/f2wBzIx+A8yMf9/qc//f33P/j/PfP9/
        fP0oAAAAIAAAAEAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAZpKo/2GMov9bhJz/VX2V/0Bec/9LcIr/RmmE/0Fjf/83V3T/FExpMQAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGrtv/R8fw/ye67/8Vsuz/BWSI/wGn6f8Ao+b/AKDi/wCc
        4P8QbJP/FExpMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFm34P9azvL/U83y/0PG8f8eb4v/JLnu/xiz
        7f8Nruv/AJ/i/wd7q/8UTGn/FExpMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWbjg/23W8v9p1fP/WM/y/yl0
        jP83wfD/Kbrv/xu17f8AoeP/BH6x/wdWev8QcJn/FExpMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABZueL/ftzz/33e
        9P9t2PT/NnmM/0zK8v89xPD/Lb3w/wCj5f8Agrb/BFmA/wZ7p/8Ocpv/AAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFm6
        4/+N5PT/kOX1/4Lf9f9Cfo3/Y9Pz/1HN8v9BxfD/AKbn/wCCtv8AXYX/BH2q/wl5pv8AAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiXFfRolxX/+Gblv/hGtZ/4FoVf9+ZVL/e2JP/3lg
        TP92XUr/Wbzn/4rh9P+K4fT/iuH0/02Ilv9+3PP/dNjy/2jT8f9o0/H/AIK2/wBdhf8FgbD/CXmm/wAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIlxX0aumYr/0sC2/9C9s//Ou7H/zLmu/8u2
        q//KtKn/x7Km/8awpP9qxOv/3fT7/930+//d9Pv/h5yj/8/w+//P8Pv/u+n6/7Xo+v8AiMD/AF2F/wWB
        sP8Jeab/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAw6+i//Pv7P/m3tr/4NTO/9/S
        yv/dzsf/2szD/9jJwf/Wxr3/1MK6/7q+vv9qxOv/q/D3/6rw9/+d6/b/W5Sf/3fb9P9h0vP/Scnx/zS/
        8P8AXYX/BYKz/wl5pv8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADEsKP/9/Px//Xw
        7v/y7ev/7+rn/+7m4//r49//6N/b/+bc1v/k2NL/4dTO/8TLzv9qxOv/fK6z/3issv8/YGb/K0tT/yVI
        Uf84hp7/KYCd/xZjff8AiMD/CXmm/wAAAAC+r6UxppGDwI12ZPiFbFr4hmtZwIJoVTEAAAAAAAAAAMWx
        pP/59/X/9/Tz//Xy7//z7uz/8Ovo/+/o5P/t5OH/6uHd/+fd2P/k2tT/4tfQ/8XO0P9fsNP/T25x/5/r
        9v8uS1H/n+v2/zJsfP9Dtdj/NcDw/yG37v8LfKz/AAAAALytosDHurD/18fB/8Otof+dg3P/h21awAAA
        AAAAAAAAxbKk//v6+f/5+Pb/+PXz//bz8P/07+7/8uzq//Dq5v/u5uL/6+Pe/+jf2v/l29b/49jS/3Js
        af9Zven/KVhs/1m96f8pV2v/Wb3p/y5hd/9Zven/RrXm/zGt4/8AAAAAsZ6Q+Pn39v/w6uj/3M7G/8Ku
        of+IcF34hm5b/4RrWf/GsqX//f39//z6+v/7+fj/+fb1//fz8v/18O7/8u7s//Dr6P/u5+T/7OTg/+nh
        3P/m3df/uK+r/3Ntav/Ivbb/3M7H/7Cjnv9uZWH/o5KK/8GqnP9sUj7/AAAAAAAAAAC4ppn4+fj3////
        ///w6+j/1snA/5N7avjHsab/s5qK/8azpf////////3+//37+//7+vn/+fj2//f18//18vD/8+/t//Hs
        6f/v6eX/7ebi/+vj3v/o39r/5tvV/+LY0v/g1M3/3c/J/9vMxf/Nuq//xKyg/29VQf8AAAAAAAAAAM3A
        tsDb0sv/+vj3//n49//KvbT/q5eJwAAAAAAAAAAAx7Om///////////////+//38/f/8+/r/+vn4//j2
        9f/38/L/9fDv//Lt6v/w6uf/7ufj/+vk3//p4Nz/5t3X/+TZ0//h1c//39HL/9C9tP/FsKT/cllF/wAA
        AAAAAAAA3NHKMc/Bt8C7qZz4tqOW+MKzqMDEtasxAAAAAAAAAADHtaf///////////////////////7+
        /f/8/Pv/+/r4//r39v/39fL/9vLv//Pv7f/y7On/7+nl/+zl4f/q4t3/597Z/+Xb1f/i19H/08K6/8iz
        qP91XEn/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMi1qMr////a////////
        /////////////////v/9/Pz//Pv6//r4+P/49vT/9vPx//Xw7v/y7er/8Orm/+3m4//r5N//6eDb/+bc
        1//cz8j/y7er/3lfTP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiXFfMcWx
        pLL////N////6v////T////////////////+/f3//fz7//v6+f/69vX/9/Tz//Xy7//z7uz/8evo/+/o
        5f/s5eH/6uHd/+Ta1f+Gblz/hm5cRgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAiXFfMcWxpLLDr6LTwK2e6L2pnP+7ppj/t6SV/7Wgkf+xnI3/rpmJ/6uVhf+nkoH/pI59/6CK
        ev+chnX/mIJx/5V+bf+Remj/inJg/4ZuXEYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALOaiv+Ea1n/AAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAs5qK/4RrWf8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAx7Gm/4ZuW/8AAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAADHsab/hm5b/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvq+lMaaRg8CNdmT4hWxa+IZr
        WcCCaFUxAAAAAAAAAAC+r6UxppGDwI12ZPiFbFr4hmtZwIJoVTEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8raLAx7qw/9fH
        wf/DraH/nYNz/4dtWsAAAAAAAAAAALytosDHurD/18fB/8Otof+dg3P/h21awAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALGe
        kPj59/b/8Oro/9zOxv/CrqH/iHBd+AAAAAAAAAAAsZ6Q+Pn39v/w6uj/3M7G/8Kuof+IcF34AAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAuKaZ+Pn49///////8Ovo/9bJwP+Te2r4AAAAAAAAAAC4ppn4+fj3///////w6+j/1snA/5N7
        avgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAADNwLbA29LL//r49//5+Pf/yr20/6uXicAAAAAAAAAAAM3AtsDb0sv/+vj3//n4
        9//KvbT/q5eJwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAANzRyjHPwbfAu6mc+LajlvjCs6jAxLWrMQAAAAAAAAAA3NHKMc/B
        t8C7qZz4tqOW+MKzqMDEtasxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//
        ////////////////wA///8AH///AA///wAH//8AB///AAf+AAAH/AAAB/wAAAf8AAAEDAAABAwAAAQAA
        AAMAAAADAwAAAwMAAAP/AAAD/wAAA/+AAAf//Pz///z8///wMD//8DA///AwP//wMD//8DA///AwP///
        ////////KAAAABAAAAAgAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAABmkqj/YYyi/1uEnP9VfZX/QF5z/0twiv9GaYT/N1d0/wAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAARq7b/0fH8P8nuu//FbLs/wVkiP8Bp+n/AKPm/wCc4P8UTGn/AAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAFm54v9+3PP/fd70/23Y9P82eYz/TMry/z3E8P8Ao+X/BFmA/w5y
        m/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABZuuP/jeT0/5Dl9f+C3/X/Qn6N/2PT8/9RzfL/AKbn/wBd
        hf8Jeab/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWbzn/4rh9P+K4fT/iuH0/02Ilv9+3PP/dNjy/2jT
        8f8AXYX/CXmm/wAAAAAAAAAAAAAAAAAAAAAAAAAAdVtG/2rE6//d9Pv/3fT7/930+/+HnKP/z/D7/8/w
        +/+16Pr/AF2F/wl5pv8AAAAAAAAAAAAAAAD///8xhW1a/+3m4/+/p5r/asTr/3yus/94rLL/P2Bm/ytL
        U/8lSFH/OIae/xZjff8Jeab/Y0gzO2NIM/9jSDM7////apeAb//28vH/8u3q/+3m4/9fsNP/T25x/zOr
        1/8uS1H/LqnX/zJsfP9Dtdj/Ma3j/66ai///////Y0gz/2NIM/+plIT//fv8//n39//28/D/8u3q/+3n
        4/8pWGz/pox7/ylXa/8AAAAAAAAAAAAAAABjSDM7rpqL/2NIMzv///95sp2O///////8/Pv/+vj3//by
        8f/y7er/6eDb/9/Sy/9pTjr/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////RgAAAAC2oZP/rpqL/6eR
        gf+fiXn/l4Bv/4dvXf94X0z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAY0gz/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAY0gzP2NIM/9jSDM/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAK6ai///////Y0gz/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAABjSDM/rpqL/2NIMz8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//wAA/AMAAPwB
        AAD8AAAA/AAAAPwAAAD4AAAA4AAAAAAAAAAABwAAAAcAAOgPAAD/fwAA/j8AAP4/AAD+PwAA
</value>
  </data>
</root>
Deleted tools/install/Installer.2008.csproj.
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
<?xml version="1.0" encoding="utf-8"?>
<!--
 *
 * Installer.2008.csproj -
 *
 * 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="3.5">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProductVersion>9.0.30729</ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{A41FE2A5-07AD-4CE7-B836-1544634816F5}</ProjectGuid>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <OutputType>Exe</OutputType>
    <RootNamespace>Installer</RootNamespace>
    <AssemblyName>Installer</AssemblyName>
    <OldToolsVersion>2.0</OldToolsVersion>
    <SQLiteNetDir>$(MSBuildProjectDirectory)\..\..</SQLiteNetDir>
    <NetFx20>true</NetFx20>
    <ConfigurationYear>2008</ConfigurationYear>
  </PropertyGroup>
  <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets" />
  <PropertyGroup Condition="'$(BinaryOutputPath)' != ''">
    <OutputPath>$(BinaryOutputPath)</OutputPath>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="System" />
    <Reference Include="System.EnterpriseServices" />
    <Reference Include="System.Windows.Forms" />
    <Reference Include="System.Xml" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Installer.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
  </ItemGroup>
  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
</Project>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


























































































































Deleted tools/install/Installer.2010.csproj.
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
<?xml version="1.0" encoding="utf-8"?>
<!--
 *
 * Installer.2010.csproj -
 *
 * 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>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProductVersion>10.0.30319</ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{A41FE2A5-07AD-4CE7-B836-1544634816F5}</ProjectGuid>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <OutputType>Exe</OutputType>
    <RootNamespace>Installer</RootNamespace>
    <AssemblyName>Installer</AssemblyName>
    <OldToolsVersion>3.5</OldToolsVersion>
    <TargetFrameworkProfile>Client</TargetFrameworkProfile>
    <SQLiteNetDir>$(MSBuildProjectDirectory)\..\..</SQLiteNetDir>
    <ConfigurationYear>2010</ConfigurationYear>
  </PropertyGroup>
  <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets" />
  <PropertyGroup Condition="'$(BinaryOutputPath)' != ''">
    <OutputPath>$(BinaryOutputPath)</OutputPath>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="System" />
    <Reference Include="System.EnterpriseServices" />
    <Reference Include="System.Windows.Forms" />
    <Reference Include="System.Xml" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Installer.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
  </ItemGroup>
  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
</Project>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


























































































































Deleted tools/install/Installer.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
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
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
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
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
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
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
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
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
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
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
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
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
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
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
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
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
/*
 * Installer.cs --
 *
 * Written by Joe Mistachkin.
 * Released to the public domain, use at your own risk!
 */

using System.Collections.Generic;
using System.Diagnostics;
using System.EnterpriseServices.Internal;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Windows.Forms;
using System.Xml;
using Microsoft.Win32;

namespace System.Data.SQLite
{
    #region Public Delegates
    internal delegate void TraceCallback(
        string message,
        string category
    );

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

    internal delegate bool FrameworkConfigCallback(
        string fileName,
        string invariant,
        string name,
        string description,
        string typeName,
        AssemblyName assemblyName,
        object clientData,
        bool whatIf,
        bool verbose,
        ref bool saved,
        ref string error
    );

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

    internal delegate bool FrameworkRegistryCallback(
        RegistryKey rootKey,
        string frameworkName,
        Version frameworkVersion,
        string platformName,
        object clientData,
        bool whatIf,
        bool verbose,
        ref string error
    );

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

    internal delegate bool VisualStudioRegistryCallback(
        RegistryKey rootKey,
        Version vsVersion,
        Guid packageId,
        Guid serviceId,
        Guid dataSourceId,
        Guid dataProviderId,
        object clientData,
        bool whatIf,
        bool verbose,
        ref string error
    );
    #endregion

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

    #region Public Enumerations
    [Flags()]
    public enum InstallFlags
    {
        None = 0x0,
        GAC = 0x1,
        AssemblyFolders = 0x2,
        DbProviderFactory = 0x4,
        VsPackage = 0x8,
        VsDataSource = 0x10,
        VsDataProvider = 0x20,
        Framework = GAC | AssemblyFolders | DbProviderFactory,
        Vs = VsPackage | VsDataSource | VsDataProvider,
        All = Framework | Vs,
        Default = All
    }
    #endregion

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

    #region Installer Class
    internal static class Installer
    {
        #region Private Helper Classes
        #region AnyPair Class
        private sealed class AnyPair<T1, T2>
        {
            #region Public Constructors
            //
            // WARNING: This constructor produces an immutable "empty" pair
            //          object.
            //
            public AnyPair()
                : base()
            {
                // do nothing.
            }

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

            public AnyPair(T1 x)
                : this()
            {
                this.x = x;
            }

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

            public AnyPair(T1 x, T2 y)
                : this(x)
            {
                this.y = y;
            }
            #endregion

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

            #region Public Properties
            private T1 x;
            public T1 X
            {
                get { return x; }
            }

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

            private T2 y;
            public T2 Y
            {
                get { return y; }
            }
            #endregion
        }
        #endregion

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

        #region TraceOps Class
        private static class TraceOps
        {
            #region Private Constants
            private const string Iso8601DateTimeOutputFormat =
                "yyyy.MM.ddTHH:mm:ss.fffffff";
            #endregion

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

            #region Private Data
            private static object syncRoot = new object();
            private static long nextId;
            #endregion

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

            #region Interactive Support Methods
            public static string GetAssemblyTitle(
                Assembly assembly
                )
            {
                if (assembly != null)
                {
                    try
                    {
                        if (assembly.IsDefined(
                                typeof(AssemblyTitleAttribute), false))
                        {
                            AssemblyTitleAttribute title =
                                (AssemblyTitleAttribute)
                                assembly.GetCustomAttributes(
                                    typeof(AssemblyTitleAttribute), false)[0];

                            return title.Title;
                        }
                    }
                    catch
                    {
                        // do nothing.
                    }
                }

                return null;
            }

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

            public static DialogResult ShowMessage(
                TraceCallback traceCallback,
                Assembly assembly,
                string message,
                string category,
                MessageBoxButtons buttons,
                MessageBoxIcon icon
                )
            {
                DialogResult result = DialogResult.OK;

                Trace(traceCallback, message, category);

                if (SystemInformation.UserInteractive)
                {
                    string title = GetAssemblyTitle(assembly);

                    if (title == null)
                        title = Application.ProductName;

                    result = MessageBox.Show(message, title, buttons, icon);

                    Trace(traceCallback, String.Format(
                        "User choice of \"{0}\".", result), category);

                    return result;
                }

                Trace(traceCallback, String.Format(
                    "Default choice of \"{0}\".", result), category);

                return result;
            }
            #endregion

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

            #region Tracing Support Methods
            public static long NextId()
            {
                return Interlocked.Increment(ref nextId);
            }

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

            public static string TimeStamp(DateTime dateTime)
            {
                return dateTime.ToString(Iso8601DateTimeOutputFormat);
            }

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

            [MethodImpl(MethodImplOptions.NoInlining)]
            private static string GetMethodName(
                StackTrace stackTrace,
                int level
                )
            {
                try
                {
                    //
                    // NOTE: If a valid stack trace was not supplied by the
                    //       caller, create one now based on the current
                    //       execution stack.
                    //
                    if (stackTrace == null)
                    {
                        //
                        // NOTE: Grab the current execution stack.
                        //
                        stackTrace = new StackTrace();

                        //
                        // NOTE: Always skip this call frame when we capture
                        //       the stack trace.
                        //
                        level++;
                    }

                    //
                    // NOTE: Get the specified stack frame (always add one to
                    //       skip this method).
                    //
                    StackFrame stackFrame = stackTrace.GetFrame(level);

                    //
                    // NOTE: Get the method for the stack frame.
                    //
                    MethodBase methodBase = stackFrame.GetMethod();

                    //
                    // NOTE: Get the type for the method.
                    //
                    Type type = methodBase.DeclaringType;

                    //
                    // NOTE: Get the name of the method.
                    //
                    string name = methodBase.Name;

                    //
                    // NOTE: Return the properly formatted result.
                    //
                    return String.Format(
                        "{0}{1}{2}", type.Name, Type.Delimiter, name);
                }
                catch
                {
                    // do nothing.
                }

                return null;
            }

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

            public static void TraceCore(
                string message,
                string category
                )
            {
                lock (syncRoot)
                {
                    System.Diagnostics.Trace.WriteLine(message, category);
                    System.Diagnostics.Trace.Flush();
                }
            }

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

            [MethodImpl(MethodImplOptions.NoInlining)]
            public static string Trace(
                TraceCallback traceCallback,
                Exception exception,
                string category
                )
            {
                if (exception != null)
                    return Trace(traceCallback,
                        new StackTrace(exception, true), 0,
                        exception.ToString(), category);

                return null;
            }

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

            [MethodImpl(MethodImplOptions.NoInlining)]
            public static string Trace(
                TraceCallback traceCallback,
                string message,
                string category
                )
            {
                return Trace(traceCallback, null, 1, message, category);
            }

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

            [MethodImpl(MethodImplOptions.NoInlining)]
            private static string Trace(
                TraceCallback traceCallback,
                StackTrace stackTrace,
                int level,
                string message,
                string category
                )
            {
                //
                // NOTE: Always skip this call frame if the stack trace is
                //       going to be captured by GetMethodName.
                //
                if (stackTrace == null)
                    level++;

                if (traceCallback == null)
                    traceCallback = TraceCore;

                traceCallback(String.Format("{0}: {1}",
                    GetMethodName(stackTrace, level), message), category);

                return message;
            }
            #endregion
        }
        #endregion

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

        #region MockRegistryKey Class
        private sealed class MockRegistryKey : IDisposable
        {
            #region Private Constructors
            private MockRegistryKey()
            {
                whatIf = true;
            }
            #endregion

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

            #region Public Constructors
            public MockRegistryKey(
                RegistryKey key
                )
                : this()
            {
                this.key = key;
            }

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

            public MockRegistryKey(
                RegistryKey key,
                string subKeyName
                )
                : this(key)
            {
                this.subKeyName = subKeyName;
            }

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

            public MockRegistryKey(
                RegistryKey key,
                string subKeyName,
                bool whatIf
                )
                : this(key, subKeyName)
            {
                this.whatIf = whatIf;
            }

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

            public MockRegistryKey(
                RegistryKey key,
                bool whatIf
                )
                : this(key, null, whatIf)
            {
                // do nothing.
            }
            #endregion

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

            #region Public Methods
            public void Close()
            {
                //
                // NOTE: No disposed check here because calling this method
                //       should be just like calling Dispose.
                //
                Dispose(true);
            }

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

            public MockRegistryKey CreateSubKey(
                string subKeyName
                )
            {
                CheckDisposed();

                if (key == null)
                    return null;

                if (whatIf)
                {
                    //
                    // HACK: Attempt to open the specified sub-key.  If this
                    //       fails, we will simply return the wrapped root key
                    //       itself since no writes are allowed in 'what-if'
                    //       mode anyhow.
                    //
                    RegistryKey subKey = key.OpenSubKey(subKeyName);

                    return (subKey != null) ?
                        new MockRegistryKey(subKey) :
                        new MockRegistryKey(key, subKeyName);
                }
                else
                {
                    return new MockRegistryKey(
                        key.CreateSubKey(subKeyName), false);
                }
            }

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

            public void DeleteSubKey(
                string subKeyName
                )
            {
                CheckDisposed();

                if (key == null)
                    return;

                if (!whatIf)
                    key.DeleteSubKey(subKeyName);
            }

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

            public void DeleteSubKeyTree(
                string subKeyName
                )
            {
                CheckDisposed();

                if (key == null)
                    return;

                if (!whatIf)
                    key.DeleteSubKeyTree(subKeyName);
            }

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

            public void DeleteValue(
                string name
                )
            {
                CheckDisposed();

                if (key == null)
                    return;

                if (!whatIf)
                    key.DeleteValue(name);
            }

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

            public string[] GetSubKeyNames()
            {
                CheckDisposed();

                if (key == null)
                    return null;

                return key.GetSubKeyNames();
            }

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

            public object GetValue(
                string name,
                object defaultValue
                )
            {
                CheckDisposed();

                if (key == null)
                    return null;

                return key.GetValue(name, defaultValue);
            }

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

            public MockRegistryKey OpenSubKey(
                string subKeyName
                )
            {
                CheckDisposed();

                return OpenSubKey(subKeyName, false);
            }

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

            public MockRegistryKey OpenSubKey(
                string subKeyName,
                bool writable
                )
            {
                CheckDisposed();

                if (key == null)
                    return null;

                RegistryKey subKey = key.OpenSubKey(
                    subKeyName, whatIf ? false : writable);

                return (subKey != null) ?
                    new MockRegistryKey(subKey, whatIf) : null;
            }

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

            public void SetValue(
                string name,
                object value
                )
            {
                CheckDisposed();

                if (key == null)
                    return;

                if (!whatIf)
                    key.SetValue(name, value);
            }
            #endregion

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

            #region Public Properties
            public string Name
            {
                get
                {
                    CheckDisposed();

                    if (key == null)
                        return null;

                    return !String.IsNullOrEmpty(subKeyName) ?
                        String.Format("{0}\\{1}", key.Name, subKeyName) :
                        key.Name;
                }
            }

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

            private RegistryKey key;
            public RegistryKey Key
            {
                get { CheckDisposed(); return key; }
            }

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

            private string subKeyName;
            public string SubKeyName
            {
                get { CheckDisposed(); return subKeyName; }
            }

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

            private bool whatIf;
            public bool WhatIf
            {
                get { CheckDisposed(); return whatIf; }
            }
            #endregion

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

            #region System.Object Overrides
            public override string ToString()
            {
                CheckDisposed();

                return this.Name;
            }
            #endregion

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

            #region Implicit Conversion Operators
            //
            // BUGBUG: The 'what-if' mode setting here should probably be based
            //         on some static property, not hard-coded to true?
            //
            public static implicit operator MockRegistryKey(
                RegistryKey key
                )
            {
                return new MockRegistryKey(key, null, true);
            }

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

            //
            // BUGBUG: Remove me?  This should be safe because in 'what-if'
            //         mode all keys are opened read-only.
            //
            public static implicit operator RegistryKey(
                MockRegistryKey key
                )
            {
                return (key != null) ? key.Key : null;
            }
            #endregion

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

            #region IDisposable "Pattern" Members
            private bool disposed;
            private void CheckDisposed() /* throw */
            {
                if (!disposed)
                    return;

                throw new ObjectDisposedException(typeof(MockRegistryKey).Name);
            }

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

            private /* protected virtual */ void Dispose(
                bool disposing
                )
            {
                if (!disposed)
                {
                    if (disposing)
                    {
                        ////////////////////////////////////
                        // dispose managed resources here...
                        ////////////////////////////////////

                        if (key != null)
                        {
                            key.Close();
                            key = null;
                        }
                    }

                    //////////////////////////////////////
                    // release unmanaged resources here...
                    //////////////////////////////////////

                    //
                    // NOTE: This object is now disposed.
                    //
                    disposed = true;
                }
            }
            #endregion

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

            #region IDisposable Members
            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }
            #endregion

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

            #region Destructor
            ~MockRegistryKey()
            {
                Dispose(false);
            }
            #endregion
        }
        #endregion

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

        #region RegistryHelper Class
        private static class RegistryHelper
        {
            #region Public Static Properties
            private static int subKeysCreated;
            public static int SubKeysCreated
            {
                get { return subKeysCreated; }
            }

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

            private static int subKeysDeleted;
            public static int SubKeysDeleted
            {
                get { return subKeysDeleted; }
            }

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

            private static int keyValuesSet;
            public static int KeyValuesSet
            {
                get { return keyValuesSet; }
            }

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

            private static int keyValuesDeleted;
            public static int KeyValuesDeleted
            {
                get { return keyValuesDeleted; }
            }
            #endregion

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

            #region Public Static Methods
            public static RegistryKey GetRootKeyByName(
                string keyName
                )
            {
                if (String.IsNullOrEmpty(keyName))
                    return null;

                switch (keyName.ToUpperInvariant())
                {
                    case "HKCR":
                    case "HKEY_CLASSES_ROOT":
                        return Registry.ClassesRoot;
                    case "HKCC":
                    case "HKEY_CURRENT_CONFIG":
                        return Registry.CurrentConfig;
                    case "HKCU":
                    case "HKEY_CURRENT_USER":
                        return Registry.CurrentUser;
                    case "HKDD":
                    case "HKEY_DYN_DATA":
                        return Registry.DynData;
                    case "HKLM":
                    case "HKEY_LOCAL_MACHINE":
                        return Registry.LocalMachine;
                    case "HKPD":
                    case "HKEY_PERFORMANCE_DATA":
                        return Registry.PerformanceData;
                    case "HKU":
                    case "HKEY_USERS":
                        return Registry.Users;
                }

                return null;
            }

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

            public static MockRegistryKey OpenSubKey(
                MockRegistryKey rootKey,
                string subKeyName,
                bool writable,
                bool whatIf,
                bool verbose
                )
            {
                if (rootKey == null)
                    return null;

                if (verbose)
                    TraceOps.Trace(traceCallback, String.Format(
                        "rootKey = {0}, subKeyName = {1}, writable = {2}",
                        ForDisplay(rootKey), ForDisplay(subKeyName), writable),
                        traceCategory);

                //
                // HACK: Always forbid writable access when operating in
                //       'what-if' mode.
                //
                MockRegistryKey key = rootKey.OpenSubKey(
                    subKeyName, whatIf ? false : writable);

                return (key != null) ?
                    new MockRegistryKey(key, whatIf) : null;
            }

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

            public static MockRegistryKey CreateSubKey(
                MockRegistryKey rootKey,
                string subKeyName,
                bool whatIf,
                bool verbose
                )
            {
                if (rootKey == null)
                    return null;

                if (verbose)
                    TraceOps.Trace(traceCallback, String.Format(
                        "rootKey = {0}, subKeyName = {1}", ForDisplay(rootKey),
                        ForDisplay(subKeyName)), traceCategory);

                try
                {
                    //
                    // HACK: Always open a key, rather than creating one when
                    //       operating in 'what-if' mode.
                    //
                    if (whatIf)
                    {
                        //
                        // HACK: Attempt to open the specified sub-key.  If
                        //       this fails, we will simply return the root key
                        //       itself since no writes are allowed in
                        //       'what-if' mode anyhow.
                        //
                        MockRegistryKey key = rootKey.OpenSubKey(subKeyName);

                        return (key != null) ?
                            key : new MockRegistryKey(rootKey, subKeyName);
                    }
                    else
                    {
                        return new MockRegistryKey(
                            rootKey.CreateSubKey(subKeyName), false);
                    }
                }
                finally
                {
                    subKeysCreated++;
                }
            }

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

            public static void DeleteSubKey(
                MockRegistryKey rootKey,
                string subKeyName,
                bool whatIf,
                bool verbose
                )
            {
                if (rootKey == null)
                    return;

                if (verbose)
                    TraceOps.Trace(traceCallback, String.Format(
                        "rootKey = {0}, subKeyName = {1}", ForDisplay(rootKey),
                        ForDisplay(subKeyName)), traceCategory);

                if (!whatIf)
                    rootKey.DeleteSubKey(subKeyName);

                subKeysDeleted++;
            }

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

            public static void DeleteSubKeyTree(
                MockRegistryKey rootKey,
                string subKeyName,
                bool whatIf,
                bool verbose
                )
            {
                if (rootKey == null)
                    return;

                if (verbose)
                    TraceOps.Trace(traceCallback, String.Format(
                        "rootKey = {0}, subKeyName = {1}", ForDisplay(rootKey),
                        ForDisplay(subKeyName)), traceCategory);

                if (!whatIf)
                    rootKey.DeleteSubKeyTree(subKeyName);

                subKeysDeleted++;
            }

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

            public static string[] GetSubKeyNames(
                MockRegistryKey key,
                bool whatIf,
                bool verbose
                )
            {
                if (key == null)
                    return null;

                if (verbose)
                    TraceOps.Trace(traceCallback, String.Format(
                        "key = {0}", ForDisplay(key)), traceCategory);

                return key.GetSubKeyNames();
            }

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

            public static object GetValue(
                MockRegistryKey key,
                string name,
                object defaultValue,
                bool whatIf,
                bool verbose
                )
            {
                if (key == null)
                    return null;

                if (verbose)
                    TraceOps.Trace(traceCallback, String.Format(
                        "key = {0}, name = {1}, defaultValue = {2}",
                        ForDisplay(key), ForDisplay(name),
                        ForDisplay(defaultValue)), traceCategory);

                return key.GetValue(name, defaultValue);
            }

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

            public static void SetValue(
                MockRegistryKey key,
                string name,
                object value,
                bool whatIf,
                bool verbose
                )
            {
                if (key == null)
                    return;

                if (verbose)
                    TraceOps.Trace(traceCallback, String.Format(
                        "key = {0}, name = {1}, value = {2}", ForDisplay(key),
                        ForDisplay(name), ForDisplay(value)), traceCategory);

                if (!whatIf)
                    key.SetValue(name, value);

                keyValuesSet++;
            }

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

            public static void DeleteValue(
                MockRegistryKey key,
                string name,
                bool whatIf,
                bool verbose
                )
            {
                if (key == null)
                    return;

                if (verbose)
                    TraceOps.Trace(traceCallback, String.Format(
                        "key = {0}, name = {1}", ForDisplay(key),
                        ForDisplay(name)), traceCategory);

                if (!whatIf)
                    key.DeleteValue(name);

                keyValuesDeleted++;
            }
            #endregion
        }
        #endregion

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

        #region StringList Class
        private sealed class StringList : List<string>
        {
            public StringList()
                : base()
            {
                // do nothing.
            }

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

            public StringList(IEnumerable<string> collection)
                : base(collection)
            {
                // do nothing.
            }
        }
        #endregion

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

        #region StringDictionary Class
        private sealed class StringDictionary : Dictionary<string, string>
        {
            public StringDictionary()
            {
                // do nothing.
            }
        }
        #endregion

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

        #region VersionList Class
        private sealed class VersionList : List<Version>
        {
            public VersionList()
                : base()
            {
                // do nothing.
            }

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

            public VersionList(IEnumerable<Version> collection)
                : base(collection)
            {
                // do nothing.
            }
        }
        #endregion

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

        #region VersionMap Class
        private sealed class VersionMap : Dictionary<string, VersionList>
        {
            public VersionMap()
            {
                // do nothing.
            }
        }
        #endregion

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

        #region Configuration Class
        private sealed class Configuration
        {
            #region Private Constants
            private const char Switch = '-';
            private const char AltSwitch = '/';

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

            private static readonly char[] SwitchChars = {
                Switch, AltSwitch
            };
            #endregion

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

            #region Private Constructors
            private Configuration(
                Assembly assembly,
                string logFileName,
                string directory,
                string coreFileName,
                string linqFileName,
                string designerFileName,
                InstallFlags installFlags,
                bool install,
                bool noDesktop,
                bool noCompact,
                bool noNetFx20,
                bool noNetFx40,
                bool noVs2008,
                bool noVs2010,
                bool noTrace,
                bool noConsole,
                bool noLog,
                bool whatIf,
                bool verbose,
                bool confirm
                )
            {
                this.assembly = assembly;
                this.logFileName = logFileName;
                this.directory = directory;
                this.coreFileName = coreFileName;
                this.linqFileName = linqFileName;
                this.designerFileName = designerFileName;
                this.installFlags = installFlags;
                this.install = install;
                this.noDesktop = noDesktop;
                this.noCompact = noCompact;
                this.noNetFx20 = noNetFx20;
                this.noNetFx40 = noNetFx40;
                this.noVs2008 = noVs2008;
                this.noVs2010 = noVs2010;
                this.noTrace = noTrace;
                this.noConsole = noConsole;
                this.noLog = noLog;
                this.whatIf = whatIf;
                this.verbose = verbose;
                this.confirm = confirm;
            }
            #endregion

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

            #region Private Static Methods
            private static void GetDefaultFileNames(
                ref string directory,
                ref string coreFileName,
                ref string linqFileName,
                ref string designerFileName
                )
            {
                if (thisAssembly == null)
                    return;

                directory = Path.GetDirectoryName(thisAssembly.Location);

                if (String.IsNullOrEmpty(directory))
                    return;

                coreFileName = Path.Combine(directory,
                    Installer.CoreFileName);

                linqFileName = Path.Combine(directory,
                    Installer.LinqFileName);

                designerFileName = Path.Combine(directory,
                    Installer.DesignerFileName);
            }

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

            private static bool CheckOption(
                ref string arg
                )
            {
                string result = arg;

                if (!String.IsNullOrEmpty(result))
                {
                    //
                    // NOTE: Remove all leading switch chars.
                    //
                    result = result.TrimStart(SwitchChars);

                    //
                    // NOTE: How many chars were removed?
                    //
                    int count = arg.Length - result.Length;

                    //
                    // NOTE: Was there at least one?
                    //
                    if (count > 0)
                    {
                        //
                        // NOTE: Ok, replace their original
                        //       argument.
                        //
                        arg = result;

                        //
                        // NOTE: Yes, this is a switch.
                        //
                        return true;
                    }
                }

                return false;
            }

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

            private static bool MatchOption(
                string arg,
                string option
                )
            {
                if ((arg == null) || (option == null))
                    return false;

                return String.Compare(arg, 0, option, 0,
                    arg.Length, StringComparison.OrdinalIgnoreCase) == 0;
            }

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

            private static bool? ParseBoolean(
                string text
                )
            {
                if (!String.IsNullOrEmpty(text))
                {
                    bool value;

                    if (bool.TryParse(text, out value))
                        return value;
                }

                return null;
            }

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

            private static object ParseEnum(
                Type enumType,
                string text,
                bool noCase
                )
            {
                if ((enumType == null) || !enumType.IsEnum)
                    return null;

                if (!String.IsNullOrEmpty(text))
                {
                    try
                    {
                        return Enum.Parse(enumType, text, noCase);
                    }
                    catch
                    {
                        // do nothing.
                    }
                }

                return null;
            }
            #endregion

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

            #region Public Static Methods
            public static Configuration CreateDefault()
            {
                string directory = null;
                string coreFileName = null;
                string linqFileName = null;
                string designerFileName = null;

                GetDefaultFileNames(
                    ref directory, ref coreFileName, ref linqFileName,
                    ref designerFileName);

                return new Configuration(
                    thisAssembly, null, directory, coreFileName, linqFileName,
                    designerFileName, InstallFlags.Default, true, false, true,
                    false, false, false, false, false, false, false, true,
                    true, false);
            }

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

            public static bool FromArgs(
                string[] args,
                bool strict,
                ref Configuration configuration,
                ref string error
                )
            {
                try
                {
                    if (args == null)
                        return true;

                    if (configuration == null)
                        configuration = Configuration.CreateDefault();

                    int length = args.Length;

                    for (int index = 0; index < length; index++)
                    {
                        string arg = args[index];

                        if (String.IsNullOrEmpty(arg))
                            continue;

                        string newArg = arg;

                        if (CheckOption(ref newArg))
                        {
                            //
                            // NOTE: All the supported command line options must
                            //       have a value; therefore, attempt to advance
                            //       to it now.  If we fail, we are done.
                            //
                            index++;

                            if (index >= length)
                            {
                                error = TraceOps.Trace(
                                    traceCallback, String.Format(
                                        "Missing value for option: {0}",
                                        ForDisplay(arg)), traceCategory);

                                if (strict)
                                    return false;

                                break;
                            }

                            //
                            // NOTE: Grab the textual value of this command line
                            //       option.
                            //
                            string text = args[index];

                            //
                            // NOTE: Figure out which command line option this is
                            //       (based on a partial name match) and then try
                            //       to interpret the textual value as the correct
                            //       type.
                            //
                            if (MatchOption(newArg, "strict"))
                            {
                                bool? value = ParseBoolean(text);

                                if (value == null)
                                {
                                    error = TraceOps.Trace(traceCallback, String.Format(
                                        "Invalid {0} boolean value: {1}",
                                        ForDisplay(arg), ForDisplay(text)),
                                        traceCategory);

                                    if (strict)
                                        return false;

                                    continue;
                                }

                                //
                                // NOTE: Allow the command line arguments to override
                                //       the "strictness" setting provided by our caller.
                                //
                                strict = (bool)value;
                            }
                            else if (MatchOption(newArg, "logFileName"))
                            {
                                configuration.logFileName = text;
                            }
                            else if (MatchOption(newArg, "directory"))
                            {
                                configuration.directory = text;

                                //
                                // NOTE: *SPECIAL* Must refresh the file names
                                //       here because the underlying directory
                                //       has changed.
                                //
                                string coreFileName = configuration.coreFileName;

                                if (!String.IsNullOrEmpty(coreFileName))
                                    coreFileName = Path.GetFileName(coreFileName);

                                if (String.IsNullOrEmpty(coreFileName))
                                    coreFileName = Installer.CoreFileName;

                                configuration.coreFileName = Path.Combine(
                                    configuration.directory, coreFileName);

                                string linqFileName = configuration.linqFileName;

                                if (!String.IsNullOrEmpty(linqFileName))
                                    linqFileName = Path.GetFileName(linqFileName);

                                if (String.IsNullOrEmpty(linqFileName))
                                    linqFileName = Installer.LinqFileName;

                                configuration.linqFileName = Path.Combine(
                                    configuration.directory, linqFileName);

                                string designerFileName = configuration.designerFileName;

                                if (!String.IsNullOrEmpty(designerFileName))
                                    designerFileName = Path.GetFileName(designerFileName);

                                if (String.IsNullOrEmpty(designerFileName))
                                    designerFileName = Installer.DesignerFileName;

                                configuration.designerFileName = Path.Combine(
                                    configuration.directory, designerFileName);
                            }
                            else if (MatchOption(newArg, "coreFileName"))
                            {
                                configuration.coreFileName = text;
                            }
                            else if (MatchOption(newArg, "linqFileName"))
                            {
                                configuration.linqFileName = text;
                            }
                            else if (MatchOption(newArg, "designerFileName"))
                            {
                                configuration.designerFileName = text;
                            }
                            else if (MatchOption(newArg, "installFlags"))
                            {
                                object value = ParseEnum(
                                    typeof(InstallFlags), text, true);

                                if (value == null)
                                {
                                    error = TraceOps.Trace(traceCallback, String.Format(
                                        "Invalid install flags value: {0}",
                                        ForDisplay(text)), traceCategory);

                                    if (strict)
                                        return false;

                                    continue;
                                }

                                configuration.installFlags = (InstallFlags)value;
                            }
                            else if (MatchOption(newArg, "install"))
                            {
                                bool? value = ParseBoolean(text);

                                if (value == null)
                                {
                                    error = TraceOps.Trace(traceCallback, String.Format(
                                        "Invalid {0} boolean value: {1}",
                                        ForDisplay(arg), ForDisplay(text)),
                                        traceCategory);

                                    if (strict)
                                        return false;

                                    continue;
                                }

                                configuration.install = (bool)value;
                            }
                            else if (MatchOption(newArg, "whatIf"))
                            {
                                bool? value = ParseBoolean(text);

                                if (value == null)
                                {
                                    error = TraceOps.Trace(traceCallback, String.Format(
                                        "Invalid {0} boolean value: {1}",
                                        ForDisplay(arg), ForDisplay(text)),
                                        traceCategory);

                                    if (strict)
                                        return false;

                                    continue;
                                }

                                configuration.whatIf = (bool)value;
                            }
                            else if (MatchOption(newArg, "verbose"))
                            {
                                bool? value = ParseBoolean(text);

                                if (value == null)
                                {
                                    error = TraceOps.Trace(traceCallback, String.Format(
                                        "Invalid {0} boolean value: {1}",
                                        ForDisplay(arg), ForDisplay(text)),
                                        traceCategory);

                                    if (strict)
                                        return false;

                                    continue;
                                }

                                configuration.verbose = (bool)value;
                            }
                            else if (MatchOption(newArg, "confirm"))
                            {
                                bool? value = ParseBoolean(text);

                                if (value == null)
                                {
                                    error = TraceOps.Trace(traceCallback, String.Format(
                                        "Invalid {0} boolean value: {1}",
                                        ForDisplay(arg), ForDisplay(text)),
                                        traceCategory);

                                    if (strict)
                                        return false;

                                    continue;
                                }

                                configuration.confirm = (bool)value;
                            }
                            else if (MatchOption(newArg, "noDesktop"))
                            {
                                bool? value = ParseBoolean(text);

                                if (value == null)
                                {
                                    error = TraceOps.Trace(traceCallback, String.Format(
                                        "Invalid {0} boolean value: {1}",
                                        ForDisplay(arg), ForDisplay(text)),
                                        traceCategory);

                                    if (strict)
                                        return false;

                                    continue;
                                }

                                configuration.noDesktop = (bool)value;
                            }
                            else if (MatchOption(newArg, "noCompact"))
                            {
                                bool? value = ParseBoolean(text);

                                if (value == null)
                                {
                                    error = TraceOps.Trace(traceCallback, String.Format(
                                        "Invalid {0} boolean value: {1}",
                                        ForDisplay(arg), ForDisplay(text)),
                                        traceCategory);

                                    if (strict)
                                        return false;

                                    continue;
                                }

                                configuration.noCompact = (bool)value;
                            }
                            else if (MatchOption(newArg, "noNetFx20"))
                            {
                                bool? value = ParseBoolean(text);

                                if (value == null)
                                {
                                    error = TraceOps.Trace(traceCallback, String.Format(
                                        "Invalid {0} boolean value: {1}",
                                        ForDisplay(arg), ForDisplay(text)),
                                        traceCategory);

                                    if (strict)
                                        return false;

                                    continue;
                                }

                                configuration.noNetFx20 = (bool)value;
                            }
                            else if (MatchOption(newArg, "noNetFx40"))
                            {
                                bool? value = ParseBoolean(text);

                                if (value == null)
                                {
                                    error = TraceOps.Trace(traceCallback, String.Format(
                                        "Invalid {0} boolean value: {1}",
                                        ForDisplay(arg), ForDisplay(text)),
                                        traceCategory);

                                    if (strict)
                                        return false;

                                    continue;
                                }

                                configuration.noNetFx40 = (bool)value;
                            }
                            else if (MatchOption(newArg, "noVs2008"))
                            {
                                bool? value = ParseBoolean(text);

                                if (value == null)
                                {
                                    error = TraceOps.Trace(traceCallback, String.Format(
                                        "Invalid {0} boolean value: {1}",
                                        ForDisplay(arg), ForDisplay(text)),
                                        traceCategory);

                                    if (strict)
                                        return false;

                                    continue;
                                }

                                configuration.noVs2008 = (bool)value;
                            }
                            else if (MatchOption(newArg, "noVs2010"))
                            {
                                bool? value = ParseBoolean(text);

                                if (value == null)
                                {
                                    error = TraceOps.Trace(traceCallback, String.Format(
                                        "Invalid {0} boolean value: {1}",
                                        ForDisplay(arg), ForDisplay(text)),
                                        traceCategory);

                                    if (strict)
                                        return false;

                                    continue;
                                }

                                configuration.noVs2010 = (bool)value;
                            }
                            else if (MatchOption(newArg, "noTrace"))
                            {
                                bool? value = ParseBoolean(text);

                                if (value == null)
                                {
                                    error = TraceOps.Trace(traceCallback, String.Format(
                                        "Invalid {0} boolean value: {1}",
                                        ForDisplay(arg), ForDisplay(text)),
                                        traceCategory);

                                    if (strict)
                                        return false;

                                    continue;
                                }

                                configuration.noTrace = (bool)value;
                            }
                            else if (MatchOption(newArg, "noConsole"))
                            {
                                bool? value = ParseBoolean(text);

                                if (value == null)
                                {
                                    error = TraceOps.Trace(traceCallback, String.Format(
                                        "Invalid {0} boolean value: {1}",
                                        ForDisplay(arg), ForDisplay(text)),
                                        traceCategory);

                                    if (strict)
                                        return false;

                                    continue;
                                }

                                configuration.noConsole = (bool)value;
                            }
                            else if (MatchOption(newArg, "noLog"))
                            {
                                bool? value = ParseBoolean(text);

                                if (value == null)
                                {
                                    error = TraceOps.Trace(traceCallback, String.Format(
                                        "Invalid {0} boolean value: {1}",
                                        ForDisplay(arg), ForDisplay(text)),
                                        traceCategory);

                                    if (strict)
                                        return false;

                                    continue;
                                }

                                configuration.noLog = (bool)value;
                            }
                            else
                            {
                                error = TraceOps.Trace(traceCallback, String.Format(
                                    "Unsupported command line option: {0}",
                                    ForDisplay(arg)), traceCategory);

                                if (strict)
                                    return false;
                            }
                        }
                        else
                        {
                            error = TraceOps.Trace(traceCallback, String.Format(
                                "Unsupported command line argument: {0}",
                                ForDisplay(arg)), traceCategory);

                            if (strict)
                                return false;
                        }
                    }

                    return true;
                }
                catch (Exception e)
                {
                    TraceOps.Trace(traceCallback, e, traceCategory);

                    error = "Failed to modify configuration.";
                }

                return false;
            }

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

            public static bool Process(
                string[] args,
                Configuration configuration,
                bool strict,
                ref string error
                )
            {
                try
                {
                    if (configuration == null)
                    {
                        error = "Invalid configuration.";
                        return false;
                    }

                    Assembly assembly = configuration.assembly;

                    if (assembly == null)
                    {
                        error = "Invalid assembly.";
                        return false;
                    }

                    if (!configuration.noTrace)
                    {
                        if (!configuration.noLog &&
                            String.IsNullOrEmpty(configuration.logFileName))
                        {
                            configuration.logFileName = GetLogFileName();
                        }

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

                        if (!configuration.noConsole)
                        {
                            Trace.Listeners.Add(new ConsoleTraceListener());
                        }

                        if (!configuration.noLog &&
                            !String.IsNullOrEmpty(configuration.logFileName))
                        {
                            Trace.Listeners.Add(new TextWriterTraceListener(
                                configuration.logFileName));
                        }
                    }

                    //
                    // NOTE: Dump the configuration now in case we need to
                    //       troubleshoot any issues.
                    //
                    configuration.Dump();

                    //
                    // NOTE: Show where we are running from and how we were
                    //       invoked.
                    //
                    string location = assembly.Location;

                    TraceOps.Trace(traceCallback, String.Format(
                        "Original command line is: {0}",
                        Environment.CommandLine), traceCategory);

                    //
                    // NOTE: If the debugger is attached and What-If mode is
                    //       [now] disabled, issue a warning.
                    //
                    if (!configuration.whatIf && Debugger.IsAttached)
                    {
                        TraceOps.Trace(traceCallback,
                            "Forced to disable \"what-if\" mode with " +
                            "debugger attached.", traceCategory);
                    }

                    //
                    // NOTE: If the command line has not been manually
                    //       confirmed (i.e. via the explicit command line
                    //       option), then stop processing now.  We enforce
                    //       this rule so that simply double-clicking the
                    //       executable will not result in any changes being
                    //       made to the system.
                    //
                    if (!configuration.confirm)
                    {
                        error = "Cannot continue, the \"confirm\" option is " +
                            "not enabled.";

                        return false;
                    }

                    return true;
                }
                catch (Exception e)
                {
                    TraceOps.Trace(traceCallback, e, traceCategory);

                    error = "Failed to process configuration.";
                }

                return false;
            }
            #endregion

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

            #region Public Methods
            public bool HasFlags(
                InstallFlags hasFlags,
                bool all
                )
            {
                if (all)
                    return ((installFlags & hasFlags) == hasFlags);
                else
                    return ((installFlags & hasFlags) != InstallFlags.None);
            }

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

            public void Dump()
            {
                if (traceCallback != null)
                {
                    traceCallback(String.Format(NameAndValueFormat,
                        "Assembly", ForDisplay(assembly)),
                        traceCategory);

                    traceCallback(String.Format(NameAndValueFormat,
                        "LogFileName", ForDisplay(logFileName)),
                        traceCategory);

                    traceCallback(String.Format(NameAndValueFormat,
                        "Directory", ForDisplay(directory)),
                        traceCategory);

                    traceCallback(String.Format(NameAndValueFormat,
                        "CoreFileName", ForDisplay(coreFileName)),
                        traceCategory);

                    traceCallback(String.Format(NameAndValueFormat,
                        "LinqFileName", ForDisplay(linqFileName)),
                        traceCategory);

                    traceCallback(String.Format(NameAndValueFormat,
                        "DesignerFileName", ForDisplay(designerFileName)),
                        traceCategory);

                    traceCallback(String.Format(NameAndValueFormat,
                        "InstallFlags", ForDisplay(installFlags)),
                        traceCategory);

                    traceCallback(String.Format(NameAndValueFormat,
                        "Install", ForDisplay(install)),
                        traceCategory);

                    traceCallback(String.Format(NameAndValueFormat,
                        "NoDesktop", ForDisplay(noDesktop)),
                        traceCategory);

                    traceCallback(String.Format(NameAndValueFormat,
                        "NoCompact", ForDisplay(noCompact)),
                        traceCategory);

                    traceCallback(String.Format(NameAndValueFormat,
                        "NoNetFx20", ForDisplay(noNetFx20)),
                        traceCategory);

                    traceCallback(String.Format(NameAndValueFormat,
                        "NoNetFx40", ForDisplay(noNetFx40)),
                        traceCategory);

                    traceCallback(String.Format(NameAndValueFormat,
                        "NoVs2008", ForDisplay(noVs2008)),
                        traceCategory);

                    traceCallback(String.Format(NameAndValueFormat,
                        "NoVs2010", ForDisplay(noVs2010)),
                        traceCategory);

                    traceCallback(String.Format(NameAndValueFormat,
                        "NoTrace", ForDisplay(noTrace)),
                        traceCategory);

                    traceCallback(String.Format(NameAndValueFormat,
                        "NoConsole", ForDisplay(noConsole)),
                        traceCategory);

                    traceCallback(String.Format(NameAndValueFormat,
                        "NoLog", ForDisplay(noLog)),
                        traceCategory);

                    traceCallback(String.Format(NameAndValueFormat,
                        "WhatIf", ForDisplay(whatIf)),
                        traceCategory);

                    traceCallback(String.Format(NameAndValueFormat,
                        "Verbose", ForDisplay(verbose)),
                        traceCategory);

                    traceCallback(String.Format(NameAndValueFormat,
                        "Confirm", ForDisplay(confirm)),
                        traceCategory);
                }
            }
            #endregion

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

            #region Public Properties
            private Assembly assembly;
            public Assembly Assembly
            {
                get { return assembly; }
                set { assembly = value; }
            }

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

            private string logFileName;
            public string LogFileName
            {
                get { return logFileName; }
                set { logFileName = value; }
            }

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

            private string directory;
            public string Directory
            {
                get { return directory; }
                set { directory = value; }
            }

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

            private string coreFileName;
            public string CoreFileName
            {
                get { return coreFileName; }
                set { coreFileName = value; }
            }

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

            private string linqFileName;
            public string LinqFileName
            {
                get { return linqFileName; }
                set { linqFileName = value; }
            }

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

            private string designerFileName;
            public string DesignerFileName
            {
                get { return designerFileName; }
                set { designerFileName = value; }
            }

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

            private InstallFlags installFlags;
            public InstallFlags InstallFlags
            {
                get { return installFlags; }
                set { installFlags = value; }
            }

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

            private bool install;
            public bool Install
            {
                get { return install; }
                set { install = value; }
            }

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

            private bool noDesktop;
            public bool NoDesktop
            {
                get { return noDesktop; }
                set { noDesktop = value; }
            }

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

            private bool noCompact;
            public bool NoCompact
            {
                get { return noCompact; }
                set { noCompact = value; }
            }

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

            private bool noNetFx20;
            public bool NoNetFx20
            {
                get { return noNetFx20; }
                set { noNetFx20 = value; }
            }

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

            private bool noNetFx40;
            public bool NoNetFx40
            {
                get { return noNetFx40; }
                set { noNetFx40 = value; }
            }

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

            private bool noVs2008;
            public bool NoVs2008
            {
                get { return noVs2008; }
                set { noVs2008 = value; }
            }

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

            private bool noVs2010;
            public bool NoVs2010
            {
                get { return noVs2010; }
                set { noVs2010 = value; }
            }

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

            private bool noTrace;
            public bool NoTrace
            {
                get { return noTrace; }
                set { noTrace = value; }
            }

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

            private bool noConsole;
            public bool NoConsole
            {
                get { return noConsole; }
                set { noConsole = value; }
            }

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

            private bool noLog;
            public bool NoLog
            {
                get { return noLog; }
                set { noLog = value; }
            }

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

            private bool whatIf;
            public bool WhatIf
            {
                get { return whatIf; }
                set { whatIf = value; }
            }

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

            private bool verbose;
            public bool Verbose
            {
                get { return verbose; }
                set { verbose = value; }
            }

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

            private bool confirm;
            public bool Confirm
            {
                get { return confirm; }
                set { confirm = value; }
            }
            #endregion
        }
        #endregion
        #endregion

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

        #region Private Constant Data
        private const string CoreFileName = "System.Data.SQLite.dll";
        private const string LinqFileName = "System.Data.SQLite.Linq.dll";
        private const string DesignerFileName = "SQLite.Designer.dll";
        private const string ProviderName = "SQLite Data Provider";
        private const string ProjectName = "System.Data.SQLite";
        private const string LegacyProjectName = "SQLite";
        private const string InvariantName = "System.Data.SQLite";
        private const string FactoryTypeName = "System.Data.SQLite.SQLiteFactory";
        private const string Description = ".NET Framework Data Provider for SQLite";

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

        private const string NameAndValueFormat = "{0}: {1}";
        private const string TraceFormat = "#{0} @ {1}: {2}";
        private const string LogFileSuffix = ".log";

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

        private static readonly string VsIdFormat = "B";

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

        private static readonly string FrameworkKeyName =
            "Software\\Microsoft\\.NETFramework";

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

        private static readonly string FrameworkSdkKeyName =
            "Software\\Microsoft\\Microsoft SDKs\\.NETFramework";

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

        private static readonly string WindowsSdkKeyName =
            "Software\\Microsoft\\Microsoft SDKs\\Windows";

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

        private static readonly string XPathForAddElement =
            "configuration/system.data/DbProviderFactories/add[@invariant=\"{0}\"]";

        private static readonly string XPathForRemoveElement =
            "configuration/system.data/DbProviderFactories/remove[@invariant=\"{0}\"]";
        #endregion

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

        #region Private Data
        private static Assembly thisAssembly = Assembly.GetExecutingAssembly();

        private static string traceCategory = Path.GetFileName(
            thisAssembly.Location);

        private static TraceCallback traceCallback = AppTrace;

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

        private static RegistryKey frameworkRootKey;
        private static StringList frameworkNameList;
        private static VersionMap frameworkVersionMap;
        private static StringList platformNameList;

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

        private static RegistryKey vsRootKey;
        private static VersionList vsVersionList;
        private static Guid? vsPackageId;
        private static Guid? vsServiceId;
        private static Guid? vsDataSourcesId;
        private static Guid? vsDataProviderId;
        private static Guid? vsAdoNetTechnologyId;
        #endregion

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

        #region Trace Handling
        private static string GetLogFileName()
        {
            string result = Path.GetTempFileName(); /* throw */

            File.Move(result, result + LogFileSuffix); /* throw */
            result += LogFileSuffix;

            return result;
        }

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

        private static void AppTrace(
            string message,
            string category
            )
        {
            TraceOps.TraceCore(String.Format(
                TraceFormat, TraceOps.NextId(),
                TraceOps.TimeStamp(DateTime.UtcNow), message), category);
        }
        #endregion

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

        #region Generic String Handling
        private static string ForDisplay(
            object value
            )
        {
            if (value == null)
                return "<null>";

            string result;
            Type type = value.GetType();

            if (type == typeof(XmlElement))
            {
                XmlElement element = (XmlElement)value;

                result = element.OuterXml;
            }
            else
            {
                result = value.ToString();

                if (result.Length == 0)
                    return "<empty>";

                result = String.Format(
                    type.IsSubclassOf(typeof(ValueType)) ? "{0}" : "\"{0}\"",
                    result);
            }

            return result;
        }
        #endregion

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

        #region .NET Framework Handling
        private static string GetFrameworkDirectory(
            RegistryKey rootKey,
            Version frameworkVersion,
            bool whatIf,
            bool verbose
            )
        {
            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, FrameworkKeyName, false, whatIf, verbose))
            {
                if (key == null)
                    return null;

                object value = RegistryHelper.GetValue(
                    key, "InstallRoot", null, whatIf, verbose);

                if (!(value is string))
                    return null;

                return Path.Combine(
                    (string)value, String.Format("v{0}", frameworkVersion));
            }
        }

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

        private static string GetSdkBinaryFileName(
            RegistryKey rootKey,
            string fileName,
            bool whatIf,
            bool verbose
            )
        {
            StringDictionary results = new StringDictionary();

            string[] keyNames = {
                FrameworkKeyName,
                FrameworkSdkKeyName,
                WindowsSdkKeyName
            };

            string[] valueNames = {
                "sdkInstallRootv2.0",
                "InstallationFolder",
                "InstallationFolder"
            };

            bool[] useSubKeys = {
                false,
                true,
                true
            };

            for (int index = 0; index < keyNames.Length; index++)
            {
                using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                        rootKey, keyNames[index], false, whatIf, verbose))
                {
                    if (key == null)
                        continue;

                    if (useSubKeys[index])
                    {
                        foreach (string subKeyName in RegistryHelper.GetSubKeyNames(
                                key, whatIf, verbose))
                        {
                            using (MockRegistryKey subKey = RegistryHelper.OpenSubKey(
                                    key, subKeyName, false, whatIf, verbose))
                            {
                                if (subKey == null)
                                    continue;

                                object value = RegistryHelper.GetValue(
                                    subKey, valueNames[index], null, whatIf,
                                    verbose);

                                if (!(value is string))
                                    continue;

                                string path = (string)value;

                                if (!Directory.Exists(path))
                                    continue;

                                path = Path.Combine(path, "bin");

                                if (!Directory.Exists(path))
                                    continue;

                                if (String.IsNullOrEmpty(fileName))
                                {
                                    results.Add(subKey.Name, path);
                                    continue;
                                }

                                path = Path.Combine(path, fileName);

                                if (File.Exists(path))
                                    results.Add(subKey.Name, path);
                            }
                        }
                    }
                    else
                    {
                        object value = RegistryHelper.GetValue(
                            key, valueNames[index], null, whatIf, verbose);

                        if (!(value is string))
                            continue;

                        string path = (string)value;

                        if (!Directory.Exists(path))
                            continue;

                        path = Path.Combine(path, "bin");

                        if (!Directory.Exists(path))
                            continue;

                        if (String.IsNullOrEmpty(fileName))
                        {
                            results.Add(key.Name, path);
                            continue;
                        }

                        path = Path.Combine(path, fileName);

                        if (File.Exists(path))
                            results.Add(key.Name, path);
                    }
                }
            }

            //
            // NOTE: If we found some results, return the last (latest) one.
            //
            if (results.Count > 0)
                return results[new StringList(results.Keys)[results.Count - 1]];

            return null;
        }
        #endregion

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

        #region Per-Framework/Platform Handling
        private static void InitializeAllFrameworks(
            Configuration configuration
            )
        {
            if (frameworkRootKey == null)
                frameworkRootKey = Registry.LocalMachine;

            if (frameworkNameList == null)
            {
                frameworkNameList = new StringList();

                if ((configuration == null) || !configuration.NoDesktop)
                    frameworkNameList.Add(".NETFramework");

                if ((configuration == null) || !configuration.NoCompact)
                {
                    frameworkNameList.Add(".NETCompactFramework");
                    frameworkNameList.Add(".NETCompactFramework");
                    frameworkNameList.Add(".NETCompactFramework");
                }
            }

            if (frameworkVersionMap == null)
                frameworkVersionMap = new VersionMap();

            if ((configuration == null) || !configuration.NoDesktop)
            {
                VersionList desktopVersionList = new VersionList();

                if ((configuration == null) || !configuration.NoNetFx20)
                    desktopVersionList.Add(new Version(2, 0, 50727));

                if ((configuration == null) || !configuration.NoNetFx40)
                    desktopVersionList.Add(new Version(4, 0, 30319));

                frameworkVersionMap.Add(".NETFramework", desktopVersionList);
            }

            if ((configuration == null) || !configuration.NoCompact)
            {
                frameworkVersionMap.Add(".NETCompactFramework", new VersionList(
                    new Version[] {
                    new Version(2, 0, 0, 0), new Version(3, 5, 0, 0)
                }));
            }

            if (platformNameList == null)
            {
                platformNameList = new StringList();

                if ((configuration == null) || !configuration.NoDesktop)
                    platformNameList.Add(null);

                if ((configuration == null) || !configuration.NoCompact)
                {
                    platformNameList.Add("PocketPC");
                    platformNameList.Add("Smartphone");
                    platformNameList.Add("WindowsCE");
                }
            }
        }

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

        private static bool HaveFramework(
            RegistryKey rootKey,
            string frameworkName,
            Version frameworkVersion,
            string platformName,
            bool whatIf,
            bool verbose
            )
        {
            string format = !String.IsNullOrEmpty(platformName) ?
                "Software\\Microsoft\\{0}\\v{1}\\{2}" :
                "Software\\Microsoft\\{0}\\v{1}";

            string keyName = String.Format(
                format, frameworkName, frameworkVersion, platformName);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, false, whatIf, verbose))
            {
                if (key == null)
                    return false;

                if (platformName != null) // NOTE: Skip non-desktop frameworks.
                    return true;

                string directory = GetFrameworkDirectory(
                    rootKey, frameworkVersion, whatIf, verbose);

                if (String.IsNullOrEmpty(directory))
                    return false;

                if (!Directory.Exists(directory))
                    return false;

                return true;
            }
        }

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

        private static bool ForEachFrameworkConfig(
            FrameworkConfigCallback callback,
            string invariant,
            string name,
            string description,
            string typeName,
            AssemblyName assemblyName,
            object clientData,
            bool whatIf,
            bool verbose,
            ref bool saved,
            ref string error
            )
        {
            RegistryKey rootKey = frameworkRootKey;

            if (rootKey == null)
            {
                error = "invalid root key";
                return false;
            }

            if (!Object.ReferenceEquals(rootKey, Registry.CurrentUser) &&
                !Object.ReferenceEquals(rootKey, Registry.LocalMachine))
            {
                error = "root key must be per-user or per-machine";
                return false;
            }

            if (frameworkNameList == null)
            {
                error = "no framework names found";
                return false;
            }

            if (frameworkVersionMap == null)
            {
                error = "no framework versions found";
                return false;
            }

            if (platformNameList == null)
            {
                error = "no platform names found";
                return false;
            }

            if (frameworkNameList.Count != platformNameList.Count)
            {
                error = String.Format("framework name count {0} does not " +
                    "match platform name count {1}", frameworkNameList.Count,
                    platformNameList.Count);

                return false;
            }

            for (int index = 0; index < frameworkNameList.Count; index++)
            {
                //
                // NOTE: Grab the name of the framework (e.g. ".NETFramework")
                //       and the name of the platform (e.g. "WindowsCE").
                //
                string frameworkName = frameworkNameList[index];
                string platformName = platformNameList[index];

                //
                // NOTE: Skip all non-desktop frameworks (i.e. if the platform
                //       name is not null).
                //
                if (platformName != null)
                    continue;

                //
                // NOTE: Grab the supported versions of this particular
                //       framework.
                //
                VersionList frameworkVersionList;

                if (!frameworkVersionMap.TryGetValue(
                        frameworkName, out frameworkVersionList) ||
                    (frameworkVersionList == null))
                {
                    continue;
                }

                foreach (Version frameworkVersion in frameworkVersionList)
                {
                    TraceOps.Trace(traceCallback, String.Format(
                        "frameworkName = {0}, frameworkVersion = {1}, " +
                        "platformName = {2}", ForDisplay(frameworkName),
                        ForDisplay(frameworkVersion),
                        ForDisplay(platformName)), traceCategory);

                    if (!HaveFramework(
                            rootKey, frameworkName, frameworkVersion,
                            platformName, whatIf, verbose))
                    {
                        TraceOps.Trace(traceCallback,
                            ".NET Framework not found, skipping...",
                            traceCategory);

                        continue;
                    }

                    if (callback == null)
                        continue;

                    string directory = GetFrameworkDirectory(
                        rootKey, frameworkVersion, whatIf, verbose);

                    if (String.IsNullOrEmpty(directory))
                    {
                        TraceOps.Trace(traceCallback, String.Format(
                            ".NET Framework v{0} directory is invalid, " +
                            "skipping...", frameworkVersion), traceCategory);

                        continue;
                    }

                    directory = Path.Combine(directory, "Config");

                    if (!Directory.Exists(directory))
                    {
                        TraceOps.Trace(traceCallback, String.Format(
                            ".NET Framework v{0} directory \"{1}\" does not " +
                            "exist, skipping...", frameworkVersion, directory),
                            traceCategory);

                        continue;
                    }

                    string fileName = Path.Combine(directory, "machine.config");

                    if (!File.Exists(fileName))
                    {
                        TraceOps.Trace(traceCallback, String.Format(
                            ".NET Framework v{0} file \"{1}\" does not exist, " +
                            "skipping...", frameworkVersion, fileName),
                            traceCategory);

                        continue;
                    }

                    bool localSaved = false;

                    if (!callback(
                            fileName, invariant, name, description, typeName,
                            assemblyName, clientData, whatIf, verbose,
                            ref localSaved, ref error))
                    {
                        return false;
                    }
                    else
                    {
                        if (localSaved && !saved)
                            saved = true;

                        if (verbose)
                            TraceOps.Trace(traceCallback, String.Format(
                                "localSaved = {0}, saved = {1}", localSaved,
                                saved), traceCategory);
                    }
                }
            }

            return true;
        }

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

        private static bool ForEachFrameworkRegistry(
            FrameworkRegistryCallback callback,
            object clientData,
            bool whatIf,
            bool verbose,
            ref string error
            )
        {
            RegistryKey rootKey = frameworkRootKey;

            if (rootKey == null)
            {
                error = "invalid root key";
                return false;
            }

            if (!Object.ReferenceEquals(rootKey, Registry.CurrentUser) &&
                !Object.ReferenceEquals(rootKey, Registry.LocalMachine))
            {
                error = "root key must be per-user or per-machine";
                return false;
            }

            if (frameworkNameList == null)
            {
                error = "no framework names found";
                return false;
            }

            if (frameworkVersionMap == null)
            {
                error = "no framework versions found";
                return false;
            }

            if (platformNameList == null)
            {
                error = "no platform names found";
                return false;
            }

            if (frameworkNameList.Count != platformNameList.Count)
            {
                error = String.Format("framework name count {0} does not " +
                    "match platform name count {1}", frameworkNameList.Count,
                    platformNameList.Count);

                return false;
            }

            for (int index = 0; index < frameworkNameList.Count; index++)
            {
                //
                // NOTE: Grab the name of the framework (e.g. ".NETFramework")
                //       and the name of the platform (e.g. "WindowsCE").
                //
                string frameworkName = frameworkNameList[index];
                string platformName = platformNameList[index];

                //
                // NOTE: Grab the supported versions of this particular
                //       framework.
                //
                VersionList frameworkVersionList;

                if (!frameworkVersionMap.TryGetValue(
                        frameworkName, out frameworkVersionList) ||
                    (frameworkVersionList == null))
                {
                    continue;
                }

                foreach (Version frameworkVersion in frameworkVersionList)
                {
                    TraceOps.Trace(traceCallback, String.Format(
                        "frameworkName = {0}, frameworkVersion = {1}, " +
                        "platformName = {2}", ForDisplay(frameworkName),
                        ForDisplay(frameworkVersion),
                        ForDisplay(platformName)), traceCategory);

                    if (!HaveFramework(
                            rootKey, frameworkName, frameworkVersion,
                            platformName, whatIf, verbose))
                    {
                        TraceOps.Trace(traceCallback,
                            ".NET Framework not found, skipping...",
                            traceCategory);

                        continue;
                    }

                    if (callback == null)
                        continue;

                    if (!callback(
                            rootKey, frameworkName, frameworkVersion,
                            platformName, clientData, whatIf, verbose,
                            ref error))
                    {
                        return false;
                    }
                }
            }

            return true;
        }
        #endregion

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

        #region Per-Visual Studio Version Handling
        private static void InitializeAllVsVersions(
            Configuration configuration
            )
        {
            if (vsRootKey == null)
                vsRootKey = Registry.LocalMachine;

            if (vsAdoNetTechnologyId == null)
                vsAdoNetTechnologyId = new Guid(
                    "77AB9A9D-78B9-4BA7-91AC-873F5338F1D2");

            if (vsPackageId == null)
                vsPackageId = new Guid(
                    "DCBE6C8D-0E57-4099-A183-98FF74C64D9C");

            if (vsServiceId == null)
                vsServiceId = new Guid(
                    "DCBE6C8D-0E57-4099-A183-98FF74C64D9D");

            if (vsDataSourcesId == null)
                vsDataSourcesId = new Guid(
                    "0EBAAB6E-CA80-4B4A-8DDF-CBE6BF058C71");

            if (vsDataProviderId == null)
                vsDataProviderId = new Guid(
                    "0EBAAB6E-CA80-4B4A-8DDF-CBE6BF058C70");

            if (vsVersionList == null)
            {
                vsVersionList = new VersionList();

                // vsVersionList.Add(new Version(8, 0)); // Visual Studio 2005

                if ((configuration == null) || !configuration.NoVs2008)
                    vsVersionList.Add(new Version(9, 0)); // Visual Studio 2008

                if ((configuration == null) || !configuration.NoVs2010)
                    vsVersionList.Add(new Version(10, 0));// Visual Studio 2010
            }
        }

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

        private static bool HaveVsVersion(
            RegistryKey rootKey,
            Version vsVersion,
            bool whatIf,
            bool verbose
            )
        {
            string format = "Software\\Microsoft\\VisualStudio\\{0}";
            string keyName = String.Format(format, vsVersion);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, false, whatIf, verbose))
            {
                if (key == null)
                    return false;

                object value = RegistryHelper.GetValue(
                    key, "InstallDir", null, whatIf, verbose);

                if (!(value is string))
                    return false;

                string directory = (string)value;

                if (String.IsNullOrEmpty(directory))
                    return false;

                if (!Directory.Exists(directory))
                    return false;

                return true;
            }
        }

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

        private static bool ForEachVsVersionRegistry(
            VisualStudioRegistryCallback callback,
            Guid packageId,
            Guid serviceId,
            Guid dataSourceId,
            Guid dataProviderId,
            object clientData,
            bool whatIf,
            bool verbose,
            ref string error
            )
        {
            RegistryKey rootKey = vsRootKey;

            if (rootKey == null)
            {
                error = "invalid root key";
                return false;
            }

            if (!Object.ReferenceEquals(rootKey, Registry.CurrentUser) &&
                !Object.ReferenceEquals(rootKey, Registry.LocalMachine))
            {
                error = "root key must be per-user or per-machine";
                return false;
            }

            if (vsVersionList == null)
            {
                error = "no VS versions found";
                return false;
            }

            foreach (Version vsVersion in vsVersionList)
            {
                TraceOps.Trace(traceCallback, String.Format(
                    "vsVersion = {0}", ForDisplay(vsVersion)),
                    traceCategory);

                if (!HaveVsVersion(rootKey, vsVersion, whatIf, verbose))
                {
                    TraceOps.Trace(traceCallback,
                        "Visual Studio version not found, skipping...",
                        traceCategory);

                    continue;
                }

                if (callback == null)
                    continue;

                if (!callback(
                        rootKey, vsVersion, packageId, serviceId,
                        dataSourceId, dataProviderId, clientData, whatIf,
                        verbose, ref error))
                {
                    return false;
                }
            }

            return true;
        }
        #endregion

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

        #region Configuration File Handling
        private static bool AddDbProviderFactory(
            string fileName,
            string invariant,
            string name,
            string description,
            string typeName,
            AssemblyName assemblyName,
            bool whatIf,
            bool verbose,
            ref bool saved,
            ref string error
            )
        {
            bool dirty = false;
            XmlDocument document = new XmlDocument();

            document.PreserveWhitespace = true;
            document.Load(fileName);

            XmlElement element = document.SelectSingleNode(String.Format(
                XPathForAddElement, invariant)) as XmlElement;

            if (element == null)
            {
                string[] elementNames = {
                        "system.data", "DbProviderFactories"
                    };

                XmlElement previousElement =
                    document.DocumentElement; /* configuration */

                foreach (string elementName in elementNames)
                {
                    element = previousElement.SelectSingleNode(
                        elementName) as XmlElement;

                    if (element == null)
                    {
                        element = document.CreateElement(
                            elementName, String.Empty);

                        previousElement.AppendChild(element);
                    }

                    previousElement = element;
                }

                element = document.CreateElement(
                    "add", String.Empty);

                previousElement.AppendChild(element);

                dirty = true;
            }

            if (!String.Equals(element.GetAttribute("name"),
                    name, StringComparison.InvariantCulture))
            {
                element.SetAttribute("name", name);
                dirty = true;
            }

            if (!String.Equals(element.GetAttribute("invariant"),
                    invariant, StringComparison.InvariantCulture))
            {
                element.SetAttribute("invariant", invariant);
                dirty = true;
            }

            if (!String.Equals(element.GetAttribute("description"),
                    description, StringComparison.InvariantCulture))
            {
                element.SetAttribute("description", description);
                dirty = true;
            }

            string fullTypeName = String.Format("{0}, {1}",
                typeName, assemblyName);

            if (!String.Equals(element.GetAttribute("type"),
                    fullTypeName, StringComparison.InvariantCulture))
            {
                element.SetAttribute("type", fullTypeName);
                dirty = true;
            }

            if (dirty)
            {
                if (verbose)
                    TraceOps.Trace(traceCallback, String.Format(
                        "element = {0}", ForDisplay(element)), traceCategory);

                if (!whatIf)
                    document.Save(fileName);

                saved = true;
            }

            return true;
        }

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

        private static bool RemoveDbProviderFactory(
            string fileName,
            string invariant,
            bool whatIf,
            bool verbose,
            ref bool saved,
            ref string error
            )
        {
            bool dirty = false;
            XmlDocument document = new XmlDocument();

            document.PreserveWhitespace = true;
            document.Load(fileName);

            XmlElement element = document.SelectSingleNode(String.Format(
                XPathForAddElement, invariant)) as XmlElement;

            if (element != null)
            {
                element.ParentNode.RemoveChild(element);
                dirty = true;
            }

            element = document.SelectSingleNode(String.Format(
                XPathForRemoveElement, invariant)) as XmlElement;

            if (element != null)
            {
                element.ParentNode.RemoveChild(element);
                dirty = true;
            }

            if (dirty)
            {
                if (verbose)
                    TraceOps.Trace(traceCallback, String.Format(
                        "element = {0}", ForDisplay(element)), traceCategory);

                if (!whatIf)
                    document.Save(fileName);

                saved = true;
            }

            return true;
        }

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

        private static bool ProcessDbProviderFactory(
            string fileName,
            string invariant,
            string name,
            string description,
            string typeName,
            AssemblyName assemblyName,
            object clientData,
            bool whatIf,
            bool verbose,
            ref bool saved,
            ref string error
            )
        {
            AnyPair<string, bool> pair = clientData as AnyPair<string, bool>;

            if (pair == null)
            {
                error = "invalid framework config callback data";
                return false;
            }

            if (pair.Y)
            {
                return RemoveDbProviderFactory(
                    fileName, invariant, whatIf, verbose, ref saved,
                    ref error) &&
                AddDbProviderFactory(
                    fileName, invariant, name, description, typeName,
                    assemblyName, whatIf, verbose, ref saved, ref error);
            }
            else
            {
                return RemoveDbProviderFactory(
                    fileName, invariant, whatIf, verbose, ref saved,
                    ref error);
            }
        }
        #endregion

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

        #region Assembly Folders Handling
        private static string GetAssemblyFoldersKeyName(
            string frameworkName,
            Version frameworkVersion,
            string platformName
            )
        {
            string format = !String.IsNullOrEmpty(platformName) ?
                "Software\\Microsoft\\{0}\\v{1}\\{2}\\AssemblyFoldersEx" :
                "Software\\Microsoft\\{0}\\v{1}\\AssemblyFoldersEx";

            return String.Format(format, frameworkName, frameworkVersion,
                platformName);
        }

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

        private static bool AddToAssemblyFolders(
            RegistryKey rootKey,
            string frameworkName,
            Version frameworkVersion,
            string platformName,
            string subKeyName,
            string directory,
            bool whatIf,
            bool verbose,
            ref string error
            )
        {
            string keyName = GetAssemblyFoldersKeyName(
                frameworkName, frameworkVersion, platformName);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, true, whatIf, verbose))
            {
                if (key == null)
                {
                    error = String.Format(
                        "could not open registry key: {0}\\{1}",
                        rootKey, keyName);

                    return false;
                }

                using (MockRegistryKey subKey = RegistryHelper.CreateSubKey(
                        key, subKeyName, whatIf, verbose))
                {
                    if (subKey == null)
                    {
                        error = String.Format(
                            "could not create registry key: {0}\\{1}",
                            key, subKeyName);

                        return false;
                    }

                    RegistryHelper.SetValue(
                        subKey, null, directory, whatIf, verbose);
                }
            }

            return true;
        }

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

        private static bool RemoveFromAssemblyFolders(
            RegistryKey rootKey,
            string frameworkName,
            Version frameworkVersion,
            string platformName,
            string subKeyName,
            bool whatIf,
            bool verbose,
            ref string error
            )
        {
            string keyName = GetAssemblyFoldersKeyName(
                frameworkName, frameworkVersion, platformName);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, false, whatIf, verbose))
            {
                if (key == null)
                {
                    error = String.Format(
                        "could not open registry key: {0}\\{1}",
                        rootKey, keyName);

                    return false;
                }

                RegistryHelper.DeleteSubKey(
                    key, subKeyName, whatIf, verbose);
            }

            return true;
        }

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

        private static bool ProcessAssemblyFolders(
            RegistryKey rootKey,
            string frameworkName,
            Version frameworkVersion,
            string platformName,
            object clientData,
            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, whatIf, verbose, ref error) &&
                AddToAssemblyFolders(
                    rootKey, frameworkName, frameworkVersion, platformName,
                    ProjectName, pair.X, whatIf, verbose, ref error);
            }
            else
            {
                return RemoveFromAssemblyFolders(
                    rootKey, frameworkName, frameworkVersion, platformName,
                    ProjectName, whatIf, verbose, ref error);
            }
        }
        #endregion

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

        #region Visual Studio Handling
        private static string GetVsKeyName(
            Version vsVersion
            )
        {
            return String.Format("Software\\Microsoft\\VisualStudio\\{0}",
                vsVersion);
        }

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

        #region Visual Studio Data Source Handling
        private static bool AddVsDataSource(
            RegistryKey rootKey,
            Version vsVersion,
            Guid dataSourceId,
            Guid dataProviderId,
            bool whatIf,
            bool verbose,
            ref string error
            )
        {
            string keyName = GetVsKeyName(vsVersion);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, false, whatIf, verbose))
            {
                if (key == null)
                {
                    error = String.Format(
                        "could not open registry key: {0}\\{1}",
                        rootKey, keyName);

                    return false;
                }

                using (MockRegistryKey subKey = RegistryHelper.OpenSubKey(
                        key, "DataSources", true, whatIf, verbose))
                {
                    if (subKey == null)
                    {
                        error = String.Format(
                            "could not open registry key: {0}\\DataSources",
                            key);

                        return false;
                    }

                    using (MockRegistryKey dataSourceKey = RegistryHelper.CreateSubKey(
                            subKey, dataSourceId.ToString(VsIdFormat), whatIf,
                            verbose))
                    {
                        if (dataSourceKey == null)
                        {
                            error = String.Format(
                                "could not create registry key: {0}\\{1}",
                                key, dataSourceId.ToString(VsIdFormat));

                            return false;
                        }

                        RegistryHelper.SetValue(
                            dataSourceKey, null, String.Format(
                            "{0} Database File", ProjectName), whatIf,
                            verbose);

                        RegistryHelper.CreateSubKey(dataSourceKey,
                            String.Format("SupportingProviders\\{0}",
                            dataProviderId.ToString(VsIdFormat)), whatIf,
                            verbose);
                    }
                }
            }

            return true;
        }

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

        private static bool RemoveVsDataSource(
            RegistryKey rootKey,
            Version vsVersion,
            Guid dataSourceId,
            bool whatIf,
            bool verbose,
            ref string error
            )
        {
            string keyName = GetVsKeyName(vsVersion);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, false, whatIf, verbose))
            {
                if (key == null)
                {
                    error = String.Format(
                        "could not open registry key: {0}\\{1}",
                        rootKey, keyName);

                    return false;
                }

                using (MockRegistryKey subKey = RegistryHelper.OpenSubKey(
                        key, "DataSources", true, whatIf, verbose))
                {
                    if (subKey == null)
                    {
                        error = String.Format(
                            "could not open registry key: {0}\\DataSources",
                            key);

                        return false;
                    }

                    RegistryHelper.DeleteSubKeyTree(
                        subKey, dataSourceId.ToString(VsIdFormat), whatIf,
                        verbose);
                }
            }

            return true;
        }

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

        private static bool ProcessVsDataSource(
            RegistryKey rootKey,
            Version vsVersion,
            Guid packageId, /* NOT USED */
            Guid serviceId, /* NOT USED */
            Guid dataSourceId,
            Guid dataProviderId,
            object clientData,
            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 AddVsDataSource(
                    rootKey, vsVersion, dataSourceId, dataProviderId,
                    whatIf, verbose, ref error);
            }
            else
            {
                return RemoveVsDataSource(
                    rootKey, vsVersion, dataSourceId, whatIf, verbose,
                    ref error);
            }
        }
        #endregion

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

        #region Visual Studio Data Provider Handling
        private static bool AddVsDataProvider(
            RegistryKey rootKey,
            Version vsVersion,
            Guid serviceId,
            Guid dataProviderId,
            string fileName,
            bool whatIf,
            bool verbose,
            ref string error
            )
        {
            if (vsAdoNetTechnologyId == null)
            {
                error = "invalid ADO.NET technology Id";
                return false;
            }

            string keyName = GetVsKeyName(vsVersion);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, false, whatIf, verbose))
            {
                if (key == null)
                {
                    error = String.Format(
                        "could not open registry key: {0}\\{1}",
                        rootKey, keyName);

                    return false;
                }

                using (MockRegistryKey subKey = RegistryHelper.OpenSubKey(
                        key, "DataProviders", true, whatIf, verbose))
                {
                    if (subKey == null)
                    {
                        error = String.Format(
                            "could not open registry key: {0}\\DataProviders",
                            key);

                        return false;
                    }

                    using (MockRegistryKey dataProviderKey = RegistryHelper.CreateSubKey(
                            subKey, dataProviderId.ToString(VsIdFormat), whatIf,
                            verbose))
                    {
                        if (dataProviderKey == null)
                        {
                            error = String.Format(
                                "could not create registry key: {0}\\{1}",
                                key, dataProviderId.ToString(VsIdFormat));

                            return false;
                        }

                        RegistryHelper.SetValue(
                            dataProviderKey, null, Description, whatIf,
                            verbose);

                        RegistryHelper.SetValue(
                            dataProviderKey, "InvariantName", InvariantName,
                            whatIf, verbose);

                        RegistryHelper.SetValue(
                            dataProviderKey, "Technology",
                            ((Guid)vsAdoNetTechnologyId).ToString(VsIdFormat),
                            whatIf, verbose);

                        RegistryHelper.SetValue(
                            dataProviderKey, "CodeBase", fileName, whatIf,
                            verbose);

                        RegistryHelper.SetValue(
                            dataProviderKey, "FactoryService",
                            serviceId.ToString(VsIdFormat), whatIf, verbose);

                        RegistryHelper.CreateSubKey(dataProviderKey,
                            "SupportedObjects\\DataConnectionUIControl",
                            whatIf, verbose);

                        RegistryHelper.CreateSubKey(dataProviderKey,
                            "SupportedObjects\\DataConnectionProperties",
                            whatIf, verbose);

                        RegistryHelper.CreateSubKey(dataProviderKey,
                            "SupportedObjects\\DataConnectionSupport", whatIf,
                            verbose);

                        RegistryHelper.CreateSubKey(dataProviderKey,
                            "SupportedObjects\\DataObjectSupport", whatIf,
                            verbose);

                        RegistryHelper.CreateSubKey(dataProviderKey,
                            "SupportedObjects\\DataViewSupport", whatIf,
                            verbose);
                    }
                }
            }

            return true;
        }

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

        private static bool RemoveVsDataProvider(
            RegistryKey rootKey,
            Version vsVersion,
            Guid dataProviderId,
            bool whatIf,
            bool verbose,
            ref string error
            )
        {
            string keyName = GetVsKeyName(vsVersion);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, false, whatIf, verbose))
            {
                if (key == null)
                {
                    error = String.Format(
                        "could not open registry key: {0}\\{1}",
                        rootKey, keyName);

                    return false;
                }

                using (MockRegistryKey subKey = RegistryHelper.OpenSubKey(
                        key, "DataProviders", true, whatIf, verbose))
                {
                    if (subKey == null)
                    {
                        error = String.Format(
                            "could not open registry key: {0}\\DataProviders",
                            key);

                        return false;
                    }

                    RegistryHelper.DeleteSubKeyTree(
                        subKey, dataProviderId.ToString(VsIdFormat), whatIf,
                        verbose);
                }
            }

            return true;
        }

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

        private static bool ProcessVsDataProvider(
            RegistryKey rootKey,
            Version vsVersion,
            Guid packageId, /* NOT USED */
            Guid serviceId,
            Guid dataSourceId, /* NOT USED */
            Guid dataProviderId,
            object clientData,
            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, serviceId, dataProviderId, pair.X,
                    whatIf, verbose, ref error);
            }
            else
            {
                return RemoveVsDataProvider(
                    rootKey, vsVersion, dataProviderId, whatIf, verbose,
                    ref error);
            }
        }
        #endregion

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

        #region Visual Studio Package Handling
        private static bool AddVsPackage(
            RegistryKey rootKey,
            Version vsVersion,
            Guid packageId,
            Guid serviceId,
            string fileName,
            bool whatIf,
            bool verbose,
            ref string error
            )
        {
            string keyName = GetVsKeyName(vsVersion);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, false, whatIf, verbose))
            {
                if (key == null)
                {
                    error = String.Format(
                        "could not open registry key: {0}\\{1}",
                        rootKey, keyName);

                    return false;
                }

                using (MockRegistryKey subKey = RegistryHelper.OpenSubKey(
                        key, "Packages", true, whatIf, verbose))
                {
                    if (subKey == null)
                    {
                        error = String.Format(
                            "could not open registry key: {0}\\Packages",
                            key);

                        return false;
                    }

                    using (MockRegistryKey packageKey = RegistryHelper.CreateSubKey(
                            subKey, packageId.ToString(VsIdFormat), whatIf,
                            verbose))
                    {
                        if (packageKey == null)
                        {
                            error = String.Format(
                                "could not create registry key: {0}\\{1}",
                                key, packageId.ToString(VsIdFormat));

                            return false;
                        }

                        RegistryHelper.SetValue(packageKey, null, String.Format(
                            "{0} Designer Package", ProjectName), whatIf,
                            verbose);

                        RegistryHelper.SetValue(packageKey, "Class",
                            "SQLite.Designer.SQLitePackage", whatIf, verbose);

                        RegistryHelper.SetValue(packageKey, "CodeBase",
                            fileName, whatIf, verbose);

                        RegistryHelper.SetValue(packageKey, "ID", 400, whatIf,
                            verbose);

                        RegistryHelper.SetValue(packageKey, "InprocServer32",
                            Path.Combine(Environment.SystemDirectory,
                                "mscoree.dll"), whatIf, verbose);

                        RegistryHelper.SetValue(packageKey, "CompanyName",
                            "http://system.data.sqlite.org/", whatIf, verbose);

                        RegistryHelper.SetValue(packageKey, "MinEdition",
                            "standard", whatIf, verbose);

                        RegistryHelper.SetValue(packageKey, "ProductName",
                            String.Format("{0} Designer Package", ProjectName),
                            whatIf, verbose);

                        RegistryHelper.SetValue(packageKey, "ProductVersion",
                            "1.0", whatIf, verbose);

                        using (MockRegistryKey toolboxKey = RegistryHelper.CreateSubKey(
                                packageKey, "Toolbox", whatIf, verbose))
                        {
                            if (toolboxKey == null)
                            {
                                error = String.Format(
                                    "could not create registry key: {0}\\Toolbox",
                                    packageKey);

                                return false;
                            }

                            RegistryHelper.SetValue(
                                toolboxKey, "Default Items", 3, whatIf,
                                verbose);
                        }
                    }
                }

                using (MockRegistryKey subKey = RegistryHelper.OpenSubKey(
                        key, "Menus", true, whatIf, verbose))
                {
                    if (subKey == null)
                    {
                        error = String.Format(
                            "could not open registry key: {0}\\Menus",
                            key);

                        return false;
                    }

                    RegistryHelper.SetValue(
                        subKey, packageId.ToString(VsIdFormat), ", 1000, 3",
                        whatIf, verbose);
                }

                using (MockRegistryKey subKey = RegistryHelper.OpenSubKey(
                        key, "Services", true, whatIf, verbose))
                {
                    if (subKey == null)
                    {
                        error = String.Format(
                            "could not open registry key: {0}\\Services",
                            key);

                        return false;
                    }

                    using (MockRegistryKey serviceKey = RegistryHelper.CreateSubKey(
                            subKey, serviceId.ToString(VsIdFormat), whatIf,
                            verbose))
                    {
                        if (serviceKey == null)
                        {
                            error = String.Format(
                                "could not create registry key: {0}\\{1}",
                                key, serviceId.ToString(VsIdFormat));

                            return false;
                        }

                        RegistryHelper.SetValue(serviceKey, null,
                            packageId.ToString(VsIdFormat), whatIf, verbose);

                        RegistryHelper.SetValue(serviceKey, "Name",
                            String.Format("{0} Designer Service", ProjectName),
                            whatIf, verbose);
                    }
                }
            }

            return true;
        }

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

        private static bool RemoveVsPackage(
            RegistryKey rootKey,
            Version vsVersion,
            Guid packageId,
            Guid serviceId,
            bool whatIf,
            bool verbose,
            ref string error
            )
        {
            string keyName = GetVsKeyName(vsVersion);

            using (MockRegistryKey key = RegistryHelper.OpenSubKey(
                    rootKey, keyName, false, whatIf, verbose))
            {
                if (key == null)
                {
                    error = String.Format(
                        "could not open registry key: {0}\\{1}",
                        rootKey, keyName);

                    return false;
                }

                using (MockRegistryKey subKey = RegistryHelper.OpenSubKey(
                        key, "Packages", true, whatIf, verbose))
                {
                    if (subKey == null)
                    {
                        error = String.Format(
                            "could not open registry key: {0}\\Packages",
                            key);

                        return false;
                    }

                    RegistryHelper.DeleteSubKeyTree(
                        key, packageId.ToString(VsIdFormat), whatIf, verbose);
                }

                using (MockRegistryKey subKey = RegistryHelper.OpenSubKey(
                        key, "Menus", true, whatIf, verbose))
                {
                    if (subKey == null)
                    {
                        error = String.Format(
                            "could not open registry key: {0}\\Menus",
                            key);

                        return false;
                    }

                    RegistryHelper.DeleteValue(
                        subKey, packageId.ToString(VsIdFormat), whatIf,
                        verbose);
                }

                using (MockRegistryKey subKey = RegistryHelper.OpenSubKey(
                        key, "Services", true, whatIf, verbose))
                {
                    if (subKey == null)
                    {
                        error = String.Format(
                            "could not open registry key: {0}\\Services",
                            key);

                        return false;
                    }

                    RegistryHelper.DeleteSubKeyTree(
                        subKey, serviceId.ToString(VsIdFormat), whatIf,
                        verbose);
                }
            }

            return true;
        }

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

        private static bool ProcessVsPackage(
            RegistryKey rootKey,
            Version vsVersion,
            Guid packageId,
            Guid serviceId,
            Guid dataSourceId,
            Guid dataProviderId,
            object clientData,
            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, packageId, serviceId, pair.X, whatIf,
                    verbose, ref error);
            }
            else
            {
                return RemoveVsPackage(
                    rootKey, vsVersion, packageId, serviceId, whatIf, verbose,
                    ref error);
            }
        }
        #endregion
        #endregion

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

        #region Application Entry Point
        private static int Main(string[] args)
        {
            Configuration configuration = null;
            string error = null;

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

            #region Command Line Processing
            if (!Configuration.FromArgs(
                    args, true, ref configuration, ref error) ||
                !Configuration.Process(
                    args, configuration, true, ref error))
            {
                TraceOps.ShowMessage(
                    traceCallback, thisAssembly, error, traceCategory,
                    MessageBoxButtons.OK, MessageBoxIcon.Error);

                return 1;
            }

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

            InitializeAllFrameworks(configuration);
            InitializeAllVsVersions(configuration);
            #endregion

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

            AnyPair<string, bool> directoryPair = new AnyPair<string, bool>(
                configuration.Directory, configuration.Install);

            AnyPair<string, bool> fileNamePair = new AnyPair<string, bool>(
                configuration.DesignerFileName, configuration.Install);

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

            #region .NET GAC Install/Remove
            if (configuration.HasFlags(InstallFlags.GAC, true))
            {
                Publish publish = new Publish();

                if (configuration.Install)
                {
                    if (!configuration.WhatIf)
                    {
                        publish.GacInstall(configuration.CoreFileName); /* throw */
                        publish.GacInstall(configuration.LinqFileName); /* throw */
                    }
                    else
                    {
                        TraceOps.Trace(traceCallback, String.Format(
                            "GacInstall: assemblyPath = {0}",
                            configuration.CoreFileName), traceCategory);

                        TraceOps.Trace(traceCallback, String.Format(
                            "GacInstall: assemblyPath = {0}",
                            configuration.LinqFileName), traceCategory);
                    }
                }
                else
                {
                    if (!configuration.WhatIf)
                    {
                        publish.GacRemove(configuration.LinqFileName); /* throw */
                        publish.GacRemove(configuration.CoreFileName); /* throw */
                    }
                    else
                    {
                        TraceOps.Trace(traceCallback, String.Format(
                            "GacRemove: assemblyPath = {0}",
                            configuration.LinqFileName), traceCategory);

                        TraceOps.Trace(traceCallback, String.Format(
                            "GacRemove: assemblyPath = {0}",
                            configuration.CoreFileName), traceCategory);
                    }
                }
            }
            #endregion

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

            #region .NET AssemblyFolders
            if (configuration.HasFlags(InstallFlags.AssemblyFolders, true))
            {
                if (!ForEachFrameworkRegistry(ProcessAssemblyFolders,
                        directoryPair, configuration.WhatIf,
                        configuration.Verbose, ref error))
                {
                    TraceOps.ShowMessage(
                        traceCallback, null, error, traceCategory,
                        MessageBoxButtons.OK, MessageBoxIcon.Error);

                    return 1;
                }
            }
            #endregion

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

            #region .NET DbProviderFactory
            if (configuration.HasFlags(InstallFlags.DbProviderFactory, true))
            {
                bool saved = false;

                if (!ForEachFrameworkConfig(ProcessDbProviderFactory,
                        InvariantName, ProviderName, Description,
                        FactoryTypeName, AssemblyName.GetAssemblyName(
                            configuration.CoreFileName), directoryPair,
                        configuration.WhatIf, configuration.Verbose,
                        ref saved, ref error))
                {
                    TraceOps.ShowMessage(
                        traceCallback, null, error, traceCategory,
                        MessageBoxButtons.OK, MessageBoxIcon.Error);

                    return 1;
                }
            }
            #endregion

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

            #region VS Package
            if (configuration.HasFlags(InstallFlags.VsPackage, true))
            {
                if (!ForEachVsVersionRegistry(ProcessVsPackage,
                        (Guid)vsPackageId, (Guid)vsServiceId,
                        (Guid)vsDataSourcesId, (Guid)vsDataProviderId,
                        fileNamePair, configuration.WhatIf,
                        configuration.Verbose, ref error))
                {
                    TraceOps.ShowMessage(
                        traceCallback, null, error, traceCategory,
                        MessageBoxButtons.OK, MessageBoxIcon.Error);

                    return 1;
                }
            }
            #endregion

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

            #region VS DataSource
            if (configuration.HasFlags(InstallFlags.VsDataSource, true))
            {
                if (!ForEachVsVersionRegistry(ProcessVsDataSource,
                        (Guid)vsPackageId, (Guid)vsServiceId,
                        (Guid)vsDataSourcesId, (Guid)vsDataProviderId,
                        fileNamePair, configuration.WhatIf,
                        configuration.Verbose, ref error))
                {
                    TraceOps.ShowMessage(
                        traceCallback, null, error, traceCategory,
                        MessageBoxButtons.OK, MessageBoxIcon.Error);

                    return 1;
                }
            }
            #endregion

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

            #region VS DataProvider
            if (configuration.HasFlags(InstallFlags.VsDataProvider, true))
            {
                if (!ForEachVsVersionRegistry(ProcessVsDataProvider,
                        (Guid)vsPackageId, (Guid)vsServiceId,
                        (Guid)vsDataSourcesId, (Guid)vsDataProviderId,
                        fileNamePair, configuration.WhatIf,
                        configuration.Verbose, ref error))
                {
                    TraceOps.ShowMessage(
                        traceCallback, null, error, traceCategory,
                        MessageBoxButtons.OK, MessageBoxIcon.Error);

                    return 1;
                }
            }
            #endregion

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

            TraceOps.Trace(traceCallback, String.Format(
                "subKeysCreated = {0}, subKeysDeleted = {1}, " +
                "keyValuesSet = {2}, keyValuesDeleted = {3}",
                RegistryHelper.SubKeysCreated, RegistryHelper.SubKeysDeleted,
                RegistryHelper.KeyValuesSet, RegistryHelper.KeyValuesDeleted),
                traceCategory);

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

            return 0;
        }
        #endregion
    }
    #endregion
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































Added tools/install/Program.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
using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace install
{
  static class Program
  {
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
      Application.EnableVisualStyles();
      Application.SetCompatibleTextRenderingDefault(false);
      Environment.CurrentDirectory = System.IO.Path.GetDirectoryName(Application.ExecutablePath);

      InstallDesigner designer = new InstallDesigner();
      if (designer._remove == false)
        designer.ShowDialog();
    }
  }
}
Changes to tools/install/Properties/AssemblyInfo.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
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following 
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("System.Data.SQLite Designer Installer")]

[assembly: AssemblyDescription("ADO.NET Data Provider for SQLite")]
[assembly: AssemblyCompany("http://system.data.sqlite.org/")]
[assembly: AssemblyProduct("System.Data.SQLite")]
[assembly: AssemblyCopyright("Public Domain")]

#if DEBUG
[assembly: AssemblyConfiguration("Debug")]
#else
[assembly: AssemblyConfiguration("Release")]
#endif

// Setting ComVisible to false makes the types in this assembly not visible 
// to COM components.  If you need to access a type in this assembly from 
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version 
//      Build Number
//      Revision
//
[assembly: AssemblyVersion("1.0.76.0")]
[assembly: AssemblyFileVersion("1.0.76.0")]







|
>
|
|
|

<
<
|
<
|
<













|
|
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
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following 
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SQLite.Designer Installer")]
[assembly: AssemblyDescription("SQLite ADO.NET Design-Time Installer")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("http://system.data.sqlite.org")]
[assembly: AssemblyProduct("SQLite Installer")]
[assembly: AssemblyCopyright("Public Domain")]


[assembly: AssemblyTrademark("")]

[assembly: AssemblyCulture("")]


// Setting ComVisible to false makes the types in this assembly not visible 
// to COM components.  If you need to access a type in this assembly from 
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version 
//      Build Number
//      Revision
//
[assembly: AssemblyVersion("1.0.0.*")]
[assembly: AssemblyFileVersion("1.0.0.0")]
Added tools/install/Properties/Resources.Designer.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
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.1
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace install.Properties {
    using System;
    
    
    /// <summary>
    ///   A strongly-typed resource class, for looking up localized strings, etc.
    /// </summary>
    // This class was auto-generated by the StronglyTypedResourceBuilder
    // class via a tool like ResGen or Visual Studio.
    // To add or remove a member, edit your .ResX file then rerun ResGen
    // with the /str option, or rebuild your VS project.
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    internal class Resources {
        
        private static global::System.Resources.ResourceManager resourceMan;
        
        private static global::System.Globalization.CultureInfo resourceCulture;
        
        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
        internal Resources() {
        }
        
        /// <summary>
        ///   Returns the cached ResourceManager instance used by this class.
        /// </summary>
        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
        internal static global::System.Resources.ResourceManager ResourceManager {
            get {
                if (object.ReferenceEquals(resourceMan, null)) {
                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("install.Properties.Resources", typeof(Resources).Assembly);
                    resourceMan = temp;
                }
                return resourceMan;
            }
        }
        
        /// <summary>
        ///   Overrides the current thread's CurrentUICulture property for all
        ///   resource lookups using this strongly typed resource class.
        /// </summary>
        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
        internal static global::System.Globalization.CultureInfo Culture {
            get {
                return resourceCulture;
            }
            set {
                resourceCulture = value;
            }
        }
        
        internal static byte[] System_Data_SQLite {
            get {
                object obj = ResourceManager.GetObject("System_Data_SQLite", resourceCulture);
                return ((byte[])(obj));
            }
        }
    }
}
Added tools/install/Properties/Resources.resx.
























































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
<?xml version="1.0" encoding="utf-8"?>
<root>
  <!-- 
    Microsoft ResX Schema 
    
    Version 2.0
    
    The primary goals of this format is to allow a simple XML format 
    that is mostly human readable. The generation and parsing of the 
    various data types are done through the TypeConverter classes 
    associated with the data types.
    
    Example:
    
    ... ado.net/XML headers & schema ...
    <resheader name="resmimetype">text/microsoft-resx</resheader>
    <resheader name="version">2.0</resheader>
    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
        <value>[base64 mime encoded serialized .NET Framework object]</value>
    </data>
    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
        <comment>This is a comment</comment>
    </data>
                
    There are any number of "resheader" rows that contain simple 
    name/value pairs.
    
    Each data row contains a name, and value. The row also contains a 
    type or mimetype. Type corresponds to a .NET class that support 
    text/value conversion through the TypeConverter architecture. 
    Classes that don't support this are serialized and stored with the 
    mimetype set.
    
    The mimetype is used for serialized objects, and tells the 
    ResXResourceReader how to depersist the object. This is currently not 
    extensible. For a given mimetype the value must be set accordingly:
    
    Note - application/x-microsoft.net.object.binary.base64 is the format 
    that the ResXResourceWriter will generate, however the reader can 
    read any of the formats listed below.
    
    mimetype: application/x-microsoft.net.object.binary.base64
    value   : The object must be serialized with 
            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
            : and then encoded with base64 encoding.
    
    mimetype: application/x-microsoft.net.object.soap.base64
    value   : The object must be serialized with 
            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
            : and then encoded with base64 encoding.

    mimetype: application/x-microsoft.net.object.bytearray.base64
    value   : The object must be serialized into a byte array 
            : using a System.ComponentModel.TypeConverter
            : and then encoded with base64 encoding.
    -->
  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
    <xsd:element name="root" msdata:IsDataSet="true">
      <xsd:complexType>
        <xsd:choice maxOccurs="unbounded">
          <xsd:element name="metadata">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" />
              </xsd:sequence>
              <xsd:attribute name="name" use="required" type="xsd:string" />
              <xsd:attribute name="type" type="xsd:string" />
              <xsd:attribute name="mimetype" type="xsd:string" />
              <xsd:attribute ref="xml:space" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="assembly">
            <xsd:complexType>
              <xsd:attribute name="alias" type="xsd:string" />
              <xsd:attribute name="name" type="xsd:string" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="data">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
              <xsd:attribute ref="xml:space" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="resheader">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" use="required" />
            </xsd:complexType>
          </xsd:element>
        </xsd:choice>
      </xsd:complexType>
    </xsd:element>
  </xsd:schema>
  <resheader name="resmimetype">
    <value>text/microsoft-resx</value>
  </resheader>
  <resheader name="version">
    <value>2.0</value>
  </resheader>
  <resheader name="reader">
    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <resheader name="writer">
    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
  <data name="System_Data_SQLite" type="System.Resources.ResXFileRef, System.Windows.Forms">
    <value>..\Resources\System.Data.SQLite.dll;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </data>
</root>
Added tools/install/Resources/System.Data.SQLite.dll.

cannot compute difference between binary files

Added tools/install/app.config.






>
>
>
1
2
3
<?xml version="1.0"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client"/></startup></configuration>
Added tools/install/install.exe.manifest.
























>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity version="1.0.0.0" processorArchitecture="X86" name="install" type="win32"/>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="requireAdministrator"/>
      </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>

Added tools/install/install.ico.

cannot compute difference between binary files

Added tools/mergebin/MetaData.cpp.












































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/********************************************************
 * mergebin
 * Written by Robert Simpson (robert@blackcastlesoft.com)
 * 
 * Released to the public domain, use at your own risk!
 ********************************************************/

#include "StdAfx.h"
#include "MetaData.h"

CMetadata::CStream::operator LPBYTE() const
{
  return m_pbData;
}

CMetadata::CMetadata(CPEFile& peFile) : m_peFile(peFile)
{
  PIMAGE_COR20_HEADER pCor = m_peFile;
  if (!pCor) throw;

  LPBYTE pb = (LPBYTE)m_peFile.GetPtrFromRVA(pCor->MetaData.VirtualAddress);
  LPBYTE pbRoot = pb;
  size_t x;
  if (!pb) throw;

  m_pdwSignature     = (LPDWORD)pb;
  m_pwMajorVersion   = (LPWORD)(m_pdwSignature + 1);
  m_pwMinorVersion   = m_pwMajorVersion + 1;
  m_pdwVersionLength = (LPDWORD)(m_pwMinorVersion + 3);
  m_pszVersion       = (LPSTR)(m_pdwVersionLength + 1);

  pb = (LPBYTE)m_pszVersion;
  x = *m_pdwVersionLength;
  if (x % 4) x += 4 - (x % 4);
  pb += x;
  pb += 2;
  
  m_pwStreams        = (LPWORD)pb;
  m_pStreams = new CStream[*m_pwStreams];
  pb = (LPBYTE)(m_pwStreams + 1);

  for (WORD n = 0; n < *m_pwStreams; n++)
  {
    m_pStreams[n].m_pdwOffset  = (LPDWORD)pb;
    m_pStreams[n].m_pdwSize    = m_pStreams[n].m_pdwOffset + 1;
    m_pStreams[n].m_pszName    = (LPSTR)(m_pStreams[n].m_pdwSize + 1);
    m_pStreams[n].m_pbData     = pbRoot + (*m_pStreams[n].m_pdwOffset);

    x = strlen(m_pStreams[n].m_pszName) + 1;
    if (x % 4) x += 4 - (x % 4);

    pb = (LPBYTE)m_pStreams[n].m_pszName + x;
  }
}

CMetadata::~CMetadata(void)
{
  delete[] m_pStreams;
}

CMetadata::operator CPEFile&() const
{
  return m_peFile;
}

CMetadata::CStream * CMetadata::GetStream(UINT uiStream)
{
  if (uiStream >= *m_pwStreams) return NULL;
  return &m_pStreams[uiStream];
}

CMetadata::CStream * CMetadata::GetStream(LPCSTR pszStreamName)
{
  for (WORD n = 0; n < *m_pwStreams; n++)
  {
    if (_stricmp(pszStreamName, m_pStreams[n].m_pszName) == 0)
      return &m_pStreams[n];
  }
  return NULL;
}

WORD * CMetadata::StreamCount() const
{
  return m_pwStreams;
}

Added tools/mergebin/MetaData.h.
































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/********************************************************
 * mergebin
 * Written by Robert Simpson (robert@blackcastlesoft.com)
 * 
 * Released to the public domain, use at your own risk!
 ********************************************************/

#pragma once

#include "pefile.h"

class CMetadata
{
public:
  class CStream
  {
    friend CMetadata;
  public:
    operator LPBYTE() const;

  protected:
    DWORD *m_pdwOffset;
    DWORD *m_pdwSize;
    LPSTR  m_pszName;
    LPBYTE m_pbData;
  };
public:
  CMetadata(CPEFile& peFile);
  virtual ~CMetadata(void);

protected:
  CPEFile& m_peFile;

  DWORD   *m_pdwSignature;
  WORD    *m_pwMajorVersion;
  WORD    *m_pwMinorVersion;
  DWORD   *m_pdwVersionLength;
  LPSTR    m_pszVersion;
  WORD    *m_pwStreams;
  CStream *m_pStreams;

public:
  operator CPEFile&() const;

  WORD *               StreamCount () const;
  CMetadata::CStream * GetStream   (UINT uiStream);
  CMetadata::CStream * GetStream   (LPCSTR pszStreamName);
};
Added tools/mergebin/MetaDataTables.cpp.




















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/********************************************************
 * mergebin
 * Written by Robert Simpson (robert@blackcastlesoft.com)
 * 
 * Released to the public domain, use at your own risk!
 ********************************************************/

#include "StdAfx.h"
#include "MetaDataTables.h"
#include "TableData.h"

CMetadataTables::CMetadataTables(CMetadata& metaData) : m_meta(metaData)
{
  CMetadata::CStream *ps = m_meta.GetStream("#~");
  if (!ps) throw;

  *static_cast<CMetadata::CStream *>(this) = *ps;

  LPBYTE pb = m_pbData + sizeof(DWORD);
  m_pbMajorVersion = pb;
  m_pbMinorVersion = m_pbMajorVersion + 1;
  m_pbHeapOffsetSizes = m_pbMinorVersion + 1;
  // Skip a byte
  m_pullMaskValid = (UINT64 *)(m_pbHeapOffsetSizes + 2);
  m_pullMaskSorted = m_pullMaskValid + 1;

  m_pdwTableLengths = (LPDWORD)(m_pullMaskSorted + 1);

  m_dwTables = 0;
  for (int n = 0; n < 64; n++)
  {
    if ((((*m_pullMaskValid) >> n) & 1) == 1)
    {
      m_pdwTableLengthIndex[n] = &m_pdwTableLengths[m_dwTables ++];
    }
    else
    {
      m_pdwTableLengthIndex[n] = NULL;
    }
  }
  m_pbData = (LPBYTE)(m_pdwTableLengths + m_dwTables);

  for (int n = 0; n < 64; n++)
  {
    if (m_pdwTableLengthIndex[n] && g_arTableTypes[n])
    {
      m_pTables[n] = g_arTableTypes[n](this);
    }
    else
      m_pTables[n] = 0;
  }
}

CMetadataTables::~CMetadataTables(void)
{
  for (int n = 0; n < 64; n++)
  {
    if (m_pTables[n])
      delete m_pTables[n];
  }
}

UINT CMetadataTables::GetStringIndexSize(void)
{
  return ((*m_pbHeapOffsetSizes) & 0x01) == 0 ? sizeof(WORD) : sizeof(DWORD);
}

UINT CMetadataTables::GetGuidIndexSize(void)
{
  return ((*m_pbHeapOffsetSizes) & 0x02) == 0 ? sizeof(WORD) : sizeof(DWORD);
}

UINT CMetadataTables::GetBlobIndexSize(void)
{
  return ((*m_pbHeapOffsetSizes) & 0x04) == 0 ? sizeof(WORD) : sizeof(DWORD);
}

DWORD *CMetadataTables::TableRowCount(UINT uType)
{
  return m_pdwTableLengthIndex[uType];
}

DWORD CMetadataTables::GetMaxIndexSizeOf(UINT * puiTables)
{
  DWORD dwMaxRows = 0;
  DWORD *pdwLength;
  UINT uCount = 0;

  while (*puiTables)
  {
    uCount ++;
    pdwLength = m_pdwTableLengthIndex[*puiTables];
    if (pdwLength)
      dwMaxRows = max(dwMaxRows, pdwLength[0]);

    puiTables ++;
  }

  return (dwMaxRows > 0xFFFF) ? 4 : 2;
  //return (dwMaxRows > (ULONG)(2 << (16 - uCount))) ? 4 : 2;
}

CTableData *CMetadataTables::GetTable(UINT uId)
{
  return m_pTables[uId];
}
Added tools/mergebin/MetaDataTables.h.


























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/********************************************************
 * mergebin
 * Written by Robert Simpson (robert@blackcastlesoft.com)
 * 
 * Released to the public domain, use at your own risk!
 ********************************************************/

#pragma once
#include "metadata.h"

class CTableData;

class CMetadataTables :
  public CMetadata::CStream
{
  friend CTableData;

public:
  CMetadataTables(CMetadata& metaData);
  virtual ~CMetadataTables(void);

protected:
  CMetadata&  m_meta;
  BYTE       *m_pbMajorVersion;
  BYTE       *m_pbMinorVersion;
  BYTE       *m_pbHeapOffsetSizes;
  UINT64     *m_pullMaskValid;
  UINT64     *m_pullMaskSorted;
  DWORD      *m_pdwTableLengths;

  DWORD      *m_pdwTableLengthIndex[64];
  DWORD       m_dwTables;

  CTableData *m_pTables[64];

public:
  UINT        GetStringIndexSize ();
  UINT        GetGuidIndexSize   ();
  UINT        GetBlobIndexSize   ();
  DWORD       GetMaxIndexSizeOf  (UINT *);

  DWORD *     TableRowCount      (UINT uType);

  CTableData *GetTable           (UINT uId);
};
Added tools/mergebin/PEFile.cpp.
















































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/********************************************************
 * mergebin
 * Written by Robert Simpson (robert@blackcastlesoft.com)
 * 
 * Released to the public domain, use at your own risk!
 ********************************************************/

#include "StdAfx.h"
#include "PEFile.h"

#define MakePtr( cast, ptr, addValue ) (cast)( (DWORD_PTR)(ptr) + (DWORD_PTR)(addValue))

CPEFile::CPEFile(void)
{
  m_hMap = NULL;
  m_hFile = INVALID_HANDLE_VALUE;
  m_pBase = NULL;
}

CPEFile::~CPEFile(void)
{
  Close();
}

HRESULT CPEFile::Open(LPCTSTR pszFile, BOOL bReadOnly)
{
  HRESULT hr = S_OK;
  Close();

  m_hFile = CreateFile(pszFile, GENERIC_READ | ((bReadOnly == FALSE) ? GENERIC_WRITE: 0), FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  if (m_hFile == INVALID_HANDLE_VALUE)
  {
    hr = HRESULT_FROM_WIN32(GetLastError());
  }
  else
  {
    m_hMap = CreateFileMapping(m_hFile, NULL, (bReadOnly == TRUE) ? PAGE_READONLY:PAGE_READWRITE, 0, 0, NULL);
    if (!m_hMap)
    {
      hr = HRESULT_FROM_WIN32(GetLastError());
    }
    else
    {
      m_pBase = (PIMAGE_DOS_HEADER)MapViewOfFile(m_hMap, FILE_MAP_READ | ((bReadOnly == FALSE) ? FILE_MAP_WRITE:0), 0, 0, 0);
      if (!m_pBase)
      {
        hr = HRESULT_FROM_WIN32(GetLastError());
      }
    }
  }

  if (SUCCEEDED(hr))
  {
    PIMAGE_FILE_HEADER pImageHeader = (PIMAGE_FILE_HEADER)m_pBase;
    if (m_pBase->e_magic != IMAGE_DOS_SIGNATURE)
    {
      hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
    }

    m_pNTHeader = MakePtr(PIMAGE_NT_HEADERS, m_pBase, m_pBase->e_lfanew);
    if (IsBadReadPtr(m_pNTHeader, sizeof(m_pNTHeader->Signature)))
    {
      hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
    }
    else
    {
      if (m_pNTHeader->Signature != IMAGE_NT_SIGNATURE)
      {
        hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
      }
    }
    m_bIs64Bit = (m_pNTHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC);
  }

  if (FAILED(hr)) Close();

  return hr;
}

void CPEFile::Close(void)
{
  if (m_pBase)
  {
    UnmapViewOfFile(m_pBase);
  }

  if (m_hMap)
    CloseHandle(m_hMap);

  if (m_hFile != INVALID_HANDLE_VALUE)
    CloseHandle(m_hFile);

  m_hMap = NULL;
  m_hFile = INVALID_HANDLE_VALUE;
  m_pBase = NULL;
}

PIMAGE_SECTION_HEADER CPEFile::GetEnclosingSectionHeader(DWORD rva) const
{
  PIMAGE_SECTION_HEADER section;
  
  if (m_bIs64Bit)
    section = IMAGE_FIRST_SECTION((PIMAGE_NT_HEADERS64)m_pNTHeader);
  else
    section = IMAGE_FIRST_SECTION(m_pNTHeader);

  for (UINT i=0; i < m_pNTHeader->FileHeader.NumberOfSections; i++, section++ )
  {
    DWORD size = section->Misc.VirtualSize;
    if (!size)
      size = section->SizeOfRawData;

    if ( (rva >= section->VirtualAddress) && 
      (rva < (section->VirtualAddress + size)))
      return section;
  }
  return NULL;
}

LPVOID CPEFile::GetPtrFromRVA(DWORD rva) const
{
  PIMAGE_SECTION_HEADER pSectionHdr;
  INT delta;

  pSectionHdr = GetEnclosingSectionHeader(rva);
  if ( !pSectionHdr )
    return 0;

  delta = (INT)(pSectionHdr->VirtualAddress-pSectionHdr->PointerToRawData);
  return (PVOID) (((LPBYTE)m_pBase) + rva - delta);
}

PIMAGE_SECTION_HEADER CPEFile::GetSectionHeader(LPCSTR name) const
{
  PIMAGE_SECTION_HEADER section;
  
  if (m_bIs64Bit)
    section = IMAGE_FIRST_SECTION((PIMAGE_NT_HEADERS64)m_pNTHeader);
  else
    section = IMAGE_FIRST_SECTION(m_pNTHeader);

  for (UINT i=0; i < m_pNTHeader->FileHeader.NumberOfSections; i++, section++)
  {
    if (_strnicmp((char *)section->Name,name,IMAGE_SIZEOF_SHORT_NAME) == 0)
      return section;
  }

  return NULL;
}

CPEFile::operator PIMAGE_NT_HEADERS32() const
{
  if (!m_pBase || m_bIs64Bit) return NULL;
  return m_pNTHeader;
}

CPEFile::operator PIMAGE_NT_HEADERS64() const
{
  if (!m_pBase || !m_bIs64Bit) return NULL;
  return (PIMAGE_NT_HEADERS64)m_pNTHeader;
}

CPEFile::operator PIMAGE_DOS_HEADER() const
{
  return m_pBase;
}

CPEFile::operator PIMAGE_COR20_HEADER() const
{
  if (!m_pBase) return NULL;

  DWORD dwRVA;

  if (m_bIs64Bit)
    dwRVA = ((PIMAGE_NT_HEADERS64)m_pNTHeader)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress;
  else
    dwRVA = m_pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress;
  if (!dwRVA)
  {
    return NULL;
  }

  return ((PIMAGE_COR20_HEADER)GetPtrFromRVA(dwRVA));
}
Added tools/mergebin/PEFile.h.






































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/********************************************************
 * mergebin
 * Written by Robert Simpson (robert@blackcastlesoft.com)
 * 
 * Released to the public domain, use at your own risk!
 ********************************************************/

#pragma once

class CPEFile
{
public:
  CPEFile();
  virtual ~CPEFile(void);

protected:
  HANDLE              m_hMap;
  HANDLE              m_hFile;
  PIMAGE_DOS_HEADER   m_pBase;
  PIMAGE_NT_HEADERS32 m_pNTHeader;
  BOOL                m_bIs64Bit;

public:
  HRESULT Open  (LPCTSTR pszFile, BOOL bReadOnly = TRUE);
  void    Close (void);

  PIMAGE_SECTION_HEADER GetEnclosingSectionHeader (DWORD rva) const;
  LPVOID                GetPtrFromRVA             (DWORD rva) const;
  PIMAGE_SECTION_HEADER GetSectionHeader          (LPCSTR name) const;
  
  operator PIMAGE_DOS_HEADER   () const;
  operator PIMAGE_NT_HEADERS32 () const;
  operator PIMAGE_NT_HEADERS64 () const;
  operator PIMAGE_COR20_HEADER () const;
};
Added tools/mergebin/StreamTable.cpp.




























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
#include "StdAfx.h"
#include "StreamTable.h"

CREATEINSTANCE g_arTableTypes[64] = {
  CStreamTable::CreateInstance<CModuleTable>,
  CStreamTable::CreateInstance<CTypeRefTable>,
  CStreamTable::CreateInstance<CTypeDefTable>,
  NULL,
};

CStreamTable::CStreamTable(CMetadataTables& tables) : m_tables(tables)
{
}

CStreamTable::~CStreamTable(void)
{
}

template<class C>
static CStreamTable * CALLBACK CStreamTable::CreateInstance(CMetadataTables *ptables)
{
  CStreamTable *p = new C(*ptables);
  p->Init();

  return p;
}

void CStreamTable::Init()
{
  m_pbData = m_tables.m_pbData;
  CStreamTable *p;

  for (UINT n = 0; n < GetType(); n++)
  {
    p = m_tables.GetTable(n);
    if (p)
    {
      m_pbData += (p->GetRowSize() * p->GetRowCount());
    }
  }
}

DWORD CStreamTable::GetRowCount()
{
  return *m_tables.TableRowCount(GetType());
}

UINT CStreamTable::GetRowSize()
{
  TABLE_COLUMN *pc = GetColumns();
  UINT ulen = 0;

  while (pc->uSize)
  {
    ulen += pc->uSize;
    pc ++;
  }

  return ulen;
}

UINT CStreamTable::GetColumnCount()
{
  TABLE_COLUMN *pc = GetColumns();
  UINT ucount = 0;

  while (pc->uSize)
  {
    ucount ++;
    pc ++;
  }
  return ucount;
}

LPBYTE CStreamTable::operator[](UINT uRow)
{
  return m_pbData + (uRow * GetRowSize());
}
Added tools/mergebin/StreamTable.h.




























































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
#pragma once
#include "MetaDataTables.h"

typedef enum TableTypes
{
  ttModule = 0,
  ttTypeRef = 1,
  ttTypeDef = 2,
  ttFieldPtr = 3, 
  ttField = 4,
  ttMethodPtr = 5,
  ttMethodDef = 6,
  ttParamPtr = 7, 
  ttParam = 8,
  ttInterfaceImpl = 9,
  ttMemberRef = 10,
  ttConstant = 11, 
  ttCustomAttribute = 12,
  ttFieldMarshal = 13,
  ttPermission = 14,
  ttClassLayout = 15, 
  ttFieldLayout = 16,
  ttStandAloneSig = 17,
  ttEventMap = 18,
  ttEventPtr = 19, 
  ttEvent = 20,
  ttPropertyMap = 21,
  ttPropertyPtr = 22,
  ttProperty = 23, 
  ttMethodSemantics = 24,
  ttMethodImpl = 25,
  ttModuleRef = 26,
  ttTypeSpec = 27, 
  ttImplMap = 28, //lidin book is wrong again here?  It has enclog at 28
  ttFieldRVA = 29,
  ttENCLog = 30,
  ttENCMap = 31, 
  ttAssembly = 32,
  ttAssemblyProcessor= 33,
  ttAssemblyOS = 34,
  ttAssemblyRef = 35, 
  ttAssemblyRefProcessor = 36,
  ttAssemblyRefOS = 37,
  ttFile = 38,
  ttExportedType = 39, 
  ttManifestResource = 40,
  ttNestedClass = 41,
  ttTypeTyPar = 42,
  ttMethodTyPar = 43,
} TableTypes;

#define STRING_INDEXSIZE (m_tables.GetStringIndexSize())
#define GUID_INDEXSIZE (m_tables.GetGuidIndexSize())
#define BLOB_INDEXSIZE (m_tables.GetBlobIndexSize())
#define TABLE_ROWCOUNT(x) (m_tables.TableRowCount(x)[0])
#define TABLE_INDEXSIZE(x) (TABLE_ROWCOUNT(x) > 65535 ? 4 : 2)
#define MAX_INDEXSIZE(x) (m_tables.GetMaxIndexSizeOf(x))

class CStreamTable;

typedef CStreamTable* (CALLBACK* CREATEINSTANCE)(CMetadataTables *);

#define DECLARE_TABLE(classname, typ, nam) \
  public: \
  classname##(CMetadataTables& tables) : CStreamTable(tables) {} \
  UINT GetType() { return typ; } \
  LPCTSTR GetName() { return _T(nam); }

typedef struct TABLE_COLUMN
{
  UINT uSize;
  LPCTSTR pszName;
} TABLE_COLUMNS;

#define BEGIN_COLUMN_MAP() \
  protected: \
  TABLE_COLUMN *GetColumns() \
  { \
    static TABLE_COLUMN map[] = {

#define END_COLUMN_MAP() \
      { 0, NULL } \
    }; \
    return map; \
  }

#define COLUMN_ENTRY(name, size) { size, _T(name) },

class CStreamTable
{
public:
  CStreamTable(CMetadataTables& tables);
  virtual ~CStreamTable(void);

  DWORD GetRowCount();
  LPBYTE operator[](UINT uRow);

  virtual UINT GetType() = 0;
  virtual LPCTSTR GetName() = 0;

  template<class C> static CStreamTable * CALLBACK CreateInstance(CMetadataTables *ptables);

protected:
  CMetadataTables& m_tables;
  LPBYTE m_pbData;

  virtual UINT GetRowSize();
  virtual UINT GetColumnCount();

  virtual TABLE_COLUMN *GetColumns() = 0;

private:
  void Init();
};

class CModuleTable : public CStreamTable
{
  DECLARE_TABLE(CModuleTable, ttModule, "Module")
  
  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("Generation", sizeof(WORD))
    COLUMN_ENTRY("Name",       STRING_INDEXSIZE)
    COLUMN_ENTRY("Mvid",       GUID_INDEXSIZE)
    COLUMN_ENTRY("EncId",      GUID_INDEXSIZE)
    COLUMN_ENTRY("EncBaseId",  GUID_INDEXSIZE)
  END_COLUMN_MAP()
};

static UINT ResolutionScopeIndex[] = {ttModule, ttModuleRef, ttAssemblyRef, ttTypeRef, 0};

class CTypeRefTable : public CStreamTable
{
  DECLARE_TABLE(CTypeRefTable, ttTypeRef, "TypeRef")

  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("ResolutionScope", MAX_INDEXSIZE(ResolutionScopeIndex))
    COLUMN_ENTRY("TypeName", STRING_INDEXSIZE)
    COLUMN_ENTRY("TypeNamespace", STRING_INDEXSIZE)
  END_COLUMN_MAP()
};

static UINT TypeDefOrRefIndex[] = {ttTypeDef, ttTypeRef, ttTypeSpec, 0};

class CTypeDefTable : public CStreamTable
{
  DECLARE_TABLE(CTypeDefTable, ttTypeDef, "TypeDef")

  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("Flags", sizeof(DWORD))
    COLUMN_ENTRY("TypeName", STRING_INDEXSIZE)
    COLUMN_ENTRY("TypeNamespace", STRING_INDEXSIZE)
    COLUMN_ENTRY("Extends", MAX_INDEXSIZE(TypeDefOrRefIndex))
    COLUMN_ENTRY("FieldList", TABLE_INDEXSIZE(ttField))
    COLUMN_ENTRY("MethodList", TABLE_INDEXSIZE(ttMethodDef))
  END_COLUMN_MAP()
};

extern CREATEINSTANCE g_arTableTypes[64];
Added tools/mergebin/TableData.cpp.












































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/********************************************************
 * mergebin
 * Written by Robert Simpson (robert@blackcastlesoft.com)
 * 
 * Released to the public domain, use at your own risk!
 ********************************************************/

#include "StdAfx.h"
#include "TableData.h"

CREATEINSTANCE g_arTableTypes[64] = {
  CTableData::CreateInstance<CModuleTable>,
  CTableData::CreateInstance<CTypeRefTable>,
  CTableData::CreateInstance<CTypeDefTable>,
  CTableData::CreateInstance<CFieldPtrTable>,
  CTableData::CreateInstance<CFieldTable>,
  CTableData::CreateInstance<CMethodPtrTable>,
  CTableData::CreateInstance<CMethodTable>,
  CTableData::CreateInstance<CParamPtrTable>,
  CTableData::CreateInstance<CParamTable>,
  CTableData::CreateInstance<CInterfaceImplTable>,
  CTableData::CreateInstance<CMemberRefTable>,
  CTableData::CreateInstance<CConstantTable>,
  CTableData::CreateInstance<CCustomAttributeTable>,
  CTableData::CreateInstance<CFieldMarshalTable>,
  CTableData::CreateInstance<CDeclSecurityTable>,
  CTableData::CreateInstance<CClassLayoutTable>,
  CTableData::CreateInstance<CFieldLayoutTable>,
  CTableData::CreateInstance<CStandAloneSigTable>,
  CTableData::CreateInstance<CEventMapTable>,
  CTableData::CreateInstance<CEventPtrTable>,
  CTableData::CreateInstance<CEventTable>,
  CTableData::CreateInstance<CPropertyMapTable>,
  CTableData::CreateInstance<CPropertyPtrTable>,
  CTableData::CreateInstance<CPropertyTable>,
  CTableData::CreateInstance<CMethodSemanticsTable>,
  CTableData::CreateInstance<CMethodImplTable>,
  CTableData::CreateInstance<CModuleRefTable>,
  CTableData::CreateInstance<CTypeSpecTable>,
  CTableData::CreateInstance<CImplMapTable>,
  CTableData::CreateInstance<CFieldRVATable>,
  NULL,
};

CTableData::CTableData(CMetadataTables& tables) : m_tables(tables)
{
  m_uiRowSize = 0;
}

CTableData::~CTableData(void)
{
  if (m_pColumns) 
    delete[] m_pColumns;
}

template<class C>
static CTableData * CALLBACK CTableData::CreateInstance(CMetadataTables *ptables)
{
  CTableData *p = new C(*ptables);
  p->Init();

  return p;
}

void CTableData::Init()
{
  m_pbData = m_tables.m_pbData;
  CTableData *p;
  UINT n = GetType();
  
  while(n--)
  {
    p = m_tables.GetTable(n);
    if (p)
    {
      m_pbData = p->m_pbData + (p->GetRowSize() * p->GetRowCount());
      break;
    }
  }

  m_pColumns = _CreateColumns();
  TABLE_COLUMNS *tc = m_pColumns + 1;

  while (tc->pszName && !tc->dwOffset)
  {
    tc->dwOffset = tc[-1].dwOffset + tc[-1].uSize;
    tc ++;
  }
}

TABLE_COLUMN * CTableData::GetColumns()
{
  return m_pColumns;
}

DWORD CTableData::GetRowCount()
{
  return *m_tables.TableRowCount(GetType());
}

UINT CTableData::GetRowSize()
{
  if (m_uiRowSize == 0)
  {
    TABLE_COLUMN *pc = m_pColumns;

    while (pc->uSize)
    {
      m_uiRowSize += pc->uSize;
      pc ++;
    }
  }

  return m_uiRowSize;
}

UINT CTableData::GetColumnCount()
{
  TABLE_COLUMN *pc = m_pColumns;
  UINT ucount = 0;

  while (pc->uSize)
  {
    ucount ++;
    pc ++;
  }
  return ucount;
}

int CTableData::GetColumnIndex(LPCTSTR pszName)
{
  TABLE_COLUMN *pc = m_pColumns;
  for (int n = 0; pc[n].pszName; n++)
  {
    if (lstrcmpi(pszName, pc[n].pszName) == 0) return n;
  }
  return -1;
}

UINT CTableData::GetColumnSize(UINT uIndex)
{
  return m_pColumns[uIndex].uSize;
}

UINT CTableData::GetColumnSize(LPCTSTR pszName)
{
  int n = GetColumnIndex(pszName);
  if (n < 0) return 0;

  return GetColumnSize(n);
}

LPBYTE CTableData::Column(UINT uRow, UINT uIndex)
{
  TABLE_COLUMN *pc = m_pColumns;
  LPBYTE pb = m_pbData + (uRow * GetRowSize()) + pc[uIndex].dwOffset;

  return pb;
}

LPBYTE CTableData::Column(UINT uRow, LPCTSTR pszName)
{
  int n = GetColumnIndex(pszName);
  if (n < 0) return NULL;
  return Column(uRow, n);
}
Added tools/mergebin/TableData.h.














































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/********************************************************
 * mergebin
 * Written by Robert Simpson (robert@blackcastlesoft.com)
 * 
 * Released to the public domain, use at your own risk!
 ********************************************************/

#pragma once
#include "MetaDataTables.h"

typedef enum TableTypes
{
  ttModule = 0,
  ttTypeRef = 1,
  ttTypeDef = 2,
  ttFieldPtr = 3, 
  ttField = 4,
  ttMethodPtr = 5,
  ttMethodDef = 6,
  ttParamPtr = 7, 
  ttParam = 8,
  ttInterfaceImpl = 9,
  ttMemberRef = 10,
  ttConstant = 11, 
  ttCustomAttribute = 12,
  ttFieldMarshal = 13,
  ttDeclSecurity = 14,
  ttClassLayout = 15, 
  ttFieldLayout = 16,
  ttStandAloneSig = 17,
  ttEventMap = 18,
  ttEventPtr = 19, 
  ttEvent = 20,
  ttPropertyMap = 21,
  ttPropertyPtr = 22,
  ttProperty = 23, 
  ttMethodSemantics = 24,
  ttMethodImpl = 25,
  ttModuleRef = 26,
  ttTypeSpec = 27, 
  ttImplMap = 28,
  ttFieldRVA = 29,
  ttENCLog = 30,
  ttENCMap = 31, 
  ttAssembly = 32,
  ttAssemblyProcessor= 33,
  ttAssemblyOS = 34,
  ttAssemblyRef = 35, 
  ttAssemblyRefProcessor = 36,
  ttAssemblyRefOS = 37,
  ttFile = 38,
  ttExportedType = 39, 
  ttManifestResource = 40,
  ttNestedClass = 41,
  ttGenericParam = 42,
  ttMethodSpec = 43,
  ttGenericParamConstraint = 44,
} TableTypes;

typedef struct TABLE_COLUMN
{
  UINT uSize;
  LPCTSTR pszName;
  DWORD dwOffset;
} TABLE_COLUMNS;

class CTableData;

/*
** Helpers
*/
#define STRING_INDEXSIZE (m_tables.GetStringIndexSize())
#define GUID_INDEXSIZE (m_tables.GetGuidIndexSize())
#define BLOB_INDEXSIZE (m_tables.GetBlobIndexSize())
#define TABLE_ROWCOUNT(x) (m_tables.TableRowCount(x)[0])
#define TABLE_INDEXSIZE(x) (TABLE_ROWCOUNT(x) > 65535 ? 4 : 2)
#define MAX_INDEXSIZE(x) (m_tables.GetMaxIndexSizeOf(x))

#define DECLARE_TABLE(classname, typ, nam) \
  public: \
  classname##(CMetadataTables& tables) : CTableData(tables) {} \
  UINT GetType() { return typ; } \
  LPCTSTR GetName() { return _T(nam); }

#define BEGIN_COLUMN_MAP() \
  protected: \
  TABLE_COLUMN *_CreateColumns() \
  { \
    TABLE_COLUMN map[] = {

#define END_COLUMN_MAP() \
      { 0, NULL } \
    }; \
    TABLE_COLUMN *p = new TABLE_COLUMN[sizeof(map) / sizeof(TABLE_COLUMN)]; \
    CopyMemory(p, map, sizeof(map)); \
    return p; \
  }

#define COLUMN_ENTRY(name, size) { size, _T(name), 0 },
/*
** End Of Helpers
*/

class CTableData
{
public:
  CTableData(CMetadataTables& tables);
  virtual ~CTableData(void);

  virtual UINT          GetType        () = 0;
  virtual LPCTSTR       GetName        () = 0;
  virtual TABLE_COLUMN *_CreateColumns () = 0;

  template<class C> static CTableData * CALLBACK CreateInstance(CMetadataTables *ptables);

  virtual DWORD         GetRowCount ();
  virtual UINT          GetRowSize  ();

  int           GetColumnIndex (LPCTSTR pszName);
  UINT          GetColumnSize  (UINT uIndex);
  UINT          GetColumnSize  (LPCTSTR pszName);
  UINT          GetColumnCount ();
  LPBYTE        Column         (UINT uRow, UINT uIndex);
  LPBYTE        Column         (UINT uRow, LPCTSTR pszName);
  TABLE_COLUMN *GetColumns     ();

protected:
  CMetadataTables& m_tables;
  LPBYTE           m_pbData;
  UINT             m_uiRowSize;
  TABLE_COLUMN    *m_pColumns;

private:
  void Init ();
};

class CModuleTable : public CTableData
{
  DECLARE_TABLE(CModuleTable, ttModule, "Module")
  
  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("Generation", sizeof(WORD))
    COLUMN_ENTRY("Name",       STRING_INDEXSIZE)
    COLUMN_ENTRY("Mvid",       GUID_INDEXSIZE)
    COLUMN_ENTRY("EncId",      GUID_INDEXSIZE)
    COLUMN_ENTRY("EncBaseId",  GUID_INDEXSIZE)
  END_COLUMN_MAP()
};

static UINT TypeDefOrRefIndex[]        = { ttTypeDef,   ttTypeRef,     ttTypeSpec,     0 };
static UINT HasConstantIndex[]         = { ttField,     ttParam,       ttProperty,     0 };
static UINT HasCustomAttributeIndex[]  = { ttMethodDef, ttField,       ttTypeRef,      ttTypeDef,   ttParam,    ttInterfaceImpl, ttMemberRef, ttModule, ttDeclSecurity, ttProperty, ttEvent, ttStandAloneSig, ttModuleRef, ttTypeSpec, ttAssembly, ttAssemblyRef, ttFile, ttExportedType, ttManifestResource, 0 };
static UINT HasFieldMarshalIndex[]     = { ttField,     ttParam,       0 };
static UINT HasDeclSecurityIndex[]     = { ttTypeDef,   ttMethodDef,   ttAssembly,     0 };
static UINT MemberRefParentIndex[]     = { ttTypeDef,   ttTypeRef,     ttModuleRef,    ttMethodDef, ttTypeSpec, 0 };
static UINT HasSemanticsIndex[]        = { ttEvent,     ttProperty,    0 };
static UINT MethodDefOrRefIndex[]      = { ttMethodDef, ttMemberRef,   0 };
static UINT MemberForwardedIndex[]     = { ttField,     ttMethodDef,   0 };
static UINT ImplementationIndex[]      = { ttFile,      ttAssemblyRef, ttExportedType, 0 };
static UINT CustomAttributeTypeIndex[] = { 63,          63,            ttMethodDef,    ttMemberRef, 63,         0 };
static UINT ResolutionScopeIndex[]     = { ttModule,    ttModuleRef,   ttAssemblyRef,  ttTypeRef,   0 };
static UINT TypeOrMethodDefIndex[]     = { ttTypeDef,   ttMethodDef,   0 };

class CTypeRefTable : public CTableData
{
  DECLARE_TABLE(CTypeRefTable, ttTypeRef, "TypeRef")

  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("ResolutionScope", MAX_INDEXSIZE(ResolutionScopeIndex))
    COLUMN_ENTRY("TypeName",        STRING_INDEXSIZE)
    COLUMN_ENTRY("TypeNamespace",   STRING_INDEXSIZE)
  END_COLUMN_MAP()
};

class CTypeDefTable : public CTableData
{
  DECLARE_TABLE(CTypeDefTable, ttTypeDef, "TypeDef")

  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("Flags",         sizeof(DWORD))
    COLUMN_ENTRY("TypeName",      STRING_INDEXSIZE)
    COLUMN_ENTRY("TypeNamespace", STRING_INDEXSIZE)
    COLUMN_ENTRY("Extends",       MAX_INDEXSIZE(TypeDefOrRefIndex))
    COLUMN_ENTRY("FieldList",     TABLE_INDEXSIZE(ttField))
    COLUMN_ENTRY("MethodList",    TABLE_INDEXSIZE(ttMethodDef))
  END_COLUMN_MAP()
};

class CFieldPtrTable : public CTableData
{
  DECLARE_TABLE(CFieldPtrTable, ttFieldPtr, "FieldPtr")

  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("Field", TABLE_INDEXSIZE(ttField))
  END_COLUMN_MAP()
};

class CFieldTable : public CTableData
{
  DECLARE_TABLE(CFieldTable, ttField, "Field")

  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("Flags",     sizeof(WORD))
    COLUMN_ENTRY("Name",      STRING_INDEXSIZE)
    COLUMN_ENTRY("Signature", BLOB_INDEXSIZE)
  END_COLUMN_MAP()
};

class CMethodPtrTable : public CTableData
{
  DECLARE_TABLE(CMethodPtrTable, ttMethodPtr, "MethodPtr")

  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("Method", TABLE_INDEXSIZE(ttMethodDef))
  END_COLUMN_MAP()
};

class CMethodTable : public CTableData
{
  DECLARE_TABLE(CMethodTable, ttMethodDef, "Method")

  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("RVA",        sizeof(DWORD))
    COLUMN_ENTRY("ImplFlags",  sizeof(WORD))
    COLUMN_ENTRY("Flags",      sizeof(WORD))
    COLUMN_ENTRY("Name",       STRING_INDEXSIZE)
    COLUMN_ENTRY("Signature",  BLOB_INDEXSIZE)
    COLUMN_ENTRY("Parameters", TABLE_INDEXSIZE(ttParam))
  END_COLUMN_MAP()
};

class CParamPtrTable : public CTableData
{
  DECLARE_TABLE(CParamPtrTable, ttParamPtr, "ParamPtr")

  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("Param", TABLE_INDEXSIZE(ttParam))
  END_COLUMN_MAP()
};

class CParamTable : public CTableData
{
  DECLARE_TABLE(CParamTable, ttParam, "Param")

  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("Flags",    sizeof(WORD))
    COLUMN_ENTRY("Sequence", sizeof(WORD))
    COLUMN_ENTRY("Name",     STRING_INDEXSIZE)
  END_COLUMN_MAP()
};

class CInterfaceImplTable : public CTableData
{
  DECLARE_TABLE(CInterfaceImplTable, ttInterfaceImpl, "Interface")

  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("Class",     TABLE_INDEXSIZE(ttTypeDef))
    COLUMN_ENTRY("Interface", MAX_INDEXSIZE(TypeDefOrRefIndex))
  END_COLUMN_MAP()
};

class CMemberRefTable : public CTableData
{
  DECLARE_TABLE(CMemberRefTable, ttMemberRef, "Member")

  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("Class",     MAX_INDEXSIZE(MemberRefParentIndex))
    COLUMN_ENTRY("Name",      STRING_INDEXSIZE)
    COLUMN_ENTRY("Signature", BLOB_INDEXSIZE)
  END_COLUMN_MAP()
};

class CConstantTable : public CTableData
{
  DECLARE_TABLE(CConstantTable, ttConstant, "Constant")

  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("Type",   sizeof(WORD))
    COLUMN_ENTRY("Parent", MAX_INDEXSIZE(HasConstantIndex))
    COLUMN_ENTRY("Value",  BLOB_INDEXSIZE)
  END_COLUMN_MAP()
};

class CCustomAttributeTable : public CTableData
{
  DECLARE_TABLE(CCustomAttributeTable, ttCustomAttribute, "CustomAttribute")

  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("Parent", MAX_INDEXSIZE(HasCustomAttributeIndex))
    COLUMN_ENTRY("Type",   MAX_INDEXSIZE(CustomAttributeTypeIndex))
    COLUMN_ENTRY("Value",  BLOB_INDEXSIZE)
  END_COLUMN_MAP()
};

class CFieldMarshalTable : public CTableData
{
  DECLARE_TABLE(CFieldMarshalTable, ttFieldMarshal, "FieldMarshal")

  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("Parent",     MAX_INDEXSIZE(HasFieldMarshalIndex))
    COLUMN_ENTRY("NativeType", BLOB_INDEXSIZE)
  END_COLUMN_MAP()
};

class CDeclSecurityTable : public CTableData
{
  DECLARE_TABLE(CDeclSecurityTable, ttDeclSecurity, "DeclSecurity")

  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("Action",        sizeof(WORD))
    COLUMN_ENTRY("Parent",        MAX_INDEXSIZE(HasDeclSecurityIndex))
    COLUMN_ENTRY("PermissionSet", BLOB_INDEXSIZE)
  END_COLUMN_MAP()
};

class CClassLayoutTable : public CTableData
{
  DECLARE_TABLE(CClassLayoutTable, ttClassLayout, "ClassLayout")
  
  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("PackingSize", sizeof(WORD))
    COLUMN_ENTRY("ClassSize",   sizeof(DWORD))
    COLUMN_ENTRY("Parent",      TABLE_INDEXSIZE(ttTypeDef))
  END_COLUMN_MAP()
};

class CFieldLayoutTable : public CTableData
{
  DECLARE_TABLE(CFieldLayoutTable, ttFieldLayout, "FieldLayout")

  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("Offset", sizeof(DWORD))
    COLUMN_ENTRY("Field",  TABLE_INDEXSIZE(ttField))
  END_COLUMN_MAP()
};

class CStandAloneSigTable : public CTableData
{
  DECLARE_TABLE(CStandAloneSigTable, ttStandAloneSig, "StandAloneSig")

  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("Signature", BLOB_INDEXSIZE)
  END_COLUMN_MAP()
};

class CEventMapTable : public CTableData
{
  DECLARE_TABLE(CEventMapTable, ttEventMap, "EventMap")

  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("Parent",    TABLE_INDEXSIZE(ttTypeDef))
    COLUMN_ENTRY("EventList", TABLE_INDEXSIZE(ttEvent))
  END_COLUMN_MAP()
};

class CEventTable : public CTableData
{
  DECLARE_TABLE(CEventTable, ttEvent, "Event")

  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("EventFlags", sizeof(WORD))
    COLUMN_ENTRY("Name",       STRING_INDEXSIZE)
    COLUMN_ENTRY("EventType",  MAX_INDEXSIZE(TypeDefOrRefIndex))
  END_COLUMN_MAP()
};

class CEventPtrTable : public CTableData
{
  DECLARE_TABLE(CEventPtrTable, ttEventPtr, "EventPtr")

  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("Event", TABLE_INDEXSIZE(ttEvent))
  END_COLUMN_MAP()
};

class CPropertyMapTable : public CTableData
{
  DECLARE_TABLE(CPropertyMapTable, ttPropertyMap, "PropertyMap")

  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("Parent",       TABLE_INDEXSIZE(ttTypeDef))
    COLUMN_ENTRY("PropertyList", TABLE_INDEXSIZE(ttProperty))
  END_COLUMN_MAP()
};

class CPropertyPtrTable : public CTableData
{
  DECLARE_TABLE(CPropertyPtrTable, ttEventPtr, "PropertyPtr")

  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("Property", TABLE_INDEXSIZE(ttProperty))
  END_COLUMN_MAP()
};

class CPropertyTable : public CTableData
{
  DECLARE_TABLE(CPropertyTable, ttProperty, "Property")

  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("Flags", sizeof(WORD))
    COLUMN_ENTRY("Name",  STRING_INDEXSIZE)
    COLUMN_ENTRY("Type",  BLOB_INDEXSIZE)
  END_COLUMN_MAP()
};

class CMethodSemanticsTable : public CTableData
{
  DECLARE_TABLE(CMethodSemanticsTable, ttMethodSemantics, "MethodSemantics")

  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("Semantics",   sizeof(WORD))
    COLUMN_ENTRY("Method",      TABLE_INDEXSIZE(ttMethodDef))
    COLUMN_ENTRY("Association", MAX_INDEXSIZE(HasSemanticsIndex))
  END_COLUMN_MAP()
};

class CMethodImplTable : public CTableData
{
  DECLARE_TABLE(CMethodImplTable, ttMethodImpl, "MethodImpl")

  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("Class",             TABLE_INDEXSIZE(ttTypeDef))
    COLUMN_ENTRY("MethodBody",        MAX_INDEXSIZE(MethodDefOrRefIndex))
    COLUMN_ENTRY("MethodDeclaration", MAX_INDEXSIZE(MethodDefOrRefIndex))
  END_COLUMN_MAP()
};

class CModuleRefTable : public CTableData
{
  DECLARE_TABLE(CModuleRefTable, ttModuleRef, "ModuleRef")

  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("Name", STRING_INDEXSIZE)
  END_COLUMN_MAP()
};

class CTypeSpecTable : public CTableData
{
  DECLARE_TABLE(CTypeSpecTable, ttTypeSpec, "TypeSpec")

  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("Signature", BLOB_INDEXSIZE)
  END_COLUMN_MAP()
};

class CImplMapTable : public CTableData
{
  DECLARE_TABLE(CImplMapTable, ttImplMap, "ImplMap")

  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("MappingFlags",    sizeof(WORD))
    COLUMN_ENTRY("MemberForwarded", MAX_INDEXSIZE(MemberForwardedIndex))
    COLUMN_ENTRY("ImportName",      STRING_INDEXSIZE)
    COLUMN_ENTRY("ImportScope",     TABLE_INDEXSIZE(ttModuleRef))
  END_COLUMN_MAP()
};

class CFieldRVATable : public CTableData
{
  DECLARE_TABLE(CFieldRVATable, ttFieldRVA, "FieldRVA")

  BEGIN_COLUMN_MAP()
    COLUMN_ENTRY("RVA",   sizeof(DWORD))
    COLUMN_ENTRY("Field", TABLE_INDEXSIZE(ttField))
  END_COLUMN_MAP()
};

// Only tables up to ttFieldRVA are mapped, because they're all I needed.  If you need the tables beyond that, map them yourself!

typedef CTableData* (CALLBACK* CREATEINSTANCE)(CMetadataTables *);
extern CREATEINSTANCE g_arTableTypes[64];
Added tools/mergebin/mergebin.cpp.






























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/********************************************************
 * mergebin
 * Written by Robert Simpson (robert@blackcastlesoft.com)
 * 
 * Released to the public domain, use at your own risk!
 ********************************************************/

#include "stdafx.h"
#include "MetaData.h"
#include "MetaDataTables.h"
#include "TableData.h"

void DumpCLRInfo(LPCTSTR pszFile);
void MergeModules(LPCTSTR pszAssembly, LPCTSTR pszNative, LPCTSTR pszSection, DWORD dwAdjust);
void DumpCLRPragma(LPCTSTR pszAssembly, LPCTSTR pszSection);
void FixObjFile(LPCTSTR pszFile);

typedef struct EXTRA_STUFF
{
  DWORD dwNativeEntryPoint;
} EXTRA_STUFF, *LPEXTRA_STUFF;

int _tmain(int argc, _TCHAR* argv[])
{
  if (argc == 1)
  {
    _tprintf(_T(
"MERGEBIN - Merges a pure .NET assembly with a native DLL\n \
Syntax: MERGEBIN [/I:assembly] [/S:sectionname assembly nativedll]\n \
/I:assembly            Returns the number of bytes required\n \
                       to consume the assembly\n \
/S:sectionname         The name of the section in the nativedll\n \
                       to insert the CLR data\n \
/P:assembly            Outputs the C++ pragma code that can be used\n \
                       as additional input to a C++ app to reserve\n \
                       a section block large enough for the managed code.\n \
/B:objectfile          Windows CE workaround, changes the attributes of\n \
                       the .BSS section of an object file to generate a\n \
                       DLL that doesn't have a .bss section whos \n \
                       virtualsize is larger than the rawdata size.\n \
The native DLL must have an unused section in it, into which the\n \
.NET assembly will be inserted.  You can do this with the following code:\n \
  #pragma data_seg(\".clr\")\n \
  #pragma comment(linker, \"/SECTION:.clr,ER\")\n \
   char __ph[92316] = {0}; // 92316 is the number of bytes to reserve\n \
  #pragma data_seg()\n \
You would then specify /SECTION:.CLR in the command-line for the location to\n \
insert the .NET assembly.  The number of bytes reserved in the section needs\n \
to be equal to or more than the number of bytes returned by the /I parameter.\n \
\n \
The native DLL must also export a function that calls _CorDllMain in \n \
MSCOREE.DLL.  This function must have the same parameters and calling\n \
conventions as DllMain, and its name must have the word \"CORDLLMAIN\"\n \
in it.\n \
"));
    return 0;
  }

  LPTSTR pszAssembly = NULL;
  LPTSTR pszNative = NULL;
  LPTSTR pszSection = NULL;
  BOOL bDoPragma = FALSE;
  BOOL bDoObj = FALSE;
  DWORD dwAdjust = 0;

  for (int n = 1; n < argc; n++)
  {
    if (argv[n][0] != '-' && argv[n][0] != '/')
    {
      if (pszAssembly == NULL)
        pszAssembly = argv[n];
      else if (pszNative == NULL)
        pszNative = argv[n];
      else
      {
        _tprintf(_T("Too many files specified\n"));
        return 0;
      }
      continue;
    }

    switch(argv[n][1])
    {
    case 'I':
    case 'i':
      pszAssembly = &argv[n][3];
      if (argv[n][2] != ':' || lstrlen(pszAssembly) == 0)
      {
        _tprintf(_T("/I requires an assembly name\n"));
        return 0;
      }
      DumpCLRInfo(pszAssembly);
      return 0;
      break;
    case 'P':
    case 'p':
      pszAssembly = &argv[n][3];
      if (argv[n][2] != ':' || lstrlen(pszAssembly) == 0)
      {
        _tprintf(_T("/P requires an assembly name\n"));
        return 0;
      }
      bDoPragma = TRUE;
      break;
    case 'S':
    case 's':
      pszSection = &argv[n][3];
      if (argv[n][2] != ':' || lstrlen(pszSection) == 0)
      {
        _tprintf(_T("/S requires a section name\n"));
        return 0;
      }
      break;
    //case 'A':
    //case 'a':
    //  if (argv[n][2] != ':')
    //  {
    //    _tprintf(_T("A parameter requires a numeric value\n"));
    //    return 0;
    //  }
    //  dwAdjust = _ttol(&argv[n][3]);
    //  break;
    case 'B':
    case 'b':
      pszAssembly = &argv[n][3];
      if (argv[n][2] != ':' || lstrlen(pszAssembly) == 0)
      {
        _tprintf(_T("/B requires an object file name\n"));
        return 0;
      }
      bDoObj = TRUE;
      break;
    }
  }

  if (pszAssembly && bDoObj)
    FixObjFile(pszAssembly);
  else if (pszAssembly && pszNative && pszSection && !bDoPragma)
    MergeModules(pszAssembly, pszNative, pszSection, dwAdjust);
  else if (pszAssembly && bDoPragma)
    DumpCLRPragma(pszAssembly, pszSection);

  return 0;
}

LPBYTE memstr(LPBYTE buffer, LPCSTR find, DWORD size)
{
	LPBYTE p;
	DWORD findsize = lstrlenA(find);

	for (p = buffer; p <= (buffer-findsize+size); p++)
	{
		if (memcmp(p, find, findsize) == 0)
			return p; /* found */
	}
	return NULL;
}

void FixObjFile(LPCTSTR pszFile)
{
  HANDLE hMap = INVALID_HANDLE_VALUE;
  HANDLE hFile = CreateFile(pszFile, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
  LPBYTE p;
  DWORD dwSize;

  if (hFile == INVALID_HANDLE_VALUE) return;

  dwSize = GetFileSize(hFile, NULL);
  hMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
  if (hMap)
  {
    p = (LPBYTE)MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
    if (p)
    {
      PIMAGE_SECTION_HEADER section = (PIMAGE_SECTION_HEADER)memstr(p, ".bss", dwSize);

      if (section)
      {
        section->Characteristics &= ~IMAGE_SCN_CNT_UNINITIALIZED_DATA;
        section->Characteristics |= IMAGE_SCN_CNT_INITIALIZED_DATA;
      }
      UnmapViewOfFile(p);
    }
    CloseHandle(hMap);
  }
  CloseHandle(hFile);
}


BOOL GetMinMaxCOR20RVA(CPEFile& file, DWORD& dwMin, DWORD& dwMax)
{
  PIMAGE_COR20_HEADER pCor = file;
  dwMin = MAXDWORD;
  dwMax = 0;

  if (!pCor) return FALSE;

  if (pCor->MetaData.Size) dwMin = min(dwMin, pCor->MetaData.VirtualAddress);
  if (pCor->Resources.Size) dwMin = min(dwMin, pCor->Resources.VirtualAddress);
  if (pCor->StrongNameSignature.Size) dwMin = min(dwMin, pCor->StrongNameSignature.VirtualAddress);
  if (pCor->CodeManagerTable.Size) dwMin = min(dwMin, pCor->CodeManagerTable.VirtualAddress);
  if (pCor->VTableFixups.Size) dwMin = min(dwMin, pCor->VTableFixups.VirtualAddress);
  if (pCor->ExportAddressTableJumps.Size) dwMin = min(dwMin, pCor->ExportAddressTableJumps.VirtualAddress);
  if (pCor->ManagedNativeHeader.Size) dwMin = min(dwMin, pCor->ManagedNativeHeader.VirtualAddress);

  dwMax = max(dwMax, (pCor->MetaData.VirtualAddress + pCor->MetaData.Size));
  dwMax = max(dwMax, (pCor->Resources.VirtualAddress + pCor->Resources.Size));
  dwMax = max(dwMax, (pCor->StrongNameSignature.VirtualAddress + pCor->StrongNameSignature.Size));
  dwMax = max(dwMax, (pCor->CodeManagerTable.VirtualAddress + pCor->CodeManagerTable.Size));
  dwMax = max(dwMax, (pCor->VTableFixups.VirtualAddress + pCor->VTableFixups.Size));
  dwMax = max(dwMax, (pCor->ExportAddressTableJumps.VirtualAddress + pCor->ExportAddressTableJumps.Size));
  dwMax = max(dwMax, (pCor->ManagedNativeHeader.VirtualAddress + pCor->ManagedNativeHeader.Size));

  CMetadata meta(file);
  CMetadataTables tables(meta);
  CTableData *p;
  DWORD *pdwRVA;
  DWORD dwRows;

  for (int n = 0; n < 2; n++)
  {
    p = tables.GetTable((n == 0) ? ttMethodDef : ttFieldRVA);
    if (p)
    {
      dwRows = p->GetRowCount();
      for (UINT uRow = 0; uRow < dwRows; uRow ++)
      {
        pdwRVA = (DWORD *)p->Column(uRow, (UINT)0);
        if (*pdwRVA)
          dwMin = min(dwMin, (*pdwRVA));
      }
    }
  }
  return TRUE;
}

void DumpCLRInfo(LPCTSTR pszFile)
{
  CPEFile peFile;
  HRESULT hr;
  hr = peFile.Open(pszFile);
  if (FAILED(hr)) return;

  DWORD dwMinRVA;
  DWORD dwMaxRVA;

  if (!GetMinMaxCOR20RVA(peFile, dwMinRVA, dwMaxRVA))
  {
    _tprintf(_T("Unable to retrieve .NET assembly information for file %s\n"), pszFile);
    return;
  }

  _tprintf(_T("%d Bytes required to merge %s\n"), (dwMaxRVA - dwMinRVA) + ((PIMAGE_COR20_HEADER)peFile)->cb + sizeof(EXTRA_STUFF), pszFile);
}

void DumpCLRPragma(LPCTSTR pszAssembly, LPCTSTR pszSection)
{
  CPEFile peFile;
  HRESULT hr;
  DWORD dwMinRVA;
  DWORD dwMaxRVA;

  hr = peFile.Open(pszAssembly);
  if (FAILED(hr)) return;
  
  if (pszSection == NULL) pszSection = _T(".clr");

  if (!GetMinMaxCOR20RVA(peFile, dwMinRVA, dwMaxRVA))
  {
    _tprintf(_T("// Unable to retrieve .NET assembly information for file %s\n"), pszAssembly);
    return;
  }

  _tprintf(_T("// This code was automatically generated from assembly\n\
// %s\n\n\
#include <windef.h>\n\n\
#pragma data_seg(push,clrseg,\"%s\")\n\
#pragma comment(linker, \"/SECTION:%s,ER\")\n\
  char __ph[%d] = {0}; // The number of bytes to reserve\n\
#pragma data_seg(pop,clrseg)\n\n\
typedef BOOL (WINAPI *DLLMAIN)(HANDLE, DWORD, LPVOID);\n\
typedef struct EXTRA_STUFF\n\
{\n\
  DWORD dwNativeEntryPoint;\n\
} EXTRA_STUFF, *LPEXTRA_STUFF;\n\n\
__declspec(dllexport) BOOL WINAPI _CorDllMainStub(HANDLE hModule, DWORD dwReason, LPVOID pvReserved)\n\
{\n\
  HANDLE hMod;\n\
  DLLMAIN proc;\n\
  LPEXTRA_STUFF pExtra;\n\n\
  hMod = GetModuleHandle(_T(\"mscoree\"));\n\
  if (hMod)\n\
    proc = (DLLMAIN)GetProcAddress(hMod, _T(\"_CorDllMain\"));\n\
  else\n\
  {\n\
    MEMORY_BASIC_INFORMATION mbi;\n\n\
    VirtualQuery(_CorDllMainStub, &mbi, sizeof(mbi));\n\
    pExtra = (LPEXTRA_STUFF)__ph;\n\
    proc = (DLLMAIN)(pExtra->dwNativeEntryPoint + (DWORD)mbi.AllocationBase);\n\
  }\n\
  return proc(hModule, dwReason, pvReserved);\n\
}\n\
"), pszAssembly, pszSection, pszSection, (dwMaxRVA - dwMinRVA) + ((PIMAGE_COR20_HEADER)peFile)->cb + sizeof(EXTRA_STUFF));
}

/*   When merged, the native DLL's entrypoint must go to _CorDllMain in MSCOREE.DLL.
  ** In order to do this, we need to change the DLL's entrypoint to "something" that will
  ** call CorDllMain.  Since its too much hassle to add imports to the DLL and make drastic
  ** changes to it, we rely on the native DLL to export a function that we can call which will
  ** forward to CorDllMain.  Exported functions are easy to identify and get an RVA for.
  ** The exported function must have the same calling conventions and parameters as DllMain,
  ** and must contain the letters "CORDLLMAIN" in the name.  The search is case-insensitive. */
DWORD GetExportedCorDllMainRVA(CPEFile& file)
{
  PIMAGE_EXPORT_DIRECTORY pExportDir;
  PIMAGE_SECTION_HEADER header;
  INT delta; 
  DWORD i;
  DWORD *pdwFunctions;
  PWORD pwOrdinals;
  DWORD *pszFuncNames;
  DWORD exportsStartRVA;
  DWORD exportsEndRVA;
  CHAR szName[MAX_PATH + 1];
  PIMAGE_NT_HEADERS32 pNT = file;
  PIMAGE_NT_HEADERS64 pNT64 = file;

  if (pNT)
  {
    exportsStartRVA = pNT->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
    exportsEndRVA = exportsStartRVA + pNT->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
  }
  else
  {
    exportsStartRVA = pNT64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
    exportsEndRVA = exportsStartRVA + pNT64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
  }

  header = file.GetEnclosingSectionHeader(exportsStartRVA);
  if (!header)
    return 0;

  delta = (INT)(header->VirtualAddress - header->PointerToRawData);

  pExportDir   =  (PIMAGE_EXPORT_DIRECTORY)file.GetPtrFromRVA(exportsStartRVA);
  pdwFunctions =	(PDWORD)file.GetPtrFromRVA(pExportDir->AddressOfFunctions);
  pwOrdinals   =	(PWORD)file.GetPtrFromRVA(pExportDir->AddressOfNameOrdinals);
  pszFuncNames =	(DWORD *)file.GetPtrFromRVA(pExportDir->AddressOfNames);

  for (i = 0; i < pExportDir->NumberOfFunctions; i++, pdwFunctions++)
  {
    DWORD entryPointRVA = *pdwFunctions;

    if ( entryPointRVA == 0 )
      continue;

    for (UINT j = 0; j < pExportDir->NumberOfNames; j++)
    {
      if (pwOrdinals[j] == i)
      {
        lstrcpynA(szName, (LPSTR)file.GetPtrFromRVA(pszFuncNames[j]), MAX_PATH);
        szName[MAX_PATH] = 0;
        CharUpper(szName);
        if (strstr(szName, "CORDLLMAIN") != 0) return entryPointRVA;
      }
    }
  }
  return 0;
}

// Merges a pure .NET assembly with a native DLL, inserting it into the specified section
void MergeModules(LPCTSTR pszAssembly, LPCTSTR pszNative, LPCTSTR pszSection, DWORD dwAdjust)
{
  CPEFile peFile;
  CPEFile peDest;
  HRESULT hr;
  DWORD dwMinRVA;
  DWORD dwMaxRVA;
  DWORD dwDestRVA;
  PIMAGE_SECTION_HEADER pSection;
  LPBYTE pSrc;
  LPBYTE pDest;
  DWORD dwSize;
  DWORD dwNewEntrypoint;
  PIMAGE_COR20_HEADER pCor;
  PIMAGE_NT_HEADERS32 pNT;
  PIMAGE_NT_HEADERS64 pNT64;
  int diffRVA;
  CTableData *p;
  DWORD *pdwRVA;
  DWORD dwRows;
  LPEXTRA_STUFF pExtra;

  // Open the .NET assembly
  hr = peFile.Open(pszAssembly);
  if (FAILED(hr)) return;

  // Scan the .NET assembly and find the block of .NET code specified in the .NET metadata
  if (!GetMinMaxCOR20RVA(peFile, dwMinRVA, dwMaxRVA))
  {
    _tprintf(_T("Unable to retrieve .NET assembly information for file %s\n"), pszAssembly);
    return;
  }
  // Total number of bytes of the block of .NET code we're going to merge
  dwSize = (dwMaxRVA - dwMinRVA) + ((PIMAGE_COR20_HEADER)peFile)->cb;

  // Open the destination file for readwrite access
  hr = peDest.Open(pszNative, FALSE);
  if (FAILED(hr)) return;

  // Make sure it has the section specified in the command-line
  pSection = peDest.GetSectionHeader(pszSection);
  if (!pSection)
  {
    _tprintf(_T("Unable to find section %s in file\n"), pszSection);
    return;
  }

  // If the section isn't large enough, tell the user how large it needs to be
  if (pSection->Misc.VirtualSize < (dwSize + sizeof(EXTRA_STUFF)))
  {
    _tprintf(_T("Not enough room in section for data.  Need %d bytes\n"), dwSize + sizeof(EXTRA_STUFF));
    return;
  }

  /*
  ** Find a new entrypoint to use for the DLL.  The old entrypoint is written into the .NET header
  */
  dwNewEntrypoint = GetExportedCorDllMainRVA(peDest);
  if (!dwNewEntrypoint)
  {
    _tprintf(_T("Native DLL must export a function that calls _CorDllMain, and its name must contain the word \"CorDllMain\".\n"));
    return;
  }

  // Change this section's flags
  pSection->Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ;
  dwDestRVA = pSection->VirtualAddress;

  pExtra = (LPEXTRA_STUFF)peDest.GetPtrFromRVA(dwDestRVA);
  dwDestRVA += sizeof(EXTRA_STUFF);

  // If the native DLL has been merged with an assembly beforehand, we need to strip the .NET stuff and restore the entrypoint
  pCor = peDest;
  if (pCor)
  {
    if (pCor->Flags & 0x10)
    {
      pNT = peDest;
      pNT64 = peDest;

      if (pNT)
        pNT->OptionalHeader.AddressOfEntryPoint = pCor->EntryPointToken;
      else
        pNT64->OptionalHeader.AddressOfEntryPoint = pCor->EntryPointToken;
    }
  }

  // Copy the assembly's .NET header into the section
  dwSize = ((PIMAGE_COR20_HEADER)peFile)->cb;
  pSrc = (LPBYTE)(PIMAGE_COR20_HEADER)peFile;
  pDest = (LPBYTE)peDest.GetPtrFromRVA(dwDestRVA);
  CopyMemory(pDest, pSrc, dwSize);

  pNT = peDest;
  pNT64 = peDest;

  // Fixup the NT header on the native DLL to include the new .NET header
  if (pNT)
  {
    pExtra->dwNativeEntryPoint = pNT->OptionalHeader.AddressOfEntryPoint;
    pNT->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress = dwDestRVA;
    pNT->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size = dwSize;
  }
  else
  {
    pExtra->dwNativeEntryPoint = pNT64->OptionalHeader.AddressOfEntryPoint;
    pNT64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress = dwDestRVA;
    pNT64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size = dwSize;
  }
  dwDestRVA += dwSize;
  if (dwDestRVA % 4) dwDestRVA += (4 - (dwDestRVA % 4));

  // Copy the .NET block of code and metadata into the section, after the header
  dwSize = dwMaxRVA - dwMinRVA;
  pSrc = (LPBYTE)peFile.GetPtrFromRVA(dwMinRVA);
  pDest = (LPBYTE)peDest.GetPtrFromRVA(dwDestRVA);
  CopyMemory(pDest, pSrc, dwSize);

  // Figure out by how much we need to change the RVA's to compensate for the relocation
  diffRVA = dwDestRVA - dwMinRVA;
  pCor = peDest;

  // Fixup the DLL entrypoints
  if (pNT)
  {
    pNT->OptionalHeader.MajorOperatingSystemVersion = 4;
    pNT->OptionalHeader.MajorSubsystemVersion = 4;
    if (pNT->OptionalHeader.AddressOfEntryPoint != dwNewEntrypoint)
    {
      pCor->EntryPointToken = pNT->OptionalHeader.AddressOfEntryPoint;
      pNT->OptionalHeader.AddressOfEntryPoint = dwNewEntrypoint;
    }
  }
  else
  {
    if (pNT64->OptionalHeader.AddressOfEntryPoint != dwNewEntrypoint)
    {
      pCor->EntryPointToken = pNT64->OptionalHeader.AddressOfEntryPoint;
      pNT64->OptionalHeader.AddressOfEntryPoint = dwNewEntrypoint;
    }
  }
  // Adjust the .NET headers to indicate we're a mixed DLL
  pCor->Flags = (pCor->Flags & 0xFFFE) | 0x10;

  // Fixup the metadata header RVA's
  if (pCor->MetaData.VirtualAddress) pCor->MetaData.VirtualAddress += diffRVA;
  if (pCor->Resources.VirtualAddress) pCor->Resources.VirtualAddress += diffRVA;
  if (pCor->StrongNameSignature.VirtualAddress) pCor->StrongNameSignature.VirtualAddress += diffRVA;
  if (pCor->CodeManagerTable.VirtualAddress) pCor->CodeManagerTable.VirtualAddress += diffRVA;
  if (pCor->VTableFixups.VirtualAddress) pCor->VTableFixups.VirtualAddress += diffRVA;
  if (pCor->ExportAddressTableJumps.VirtualAddress) pCor->ExportAddressTableJumps.VirtualAddress += diffRVA;
  if (pCor->ManagedNativeHeader.VirtualAddress) pCor->ManagedNativeHeader.VirtualAddress += diffRVA;

  CMetadata meta(peDest);
  CMetadataTables tables(meta);

  // Fixup all the RVA's for methods and fields that have them in the .NET code
  for (int n = 0; n < 2; n++)
  {
    p = tables.GetTable((n == 0) ? ttMethodDef : ttFieldRVA);
    if (p)
    {
      dwRows = p->GetRowCount();
      for (UINT uRow = 0; uRow < dwRows; uRow ++)
      {
        pdwRVA = (DWORD *)p->Column(uRow, (UINT)0);
        if (*pdwRVA)
          *pdwRVA = (*pdwRVA) + diffRVA;
      }
    }
  }

  // If this is a CE file, then change the processor to x86
  if (pNT)
  {
    if (pNT->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 
      || pNT->FileHeader.Machine == IMAGE_FILE_MACHINE_ARM)
    {
      pNT->FileHeader.Machine = IMAGE_FILE_MACHINE_I386;
      pNT->OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
    }

    if (pNT->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI && (pCor->Flags & 0x08))
    {
      PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(pNT);
      for (UINT i=0; i < pNT->FileHeader.NumberOfSections; i++, section++)
      {
        if (_tcscmp((LPCSTR)section->Name, _T(".bss")) == 0)
        {
          _tcscpy((LPSTR)section->Name, _T(".idata"));
          //section->Characteristics &= ~IMAGE_SCN_CNT_INITIALIZED_DATA;
          //section->Characteristics |= IMAGE_SCN_CNT_UNINITIALIZED_DATA;
          DWORD dwBSSRVA = section->VirtualAddress;
          LPBYTE pBSS = (LPBYTE)peDest.GetPtrFromRVA(dwBSSRVA);
          for (DWORD u = 0; u < section->SizeOfRawData; u++)
          {
            pBSS[u] = 0;
          }
        }
        if (section->SizeOfRawData < section->Misc.VirtualSize)
        {
          if (_tcscmp((LPCSTR)section->Name, _T(".data")) == 0 && dwAdjust > 0)
          {
            _tprintf(_T("\nWARNING: %s section has a RawData size of %d, less than its VirtualSize of %d, adjusting VirtualSize to %d\n"), section->Name, section->SizeOfRawData, section->Misc.VirtualSize, dwAdjust);
            section->Misc.VirtualSize = dwAdjust;
          }
          else
          {
            _tprintf(_T("\nWARNING: %s section has a RawData size of %d and a VirtualSize of %d, strong named image may not run on Windows CE\n"), section->Name, section->SizeOfRawData, section->Misc.VirtualSize);
          }
        }
      }
    }
  }

  if (pCor->Flags & 0x08)
    _tprintf(_T("\nWARNING: %s must be re-signed before it can be used!\n"), pszNative);

  _tprintf(_T("Success!\n"));
}
Added tools/mergebin/stdafx.cpp.
















>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
// stdafx.cpp : source file that includes just the standard includes
// mergebin.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information

#include "stdafx.h"

// TODO: reference any additional headers you need in STDAFX.H
// and not in this file
Added tools/mergebin/stdafx.h.
































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//

#pragma once


#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#define _WIN32_WINNT 0x0400

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>
// TODO: reference additional headers your program requires here
Added tools/setup/exe/setup/admin.manifest.




















>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="requireAdministrator"/>
      </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>
Added tools/setup/exe/setup/install.ico.

cannot compute difference between binary files

Added tools/setup/exe/setup/resource.h.










































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by setup.rc
//
#define IDI_SETUP                       5
#define IDD_SETUP_DIALOG                102
#define IDR_MAINFRAME                   128
#define IDR_MSI1                        130
#define IDC_STATIC                      -1

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC                     1
#define _APS_NEXT_RESOURCE_VALUE        131
#define _APS_NEXT_COMMAND_VALUE         32771
#define _APS_NEXT_CONTROL_VALUE         1000
#define _APS_NEXT_SYMED_VALUE           110
#endif
#endif
Added tools/setup/exe/setup/setup.cpp.
































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// setup.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "setup.h"

int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE /*hPrevInstance*/,
                     LPTSTR    /*lpCmdLine*/,
                     int       /*nCmdShow*/)
{
  HRSRC hRes = FindResource(hInstance, MAKEINTRESOURCE(1), _T("MSI"));
  HGLOBAL hGlob = LoadResource(hInstance, hRes);
  DWORD dwSize = SizeofResource(hInstance, hRes);
  LPVOID pv  = LockResource(hGlob);
  TCHAR szDir[MAX_PATH];
  TCHAR szPath[MAX_PATH];

  GetTempPath(MAX_PATH, szDir);
  GetTempFileName(szDir, _T("tmp"), 0, szPath);
  DeleteFile(szPath);
  lstrcat(szPath, _T(".msi"));

  HANDLE hFile = CreateFile(szPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
  WriteFile(hFile, pv, dwSize, &dwSize, NULL);
  CloseHandle(hFile);

  SHELLEXECUTEINFO shex;

  ZeroMemory(&shex, sizeof(shex));

  shex.cbSize = sizeof(shex);
  shex.fMask = SEE_MASK_NOCLOSEPROCESS;

  shex.lpFile = szPath;

  if (ShellExecuteEx(&shex))
  {
    if (shex.hProcess)
    {
      WaitForSingleObject(shex.hProcess, INFINITE);
    }
  }
  while (!DeleteFile(szPath))
    Sleep(250);

  return 0;
}
Added tools/setup/exe/setup/setup.h.






>
>
>
1
2
3
#pragma once

#include "resource.h"
Added tools/setup/exe/setup/setup.rc.




















































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#define APSTUDIO_HIDDEN_SYMBOLS
#include "windows.h"
#undef APSTUDIO_HIDDEN_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE 
BEGIN
    "resource.h\0"
END

2 TEXTINCLUDE 
BEGIN
    "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
    "#include ""windows.h""\r\n"
    "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
    "\0"
END

3 TEXTINCLUDE 
BEGIN
    "\r\n"
    "\0"
END

#endif    // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// Version
//

VS_VERSION_INFO VERSIONINFO
 FILEVERSION 1,0,67,0
 PRODUCTVERSION 1,0,0,0
 FILEFLAGSMASK 0x17L
#ifdef _DEBUG
 FILEFLAGS 0x1L
#else
 FILEFLAGS 0x0L
#endif
 FILEOS 0x4L
 FILETYPE 0x1L
 FILESUBTYPE 0x0L
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904b0"
        BEGIN
            VALUE "Comments", "http://sqlite.phxsoftware.com"
            VALUE "FileDescription", "SQLite ADO.NET Setup"
            VALUE "FileVersion", "1.0.67.0"
            VALUE "InternalName", "setup"
            VALUE "LegalCopyright", "Released to the public domain"
            VALUE "OriginalFilename", "setup.exe"
            VALUE "ProductName", "System.Data.SQLite"
            VALUE "ProductVersion", "1.0"
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x409, 1200
    END
END


/////////////////////////////////////////////////////////////////////////////
//
// Icon
//

// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_SETUP               ICON                    ".\\install.ico"

/////////////////////////////////////////////////////////////////////////////
//
// MSI
//

1                       MSI                     "..\\..\\sqlite_setup.msi"
#endif    // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//


/////////////////////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKED

Added tools/setup/exe/setup/stdafx.cpp.
















>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
// stdafx.cpp : source file that includes just the standard includes
// setup.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information

#include "stdafx.h"

// TODO: reference any additional headers you need in STDAFX.H
// and not in this file
Added tools/setup/exe/setup/stdafx.h.










































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//

#pragma once

// Modify the following defines if you have to target a platform prior to the ones specified below.
// Refer to MSDN for the latest info on corresponding values for different platforms.
#ifndef WINVER				// Allow use of features specific to Windows XP or later.
#define WINVER 0x0500		// Change this to the appropriate value to target other versions of Windows.
#endif

#ifndef _WIN32_WINNT		// Allow use of features specific to Windows XP or later.                   
#define _WIN32_WINNT 0x0500	// Change this to the appropriate value to target other versions of Windows.
#endif						

#ifndef _WIN32_WINDOWS		// Allow use of features specific to Windows 98 or later.
#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
#endif

#ifndef _WIN32_IE			// Allow use of features specific to IE 6.0 or later.
#define _WIN32_IE 0x0500	// Change this to the appropriate value to target other versions of IE.
#endif

#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#include <windows.h>

// C RunTime Header Files
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#include <shellapi.h>

// TODO: reference additional headers your program requires here
Added tools/setup/install.ico.

cannot compute difference between binary files

Added tools/setup/sqlite_setup.vdproj.








































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
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
"DeployProject"
{
"VSVersion" = "3:800"
"ProjectType" = "8:{978C614F-708E-4E1A-B201-565925725DBA}"
"IsWebType" = "8:FALSE"
"ProjectName" = "8:sqlite_msi"
"LanguageId" = "3:1033"
"CodePage" = "3:1252"
"UILanguageId" = "3:1033"
"SccProjectName" = "8:"
"SccLocalPath" = "8:"
"SccAuxPath" = "8:"
"SccProvider" = "8:"
    "Hierarchy"
    {
        "Entry"
        {
        "MsmKey" = "8:_055B2BCD025C40A08F3B155843F41702"
        "OwnerKey" = "8:_UNDEFINED"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_26E74AC417994018832F9B82462AA3AF"
        "OwnerKey" = "8:_UNDEFINED"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_2C7EDFF06B61482393D94E3A63D90113"
        "OwnerKey" = "8:_UNDEFINED"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_33349D46CCFB4E16A3F7C6CE1FE6F6C9"
        "OwnerKey" = "8:_UNDEFINED"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_3ED55D8CC0EF87B27C01F6698F3EE7B2"
        "OwnerKey" = "8:_2C7EDFF06B61482393D94E3A63D90113"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_3ED55D8CC0EF87B27C01F6698F3EE7B2"
        "OwnerKey" = "8:_CE9E3EF0722342DB8DE0860C0DDCD39E"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_58B331DC63A74A74B1C85278A998798F"
        "OwnerKey" = "8:_UNDEFINED"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_60E2C442F77C48DE8150EBFC86663225"
        "OwnerKey" = "8:_UNDEFINED"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_B29C75F5F4D24817846DCEF9951068E1"
        "OwnerKey" = "8:_UNDEFINED"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_B6156897CBBB4E929D9C1F7358CE9E90"
        "OwnerKey" = "8:_UNDEFINED"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_C8E329AC56AD4C88A986481E639F72A5"
        "OwnerKey" = "8:_UNDEFINED"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_CE9E3EF0722342DB8DE0860C0DDCD39E"
        "OwnerKey" = "8:_UNDEFINED"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_D7FECFD3C8164DA7B3712AF54D0CDDAD"
        "OwnerKey" = "8:_UNDEFINED"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_UNDEFINED"
        "OwnerKey" = "8:_B29C75F5F4D24817846DCEF9951068E1"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_UNDEFINED"
        "OwnerKey" = "8:_CE9E3EF0722342DB8DE0860C0DDCD39E"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_UNDEFINED"
        "OwnerKey" = "8:_58B331DC63A74A74B1C85278A998798F"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_UNDEFINED"
        "OwnerKey" = "8:_2C7EDFF06B61482393D94E3A63D90113"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_UNDEFINED"
        "OwnerKey" = "8:_3ED55D8CC0EF87B27C01F6698F3EE7B2"
        "MsmSig" = "8:_UNDEFINED"
        }
    }
    "Configurations"
    {
        "Debug"
        {
        "DisplayName" = "8:Debug"
        "IsDebugOnly" = "11:TRUE"
        "IsReleaseOnly" = "11:FALSE"
        "OutputFilename" = "8:Debug\\sqlite_setup.msi"
        "PackageFilesAs" = "3:4"
        "PackageFileSize" = "3:-2147483648"
        "CabType" = "3:1"
        "Compression" = "3:3"
        "SignOutput" = "11:FALSE"
        "CertificateFile" = "8:"
        "PrivateKeyFile" = "8:"
        "TimeStampServer" = "8:"
        "InstallerBootstrapper" = "3:2"
            "BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}"
            {
            "Enabled" = "11:TRUE"
            "PromptEnabled" = "11:TRUE"
            "PrerequisitesLocation" = "2:1"
            "Url" = "8:"
            "ComponentsUrl" = "8:"
                "Items"
                {
                }
            }
        }
        "Release"
        {
        "DisplayName" = "8:Release"
        "IsDebugOnly" = "11:FALSE"
        "IsReleaseOnly" = "11:TRUE"
        "OutputFilename" = "8:sqlite_setup.msi"
        "PackageFilesAs" = "3:2"
        "PackageFileSize" = "3:-2147483648"
        "CabType" = "3:1"
        "Compression" = "3:3"
        "SignOutput" = "11:FALSE"
        "CertificateFile" = "8:"
        "PrivateKeyFile" = "8:"
        "TimeStampServer" = "8:"
        "InstallerBootstrapper" = "3:2"
            "BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}"
            {
            "Enabled" = "11:FALSE"
            "PromptEnabled" = "11:TRUE"
            "PrerequisitesLocation" = "2:1"
            "Url" = "8:"
            "ComponentsUrl" = "8:"
                "Items"
                {
                    "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:Microsoft.Net.Framework.2.0"
                    {
                    "Name" = "8:.NET Framework 2.0"
                    "ProductCode" = "8:Microsoft.Net.Framework.2.0"
                    }
                }
            }
        }
    }
    "Deployable"
    {
        "CustomAction"
        {
        }
        "DefaultFeature"
        {
        "Name" = "8:DefaultFeature"
        "Title" = "8:"
        "Description" = "8:"
        }
        "ExternalPersistence"
        {
            "LaunchCondition"
            {
                "{A06ECF26-33A3-4562-8140-9B0E340D4F24}:_2A5202AB8FA440F9AA45DF7B9C7CEAD5"
                {
                "Name" = "8:.NET Framework"
                "Message" = "8:[VSDNETMSG]"
                "FrameworkVersion" = "8:2.0.50727     "
                "AllowLaterVersions" = "11:TRUE"
                "InstallUrl" = "8:http://go.microsoft.com/fwlink/?LinkId=9832"
                }
            }
        }
        "File"
        {
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_055B2BCD025C40A08F3B155843F41702"
            {
            "SourcePath" = "8:..\\..\\bin\\test.exe.config"
            "TargetName" = "8:test.exe.config"
            "Tag" = "8:"
            "Folder" = "8:_30C77BF2E6E84D01ADE5FB8BA2F81504"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:FALSE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_26E74AC417994018832F9B82462AA3AF"
            {
            "SourcePath" = "8:..\\..\\bin\\x64\\System.Data.SQLite.lib"
            "TargetName" = "8:System.Data.SQLite.lib"
            "Tag" = "8:"
            "Folder" = "8:_66DBD0998AA8499691D4F5E42417697D"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:FALSE"
            "IsolateTo" = "8:"
            }
            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_2C7EDFF06B61482393D94E3A63D90113"
            {
            "AssemblyRegister" = "3:1"
            "AssemblyIsInGAC" = "11:FALSE"
            "AssemblyAsmDisplayName" = "8:test, Version=1.0.0.40629, Culture=neutral, processorArchitecture=x86"
                "ScatterAssemblies"
                {
                    "_2C7EDFF06B61482393D94E3A63D90113"
                    {
                    "Name" = "8:test.exe"
                    "Attributes" = "3:512"
                    }
                }
            "SourcePath" = "8:..\\..\\bin\\test.exe"
            "TargetName" = "8:"
            "Tag" = "8:"
            "Folder" = "8:_30C77BF2E6E84D01ADE5FB8BA2F81504"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:FALSE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_33349D46CCFB4E16A3F7C6CE1FE6F6C9"
            {
            "SourcePath" = "8:..\\..\\bin\\System.Data.SQLite.XML"
            "TargetName" = "8:System.Data.SQLite.XML"
            "Tag" = "8:"
            "Folder" = "8:_30C77BF2E6E84D01ADE5FB8BA2F81504"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:FALSE"
            "IsolateTo" = "8:"
            }
            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_3ED55D8CC0EF87B27C01F6698F3EE7B2"
            {
            "AssemblyRegister" = "3:1"
            "AssemblyIsInGAC" = "11:FALSE"
            "AssemblyAsmDisplayName" = "8:System.Data.SQLite, Version=1.0.67.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=x86"
                "ScatterAssemblies"
                {
                    "_3ED55D8CC0EF87B27C01F6698F3EE7B2"
                    {
                    "Name" = "8:System.Data.SQLite.DLL"
                    "Attributes" = "3:512"
                    }
                }
            "SourcePath" = "8:System.Data.SQLite.DLL"
            "TargetName" = "8:"
            "Tag" = "8:"
            "Folder" = "8:_30C77BF2E6E84D01ADE5FB8BA2F81504"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:TRUE"
            "IsolateTo" = "8:"
            }
            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_58B331DC63A74A74B1C85278A998798F"
            {
            "AssemblyRegister" = "3:1"
            "AssemblyIsInGAC" = "11:FALSE"
            "AssemblyAsmDisplayName" = "8:System.Data.SQLite, Version=1.0.67.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=x86"
                "ScatterAssemblies"
                {
                    "_58B331DC63A74A74B1C85278A998798F"
                    {
                    "Name" = "8:System.Data.SQLite.DLL"
                    "Attributes" = "3:512"
                    }
                }
            "SourcePath" = "8:..\\..\\bin\\System.Data.SQLite.DLL"
            "TargetName" = "8:"
            "Tag" = "8:"
            "Folder" = "8:_A0841E79B7874F7288672343934C7657"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:FALSE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_60E2C442F77C48DE8150EBFC86663225"
            {
            "SourcePath" = "8:..\\..\\Doc\\SQLite.NET.chm"
            "TargetName" = "8:SQLite.NET.chm"
            "Tag" = "8:"
            "Folder" = "8:_CA5E61837F5B452B8169C698979CF05C"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:FALSE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B29C75F5F4D24817846DCEF9951068E1"
            {
            "SourcePath" = "8:..\\..\\bin\\x64\\System.Data.SQLite.DLL"
            "TargetName" = "8:System.Data.SQLite.DLL"
            "Tag" = "8:"
            "Folder" = "8:_66DBD0998AA8499691D4F5E42417697D"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:FALSE"
            "IsolateTo" = "8:"
            "AssemblyAsmDisplayName" = "8:System.Data.SQLite, Version=1.0.27.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=AMD64"
            "AssemblyIsInGAC" = "11:FALSE"
            "AssemblyRegister" = "3:1"
                "ScatterAssemblies"
                {
                    "_B29C75F5F4D24817846DCEF9951068E1"
                    {
                    "Attributes" = "3:512"
                    "Name" = "8:System.Data.SQLite.DLL"
                    }
                }
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B6156897CBBB4E929D9C1F7358CE9E90"
            {
            "SourcePath" = "8:topband.jpg"
            "TargetName" = "8:topband.jpg"
            "Tag" = "8:"
            "Folder" = "8:_A0841E79B7874F7288672343934C7657"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:TRUE"
            "IsDependency" = "11:FALSE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_C8E329AC56AD4C88A986481E639F72A5"
            {
            "SourcePath" = "8:..\\..\\readme.htm"
            "TargetName" = "8:readme.htm"
            "Tag" = "8:"
            "Folder" = "8:_A0841E79B7874F7288672343934C7657"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:FALSE"
            "IsolateTo" = "8:"
            }
            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_CE9E3EF0722342DB8DE0860C0DDCD39E"
            {
            "AssemblyRegister" = "3:1"
            "AssemblyIsInGAC" = "11:FALSE"
            "AssemblyAsmDisplayName" = "8:System.Data.SQLite.Linq, Version=1.0.38.1, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=MSIL"
                "ScatterAssemblies"
                {
                    "_CE9E3EF0722342DB8DE0860C0DDCD39E"
                    {
                    "Name" = "8:System.Data.SQLite.Linq.dll"
                    "Attributes" = "3:512"
                    }
                }
            "SourcePath" = "8:..\\..\\bin\\System.Data.SQLite.Linq.dll"
            "TargetName" = "8:"
            "Tag" = "8:"
            "Folder" = "8:_30C77BF2E6E84D01ADE5FB8BA2F81504"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:FALSE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D7FECFD3C8164DA7B3712AF54D0CDDAD"
            {
            "SourcePath" = "8:..\\..\\bin\\System.Data.SQLite.lib"
            "TargetName" = "8:System.Data.SQLite.lib"
            "Tag" = "8:"
            "Folder" = "8:_30C77BF2E6E84D01ADE5FB8BA2F81504"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:FALSE"
            "IsolateTo" = "8:"
            }
        }
        "FileType"
        {
        }
        "Folder"
        {
            "{3C67513D-01DD-4637-8A68-80971EB9504F}:_A0841E79B7874F7288672343934C7657"
            {
            "DefaultLocation" = "8:[ProgramFilesFolder]SQLite.NET4"
            "Name" = "8:#1925"
            "AlwaysCreate" = "11:FALSE"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Property" = "8:TARGETDIR"
                "Folders"
                {
                    "{9EF0B969-E518-4E46-987F-47570745A589}:_30C77BF2E6E84D01ADE5FB8BA2F81504"
                    {
                    "Name" = "8:bin"
                    "AlwaysCreate" = "11:FALSE"
                    "Condition" = "8:"
                    "Transitive" = "11:FALSE"
                    "Property" = "8:_BD4105DB73B04559A56BB70C4E151056"
                        "Folders"
                        {
                            "{9EF0B969-E518-4E46-987F-47570745A589}:_66DBD0998AA8499691D4F5E42417697D"
                            {
                            "Name" = "8:x64"
                            "AlwaysCreate" = "11:FALSE"
                            "Condition" = "8:"
                            "Transitive" = "11:FALSE"
                            "Property" = "8:_7C07DE0299AB478C8BC7AFB40E220305"
                                "Folders"
                                {
                                }
                            }
                            "{9EF0B969-E518-4E46-987F-47570745A589}:_F11D54EE0EEA4BF59B52E621630B6A2E"
                            {
                            "Name" = "8:Designer"
                            "AlwaysCreate" = "11:FALSE"
                            "Condition" = "8:"
                            "Transitive" = "11:FALSE"
                            "Property" = "8:_CA865020181A40EEB518ACF5F89BD66A"
                                "Folders"
                                {
                                }
                            }
                        }
                    }
                    "{9EF0B969-E518-4E46-987F-47570745A589}:_CA5E61837F5B452B8169C698979CF05C"
                    {
                    "Name" = "8:Doc"
                    "AlwaysCreate" = "11:FALSE"
                    "Condition" = "8:"
                    "Transitive" = "11:FALSE"
                    "Property" = "8:_B787482AA405492D998CAAD43761AF61"
                        "Folders"
                        {
                        }
                    }
                }
            }
            "{1525181F-901A-416C-8A58-119130FE478E}:_AB7F365F78A44DE79C7007FB08F7343E"
            {
            "Name" = "8:#1916"
            "AlwaysCreate" = "11:FALSE"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Property" = "8:DesktopFolder"
                "Folders"
                {
                }
            }
            "{1525181F-901A-416C-8A58-119130FE478E}:_E420345AA61B4AF780EEA7BC8AFAF268"
            {
            "Name" = "8:#1919"
            "AlwaysCreate" = "11:FALSE"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Property" = "8:ProgramMenuFolder"
                "Folders"
                {
                    "{9EF0B969-E518-4E46-987F-47570745A589}:_1B562A9F876E47058AB813C418E24FBF"
                    {
                    "Name" = "8:SQLite.NET4"
                    "AlwaysCreate" = "11:FALSE"
                    "Condition" = "8:"
                    "Transitive" = "11:FALSE"
                    "Property" = "8:_85ED61DA38214E1C9AB39E119A89D75B"
                        "Folders"
                        {
                        }
                    }
                }
            }
        }
        "LaunchCondition"
        {
        }
        "Locator"
        {
        }
        "MsiBootstrapper"
        {
        "LangId" = "3:1033"
        "RequiresElevation" = "11:FALSE"
        }
        "Product"
        {
        "Name" = "8:Microsoft Visual Studio"
        "ProductName" = "8:SQLite ADO.NET Provider"
        "ProductCode" = "8:{902C69AF-5B0C-4E21-89F2-064462C2BBC4}"
        "PackageCode" = "8:{73B9EABC-05DF-499D-B771-8FB6F1E5AF1B}"
        "UpgradeCode" = "8:{E779C0FF-CCE2-493A-B8C2-6DD04E26072C}"
        "AspNetVersion" = "8:4.0.30319.0"
        "RestartWWWService" = "11:FALSE"
        "RemovePreviousVersions" = "11:TRUE"
        "DetectNewerInstalledVersion" = "11:TRUE"
        "InstallAllUsers" = "11:TRUE"
        "ProductVersion" = "8:1.066.1"
        "Manufacturer" = "8:Phoenix Software Solutions, LLC"
        "ARPHELPTELEPHONE" = "8:"
        "ARPHELPLINK" = "8:http://sqlite.phxsoftware.com"
        "Title" = "8:SQLite ADO.NET Provider"
        "Subject" = "8:"
        "ARPCONTACT" = "8:Phoenix Software Solutions, LLC"
        "Keywords" = "8:"
        "ARPCOMMENTS" = "8:"
        "ARPURLINFOABOUT" = "8:"
        "ARPPRODUCTICON" = "8:"
        "ARPIconIndex" = "3:0"
        "SearchPath" = "8:"
        "UseSystemSearchPath" = "11:TRUE"
        "TargetPlatform" = "3:0"
        "PreBuildEvent" = "8:"
        "PostBuildEvent" = "8:"
        "RunPostBuildEvent" = "3:0"
        }
        "Registry"
        {
            "HKLM"
            {
                "Keys"
                {
                }
            }
            "HKCU"
            {
                "Keys"
                {
                }
            }
            "HKCR"
            {
                "Keys"
                {
                }
            }
            "HKU"
            {
                "Keys"
                {
                }
            }
            "HKPU"
            {
                "Keys"
                {
                }
            }
        }
        "Sequences"
        {
        }
        "Shortcut"
        {
            "{970C0BB2-C7D0-45D7-ABFA-7EC378858BC0}:_920202B002F9475288A945B0C8361A44"
            {
            "Name" = "8:SQLite Test Application"
            "Arguments" = "8:"
            "Description" = "8:"
            "ShowCmd" = "3:1"
            "IconIndex" = "3:0"
            "Transitive" = "11:FALSE"
            "Target" = "8:_2C7EDFF06B61482393D94E3A63D90113"
            "Folder" = "8:_1B562A9F876E47058AB813C418E24FBF"
            "WorkingFolder" = "8:_30C77BF2E6E84D01ADE5FB8BA2F81504"
            "Icon" = "8:"
            "Feature" = "8:"
            }
            "{970C0BB2-C7D0-45D7-ABFA-7EC378858BC0}:_CC64AEB6D8A643F7BC8EB95EBC803EB5"
            {
            "Name" = "8:Help"
            "Arguments" = "8:"
            "Description" = "8:"
            "ShowCmd" = "3:1"
            "IconIndex" = "3:0"
            "Transitive" = "11:FALSE"
            "Target" = "8:_60E2C442F77C48DE8150EBFC86663225"
            "Folder" = "8:_1B562A9F876E47058AB813C418E24FBF"
            "WorkingFolder" = "8:_CA5E61837F5B452B8169C698979CF05C"
            "Icon" = "8:"
            "Feature" = "8:"
            }
        }
        "UserInterface"
        {
            "{2479F3F5-0309-486D-8047-8187E2CE5BA0}:_027E806A39AD4FCD8E7A4EBE86AD3DF3"
            {
            "UseDynamicProperties" = "11:FALSE"
            "IsDependency" = "11:FALSE"
            "SourcePath" = "8:<VsdDialogDir>\\VsdUserInterface.wim"
            }
            "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_349E960F62F043E79FD080CB87E24922"
            {
            "Name" = "8:#1902"
            "Sequence" = "3:2"
            "Attributes" = "3:3"
                "Dialogs"
                {
                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_F1CAA16A464043FBB06804165AB31D0C"
                    {
                    "Sequence" = "3:100"
                    "DisplayName" = "8:Finished"
                    "UseDynamicProperties" = "11:TRUE"
                    "IsDependency" = "11:FALSE"
                    "SourcePath" = "8:<VsdDialogDir>\\VsdAdminFinishedDlg.wid"
                        "Properties"
                        {
                            "BannerBitmap"
                            {
                            "Name" = "8:BannerBitmap"
                            "DisplayName" = "8:#1001"
                            "Description" = "8:#1101"
                            "Type" = "3:8"
                            "ContextData" = "8:Bitmap"
                            "Attributes" = "3:4"
                            "Setting" = "3:2"
                            "Value" = "8:_B6156897CBBB4E929D9C1F7358CE9E90"
                            "UsePlugInResources" = "11:TRUE"
                            }
                        }
                    }
                }
            }
            "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_3CB3696DF5D54FCA98E2BF3D4579451E"
            {
            "Name" = "8:#1901"
            "Sequence" = "3:1"
            "Attributes" = "3:2"
                "Dialogs"
                {
                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_1DBE83588B574F75A6233D46A3234D69"
                    {
                    "Sequence" = "3:100"
                    "DisplayName" = "8:Progress"
                    "UseDynamicProperties" = "11:TRUE"
                    "IsDependency" = "11:FALSE"
                    "SourcePath" = "8:<VsdDialogDir>\\VsdProgressDlg.wid"
                        "Properties"
                        {
                            "BannerBitmap"
                            {
                            "Name" = "8:BannerBitmap"
                            "DisplayName" = "8:#1001"
                            "Description" = "8:#1101"
                            "Type" = "3:8"
                            "ContextData" = "8:Bitmap"
                            "Attributes" = "3:4"
                            "Setting" = "3:2"
                            "Value" = "8:_B6156897CBBB4E929D9C1F7358CE9E90"
                            "UsePlugInResources" = "11:TRUE"
                            }
                            "ShowProgress"
                            {
                            "Name" = "8:ShowProgress"
                            "DisplayName" = "8:#1009"
                            "Description" = "8:#1109"
                            "Type" = "3:5"
                            "ContextData" = "8:1;True=1;False=0"
                            "Attributes" = "3:0"
                            "Setting" = "3:0"
                            "Value" = "3:1"
                            "DefaultValue" = "3:1"
                            "UsePlugInResources" = "11:TRUE"
                            }
                        }
                    }
                }
            }
            "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_573543E04AA54E9387CD1AAF21220444"
            {
            "Name" = "8:#1902"
            "Sequence" = "3:1"
            "Attributes" = "3:3"
                "Dialogs"
                {
                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_991B7280E37E4C23A54CC7027F774891"
                    {
                    "Sequence" = "3:100"
                    "DisplayName" = "8:Finished"
                    "UseDynamicProperties" = "11:TRUE"
                    "IsDependency" = "11:FALSE"
                    "SourcePath" = "8:<VsdDialogDir>\\VsdFinishedDlg.wid"
                        "Properties"
                        {
                            "BannerBitmap"
                            {
                            "Name" = "8:BannerBitmap"
                            "DisplayName" = "8:#1001"
                            "Description" = "8:#1101"
                            "Type" = "3:8"
                            "ContextData" = "8:Bitmap"
                            "Attributes" = "3:4"
                            "Setting" = "3:2"
                            "Value" = "8:_B6156897CBBB4E929D9C1F7358CE9E90"
                            "UsePlugInResources" = "11:TRUE"
                            }
                            "UpdateText"
                            {
                            "Name" = "8:UpdateText"
                            "DisplayName" = "8:#1058"
                            "Description" = "8:#1158"
                            "Type" = "3:15"
                            "ContextData" = "8:"
                            "Attributes" = "3:0"
                            "Setting" = "3:1"
                            "Value" = "8:#1258"
                            "DefaultValue" = "8:#1258"
                            "UsePlugInResources" = "11:TRUE"
                            }
                        }
                    }
                }
            }
            "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_5E0AF2B2658547308882EEE91399D911"
            {
            "Name" = "8:#1901"
            "Sequence" = "3:2"
            "Attributes" = "3:2"
                "Dialogs"
                {
                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_82FCCA944F324BA18F0E3E01BCA1E60B"
                    {
                    "Sequence" = "3:100"
                    "DisplayName" = "8:Progress"
                    "UseDynamicProperties" = "11:TRUE"
                    "IsDependency" = "11:FALSE"
                    "SourcePath" = "8:<VsdDialogDir>\\VsdAdminProgressDlg.wid"
                        "Properties"
                        {
                            "BannerBitmap"
                            {
                            "Name" = "8:BannerBitmap"
                            "DisplayName" = "8:#1001"
                            "Description" = "8:#1101"
                            "Type" = "3:8"
                            "ContextData" = "8:Bitmap"
                            "Attributes" = "3:4"
                            "Setting" = "3:2"
                            "Value" = "8:_B6156897CBBB4E929D9C1F7358CE9E90"
                            "UsePlugInResources" = "11:TRUE"
                            }
                            "ShowProgress"
                            {
                            "Name" = "8:ShowProgress"
                            "DisplayName" = "8:#1009"
                            "Description" = "8:#1109"
                            "Type" = "3:5"
                            "ContextData" = "8:1;True=1;False=0"
                            "Attributes" = "3:0"
                            "Setting" = "3:0"
                            "Value" = "3:1"
                            "DefaultValue" = "3:1"
                            "UsePlugInResources" = "11:TRUE"
                            }
                        }
                    }
                }
            }
            "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_7046F6E46106420BA50AA9A9ED86389A"
            {
            "Name" = "8:#1900"
            "Sequence" = "3:1"
            "Attributes" = "3:1"
                "Dialogs"
                {
                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_03C4F0FAD7804F3DAE9A980E584F691E"
                    {
                    "Sequence" = "3:300"
                    "DisplayName" = "8:Confirm Installation"
                    "UseDynamicProperties" = "11:TRUE"
                    "IsDependency" = "11:FALSE"
                    "SourcePath" = "8:<VsdDialogDir>\\VsdConfirmDlg.wid"
                        "Properties"
                        {
                            "BannerBitmap"
                            {
                            "Name" = "8:BannerBitmap"
                            "DisplayName" = "8:#1001"
                            "Description" = "8:#1101"
                            "Type" = "3:8"
                            "ContextData" = "8:Bitmap"
                            "Attributes" = "3:4"
                            "Setting" = "3:2"
                            "Value" = "8:_B6156897CBBB4E929D9C1F7358CE9E90"
                            "UsePlugInResources" = "11:TRUE"
                            }
                        }
                    }
                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_4B4F0FAA5A094FCC952CA8A93DEA0F04"
                    {
                    "Sequence" = "3:100"
                    "DisplayName" = "8:Welcome"
                    "UseDynamicProperties" = "11:TRUE"
                    "IsDependency" = "11:FALSE"
                    "SourcePath" = "8:<VsdDialogDir>\\VsdWelcomeDlg.wid"
                        "Properties"
                        {
                            "BannerBitmap"
                            {
                            "Name" = "8:BannerBitmap"
                            "DisplayName" = "8:#1001"
                            "Description" = "8:#1101"
                            "Type" = "3:8"
                            "ContextData" = "8:Bitmap"
                            "Attributes" = "3:4"
                            "Setting" = "3:2"
                            "Value" = "8:_B6156897CBBB4E929D9C1F7358CE9E90"
                            "UsePlugInResources" = "11:TRUE"
                            }
                            "CopyrightWarning"
                            {
                            "Name" = "8:CopyrightWarning"
                            "DisplayName" = "8:#1002"
                            "Description" = "8:#1102"
                            "Type" = "3:3"
                            "ContextData" = "8:"
                            "Attributes" = "3:0"
                            "Setting" = "3:2"
                            "Value" = "8:"
                            "DefaultValue" = "8:#1202"
                            "UsePlugInResources" = "11:TRUE"
                            }
                            "Welcome"
                            {
                            "Name" = "8:Welcome"
                            "DisplayName" = "8:#1003"
                            "Description" = "8:#1103"
                            "Type" = "3:3"
                            "ContextData" = "8:"
                            "Attributes" = "3:0"
                            "Setting" = "3:1"
                            "Value" = "8:#1203"
                            "DefaultValue" = "8:#1203"
                            "UsePlugInResources" = "11:TRUE"
                            }
                        }
                    }
                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_CAD4CD70D47945E7A7FCD4428405F7FD"
                    {
                    "Sequence" = "3:200"
                    "DisplayName" = "8:Installation Folder"
                    "UseDynamicProperties" = "11:TRUE"
                    "IsDependency" = "11:FALSE"
                    "SourcePath" = "8:<VsdDialogDir>\\VsdFolderDlg.wid"
                        "Properties"
                        {
                            "BannerBitmap"
                            {
                            "Name" = "8:BannerBitmap"
                            "DisplayName" = "8:#1001"
                            "Description" = "8:#1101"
                            "Type" = "3:8"
                            "ContextData" = "8:Bitmap"
                            "Attributes" = "3:4"
                            "Setting" = "3:2"
                            "Value" = "8:_B6156897CBBB4E929D9C1F7358CE9E90"
                            "UsePlugInResources" = "11:TRUE"
                            }
                            "InstallAllUsersVisible"
                            {
                            "Name" = "8:InstallAllUsersVisible"
                            "DisplayName" = "8:#1059"
                            "Description" = "8:#1159"
                            "Type" = "3:5"
                            "ContextData" = "8:1;True=1;False=0"
                            "Attributes" = "3:0"
                            "Setting" = "3:0"
                            "Value" = "3:1"
                            "DefaultValue" = "3:1"
                            "UsePlugInResources" = "11:TRUE"
                            }
                        }
                    }
                }
            }
            "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_A95B4EFD2C5249848F009D88CBA3739B"
            {
            "Name" = "8:#1900"
            "Sequence" = "3:2"
            "Attributes" = "3:1"
                "Dialogs"
                {
                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_101B4B845E67488FB6A0AC097773DA38"
                    {
                    "Sequence" = "3:300"
                    "DisplayName" = "8:Confirm Installation"
                    "UseDynamicProperties" = "11:TRUE"
                    "IsDependency" = "11:FALSE"
                    "SourcePath" = "8:<VsdDialogDir>\\VsdAdminConfirmDlg.wid"
                        "Properties"
                        {
                            "BannerBitmap"
                            {
                            "Name" = "8:BannerBitmap"
                            "DisplayName" = "8:#1001"
                            "Description" = "8:#1101"
                            "Type" = "3:8"
                            "ContextData" = "8:Bitmap"
                            "Attributes" = "3:4"
                            "Setting" = "3:2"
                            "Value" = "8:_B6156897CBBB4E929D9C1F7358CE9E90"
                            "UsePlugInResources" = "11:TRUE"
                            }
                        }
                    }
                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_1AD3D10EBB64435985C57A85063E6CDF"
                    {
                    "Sequence" = "3:100"
                    "DisplayName" = "8:Welcome"
                    "UseDynamicProperties" = "11:TRUE"
                    "IsDependency" = "11:FALSE"
                    "SourcePath" = "8:<VsdDialogDir>\\VsdAdminWelcomeDlg.wid"
                        "Properties"
                        {
                            "BannerBitmap"
                            {
                            "Name" = "8:BannerBitmap"
                            "DisplayName" = "8:#1001"
                            "Description" = "8:#1101"
                            "Type" = "3:8"
                            "ContextData" = "8:Bitmap"
                            "Attributes" = "3:4"
                            "Setting" = "3:2"
                            "Value" = "8:_B6156897CBBB4E929D9C1F7358CE9E90"
                            "UsePlugInResources" = "11:TRUE"
                            }
                            "CopyrightWarning"
                            {
                            "Name" = "8:CopyrightWarning"
                            "DisplayName" = "8:#1002"
                            "Description" = "8:#1102"
                            "Type" = "3:3"
                            "ContextData" = "8:"
                            "Attributes" = "3:0"
                            "Setting" = "3:2"
                            "Value" = "8:"
                            "DefaultValue" = "8:#1202"
                            "UsePlugInResources" = "11:TRUE"
                            }
                            "Welcome"
                            {
                            "Name" = "8:Welcome"
                            "DisplayName" = "8:#1003"
                            "Description" = "8:#1103"
                            "Type" = "3:3"
                            "ContextData" = "8:"
                            "Attributes" = "3:0"
                            "Setting" = "3:1"
                            "Value" = "8:#1203"
                            "DefaultValue" = "8:#1203"
                            "UsePlugInResources" = "11:TRUE"
                            }
                        }
                    }
                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_F5C2368EB13F47EF8808B4E5855A647B"
                    {
                    "Sequence" = "3:200"
                    "DisplayName" = "8:Installation Folder"
                    "UseDynamicProperties" = "11:TRUE"
                    "IsDependency" = "11:FALSE"
                    "SourcePath" = "8:<VsdDialogDir>\\VsdAdminFolderDlg.wid"
                        "Properties"
                        {
                            "BannerBitmap"
                            {
                            "Name" = "8:BannerBitmap"
                            "DisplayName" = "8:#1001"
                            "Description" = "8:#1101"
                            "Type" = "3:8"
                            "ContextData" = "8:Bitmap"
                            "Attributes" = "3:4"
                            "Setting" = "3:2"
                            "Value" = "8:_B6156897CBBB4E929D9C1F7358CE9E90"
                            "UsePlugInResources" = "11:TRUE"
                            }
                        }
                    }
                }
            }
            "{2479F3F5-0309-486D-8047-8187E2CE5BA0}:_F02FDE6DA53449159DF6E6441E2314C9"
            {
            "UseDynamicProperties" = "11:FALSE"
            "IsDependency" = "11:FALSE"
            "SourcePath" = "8:<VsdDialogDir>\\VsdBasicDialogs.wim"
            }
        }
        "MergeModule"
        {
        }
        "ProjectOutput"
        {
        }
    }
}
Added tools/setup/topband.jpg.

cannot compute difference between binary files

Deleted www/art/sqlite100.png.

cannot compute difference between binary files

Deleted www/art/sqlite200.png.

cannot compute difference between binary files

Deleted www/art/sqlite32.png.

cannot compute difference between binary files

Changes to www/build.wiki.
15
16
17
18
19
20
21
22
23
24
25
26
27
28

29
30
31
32
33
34
35

<p>
  The new build system has been setup using modular solution, project, and
  property files.
</p>

<p>
  In general, files with 2008 in the name (e.g.
  &quot;SQLite.Interop.2008.vcproj&quot;) or files ending in
  &quot;.vsprops&quot; are project and property files for the Visual Studio 2008
  solution.  Files with 2010 in the name (e.g.
  &quot;SQLite.Interop.2010.vcxproj&quot;) or files ending in &quot;.props&quot;
  are project and property files for the Visual Studio 2010 solution.  When
  making changes, you should make changes to both to keep them in sync.

</p>

<p>
  You can either [./build.wiki#manual | manually build] the System.Data.SQLite
  binaries using one of the supplied Visual Studio solutions or follow the steps
  outlined in the [./build.wiki#automated | Automated Build] section below.
</p>







|
<
|
|
|
<
|
>







15
16
17
18
19
20
21
22

23
24
25

26
27
28
29
30
31
32
33
34

<p>
  The new build system has been setup using modular solution, project, and
  property files.
</p>

<p>
  In general, files with 2008 in the name (e.g. SQLite.Interop.2008.vcproj) or

  files ending in .vsprops are project and property files for the Visual Studio
  2008 solution.  Files with 2010 in the name (e.g. SQLite.Interop.2010.vcxproj)
  or files ending in .props are property and project files for the Visual Studio

  2010 solution.  When making changes, you should make changes to both to keep
  them in sync.
</p>

<p>
  You can either [./build.wiki#manual | manually build] the System.Data.SQLite
  binaries using one of the supplied Visual Studio solutions or follow the steps
  outlined in the [./build.wiki#automated | Automated Build] section below.
</p>
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
  </li>

  <li>
    We want to ship native binaries that rely on the Visual C++ 2008 Runtime.
  </li>

  <li>
    We want to ship the separate managed-only &quot;System.Data.SQLite.dll&quot;
    assembly and the &quot;SQLite.Interop.dll&quot; native library.  This will
    make it easier to maintain and deploy the included core SQLite code (in the
    &quot;SQLite.Interop.dll&quot; native library).  We also want to ship the
    &quot;monster DLL&quot; (i.e. the mixed-mode
    &quot;System.Data.SQLite.dll&quot; assembly that includes all the necessary
    native and managed code).  This will make it easier for developers that wish
    to register the assembly in the Global Assembly Cache (GAC).
  </li>

  <li>
    The machine used to prepare the official releases will have the
    [http://www.microsoft.com/downloads/en/details.aspx?FamilyID=ab99342f-5d1a-413d-8319-81da479ab0d7 | .NET Framework 3.5 SP1]
    and the corresponding
    [http://www.microsoft.com/downloads/details.aspx?FamilyId=E6E1C3DF-A74F-4207-8586-711EBE331CDC | SDK]
    installed.
  </li>

  <li>
    The machine used to prepare the official releases will have
    [http://www.jrsoftware.org/isdl.php | Inno Setup 5.4.2] or higher installed
    in &quot;%ProgramFiles%\Inno Setup 5&quot; or &quot;%ProgramFiles(x86)%\Inno
    Setup 5&quot; for an 64-bit machines.  Alternatively, the Inno Setup
    directory may be included in the PATH environment variable.
  </li>

  <li>
    The string &quot;&lt;root&gt;&quot; represents the root of your source tree
    for the System.Data.SQLite project.
  </li>

  <li>
    The string &quot;&lt;year&gt;&quot; represents the version of Visual Studio
    being used (e.g. 2008).
  </li>
</ol>







|
|
|
|
<
|
|
|





<
|







|





|







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

  <li>
    We want to ship native binaries that rely on the Visual C++ 2008 Runtime.
  </li>

  <li>
    We want to ship the separate managed-only System.Data.SQLite assembly and
    the SQLite.Interop.dll native library.  This will make it easier to maintain
    and deploy the included core SQLite code (in the &quot;SQLite.Interop.dll&quot;
    native library).  We also want to ship the &quot;monster DLL&quot; (i.e. the

    &quot;mixed-mode&quot; System.Data.SQLite assembly that includes all the
    necessary native and managed code).  This will make it easier for developers
    that wish to register the assembly in the Global Assembly Cache (GAC).
  </li>

  <li>
    The machine used to prepare the official releases will have the
    [http://www.microsoft.com/downloads/en/details.aspx?FamilyID=ab99342f-5d1a-413d-8319-81da479ab0d7 | .NET Framework 3.5 SP1]

    and the corresponding [http://www.microsoft.com/downloads/details.aspx?FamilyId=E6E1C3DF-A74F-4207-8586-711EBE331CDC | SDK]
    installed.
  </li>

  <li>
    The machine used to prepare the official releases will have
    [http://www.jrsoftware.org/isdl.php | Inno Setup 5.4.2] or higher installed
    in &quot;%ProgramFiles%\Inno Setup 5&quot; or &quot;%ProgramFiles(x86)%\Inno
    Setup 5&quot; for an 64-bit machines.  Alternatively, the InnoSetup
    directory may be included in the PATH environment variable.
  </li>

  <li>
    The string &quot;&lt;root&gt;&quot; represents the root of your source tree
    for System.Data.SQLite.
  </li>

  <li>
    The string &quot;&lt;year&gt;&quot; represents the version of Visual Studio
    being used (e.g. 2008).
  </li>
</ol>
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
  </li>

  <li>
    Make sure the version information is correct for System.Data.SQLite in the
    following files:

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

      <li>&lt;root&gt;\SQLite.Interop\props\SQLite.Interop.vsprops</li>
      <li>&lt;root&gt;\SQLite.Interop\props\SQLite.Interop.props</li>
      <li>&lt;root&gt;\SQLite.Interop\src\win\interop.h</li>
      <li>&lt;root&gt;\System.Data.SQLite\AssemblyInfo.cs</li>
      <li>&lt;root&gt;\System.Data.SQLite\SQLite3.cs</li>
      <li>&lt;root&gt;\System.Data.SQLite\UnsafeNativeMethods.cs</li>
      <li>&lt;root&gt;\System.Data.SQLite.Linq\AssemblyInfo.cs</li>
      <li>&lt;root&gt;\test\AssemblyInfo.cs</li>
      <li>&lt;root&gt;\test\app.config</li>
      <li>&lt;root&gt;\testce\AssemblyInfo.cs</li>
      <li>&lt;root&gt;\testlinq\2008\App.config</li>
      <li>&lt;root&gt;\testlinq\2010\App.config</li>
      <li>&lt;root&gt;\testlinq\Properties\AssemblyInfo.cs</li>
      <li>&lt;root&gt;\Tests\version.eagle</li>
      <li>&lt;root&gt;\tools\install\Properties\AssemblyInfo.cs</li>
    </ul>

    You'll need to update the INTEROP_BUILD_NUMBER, INTEROP_MANIFEST_VERSION,
    and INTEROP_RC_VERSION properties in the &quot;.vsprops&quot; and
    &quot;.props&quot; files, and the INTEROP_VERSION define in
    &quot;interop.h&quot;.  This version number should track the release
    versions of the System.Data.SQLite packages (i.e. [./news.wiki | 1.0.x]).
  </li>
</ol>

<a name="manual"></a>
<h2>Manual Build</h2>

<ol>
  <li>
    Complete the steps outlined in the [./build.wiki#all | All Builds] section
    (above).
  </li>

  <li>
    Open the appropriate solution for your build platform.

    <ul>
      <li>
        The &quot;SQLite.NET.2008.sln&quot; file is the top-level solution
        primarily designed for use with Visual Studio 2008 in the IDE; however,
        it may also be used from the command line with MSBuild 3.5.
      </li>

      <li>
        The &quot;SQLite.NET.2010.sln&quot; file is the top-level solution
        primarily designed for use with Visual Studio 2010 in the IDE; however,
        it may also be used from the command line with MSBuild 4.0.
      </li>

      <li>
        The &quot;SQLite.NET.2008.MSBuild.sln&quot; file is the top-level
        solution primarily designed for use with MSBuild 3.5 on the command
        line; however, it may also be used from the Visual Studio 2008 IDE.
      </li>

      <li>
        The &quot;SQLite.NET.2010.MSBuild.sln&quot; file is the top-level
        solution primarily designed for use with MSBuild 4.0 on the command
        line; however, it may also be used from the Visual Studio 2010 IDE.
      </li>
    </ul>
  </li>

  <li>
    Select the desired solution configuration (e.g. ReleaseNativeOnly) and and
    solution platform (e.g. x64), then &quot;Build->Rebuild Solution&quot;.







<
<
<
<


|
|
>




<


<
<
<
<
<
<
<
<



|
<
|
|












<
|
<


|
|
|



|
|
|



|
|
|



|
|
|







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

  <li>
    Make sure the version information is correct for System.Data.SQLite in the
    following files:

    <ul>




      <li>&lt;root&gt;\Doc\Extra\dbfactorysupport.html</li>
      <li>&lt;root&gt;\Doc\Extra\welcome.html</li>
      <li>&lt;root&gt;\test\app.config</li>
      <li>&lt;root&gt;\testlinq\2008\App.config</li>
      <li>&lt;root&gt;\testlinq\2010\App.config</li>
      <li>&lt;root&gt;\SQLite.Interop\props\SQLite.Interop.vsprops</li>
      <li>&lt;root&gt;\SQLite.Interop\props\SQLite.Interop.props</li>
      <li>&lt;root&gt;\SQLite.Interop\src\win\interop.h</li>
      <li>&lt;root&gt;\System.Data.SQLite\AssemblyInfo.cs</li>

      <li>&lt;root&gt;\System.Data.SQLite\UnsafeNativeMethods.cs</li>
      <li>&lt;root&gt;\System.Data.SQLite.Linq\AssemblyInfo.cs</li>








    </ul>

    You'll need to update the INTEROP_BUILD_NUMBER, INTEROP_MANIFEST_VERSION,
    and INTEROP_RC_VERSION properties in the .vsprops and .props files, and the

    INTEROP_VERSION define in interop.h.  This version number should track the
    release versions of the System.Data.SQLite packages (i.e. [./news.wiki | 1.0.x]).
  </li>
</ol>

<a name="manual"></a>
<h2>Manual Build</h2>

<ol>
  <li>
    Complete the steps outlined in the [./build.wiki#all | All Builds] section
    (above).
  </li>


  <li>Open the appropriate solution for your build platform.

    <ul>
      <li>
        SQLite.NET.2008.sln is the top-level solution primarily designed for use
        with Visual Studio 2008 in the IDE; however, it may also be used from
        the command line with MSBuild 3.5.
      </li>

      <li>
        SQLite.NET.2010.sln is the top-level solution primarily designed for use
        with Visual Studio 2010 in the IDE; however, it may also be used from
        the command line with MSBuild 4.0.
      </li>

      <li>
        SQLite.NET.2008.MSBuild.sln is the top-level solution primarily designed
        for use with MSBuild 3.5 on the command line; however, it may also be
        used from the Visual Studio 2008 IDE.
      </li>

      <li>
        SQLite.NET.2010.MSBuild.sln is the top-level solution primarily designed
        for use with MSBuild 4.0 on the command line; however, it may also be
        used from the Visual Studio 2010 IDE.
      </li>
    </ul>
  </li>

  <li>
    Select the desired solution configuration (e.g. ReleaseNativeOnly) and and
    solution platform (e.g. x64), then &quot;Build->Rebuild Solution&quot;.
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
  <li>
    Make sure the &quot;&lt;root&gt;\bin&quot; and &quot;&lt;root&gt;\obj&quot;
    directories are completely free of all output files.  In theory, you should
    be able to simply delete these directories.
  </li>

  <li>Open a normal command prompt window with &quot;cmd.exe&quot;.</li>

  <li>Change the current directory to &quot;&lt;root&gt;\Setup&quot;.</li>

  <li>
    Enter the following command to build the binaries for Win32 (x86):&nbsp;
    <b>build.bat ReleaseNativeOnly Win32</b><br /><i>You may need to enter the
    command &quot;<b>setenv /x86</b>&quot; first if you are using a
    &quot;Windows SDK Command Prompt&quot; or &quot;Visual Studio Command
    Prompt&quot; window.</i>
  </li>

  <li>
    Make sure everything succeeds with no errors; the log file
    &quot;%TEMP%\System.Data.SQLite.Build_ReleaseNativeOnly_Win32_&lt;year&gt;_Unknown.log&quot;
    may be checked if any errors should occur.
  </li>

  <li>
    Enter the following command to build the binaries for x64:&nbsp;<b>build.bat
    ReleaseNativeOnly x64</b><br /><i>You may need to enter the command
    &quot;<b>setenv /x64</b>&quot; first if you are using a &quot;Windows SDK
    Command Prompt&quot; or &quot;Visual Studio Command Prompt&quot; window.</i>
  </li>

  <li>
    Make sure everything succeeds with no errors; the log file
    &quot;%TEMP%\System.Data.SQLite.Build_ReleaseNativeOnly_x64_&lt;year&gt;_Unknown.log&quot;
    may be checked if any errors should occur.
  </li>

  <li>
    Enter the following command to build the setup binaries for all supported
    build configurations (unfortunately, it is not possible to build the setup
    using the Inno Setup IDE.  It must be done using the provided command line
    tools due to its highly dynamic nature):&nbsp;<b>bake_all.bat</b>
  </li>

  <li>
    Make sure everything succeeds with no errors.  Inno Setup should produce
    &quot;success&quot; messages very similar to the following:&nbsp;
    <b>Successful compile (X.XXX sec). Resulting Setup program filename
    is:&nbsp;abc</b>
  </li>
</ol>







<



|
|
|
|
<









|
|
|
|











|
|



|
|
|
<


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
  <li>
    Make sure the &quot;&lt;root&gt;\bin&quot; and &quot;&lt;root&gt;\obj&quot;
    directories are completely free of all output files.  In theory, you should
    be able to simply delete these directories.
  </li>

  <li>Open a normal command prompt window with &quot;cmd.exe&quot;.</li>

  <li>Change the current directory to &quot;&lt;root&gt;\Setup&quot;.</li>

  <li>
    Enter the following command to build the binaries for Win32 (x86): build.bat
    ReleaseNativeOnly Win32<br /><i>You may need to enter the command
    &quot;setenv /x86&quot; first if you are using a &quot;Windows SDK Command
    Prompt&quot; or &quot;Visual Studio Command Prompt&quot; window.</i>

  </li>

  <li>
    Make sure everything succeeds with no errors; the log file
    &quot;%TEMP%\System.Data.SQLite.Build_ReleaseNativeOnly_Win32_&lt;year&gt;_Unknown.log&quot;
    may be checked if any errors should occur.
  </li>

  <li>
    Enter the following command to build the binaries for x64: build.bat
    ReleaseNativeOnly x64<br /><i>You may need to enter the command &quot;setenv
    /x64&quot; first if you are using a &quot;Windows SDK Command Prompt&quot;
    or &quot;Visual Studio Command Prompt&quot; window.</i>
  </li>

  <li>
    Make sure everything succeeds with no errors; the log file
    &quot;%TEMP%\System.Data.SQLite.Build_ReleaseNativeOnly_x64_&lt;year&gt;_Unknown.log&quot;
    may be checked if any errors should occur.
  </li>

  <li>
    Enter the following command to build the setup binaries for all supported
    build configurations (unfortunately, it is not possible to build the setup
    using the InnoSetup IDE.  It must be done using the provided command line
    tools due to its highly dynamic nature): bake_all.bat
  </li>

  <li>
    Make sure everything succeeds with no errors.  InnoSetup should produce
    &quot;success&quot; messages very similar to the following: Successful
    compile (X.XXX sec). Resulting Setup program filename is: abc

  </li>
</ol>
Changes to www/downloads.wiki.
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
      <b>Source Code</b>
    </td>
  </tr>

  <tr>
    <td width="10">&nbsp;</td>
    <td valign="top" align="right">
      <a href="/sqlite-netFx-source-1.0.76.0.zip">sqlite-netFx-source-1.0.76.0.zip</a>
      <br />
      (2.53 MiB)
    </td>
    <td width="5"></td>
    <td valign="top">
      This ZIP archive contains all current source code for System.Data.SQLite
      1.0.76.0 (3.7.8) combined into a single archive file.
      <br />
      (sha1: fba56449601e4f023aa450c1c5471ee58d424b2d)
    </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 valign="top" align="right">
      <a href="/sqlite-netFx35-setup-bundle-x86-2008-1.0.76.0.exe">sqlite-netFx35-setup-bundle-x86-2008-1.0.76.0.exe</a>
      <br />
      (5.86 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.76.0 (3.7.8) package.  The Visual C++ 2008
      SP1 runtime for x86 is included.  The .NET Framework 3.5 SP1 is required.
      <br />
      (sha1: 1f9c794d866e23f9e8828fad13e8d062610cf310)
    </td>
  </tr>

  <tr>
    <td width="10">&nbsp;</td>
    <td valign="top" align="right">
      <a href="/sqlite-netFx35-setup-x86-2008-1.0.76.0.exe">sqlite-netFx35-setup-x86-2008-1.0.76.0.exe</a>
      <br />
      (5.86 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.76.0
      (3.7.8) package.  The Visual C++ 2008 SP1 runtime for x86 is included.
      The .NET Framework 3.5 SP1 is required.
      <br />
      (sha1: e0585ea3563eb838bdd8833bd64ebff9802efd0f)
    </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 valign="top" align="right">
      <a href="/sqlite-netFx35-setup-bundle-x64-2008-1.0.76.0.exe">sqlite-netFx35-setup-bundle-x64-2008-1.0.76.0.exe</a>
      <br />
      (6.60 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.76.0 (3.7.8) package.  The Visual C++ 2008
      SP1 runtime for x64 is included.  The .NET Framework 3.5 SP1 is required.
      <br />
      (sha1: 75389cd822172c1690ab80c79229ca992d0d127e)
    </td>
  </tr>

  <tr>
    <td width="10">&nbsp;</td>
    <td valign="top" align="right">
      <a href="/sqlite-netFx35-setup-x64-2008-1.0.76.0.exe">sqlite-netFx35-setup-x64-2008-1.0.76.0.exe</a>
      <br />
      (6.60 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.76.0
      (3.7.8) package.  The Visual C++ 2008 SP1 runtime for x64 is included.
      The .NET Framework 3.5 SP1 is required.
      <br />
      (sha1: 1a81ecdb4062d0c913551d74dee5eb477677aa00)
    </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 valign="top" align="right">
      <a href="/sqlite-netFx40-setup-bundle-x86-2010-1.0.76.0.exe">sqlite-netFx40-setup-bundle-x86-2010-1.0.76.0.exe</a>
      <br />
      (10.23 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.76.0 (3.7.8) package.  The Visual C++ 2010
      SP1 runtime for x86 is included.  The .NET Framework 4.0 is required.
      <br />
      (sha1: 0f48a58182afb4aeca22428885520f1359155bbb)
    </td>
  </tr>

  <tr>
    <td width="10">&nbsp;</td>
    <td valign="top" align="right">
      <a href="/sqlite-netFx40-setup-x86-2010-1.0.76.0.exe">sqlite-netFx40-setup-x86-2010-1.0.76.0.exe</a>
      <br />
      (10.23 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.76.0
      (3.7.8) package.  The Visual C++ 2010 SP1 runtime for x86 is included.
      The .NET Framework 4.0 is required.
      <br />
      (sha1: 9752bf41e287ff4781673cf79e3a0413c8229997)
    </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 valign="top" align="right">
      <a href="/sqlite-netFx40-setup-bundle-x64-2010-1.0.76.0.exe">sqlite-netFx40-setup-bundle-x64-2010-1.0.76.0.exe</a>
      <br />
      (11.44 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.76.0 (3.7.8) package.  The Visual C++ 2010
      SP1 runtime for x64 is included.  The .NET Framework 4.0 is required.
      <br />
      (sha1: 86dfd84874d322f0cdb4b3807d02f19b86c28bc6)
    </td>
  </tr>

  <tr>
    <td width="10">&nbsp;</td>
    <td valign="top" align="right">
      <a href="/sqlite-netFx40-setup-x64-2010-1.0.76.0.exe">sqlite-netFx40-setup-x64-2010-1.0.76.0.exe</a>
      <br />
      (11.44 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.76.0
      (3.7.8) package.  The Visual C++ 2010 SP1 runtime for x64 is included.
      The .NET Framework 4.0 is required.
      <br />
      (sha1: 7184b5ff13deb8692a85d0c8c4a06f2f8c64ae4b)
    </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 valign="top" align="right">
      <a href="/sqlite-netFx35-binary-bundle-Win32-2008-1.0.76.0.zip">sqlite-netFx35-binary-bundle-Win32-2008-1.0.76.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.76.0 (3.7.8)
      package.  The Visual C++ 2008 SP1 runtime for x86 and the .NET Framework
      3.5 SP1 are required.
      <br />
      (sha1: c11309defe95d31acba09e2960bf5f8398772e1f)
    </td>
  </tr>

  <tr>
    <td width="10">&nbsp;</td>
    <td valign="top" align="right">
      <a href="/sqlite-netFx35-binary-Win32-2008-1.0.76.0.zip">sqlite-netFx35-binary-Win32-2008-1.0.76.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.76.0 (3.7.8) package.  The Visual C++ 2008 SP1
      runtime for x86 and the .NET Framework 3.5 SP1 are required.
      <br />
      (sha1: 8c34d86a88487b2c13b3738222be5a2f546d828b)
    </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 valign="top" align="right">
      <a href="/sqlite-netFx35-binary-bundle-x64-2008-1.0.76.0.zip">sqlite-netFx35-binary-bundle-x64-2008-1.0.76.0.zip</a>
      <br />
      (1.46 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.76.0 (3.7.8)
      package.  The Visual C++ 2008 SP1 runtime for x64 and the .NET Framework
      3.5 SP1 are required.
      <br />
      (sha1: 715cb5c6ded65c143949e91a9e338e86181d7e9b)
    </td>
  </tr>

  <tr>
    <td width="10">&nbsp;</td>
    <td valign="top" align="right">
      <a href="/sqlite-netFx35-binary-x64-2008-1.0.76.0.zip">sqlite-netFx35-binary-x64-2008-1.0.76.0.zip</a>
      <br />
      (1.45 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.76.0 (3.7.8) package.  The Visual C++ 2008 SP1
      runtime for x64 and the .NET Framework 3.5 SP1 are required.
      <br />
      (sha1: 20c08bfb7314489f11b813973464746b97195b88)
    </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 valign="top" align="right">
      <a href="/sqlite-netFx40-binary-bundle-Win32-2010-1.0.76.0.zip">sqlite-netFx40-binary-bundle-Win32-2010-1.0.76.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.76.0 (3.7.8)
      package.  The Visual C++ 2010 SP1 runtime for x86 and the .NET Framework
      4.0 are required.
      <br />
      (sha1: cf0efe272bffb48313b9f7781b8de723fb4ea5d2)
    </td>
  </tr>

  <tr>
    <td width="10">&nbsp;</td>
    <td valign="top" align="right">
      <a href="/sqlite-netFx40-binary-Win32-2010-1.0.76.0.zip">sqlite-netFx40-binary-Win32-2010-1.0.76.0.zip</a>
      <br />
      (1.43 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.76.0 (3.7.8) package.  The Visual C++ 2010 SP1
      runtime for x86 and the .NET Framework 4.0 are required.
      <br />
      (sha1: 12d98305a9bd4860bfa98f1ffd7207df67022323)
    </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 valign="top" align="right">
      <a href="/sqlite-netFx40-binary-bundle-x64-2010-1.0.76.0.zip">sqlite-netFx40-binary-bundle-x64-2010-1.0.76.0.zip</a>
      <br />
      (1.46 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.76.0 (3.7.8)
      package.  The Visual C++ 2010 SP1 runtime for x64 and the .NET Framework
      4.0 are required.
      <br />
      (sha1: 0bb3ebde1b9a0838e911de8eb2a9608cd2f95010)
    </td>
  </tr>

  <tr>
    <td width="10">&nbsp;</td>
    <td valign="top" align="right">
      <a href="/sqlite-netFx40-binary-x64-2010-1.0.76.0.zip">sqlite-netFx40-binary-x64-2010-1.0.76.0.zip</a>
      <br />
      (1.45 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.76.0 (3.7.8) package.  The Visual C++ 2010 SP1
      runtime for x64 and the .NET Framework 4.0 are required.
      <br />
      (sha1: f93461445c3b36586b5eed8e78acd32c0be01f75)
    </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 valign="top" align="right">
      <a href="/sqlite-netFx35-static-binary-bundle-Win32-2008-1.0.76.0.zip">sqlite-netFx35-static-binary-bundle-Win32-2008-1.0.76.0.zip</a>
      <br />
      (1.61 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.76.0 (3.7.8)
      package.  The Visual C++ 2008 SP1 runtime for x86 is statically linked.
      The .NET Framework 3.5 SP1 is required.
      <br />
      (sha1: 286a2fafef12dfc15810b834c37007a2c97f7bbb)
    </td>
  </tr>

  <tr>
    <td width="10">&nbsp;</td>
    <td valign="top" align="right">
      <a href="/sqlite-netFx35-static-binary-Win32-2008-1.0.76.0.zip">sqlite-netFx35-static-binary-Win32-2008-1.0.76.0.zip</a>
      <br />
      (1.60 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.76.0 (3.7.8) package.  The Visual C++ 2008 SP1
      runtime for x86 is statically linked.  The .NET Framework 3.5 SP1 is
      required.
      <br />
      (sha1: bb1babce67aa349352ca2ad135d8932702d3859d)
    </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 valign="top" align="right">
      <a href="/sqlite-netFx35-static-binary-bundle-x64-2008-1.0.76.0.zip">sqlite-netFx35-static-binary-bundle-x64-2008-1.0.76.0.zip</a>
      <br />
      (1.64 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.76.0 (3.7.8)
      package.  The Visual C++ 2008 SP1 runtime for x64 is statically linked.
      The .NET Framework 3.5 SP1 is required.
      <br />
      (sha1: 4e88bb3125718e19f869bd9d5ffdd60faee275fb)
    </td>
  </tr>

  <tr>
    <td width="10">&nbsp;</td>
    <td valign="top" align="right">
      <a href="/sqlite-netFx35-static-binary-x64-2008-1.0.76.0.zip">sqlite-netFx35-static-binary-x64-2008-1.0.76.0.zip</a>
      <br />
      (1.63 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.76.0 (3.7.8) package.  The Visual C++ 2008 SP1
      runtime for x64 is statically linked.  The .NET Framework 3.5 SP1 is
      required.
      <br />
      (sha1: 8cbea2faa17623d49a407e591f663ce976422b33)
    </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 valign="top" align="right">
      <a href="/sqlite-netFx40-static-binary-bundle-Win32-2010-1.0.76.0.zip">sqlite-netFx40-static-binary-bundle-Win32-2010-1.0.76.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.76.0 (3.7.8)
      package.  The Visual C++ 2010 SP1 runtime for x86 is statically linked.
      The .NET Framework 4.0 is required.
      <br />
      (sha1: 7942b03061317c3297882a2d9a155abe3a9dca68)
    </td>
  </tr>

  <tr>
    <td width="10">&nbsp;</td>
    <td valign="top" align="right">
      <a href="/sqlite-netFx40-static-binary-Win32-2010-1.0.76.0.zip">sqlite-netFx40-static-binary-Win32-2010-1.0.76.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.76.0 (3.7.8) package.  The Visual C++ 2010 SP1
      runtime for x86 is statically linked.  The .NET Framework 4.0 is required.
      <br />
      (sha1: 56763c0e40f347ed1c66917c52dc2f5fd32c572e)
    </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 valign="top" align="right">
      <a href="/sqlite-netFx40-static-binary-bundle-x64-2010-1.0.76.0.zip">sqlite-netFx40-static-binary-bundle-x64-2010-1.0.76.0.zip</a>
      <br />
      (1.40 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.76.0 (3.7.8)
      package.  The Visual C++ 2010 SP1 runtime for x64 is statically linked.
      The .NET Framework 4.0 is required.
      <br />
      (sha1: ffa622c031a4bdb9de3dd32839fd261b580426cf)
    </td>
  </tr>

  <tr>
    <td width="10">&nbsp;</td>
    <td valign="top" align="right">
      <a href="/sqlite-netFx40-static-binary-x64-2010-1.0.76.0.zip">sqlite-netFx40-static-binary-x64-2010-1.0.76.0.zip</a>
      <br />
      (1.39 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.76.0 (3.7.8) package.  The Visual C++ 2010 SP1
      runtime for x64 is statically linked.  The .NET Framework 4.0 is required.
      <br />
      (sha1: 36411ff1712baf96378c4bfdc4bbd08376dc4f5c)
    </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 valign="top" align="right">
      <a href="/sqlite-netFx35-binary-PocketPC-2008-1.0.76.0.zip">sqlite-netFx35-binary-PocketPC-2008-1.0.76.0.zip</a>
      <br />
      (0.79 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.76.0 (3.7.8) package.  The .NET Compact
      Framework 3.5 is required.
      <br />
      (sha1: 3168092dbacd5faf1140e4fb8637603b237d67c8)
    </td>
  </tr>

  <tr>
    <td colspan="4">
      <b>Legacy Versions</b>
    </td>







|

|




|

|












|

|





|


|






|

|




|
|


|












|

|





|


|






|

|




|
|


|












|

|





|


|






|

|




|
|


|












|

|





|


|






|

|




|
|


|












|

|




|



|






|

|




|


|












|

|




|



|






|

|




|


|












|

|




|

|

|






|

|




|


|












|

|




|

|

|






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






|
|

|












|

|




|


|







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
      <b>Source Code</b>
    </td>
  </tr>

  <tr>
    <td width="10">&nbsp;</td>
    <td valign="top" align="right">
      <a href="/sqlite-netFx-source-1.0.74.0.zip">sqlite-netFx-source-1.0.74.0.zip</a>
      <br />
      (2.45 MiB)
    </td>
    <td width="5"></td>
    <td valign="top">
      This ZIP archive contains all current source code for System.Data.SQLite
      1.0.74.0 (3.7.7.1) combined into a single archive file.
      <br />
      (sha1: 09cc9daf98d1378c00bbb10b041d1fb08ddc5c75)
    </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 valign="top" align="right">
      <a href="/sqlite-netFx35-setup-bundle-x86-2008-1.0.74.0.exe">sqlite-netFx35-setup-bundle-x86-2008-1.0.74.0.exe</a>
      <br />
      (5.83 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.74.0 (3.7.7.1) package.  The Visual C++ 2008
      SP1 runtime for x86 is included.  The .NET Framework 3.5 SP1 is required.
      <br />
      (sha1: d20aaeeba73ddf8796449aefd06c887970fd94c4)
    </td>
  </tr>

  <tr>
    <td width="10">&nbsp;</td>
    <td valign="top" align="right">
      <a href="/sqlite-netFx35-setup-x86-2008-1.0.74.0.exe">sqlite-netFx35-setup-x86-2008-1.0.74.0.exe</a>
      <br />
      (5.82 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.74.0
      (3.7.7.1) package.  The Visual C++ 2008 SP1 runtime for x86 is included.
      The .NET Framework 3.5 SP1 is required.
      <br />
      (sha1: f077f17a52de05fd9aa3632e66a36388329c9318)
    </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 valign="top" align="right">
      <a href="/sqlite-netFx35-setup-bundle-x64-2008-1.0.74.0.exe">sqlite-netFx35-setup-bundle-x64-2008-1.0.74.0.exe</a>
      <br />
      (6.56 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.74.0 (3.7.7.1) package.  The Visual C++ 2008
      SP1 runtime for x64 is included.  The .NET Framework 3.5 SP1 is required.
      <br />
      (sha1: 567ff1db02755f3f7770acc0805a54b8846103c8)
    </td>
  </tr>

  <tr>
    <td width="10">&nbsp;</td>
    <td valign="top" align="right">
      <a href="/sqlite-netFx35-setup-x64-2008-1.0.74.0.exe">sqlite-netFx35-setup-x64-2008-1.0.74.0.exe</a>
      <br />
      (6.56 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.74.0
      (3.7.7.1) package.  The Visual C++ 2008 SP1 runtime for x64 is included.
      The .NET Framework 3.5 SP1 is required.
      <br />
      (sha1: 1ad120e0b3e838253f5f0c181d63f812ee6dcccf)
    </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 valign="top" align="right">
      <a href="/sqlite-netFx40-setup-bundle-x86-2010-1.0.74.0.exe">sqlite-netFx40-setup-bundle-x86-2010-1.0.74.0.exe</a>
      <br />
      (10.19 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.74.0 (3.7.7.1) package.  The Visual C++ 2010
      SP1 runtime for x86 is included.  The .NET Framework 4.0 is required.
      <br />
      (sha1: 9e3cc891d61533e3bb254a8359727ef8a6116487)
    </td>
  </tr>

  <tr>
    <td width="10">&nbsp;</td>
    <td valign="top" align="right">
      <a href="/sqlite-netFx40-setup-x86-2010-1.0.74.0.exe">sqlite-netFx40-setup-x86-2010-1.0.74.0.exe</a>
      <br />
      (10.19 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.74.0
      (3.7.7.1) package.  The Visual C++ 2010 SP1 runtime for x86 is included.
      The .NET Framework 4.0 is required.
      <br />
      (sha1: c16ad14d044b4cdcf159ca83c3eb198ba6f26f95)
    </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 valign="top" align="right">
      <a href="/sqlite-netFx40-setup-bundle-x64-2010-1.0.74.0.exe">sqlite-netFx40-setup-bundle-x64-2010-1.0.74.0.exe</a>
      <br />
      (11.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 x64 version of
      the System.Data.SQLite 1.0.74.0 (3.7.7.1) package.  The Visual C++ 2010
      SP1 runtime for x64 is included.  The .NET Framework 4.0 is required.
      <br />
      (sha1: 352a8b2506820a42cec9ea1a3d1e07ba4c37700c)
    </td>
  </tr>

  <tr>
    <td width="10">&nbsp;</td>
    <td valign="top" align="right">
      <a href="/sqlite-netFx40-setup-x64-2010-1.0.74.0.exe">sqlite-netFx40-setup-x64-2010-1.0.74.0.exe</a>
      <br />
      (11.39 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.74.0
      (3.7.7.1) package.  The Visual C++ 2010 SP1 runtime for x64 is included.
      The .NET Framework 4.0 is required.
      <br />
      (sha1: 0790a24b0058b5b88a7c537dcf71424bfed63ed2)
    </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 valign="top" align="right">
      <a href="/sqlite-netFx35-binary-bundle-Win32-2008-1.0.74.0.zip">sqlite-netFx35-binary-bundle-Win32-2008-1.0.74.0.zip</a>
      <br />
      (1.33 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.74.0 (3.7.7.1)
      package.  The Visual C++ 2008 SP1 runtime for x86 and the .NET Framework
      3.5 SP1 are required.
      <br />
      (sha1: 35ff1c2138d71602d10fd288636ab3e6fd32c931)
    </td>
  </tr>

  <tr>
    <td width="10">&nbsp;</td>
    <td valign="top" align="right">
      <a href="/sqlite-netFx35-binary-Win32-2008-1.0.74.0.zip">sqlite-netFx35-binary-Win32-2008-1.0.74.0.zip</a>
      <br />
      (1.33 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.74.0 (3.7.7.1) package.  The Visual C++ 2008 SP1
      runtime for x86 and the .NET Framework 3.5 SP1 are required.
      <br />
      (sha1: 59ed564db4fd83fec17010b6ab3f5eb89778f86a)
    </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 valign="top" align="right">
      <a href="/sqlite-netFx35-binary-bundle-x64-2008-1.0.74.0.zip">sqlite-netFx35-binary-bundle-x64-2008-1.0.74.0.zip</a>
      <br />
      (1.40 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.74.0 (3.7.7.1)
      package.  The Visual C++ 2008 SP1 runtime for x64 and the .NET Framework
      3.5 SP1 are required.
      <br />
      (sha1: 7dcc7fb52bba647c14bba5934059d039cc73373c)
    </td>
  </tr>

  <tr>
    <td width="10">&nbsp;</td>
    <td valign="top" align="right">
      <a href="/sqlite-netFx35-binary-x64-2008-1.0.74.0.zip">sqlite-netFx35-binary-x64-2008-1.0.74.0.zip</a>
      <br />
      (1.39 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.74.0 (3.7.7.1) package.  The Visual C++ 2008 SP1
      runtime for x64 and the .NET Framework 3.5 SP1 are required.
      <br />
      (sha1: b61c3964dc7b45ab8fce30ed02b077c0a21839f8)
    </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 valign="top" align="right">
      <a href="/sqlite-netFx40-binary-bundle-Win32-2010-1.0.74.0.zip">sqlite-netFx40-binary-bundle-Win32-2010-1.0.74.0.zip</a>
      <br />
      (1.38 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.74.0 (3.7.7.1)
      package.  The Visual C++ 2010 SP1 runtime for x86 and the .NET Framework
      3.5 SP1 are required.
      <br />
      (sha1: 76d0e38e1a687d8ddaaa94744b4da5e2841492e8)
    </td>
  </tr>

  <tr>
    <td width="10">&nbsp;</td>
    <td valign="top" align="right">
      <a href="/sqlite-netFx40-binary-Win32-2010-1.0.74.0.zip">sqlite-netFx40-binary-Win32-2010-1.0.74.0.zip</a>
      <br />
      (1.37 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.74.0 (3.7.7.1) package.  The Visual C++ 2010 SP1
      runtime for x86 and the .NET Framework 4.0 are required.
      <br />
      (sha1: e7d74609eae6f3799cbe3a9a8be86be1c2f49c04)
    </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 valign="top" align="right">
      <a href="/sqlite-netFx40-binary-bundle-x64-2010-1.0.74.0.zip">sqlite-netFx40-binary-bundle-x64-2010-1.0.74.0.zip</a>
      <br />
      (1.40 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.74.0 (3.7.7.1)
      package.  The Visual C++ 2010 SP1 runtime for x64 and the .NET Framework
      3.5 SP1 are required.
      <br />
      (sha1: a3648c38cf1522493e3641bfd590c093708c1fc9)
    </td>
  </tr>

  <tr>
    <td width="10">&nbsp;</td>
    <td valign="top" align="right">
      <a href="/sqlite-netFx40-binary-x64-2010-1.0.74.0.zip">sqlite-netFx40-binary-x64-2010-1.0.74.0.zip</a>






































































































































































      <br />
      (1.39 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.74.0 (3.7.7.1) package.  The Visual C++ 2010 SP1
      runtime for x64 and the .NET Framework 4.0 SP1 are required.
      <br />
      (sha1: 797fa10130f0177118daac2864be28a1ad04e8d4)
    </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 valign="top" align="right">
      <a href="/sqlite-netFx35-binary-PocketPC-2008-1.0.74.0.zip">sqlite-netFx35-binary-PocketPC-2008-1.0.74.0.zip</a>
      <br />
      (0.76 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.74.0 (3.7.7.1) package.  The .NET Compact
      Framework 3.5 is required.
      <br />
      (sha1: 0bf68d78083dfbe4fa84eab3eb59c051bfdd53f6)
    </td>
  </tr>

  <tr>
    <td colspan="4">
      <b>Legacy Versions</b>
    </td>
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
  <ol>
    <li><b>sqlite-netFx-source-</b>version<b>.zip</b></li>
    <li><b>sqlite-netFx-source-</b>version<b>.tar.gz</b></li>
    <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 framework in templates (3), (4), (5), (6), (7), and (8) will be one of netFx35, netFx40.
</p>

<p>
  The cpu in templates (3) and (4) will be one of x86, x64, arm, ia64.
</p>

<p>
  The platform in templates (5), (6), (7), and (8) will be one of Win32, x64, PocketPC.




</p>

<p>
  The year in templates (3), (4), (5), (6), (7), and (8) will be one of 2008, 2010.
</p>

<p>
  The version in templates (1), (2), (3), (4), (5), (6), (7), and (8) is the dot-delimited version number of the primary System.Data.SQLite assembly.
</p>

<p>
  The date 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







<
<











|
<
<
<
|



|







|
>
>
>
>



|



<
<
<
<
|







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
  <ol>
    <li><b>sqlite-netFx-source-</b>version<b>.zip</b></li>
    <li><b>sqlite-netFx-source-</b>version<b>.tar.gz</b></li>
    <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-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 unofficial



  pre-release &quot;snapshots&quot; of source code.
</p>

<p>
  The framework in templates (3), (4), (5), and (6) will be one of netFx35, netFx40.
</p>

<p>
  The cpu in templates (3) and (4) will be one of x86, x64, arm, ia64.
</p>

<p>
  The platform in templates (5) and (6) will be one of Win32, x64, PocketPC.
</p>

<p>
  The year in templates (3), (4), (5), and (6) will be one of 2008, 2010.
</p>

<p>
  The version in templates (1), (2), (3), (4), (5), and (6) is the dot-delimited version number of the primary System.Data.SQLite assembly.
</p>

<p>




  The date in template (7) 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
Changes to www/index.wiki.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<title>About</title>

<table align="right" border="1" cellpadding="10" hspace="10" cellspacing="0">
  <tr>
    <td>
      <ul>
        <li>[./features.wiki | Features]</li>
        <li>[./news.wiki | News]</li>
        <li>[./support.wiki | Support]</li>
        <li>[./downloads.wiki | Downloads]</li>
        <li>[./contribute.wiki | Contributing]</li>
        <li>[./build.wiki | Build Procedures]</li>
        <li>[./test.wiki | Test Procedures]</li>
        <li>[./release.wiki | Release Procedures]</li>
      </ul>
    </td>
  </tr>
</table>

<p>












<







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

13
14
15
16
17
18
19
<title>About</title>

<table align="right" border="1" cellpadding="10" hspace="10" cellspacing="0">
  <tr>
    <td>
      <ul>
        <li>[./features.wiki | Features]</li>
        <li>[./news.wiki | News]</li>
        <li>[./support.wiki | Support]</li>
        <li>[./downloads.wiki | Downloads]</li>
        <li>[./contribute.wiki | Contributing]</li>
        <li>[./build.wiki | Build Procedures]</li>

        <li>[./release.wiki | Release Procedures]</li>
      </ul>
    </td>
  </tr>
</table>

<p>
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

<p>
  Historical versions, as well as the original support forums, may still be
  found at <a href="http://sqlite.phxsoftware.com/">http://sqlite.phxsoftware.com/</a>,
  though there have been no updates to this version since April of 2010.
</p>

<p>
  &nbsp;
</p>

<p>
  &nbsp;
</p>

<p>
  &nbsp;
</p>

<p>
  &nbsp;
</p>







<
<
<
<











27
28
29
30
31
32
33




34
35
36
37
38
39
40
41
42
43
44

<p>
  Historical versions, as well as the original support forums, may still be
  found at <a href="http://sqlite.phxsoftware.com/">http://sqlite.phxsoftware.com/</a>,
  though there have been no updates to this version since April of 2010.
</p>





<p>
  &nbsp;
</p>

<p>
  &nbsp;
</p>

<p>
  &nbsp;
</p>
Changes to www/news.wiki.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<title>News</title>

<b>Version History</b>

<p>
    <b>1.0.76.0 - October 4, 2011</b>
</p>
<ul>
    <li>Prevent the domain unload event handler in SQLiteLog from being registered multiple times. Fix for [0d5b1ef362].</li>
    <li>Stop allowing non-default application domains to initialize the SQLiteLog class. Fix for [ac47dd230a].</li>
</ul>
<p>
    <b>1.0.75.0 - October 3, 2011</b>
</p>
<ul>
    <li>Updated to SQLite 3.7.8 <a href="http://www.sqlite.org/src/info/3e0da808d2">[3e0da808d2]</a>.</li>
    <li>More enhancements to the build system.</li>
    <li>Add official <a href="http://www.nuget.org/">NuGet</a> packages for x86 and x64.</li>
    <li>Add Changes and LastInsertRowId properties to the connection class.</li>
    <li>Support more formats when converting data from/to the DateTime type.</li>
    <li>Make all the assembly versioning attributes consistent.</li>
    <li>Add unit testing infrastructure using <a href="http://eagle.to/">Eagle</a>.</li>
    <li>Integrate all legacy unit tests, including the &quot;testlinq&quot; project, into the new test suite.</li>
    <li>Add projects to build the interop assembly statically linked to the Visual C++ runtime. Fix for [53f0c5cbf6].</li>
    <li>Add SQLITE_ENABLE_STAT2 compile-time option to the interop assembly. Fix for [74807fbf27].</li>
    <li>Fix mutex issues exposed when running the test suite with the debug version of SQLite.</li>
    <li>Fix transaction enlistment when repeated attempts are made to enlist in the same transaction. Fix for [ccfa69fc32].</li>
    <li>Support the SQLITE_FCNTL_WIN32_AV_RETRY file control to mitigate the impact of file sharing violations caused by external processes.</li>
    <li>Refactor the logging interface to be thread-safe and self-initializing.</li>
    <li>Shutdown the SQLite native interface when the AppDomain is being unloaded. Fix for [b4a7ddc83f].</li>
    <li>Support Skip operation for LINQ using OFFSET. Fix for [8b7d179c3c].</li>
    <li>Support EndsWith operation for LINQ using SUBSTR. Fix for [59edc1018b].</li>
    <li>Support all SQLite journal modes. Fix for [448d663d11].</li>
    <li>Do not throw exceptions when disposing SQLiteDataReader. Fix for [e1b2e0f769].</li>
    <li>The REAL type should be mapped to System.Double. Fix for [2c630bffa7] and [b0a5990f48].</li>
    <li>Minor optimization to GetParamValueBytes(). Fix for [201128cc88].</li>
    <li>Support the ON UPDATE, ON DELETE, and MATCH clause information when generating schema metadata for foreign keys. Partial fix for [b226147b37]. VS designer changes are not yet tested.</li>
    <li>Fix incorrect resource name for SR.resx in the mixed-mode assembly.</li>
    <li>Reduce the number of String.Compare() calls in the hot path for SQLiteCommand.ExecuteReader().</li>
</ul>
<p>
    <b>1.0.74.0 - July 4, 2011</b>
</p>
<ul>
    <li>Updated to SQLite 3.7.7.1 <a href="http://www.sqlite.org/src/info/af0d91adf4">[af0d91adf4]</a>.</li>
    <li>Fix incorrect hard-coded .NET Framework version information SQLiteFactory_Linq.cs that was causing IServiceProvider.GetService to fail when running against the .NET Framework 3.5.</li>
    <li>Fix all XML documentation warnings.</li>
    <li>Restore support for the mixed-mode assembly (i.e. the one that can be registered in the Global Assembly Cache).</li>





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







1
2
3
4
5




































6
7
8
9
10
11
12
<title>News</title>

<b>Version History</b>

<p>




































    <b>1.0.74.0 - July 4, 2011</b>
</p>
<ul>
    <li>Updated to SQLite 3.7.7.1 <a href="http://www.sqlite.org/src/info/af0d91adf4">[af0d91adf4]</a>.</li>
    <li>Fix incorrect hard-coded .NET Framework version information SQLiteFactory_Linq.cs that was causing IServiceProvider.GetService to fail when running against the .NET Framework 3.5.</li>
    <li>Fix all XML documentation warnings.</li>
    <li>Restore support for the mixed-mode assembly (i.e. the one that can be registered in the Global Assembly Cache).</li>
Deleted www/test.wiki.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
<title>Test Procedures</title>

<a name="assumptions"></a>
<h2>Test Assumptions &amp; Prerequisites</h2>

<ol>
  <li>
    The string &quot;&lt;root&gt;&quot; represents the root of the source tree
    (i.e. the working check-out directory) for the System.Data.SQLite project.
  </li>

  <li>
    The string &quot;&lt;year&gt;&quot; represents the version of Visual Studio
    used (e.g. &quot;2008&quot; or &quot;2010&quot;) to build the binaries being
    tested.
  </li>

  <li>
    The string &quot;&lt;configuration&gt;&quot; represents the build
    configuration for the binaries being tested (e.g. &quot;Debug&quot; or
    &quot;Release&quot;).
  </li>

  <li>
    The string &quot;&lt;platform&gt;&quot; represents the native platform for
    the binaries being tested (e.g. &quot;Win32&quot; or &quot;x64&quot;).
  </li>

  <li>
    The string &quot;&lt;pid&gt;&quot; represents the process identifier for the
    instance of EagleShell being used to run the unit tests (e.g.
    &quot;1234&quot;).
  </li>
</ol>

<a name="procedures"></a>
<h2>Test Procedures</h2>

<p>
  Follow these steps to unit test the System.Data.SQLite (SDS) binaries.
  Unless otherwise noted, all steps need to be done in the order specified.
</p>

<p>
  First, you will need a full source check-out for the System.Data.SQLite
  project, including the
  &quot;<a href="/index.html/dir?name=Externals/Eagle">Externals\Eagle</a>&quot;
  directory.
</p>

<p>
  The binaries to test must be [./build.wiki | built] or
  [./downloads.wiki | downloaded].  If the binaries are downloaded, they must be
  placed in the appropriate build output directory (e.g.
  &quot;&lt;root&gt;\bin\&lt;year&gt;\&lt;configuration&gt;\bin&quot; for the
  separate managed and interop assemblies or
  &quot;&lt;root&gt;\bin\&lt;year&gt;\&lt;platform&gt;\&lt;configuration&gt;&quot;
  for the mixed-mode assembly).
</p>

<p>
  The new unit tests have been setup using <a href="http://eagle.to/">Eagle</a>
  and its associated unit testing framework, named &quot;EagleTest&quot;.  Eagle
  is an implementation of the <a href="http://www.tcl.tk/">Tcl</a> scripting
  language for the Common Language Runtime (CLR).  EagleTest is the unit testing
  framework for Eagle, packaged as a collection of Eagle scripts, based loosely
  on the implementation of
  <a href="http://www.tcl.tk/man/tcl8.4/TclCmd/tcltest.htm">tcltest</a>.
</p>

<a name="automated"></a>
<h2>Automated Unit Tests</h2>

<ol>
  <li>Open a normal command prompt window with &quot;cmd.exe&quot;.</li>

  <li>Change the current directory to &quot;&lt;root&gt;&quot;.</li>

  <li>
    Enter the following command to run all the unit tests against the binaries
    built with a separate managed and interop assembly:
    <b>Externals\Eagle\bin\EagleShell.exe -file Tests\all.eagle</b>
  </li>

  <li>
    Enter the following command to run all the unit tests against the binaries
    built with a mixed-mode assembly:
    <b>Externals\Eagle\bin\EagleShell.exe -initialize -runtimeOption native -file Tests\all.eagle</b>
  </li>

  <li>
    To test binaries built with MSBuild 3.5 or Visual Studio 2008 (i.e. because
    the default is to test binaries built with MSBuild 4.0 or Visual Studio
    2010) add the following command line argument right after
    &quot;Externals\Eagle\bin\EagleShell.exe&quot; in either of the above
    command lines:
    <b>-preInitialize &quot;set test_year 2008&quot;</b>
  </li>

  <li>
    To test binaries built in the &quot;Debug&quot; build configuration (i.e.
    because the default is to test binaries built in the &quot;Release&quot;
    build configuration) add the following command line argument right after
    &quot;Externals\Eagle\bin\EagleShell.exe&quot; in either of the above
    command lines:
    <b>-preInitialize &quot;set test_configuration Debug&quot;</b>
  </li>

  <li>
    Make sure all tests pass; the log file
    &quot;%TEMP%\EagleShell.exe.test.&lt;pid&gt;.log&quot; may be checked if any
    errors should occur.  EagleTest should produce &quot;success&quot; messages
    very similar to the following:<br /><br />
    PASSED: 96<br />
    TOTAL: 96<br />
    PASS PERCENTAGE: 100%<br />
    OVERALL RESULT: SUCCESS<br />
  </li>
</ol>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<